@jobber/components-native 0.95.2-JOB-141866-990fa70.9 → 0.95.2-JOB-141866-a6ee36d.22
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 +10 -17
- package/dist/src/InputText/InputText.js +3 -45
- package/dist/src/InputText/context/InputAccessoriesContext.js +0 -2
- package/dist/src/InputText/context/InputAccessoriesProvider.js +1 -6
- 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/InputText/InputText.d.ts +0 -5
- package/dist/types/src/InputText/context/types.d.ts +0 -2
- 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 +12 -24
- package/src/Form/types.ts +8 -0
- package/src/InputText/InputText.tsx +2 -37
- package/src/InputText/context/InputAccessoriesContext.ts +0 -2
- package/src/InputText/context/InputAccessoriesProvider.tsx +0 -7
- package/src/InputText/context/types.ts +0 -2
- 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> = {
|
|
@@ -6,11 +6,6 @@ import type { RegisterOptions } from "react-hook-form";
|
|
|
6
6
|
import type { IconNames } from "@jobber/design";
|
|
7
7
|
import type { Clearable } from "@jobber/hooks";
|
|
8
8
|
import type { InputFieldStyleOverride, InputFieldWrapperProps } from "../InputFieldWrapper/InputFieldWrapper";
|
|
9
|
-
/**
|
|
10
|
-
* Buffer zone in pixels for offscreen detection.
|
|
11
|
-
* This makes the detection more sensitive by marking the component as offscreen
|
|
12
|
-
* even if it's technically still visible but within this buffer distance from the edge.
|
|
13
|
-
*/
|
|
14
9
|
export interface InputTextProps extends Pick<InputFieldWrapperProps, "toolbar" | "toolbarVisibility" | "loading" | "loadingType"> {
|
|
15
10
|
/**
|
|
16
11
|
* Highlights the field red and shows message below (if string) to indicate an error
|
|
@@ -19,7 +19,5 @@ export interface InputAccessoriesContextProps {
|
|
|
19
19
|
readonly onFocusNext: () => void;
|
|
20
20
|
readonly onFocusPrevious: () => void;
|
|
21
21
|
readonly setFocusedInput: (name: string) => void;
|
|
22
|
-
readonly isScrolling: boolean;
|
|
23
|
-
readonly setIsScrolling: (isScrolling: boolean) => void;
|
|
24
22
|
}
|
|
25
23
|
export {};
|
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-a6ee36d.22+a6ee36d10",
|
|
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": "a6ee36d10f2c1ba08f20ad6bb9019e274bcee16f"
|
|
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";
|
|
@@ -26,10 +27,7 @@ import { FormSaveButton } from "./components/FormSaveButton";
|
|
|
26
27
|
import { useSaveButtonPosition } from "./hooks/useSaveButtonPosition";
|
|
27
28
|
import { FormCache } from "./components/FormCache/FormCache";
|
|
28
29
|
import { useAtlantisFormContext } from "./context/AtlantisFormContext";
|
|
29
|
-
import {
|
|
30
|
-
InputAccessoriesProvider,
|
|
31
|
-
useInputAccessoriesContext,
|
|
32
|
-
} from "../InputText";
|
|
30
|
+
import { InputAccessoriesProvider } from "../InputText";
|
|
33
31
|
import { tokens } from "../utils/design";
|
|
34
32
|
import { ErrorMessageProvider } from "../ErrorMessageWrapper";
|
|
35
33
|
|
|
@@ -67,13 +65,13 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
67
65
|
secondaryActions,
|
|
68
66
|
saveButtonOffset,
|
|
69
67
|
showStickySaveButton = false,
|
|
68
|
+
disableKeyboardAwareScroll = false,
|
|
70
69
|
renderFooter,
|
|
71
70
|
UNSAFE_allowDiscardLocalCacheWhenOffline,
|
|
72
71
|
}: InternalFormProps<T, S>) {
|
|
73
72
|
const { scrollViewRef, bottomViewRef, scrollToTop } = useFormViewRefs();
|
|
74
73
|
const [saveButtonHeight, setSaveButtonHeight] = useState(0);
|
|
75
74
|
const [messageBannerHeight, setMessageBannerHeight] = useState(0);
|
|
76
|
-
const { setIsScrolling } = useInputAccessoriesContext();
|
|
77
75
|
const {
|
|
78
76
|
formMethods,
|
|
79
77
|
handleSubmit,
|
|
@@ -111,12 +109,8 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
111
109
|
const [isSecondaryActionLoading, setIsSecondaryActionLoading] =
|
|
112
110
|
useState<boolean>(false);
|
|
113
111
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
calculatedKeyboardHeight:
|
|
117
|
-
keyboardHeight - (paddingBottom + KEYBOARD_SAVE_BUTTON_DISTANCE),
|
|
118
|
-
};
|
|
119
|
-
}, [paddingBottom, keyboardHeight]);
|
|
112
|
+
const extraViewHeight = paddingBottom + KEYBOARD_SAVE_BUTTON_DISTANCE;
|
|
113
|
+
const calculatedKeyboardHeight = keyboardHeight - extraViewHeight;
|
|
120
114
|
|
|
121
115
|
useScrollToError({
|
|
122
116
|
formState: formMethods.formState,
|
|
@@ -138,6 +132,10 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
138
132
|
},
|
|
139
133
|
});
|
|
140
134
|
|
|
135
|
+
const onLayout = (event: LayoutChangeEvent) => {
|
|
136
|
+
setMessageBannerHeight(event.nativeEvent.layout.height);
|
|
137
|
+
};
|
|
138
|
+
|
|
141
139
|
const styles = useStyles();
|
|
142
140
|
|
|
143
141
|
const { edgeToEdgeEnabled } = useAtlantisFormContext();
|
|
@@ -168,7 +166,7 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
168
166
|
>
|
|
169
167
|
<KeyboardAwareScrollView
|
|
170
168
|
enableResetScrollToCoords={false}
|
|
171
|
-
enableAutomaticScroll={
|
|
169
|
+
enableAutomaticScroll={!disableKeyboardAwareScroll}
|
|
172
170
|
enableOnAndroid={edgeToEdgeEnabled}
|
|
173
171
|
keyboardOpeningTime={
|
|
174
172
|
Platform.OS === "ios" ? tokens["timing-slowest"] : 0
|
|
@@ -181,23 +179,13 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
181
179
|
contentContainerStyle={
|
|
182
180
|
!keyboardHeight && styles.scrollContentContainer
|
|
183
181
|
}
|
|
184
|
-
onScrollBeginDrag={() => {
|
|
185
|
-
setIsScrolling(true);
|
|
186
|
-
}}
|
|
187
|
-
onScrollEndDrag={() => {
|
|
188
|
-
setIsScrolling(false);
|
|
189
|
-
}}
|
|
190
182
|
>
|
|
191
183
|
<View
|
|
192
184
|
onLayout={({ nativeEvent }) => {
|
|
193
185
|
setFormContentHeight(nativeEvent.layout.height);
|
|
194
186
|
}}
|
|
195
187
|
>
|
|
196
|
-
<View
|
|
197
|
-
onLayout={({ nativeEvent }) => {
|
|
198
|
-
setMessageBannerHeight(nativeEvent.layout.height);
|
|
199
|
-
}}
|
|
200
|
-
>
|
|
188
|
+
<View onLayout={onLayout}>
|
|
201
189
|
<FormMessageBanner bannerMessages={bannerMessages} />
|
|
202
190
|
<FormErrorBanner
|
|
203
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<
|
|
@@ -29,15 +29,6 @@ import type {
|
|
|
29
29
|
} from "../InputFieldWrapper/InputFieldWrapper";
|
|
30
30
|
import { InputFieldWrapper } from "../InputFieldWrapper";
|
|
31
31
|
import { useCommonInputStyles } from "../InputFieldWrapper/CommonInputStyles.style";
|
|
32
|
-
// import { useScreenInformation } from "../Form/hooks/useScreenInformation";
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Buffer zone in pixels for offscreen detection.
|
|
36
|
-
* This makes the detection more sensitive by marking the component as offscreen
|
|
37
|
-
* even if it's technically still visible but within this buffer distance from the edge.
|
|
38
|
-
*/
|
|
39
|
-
// 44 (accessory bar height) + 20 (buffer)
|
|
40
|
-
// const KEYBOARD_AWARE_DETECTION_BUFFER = 64;
|
|
41
32
|
|
|
42
33
|
export interface InputTextProps
|
|
43
34
|
extends Pick<
|
|
@@ -341,7 +332,6 @@ function InputTextInternal(
|
|
|
341
332
|
unregister,
|
|
342
333
|
setFocusedInput,
|
|
343
334
|
canFocusNext,
|
|
344
|
-
isScrolling,
|
|
345
335
|
onFocusNext,
|
|
346
336
|
} = useInputAccessoriesContext();
|
|
347
337
|
useEffect(() => {
|
|
@@ -382,10 +372,6 @@ function InputTextInternal(
|
|
|
382
372
|
|
|
383
373
|
const styles = useStyles();
|
|
384
374
|
const commonInputStyles = useCommonInputStyles();
|
|
385
|
-
// const { headerHeight, windowHeight } = useScreenInformation();
|
|
386
|
-
// State to track if the InputText component can fully fit on screen
|
|
387
|
-
// (i.e., it's completely visible). Use this state to handle visibility issues.
|
|
388
|
-
// const [canFullyFitOnScreen, setCanFullyFitOnScreen] = useState(true);
|
|
389
375
|
|
|
390
376
|
return (
|
|
391
377
|
<InputFieldWrapper
|
|
@@ -408,20 +394,6 @@ function InputTextInternal(
|
|
|
408
394
|
loadingType={loadingType}
|
|
409
395
|
>
|
|
410
396
|
<TextInput
|
|
411
|
-
// onLayout={(event: LayoutChangeEvent) => {
|
|
412
|
-
// event.target?.measureInWindow((_, y, __, height) => {
|
|
413
|
-
// // Check if component can't fully fit on screen (height only)
|
|
414
|
-
// // Account for headerHeight at the top of the screen and buffer zone
|
|
415
|
-
// const visibleTop = headerHeight + KEYBOARD_AWARE_DETECTION_BUFFER; // Top of visible area (below header) with buffer
|
|
416
|
-
// const visibleBottom =
|
|
417
|
-
// windowHeight - KEYBOARD_AWARE_DETECTION_BUFFER; // Bottom of visible area with buffer
|
|
418
|
-
// const isOffScreen =
|
|
419
|
-
// y < visibleTop || // Top edge is behind or above the header (with buffer)
|
|
420
|
-
// y + height > visibleBottom; // Bottom edge is below the window (with buffer)
|
|
421
|
-
|
|
422
|
-
// setCanFullyFitOnScreen(!isOffScreen);
|
|
423
|
-
// });
|
|
424
|
-
// }}
|
|
425
397
|
inputAccessoryViewID={inputAccessoryID || undefined}
|
|
426
398
|
testID={testID}
|
|
427
399
|
autoCapitalize={autoCapitalize}
|
|
@@ -441,21 +413,14 @@ function InputTextInternal(
|
|
|
441
413
|
styleOverride?.inputText,
|
|
442
414
|
loading && loadingType === "glimmer" && { color: "transparent" },
|
|
443
415
|
]}
|
|
444
|
-
|
|
445
|
-
// the input focusing when the user is trying to scroll the form
|
|
446
|
-
readOnly={readonly || (multiline && isScrolling && !focused)}
|
|
447
|
-
// readOnly={readonly}
|
|
416
|
+
readOnly={readonly}
|
|
448
417
|
editable={!disabled}
|
|
449
418
|
keyboardType={keyboard}
|
|
450
419
|
value={inputTransform(internalValue)}
|
|
451
420
|
autoFocus={autoFocus}
|
|
452
421
|
autoComplete={autoComplete}
|
|
453
422
|
multiline={multiline}
|
|
454
|
-
|
|
455
|
-
// State for tracking if the input should be scrollable.
|
|
456
|
-
// This is tech debt related to an issue where keyboard aware scrollview doesn't work if `scrollEnabled` is true. However,
|
|
457
|
-
// 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.
|
|
458
|
-
scrollEnabled={Platform.OS === "ios"}
|
|
423
|
+
scrollEnabled={false}
|
|
459
424
|
textContentType={textContentType}
|
|
460
425
|
onChangeText={handleChangeText}
|
|
461
426
|
onSubmitEditing={handleOnSubmitEditing}
|
|
@@ -12,8 +12,6 @@ const inputAccessoriesContextDefaultValues: InputAccessoriesContextProps = {
|
|
|
12
12
|
onFocusNext: () => undefined,
|
|
13
13
|
onFocusPrevious: () => undefined,
|
|
14
14
|
setFocusedInput: () => undefined,
|
|
15
|
-
isScrolling: false,
|
|
16
|
-
setIsScrolling: () => undefined,
|
|
17
15
|
};
|
|
18
16
|
|
|
19
17
|
export const InputAccessoriesContext = createContext(
|
|
@@ -27,8 +27,6 @@ export function InputAccessoriesProvider({
|
|
|
27
27
|
setElements,
|
|
28
28
|
previousKey,
|
|
29
29
|
nextKey,
|
|
30
|
-
isScrolling,
|
|
31
|
-
setIsScrolling,
|
|
32
30
|
} = useInputAccessoriesProviderState();
|
|
33
31
|
|
|
34
32
|
const colorScheme = useColorScheme();
|
|
@@ -48,8 +46,6 @@ export function InputAccessoriesProvider({
|
|
|
48
46
|
onFocusNext,
|
|
49
47
|
onFocusPrevious,
|
|
50
48
|
setFocusedInput,
|
|
51
|
-
isScrolling,
|
|
52
|
-
setIsScrolling,
|
|
53
49
|
}}
|
|
54
50
|
>
|
|
55
51
|
{children}
|
|
@@ -100,7 +96,6 @@ function useInputAccessoriesProviderState() {
|
|
|
100
96
|
const [canFocusNext, setCanFocusNext] = useState(false);
|
|
101
97
|
const [canFocusPrevious, setCanFocusPrevious] = useState(false);
|
|
102
98
|
const [elements, setElements] = useState<Record<string, () => void>>({});
|
|
103
|
-
const [isScrolling, setIsScrolling] = useState(false);
|
|
104
99
|
|
|
105
100
|
const keys = Object.keys(elements);
|
|
106
101
|
const selectedIndex = keys.findIndex(key => key === focusedInput);
|
|
@@ -124,7 +119,5 @@ function useInputAccessoriesProviderState() {
|
|
|
124
119
|
setCanFocusPrevious,
|
|
125
120
|
elements,
|
|
126
121
|
setElements,
|
|
127
|
-
isScrolling,
|
|
128
|
-
setIsScrolling,
|
|
129
122
|
};
|
|
130
123
|
}
|
|
@@ -25,6 +25,4 @@ export interface InputAccessoriesContextProps {
|
|
|
25
25
|
readonly onFocusNext: () => void;
|
|
26
26
|
readonly onFocusPrevious: () => void;
|
|
27
27
|
readonly setFocusedInput: (name: string) => void;
|
|
28
|
-
readonly isScrolling: boolean;
|
|
29
|
-
readonly setIsScrolling: (isScrolling: boolean) => void;
|
|
30
28
|
}
|
package/src/hooks/index.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|