@jobber/components-native 0.95.2-JOB-141866-ccf6ba8.10 → 0.95.2-JOB-141866-5052098.24
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 +2 -2
- package/dist/src/ContentOverlay/ContentOverlay.js +2 -1
- package/dist/src/Form/Form.js +9 -11
- package/dist/src/InputFieldWrapper/InputFieldWrapper.js +2 -2
- package/dist/src/InputText/InputText.js +7 -27
- package/dist/src/hooks/index.js +0 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/src/Form/types.d.ts +7 -0
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.d.ts +2 -3
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/package.json +2 -2
- package/src/ContentOverlay/ContentOverlay.tsx +2 -1
- package/src/Form/Form.tsx +11 -13
- package/src/Form/types.ts +8 -0
- package/src/InputFieldWrapper/InputFieldWrapper.tsx +1 -10
- package/src/InputText/InputText.tsx +5 -30
- package/src/InputText/context/InputAccessoriesProvider.test.tsx +0 -1
- package/src/hooks/index.ts +0 -1
- /package/dist/src/{hooks → ContentOverlay/hooks}/useKeyboardVisibility.js +0 -0
- /package/dist/types/src/{hooks → ContentOverlay/hooks}/useKeyboardVisibility.d.ts +0 -0
- /package/src/{hooks → ContentOverlay/hooks}/useKeyboardVisibility.test.ts +0 -0
- /package/src/{hooks → ContentOverlay/hooks}/useKeyboardVisibility.ts +0 -0
|
@@ -157,6 +157,13 @@ export interface FormProps<T extends FieldValues, SubmitResponseType> {
|
|
|
157
157
|
* Renders a footer below the save button.
|
|
158
158
|
*/
|
|
159
159
|
renderFooter?: React.ReactNode;
|
|
160
|
+
/**
|
|
161
|
+
* TODO: JOB-147156 This is a HACK for multiline inputs on iOS scrolling issue.
|
|
162
|
+
* Disables the keyboard aware scroll view.
|
|
163
|
+
* This is useful when you want to disable the keyboard aware scroll view for a specific form.
|
|
164
|
+
* For example, when you have a form with a lot of fields and you want to disable the keyboard aware scroll view.
|
|
165
|
+
*/
|
|
166
|
+
disableKeyboardAwareScroll?: boolean;
|
|
160
167
|
}
|
|
161
168
|
export type InternalFormProps<T extends FieldValues, SubmitResponseType> = Omit<FormProps<T, SubmitResponseType>, "initialLoading">;
|
|
162
169
|
export type ValidationRulesByFieldPath<T extends FieldValues> = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
3
3
|
import type { FieldError } from "react-hook-form";
|
|
4
4
|
import type { IconNames } from "@jobber/design";
|
|
5
5
|
export type Clearable = "never" | "while-editing" | "always";
|
|
@@ -82,8 +82,7 @@ export interface InputFieldWrapperProps {
|
|
|
82
82
|
* Change the type of loading indicator to spinner or glimmer.
|
|
83
83
|
*/
|
|
84
84
|
readonly loadingType?: "spinner" | "glimmer";
|
|
85
|
-
readonly scrollViewHackOnLayout?: (event: LayoutChangeEvent) => void;
|
|
86
85
|
}
|
|
87
86
|
export declare const INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID = "ATL-InputFieldWrapper-Glimmers";
|
|
88
87
|
export declare const INPUT_FIELD_WRAPPER_SPINNER_TEST_ID = "ATL-InputFieldWrapper-Spinner";
|
|
89
|
-
export declare function InputFieldWrapper({ invalid, disabled, placeholder, assistiveText, prefix, suffix, placeholderMode, hasValue, error, focused, children, onClear, showClearAction, styleOverride, toolbar, toolbarVisibility, loading, loadingType,
|
|
88
|
+
export declare function InputFieldWrapper({ invalid, disabled, placeholder, assistiveText, prefix, suffix, placeholderMode, hasValue, error, focused, children, onClear, showClearAction, styleOverride, toolbar, toolbarVisibility, loading, loadingType, }: InputFieldWrapperProps): React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.95.2-JOB-141866-
|
|
3
|
+
"version": "0.95.2-JOB-141866-5052098.24+505209802",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -96,5 +96,5 @@
|
|
|
96
96
|
"react-native-safe-area-context": "^5.4.0",
|
|
97
97
|
"react-native-svg": ">=12.0.0"
|
|
98
98
|
},
|
|
99
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "5052098024ddd00b6992954ce35278a551c13ed4"
|
|
100
100
|
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
useWindowDimensions,
|
|
19
19
|
} from "react-native";
|
|
20
20
|
import { Portal } from "react-native-portalize";
|
|
21
|
+
import { useKeyboardVisibility } from "./hooks/useKeyboardVisibility";
|
|
21
22
|
import { useStyles } from "./ContentOverlay.style";
|
|
22
23
|
import { useViewLayoutHeight } from "./hooks/useViewLayoutHeight";
|
|
23
24
|
import type {
|
|
@@ -26,7 +27,7 @@ import type {
|
|
|
26
27
|
ModalBackgroundColor,
|
|
27
28
|
} from "./types";
|
|
28
29
|
import { UNSAFE_WrappedModalize } from "./UNSAFE_WrappedModalize";
|
|
29
|
-
import { useIsScreenReaderEnabled
|
|
30
|
+
import { useIsScreenReaderEnabled } from "../hooks";
|
|
30
31
|
import { IconButton } from "../IconButton";
|
|
31
32
|
import { Heading } from "../Heading";
|
|
32
33
|
import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
|
package/src/Form/Form.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import type { FieldValues } from "react-hook-form";
|
|
3
3
|
import { FormProvider } from "react-hook-form";
|
|
4
4
|
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
|
5
|
+
import type { LayoutChangeEvent } from "react-native";
|
|
5
6
|
import { Keyboard, Platform, View, findNodeHandle } from "react-native";
|
|
6
7
|
import { useStyles } from "./Form.style";
|
|
7
8
|
import { FormErrorBanner } from "./components/FormErrorBanner";
|
|
@@ -64,6 +65,7 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
64
65
|
secondaryActions,
|
|
65
66
|
saveButtonOffset,
|
|
66
67
|
showStickySaveButton = false,
|
|
68
|
+
disableKeyboardAwareScroll = false,
|
|
67
69
|
renderFooter,
|
|
68
70
|
UNSAFE_allowDiscardLocalCacheWhenOffline,
|
|
69
71
|
}: InternalFormProps<T, S>) {
|
|
@@ -107,12 +109,8 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
107
109
|
const [isSecondaryActionLoading, setIsSecondaryActionLoading] =
|
|
108
110
|
useState<boolean>(false);
|
|
109
111
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
calculatedKeyboardHeight:
|
|
113
|
-
keyboardHeight - (paddingBottom + KEYBOARD_SAVE_BUTTON_DISTANCE),
|
|
114
|
-
};
|
|
115
|
-
}, [paddingBottom, keyboardHeight]);
|
|
112
|
+
const extraViewHeight = paddingBottom + KEYBOARD_SAVE_BUTTON_DISTANCE;
|
|
113
|
+
const calculatedKeyboardHeight = keyboardHeight - extraViewHeight;
|
|
116
114
|
|
|
117
115
|
useScrollToError({
|
|
118
116
|
formState: formMethods.formState,
|
|
@@ -134,6 +132,10 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
134
132
|
},
|
|
135
133
|
});
|
|
136
134
|
|
|
135
|
+
const onLayout = (event: LayoutChangeEvent) => {
|
|
136
|
+
setMessageBannerHeight(event.nativeEvent.layout.height);
|
|
137
|
+
};
|
|
138
|
+
|
|
137
139
|
const styles = useStyles();
|
|
138
140
|
|
|
139
141
|
const { edgeToEdgeEnabled } = useAtlantisFormContext();
|
|
@@ -164,7 +166,7 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
164
166
|
>
|
|
165
167
|
<KeyboardAwareScrollView
|
|
166
168
|
enableResetScrollToCoords={false}
|
|
167
|
-
enableAutomaticScroll={
|
|
169
|
+
enableAutomaticScroll={!disableKeyboardAwareScroll}
|
|
168
170
|
enableOnAndroid={edgeToEdgeEnabled}
|
|
169
171
|
keyboardOpeningTime={
|
|
170
172
|
Platform.OS === "ios" ? tokens["timing-slowest"] : 0
|
|
@@ -183,11 +185,7 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
183
185
|
setFormContentHeight(nativeEvent.layout.height);
|
|
184
186
|
}}
|
|
185
187
|
>
|
|
186
|
-
<View
|
|
187
|
-
onLayout={({ nativeEvent }) => {
|
|
188
|
-
setMessageBannerHeight(nativeEvent.layout.height);
|
|
189
|
-
}}
|
|
190
|
-
>
|
|
188
|
+
<View onLayout={onLayout}>
|
|
191
189
|
<FormMessageBanner bannerMessages={bannerMessages} />
|
|
192
190
|
<FormErrorBanner
|
|
193
191
|
networkError={bannerErrors?.networkError}
|
package/src/Form/types.ts
CHANGED
|
@@ -201,6 +201,14 @@ export interface FormProps<T extends FieldValues, SubmitResponseType> {
|
|
|
201
201
|
* Renders a footer below the save button.
|
|
202
202
|
*/
|
|
203
203
|
renderFooter?: React.ReactNode;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* TODO: JOB-147156 This is a HACK for multiline inputs on iOS scrolling issue.
|
|
207
|
+
* Disables the keyboard aware scroll view.
|
|
208
|
+
* This is useful when you want to disable the keyboard aware scroll view for a specific form.
|
|
209
|
+
* For example, when you have a form with a lot of fields and you want to disable the keyboard aware scroll view.
|
|
210
|
+
*/
|
|
211
|
+
disableKeyboardAwareScroll?: boolean;
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
export type InternalFormProps<T extends FieldValues, SubmitResponseType> = Omit<
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
3
|
-
LayoutChangeEvent,
|
|
4
|
-
StyleProp,
|
|
5
|
-
TextStyle,
|
|
6
|
-
ViewStyle,
|
|
7
|
-
} from "react-native";
|
|
2
|
+
import type { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
8
3
|
import { Text as RNText, View } from "react-native";
|
|
9
4
|
import type { FieldError } from "react-hook-form";
|
|
10
5
|
import type { IconNames } from "@jobber/design";
|
|
@@ -117,8 +112,6 @@ export interface InputFieldWrapperProps {
|
|
|
117
112
|
* Change the type of loading indicator to spinner or glimmer.
|
|
118
113
|
*/
|
|
119
114
|
readonly loadingType?: "spinner" | "glimmer";
|
|
120
|
-
|
|
121
|
-
readonly scrollViewHackOnLayout?: (event: LayoutChangeEvent) => void;
|
|
122
115
|
}
|
|
123
116
|
|
|
124
117
|
export const INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID =
|
|
@@ -145,7 +138,6 @@ export function InputFieldWrapper({
|
|
|
145
138
|
toolbarVisibility = "while-editing",
|
|
146
139
|
loading = false,
|
|
147
140
|
loadingType = "spinner",
|
|
148
|
-
scrollViewHackOnLayout,
|
|
149
141
|
}: InputFieldWrapperProps) {
|
|
150
142
|
fieldAffixRequiredPropsCheck([prefix, suffix]);
|
|
151
143
|
const handleClear = onClear ?? noopClear;
|
|
@@ -172,7 +164,6 @@ export function InputFieldWrapper({
|
|
|
172
164
|
disabled && styles.disabled,
|
|
173
165
|
styleOverride?.container,
|
|
174
166
|
]}
|
|
175
|
-
onLayout={scrollViewHackOnLayout}
|
|
176
167
|
>
|
|
177
168
|
<View style={styles.field}>
|
|
178
169
|
{prefix?.icon && (
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Ref, SyntheticEvent } from "react";
|
|
2
2
|
import React, {
|
|
3
3
|
forwardRef,
|
|
4
|
-
useDeferredValue,
|
|
5
4
|
useEffect,
|
|
6
5
|
useImperativeHandle,
|
|
7
6
|
useMemo,
|
|
@@ -23,23 +22,13 @@ import type { Clearable } from "@jobber/hooks";
|
|
|
23
22
|
import { useShowClear } from "@jobber/hooks";
|
|
24
23
|
import { useStyles } from "./InputText.style";
|
|
25
24
|
import { useInputAccessoriesContext } from "./context";
|
|
26
|
-
import { useFormController
|
|
25
|
+
import { useFormController } from "../hooks";
|
|
27
26
|
import type {
|
|
28
27
|
InputFieldStyleOverride,
|
|
29
28
|
InputFieldWrapperProps,
|
|
30
29
|
} from "../InputFieldWrapper/InputFieldWrapper";
|
|
31
30
|
import { InputFieldWrapper } from "../InputFieldWrapper";
|
|
32
31
|
import { useCommonInputStyles } from "../InputFieldWrapper/CommonInputStyles.style";
|
|
33
|
-
import { useScreenInformation } from "../Form/hooks/useScreenInformation";
|
|
34
|
-
// import { useScreenInformation } from "../Form/hooks/useScreenInformation";
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Buffer zone in pixels for offscreen detection.
|
|
38
|
-
* This makes the detection more sensitive by marking the component as offscreen
|
|
39
|
-
* even if it's technically still visible but within this buffer distance from the edge.
|
|
40
|
-
*/
|
|
41
|
-
// 44 (accessory bar height) + 20 (buffer)
|
|
42
|
-
const KEYBOARD_AWARE_DETECTION_BUFFER = 40;
|
|
43
32
|
|
|
44
33
|
export interface InputTextProps
|
|
45
34
|
extends Pick<
|
|
@@ -383,25 +372,9 @@ function InputTextInternal(
|
|
|
383
372
|
|
|
384
373
|
const styles = useStyles();
|
|
385
374
|
const commonInputStyles = useCommonInputStyles();
|
|
386
|
-
const { headerHeight, windowHeight } = useScreenInformation();
|
|
387
|
-
const { keyboardHeight } = useKeyboardVisibility();
|
|
388
|
-
const maxHeight = useDeferredValue(
|
|
389
|
-
windowHeight -
|
|
390
|
-
headerHeight -
|
|
391
|
-
keyboardHeight -
|
|
392
|
-
KEYBOARD_AWARE_DETECTION_BUFFER,
|
|
393
|
-
);
|
|
394
|
-
const [inputHeight, setInputHeight] = useState(0);
|
|
395
|
-
|
|
396
|
-
const enableScroll = useDeferredValue(inputHeight > maxHeight);
|
|
397
375
|
|
|
398
376
|
return (
|
|
399
377
|
<InputFieldWrapper
|
|
400
|
-
scrollViewHackOnLayout={event => {
|
|
401
|
-
event.target?.measureInWindow((_, y, __, height) => {
|
|
402
|
-
setInputHeight(height);
|
|
403
|
-
});
|
|
404
|
-
}}
|
|
405
378
|
prefix={prefix}
|
|
406
379
|
suffix={suffix}
|
|
407
380
|
hasValue={hasValue}
|
|
@@ -447,11 +420,13 @@ function InputTextInternal(
|
|
|
447
420
|
autoFocus={autoFocus}
|
|
448
421
|
autoComplete={autoComplete}
|
|
449
422
|
multiline={multiline}
|
|
423
|
+
// TODO: JOB-147156 This is a HACK for multiline inputs on iOS scrolling issue.
|
|
424
|
+
// This hack should be removed once we swap keyboard aware libraries in JOB-147156
|
|
425
|
+
// If this is needed then we need to figure out a better solution.
|
|
450
426
|
// Makes sure it doesn't jump to the top of the screen when the keyboard is shown and a new line is added.
|
|
451
|
-
// State for tracking if the input should be scrollable.
|
|
452
427
|
// This is tech debt related to an issue where keyboard aware scrollview doesn't work if `scrollEnabled` is true. However,
|
|
453
428
|
// when `scrollEnabled` is false it causes an issue where super long text inputs will jump to the top when a new line is added to the bottom of the input.
|
|
454
|
-
scrollEnabled={Platform.OS === "ios" &&
|
|
429
|
+
scrollEnabled={Platform.OS === "ios" && multiline}
|
|
455
430
|
textContentType={textContentType}
|
|
456
431
|
onChangeText={handleChangeText}
|
|
457
432
|
onSubmitEditing={handleOnSubmitEditing}
|
|
@@ -8,7 +8,6 @@ import { InputText } from "../InputText";
|
|
|
8
8
|
const mockUseFormController = jest.fn();
|
|
9
9
|
jest.mock("../../hooks", () => {
|
|
10
10
|
return {
|
|
11
|
-
...jest.requireActual("../../hooks"),
|
|
12
11
|
useFormController: (
|
|
13
12
|
...args: [{ name: string; value: string; validations: unknown }]
|
|
14
13
|
) => mockUseFormController(...args),
|
package/src/hooks/index.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|