@jobber/components-native 0.89.5-JOB-139254-4e3c64d.7 → 0.89.5-JOB-140604-c92b387.42
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 +4 -2
- package/dist/src/BottomSheet/BottomSheet.js +55 -35
- package/dist/src/BottomSheet/BottomSheet.style.js +13 -8
- package/dist/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.js +45 -0
- package/dist/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.styles.js +8 -0
- package/dist/src/ButtonGroup/ButtonGroup.js +1 -1
- package/dist/src/Form/Form.js +1 -2
- package/dist/src/Form/hooks/useInternalForm.js +3 -6
- package/dist/src/InputText/InputText.js +2 -2
- package/dist/src/utils/meta/meta.json +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/src/BottomSheet/BottomSheet.d.ts +13 -4
- package/dist/types/src/BottomSheet/BottomSheet.style.d.ts +12 -7
- package/dist/types/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.d.ts +9 -0
- package/dist/types/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.styles.d.ts +5 -0
- package/dist/types/src/Form/hooks/useInternalForm.d.ts +2 -2
- package/dist/types/src/Form/types.d.ts +0 -6
- package/dist/types/src/InputText/InputText.d.ts +1 -1
- package/package.json +4 -2
- package/src/BottomSheet/BottomSheet.stories.tsx +129 -0
- package/src/BottomSheet/BottomSheet.style.ts +13 -11
- package/src/BottomSheet/BottomSheet.test.tsx +19 -24
- package/src/BottomSheet/BottomSheet.tsx +126 -103
- package/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.styles.ts +9 -0
- package/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.tsx +89 -0
- package/src/ButtonGroup/ButtonGroup.tsx +1 -1
- package/src/Form/Form.tsx +0 -2
- package/src/Form/hooks/useInternalForm.ts +2 -9
- package/src/Form/types.ts +0 -7
- package/src/InputText/InputText.tsx +3 -3
- package/src/ThumbnailList/__snapshots__/ThumbnailList.test.tsx.snap +216 -1
- package/src/utils/meta/meta.json +1 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback } from "react";
|
|
2
|
+
import type { FocusEvent } from "react-native";
|
|
3
|
+
import { TextInput, View, findNodeHandle } from "react-native";
|
|
4
|
+
import { useBottomSheetInternal } from "@gorhom/bottom-sheet";
|
|
5
|
+
import { useStyles } from "./BottomSheetInputText.styles";
|
|
6
|
+
import type {
|
|
7
|
+
InputTextProps,
|
|
8
|
+
InputTextRef,
|
|
9
|
+
} from "../../../InputText/InputText";
|
|
10
|
+
import { InputText } from "../../../InputText/InputText";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* BottomSheetInputText is a wrapper around InputText that provides
|
|
14
|
+
* bottom sheet keyboard handling. It implements the handleOnFocus and
|
|
15
|
+
* handleOnBlur logic from BottomSheetTextInput to ensure proper keyboard
|
|
16
|
+
* positioning within bottom sheets.
|
|
17
|
+
*/
|
|
18
|
+
export const BottomSheetInputText = forwardRef<InputTextRef, InputTextProps>(
|
|
19
|
+
function BottomSheetInputText(props, ref) {
|
|
20
|
+
const styles = useStyles();
|
|
21
|
+
const { onFocus, onBlur } = props;
|
|
22
|
+
const { animatedKeyboardState, textInputNodesRef } =
|
|
23
|
+
useBottomSheetInternal();
|
|
24
|
+
|
|
25
|
+
const handleOnFocus = useCallback(
|
|
26
|
+
(event?: FocusEvent) => {
|
|
27
|
+
animatedKeyboardState.set(
|
|
28
|
+
(state: ReturnType<typeof animatedKeyboardState.get>) => ({
|
|
29
|
+
...state,
|
|
30
|
+
target: event?.nativeEvent.target,
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
onFocus?.(event);
|
|
35
|
+
},
|
|
36
|
+
[animatedKeyboardState, onFocus],
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const handleOnBlur = useCallback(
|
|
40
|
+
(event?: FocusEvent) => {
|
|
41
|
+
const keyboardState = animatedKeyboardState.get();
|
|
42
|
+
const currentlyFocusedInput = TextInput.State.currentlyFocusedInput();
|
|
43
|
+
const currentFocusedInput =
|
|
44
|
+
currentlyFocusedInput !== null
|
|
45
|
+
? findNodeHandle(
|
|
46
|
+
// @ts-expect-error - TextInput.State.currentlyFocusedInput() returns NativeMethods
|
|
47
|
+
// which is not directly assignable to findNodeHandle's expected type,
|
|
48
|
+
// but it works at runtime. This is a known type limitation in React Native.
|
|
49
|
+
currentlyFocusedInput,
|
|
50
|
+
)
|
|
51
|
+
: null;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* we need to make sure that we only remove the target
|
|
55
|
+
* if the target belong to the current component and
|
|
56
|
+
* if the currently focused input is not in the targets set.
|
|
57
|
+
*/
|
|
58
|
+
const shouldRemoveCurrentTarget =
|
|
59
|
+
keyboardState.target === event?.nativeEvent.target;
|
|
60
|
+
const shouldIgnoreBlurEvent =
|
|
61
|
+
currentFocusedInput &&
|
|
62
|
+
textInputNodesRef.current.has(currentFocusedInput);
|
|
63
|
+
|
|
64
|
+
if (shouldRemoveCurrentTarget && !shouldIgnoreBlurEvent) {
|
|
65
|
+
animatedKeyboardState.set(
|
|
66
|
+
(state: ReturnType<typeof animatedKeyboardState.get>) => ({
|
|
67
|
+
...state,
|
|
68
|
+
target: undefined,
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
onBlur?.(event);
|
|
74
|
+
},
|
|
75
|
+
[animatedKeyboardState, textInputNodesRef, onBlur],
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<View style={styles.inputText}>
|
|
80
|
+
<InputText
|
|
81
|
+
{...props}
|
|
82
|
+
ref={ref}
|
|
83
|
+
onFocus={handleOnFocus}
|
|
84
|
+
onBlur={handleOnBlur}
|
|
85
|
+
/>
|
|
86
|
+
</View>
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
);
|
|
@@ -48,7 +48,7 @@ export function ButtonGroup({
|
|
|
48
48
|
}: ButtonGroupProps): JSX.Element {
|
|
49
49
|
const { t } = useAtlantisI18n();
|
|
50
50
|
const { handlePress } = usePreventTapWhenOffline();
|
|
51
|
-
const secondaryActionsRef = useRef<BottomSheetRef>();
|
|
51
|
+
const secondaryActionsRef = useRef<BottomSheetRef>(null);
|
|
52
52
|
const { primaryActions, secondaryActions } = getActions(children);
|
|
53
53
|
const styles = useStyles();
|
|
54
54
|
|
package/src/Form/Form.tsx
CHANGED
|
@@ -66,7 +66,6 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
66
66
|
saveButtonOffset,
|
|
67
67
|
showStickySaveButton = false,
|
|
68
68
|
renderFooter,
|
|
69
|
-
removeLocalCacheOnBackOffline,
|
|
70
69
|
}: InternalFormProps<T, S>) {
|
|
71
70
|
const { scrollViewRef, bottomViewRef, scrollToTop } = useFormViewRefs();
|
|
72
71
|
const [saveButtonHeight, setSaveButtonHeight] = useState(0);
|
|
@@ -88,7 +87,6 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
88
87
|
scrollViewRef,
|
|
89
88
|
saveButtonHeight,
|
|
90
89
|
messageBannerHeight,
|
|
91
|
-
removeLocalCacheOnBackOffline,
|
|
92
90
|
});
|
|
93
91
|
const { windowHeight, headerHeight } = useScreenInformation();
|
|
94
92
|
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
@@ -20,7 +20,6 @@ type UseInternalFormProps<T extends FieldValues, SubmitResponseType> = Pick<
|
|
|
20
20
|
| "localCacheKey"
|
|
21
21
|
| "localCacheExclude"
|
|
22
22
|
| "localCacheId"
|
|
23
|
-
| "removeLocalCacheOnBackOffline"
|
|
24
23
|
> & {
|
|
25
24
|
scrollViewRef?: RefObject<KeyboardAwareScrollView>;
|
|
26
25
|
readonly saveButtonHeight: number;
|
|
@@ -46,7 +45,6 @@ export function useInternalForm<T extends FieldValues, SubmitResponseType>({
|
|
|
46
45
|
scrollViewRef,
|
|
47
46
|
saveButtonHeight,
|
|
48
47
|
messageBannerHeight,
|
|
49
|
-
removeLocalCacheOnBackOffline = false,
|
|
50
48
|
}: UseInternalFormProps<T, SubmitResponseType>): UseInternalForm<T> {
|
|
51
49
|
const { useConfirmBeforeBack, useInternalFormLocalCache } =
|
|
52
50
|
useAtlantisFormContext();
|
|
@@ -84,16 +82,11 @@ export function useInternalForm<T extends FieldValues, SubmitResponseType>({
|
|
|
84
82
|
};
|
|
85
83
|
}
|
|
86
84
|
|
|
87
|
-
const shouldRemoveCacheOnBack = removeLocalCacheOnBackOffline
|
|
88
|
-
? true
|
|
89
|
-
: isOnline;
|
|
90
|
-
|
|
91
85
|
const removeListenerRef = useConfirmBeforeBack({
|
|
92
86
|
alwaysPreventBack: isSubmitting,
|
|
93
87
|
shouldShowAlert: isDirty,
|
|
94
|
-
onAcceptEvent:
|
|
95
|
-
showLostProgressMessage:
|
|
96
|
-
shouldRemoveCacheOnBack || !clientSideSaveOn ? true : false,
|
|
88
|
+
onAcceptEvent: isOnline ? removeLocalCache : undefined,
|
|
89
|
+
showLostProgressMessage: isOnline || !clientSideSaveOn ? true : false,
|
|
97
90
|
});
|
|
98
91
|
|
|
99
92
|
return {
|
package/src/Form/types.ts
CHANGED
|
@@ -171,13 +171,6 @@ export interface FormProps<T extends FieldValues, SubmitResponseType> {
|
|
|
171
171
|
*/
|
|
172
172
|
localCacheId?: string | string[];
|
|
173
173
|
|
|
174
|
-
/**
|
|
175
|
-
* If true, the local cache will be removed when the user navigates away from
|
|
176
|
-
* the dirty form even when offline. By default, cache is only removed on back when online.
|
|
177
|
-
* Defaults to false.
|
|
178
|
-
*/
|
|
179
|
-
removeLocalCacheOnBackOffline?: boolean;
|
|
180
|
-
|
|
181
174
|
/**
|
|
182
175
|
* Secondary Action for ButtonGroup
|
|
183
176
|
*/
|
|
@@ -117,7 +117,7 @@ export interface InputTextProps
|
|
|
117
117
|
/**
|
|
118
118
|
* Callback that is called when the text input is blurred
|
|
119
119
|
*/
|
|
120
|
-
readonly onBlur?: () => void;
|
|
120
|
+
readonly onBlur?: (event?: FocusEvent) => void;
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* VoiceOver will read this string when a user selects the associated element
|
|
@@ -422,10 +422,10 @@ function InputTextInternal(
|
|
|
422
422
|
setFocused(true);
|
|
423
423
|
onFocus?.(event);
|
|
424
424
|
}}
|
|
425
|
-
onBlur={
|
|
425
|
+
onBlur={event => {
|
|
426
426
|
_name && setFocusedInput("");
|
|
427
427
|
setFocused(false);
|
|
428
|
-
onBlur?.();
|
|
428
|
+
onBlur?.(event);
|
|
429
429
|
field.onBlur();
|
|
430
430
|
trimWhitespace(inputTransform(field.value), updateFormAndState);
|
|
431
431
|
}}
|
|
@@ -150,6 +150,221 @@ exports[`renders a thumbnail component with attachments 1`] = `
|
|
|
150
150
|
"top": 0,
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
|
|
153
|
+
>
|
|
154
|
+
<View
|
|
155
|
+
backdropComponent={[Function]}
|
|
156
|
+
backgroundStyle={
|
|
157
|
+
{
|
|
158
|
+
"borderTopLeftRadius": 24,
|
|
159
|
+
"borderTopRightRadius": 24,
|
|
160
|
+
"paddingTop": 8,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
enablePanDownToClose={true}
|
|
164
|
+
handleStyle={
|
|
165
|
+
{
|
|
166
|
+
"display": "none",
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
keyboardBlurBehavior="restore"
|
|
170
|
+
style={
|
|
171
|
+
{
|
|
172
|
+
"display": "none",
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
testID="bottom-sheet-mock"
|
|
176
|
+
>
|
|
177
|
+
<View
|
|
178
|
+
enableFooterMarginAdjustment={true}
|
|
179
|
+
style={
|
|
180
|
+
{
|
|
181
|
+
"paddingBottom": 8,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
testID="bottom-sheet-view"
|
|
185
|
+
>
|
|
186
|
+
<View
|
|
187
|
+
accessibilityLabel="Preview "
|
|
188
|
+
accessibilityState={
|
|
189
|
+
{
|
|
190
|
+
"busy": undefined,
|
|
191
|
+
"checked": undefined,
|
|
192
|
+
"disabled": undefined,
|
|
193
|
+
"expanded": undefined,
|
|
194
|
+
"selected": undefined,
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
accessibilityValue={
|
|
198
|
+
{
|
|
199
|
+
"max": undefined,
|
|
200
|
+
"min": undefined,
|
|
201
|
+
"now": undefined,
|
|
202
|
+
"text": undefined,
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
accessible={true}
|
|
206
|
+
collapsable={false}
|
|
207
|
+
focusable={true}
|
|
208
|
+
onClick={[Function]}
|
|
209
|
+
onResponderGrant={[Function]}
|
|
210
|
+
onResponderMove={[Function]}
|
|
211
|
+
onResponderRelease={[Function]}
|
|
212
|
+
onResponderTerminate={[Function]}
|
|
213
|
+
onResponderTerminationRequest={[Function]}
|
|
214
|
+
onStartShouldSetResponder={[Function]}
|
|
215
|
+
style={
|
|
216
|
+
{
|
|
217
|
+
"alignContent": "center",
|
|
218
|
+
"alignItems": "center",
|
|
219
|
+
"display": "flex",
|
|
220
|
+
"flexDirection": "row",
|
|
221
|
+
"opacity": 1,
|
|
222
|
+
"padding": 8,
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
>
|
|
226
|
+
<View
|
|
227
|
+
style={
|
|
228
|
+
{
|
|
229
|
+
"paddingHorizontal": 8,
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
>
|
|
233
|
+
<RNSVGSvgView
|
|
234
|
+
align="xMidYMid"
|
|
235
|
+
bbHeight={24}
|
|
236
|
+
bbWidth={24}
|
|
237
|
+
focusable={false}
|
|
238
|
+
meetOrSlice={0}
|
|
239
|
+
minX={0}
|
|
240
|
+
minY={0}
|
|
241
|
+
style={
|
|
242
|
+
[
|
|
243
|
+
{
|
|
244
|
+
"backgroundColor": "transparent",
|
|
245
|
+
"borderWidth": 0,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"display": "flex",
|
|
249
|
+
"fill": "hsl(198, 35%, 21%)",
|
|
250
|
+
"height": 24,
|
|
251
|
+
"verticalAlign": "middle",
|
|
252
|
+
"width": 24,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"flex": 0,
|
|
256
|
+
"height": 24,
|
|
257
|
+
"width": 24,
|
|
258
|
+
},
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
testID="eye"
|
|
262
|
+
vbHeight={24}
|
|
263
|
+
vbWidth={24}
|
|
264
|
+
>
|
|
265
|
+
<RNSVGGroup
|
|
266
|
+
fill={
|
|
267
|
+
{
|
|
268
|
+
"payload": 4280499528,
|
|
269
|
+
"type": 0,
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
propList={
|
|
273
|
+
[
|
|
274
|
+
"fill",
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
>
|
|
278
|
+
<RNSVGPath
|
|
279
|
+
d="M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Zm-2 0a2 2 0 1 0-4 0 2 2 0 0 0 4 0Z"
|
|
280
|
+
fill={
|
|
281
|
+
{
|
|
282
|
+
"payload": 4280499528,
|
|
283
|
+
"type": 0,
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
propList={
|
|
287
|
+
[
|
|
288
|
+
"fill",
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
/>
|
|
292
|
+
<RNSVGPath
|
|
293
|
+
d="M21.863 12.477C20.794 14.2 16.703 20 12 20c-4.702 0-8.795-5.8-9.863-7.523a.903.903 0 0 1 0-.954C3.205 9.8 7.297 4 12 4c4.703 0 8.794 5.8 9.863 7.523a.903.903 0 0 1 0 .954ZM20 12s-3.582-6-8-6-8 6-8 6 3.582 6 8 6 8-6 8-6Z"
|
|
294
|
+
fill={
|
|
295
|
+
{
|
|
296
|
+
"payload": 4280499528,
|
|
297
|
+
"type": 0,
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
propList={
|
|
301
|
+
[
|
|
302
|
+
"fill",
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
/>
|
|
306
|
+
</RNSVGGroup>
|
|
307
|
+
</RNSVGSvgView>
|
|
308
|
+
</View>
|
|
309
|
+
<View
|
|
310
|
+
style={
|
|
311
|
+
{
|
|
312
|
+
"flexShrink": 1,
|
|
313
|
+
"paddingHorizontal": 8,
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
>
|
|
317
|
+
<Text
|
|
318
|
+
accessibilityRole="text"
|
|
319
|
+
adjustsFontSizeToFit={false}
|
|
320
|
+
allowFontScaling={true}
|
|
321
|
+
collapsable={false}
|
|
322
|
+
maxFontSizeMultiplier={3.125}
|
|
323
|
+
selectable={true}
|
|
324
|
+
selectionColor="hsl(86, 100%, 46%)"
|
|
325
|
+
style={
|
|
326
|
+
[
|
|
327
|
+
{
|
|
328
|
+
"fontFamily": "inter-semibold",
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"color": "hsl(197, 15%, 43%)",
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"textAlign": "left",
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"fontSize": 16,
|
|
338
|
+
"lineHeight": 20,
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"letterSpacing": 0,
|
|
342
|
+
},
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
>
|
|
346
|
+
Preview
|
|
347
|
+
</Text>
|
|
348
|
+
</View>
|
|
349
|
+
</View>
|
|
350
|
+
</View>
|
|
351
|
+
<View
|
|
352
|
+
testID="bottom-sheet-footer"
|
|
353
|
+
>
|
|
354
|
+
<View
|
|
355
|
+
style={
|
|
356
|
+
[
|
|
357
|
+
{
|
|
358
|
+
"backgroundColor": "rgba(255, 255, 255, 1)",
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"paddingBottom": 0,
|
|
362
|
+
},
|
|
363
|
+
]
|
|
364
|
+
}
|
|
365
|
+
/>
|
|
366
|
+
</View>
|
|
367
|
+
</View>
|
|
368
|
+
</View>,
|
|
154
369
|
]
|
|
155
370
|
`;
|