@jobber/components-native 0.44.2 → 0.45.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 +88 -0
- package/dist/src/AtlantisContext/AtlantisContext.js +1 -0
- package/dist/src/BottomSheet/BottomSheet.js +3 -4
- package/dist/src/ButtonGroup/ButtonGroup.js +3 -4
- package/dist/src/ButtonGroup/utils.js +4 -5
- package/dist/src/ContentOverlay/ContentOverlay.js +3 -4
- package/dist/src/Form/components/FormErrorBanner/FormErrorBanner.js +5 -13
- package/dist/src/Form/components/FormMask/FormMask.js +3 -4
- package/dist/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.js +4 -5
- package/dist/src/Form/components/FormSaveButton/FormSaveButton.js +4 -5
- package/dist/src/Form/hooks/useOfflineHandler.js +6 -7
- package/dist/src/FormatFile/FormatFile.js +3 -4
- package/dist/src/FormatFile/components/FileView/FileView.js +3 -3
- package/dist/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.js +6 -7
- package/dist/src/FormatFile/components/MediaView/MediaView.js +3 -3
- package/dist/src/FormatFile/utils/computeA11yLabel.js +4 -5
- package/dist/src/InputCurrency/InputCurrency.js +3 -3
- package/dist/src/InputDate/InputDate.js +4 -5
- package/dist/src/InputFieldWrapper/components/ClearAction/ClearAction.js +3 -4
- package/dist/src/InputFieldWrapper/components/ClearAction/index.js +0 -1
- package/dist/src/InputNumber/InputNumber.js +3 -4
- package/dist/src/InputPassword/InputPassword.js +3 -4
- package/dist/src/InputTime/InputTime.js +3 -4
- package/dist/src/Menu/Menu.js +3 -4
- package/dist/src/ProgressBar/ProgressBar.js +14 -8
- package/dist/src/Select/Select.js +5 -6
- package/dist/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.ios.js +3 -4
- package/dist/src/Toast/Toast.js +4 -5
- package/dist/src/hooks/useAtlantisI18n/index.js +1 -0
- package/dist/src/hooks/useAtlantisI18n/locales/en.json +31 -0
- package/dist/src/hooks/useAtlantisI18n/locales/es.json +31 -0
- package/dist/src/hooks/useAtlantisI18n/useAtlantisI18n.js +22 -0
- package/dist/tsconfig.json +38 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/AtlantisContext/AtlantisContext.d.ts +8 -0
- package/dist/types/src/FormatFile/utils/computeA11yLabel.d.ts +6 -6
- package/dist/types/src/InputFieldWrapper/components/ClearAction/index.d.ts +0 -1
- package/dist/types/src/hooks/useAtlantisI18n/index.d.ts +1 -0
- package/dist/types/src/hooks/useAtlantisI18n/useAtlantisI18n.d.ts +6 -0
- package/package.json +2 -2
- package/src/AtlantisContext/AtlantisContext.tsx +10 -0
- package/src/BottomSheet/BottomSheet.test.tsx +3 -4
- package/src/BottomSheet/BottomSheet.tsx +3 -4
- package/src/ButtonGroup/ButtonGroup.test.tsx +8 -9
- package/src/ButtonGroup/ButtonGroup.tsx +3 -4
- package/src/ButtonGroup/utils.ts +5 -6
- package/src/ContentOverlay/ContentOverlay.test.tsx +1 -11
- package/src/ContentOverlay/ContentOverlay.tsx +5 -9
- package/src/Form/Form.test.tsx +9 -40
- package/src/Form/components/FormErrorBanner/FormErrorBanner.test.tsx +9 -72
- package/src/Form/components/FormErrorBanner/FormErrorBanner.tsx +6 -15
- package/src/Form/components/FormMask/FormMask.tsx +3 -7
- package/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.tsx +4 -5
- package/src/Form/components/FormSaveButton/FormSaveButton.test.tsx +3 -7
- package/src/Form/components/FormSaveButton/FormSaveButton.tsx +4 -5
- package/src/Form/hooks/useOfflineHandler.ts +7 -8
- package/src/FormatFile/FormatFile.test.tsx +7 -31
- package/src/FormatFile/FormatFile.tsx +3 -7
- package/src/FormatFile/components/FileView/FileView.tsx +3 -3
- package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.test.tsx +2 -9
- package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.tsx +6 -7
- package/src/FormatFile/components/MediaView/MediaView.tsx +3 -3
- package/src/FormatFile/utils/computeA11yLabel.ts +9 -12
- package/src/InputCurrency/InputCurrency.test.tsx +6 -1
- package/src/InputCurrency/InputCurrency.tsx +3 -3
- package/src/InputDate/InputDate.tsx +6 -5
- package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +4 -15
- package/src/InputFieldWrapper/components/ClearAction/ClearAction.test.tsx +1 -5
- package/src/InputFieldWrapper/components/ClearAction/ClearAction.tsx +3 -4
- package/src/InputFieldWrapper/components/ClearAction/index.ts +0 -1
- package/src/InputNumber/InputNumber.test.tsx +10 -18
- package/src/InputNumber/InputNumber.tsx +3 -4
- package/src/InputPassword/InputPassword.test.tsx +1 -2
- package/src/InputPassword/InputPassword.tsx +3 -4
- package/src/InputSearch/InputSearch.test.tsx +1 -6
- package/src/InputText/InputText.test.tsx +10 -38
- package/src/InputTime/InputTime.tsx +3 -4
- package/src/Menu/Menu.test.tsx +10 -9
- package/src/Menu/Menu.tsx +3 -4
- package/src/ProgressBar/ProgressBar.tsx +17 -8
- package/src/Select/Select.test.tsx +4 -5
- package/src/Select/Select.tsx +5 -8
- package/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.ios.tsx +3 -4
- package/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.test.tsx +1 -2
- package/src/Toast/Toast.tsx +4 -9
- package/src/hooks/useAtlantisI18n/index.ts +1 -0
- package/src/hooks/useAtlantisI18n/locales/en.json +31 -0
- package/src/hooks/useAtlantisI18n/locales/es.json +31 -0
- package/src/hooks/useAtlantisI18n/useAtlantisI18n.test.ts +53 -0
- package/src/hooks/useAtlantisI18n/useAtlantisI18n.ts +43 -0
- package/dist/src/BottomSheet/messages.js +0 -8
- package/dist/src/ButtonGroup/messages.js +0 -18
- package/dist/src/ContentOverlay/messages.js +0 -8
- package/dist/src/Form/components/FormErrorBanner/messages.js +0 -13
- package/dist/src/Form/components/FormMessage/components/InternalFormMessage/messages.js +0 -8
- package/dist/src/Form/components/FormSaveButton/messages.js +0 -8
- package/dist/src/Form/messages.js +0 -28
- package/dist/src/FormatFile/components/FormatFileBottomSheet/messages.js +0 -13
- package/dist/src/FormatFile/messages.js +0 -23
- package/dist/src/InputCurrency/messages.js +0 -8
- package/dist/src/InputDate/messages.js +0 -8
- package/dist/src/InputFieldWrapper/components/ClearAction/messages.js +0 -8
- package/dist/src/InputNumber/messages.js +0 -8
- package/dist/src/InputPassword/messages.js +0 -8
- package/dist/src/InputTime/messages.js +0 -8
- package/dist/src/Menu/messages.js +0 -8
- package/dist/src/ProgressBar/messages.js +0 -13
- package/dist/src/Select/components/SelectDefaultPicker/messages.js +0 -8
- package/dist/src/Select/messages.js +0 -13
- package/dist/src/Toast/messages.js +0 -13
- package/dist/types/src/BottomSheet/messages.d.ts +0 -7
- package/dist/types/src/ButtonGroup/messages.d.ts +0 -17
- package/dist/types/src/ContentOverlay/messages.d.ts +0 -7
- package/dist/types/src/Form/components/FormErrorBanner/messages.d.ts +0 -12
- package/dist/types/src/Form/components/FormMessage/components/InternalFormMessage/messages.d.ts +0 -7
- package/dist/types/src/Form/components/FormSaveButton/messages.d.ts +0 -7
- package/dist/types/src/Form/messages.d.ts +0 -27
- package/dist/types/src/FormatFile/components/FormatFileBottomSheet/messages.d.ts +0 -12
- package/dist/types/src/FormatFile/messages.d.ts +0 -22
- package/dist/types/src/InputCurrency/messages.d.ts +0 -7
- package/dist/types/src/InputDate/messages.d.ts +0 -7
- package/dist/types/src/InputFieldWrapper/components/ClearAction/messages.d.ts +0 -7
- package/dist/types/src/InputNumber/messages.d.ts +0 -7
- package/dist/types/src/InputPassword/messages.d.ts +0 -7
- package/dist/types/src/InputTime/messages.d.ts +0 -7
- package/dist/types/src/Menu/messages.d.ts +0 -7
- package/dist/types/src/ProgressBar/messages.d.ts +0 -12
- package/dist/types/src/Select/components/SelectDefaultPicker/messages.d.ts +0 -7
- package/dist/types/src/Select/messages.d.ts +0 -12
- package/dist/types/src/Toast/messages.d.ts +0 -12
- package/src/BottomSheet/messages.ts +0 -9
- package/src/ButtonGroup/messages.ts +0 -19
- package/src/ContentOverlay/messages.ts +0 -9
- package/src/Form/components/FormErrorBanner/messages.ts +0 -14
- package/src/Form/components/FormMessage/components/InternalFormMessage/messages.ts +0 -10
- package/src/Form/components/FormSaveButton/messages.ts +0 -9
- package/src/Form/messages.ts +0 -33
- package/src/FormatFile/components/FormatFileBottomSheet/messages.ts +0 -14
- package/src/FormatFile/messages.ts +0 -24
- package/src/InputCurrency/messages.ts +0 -10
- package/src/InputDate/messages.ts +0 -9
- package/src/InputFieldWrapper/components/ClearAction/messages.ts +0 -9
- package/src/InputNumber/messages.ts +0 -10
- package/src/InputPassword/messages.ts +0 -9
- package/src/InputTime/messages.ts +0 -9
- package/src/Menu/messages.ts +0 -9
- package/src/ProgressBar/messages.ts +0 -14
- package/src/Select/components/SelectDefaultPicker/messages.ts +0 -9
- package/src/Select/messages.ts +0 -14
- package/src/Toast/messages.ts +0 -14
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Pressable, View } from "react-native";
|
|
3
|
-
import { useIntl } from "react-intl";
|
|
4
3
|
import { styles } from "./ClearAction.style";
|
|
5
|
-
import { messages } from "./messages";
|
|
6
4
|
import { Icon } from "../../../Icon";
|
|
5
|
+
import { useAtlantisI18n } from "../../../hooks/useAtlantisI18n";
|
|
7
6
|
|
|
8
7
|
interface ClearActionProps {
|
|
9
8
|
/**
|
|
@@ -17,12 +16,12 @@ export function ClearAction({
|
|
|
17
16
|
onPress,
|
|
18
17
|
hasMarginRight = false,
|
|
19
18
|
}: ClearActionProps): JSX.Element {
|
|
20
|
-
const {
|
|
19
|
+
const { t } = useAtlantisI18n();
|
|
21
20
|
return (
|
|
22
21
|
<Pressable
|
|
23
22
|
style={[styles.container, hasMarginRight && styles.addedMargin]}
|
|
24
23
|
onPress={onPress}
|
|
25
|
-
accessibilityLabel={
|
|
24
|
+
accessibilityLabel={t("InputFieldWrapper.clear")}
|
|
26
25
|
>
|
|
27
26
|
<View style={styles.circle}>
|
|
28
27
|
<Icon size="small" name="cross" color="interactiveSubtle" />
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { fireEvent, render, waitFor } from "@testing-library/react-native";
|
|
3
|
-
import { useIntl } from "react-intl";
|
|
4
3
|
import { InputNumber } from ".";
|
|
5
|
-
import { messages } from "./messages";
|
|
6
4
|
|
|
7
5
|
type OS = "ios" | "android";
|
|
8
6
|
let Platform: { OS: OS };
|
|
@@ -28,8 +26,9 @@ it.each(platforms)(
|
|
|
28
26
|
},
|
|
29
27
|
);
|
|
30
28
|
|
|
29
|
+
const notANumberErrorMessage = "Enter a number";
|
|
30
|
+
|
|
31
31
|
it("Displays a validation message when the value is not a number", async () => {
|
|
32
|
-
const { formatMessage } = useIntl();
|
|
33
32
|
const a11yLabel = "InputNumberTest";
|
|
34
33
|
const onChange = jest.fn();
|
|
35
34
|
const { getByText, getByLabelText } = render(
|
|
@@ -42,7 +41,7 @@ it("Displays a validation message when the value is not a number", async () => {
|
|
|
42
41
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
43
42
|
});
|
|
44
43
|
expect(
|
|
45
|
-
getByText(
|
|
44
|
+
getByText(notANumberErrorMessage, {
|
|
46
45
|
includeHiddenElements: true,
|
|
47
46
|
}),
|
|
48
47
|
).toBeDefined();
|
|
@@ -74,7 +73,6 @@ it("doesn't change the value when the input is controlled without an onChange",
|
|
|
74
73
|
});
|
|
75
74
|
|
|
76
75
|
it("passes validation when decimal value is entered", async () => {
|
|
77
|
-
const { formatMessage } = useIntl();
|
|
78
76
|
const a11yLabel = "InputNumberTest";
|
|
79
77
|
const onChange = jest.fn();
|
|
80
78
|
const { queryByText, getByLabelText } = render(
|
|
@@ -86,12 +84,11 @@ it("passes validation when decimal value is entered", async () => {
|
|
|
86
84
|
await waitFor(() => {
|
|
87
85
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
88
86
|
});
|
|
89
|
-
expect(queryByText(
|
|
87
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
90
88
|
expect(onChange).toHaveBeenCalledWith(parseFloat(numInput));
|
|
91
89
|
});
|
|
92
90
|
|
|
93
91
|
it("passes validation when negative value is entered", async () => {
|
|
94
|
-
const { formatMessage } = useIntl();
|
|
95
92
|
const a11yLabel = "InputNumberTest";
|
|
96
93
|
const onChange = jest.fn();
|
|
97
94
|
const { queryByText, getByLabelText } = render(
|
|
@@ -104,12 +101,11 @@ it("passes validation when negative value is entered", async () => {
|
|
|
104
101
|
await waitFor(() => {
|
|
105
102
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
106
103
|
});
|
|
107
|
-
expect(queryByText(
|
|
104
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
108
105
|
expect(onChange).toHaveBeenCalledWith(parseInt(numInput, 10));
|
|
109
106
|
});
|
|
110
107
|
|
|
111
108
|
it("passes validation when negative decimal value is entered", async () => {
|
|
112
|
-
const { formatMessage } = useIntl();
|
|
113
109
|
const a11yLabel = "InputNumberTest";
|
|
114
110
|
const onChange = jest.fn();
|
|
115
111
|
const { queryByText, getByLabelText } = render(
|
|
@@ -121,12 +117,11 @@ it("passes validation when negative decimal value is entered", async () => {
|
|
|
121
117
|
await waitFor(() => {
|
|
122
118
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
123
119
|
});
|
|
124
|
-
expect(queryByText(
|
|
120
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
125
121
|
expect(onChange).toHaveBeenCalledWith(parseFloat(numInput));
|
|
126
122
|
});
|
|
127
123
|
|
|
128
124
|
it("passes validation when explicit positive value is entered", async () => {
|
|
129
|
-
const { formatMessage } = useIntl();
|
|
130
125
|
const a11yLabel = "InputNumberTest";
|
|
131
126
|
const onChange = jest.fn();
|
|
132
127
|
const { queryByText, getByLabelText } = render(
|
|
@@ -139,12 +134,11 @@ it("passes validation when explicit positive value is entered", async () => {
|
|
|
139
134
|
await waitFor(() => {
|
|
140
135
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
141
136
|
});
|
|
142
|
-
expect(queryByText(
|
|
137
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
143
138
|
expect(onChange).toHaveBeenCalledWith(parseInt(numInput, 10));
|
|
144
139
|
});
|
|
145
140
|
|
|
146
141
|
it("passes validation when e notation value is entered", async () => {
|
|
147
|
-
const { formatMessage } = useIntl();
|
|
148
142
|
const a11yLabel = "InputNumberTest";
|
|
149
143
|
const onChange = jest.fn();
|
|
150
144
|
const { queryByText, getByLabelText } = render(
|
|
@@ -157,12 +151,11 @@ it("passes validation when e notation value is entered", async () => {
|
|
|
157
151
|
await waitFor(() => {
|
|
158
152
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
159
153
|
});
|
|
160
|
-
expect(queryByText(
|
|
154
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
161
155
|
expect(onChange).toHaveBeenCalledWith(parseFloat(numInput));
|
|
162
156
|
});
|
|
163
157
|
|
|
164
158
|
it("passes validation when e notation decimal value is entered", async () => {
|
|
165
|
-
const { formatMessage } = useIntl();
|
|
166
159
|
const a11yLabel = "InputNumberTest";
|
|
167
160
|
const onChange = jest.fn();
|
|
168
161
|
const { queryByText, getByLabelText } = render(
|
|
@@ -175,12 +168,11 @@ it("passes validation when e notation decimal value is entered", async () => {
|
|
|
175
168
|
await waitFor(() => {
|
|
176
169
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
177
170
|
});
|
|
178
|
-
expect(queryByText(
|
|
171
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
179
172
|
expect(onChange).toHaveBeenCalledWith(parseFloat(numInput));
|
|
180
173
|
});
|
|
181
174
|
|
|
182
175
|
it("passes validation when e notation for representing decimal value is entered", async () => {
|
|
183
|
-
const { formatMessage } = useIntl();
|
|
184
176
|
const a11yLabel = "InputNumberTest";
|
|
185
177
|
const onChange = jest.fn();
|
|
186
178
|
const { queryByText, getByLabelText } = render(
|
|
@@ -193,7 +185,7 @@ it("passes validation when e notation for representing decimal value is entered"
|
|
|
193
185
|
await waitFor(() => {
|
|
194
186
|
fireEvent(getByLabelText(a11yLabel), "blur");
|
|
195
187
|
});
|
|
196
|
-
expect(queryByText(
|
|
188
|
+
expect(queryByText(notANumberErrorMessage)).toBeNull();
|
|
197
189
|
expect(onChange).toHaveBeenCalledWith(parseFloat(numInput));
|
|
198
190
|
});
|
|
199
191
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React, { Ref, forwardRef, useState } from "react";
|
|
2
2
|
import { Platform } from "react-native";
|
|
3
|
-
import { useIntl } from "react-intl";
|
|
4
3
|
import flow from "lodash/flow";
|
|
5
4
|
import identity from "lodash/identity";
|
|
6
|
-
import { messages } from "./messages";
|
|
7
5
|
import { InputText, InputTextProps, InputTextRef } from "../InputText";
|
|
6
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
8
7
|
|
|
9
8
|
type NumberKeyboard = "decimal-pad" | "numbers-and-punctuation";
|
|
10
9
|
export interface InputNumberProps
|
|
@@ -36,7 +35,7 @@ function InputNumberInternal(props: InputNumberProps, ref: Ref<InputTextRef>) {
|
|
|
36
35
|
return "numeric";
|
|
37
36
|
}
|
|
38
37
|
};
|
|
39
|
-
const {
|
|
38
|
+
const { t } = useAtlantisI18n();
|
|
40
39
|
const handleChange = (newValue: number | string | undefined) => {
|
|
41
40
|
props.onChange?.(newValue);
|
|
42
41
|
};
|
|
@@ -58,7 +57,7 @@ function InputNumberInternal(props: InputNumberProps, ref: Ref<InputTextRef>) {
|
|
|
58
57
|
validations={{
|
|
59
58
|
pattern: {
|
|
60
59
|
value: NUMBER_VALIDATION_REGEX,
|
|
61
|
-
message:
|
|
60
|
+
message: t("errors.notANumber"),
|
|
62
61
|
},
|
|
63
62
|
...props.validations,
|
|
64
63
|
}}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { fireEvent, render, waitFor } from "@testing-library/react-native";
|
|
3
3
|
import { InputPassword } from "./InputPassword";
|
|
4
|
-
import { messages } from "./messages";
|
|
5
4
|
import { InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
6
5
|
|
|
7
6
|
const MockInputFieldWrapper = jest.fn();
|
|
@@ -30,7 +29,7 @@ describe("InputPassword", () => {
|
|
|
30
29
|
});
|
|
31
30
|
|
|
32
31
|
expect(
|
|
33
|
-
getByText(
|
|
32
|
+
getByText("Enter a password", {
|
|
34
33
|
includeHiddenElements: true,
|
|
35
34
|
}),
|
|
36
35
|
).toBeDefined();
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React, { Ref, forwardRef, useState } from "react";
|
|
2
|
-
import { useIntl } from "react-intl";
|
|
3
2
|
import { IconNames } from "@jobber/design";
|
|
4
|
-
import { messages } from "./messages";
|
|
5
3
|
import { InputText, InputTextProps, InputTextRef } from "../InputText";
|
|
4
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
6
5
|
|
|
7
6
|
export const InputPassword = forwardRef(InputPasswordInternal);
|
|
8
7
|
|
|
@@ -23,7 +22,7 @@ function InputPasswordInternal(
|
|
|
23
22
|
{ usePrivacyEye = true, ...props }: InputPasswordProps,
|
|
24
23
|
ref: Ref<InputTextRef>,
|
|
25
24
|
): JSX.Element {
|
|
26
|
-
const {
|
|
25
|
+
const { t } = useAtlantisI18n();
|
|
27
26
|
const [passwordHidden, setPasswordHidden] = useState(true);
|
|
28
27
|
const [privacyEye, setPrivacyEye] = useState<IconNames>("eye");
|
|
29
28
|
|
|
@@ -59,7 +58,7 @@ function InputPasswordInternal(
|
|
|
59
58
|
validations={{
|
|
60
59
|
required: {
|
|
61
60
|
value: true,
|
|
62
|
-
message:
|
|
61
|
+
message: t("InputPassword.enterPassword"),
|
|
63
62
|
},
|
|
64
63
|
...props.validations,
|
|
65
64
|
}}
|
|
@@ -5,9 +5,7 @@ import {
|
|
|
5
5
|
render,
|
|
6
6
|
waitFor,
|
|
7
7
|
} from "@testing-library/react-native";
|
|
8
|
-
import { useIntl } from "react-intl";
|
|
9
8
|
import { InputSearch } from "./InputSearch";
|
|
10
|
-
import { messages as clearMessages } from "../InputFieldWrapper/components/ClearAction";
|
|
11
9
|
|
|
12
10
|
const accessibilityLabelSearch = "Search";
|
|
13
11
|
const accessibilityHint = "Search clients, properties, quotes, etc.";
|
|
@@ -63,14 +61,11 @@ describe("InputSearch", () => {
|
|
|
63
61
|
|
|
64
62
|
it("clears the search value when the clear button is pressed", () => {
|
|
65
63
|
searchValue = "test search value";
|
|
66
|
-
const { formatMessage } = useIntl();
|
|
67
64
|
const { getByLabelText } = setup();
|
|
68
65
|
|
|
69
66
|
fireEvent(getByLabelText(accessibilityLabelSearch), "focus");
|
|
70
67
|
|
|
71
|
-
const inputSearchClearButton = getByLabelText(
|
|
72
|
-
formatMessage(clearMessages.clearTextLabel),
|
|
73
|
-
);
|
|
68
|
+
const inputSearchClearButton = getByLabelText("Clear input");
|
|
74
69
|
fireEvent.press(inputSearchClearButton);
|
|
75
70
|
expect(mockOnChange).toHaveBeenCalledWith("");
|
|
76
71
|
});
|
|
@@ -5,11 +5,9 @@ import {
|
|
|
5
5
|
render,
|
|
6
6
|
waitFor,
|
|
7
7
|
} from "@testing-library/react-native";
|
|
8
|
-
import { useIntl } from "react-intl";
|
|
9
8
|
import { Platform, TextStyle } from "react-native";
|
|
10
9
|
import { InputText, InputTextProps } from "./InputText";
|
|
11
10
|
import { InputAccessoriesProvider } from "./context";
|
|
12
|
-
import { messages as ClearMessages } from "../InputFieldWrapper/components/ClearAction/messages";
|
|
13
11
|
import {
|
|
14
12
|
Clearable,
|
|
15
13
|
InputFieldWrapperProps,
|
|
@@ -39,6 +37,7 @@ function renderInputText(props: InputTextProps): RenderAPI {
|
|
|
39
37
|
return render(<InputText {...props} />);
|
|
40
38
|
}
|
|
41
39
|
|
|
40
|
+
const clearInput = "Clear input";
|
|
42
41
|
// eslint-disable-next-line max-statements
|
|
43
42
|
describe("InputText", () => {
|
|
44
43
|
describe("InputFieldWrapper gets the expected props", () => {
|
|
@@ -323,30 +322,23 @@ describe("InputText", () => {
|
|
|
323
322
|
|
|
324
323
|
describe("clearable set to always", () => {
|
|
325
324
|
it("renders the clear button when there is a value", () => {
|
|
326
|
-
const { formatMessage } = useIntl();
|
|
327
325
|
const { getByLabelText } = setup({
|
|
328
326
|
clearable: "always",
|
|
329
327
|
value: "test value",
|
|
330
328
|
});
|
|
331
329
|
|
|
332
|
-
const clearButton = getByLabelText(
|
|
333
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
334
|
-
);
|
|
330
|
+
const clearButton = getByLabelText(clearInput);
|
|
335
331
|
expect(clearButton).toBeDefined();
|
|
336
332
|
});
|
|
337
333
|
|
|
338
334
|
it("doesn't render the clear button if there is no value", () => {
|
|
339
|
-
const { formatMessage } = useIntl();
|
|
340
335
|
const { queryByLabelText } = setup({ clearable: "always", value: "" });
|
|
341
336
|
|
|
342
|
-
const clearButton = queryByLabelText(
|
|
343
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
344
|
-
);
|
|
337
|
+
const clearButton = queryByLabelText(clearInput);
|
|
345
338
|
expect(clearButton).toBeNull();
|
|
346
339
|
});
|
|
347
340
|
|
|
348
341
|
it("renders the clear button when there is a value and you are focused", async () => {
|
|
349
|
-
const { formatMessage } = useIntl();
|
|
350
342
|
const { getByLabelText } = setup({
|
|
351
343
|
clearable: "always",
|
|
352
344
|
value: "test value",
|
|
@@ -354,16 +346,13 @@ describe("InputText", () => {
|
|
|
354
346
|
});
|
|
355
347
|
await fireEvent(getByLabelText("clearableTest"), "focus");
|
|
356
348
|
|
|
357
|
-
const clearButton = getByLabelText(
|
|
358
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
359
|
-
);
|
|
349
|
+
const clearButton = getByLabelText(clearInput);
|
|
360
350
|
expect(clearButton).toBeDefined();
|
|
361
351
|
});
|
|
362
352
|
});
|
|
363
353
|
|
|
364
354
|
describe("clearable set to when editing", () => {
|
|
365
355
|
it("renders the clear button when there is a value and it is being edited", async () => {
|
|
366
|
-
const { formatMessage } = useIntl();
|
|
367
356
|
const { getByLabelText } = setup({
|
|
368
357
|
clearable: "while-editing",
|
|
369
358
|
value: "Test Input",
|
|
@@ -371,29 +360,23 @@ describe("InputText", () => {
|
|
|
371
360
|
});
|
|
372
361
|
await fireEvent(getByLabelText("clearableTest"), "focus");
|
|
373
362
|
|
|
374
|
-
const clearButton = getByLabelText(
|
|
375
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
376
|
-
);
|
|
363
|
+
const clearButton = getByLabelText(clearInput);
|
|
377
364
|
expect(clearButton).toBeDefined();
|
|
378
365
|
});
|
|
379
366
|
|
|
380
367
|
it("doesn't render the clear button if the user isn't editing", () => {
|
|
381
|
-
const { formatMessage } = useIntl();
|
|
382
368
|
const { queryByLabelText } = setup({
|
|
383
369
|
clearable: "while-editing",
|
|
384
370
|
value: "Test value",
|
|
385
371
|
});
|
|
386
372
|
|
|
387
|
-
const clearButton = queryByLabelText(
|
|
388
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
389
|
-
);
|
|
373
|
+
const clearButton = queryByLabelText(clearInput);
|
|
390
374
|
expect(clearButton).toBeNull();
|
|
391
375
|
});
|
|
392
376
|
});
|
|
393
377
|
|
|
394
378
|
describe("clearable set to never", () => {
|
|
395
379
|
it("shouldn't show the button when it is being edited", async () => {
|
|
396
|
-
const { formatMessage } = useIntl();
|
|
397
380
|
const { getByLabelText, queryByLabelText } = setup({
|
|
398
381
|
clearable: "never",
|
|
399
382
|
value: "Test Input",
|
|
@@ -401,29 +384,23 @@ describe("InputText", () => {
|
|
|
401
384
|
});
|
|
402
385
|
await fireEvent(getByLabelText("clearableTest"), "focus");
|
|
403
386
|
|
|
404
|
-
const clearButton = queryByLabelText(
|
|
405
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
406
|
-
);
|
|
387
|
+
const clearButton = queryByLabelText(clearInput);
|
|
407
388
|
expect(clearButton).toBeNull();
|
|
408
389
|
});
|
|
409
390
|
|
|
410
391
|
it("shouldn't show the clear button when the user is not editing", () => {
|
|
411
|
-
const { formatMessage } = useIntl();
|
|
412
392
|
const { queryByLabelText } = setup({
|
|
413
393
|
clearable: "never",
|
|
414
394
|
value: "Test Input",
|
|
415
395
|
accessibilityLabel: "clearableTest",
|
|
416
396
|
});
|
|
417
397
|
|
|
418
|
-
const clearButton = queryByLabelText(
|
|
419
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
420
|
-
);
|
|
398
|
+
const clearButton = queryByLabelText(clearInput);
|
|
421
399
|
expect(clearButton).toBeNull();
|
|
422
400
|
});
|
|
423
401
|
});
|
|
424
402
|
|
|
425
403
|
it("should clear the value when the clear button is pressed", () => {
|
|
426
|
-
const { formatMessage } = useIntl();
|
|
427
404
|
const onChangeHandler = jest.fn();
|
|
428
405
|
const { getByLabelText } = setup({
|
|
429
406
|
clearable: "always",
|
|
@@ -431,15 +408,12 @@ describe("InputText", () => {
|
|
|
431
408
|
onChangeText: onChangeHandler,
|
|
432
409
|
});
|
|
433
410
|
|
|
434
|
-
const clearButton = getByLabelText(
|
|
435
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
436
|
-
);
|
|
411
|
+
const clearButton = getByLabelText(clearInput);
|
|
437
412
|
fireEvent(clearButton, "press");
|
|
438
413
|
expect(onChangeHandler).toHaveBeenCalledWith("");
|
|
439
414
|
});
|
|
440
415
|
|
|
441
416
|
it("shouldn't render the clear button if the input is disabled", () => {
|
|
442
|
-
const { formatMessage } = useIntl();
|
|
443
417
|
const { queryByLabelText } = setup({
|
|
444
418
|
clearable: "always",
|
|
445
419
|
value: "Test value",
|
|
@@ -447,9 +421,7 @@ describe("InputText", () => {
|
|
|
447
421
|
disabled: true,
|
|
448
422
|
});
|
|
449
423
|
|
|
450
|
-
const clearButton = queryByLabelText(
|
|
451
|
-
formatMessage(ClearMessages.clearTextLabel),
|
|
452
|
-
);
|
|
424
|
+
const clearButton = queryByLabelText(clearInput);
|
|
453
425
|
expect(clearButton).toBeNull();
|
|
454
426
|
});
|
|
455
427
|
});
|
|
@@ -3,16 +3,15 @@ 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 { useIntl } from "react-intl";
|
|
7
6
|
import { utcToZonedTime } from "date-fns-tz";
|
|
8
7
|
import { format as formatTime } from "date-fns";
|
|
9
8
|
import { styles } from "./InputTime.style";
|
|
10
|
-
import { messages } from "./messages";
|
|
11
9
|
import { getTimeZoneOffsetInMinutes, roundUpToNearestMinutes } from "./utils";
|
|
12
10
|
import { useAtlantisContext } from "../AtlantisContext";
|
|
13
11
|
import { InputPressable } from "../InputPressable";
|
|
14
12
|
import { FormField } from "../FormField";
|
|
15
13
|
import { Clearable, InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
14
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
16
15
|
|
|
17
16
|
interface InputTimeBaseProps
|
|
18
17
|
extends Pick<InputFieldWrapperProps, "invalid" | "disabled" | "placeholder"> {
|
|
@@ -135,7 +134,7 @@ function InternalInputTime({
|
|
|
135
134
|
showIcon = true,
|
|
136
135
|
}: InputTimeProps): JSX.Element {
|
|
137
136
|
const [showPicker, setShowPicker] = useState(false);
|
|
138
|
-
const {
|
|
137
|
+
const { t } = useAtlantisI18n();
|
|
139
138
|
|
|
140
139
|
const { timeZone, timeFormat } = useAtlantisContext();
|
|
141
140
|
const is24Hour = timeFormat === "HH:mm";
|
|
@@ -162,7 +161,7 @@ function InternalInputTime({
|
|
|
162
161
|
clearable={canClearTime}
|
|
163
162
|
disabled={disabled}
|
|
164
163
|
invalid={invalid}
|
|
165
|
-
placeholder={placeholder ??
|
|
164
|
+
placeholder={placeholder ?? t("time")}
|
|
166
165
|
prefix={showIcon ? { icon: "timer" } : undefined}
|
|
167
166
|
value={formattedTime}
|
|
168
167
|
onClear={handleClear}
|
package/src/Menu/Menu.test.tsx
CHANGED
|
@@ -4,7 +4,6 @@ import { Host } from "react-native-portalize";
|
|
|
4
4
|
import { View } from "react-native";
|
|
5
5
|
import { tokens } from "@jobber/design/foundation";
|
|
6
6
|
import { Menu, MenuOptionProps, MenuProps } from ".";
|
|
7
|
-
import { messages } from "./messages";
|
|
8
7
|
import { Icon } from "../Icon";
|
|
9
8
|
import { Button } from "../Button";
|
|
10
9
|
|
|
@@ -24,6 +23,8 @@ const setup = (props?: MenuProps) => {
|
|
|
24
23
|
);
|
|
25
24
|
};
|
|
26
25
|
|
|
26
|
+
const menuLabel = "Menu";
|
|
27
|
+
|
|
27
28
|
describe("Menu", () => {
|
|
28
29
|
beforeEach(() => {
|
|
29
30
|
mockOnPress.mockClear();
|
|
@@ -35,7 +36,7 @@ describe("Menu", () => {
|
|
|
35
36
|
});
|
|
36
37
|
|
|
37
38
|
expect(getByTestId("more")).toBeDefined();
|
|
38
|
-
expect(getByLabelText(
|
|
39
|
+
expect(getByLabelText(menuLabel)).toBeDefined();
|
|
39
40
|
});
|
|
40
41
|
|
|
41
42
|
it("renders every menu option when menu is opened", () => {
|
|
@@ -48,7 +49,7 @@ describe("Menu", () => {
|
|
|
48
49
|
menuOptions,
|
|
49
50
|
});
|
|
50
51
|
|
|
51
|
-
fireEvent.press(getByLabelText(
|
|
52
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
52
53
|
expect(getByLabelText(menuOptions[0].label)).toBeDefined();
|
|
53
54
|
expect(getByLabelText(menuOptions[1].label)).toBeDefined();
|
|
54
55
|
expect(getByLabelText(menuOptions[2].label)).toBeDefined();
|
|
@@ -116,7 +117,7 @@ describe("Menu", () => {
|
|
|
116
117
|
],
|
|
117
118
|
});
|
|
118
119
|
|
|
119
|
-
fireEvent.press(getByLabelText(
|
|
120
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
120
121
|
fireEvent.press(getByLabelText("hi"));
|
|
121
122
|
expect(mockOnPress).toHaveBeenCalled();
|
|
122
123
|
});
|
|
@@ -128,7 +129,7 @@ describe("Menu", () => {
|
|
|
128
129
|
],
|
|
129
130
|
});
|
|
130
131
|
|
|
131
|
-
fireEvent.press(getByLabelText(
|
|
132
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
132
133
|
expect(getByTestId("add").props.style).toContainEqual({
|
|
133
134
|
display: "flex",
|
|
134
135
|
fill: tokens["color-critical"],
|
|
@@ -150,7 +151,7 @@ describe("Menu", () => {
|
|
|
150
151
|
],
|
|
151
152
|
});
|
|
152
153
|
|
|
153
|
-
fireEvent.press(getByLabelText(
|
|
154
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
154
155
|
fireEvent.press(getByLabelText("hi"));
|
|
155
156
|
expect(mockOnPress).toHaveBeenCalled();
|
|
156
157
|
expect(queryByLabelText("hi")).toBeNull();
|
|
@@ -167,7 +168,7 @@ describe("Menu", () => {
|
|
|
167
168
|
},
|
|
168
169
|
],
|
|
169
170
|
});
|
|
170
|
-
fireEvent.press(getByLabelText(
|
|
171
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
171
172
|
expect(getByText("Hi")).toBeDefined();
|
|
172
173
|
});
|
|
173
174
|
|
|
@@ -182,7 +183,7 @@ describe("Menu", () => {
|
|
|
182
183
|
},
|
|
183
184
|
],
|
|
184
185
|
});
|
|
185
|
-
fireEvent.press(getByLabelText(
|
|
186
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
186
187
|
expect(getByText("hi")).toBeDefined();
|
|
187
188
|
});
|
|
188
189
|
});
|
|
@@ -192,7 +193,7 @@ describe("Menu", () => {
|
|
|
192
193
|
menuOptions: [{ label: "hi", icon: "add", onPress: mockOnPress }],
|
|
193
194
|
});
|
|
194
195
|
|
|
195
|
-
fireEvent.press(getByLabelText(
|
|
196
|
+
fireEvent.press(getByLabelText(menuLabel));
|
|
196
197
|
|
|
197
198
|
expect(getByTestId("ATL-MENU-OPTIONS")).toBeDefined();
|
|
198
199
|
expect(getByTestId("add")).toBeDefined();
|
package/src/Menu/Menu.tsx
CHANGED
|
@@ -6,10 +6,8 @@ import {
|
|
|
6
6
|
useWindowDimensions,
|
|
7
7
|
} from "react-native";
|
|
8
8
|
import { Portal } from "react-native-portalize";
|
|
9
|
-
import { useIntl } from "react-intl";
|
|
10
9
|
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
11
10
|
import { styles } from "./Menu.style";
|
|
12
|
-
import { messages } from "./messages";
|
|
13
11
|
import { findViewpoint } from "./utils";
|
|
14
12
|
import { MenuProps } from "./types";
|
|
15
13
|
import { MenuOption } from "./components/MenuOption";
|
|
@@ -18,6 +16,7 @@ import { tokens } from "../utils/design";
|
|
|
18
16
|
import { Button } from "../Button";
|
|
19
17
|
import { Content } from "../Content";
|
|
20
18
|
import { useAtlantisContext } from "../AtlantisContext";
|
|
19
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
21
20
|
|
|
22
21
|
export function Menu({ menuOptions, customActivator }: MenuProps): JSX.Element {
|
|
23
22
|
const [open, setOpen] = useState<boolean>(false);
|
|
@@ -26,7 +25,7 @@ export function Menu({ menuOptions, customActivator }: MenuProps): JSX.Element {
|
|
|
26
25
|
const menuButtonRef = useRef<View | null>();
|
|
27
26
|
const screenInfo = useScreenInformation();
|
|
28
27
|
|
|
29
|
-
const {
|
|
28
|
+
const { t } = useAtlantisI18n();
|
|
30
29
|
|
|
31
30
|
const findMenuLayout = useCallback(() => {
|
|
32
31
|
if (activatorLayout.current) {
|
|
@@ -78,7 +77,7 @@ export function Menu({ menuOptions, customActivator }: MenuProps): JSX.Element {
|
|
|
78
77
|
{!customActivator && (
|
|
79
78
|
<Button
|
|
80
79
|
icon="more"
|
|
81
|
-
accessibilityLabel={
|
|
80
|
+
accessibilityLabel={t("menu")}
|
|
82
81
|
variation="cancel"
|
|
83
82
|
type="tertiary"
|
|
84
83
|
onPress={() => {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import { useIntl } from "react-intl";
|
|
4
3
|
import { ProgressBarProps } from "./types";
|
|
5
4
|
import { styles } from "./ProgressBar.style";
|
|
6
5
|
import { ProgressBarInner, calculateWidth } from "./ProgressBarInner";
|
|
7
|
-
import { messages } from "./messages";
|
|
8
6
|
import { tokens } from "../utils/design";
|
|
7
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
9
8
|
|
|
10
9
|
export function ProgressBar({
|
|
11
10
|
loading,
|
|
@@ -15,17 +14,13 @@ export function ProgressBar({
|
|
|
15
14
|
reverseTheme = false,
|
|
16
15
|
header,
|
|
17
16
|
}: ProgressBarProps): JSX.Element {
|
|
18
|
-
const {
|
|
19
|
-
const accessibilityLabel = [];
|
|
20
|
-
accessibilityLabel.push(formatMessage(messages.complete, { current, total }));
|
|
21
|
-
inProgress &&
|
|
22
|
-
accessibilityLabel.push(formatMessage(messages.inProgress, { inProgress }));
|
|
17
|
+
const { t } = useAtlantisI18n();
|
|
23
18
|
|
|
24
19
|
return (
|
|
25
20
|
<View
|
|
26
21
|
accessible
|
|
27
22
|
accessibilityRole="progressbar"
|
|
28
|
-
accessibilityLabel={
|
|
23
|
+
accessibilityLabel={getA11yLabel()}
|
|
29
24
|
>
|
|
30
25
|
{header}
|
|
31
26
|
<View style={styles.progressBarContainer}>
|
|
@@ -55,4 +50,18 @@ export function ProgressBar({
|
|
|
55
50
|
</View>
|
|
56
51
|
</View>
|
|
57
52
|
);
|
|
53
|
+
|
|
54
|
+
function getA11yLabel(): string {
|
|
55
|
+
const a11yLabelValues = {
|
|
56
|
+
current: String(current),
|
|
57
|
+
total: String(total),
|
|
58
|
+
inProgress: String(inProgress),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
if (inProgress) {
|
|
62
|
+
return t("ProgressBar.inProgress", a11yLabelValues);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return t("ProgressBar.complete", a11yLabelValues);
|
|
66
|
+
}
|
|
58
67
|
}
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
import { tokens } from "@jobber/design/foundation";
|
|
9
9
|
import { AccessibilityInfo } from "react-native";
|
|
10
10
|
import { Option, Select } from ".";
|
|
11
|
-
import { messages } from "./messages";
|
|
12
11
|
import { SelectInternalPicker } from "./components/SelectInternalPicker";
|
|
13
12
|
|
|
14
13
|
const A11yInfoSpy = jest.spyOn(AccessibilityInfo, "isScreenReaderEnabled");
|
|
@@ -24,6 +23,8 @@ afterEach(() => {
|
|
|
24
23
|
jest.resetAllMocks();
|
|
25
24
|
});
|
|
26
25
|
|
|
26
|
+
const defaultPlaceholder = "Select an option";
|
|
27
|
+
|
|
27
28
|
describe("Select", () => {
|
|
28
29
|
it("renders a Select", () => {
|
|
29
30
|
const component = render(
|
|
@@ -34,7 +35,7 @@ describe("Select", () => {
|
|
|
34
35
|
);
|
|
35
36
|
expect(component.getByTestId("arrowDown")).toBeDefined();
|
|
36
37
|
expect(
|
|
37
|
-
component.getByText(
|
|
38
|
+
component.getByText(defaultPlaceholder, {
|
|
38
39
|
includeHiddenElements: true,
|
|
39
40
|
}),
|
|
40
41
|
).toBeDefined();
|
|
@@ -191,9 +192,7 @@ describe("Select", () => {
|
|
|
191
192
|
);
|
|
192
193
|
|
|
193
194
|
expect(
|
|
194
|
-
getByText(
|
|
195
|
-
includeHiddenElements: true,
|
|
196
|
-
}),
|
|
195
|
+
getByText(defaultPlaceholder, { includeHiddenElements: true }),
|
|
197
196
|
).toBeDefined();
|
|
198
197
|
});
|
|
199
198
|
|