@jobber/components-native 0.84.3 → 0.84.4-CLEANUPre-6d043f4.28
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 +24 -15
- package/dist/src/Banner/Banner.js +2 -0
- package/dist/src/Banner/components/BannerIcon/BannerIcon.style.js +3 -0
- package/dist/src/Button/components/InternalButtonLoading/InternalButtonLoading.js +0 -1
- package/dist/src/Form/components/FormCache/FormCache.js +1 -0
- package/dist/src/FormatFile/utils/createUseCreateThumbnail.js +1 -1
- package/dist/src/InputCurrency/InputCurrency.js +42 -30
- package/dist/src/InputEmail/InputEmail.js +12 -4
- package/dist/src/InputFieldWrapper/InputFieldWrapper.style.js +1 -1
- package/dist/src/InputNumber/InputNumber.js +10 -4
- package/dist/src/InputSearch/InputSearch.js +1 -1
- package/dist/src/InputText/InputText.js +1 -0
- package/dist/src/hooks/useAtlantisI18n/locales/en.json +1 -0
- package/dist/src/hooks/useAtlantisI18n/locales/es.json +1 -0
- package/dist/src/hooks/useFormController.js +5 -14
- package/dist/tsconfig.build.json +7 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/tsconfig.json +4 -6
- package/dist/types/src/Banner/components/BannerIcon/BannerIcon.style.d.ts +3 -0
- package/dist/types/src/Banner/types.d.ts +1 -1
- package/dist/types/src/Form/components/FormCache/FormCache.d.ts +2 -2
- package/dist/types/src/Form/context/types.d.ts +2 -2
- package/dist/types/src/Form/hooks/useInternalForm.d.ts +2 -2
- package/dist/types/src/Form/types.d.ts +3 -3
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.style.d.ts +1 -1
- package/package.json +24 -15
- package/src/AtlantisContext/AtlantisContext.test.tsx +1 -1
- package/src/AutoLink/AutoLink.test.tsx +2 -4
- package/src/Banner/Banner.test.tsx +12 -0
- package/src/Banner/Banner.tsx +2 -0
- package/src/Banner/components/BannerIcon/BannerIcon.style.ts +3 -0
- package/src/Banner/types.ts +1 -1
- package/src/Button/components/InternalButtonLoading/InternalButtonLoading.tsx +0 -1
- package/src/Checkbox/CheckboxGroup.test.tsx +2 -6
- package/src/ContentOverlay/hooks/useKeyboardVisibility.test.ts +1 -1
- package/src/ContentOverlay/hooks/useViewLayoutHeight.test.ts +1 -1
- package/src/EmptyState/EmptyState.test.tsx +29 -42
- package/src/Form/components/FormCache/FormCache.tsx +4 -3
- package/src/Form/components/FormMessage/FormMessage.test.tsx +40 -27
- package/src/Form/context/AtlantisFormContext.test.tsx +1 -1
- package/src/Form/context/types.ts +2 -2
- package/src/Form/hooks/useInternalForm.ts +2 -1
- package/src/Form/hooks/useScrollToError/useScrollToError.test.tsx +2 -1
- package/src/Form/types.ts +3 -4
- package/src/FormatFile/FormatFile.test.tsx +6 -6
- package/src/FormatFile/utils/createUseCreateThumbnail.ts +1 -1
- package/src/Icon/__snapshots__/Icon.test.tsx.snap +7 -0
- package/src/InputCurrency/InputCurrency.tsx +71 -57
- package/src/InputEmail/InputEmail.tsx +15 -8
- package/src/InputFieldWrapper/InputFieldWrapper.style.ts +1 -1
- package/src/InputFieldWrapper/components/Prefix/Prefix.test.tsx +5 -11
- package/src/InputNumber/InputNumber.tsx +11 -7
- package/src/InputSearch/InputSearch.tsx +1 -1
- package/src/InputText/InputText.tsx +1 -0
- package/src/ThumbnailList/ThumbnailList.test.tsx +5 -5
- package/src/hooks/useAtlantisI18n/locales/en.json +1 -0
- package/src/hooks/useAtlantisI18n/locales/es.json +1 -0
- package/src/hooks/useFormController.ts +6 -13
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.84.
|
|
3
|
+
"version": "0.84.4-CLEANUPre-6d043f4.28+6d043f490",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"build": "npm run build:clean && npm run compile",
|
|
33
33
|
"bootstrap": "npm run build",
|
|
34
34
|
"prepack": "npm run build",
|
|
35
|
-
"compile": "tsc -
|
|
35
|
+
"compile": "tsc -p tsconfig.build.json",
|
|
36
36
|
"build:clean": "rm -rf ./dist",
|
|
37
37
|
"storybook": "storybook dev -p 6008 --disable-telemetry",
|
|
38
|
-
"build
|
|
38
|
+
"storybook:build": "storybook build --disable-telemetry"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@react-native-clipboard/clipboard": "^1.11.2",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"autolinker": "^4.0.0",
|
|
44
44
|
"deepmerge": "^4.2.2",
|
|
45
45
|
"lodash": "^4.17.21",
|
|
46
|
-
"react-hook-form": "^7.
|
|
47
|
-
"react-intl": "^
|
|
46
|
+
"react-hook-form": "^7.52.0",
|
|
47
|
+
"react-intl": "^7.1.11",
|
|
48
48
|
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
|
49
49
|
"react-native-modalize": "^2.0.13",
|
|
50
50
|
"react-native-portalize": "^1.0.7",
|
|
@@ -53,18 +53,27 @@
|
|
|
53
53
|
"ts-xor": "^1.1.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
+
"@react-native-community/datetimepicker": "^8.4.5",
|
|
57
|
+
"@react-native/babel-preset": "^0.81.1",
|
|
56
58
|
"@storybook/addon-a11y": "^9.1.2",
|
|
57
59
|
"@storybook/react": "^9.1.2",
|
|
58
60
|
"@storybook/react-native-web-vite": "^9.1.2",
|
|
59
|
-
"@testing-library/
|
|
60
|
-
"@testing-library/react-native": "^12.0.1",
|
|
61
|
+
"@testing-library/react-native": "^13.3.3",
|
|
61
62
|
"@types/lodash.chunk": "^4.2.7",
|
|
62
63
|
"@types/lodash.debounce": "^4.0.7",
|
|
63
64
|
"@types/lodash.identity": "^3.0.7",
|
|
64
|
-
"@types/react": "^18.0.28",
|
|
65
65
|
"@types/react-native-uuid": "^1.4.0",
|
|
66
|
-
"
|
|
67
|
-
"
|
|
66
|
+
"@types/react-test-renderer": "19.1.0",
|
|
67
|
+
"date-fns": "^2.30.0",
|
|
68
|
+
"date-fns-tz": "^2.0.0",
|
|
69
|
+
"react-native": "^0.81.4",
|
|
70
|
+
"react-native-gesture-handler": "^2.28.0",
|
|
71
|
+
"react-native-modal-datetime-picker": "^18.0.0",
|
|
72
|
+
"react-native-reanimated": "^3.7.1",
|
|
73
|
+
"react-native-safe-area-context": "^5.4.0",
|
|
74
|
+
"react-native-svg": "^15.1.0",
|
|
75
|
+
"react-native-web": "^0.20.0",
|
|
76
|
+
"react-test-renderer": "19.1.0",
|
|
68
77
|
"storybook": "^9.1.2"
|
|
69
78
|
},
|
|
70
79
|
"peerDependencies": {
|
|
@@ -73,10 +82,10 @@
|
|
|
73
82
|
"@react-native-community/datetimepicker": ">=6.7.0",
|
|
74
83
|
"date-fns": "^2.30.0",
|
|
75
84
|
"date-fns-tz": "^2.0.0",
|
|
76
|
-
"react": "^18.
|
|
77
|
-
"react-intl": "^6
|
|
78
|
-
"react-native": ">=0.
|
|
79
|
-
"react-native-gesture-handler": ">=2.
|
|
85
|
+
"react": "^18 || ^19.1.0",
|
|
86
|
+
"react-intl": "^6 || ^7",
|
|
87
|
+
"react-native": ">=0.79.5",
|
|
88
|
+
"react-native-gesture-handler": ">=2.22.0",
|
|
80
89
|
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
|
81
90
|
"react-native-modal-datetime-picker": " >=13.0.0",
|
|
82
91
|
"react-native-modalize": "^2.0.13",
|
|
@@ -85,5 +94,5 @@
|
|
|
85
94
|
"react-native-safe-area-context": "^5.4.0",
|
|
86
95
|
"react-native-svg": ">=12.0.0"
|
|
87
96
|
},
|
|
88
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "6d043f4908d39d779d91ffa9fe2e84418734665c"
|
|
89
98
|
}
|
|
@@ -8,7 +8,6 @@ const offset = PixelRatio.roundToNearestPixel(imageWidth / PixelRatio.get());
|
|
|
8
8
|
const leftOffset = -1 * offset;
|
|
9
9
|
// looks like deprecation for FlatList in reanimated is cascading down to other exports
|
|
10
10
|
// This is not createAnimatedComponent(FlatList), we are fine
|
|
11
|
-
// eslint-disable-next-line import/no-deprecated
|
|
12
11
|
const AnimatedImage = Animated.createAnimatedComponent(ImageBackground);
|
|
13
12
|
function InternalButtonLoadingInternal({ variation, type, }) {
|
|
14
13
|
const translateX = useSharedValue(0);
|
|
@@ -28,5 +28,6 @@ export function FormCache({ localCacheExclude, localCacheKey, setLocalCache, })
|
|
|
28
28
|
setLocalCache(formData);
|
|
29
29
|
}
|
|
30
30
|
}, [formData, isDirty, localCacheExclude, setLocalCache, shouldExclude]);
|
|
31
|
+
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
31
32
|
return React.createElement(React.Fragment, null);
|
|
32
33
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useIsMounted } from "@jobber/hooks
|
|
1
|
+
import { useIsMounted } from "@jobber/hooks";
|
|
2
2
|
import { useCallback, useEffect, useState } from "react";
|
|
3
3
|
export function createUseCreateThumbnail(createThumbnail) {
|
|
4
4
|
const useCreateThumbnail = useCallback((file) => {
|
|
@@ -24,6 +24,31 @@ const getKeyboard = (props) => {
|
|
|
24
24
|
return "numeric";
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
+
const computeDisplayFromNumericInput = (numberedValue, decimalNumbers, decimalCount, maxLength, maxDecimalPlaces, decimalPlaces, formatNumber) => {
|
|
28
|
+
const transformedValue = limitInputWholeDigits(numberedValue, maxLength);
|
|
29
|
+
const stringValue = decimalNumbers !== ""
|
|
30
|
+
? transformedValue.toString() + "." + decimalNumbers.slice(1)
|
|
31
|
+
: transformedValue.toString();
|
|
32
|
+
if (checkLastChar(stringValue)) {
|
|
33
|
+
const roundedDecimal = configureDecimal(decimalCount, maxDecimalPlaces, stringValue, decimalPlaces);
|
|
34
|
+
const internationalizedValueToDisplay = formatNumber(roundedDecimal, {
|
|
35
|
+
maximumFractionDigits: maxDecimalPlaces,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
onChangeValue: roundedDecimal,
|
|
39
|
+
displayValue: internationalizedValueToDisplay,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const internationalizedValueToDisplay = formatNumber(transformedValue, {
|
|
44
|
+
maximumFractionDigits: maxDecimalPlaces,
|
|
45
|
+
}) + decimalNumbers;
|
|
46
|
+
return {
|
|
47
|
+
onChangeValue: transformedValue.toString() + "." + decimalNumbers.slice(1),
|
|
48
|
+
displayValue: internationalizedValueToDisplay,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
27
52
|
export function InputCurrency(props) {
|
|
28
53
|
var _a, _b;
|
|
29
54
|
const { showCurrencySymbol = true, maxDecimalPlaces = 5, decimalPlaces = 2, maxLength = 10, } = props;
|
|
@@ -35,52 +60,39 @@ export function InputCurrency(props) {
|
|
|
35
60
|
});
|
|
36
61
|
const internalValue = getInternalValue(props, field, intl.formatNumber);
|
|
37
62
|
const [displayValue, setDisplayValue] = useState(internalValue);
|
|
38
|
-
const setOnChangeAndDisplayValues = (onChangeValue, valueToDisplay) => {
|
|
39
|
-
var _a;
|
|
40
|
-
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, onChangeValue);
|
|
41
|
-
setDisplayValue(valueToDisplay);
|
|
42
|
-
};
|
|
43
|
-
const checkDecimalAndI18nOfDisplayValue = (numberedValue, decimalNumbers, decimalCount) => {
|
|
44
|
-
const transformedValue = limitInputWholeDigits(numberedValue, maxLength);
|
|
45
|
-
const stringValue = decimalNumbers !== ""
|
|
46
|
-
? transformedValue.toString() + "." + decimalNumbers.slice(1)
|
|
47
|
-
: transformedValue.toString();
|
|
48
|
-
if (checkLastChar(stringValue)) {
|
|
49
|
-
const roundedDecimal = configureDecimal(decimalCount, maxDecimalPlaces, stringValue, decimalPlaces);
|
|
50
|
-
const internationalizedValueToDisplay = intl.formatNumber(roundedDecimal, {
|
|
51
|
-
maximumFractionDigits: maxDecimalPlaces,
|
|
52
|
-
});
|
|
53
|
-
setOnChangeAndDisplayValues(roundedDecimal, internationalizedValueToDisplay);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
const internationalizedValueToDisplay = intl.formatNumber(transformedValue, {
|
|
57
|
-
maximumFractionDigits: maxDecimalPlaces,
|
|
58
|
-
}) + decimalNumbers;
|
|
59
|
-
setOnChangeAndDisplayValues(transformedValue.toString() + "." + decimalNumbers.slice(1), internationalizedValueToDisplay);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
63
|
const handleChange = (newValue) => {
|
|
64
|
+
var _a, _b;
|
|
63
65
|
const [decimalCount, wholeIntegerValue, decimalNumbers] = parseGivenInput(newValue, floatSeparators.decimal);
|
|
64
66
|
const numberedValue = wholeIntegerValue
|
|
65
67
|
? convertToNumber(wholeIntegerValue)
|
|
66
68
|
: wholeIntegerValue;
|
|
67
69
|
if (isValidNumber(numberedValue) && typeof numberedValue === "number") {
|
|
68
|
-
|
|
70
|
+
const result = computeDisplayFromNumericInput(numberedValue, decimalNumbers, decimalCount, maxLength, maxDecimalPlaces, decimalPlaces, intl.formatNumber);
|
|
71
|
+
const { onChangeValue, displayValue: valueToDisplay } = result;
|
|
72
|
+
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, onChangeValue);
|
|
73
|
+
setDisplayValue(valueToDisplay);
|
|
69
74
|
}
|
|
70
75
|
else {
|
|
71
76
|
const value = (numberedValue === null || numberedValue === void 0 ? void 0 : numberedValue.toString()) + decimalNumbers;
|
|
72
|
-
|
|
77
|
+
(_b = props.onChange) === null || _b === void 0 ? void 0 : _b.call(props, value);
|
|
78
|
+
setDisplayValue(value);
|
|
73
79
|
}
|
|
74
80
|
};
|
|
75
81
|
const { t } = useAtlantisI18n();
|
|
82
|
+
const defaultValidations = {
|
|
83
|
+
pattern: {
|
|
84
|
+
value: NUMBER_VALIDATION_REGEX,
|
|
85
|
+
message: t("errors.notANumber"),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
const mergedValidations = props.validations
|
|
89
|
+
? Object.assign({}, defaultValidations, props.validations)
|
|
90
|
+
: defaultValidations;
|
|
76
91
|
return (React.createElement(InputText, Object.assign({}, props, { prefix: showCurrencySymbol ? { label: currencySymbol } : undefined, keyboard: getKeyboard(props), value: ((_a = props.value) === null || _a === void 0 ? void 0 : _a.toString()) || displayValue, defaultValue: (_b = props.defaultValue) === null || _b === void 0 ? void 0 : _b.toString(), onChangeText: handleChange, transform: {
|
|
77
92
|
output: val => {
|
|
78
93
|
return val === null || val === void 0 ? void 0 : val.split(floatSeparators.group).join("").replace(floatSeparators.decimal, ".");
|
|
79
94
|
},
|
|
80
|
-
}, validations:
|
|
81
|
-
value: NUMBER_VALIDATION_REGEX,
|
|
82
|
-
message: t("errors.notANumber"),
|
|
83
|
-
} }, props.validations), onBlur: () => {
|
|
95
|
+
}, validations: mergedValidations, onBlur: () => {
|
|
84
96
|
var _a;
|
|
85
97
|
(_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
86
98
|
if (field.value === 0 ||
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import React, { forwardRef } from "react";
|
|
2
2
|
import { InputText } from "../InputText";
|
|
3
|
+
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
|
3
4
|
export const InputEmail = forwardRef(InputEmailInternal);
|
|
4
5
|
function InputEmailInternal(props, ref) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const { t } = useAtlantisI18n();
|
|
7
|
+
const defaultValidations = {
|
|
8
|
+
pattern: {
|
|
9
|
+
value: /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/,
|
|
10
|
+
message: t("InputEmail.enterEmail"),
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
const mergedValidations = props.validations
|
|
14
|
+
? Object.assign({}, defaultValidations, props.validations)
|
|
15
|
+
: defaultValidations;
|
|
16
|
+
return (React.createElement(InputText, Object.assign({}, props, { ref: ref, autoCapitalize: "none", autoCorrect: false, keyboard: "email-address", validations: mergedValidations })));
|
|
9
17
|
}
|
|
@@ -36,6 +36,7 @@ export const useStyles = buildThemedStyles(tokens => {
|
|
|
36
36
|
right: 0,
|
|
37
37
|
bottom: 0,
|
|
38
38
|
left: 0,
|
|
39
|
+
zIndex: 1,
|
|
39
40
|
},
|
|
40
41
|
miniLabel: {
|
|
41
42
|
top: 0,
|
|
@@ -44,7 +45,6 @@ export const useStyles = buildThemedStyles(tokens => {
|
|
|
44
45
|
marginRight: tokens["space-small"],
|
|
45
46
|
maxHeight: (typographyStyles.defaultSize.lineHeight || 0) +
|
|
46
47
|
tokens["space-smaller"],
|
|
47
|
-
zIndex: 1,
|
|
48
48
|
},
|
|
49
49
|
// Prevents the miniLabel from cutting off the ClearAction button
|
|
50
50
|
miniLabelShowClearAction: {
|
|
@@ -24,13 +24,19 @@ function InputNumberInternal(props, ref) {
|
|
|
24
24
|
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newValue);
|
|
25
25
|
};
|
|
26
26
|
const { inputTransform: convertToString, outputTransform: convertToNumber } = useNumberTransform(props.value);
|
|
27
|
+
const defaultValidations = {
|
|
28
|
+
pattern: {
|
|
29
|
+
value: NUMBER_VALIDATION_REGEX,
|
|
30
|
+
message: t("errors.notANumber"),
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
const mergedValidations = props.validations
|
|
34
|
+
? Object.assign({}, defaultValidations, props.validations)
|
|
35
|
+
: defaultValidations;
|
|
27
36
|
return (React.createElement(InputText, Object.assign({}, props, { keyboard: getKeyboard(), transform: {
|
|
28
37
|
input: flow(convertToString, ((_a = props.transform) === null || _a === void 0 ? void 0 : _a.input) || identity),
|
|
29
38
|
output: flow(convertToNumber, ((_b = props.transform) === null || _b === void 0 ? void 0 : _b.output) || identity),
|
|
30
|
-
}, ref: ref, value: (_c = props.value) === null || _c === void 0 ? void 0 : _c.toString(), defaultValue: (_d = props.defaultValue) === null || _d === void 0 ? void 0 : _d.toString(), onChangeText: handleChange, validations:
|
|
31
|
-
value: NUMBER_VALIDATION_REGEX,
|
|
32
|
-
message: t("errors.notANumber"),
|
|
33
|
-
} }, props.validations) })));
|
|
39
|
+
}, ref: ref, value: (_c = props.value) === null || _c === void 0 ? void 0 : _c.toString(), defaultValue: (_d = props.defaultValue) === null || _d === void 0 ? void 0 : _d.toString(), onChangeText: handleChange, validations: mergedValidations })));
|
|
34
40
|
}
|
|
35
41
|
function hasPeriodAtEnd(value) {
|
|
36
42
|
// matches patterns like ".", "0.", "12.", "+1.", and "-0."
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import React, { forwardRef, useEffect } from "react";
|
|
13
13
|
import { View } from "react-native";
|
|
14
|
-
import { useDebounce } from "@jobber/hooks
|
|
14
|
+
import { useDebounce } from "@jobber/hooks";
|
|
15
15
|
import { styles } from "./InputSearch.style";
|
|
16
16
|
import { InputText } from "../InputText";
|
|
17
17
|
export const InputSearch = forwardRef(SearchInputInternal);
|
|
@@ -88,6 +88,7 @@ function InputTextInternal({ invalid, disabled, readonly = false, name, placehol
|
|
|
88
88
|
], readOnly: readonly, editable: !disabled, keyboardType: keyboard, value: inputTransform(internalValue), autoFocus: autoFocus, autoComplete: autoComplete, multiline: multiline, scrollEnabled: false, textContentType: textContentType, onChangeText: handleChangeText, onSubmitEditing: handleOnSubmitEditing, returnKeyType: returnKeyType, blurOnSubmit: shouldBlurOnSubmit, accessibilityLabel: accessibilityLabel || placeholder, accessibilityHint: accessibilityHint, accessibilityState: { busy: loading }, secureTextEntry: secureTextEntry }, androidA11yProps, { onFocus: event => {
|
|
89
89
|
_name && setFocusedInput(_name);
|
|
90
90
|
setFocused(true);
|
|
91
|
+
// @ts-expect-error - TODO: fix this!
|
|
91
92
|
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
92
93
|
}, onBlur: () => {
|
|
93
94
|
_name && setFocusedInput("");
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"goBack": "Go back",
|
|
19
19
|
"InputFieldWrapper.clear": "Clear input",
|
|
20
20
|
"InputPassword.enterPassword": "Enter a password",
|
|
21
|
+
"InputEmail.enterEmail": "Enter a valid email address (email@example.com)",
|
|
21
22
|
"loading": "Loading",
|
|
22
23
|
"menu": "Menu",
|
|
23
24
|
"more": "More",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"goBack": "Volver",
|
|
19
19
|
"InputFieldWrapper.clear": "Borrar",
|
|
20
20
|
"InputPassword.enterPassword": "Escriba una contraseña",
|
|
21
|
+
"InputEmail.enterEmail": "Introduzca una dirección de correo electrónico válida (email@example.com)",
|
|
21
22
|
"loading": "Cargando",
|
|
22
23
|
"menu": "Menú",
|
|
23
24
|
"more": "Más",
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { v1 } from "react-native-uuid";
|
|
2
|
-
import { useController, useForm, useFormContext } from "react-hook-form";
|
|
2
|
+
import { get, useController, useForm, useFormContext } from "react-hook-form";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
export function useFormController({ name, value, validations, }) {
|
|
5
|
-
var _a, _b;
|
|
6
5
|
const fieldName = useControlName(name);
|
|
7
6
|
const form = useForm({
|
|
8
7
|
mode: "onTouched",
|
|
@@ -17,18 +16,10 @@ export function useFormController({ name, value, validations, }) {
|
|
|
17
16
|
defaultValue: value || undefined,
|
|
18
17
|
});
|
|
19
18
|
// The naming convention established by react-hook-form for arrays of fields is, for example, "emails.0.description".
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
let error;
|
|
25
|
-
if (fieldIdentifiers.length === 3) {
|
|
26
|
-
const [section, item, identifier] = fieldIdentifiers;
|
|
27
|
-
error = (_b = (_a = errors[section]) === null || _a === void 0 ? void 0 : _a[item]) === null || _b === void 0 ? void 0 : _b[identifier];
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
error = errors[fieldName];
|
|
31
|
-
}
|
|
19
|
+
// Preserve original behavior: only treat three-part names as nested paths.
|
|
20
|
+
// For anything else, perform a flat lookup to avoid behavioral changes.
|
|
21
|
+
const identifiers = fieldName.split(".");
|
|
22
|
+
const error = identifiers.length === 3 ? get(errors, fieldName) : errors[fieldName];
|
|
32
23
|
return { error, field };
|
|
33
24
|
}
|
|
34
25
|
function useControlName(name) {
|