@jobber/components-native 0.49.2 → 0.51.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/package.json +3 -3
- package/dist/src/InputFieldWrapper/index.js +0 -1
- package/dist/src/InputPressable/InputPressable.js +2 -1
- package/dist/src/InputText/InputText.js +2 -1
- package/dist/src/ProgressBar/ProgressBar.js +4 -3
- package/dist/src/ProgressBar/ProgressBar.style.js +13 -0
- package/dist/src/ProgressBar/ProgressBarStepped.js +21 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/InputDate/InputDate.d.ts +2 -1
- package/dist/types/src/InputFieldWrapper/index.d.ts +1 -2
- package/dist/types/src/InputPressable/InputPressable.d.ts +1 -1
- package/dist/types/src/InputText/InputText.d.ts +1 -1
- package/dist/types/src/InputTime/InputTime.d.ts +2 -1
- package/dist/types/src/ProgressBar/ProgressBar.d.ts +1 -1
- package/dist/types/src/ProgressBar/ProgressBar.style.d.ts +13 -0
- package/dist/types/src/ProgressBar/ProgressBarStepped.d.ts +10 -0
- package/dist/types/src/ProgressBar/types.d.ts +7 -1
- package/package.json +3 -3
- package/src/InputDate/InputDate.tsx +3 -1
- package/src/InputFieldWrapper/InputFieldWrapper.tsx +5 -4
- package/src/InputFieldWrapper/index.ts +1 -2
- package/src/InputPressable/InputPressable.tsx +2 -6
- package/src/InputText/InputText.tsx +2 -5
- package/src/InputTime/InputTime.tsx +4 -1
- package/src/ProgressBar/ProgressBar.style.ts +13 -0
- package/src/ProgressBar/ProgressBar.test.tsx +40 -1
- package/src/ProgressBar/ProgressBar.tsx +35 -21
- package/src/ProgressBar/ProgressBarStepped.tsx +47 -0
- package/src/ProgressBar/types.ts +8 -1
- package/dist/src/InputFieldWrapper/hooks/useShowClear.js +0 -15
- package/dist/types/src/InputFieldWrapper/hooks/useShowClear.d.ts +0 -10
- package/src/InputFieldWrapper/hooks/useShowClear.test.ts +0 -158
- package/src/InputFieldWrapper/hooks/useShowClear.ts +0 -31
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { UseControllerProps } from "react-hook-form";
|
|
3
3
|
import { XOR } from "ts-xor";
|
|
4
|
-
import { Clearable
|
|
4
|
+
import { Clearable } from "@jobber/hooks";
|
|
5
|
+
import { InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
5
6
|
interface BaseInputDateProps extends Pick<InputFieldWrapperProps, "invalid" | "disabled" | "placeholder"> {
|
|
6
7
|
/**
|
|
7
8
|
* Defaulted to "always" so user can clear the dates whenever there's a value.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { commonInputStyles } from "./CommonInputStyles.style";
|
|
2
2
|
export { InputFieldWrapper } from "./InputFieldWrapper";
|
|
3
|
-
export type { InputFieldWrapperProps
|
|
4
|
-
export { useShowClear } from "./hooks/useShowClear";
|
|
3
|
+
export type { InputFieldWrapperProps } from "./InputFieldWrapper";
|
|
@@ -2,7 +2,7 @@ import React, { Ref } from "react";
|
|
|
2
2
|
import { IconNames } from "@jobber/design";
|
|
3
3
|
import { FieldError } from "react-hook-form";
|
|
4
4
|
import { Text as NativeText } from "react-native";
|
|
5
|
-
import { Clearable } from "
|
|
5
|
+
import { Clearable } from "@jobber/hooks";
|
|
6
6
|
export interface InputPressableProps {
|
|
7
7
|
/**
|
|
8
8
|
* Current value of the component
|
|
@@ -2,8 +2,8 @@ import React, { SyntheticEvent } from "react";
|
|
|
2
2
|
import { NativeSyntheticEvent, StyleProp, TextInput, TextInputFocusEventData, TextInputProps, TextStyle } from "react-native";
|
|
3
3
|
import { RegisterOptions } from "react-hook-form";
|
|
4
4
|
import { IconNames } from "@jobber/design";
|
|
5
|
+
import { Clearable } from "@jobber/hooks";
|
|
5
6
|
import { InputFieldStyleOverride } from "../InputFieldWrapper/InputFieldWrapper";
|
|
6
|
-
import { Clearable } from "../InputFieldWrapper";
|
|
7
7
|
export interface InputTextProps {
|
|
8
8
|
/**
|
|
9
9
|
* Highlights the field red and shows message below (if string) to indicate an error
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { UseControllerProps } from "react-hook-form";
|
|
3
3
|
import { XOR } from "ts-xor";
|
|
4
|
-
import { Clearable
|
|
4
|
+
import { Clearable } from "@jobber/hooks";
|
|
5
|
+
import { InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
5
6
|
interface InputTimeBaseProps extends Pick<InputFieldWrapperProps, "invalid" | "disabled" | "placeholder"> {
|
|
6
7
|
/**
|
|
7
8
|
* Defaulted to "always" so user can clear the time whenever there's a value.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { ProgressBarProps } from "./types";
|
|
3
|
-
export declare function ProgressBar({ loading, total, current, inProgress, reverseTheme, header, }: ProgressBarProps): JSX.Element;
|
|
3
|
+
export declare function ProgressBar({ loading, total, current, inProgress, reverseTheme, header, variation, }: ProgressBarProps): JSX.Element;
|
|
@@ -19,4 +19,17 @@ export declare const styles: {
|
|
|
19
19
|
height: string;
|
|
20
20
|
borderRadius: number;
|
|
21
21
|
};
|
|
22
|
+
step: {
|
|
23
|
+
flex: number;
|
|
24
|
+
marginRight: number;
|
|
25
|
+
height: string;
|
|
26
|
+
borderRadius: number;
|
|
27
|
+
borderColor: string;
|
|
28
|
+
};
|
|
29
|
+
completedStep: {
|
|
30
|
+
backgroundColor: string;
|
|
31
|
+
};
|
|
32
|
+
inProgressStep: {
|
|
33
|
+
backgroundColor: string;
|
|
34
|
+
};
|
|
22
35
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
interface ProgressBarSteppedProps {
|
|
3
|
+
readonly total: number;
|
|
4
|
+
readonly current: number;
|
|
5
|
+
readonly color?: string;
|
|
6
|
+
readonly loading?: boolean;
|
|
7
|
+
readonly inProgress?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function ProgressBarStepped({ total, current, color, loading, inProgress, }: ProgressBarSteppedProps): JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -9,7 +9,8 @@ export interface ProgressBarProps {
|
|
|
9
9
|
*/
|
|
10
10
|
readonly current: number;
|
|
11
11
|
/**
|
|
12
|
-
* The number of items in progress (not completed, but to be less than the total)
|
|
12
|
+
* The number of items in progress (not completed, but to be less than the total);
|
|
13
|
+
* not applicable with stepped variation
|
|
13
14
|
*/
|
|
14
15
|
readonly inProgress?: number;
|
|
15
16
|
/**
|
|
@@ -25,4 +26,9 @@ export interface ProgressBarProps {
|
|
|
25
26
|
* Component to render above the progress bar.
|
|
26
27
|
*/
|
|
27
28
|
readonly header?: ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Set the variation of the progress bar
|
|
31
|
+
* @default progress
|
|
32
|
+
*/
|
|
33
|
+
readonly variation?: "progress" | "stepped";
|
|
28
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@jobber/design": "^0.51.0",
|
|
40
|
-
"@jobber/hooks": "^2.
|
|
40
|
+
"@jobber/hooks": "^2.8.0",
|
|
41
41
|
"@react-native-clipboard/clipboard": "^1.11.2",
|
|
42
42
|
"@react-native-picker/picker": "^2.4.10",
|
|
43
43
|
"autolinker": "^4.0.0",
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"react-native-reanimated": "^2.17.0",
|
|
85
85
|
"react-native-safe-area-context": "^4.5.2"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "7096004da05ede6fff2bfaaed572b3e91a9ee1d9"
|
|
88
88
|
}
|
|
@@ -3,7 +3,8 @@ import DateTimePicker from "react-native-modal-datetime-picker";
|
|
|
3
3
|
import { Platform } from "react-native";
|
|
4
4
|
import { FieldError, UseControllerProps } from "react-hook-form";
|
|
5
5
|
import { XOR } from "ts-xor";
|
|
6
|
-
import { Clearable
|
|
6
|
+
import { Clearable } from "@jobber/hooks";
|
|
7
|
+
import { InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
7
8
|
import { FormField } from "../FormField";
|
|
8
9
|
import { InputPressable } from "../InputPressable";
|
|
9
10
|
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
@@ -154,6 +155,7 @@ function InternalInputDate({
|
|
|
154
155
|
|
|
155
156
|
const date = useMemo(() => {
|
|
156
157
|
if (typeof value === "string") return new Date(value);
|
|
158
|
+
|
|
157
159
|
return value;
|
|
158
160
|
}, [value]);
|
|
159
161
|
|
|
@@ -228,6 +228,7 @@ function getLabelVariation(
|
|
|
228
228
|
} else if (focused) {
|
|
229
229
|
return "interactive";
|
|
230
230
|
}
|
|
231
|
+
|
|
231
232
|
return "subdued";
|
|
232
233
|
}
|
|
233
234
|
|
|
@@ -278,10 +279,10 @@ function Placeholder({
|
|
|
278
279
|
labelVariation,
|
|
279
280
|
hasMiniLabel,
|
|
280
281
|
}: {
|
|
281
|
-
placeholder?: string;
|
|
282
|
-
styleOverride: StyleProp<TextStyle>;
|
|
283
|
-
labelVariation: TextVariation;
|
|
284
|
-
hasMiniLabel: boolean;
|
|
282
|
+
readonly placeholder?: string;
|
|
283
|
+
readonly styleOverride: StyleProp<TextStyle>;
|
|
284
|
+
readonly labelVariation: TextVariation;
|
|
285
|
+
readonly hasMiniLabel: boolean;
|
|
285
286
|
}) {
|
|
286
287
|
return (
|
|
287
288
|
<>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { commonInputStyles } from "./CommonInputStyles.style";
|
|
2
2
|
export { InputFieldWrapper } from "./InputFieldWrapper";
|
|
3
|
-
export type { InputFieldWrapperProps
|
|
4
|
-
export { useShowClear } from "./hooks/useShowClear";
|
|
3
|
+
export type { InputFieldWrapperProps } from "./InputFieldWrapper";
|
|
@@ -2,13 +2,9 @@ import React, { Ref, forwardRef, useEffect, useState } from "react";
|
|
|
2
2
|
import { IconNames } from "@jobber/design";
|
|
3
3
|
import { FieldError } from "react-hook-form";
|
|
4
4
|
import { Text as NativeText, Pressable } from "react-native";
|
|
5
|
+
import { Clearable, useShowClear } from "@jobber/hooks";
|
|
5
6
|
import { styles } from "./InputPressable.style";
|
|
6
|
-
import {
|
|
7
|
-
Clearable,
|
|
8
|
-
InputFieldWrapper,
|
|
9
|
-
commonInputStyles,
|
|
10
|
-
useShowClear,
|
|
11
|
-
} from "../InputFieldWrapper";
|
|
7
|
+
import { InputFieldWrapper, commonInputStyles } from "../InputFieldWrapper";
|
|
12
8
|
|
|
13
9
|
export interface InputPressableProps {
|
|
14
10
|
/**
|
|
@@ -25,15 +25,12 @@ import {
|
|
|
25
25
|
} from "react-hook-form";
|
|
26
26
|
import { IconNames } from "@jobber/design";
|
|
27
27
|
import identity from "lodash/identity";
|
|
28
|
+
import { Clearable, useShowClear } from "@jobber/hooks";
|
|
28
29
|
import { styles } from "./InputText.style";
|
|
29
30
|
import { useInputAccessoriesContext } from "./context";
|
|
30
31
|
import { useFormController } from "../hooks";
|
|
31
32
|
import { InputFieldStyleOverride } from "../InputFieldWrapper/InputFieldWrapper";
|
|
32
|
-
import {
|
|
33
|
-
Clearable,
|
|
34
|
-
InputFieldWrapper,
|
|
35
|
-
useShowClear,
|
|
36
|
-
} from "../InputFieldWrapper";
|
|
33
|
+
import { InputFieldWrapper } from "../InputFieldWrapper";
|
|
37
34
|
import { commonInputStyles } from "../InputFieldWrapper/CommonInputStyles.style";
|
|
38
35
|
|
|
39
36
|
export interface InputTextProps {
|
|
@@ -3,12 +3,13 @@ import { FieldError, UseControllerProps } from "react-hook-form";
|
|
|
3
3
|
import { XOR } from "ts-xor";
|
|
4
4
|
import DateTimePicker from "react-native-modal-datetime-picker";
|
|
5
5
|
import { View } from "react-native";
|
|
6
|
+
import { Clearable } from "@jobber/hooks";
|
|
6
7
|
import { styles } from "./InputTime.style";
|
|
7
8
|
import { getTimeZoneOffsetInMinutes, roundUpToNearestMinutes } from "./utils";
|
|
8
9
|
import { useAtlantisContext } from "../AtlantisContext";
|
|
9
10
|
import { InputPressable } from "../InputPressable";
|
|
10
11
|
import { FormField } from "../FormField";
|
|
11
|
-
import {
|
|
12
|
+
import { InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
12
13
|
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
13
14
|
|
|
14
15
|
interface InputTimeBaseProps
|
|
@@ -208,10 +209,12 @@ function InternalInputTime({
|
|
|
208
209
|
|
|
209
210
|
function getInitialPickerDate(date?: Date | null): Date {
|
|
210
211
|
if (date) return date;
|
|
212
|
+
|
|
211
213
|
return roundUpToNearestMinutes(new Date(), 30);
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
function getMinuteInterval(type: InputTimeBaseProps["type"]) {
|
|
215
217
|
if (type === "granular") return 1;
|
|
218
|
+
|
|
216
219
|
return 5;
|
|
217
220
|
}
|
|
@@ -22,4 +22,17 @@ export const styles = StyleSheet.create({
|
|
|
22
22
|
height: "100%",
|
|
23
23
|
borderRadius: 100,
|
|
24
24
|
},
|
|
25
|
+
step: {
|
|
26
|
+
flex: 1,
|
|
27
|
+
marginRight: tokens["space-small"],
|
|
28
|
+
height: "100%",
|
|
29
|
+
borderRadius: 100,
|
|
30
|
+
borderColor: "rgba(255,255,255,0.3)",
|
|
31
|
+
},
|
|
32
|
+
completedStep: {
|
|
33
|
+
backgroundColor: tokens["color-interactive"],
|
|
34
|
+
},
|
|
35
|
+
inProgressStep: {
|
|
36
|
+
backgroundColor: tokens["color-informative"],
|
|
37
|
+
},
|
|
25
38
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { render } from "@testing-library/react-native";
|
|
2
|
+
import { render, screen } from "@testing-library/react-native";
|
|
3
3
|
import { ProgressBar, ProgressBarProps } from ".";
|
|
4
|
+
import { styles } from "./ProgressBar.style";
|
|
4
5
|
|
|
5
6
|
const defaultSetupProps = {
|
|
6
7
|
total: 0,
|
|
@@ -39,3 +40,41 @@ it("renders green CompletedProgress bar when 1 or more jobs is completed", () =>
|
|
|
39
40
|
expect(bar).toMatchSnapshot();
|
|
40
41
|
expect(bar.getByLabelText("1 of 2 complete")).toBeDefined();
|
|
41
42
|
});
|
|
43
|
+
|
|
44
|
+
describe("with stepped variation", () => {
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
render(
|
|
47
|
+
<ProgressBar
|
|
48
|
+
total={3}
|
|
49
|
+
current={2}
|
|
50
|
+
inProgress={1}
|
|
51
|
+
variation={"stepped"}
|
|
52
|
+
/>,
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
it("renders the correct number of steps", () => {
|
|
56
|
+
const stepElements = screen.getAllByTestId("progress-step");
|
|
57
|
+
expect(stepElements).toHaveLength(3);
|
|
58
|
+
});
|
|
59
|
+
it("renders the correct number of completed steps", () => {
|
|
60
|
+
const stepElements = screen.getAllByTestId("progress-step");
|
|
61
|
+
const completedSteps = stepElements.filter(step =>
|
|
62
|
+
step.props.style.includes(styles.completedStep),
|
|
63
|
+
);
|
|
64
|
+
expect(completedSteps).toHaveLength(2);
|
|
65
|
+
});
|
|
66
|
+
it("renders the correct number of incomplete steps", () => {
|
|
67
|
+
const stepElements = screen.getAllByTestId("progress-step");
|
|
68
|
+
const incompleteSteps = stepElements.filter(
|
|
69
|
+
step => !step.props.style.includes(styles.completedStep),
|
|
70
|
+
);
|
|
71
|
+
expect(incompleteSteps).toHaveLength(1);
|
|
72
|
+
});
|
|
73
|
+
it("renders the correct number of inProgress steps", () => {
|
|
74
|
+
const stepElements = screen.getAllByTestId("progress-step");
|
|
75
|
+
const inProgressSteps = stepElements.filter(step =>
|
|
76
|
+
step.props.style.includes(styles.inProgressStep),
|
|
77
|
+
);
|
|
78
|
+
expect(inProgressSteps).toHaveLength(1);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -3,6 +3,7 @@ import { View } from "react-native";
|
|
|
3
3
|
import { ProgressBarProps } from "./types";
|
|
4
4
|
import { styles } from "./ProgressBar.style";
|
|
5
5
|
import { ProgressBarInner, calculateWidth } from "./ProgressBarInner";
|
|
6
|
+
import { ProgressBarStepped } from "./ProgressBarStepped";
|
|
6
7
|
import { tokens } from "../utils/design";
|
|
7
8
|
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
8
9
|
|
|
@@ -13,6 +14,7 @@ export function ProgressBar({
|
|
|
13
14
|
inProgress = 0,
|
|
14
15
|
reverseTheme = false,
|
|
15
16
|
header,
|
|
17
|
+
variation = "progress",
|
|
16
18
|
}: ProgressBarProps): JSX.Element {
|
|
17
19
|
const { t } = useAtlantisI18n();
|
|
18
20
|
|
|
@@ -23,31 +25,43 @@ export function ProgressBar({
|
|
|
23
25
|
accessibilityLabel={getA11yLabel()}
|
|
24
26
|
>
|
|
25
27
|
{header}
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
{variation === "stepped" ? (
|
|
29
|
+
<ProgressBarStepped
|
|
30
|
+
total={total}
|
|
31
|
+
current={current}
|
|
30
32
|
color={reverseTheme ? undefined : tokens["color-surface--background"]}
|
|
33
|
+
loading={loading}
|
|
34
|
+
inProgress={inProgress}
|
|
31
35
|
/>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
) : (
|
|
37
|
+
<View style={styles.progressBarContainer}>
|
|
38
|
+
<ProgressBarInner
|
|
39
|
+
width={100}
|
|
40
|
+
animationDuration={0}
|
|
41
|
+
color={
|
|
42
|
+
reverseTheme ? undefined : tokens["color-surface--background"]
|
|
43
|
+
}
|
|
44
|
+
/>
|
|
45
|
+
{!loading && (
|
|
46
|
+
<>
|
|
47
|
+
{inProgress && inProgress > 0 ? (
|
|
48
|
+
<ProgressBarInner
|
|
49
|
+
width={calculateWidth(total, current + inProgress)}
|
|
50
|
+
color={tokens["color-informative"]}
|
|
51
|
+
animationDuration={800}
|
|
52
|
+
/>
|
|
53
|
+
) : (
|
|
54
|
+
<></>
|
|
55
|
+
)}
|
|
35
56
|
<ProgressBarInner
|
|
36
|
-
width={calculateWidth(total, current
|
|
37
|
-
color={tokens["color-
|
|
38
|
-
animationDuration={
|
|
57
|
+
width={calculateWidth(total, current)}
|
|
58
|
+
color={tokens["color-interactive"]}
|
|
59
|
+
animationDuration={600}
|
|
39
60
|
/>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
width={calculateWidth(total, current)}
|
|
45
|
-
color={tokens["color-interactive"]}
|
|
46
|
-
animationDuration={600}
|
|
47
|
-
/>
|
|
48
|
-
</>
|
|
49
|
-
)}
|
|
50
|
-
</View>
|
|
61
|
+
</>
|
|
62
|
+
)}
|
|
63
|
+
</View>
|
|
64
|
+
)}
|
|
51
65
|
</View>
|
|
52
66
|
);
|
|
53
67
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { styles } from "./ProgressBar.style";
|
|
4
|
+
|
|
5
|
+
interface ProgressBarSteppedProps {
|
|
6
|
+
readonly total: number;
|
|
7
|
+
readonly current: number;
|
|
8
|
+
readonly color?: string;
|
|
9
|
+
readonly loading?: boolean;
|
|
10
|
+
readonly inProgress?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ProgressBarStepped({
|
|
14
|
+
total,
|
|
15
|
+
current,
|
|
16
|
+
color,
|
|
17
|
+
loading,
|
|
18
|
+
inProgress,
|
|
19
|
+
}: ProgressBarSteppedProps) {
|
|
20
|
+
return (
|
|
21
|
+
<View style={[styles.progressBarContainer, { height: 10 }]}>
|
|
22
|
+
{Array.from({ length: total }).map((_, index) => {
|
|
23
|
+
const step = index + 1;
|
|
24
|
+
const isCompleted = step <= current;
|
|
25
|
+
const lastStep = step === total;
|
|
26
|
+
const inProgressSteps = current + (inProgress || 0);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<View
|
|
30
|
+
key={step}
|
|
31
|
+
style={[
|
|
32
|
+
styles.step,
|
|
33
|
+
{ ...(color && { backgroundColor: color }) },
|
|
34
|
+
!loading && isCompleted && styles.completedStep,
|
|
35
|
+
!loading &&
|
|
36
|
+
!isCompleted &&
|
|
37
|
+
step <= inProgressSteps &&
|
|
38
|
+
styles.inProgressStep,
|
|
39
|
+
lastStep && { marginRight: 0 },
|
|
40
|
+
]}
|
|
41
|
+
testID={"progress-step"}
|
|
42
|
+
></View>
|
|
43
|
+
);
|
|
44
|
+
})}
|
|
45
|
+
</View>
|
|
46
|
+
);
|
|
47
|
+
}
|
package/src/ProgressBar/types.ts
CHANGED
|
@@ -12,7 +12,8 @@ export interface ProgressBarProps {
|
|
|
12
12
|
readonly current: number;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* The number of items in progress (not completed, but to be less than the total)
|
|
15
|
+
* The number of items in progress (not completed, but to be less than the total);
|
|
16
|
+
* not applicable with stepped variation
|
|
16
17
|
*/
|
|
17
18
|
readonly inProgress?: number;
|
|
18
19
|
|
|
@@ -31,4 +32,10 @@ export interface ProgressBarProps {
|
|
|
31
32
|
* Component to render above the progress bar.
|
|
32
33
|
*/
|
|
33
34
|
readonly header?: ReactNode;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Set the variation of the progress bar
|
|
38
|
+
* @default progress
|
|
39
|
+
*/
|
|
40
|
+
readonly variation?: "progress" | "stepped";
|
|
34
41
|
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export function useShowClear({ clearable, multiline, focused, hasValue, disabled = false, }) {
|
|
2
|
-
if (multiline && clearable !== "never") {
|
|
3
|
-
throw new Error("Multiline inputs can not be clearable");
|
|
4
|
-
}
|
|
5
|
-
// Do not show if there is no value
|
|
6
|
-
if (!hasValue || clearable === "never" || disabled) {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
switch (clearable) {
|
|
10
|
-
case "while-editing":
|
|
11
|
-
return focused;
|
|
12
|
-
case "always":
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Clearable } from "../InputFieldWrapper";
|
|
2
|
-
interface UseShowClearParameters {
|
|
3
|
-
clearable: Clearable;
|
|
4
|
-
multiline: boolean;
|
|
5
|
-
focused: boolean;
|
|
6
|
-
hasValue: boolean;
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
}
|
|
9
|
-
export declare function useShowClear({ clearable, multiline, focused, hasValue, disabled, }: UseShowClearParameters): boolean | undefined;
|
|
10
|
-
export {};
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { useShowClear } from "./useShowClear";
|
|
2
|
-
import { Clearable } from "..";
|
|
3
|
-
|
|
4
|
-
interface UseShowClearParameters {
|
|
5
|
-
clearable: Clearable;
|
|
6
|
-
hasValue: boolean;
|
|
7
|
-
focused: boolean;
|
|
8
|
-
multiline: boolean;
|
|
9
|
-
disabled: boolean;
|
|
10
|
-
expected: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
describe("useShowClear", () => {
|
|
14
|
-
describe.each<UseShowClearParameters>([
|
|
15
|
-
{
|
|
16
|
-
clearable: "always",
|
|
17
|
-
hasValue: true,
|
|
18
|
-
focused: false,
|
|
19
|
-
multiline: false,
|
|
20
|
-
disabled: false,
|
|
21
|
-
expected: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
clearable: "always",
|
|
25
|
-
hasValue: true,
|
|
26
|
-
focused: true,
|
|
27
|
-
multiline: false,
|
|
28
|
-
disabled: false,
|
|
29
|
-
expected: true,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
clearable: "always",
|
|
33
|
-
hasValue: true,
|
|
34
|
-
focused: false,
|
|
35
|
-
multiline: false,
|
|
36
|
-
disabled: true,
|
|
37
|
-
expected: false,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
clearable: "always",
|
|
41
|
-
hasValue: false,
|
|
42
|
-
focused: false,
|
|
43
|
-
multiline: false,
|
|
44
|
-
disabled: true,
|
|
45
|
-
expected: false,
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
clearable: "while-editing",
|
|
49
|
-
hasValue: true,
|
|
50
|
-
focused: false,
|
|
51
|
-
multiline: false,
|
|
52
|
-
disabled: false,
|
|
53
|
-
expected: false,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
clearable: "while-editing",
|
|
57
|
-
hasValue: true,
|
|
58
|
-
focused: true,
|
|
59
|
-
multiline: false,
|
|
60
|
-
disabled: false,
|
|
61
|
-
expected: true,
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
clearable: "while-editing",
|
|
65
|
-
hasValue: false,
|
|
66
|
-
focused: false,
|
|
67
|
-
multiline: false,
|
|
68
|
-
disabled: true,
|
|
69
|
-
expected: false,
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
clearable: "while-editing",
|
|
73
|
-
hasValue: true,
|
|
74
|
-
focused: false,
|
|
75
|
-
multiline: false,
|
|
76
|
-
disabled: true,
|
|
77
|
-
expected: false,
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
clearable: "never",
|
|
81
|
-
hasValue: true,
|
|
82
|
-
focused: false,
|
|
83
|
-
multiline: false,
|
|
84
|
-
disabled: false,
|
|
85
|
-
expected: false,
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
clearable: "never",
|
|
89
|
-
hasValue: true,
|
|
90
|
-
focused: true,
|
|
91
|
-
multiline: false,
|
|
92
|
-
disabled: false,
|
|
93
|
-
expected: false,
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
clearable: "never",
|
|
97
|
-
hasValue: false,
|
|
98
|
-
focused: false,
|
|
99
|
-
multiline: false,
|
|
100
|
-
disabled: true,
|
|
101
|
-
expected: false,
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
clearable: "never",
|
|
105
|
-
hasValue: true,
|
|
106
|
-
focused: false,
|
|
107
|
-
multiline: false,
|
|
108
|
-
disabled: true,
|
|
109
|
-
expected: false,
|
|
110
|
-
},
|
|
111
|
-
])(
|
|
112
|
-
"%j",
|
|
113
|
-
({
|
|
114
|
-
clearable,
|
|
115
|
-
hasValue,
|
|
116
|
-
focused,
|
|
117
|
-
multiline,
|
|
118
|
-
disabled,
|
|
119
|
-
expected,
|
|
120
|
-
}: UseShowClearParameters) => {
|
|
121
|
-
it(`returns ${expected}`, () => {
|
|
122
|
-
expect(
|
|
123
|
-
useShowClear({ clearable, multiline, focused, hasValue, disabled }),
|
|
124
|
-
).toEqual(expected);
|
|
125
|
-
});
|
|
126
|
-
},
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
it("throws an error if multiline is true and clearable isn't never", () => {
|
|
130
|
-
expect(() => {
|
|
131
|
-
useShowClear({
|
|
132
|
-
clearable: "always",
|
|
133
|
-
multiline: true,
|
|
134
|
-
focused: true,
|
|
135
|
-
hasValue: true,
|
|
136
|
-
disabled: false,
|
|
137
|
-
});
|
|
138
|
-
}).toThrow();
|
|
139
|
-
expect(() => {
|
|
140
|
-
useShowClear({
|
|
141
|
-
clearable: "while-editing",
|
|
142
|
-
multiline: true,
|
|
143
|
-
focused: true,
|
|
144
|
-
hasValue: true,
|
|
145
|
-
disabled: false,
|
|
146
|
-
});
|
|
147
|
-
}).toThrow();
|
|
148
|
-
expect(() => {
|
|
149
|
-
useShowClear({
|
|
150
|
-
clearable: "never",
|
|
151
|
-
multiline: true,
|
|
152
|
-
focused: true,
|
|
153
|
-
hasValue: true,
|
|
154
|
-
disabled: false,
|
|
155
|
-
});
|
|
156
|
-
}).not.toThrow();
|
|
157
|
-
});
|
|
158
|
-
});
|