@abihealth/goapp-react-native 1.45.0 → 1.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/CHANGELOG.md +7 -0
- package/dist/common/components/Input.js +11 -2
- package/dist/common/contexts/FormContext.d.ts +7 -4
- package/dist/common/contexts/FormContext.js +10 -2
- package/dist/common/hooks/useForm.d.ts +1 -0
- package/dist/common/hooks/useForm.js +27 -14
- package/dist/video-consultations/screens/DeliveryAddressScreen.js +20 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.45.1](https://github.com/abiglobalhealth/react-native-sdk/compare/goapp-react-native-v1.45.0...goapp-react-native-v1.45.1) (2025-10-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* ABI-10439 sdk accessibility error messages are not announced ([#252](https://github.com/abiglobalhealth/react-native-sdk/issues/252)) ([6b68c48](https://github.com/abiglobalhealth/react-native-sdk/commit/6b68c48f1f2c96a48d005ca481cc859cc10ad36b))
|
|
9
|
+
|
|
3
10
|
## [1.45.0](https://github.com/abiglobalhealth/react-native-sdk/compare/goapp-react-native-v1.44.0...goapp-react-native-v1.45.0) (2025-10-16)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -29,8 +29,17 @@ var Input = function (_a) {
|
|
|
29
29
|
var theme = (0, useTheme_1.useTheme)();
|
|
30
30
|
var Input = (0, useCustomComponents_1.useCustomComponents)().Input;
|
|
31
31
|
var styles = getStyles(theme);
|
|
32
|
-
var _b = (0, useForm_1.useForm)(), errors = _b.errors, data = _b.data, clearError = _b.clearError, updateData = _b.updateData, loading = _b.loading;
|
|
32
|
+
var _b = (0, useForm_1.useForm)(), errors = _b.errors, data = _b.data, clearError = _b.clearError, updateData = _b.updateData, loading = _b.loading, registerInput = _b.registerInput;
|
|
33
33
|
var _c = (0, react_1.useState)(false), focused = _c[0], setFocused = _c[1];
|
|
34
|
+
var inputRef = (0, react_1.useRef)(null);
|
|
35
|
+
(0, react_1.useEffect)(function () {
|
|
36
|
+
if (id && registerInput && inputRef.current)
|
|
37
|
+
registerInput(id, inputRef.current);
|
|
38
|
+
return function () {
|
|
39
|
+
if (id && registerInput)
|
|
40
|
+
registerInput(id, null);
|
|
41
|
+
};
|
|
42
|
+
}, [id, registerInput]);
|
|
34
43
|
var onFocus = function (e) {
|
|
35
44
|
var _a;
|
|
36
45
|
setFocused(true);
|
|
@@ -53,7 +62,7 @@ var Input = function (_a) {
|
|
|
53
62
|
var placeholderColor = (Input === null || Input === void 0 ? void 0 : Input.placeholderTextColor) || theme.palette.grey.base;
|
|
54
63
|
return (<FormControl_1.default label={label} error={err} name={id}>
|
|
55
64
|
<react_native_1.View style={{ position: 'relative' }}>
|
|
56
|
-
<react_native_1.TextInput {...props} id={id} style={[styles.input, focused && styles.focused, err && styles.error, props.style, Input === null || Input === void 0 ? void 0 : Input.containerStyle]} onFocus={onFocus} onBlur={onBlur} placeholderTextColor={placeholderColor} value={formValue || props.value} onChangeText={onChangeText} editable={!loading} accessibilityLabel={label ? "".concat(label, " input text field") : 'Input text field'} accessibilityLabelledBy={id} accessibilityState={{ busy: loading, disabled: loading }}/>
|
|
65
|
+
<react_native_1.TextInput {...props} ref={inputRef} id={id} style={[styles.input, focused && styles.focused, err && styles.error, props.style, Input === null || Input === void 0 ? void 0 : Input.containerStyle]} onFocus={onFocus} onBlur={onBlur} placeholderTextColor={placeholderColor} value={formValue || props.value} onChangeText={onChangeText} editable={!loading} accessibilityLabel={label ? "".concat(label, " input text field") : 'Input text field'} accessibilityLabelledBy={id} accessibilityState={{ busy: loading, disabled: loading }}/>
|
|
57
66
|
|
|
58
67
|
{props.multiline && !!minLength && (!formValue || (formValue === null || formValue === void 0 ? void 0 : formValue.length) < minLength) && (<react_native_1.View style={styles.hintContainer}>
|
|
59
68
|
<Text_1.Text color={placeholderColor}>{t('inputs.textarea.min_length', { minLength: minLength })}</Text_1.Text>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import React, { PropsWithChildren } from 'react';
|
|
1
|
+
import React, { Dispatch, MutableRefObject, PropsWithChildren, SetStateAction } from 'react';
|
|
2
|
+
import { TextInput } from 'react-native';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
export type HandleSubmitProps<T extends z.AnyZodObject> = {
|
|
4
5
|
onSuccess?: (data: z.TypeOf<T>) => Promise<void>;
|
|
@@ -7,14 +8,16 @@ export type HandleSubmitProps<T extends z.AnyZodObject> = {
|
|
|
7
8
|
};
|
|
8
9
|
export type FormContextProps<T extends z.AnyZodObject> = {
|
|
9
10
|
data: z.infer<T> | null;
|
|
10
|
-
setData:
|
|
11
|
+
setData: Dispatch<SetStateAction<z.infer<T> | null>>;
|
|
11
12
|
errors: Record<keyof z.infer<T>, string> | null;
|
|
12
|
-
setErrors:
|
|
13
|
+
setErrors: Dispatch<SetStateAction<Record<keyof z.infer<T>, string> | null>>;
|
|
13
14
|
schema: T;
|
|
14
15
|
onSubmit?: HandleSubmitProps<T>;
|
|
15
16
|
loading: boolean;
|
|
16
|
-
setLoading:
|
|
17
|
+
setLoading: Dispatch<SetStateAction<boolean>>;
|
|
17
18
|
loadingForm?: boolean;
|
|
19
|
+
inputRefs: MutableRefObject<Map<string, TextInput | null>>;
|
|
20
|
+
registerInput: (id: string, ref: TextInput | null) => void;
|
|
18
21
|
};
|
|
19
22
|
export declare const FormContext: React.Context<FormContextProps<any>>;
|
|
20
23
|
type FormProviderProps<T extends z.AnyZodObject> = {
|
|
@@ -44,14 +44,22 @@ exports.FormContext = (0, react_1.createContext)({
|
|
|
44
44
|
schema: zod_1.z.object({}),
|
|
45
45
|
loading: false,
|
|
46
46
|
setLoading: function () { },
|
|
47
|
-
loadingForm: false
|
|
47
|
+
loadingForm: false,
|
|
48
|
+
inputRefs: { current: new Map() },
|
|
49
|
+
registerInput: function () { }
|
|
48
50
|
});
|
|
49
51
|
var FormProvider = function (_a) {
|
|
50
52
|
var children = _a.children, schema = _a.schema, initialValues = _a.initialValues, onSubmit = _a.onSubmit, loadingForm = _a.loadingForm;
|
|
51
53
|
var _b = (0, react_1.useState)(false), loading = _b[0], setLoading = _b[1];
|
|
52
54
|
var _c = (0, react_1.useState)(initialValues || null), data = _c[0], setData = _c[1];
|
|
53
55
|
var _d = (0, react_1.useState)(null), errors = _d[0], setErrors = _d[1];
|
|
54
|
-
|
|
56
|
+
var inputRefs = (0, react_1.useRef)(new Map());
|
|
57
|
+
var registerInput = (0, react_1.useCallback)(function (id, ref) {
|
|
58
|
+
if (ref)
|
|
59
|
+
return inputRefs.current.set(id, ref);
|
|
60
|
+
inputRefs.current.delete(id);
|
|
61
|
+
}, []);
|
|
62
|
+
return (<exports.FormContext.Provider value={{ data: data, setData: setData, errors: errors, setErrors: setErrors, schema: schema, onSubmit: onSubmit, loading: loading, setLoading: setLoading, loadingForm: loadingForm, inputRefs: inputRefs, registerInput: registerInput }}>
|
|
55
63
|
{children}
|
|
56
64
|
</exports.FormContext.Provider>);
|
|
57
65
|
};
|
|
@@ -7,4 +7,5 @@ export declare const useForm: <T extends z.AnyZodObject>() => {
|
|
|
7
7
|
handleSubmit: () => Promise<void>;
|
|
8
8
|
loading: boolean;
|
|
9
9
|
setLoading: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
10
|
+
registerInput: (id: string, ref: import("react-native").TextInput | null) => void;
|
|
10
11
|
};
|
|
@@ -51,6 +51,7 @@ exports.useForm = void 0;
|
|
|
51
51
|
var FormContext_1 = require("../contexts/FormContext");
|
|
52
52
|
var zod_1 = require("../utils/zod");
|
|
53
53
|
var react_1 = require("react");
|
|
54
|
+
var react_native_1 = require("react-native");
|
|
54
55
|
var useForm = function () {
|
|
55
56
|
var context = (0, react_1.useContext)(FormContext_1.FormContext);
|
|
56
57
|
var data = context.data, setData = context.setData, errors = context.errors, setErrors = context.setErrors, schema = context.schema, onSubmit = context.onSubmit, loading = context.loading, setLoading = context.setLoading, loadingForm = context.loadingForm;
|
|
@@ -67,27 +68,38 @@ var useForm = function () {
|
|
|
67
68
|
});
|
|
68
69
|
};
|
|
69
70
|
var handleSubmit = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
70
|
-
var error_1,
|
|
71
|
-
var _a, _b, _c;
|
|
72
|
-
return __generator(this, function (
|
|
73
|
-
switch (
|
|
71
|
+
var error_1, parsedErrors_1, currentRefs, firstErrorField_1, inputRef_1;
|
|
72
|
+
var _a, _b, _c, _d;
|
|
73
|
+
return __generator(this, function (_e) {
|
|
74
|
+
switch (_e.label) {
|
|
74
75
|
case 0:
|
|
75
|
-
|
|
76
|
+
_e.trys.push([0, 2, 4, 6]);
|
|
76
77
|
setLoading(true);
|
|
77
78
|
schema.parse(data || {});
|
|
78
79
|
return [4 /*yield*/, ((_a = onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit.onSuccess) === null || _a === void 0 ? void 0 : _a.call(onSubmit, data))];
|
|
79
80
|
case 1:
|
|
80
|
-
|
|
81
|
+
_e.sent();
|
|
81
82
|
return [3 /*break*/, 6];
|
|
82
83
|
case 2:
|
|
83
|
-
error_1 =
|
|
84
|
-
|
|
85
|
-
setErrors(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
error_1 = _e.sent();
|
|
85
|
+
parsedErrors_1 = (0, zod_1.parseErrors)(error_1);
|
|
86
|
+
setErrors(parsedErrors_1);
|
|
87
|
+
currentRefs = (_b = context.inputRefs) === null || _b === void 0 ? void 0 : _b.current;
|
|
88
|
+
if (currentRefs) {
|
|
89
|
+
firstErrorField_1 = Array.from(currentRefs.keys()).find(function (key) { return parsedErrors_1[key]; });
|
|
90
|
+
if (firstErrorField_1) {
|
|
91
|
+
inputRef_1 = currentRefs.get(firstErrorField_1);
|
|
92
|
+
setTimeout(function () {
|
|
93
|
+
inputRef_1 === null || inputRef_1 === void 0 ? void 0 : inputRef_1.focus();
|
|
94
|
+
react_native_1.AccessibilityInfo.announceForAccessibility(parsedErrors_1[firstErrorField_1]);
|
|
95
|
+
}, 100);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return [4 /*yield*/, ((_c = onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit.onError) === null || _c === void 0 ? void 0 : _c.call(onSubmit, parsedErrors_1))];
|
|
99
|
+
case 3: return [2 /*return*/, _e.sent()];
|
|
100
|
+
case 4: return [4 /*yield*/, ((_d = onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit.onFinally) === null || _d === void 0 ? void 0 : _d.call(onSubmit))];
|
|
89
101
|
case 5:
|
|
90
|
-
|
|
102
|
+
_e.sent();
|
|
91
103
|
setLoading(false);
|
|
92
104
|
return [7 /*endfinally*/];
|
|
93
105
|
case 6: return [2 /*return*/];
|
|
@@ -101,7 +113,8 @@ var useForm = function () {
|
|
|
101
113
|
clearError: clearError,
|
|
102
114
|
handleSubmit: handleSubmit,
|
|
103
115
|
loading: loading || loadingForm,
|
|
104
|
-
setLoading: setLoading
|
|
116
|
+
setLoading: setLoading,
|
|
117
|
+
registerInput: context.registerInput
|
|
105
118
|
};
|
|
106
119
|
};
|
|
107
120
|
exports.useForm = useForm;
|
|
@@ -160,7 +160,7 @@ var CategorySelect = function (_a) {
|
|
|
160
160
|
padding: theme.spacing.md,
|
|
161
161
|
maxHeight: '90%',
|
|
162
162
|
minHeight: 300
|
|
163
|
-
}} onPress={function (e) { return e.stopPropagation
|
|
163
|
+
}} onPress={function (e) { var _a; return (_a = e.stopPropagation) === null || _a === void 0 ? void 0 : _a.call(e); }}>
|
|
164
164
|
<react_native_1.FlatList data={options} keyExtractor={function (item) { return item.key; }} renderItem={function (_a) {
|
|
165
165
|
var group = _a.item;
|
|
166
166
|
return (<react_native_1.View style={{ marginBottom: theme.spacing.xs }}>
|
|
@@ -222,11 +222,12 @@ var DeliveryAddressScreen = function (_a) {
|
|
|
222
222
|
}
|
|
223
223
|
});
|
|
224
224
|
}); };
|
|
225
|
-
return (<ScreenWrapper_1.ScreenWrapper header={<Header_1.Header title={t('general.consultation.videoConsultation.title')} leftIcon={<VideoConsultationIcon_1.VideoConsultationIcon />}/>} containerStyle={styles.container}>
|
|
225
|
+
return (<ScreenWrapper_1.ScreenWrapper header={<Header_1.Header title={t('general.consultation.videoConsultation.title')} leftIcon={<VideoConsultationIcon_1.VideoConsultationIcon />}/>} containerStyle={styles.container} scrollEnabled={false}>
|
|
226
226
|
{error && (<react_native_1.View style={styles.error}>
|
|
227
227
|
<WarningIcon_1.default />
|
|
228
228
|
<Text_1.Text style={styles.warningText}>{t('error.address')}</Text_1.Text>
|
|
229
229
|
</react_native_1.View>)}
|
|
230
|
+
|
|
230
231
|
<react_native_1.View>
|
|
231
232
|
<Text_1.Text variant="h2" center>
|
|
232
233
|
{t('delivery.address.title')}
|
|
@@ -234,16 +235,21 @@ var DeliveryAddressScreen = function (_a) {
|
|
|
234
235
|
<Text_1.Text center>{t('delivery.address.description')}</Text_1.Text>
|
|
235
236
|
</react_native_1.View>
|
|
236
237
|
|
|
237
|
-
<
|
|
238
|
-
|
|
238
|
+
<react_native_1.ScrollView style={styles.formScrollWrapper}>
|
|
239
|
+
<FormWrapper_1.FormWrapper schema={deliveryAddress_1.HKDeliveryAddressSchema} onSubmit={{
|
|
240
|
+
onSuccess: onSubmit,
|
|
241
|
+
onError: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
242
|
+
return [2 /*return*/, setError(true)];
|
|
243
|
+
}); }); }
|
|
239
244
|
}} initialValues={initialDeliveryAddress} submitButton={<Button_1.Button submit loading={loading}>
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
245
|
+
{t('button.confirm')}
|
|
246
|
+
</Button_1.Button>} loadingForm={loading}>
|
|
247
|
+
<Input_1.default id="house" label={t('delivery.address.number_and_floor')} placeholder={t('delivery.address.number_and_floor.placeholder')}/>
|
|
248
|
+
<Input_1.default id="street" label={t('delivery.address.street')} placeholder={t('delivery.address.street.placeholder')}/>
|
|
249
|
+
<Input_1.default id="building" label={t('delivery.address.building_name_number')} placeholder={t('delivery.address.building_name_number.placeholder')}/>
|
|
250
|
+
<CategorySelect id="district" label={t('delivery.address.district')} placeholder={t('delivery.address.district.placeholder')} options={deliveryAddress_1.DISTRICT_AREAS}/>
|
|
251
|
+
</FormWrapper_1.FormWrapper>
|
|
252
|
+
</react_native_1.ScrollView>
|
|
247
253
|
</ScreenWrapper_1.ScreenWrapper>);
|
|
248
254
|
};
|
|
249
255
|
exports.DeliveryAddressScreen = DeliveryAddressScreen;
|
|
@@ -265,6 +271,9 @@ var getStyles = function (_a) {
|
|
|
265
271
|
warningText: {
|
|
266
272
|
color: palette.white,
|
|
267
273
|
marginLeft: spacing.sm
|
|
274
|
+
},
|
|
275
|
+
formScrollWrapper: {
|
|
276
|
+
width: '100%'
|
|
268
277
|
}
|
|
269
278
|
});
|
|
270
279
|
};
|