@jobber/components-native 0.44.2 → 0.45.1
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/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.js +3 -3
- package/dist/src/AutoLink/utils.js +14 -3
- 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 +35 -0
- package/dist/src/hooks/useAtlantisI18n/locales/es.json +35 -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/AutoLink/utils.d.ts +2 -2
- 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 +7 -0
- package/package.json +2 -2
- package/src/AtlantisContext/AtlantisContext.tsx +10 -0
- package/src/AutoLink/AutoLink.test.tsx +3 -4
- package/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.tsx +3 -3
- package/src/AutoLink/utils.ts +16 -5
- 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 +35 -0
- package/src/hooks/useAtlantisI18n/locales/es.json +35 -0
- package/src/hooks/useAtlantisI18n/useAtlantisI18n.test.ts +53 -0
- package/src/hooks/useAtlantisI18n/useAtlantisI18n.ts +42 -0
- package/dist/src/AutoLink/messages.js +0 -18
- 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/AutoLink/messages.d.ts +0 -17
- 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/AutoLink/messages.ts +0 -19
- 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
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
limitInputWholeDigits,
|
|
12
12
|
parseGivenInput,
|
|
13
13
|
} from "./utils";
|
|
14
|
-
import { messages } from "./messages";
|
|
15
14
|
import { useAtlantisContext } from "../AtlantisContext";
|
|
16
15
|
import { InputText, InputTextProps } from "../InputText";
|
|
17
16
|
import { useFormController } from "../hooks/useFormController";
|
|
17
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
18
18
|
|
|
19
19
|
export interface InputCurrencyProps
|
|
20
20
|
extends Omit<
|
|
@@ -164,7 +164,7 @@ export function InputCurrency(props: InputCurrencyProps): JSX.Element {
|
|
|
164
164
|
}
|
|
165
165
|
};
|
|
166
166
|
|
|
167
|
-
const {
|
|
167
|
+
const { t } = useAtlantisI18n();
|
|
168
168
|
|
|
169
169
|
return (
|
|
170
170
|
<>
|
|
@@ -186,7 +186,7 @@ export function InputCurrency(props: InputCurrencyProps): JSX.Element {
|
|
|
186
186
|
validations={{
|
|
187
187
|
pattern: {
|
|
188
188
|
value: NUMBER_VALIDATION_REGEX,
|
|
189
|
-
message:
|
|
189
|
+
message: t("errors.notANumber"),
|
|
190
190
|
},
|
|
191
191
|
...props.validations,
|
|
192
192
|
}}
|
|
@@ -3,14 +3,13 @@ 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 { useIntl } from "react-intl";
|
|
7
6
|
import { utcToZonedTime } from "date-fns-tz";
|
|
8
7
|
import { format as formatDate } from "date-fns";
|
|
9
|
-
import { messages } from "./messages";
|
|
10
8
|
import { Clearable, InputFieldWrapperProps } from "../InputFieldWrapper";
|
|
11
9
|
import { FormField } from "../FormField";
|
|
12
10
|
import { InputPressable } from "../InputPressable";
|
|
13
11
|
import { useAtlantisContext } from "../AtlantisContext";
|
|
12
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
14
13
|
|
|
15
14
|
interface BaseInputDateProps
|
|
16
15
|
extends Pick<InputFieldWrapperProps, "invalid" | "disabled" | "placeholder"> {
|
|
@@ -154,7 +153,7 @@ function InternalInputDate({
|
|
|
154
153
|
accessibilityHint,
|
|
155
154
|
}: InputDateProps): JSX.Element {
|
|
156
155
|
const [showPicker, setShowPicker] = useState(false);
|
|
157
|
-
const {
|
|
156
|
+
const { t, locale } = useAtlantisI18n();
|
|
158
157
|
const { timeZone, dateFormat } = useAtlantisContext();
|
|
159
158
|
|
|
160
159
|
const date = useMemo(() => {
|
|
@@ -173,8 +172,7 @@ function InternalInputDate({
|
|
|
173
172
|
|
|
174
173
|
const canClearDate = formattedDate === emptyValueLabel ? "never" : clearable;
|
|
175
174
|
|
|
176
|
-
const placeholderLabel =
|
|
177
|
-
placeholder ?? formatMessage(messages.datePlaceholder);
|
|
175
|
+
const placeholderLabel = placeholder ?? t("date");
|
|
178
176
|
|
|
179
177
|
return (
|
|
180
178
|
<>
|
|
@@ -198,6 +196,9 @@ function InternalInputDate({
|
|
|
198
196
|
maximumDate={maxDate}
|
|
199
197
|
minimumDate={minDate}
|
|
200
198
|
mode="date"
|
|
199
|
+
confirmTextIOS={t("confirm")}
|
|
200
|
+
cancelTextIOS={t("cancel")}
|
|
201
|
+
locale={locale}
|
|
201
202
|
onCancel={handleCancel}
|
|
202
203
|
onConfirm={handleConfirm}
|
|
203
204
|
/>
|
|
@@ -2,13 +2,11 @@ import React from "react";
|
|
|
2
2
|
import { RenderAPI, fireEvent, render } from "@testing-library/react-native";
|
|
3
3
|
// eslint-disable-next-line no-restricted-imports
|
|
4
4
|
import { Text, ViewStyle } from "react-native";
|
|
5
|
-
import { useIntl } from "react-intl";
|
|
6
5
|
import {
|
|
7
6
|
InputFieldWrapper,
|
|
8
7
|
InputFieldWrapperProps,
|
|
9
8
|
commonInputStyles,
|
|
10
9
|
} from ".";
|
|
11
|
-
import { messages as clearMessages } from "./components/ClearAction";
|
|
12
10
|
import { styles } from "./InputFieldWrapper.style";
|
|
13
11
|
import { typographyStyles } from "../Typography";
|
|
14
12
|
|
|
@@ -32,6 +30,7 @@ function renderWithSuffixLabel(hasValue: boolean): RenderAPI {
|
|
|
32
30
|
return renderInputFieldWrapper({ suffix: mockLabel, hasValue });
|
|
33
31
|
}
|
|
34
32
|
|
|
33
|
+
const clearInput = "Clear input";
|
|
35
34
|
describe("InputFieldWrapper", () => {
|
|
36
35
|
it("renders an invalid InputFieldWrapper", () => {
|
|
37
36
|
const { getByTestId } = renderInputFieldWrapper({ invalid: true });
|
|
@@ -120,36 +119,26 @@ describe("InputFieldWrapper", () => {
|
|
|
120
119
|
|
|
121
120
|
describe("ClearAction", () => {
|
|
122
121
|
it("renders the Clear Action Button when showClearAction is true", () => {
|
|
123
|
-
const { formatMessage } = useIntl();
|
|
124
122
|
const { getByLabelText } = renderInputFieldWrapper({
|
|
125
123
|
showClearAction: true,
|
|
126
124
|
});
|
|
127
|
-
expect(
|
|
128
|
-
getByLabelText(formatMessage(clearMessages.clearTextLabel)),
|
|
129
|
-
).toBeDefined();
|
|
125
|
+
expect(getByLabelText(clearInput)).toBeDefined();
|
|
130
126
|
});
|
|
131
127
|
|
|
132
128
|
it("does not render the Clear Action Button when showClearAction is false", () => {
|
|
133
|
-
const { formatMessage } = useIntl();
|
|
134
129
|
const { queryByLabelText } = renderInputFieldWrapper({
|
|
135
130
|
showClearAction: false,
|
|
136
131
|
});
|
|
137
|
-
expect(
|
|
138
|
-
queryByLabelText(formatMessage(clearMessages.clearTextLabel)),
|
|
139
|
-
).toBeNull();
|
|
132
|
+
expect(queryByLabelText(clearInput)).toBeNull();
|
|
140
133
|
});
|
|
141
134
|
|
|
142
135
|
it("calls onClear when the Clear Action button is pressed", () => {
|
|
143
|
-
const { formatMessage } = useIntl();
|
|
144
136
|
const onClear = jest.fn();
|
|
145
137
|
const { getByLabelText } = renderInputFieldWrapper({
|
|
146
138
|
showClearAction: true,
|
|
147
139
|
onClear: onClear,
|
|
148
140
|
});
|
|
149
|
-
fireEvent(
|
|
150
|
-
getByLabelText(formatMessage(clearMessages.clearTextLabel)),
|
|
151
|
-
"press",
|
|
152
|
-
);
|
|
141
|
+
fireEvent(getByLabelText(clearInput), "press");
|
|
153
142
|
expect(onClear).toHaveBeenCalled();
|
|
154
143
|
});
|
|
155
144
|
});
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { fireEvent, render } from "@testing-library/react-native";
|
|
3
|
-
import { useIntl } from "react-intl";
|
|
4
3
|
import { ClearAction } from "./ClearAction";
|
|
5
|
-
import { messages } from "./messages";
|
|
6
4
|
|
|
7
5
|
it("should call the handler", () => {
|
|
8
6
|
const pressHandler = jest.fn();
|
|
9
|
-
const { formatMessage } = useIntl();
|
|
10
|
-
|
|
11
7
|
const { getByLabelText } = render(<ClearAction onPress={pressHandler} />);
|
|
12
8
|
|
|
13
|
-
fireEvent.press(getByLabelText(
|
|
9
|
+
fireEvent.press(getByLabelText("Clear input"));
|
|
14
10
|
expect(pressHandler).toHaveBeenCalled();
|
|
15
11
|
});
|
|
@@ -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}
|