@jobber/components-native 0.89.5-JOB-140604-2d32fc8.44 → 0.89.5-JOB-140604-8777ec5.52
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 +7 -7
- package/dist/src/ActionItem/ActionItemGroup.js +1 -1
- package/dist/src/AutoLink/components/Link/Link.js +1 -1
- package/dist/src/BottomSheet/BottomSheet.js +4 -2
- package/dist/src/BottomSheet/hooks/useBottomSheetBackHandler.js +26 -0
- package/dist/src/Chip/Chip.js +12 -1
- package/dist/src/Chip/Chip.style.js +1 -1
- package/dist/src/ContentOverlay/ContentOverlay.js +3 -5
- package/dist/src/ErrorMessageWrapper/context/ErrorMessageProvider.js +1 -1
- package/dist/src/Form/Form.js +2 -1
- package/dist/src/Form/components/FormMessageBanner/FormMessageBanner.js +1 -1
- package/dist/src/Form/hooks/useInternalForm.js +6 -3
- package/dist/src/FormatFile/components/MediaView/MediaView.js +22 -5
- package/dist/src/InputDate/InputDate.js +2 -2
- package/dist/src/InputFieldWrapper/InputFieldWrapper.js +14 -12
- package/dist/src/InputFieldWrapper/components/Prefix/Prefix.js +5 -2
- package/dist/src/InputFieldWrapper/components/Suffix/Suffix.js +5 -2
- package/dist/src/InputPressable/InputPressable.js +20 -8
- package/dist/src/InputPressable/InputPressable.style.js +3 -0
- package/dist/src/InputText/InputText.js +22 -11
- package/dist/src/InputText/InputText.style.js +4 -0
- package/dist/src/InputTime/InputTime.js +2 -2
- package/dist/src/Menu/Menu.js +2 -2
- package/dist/src/Select/components/SelectPressable/SelectPressable.js +1 -1
- package/dist/src/utils/meta/meta.json +0 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/src/ActionItem/ActionItem.d.ts +2 -1
- package/dist/types/src/ActionItem/ActionItemGroup.d.ts +2 -1
- package/dist/types/src/ActionItem/components/ActionItemContainer.d.ts +2 -1
- package/dist/types/src/ActionLabel/ActionLabel.d.ts +1 -1
- package/dist/types/src/ActivityIndicator/ActivityIndicator.d.ts +2 -1
- package/dist/types/src/AutoLink/AutoLink.d.ts +2 -1
- package/dist/types/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.d.ts +2 -1
- package/dist/types/src/AutoLink/components/Link/Link.d.ts +2 -1
- package/dist/types/src/Banner/Banner.d.ts +2 -1
- package/dist/types/src/Banner/components/BannerIcon/BannerIcon.d.ts +2 -1
- package/dist/types/src/BottomSheet/BottomSheet.d.ts +4 -9
- package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.d.ts +2 -1
- package/dist/types/src/BottomSheet/hooks/useBottomSheetBackHandler.d.ts +8 -0
- package/dist/types/src/Button/Button.d.ts +2 -1
- package/dist/types/src/Button/components/InternalButtonLoading/InternalButtonLoading.d.ts +1 -1
- package/dist/types/src/ButtonGroup/ButtonGroup.d.ts +2 -1
- package/dist/types/src/ButtonGroup/ButtonGroupAction.d.ts +4 -3
- package/dist/types/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.d.ts +3 -2
- package/dist/types/src/Card/Card.d.ts +2 -1
- package/dist/types/src/Card/components/InternalCardHeader.d.ts +2 -1
- package/dist/types/src/Checkbox/Checkbox.d.ts +2 -1
- package/dist/types/src/Checkbox/CheckboxGroup.d.ts +2 -1
- package/dist/types/src/Chip/Chip.d.ts +2 -1
- package/dist/types/src/Content/Content.d.ts +2 -1
- package/dist/types/src/ContentOverlay/UNSAFE_WrappedModalize.d.ts +1 -1
- package/dist/types/src/Disclosure/Disclosure.d.ts +1 -1
- package/dist/types/src/Divider/Divider.d.ts +2 -1
- package/dist/types/src/EmptyState/EmptyState.d.ts +2 -1
- package/dist/types/src/ErrorMessageWrapper/ErrorMessageWrapper.d.ts +2 -1
- package/dist/types/src/ErrorMessageWrapper/context/ErrorMessageProvider.d.ts +2 -1
- package/dist/types/src/ErrorMessageWrapper/context/types.d.ts +1 -1
- package/dist/types/src/Flex/Flex.d.ts +2 -1
- package/dist/types/src/Form/Form.d.ts +2 -1
- package/dist/types/src/Form/components/FormActionBar/FormActionBar.d.ts +3 -2
- package/dist/types/src/Form/components/FormBody/FormBody.d.ts +3 -2
- package/dist/types/src/Form/components/FormCache/FormCache.d.ts +2 -1
- package/dist/types/src/Form/components/FormErrorBanner/FormErrorBanner.d.ts +2 -1
- package/dist/types/src/Form/components/FormMask/FormMask.d.ts +2 -1
- package/dist/types/src/Form/components/FormMessage/FormMessage.d.ts +2 -1
- package/dist/types/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.d.ts +2 -1
- package/dist/types/src/Form/components/FormMessageBanner/FormMessageBanner.d.ts +2 -1
- package/dist/types/src/Form/components/FormSaveButton/FormSaveButton.d.ts +2 -1
- package/dist/types/src/Form/context/AtlantisFormContext.d.ts +1 -1
- package/dist/types/src/Form/context/types.d.ts +2 -2
- package/dist/types/src/Form/hooks/useFormViewRefs.d.ts +2 -2
- package/dist/types/src/Form/hooks/useInternalForm.d.ts +5 -5
- package/dist/types/src/Form/types.d.ts +10 -4
- package/dist/types/src/FormField/FormField.d.ts +1 -1
- package/dist/types/src/FormatFile/FormatFile.d.ts +2 -1
- package/dist/types/src/FormatFile/components/ErrorIcon/ErrorIcon.d.ts +2 -1
- package/dist/types/src/FormatFile/components/FileView/FileView.d.ts +2 -1
- package/dist/types/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.d.ts +3 -2
- package/dist/types/src/FormatFile/components/MediaView/MediaView.d.ts +2 -1
- package/dist/types/src/FormatFile/components/ProgressBar/ProgressBar.d.ts +2 -1
- package/dist/types/src/Heading/Heading.d.ts +1 -1
- package/dist/types/src/Icon/Icon.d.ts +2 -1
- package/dist/types/src/IconButton/IconButton.d.ts +1 -1
- package/dist/types/src/InputCurrency/InputCurrency.d.ts +2 -1
- package/dist/types/src/InputDate/InputDate.d.ts +4 -2
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.d.ts +9 -2
- package/dist/types/src/InputFieldWrapper/components/ClearAction/ClearAction.d.ts +2 -1
- package/dist/types/src/InputFieldWrapper/components/Prefix/Prefix.d.ts +4 -4
- package/dist/types/src/InputFieldWrapper/components/Suffix/Suffix.d.ts +4 -4
- package/dist/types/src/InputPressable/InputPressable.d.ts +9 -1
- package/dist/types/src/InputPressable/InputPressable.style.d.ts +3 -0
- package/dist/types/src/InputSearch/InputSearch.d.ts +1 -1
- package/dist/types/src/InputSearch/components/FilterButton.d.ts +2 -1
- package/dist/types/src/InputText/InputText.d.ts +8 -0
- package/dist/types/src/InputText/InputText.style.d.ts +4 -0
- package/dist/types/src/InputText/context/InputAccessoriesProvider.d.ts +2 -1
- package/dist/types/src/InputTime/InputTime.d.ts +4 -2
- package/dist/types/src/Menu/Menu.d.ts +2 -1
- package/dist/types/src/Menu/components/MenuOption/MenuOption.d.ts +2 -1
- package/dist/types/src/Menu/components/Overlay/Overlay.d.ts +2 -1
- package/dist/types/src/Menu/types.d.ts +6 -1
- package/dist/types/src/ProgressBar/ProgressBar.d.ts +2 -1
- package/dist/types/src/ProgressBar/ProgressBarInner.d.ts +2 -1
- package/dist/types/src/Select/Select.d.ts +3 -2
- package/dist/types/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.d.ts +2 -1
- package/dist/types/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.ios.d.ts +2 -1
- package/dist/types/src/Select/components/SelectInternalPicker/SelectInternalPicker.d.ts +2 -1
- package/dist/types/src/Select/components/SelectPressable/SelectPressable.d.ts +2 -1
- package/dist/types/src/StatusLabel/StatusLabel.d.ts +2 -1
- package/dist/types/src/Switch/Switch.d.ts +2 -1
- package/dist/types/src/Switch/components/BaseSwitch/BaseSwitch.d.ts +2 -1
- package/dist/types/src/Text/Text.d.ts +1 -1
- package/dist/types/src/TextList/TextList.d.ts +2 -1
- package/dist/types/src/ThumbnailList/ThumbnailList.d.ts +2 -1
- package/dist/types/src/Toast/Toast.d.ts +2 -1
- package/dist/types/src/Typography/Typography.d.ts +1 -1
- package/dist/types/src/Typography/TypographyGestureDetector.d.ts +2 -1
- package/dist/types/src/utils/test/MockSafeAreaProvider.d.ts +1 -1
- package/package.json +7 -7
- package/src/ActionItem/ActionItem.tsx +1 -1
- package/src/ActionItem/ActionItemGroup.tsx +1 -3
- package/src/ActionItem/components/ActionItemContainer.tsx +1 -1
- package/src/ActionLabel/ActionLabel.tsx +1 -1
- package/src/ActivityIndicator/ActivityIndicator.tsx +1 -3
- package/src/AutoLink/AutoLink.tsx +1 -1
- package/src/AutoLink/components/ComposeTextWithLinks/ComposeTextWithLinks.tsx +1 -1
- package/src/AutoLink/components/Link/Link.tsx +1 -5
- package/src/Banner/Banner.tsx +2 -2
- package/src/Banner/components/BannerIcon/BannerIcon.tsx +1 -1
- package/src/BottomSheet/BottomSheet.stories.tsx +0 -1
- package/src/BottomSheet/BottomSheet.tsx +9 -10
- package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.tsx +1 -1
- package/src/BottomSheet/hooks/useBottomSheetBackHandler.test.ts +90 -0
- package/src/BottomSheet/hooks/useBottomSheetBackHandler.ts +41 -0
- package/src/Button/Button.tsx +1 -1
- package/src/Button/components/InternalButtonLoading/InternalButtonLoading.tsx +1 -1
- package/src/ButtonGroup/ButtonGroup.tsx +1 -1
- package/src/ButtonGroup/ButtonGroupAction.tsx +4 -4
- package/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.tsx +2 -2
- package/src/Card/Card.tsx +1 -1
- package/src/Card/components/InternalCardHeader.tsx +1 -1
- package/src/Checkbox/Checkbox.tsx +2 -2
- package/src/Checkbox/CheckboxGroup.test.tsx +1 -1
- package/src/Checkbox/CheckboxGroup.tsx +2 -2
- package/src/Chip/Chip.style.ts +1 -1
- package/src/Chip/Chip.tsx +20 -2
- package/src/Content/Content.tsx +1 -1
- package/src/ContentOverlay/ContentOverlay.tsx +3 -4
- package/src/Disclosure/Disclosure.tsx +1 -1
- package/src/Divider/Divider.tsx +1 -1
- package/src/EmptyState/EmptyState.tsx +1 -1
- package/src/ErrorMessageWrapper/ErrorMessageWrapper.tsx +1 -1
- package/src/ErrorMessageWrapper/context/ErrorMessageProvider.tsx +3 -5
- package/src/ErrorMessageWrapper/context/types.ts +1 -1
- package/src/Flex/Flex.tsx +2 -2
- package/src/Form/Form.test.tsx +145 -2
- package/src/Form/Form.tsx +3 -1
- package/src/Form/components/FormActionBar/FormActionBar.tsx +3 -3
- package/src/Form/components/FormBody/FormBody.tsx +3 -3
- package/src/Form/components/FormCache/FormCache.tsx +1 -1
- package/src/Form/components/FormErrorBanner/FormErrorBanner.tsx +1 -1
- package/src/Form/components/FormMask/FormMask.tsx +1 -1
- package/src/Form/components/FormMessage/FormMessage.tsx +1 -1
- package/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.tsx +1 -1
- package/src/Form/components/FormMessageBanner/FormMessageBanner.tsx +1 -3
- package/src/Form/components/FormSaveButton/FormSaveButton.tsx +1 -1
- package/src/Form/context/types.ts +2 -2
- package/src/Form/hooks/useFormViewRefs.ts +4 -5
- package/src/Form/hooks/useInternalForm.ts +12 -5
- package/src/Form/types.ts +11 -4
- package/src/FormField/FormField.tsx +1 -1
- package/src/FormatFile/FormatFile.tsx +3 -3
- package/src/FormatFile/components/ErrorIcon/ErrorIcon.tsx +1 -1
- package/src/FormatFile/components/FileView/FileView.tsx +1 -1
- package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.tsx +2 -2
- package/src/FormatFile/components/MediaView/MediaView.test.tsx +283 -0
- package/src/FormatFile/components/MediaView/MediaView.tsx +28 -7
- package/src/FormatFile/components/ProgressBar/ProgressBar.tsx +1 -1
- package/src/Heading/Heading.tsx +1 -1
- package/src/Icon/Icon.tsx +1 -1
- package/src/IconButton/IconButton.tsx +1 -1
- package/src/InputCurrency/InputCurrency.tsx +1 -1
- package/src/InputDate/InputDate.tsx +7 -3
- package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +48 -1
- package/src/InputFieldWrapper/InputFieldWrapper.tsx +39 -29
- package/src/InputFieldWrapper/components/ClearAction/ClearAction.tsx +1 -1
- package/src/InputFieldWrapper/components/Prefix/Prefix.test.tsx +3 -5
- package/src/InputFieldWrapper/components/Prefix/Prefix.tsx +8 -6
- package/src/InputFieldWrapper/components/Suffix/Suffix.test.tsx +2 -4
- package/src/InputFieldWrapper/components/Suffix/Suffix.tsx +8 -6
- package/src/InputPassword/InputPassword.tsx +1 -1
- package/src/InputPressable/InputPressable.style.ts +4 -0
- package/src/InputPressable/InputPressable.test.tsx +75 -1
- package/src/InputPressable/InputPressable.tsx +34 -8
- package/src/InputSearch/InputSearch.tsx +1 -0
- package/src/InputSearch/components/FilterButton.tsx +1 -1
- package/src/InputText/InputText.style.ts +5 -0
- package/src/InputText/InputText.test.tsx +75 -0
- package/src/InputText/InputText.tsx +32 -12
- package/src/InputText/context/InputAccessoriesProvider.tsx +1 -1
- package/src/InputTime/InputTime.tsx +7 -3
- package/src/Menu/Menu.tsx +3 -3
- package/src/Menu/components/MenuOption/MenuOption.tsx +1 -1
- package/src/Menu/components/Overlay/Overlay.tsx +1 -1
- package/src/Menu/types.ts +7 -1
- package/src/ProgressBar/ProgressBar.tsx +1 -1
- package/src/ProgressBar/ProgressBarInner.tsx +1 -1
- package/src/Select/Select.tsx +2 -2
- package/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.ios.tsx +1 -1
- package/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.tsx +1 -1
- package/src/Select/components/SelectInternalPicker/SelectInternalPicker.tsx +1 -1
- package/src/Select/components/SelectPressable/SelectPressable.tsx +1 -4
- package/src/StatusLabel/StatusLabel.tsx +1 -1
- package/src/Switch/Switch.tsx +1 -1
- package/src/Switch/components/BaseSwitch/BaseSwitch.tsx +1 -1
- package/src/Text/Text.tsx +1 -1
- package/src/TextList/TextList.tsx +1 -1
- package/src/ThumbnailList/ThumbnailList.tsx +1 -1
- package/src/Toast/Toast.tsx +2 -2
- package/src/Typography/Typography.tsx +1 -1
- package/src/Typography/TypographyGestureDetector.tsx +1 -3
- package/src/utils/meta/meta.json +0 -1
- package/src/utils/test/MockSafeAreaProvider.tsx +1 -1
- package/dist/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.js +0 -45
- package/dist/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.styles.js +0 -8
- package/dist/types/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.d.ts +0 -9
- package/dist/types/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.styles.d.ts +0 -5
- package/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.styles.ts +0 -9
- package/src/BottomSheet/components/BottomSheetInputText/BottomSheetInputText.tsx +0 -89
package/src/Form/Form.test.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { type ReactElement } from "react";
|
|
2
2
|
import { act, fireEvent, render, waitFor } from "@testing-library/react-native";
|
|
3
3
|
import { Alert, Keyboard } from "react-native";
|
|
4
4
|
import { Host } from "react-native-portalize";
|
|
@@ -94,7 +94,7 @@ interface FormTestProps {
|
|
|
94
94
|
onSubmit: () => void,
|
|
95
95
|
label: string | undefined,
|
|
96
96
|
isSubmitting: boolean,
|
|
97
|
-
) =>
|
|
97
|
+
) => ReactElement;
|
|
98
98
|
readonly initialLoading?: boolean;
|
|
99
99
|
readonly initialValues?: FormFields;
|
|
100
100
|
readonly bannerMessages?: FormBannerMessage[];
|
|
@@ -104,6 +104,7 @@ interface FormTestProps {
|
|
|
104
104
|
readonly onBeforeSubmit?: jest.Mock;
|
|
105
105
|
readonly renderFooter?: React.ReactNode;
|
|
106
106
|
readonly saveButtonOffset?: number;
|
|
107
|
+
readonly UNSAFE_allowDiscardLocalCacheWhenOffline?: boolean;
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
function FormTest(props: FormTestProps) {
|
|
@@ -125,6 +126,7 @@ function MockForm({
|
|
|
125
126
|
localCacheId,
|
|
126
127
|
renderFooter,
|
|
127
128
|
saveButtonOffset,
|
|
129
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline = false,
|
|
128
130
|
}: FormTestProps) {
|
|
129
131
|
const formErrors: FormBannerErrors = {};
|
|
130
132
|
|
|
@@ -154,6 +156,9 @@ function MockForm({
|
|
|
154
156
|
onBeforeSubmit={onBeforeSubmit}
|
|
155
157
|
renderFooter={renderFooter}
|
|
156
158
|
saveButtonOffset={saveButtonOffset}
|
|
159
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline={
|
|
160
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline
|
|
161
|
+
}
|
|
157
162
|
>
|
|
158
163
|
<InputText
|
|
159
164
|
name={testInputTextName}
|
|
@@ -561,4 +566,142 @@ describe("Form", () => {
|
|
|
561
566
|
expect(queryByTestId("ATL-FormSafeArea")).toBeNull();
|
|
562
567
|
});
|
|
563
568
|
});
|
|
569
|
+
|
|
570
|
+
describe("Leaving the form", () => {
|
|
571
|
+
let mockUseConfirmBeforeBack: jest.Mock;
|
|
572
|
+
let mockRemoveLocalCache: jest.Mock;
|
|
573
|
+
const atlantisContextSpy = jest.spyOn(
|
|
574
|
+
atlantisContext,
|
|
575
|
+
"useAtlantisContext",
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
beforeEach(() => {
|
|
579
|
+
mockUseConfirmBeforeBack = jest
|
|
580
|
+
.fn()
|
|
581
|
+
.mockReturnValue({ current: jest.fn() });
|
|
582
|
+
mockRemoveLocalCache = jest.fn();
|
|
583
|
+
|
|
584
|
+
jest
|
|
585
|
+
.spyOn(
|
|
586
|
+
require("../Form/context/AtlantisFormContext"),
|
|
587
|
+
"useAtlantisFormContext",
|
|
588
|
+
)
|
|
589
|
+
.mockReturnValue({
|
|
590
|
+
useConfirmBeforeBack: mockUseConfirmBeforeBack,
|
|
591
|
+
useInternalFormLocalCache: () => ({
|
|
592
|
+
setLocalCache: jest.fn(),
|
|
593
|
+
removeLocalCache: mockRemoveLocalCache,
|
|
594
|
+
}),
|
|
595
|
+
edgeToEdgeEnabled: false,
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
afterEach(() => {
|
|
600
|
+
jest.restoreAllMocks();
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
describe("when UNSAFE_allowDiscardLocalCacheWhenOffline is false", () => {
|
|
604
|
+
it("should NOT pass onAcceptEvent when offline", () => {
|
|
605
|
+
atlantisContextSpy.mockReturnValue({
|
|
606
|
+
...atlantisContextDefaultValues,
|
|
607
|
+
isOnline: false,
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
render(
|
|
611
|
+
<FormTest
|
|
612
|
+
onSubmit={onSubmitMock}
|
|
613
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline={false}
|
|
614
|
+
localCacheKey="testCacheKey"
|
|
615
|
+
/>,
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
expect(mockUseConfirmBeforeBack).toHaveBeenCalled();
|
|
619
|
+
const callArgs = mockUseConfirmBeforeBack.mock.calls[0][0];
|
|
620
|
+
expect(callArgs.onAcceptEvent).toBeUndefined();
|
|
621
|
+
expect(callArgs.showLostProgressMessage).toBe(false);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it("should pass onAcceptEvent when online", () => {
|
|
625
|
+
atlantisContextSpy.mockReturnValue({
|
|
626
|
+
...atlantisContextDefaultValues,
|
|
627
|
+
isOnline: true,
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
render(
|
|
631
|
+
<FormTest
|
|
632
|
+
onSubmit={onSubmitMock}
|
|
633
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline={false}
|
|
634
|
+
localCacheKey="testCacheKey"
|
|
635
|
+
/>,
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
expect(mockUseConfirmBeforeBack).toHaveBeenCalled();
|
|
639
|
+
const callArgs = mockUseConfirmBeforeBack.mock.calls[0][0];
|
|
640
|
+
expect(callArgs.onAcceptEvent).toBe(mockRemoveLocalCache);
|
|
641
|
+
expect(callArgs.showLostProgressMessage).toBe(true);
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
describe("when UNSAFE_allowDiscardLocalCacheWhenOffline is true", () => {
|
|
646
|
+
it("should pass onAcceptEvent when offline", () => {
|
|
647
|
+
atlantisContextSpy.mockReturnValue({
|
|
648
|
+
...atlantisContextDefaultValues,
|
|
649
|
+
isOnline: false,
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
render(
|
|
653
|
+
<FormTest
|
|
654
|
+
onSubmit={onSubmitMock}
|
|
655
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline={true}
|
|
656
|
+
localCacheKey="testCacheKey"
|
|
657
|
+
/>,
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
expect(mockUseConfirmBeforeBack).toHaveBeenCalled();
|
|
661
|
+
const callArgs = mockUseConfirmBeforeBack.mock.calls[0][0];
|
|
662
|
+
expect(callArgs.onAcceptEvent).toBe(mockRemoveLocalCache);
|
|
663
|
+
expect(callArgs.showLostProgressMessage).toBe(true);
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it("should pass onAcceptEvent when online", () => {
|
|
667
|
+
atlantisContextSpy.mockReturnValue({
|
|
668
|
+
...atlantisContextDefaultValues,
|
|
669
|
+
isOnline: true,
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
render(
|
|
673
|
+
<FormTest
|
|
674
|
+
onSubmit={onSubmitMock}
|
|
675
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline={true}
|
|
676
|
+
localCacheKey="testCacheKey"
|
|
677
|
+
/>,
|
|
678
|
+
);
|
|
679
|
+
|
|
680
|
+
expect(mockUseConfirmBeforeBack).toHaveBeenCalled();
|
|
681
|
+
const callArgs = mockUseConfirmBeforeBack.mock.calls[0][0];
|
|
682
|
+
expect(callArgs.onAcceptEvent).toBe(mockRemoveLocalCache);
|
|
683
|
+
expect(callArgs.showLostProgressMessage).toBe(true);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
describe("without localCacheKey", () => {
|
|
688
|
+
it("should always show lost progress message when no cache key is provided", () => {
|
|
689
|
+
atlantisContextSpy.mockReturnValue({
|
|
690
|
+
...atlantisContextDefaultValues,
|
|
691
|
+
isOnline: false,
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
render(
|
|
695
|
+
<FormTest
|
|
696
|
+
onSubmit={onSubmitMock}
|
|
697
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline={false}
|
|
698
|
+
/>,
|
|
699
|
+
);
|
|
700
|
+
|
|
701
|
+
expect(mockUseConfirmBeforeBack).toHaveBeenCalled();
|
|
702
|
+
const callArgs = mockUseConfirmBeforeBack.mock.calls[0][0];
|
|
703
|
+
expect(callArgs.showLostProgressMessage).toBe(true);
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
});
|
|
564
707
|
});
|
package/src/Form/Form.tsx
CHANGED
|
@@ -34,7 +34,7 @@ import { ErrorMessageProvider } from "../ErrorMessageWrapper";
|
|
|
34
34
|
export function Form<T extends FieldValues, S>({
|
|
35
35
|
initialLoading,
|
|
36
36
|
...rest
|
|
37
|
-
}: FormProps<T, S>)
|
|
37
|
+
}: FormProps<T, S>) {
|
|
38
38
|
const child = initialLoading ? <FormMask /> : <InternalForm {...rest} />;
|
|
39
39
|
|
|
40
40
|
return (
|
|
@@ -66,6 +66,7 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
66
66
|
saveButtonOffset,
|
|
67
67
|
showStickySaveButton = false,
|
|
68
68
|
renderFooter,
|
|
69
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline,
|
|
69
70
|
}: InternalFormProps<T, S>) {
|
|
70
71
|
const { scrollViewRef, bottomViewRef, scrollToTop } = useFormViewRefs();
|
|
71
72
|
const [saveButtonHeight, setSaveButtonHeight] = useState(0);
|
|
@@ -87,6 +88,7 @@ function InternalForm<T extends FieldValues, S>({
|
|
|
87
88
|
scrollViewRef,
|
|
88
89
|
saveButtonHeight,
|
|
89
90
|
messageBannerHeight,
|
|
91
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline,
|
|
90
92
|
});
|
|
91
93
|
const { windowHeight, headerHeight } = useScreenInformation();
|
|
92
94
|
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { type ReactElement } from "react";
|
|
2
2
|
import type { LayoutChangeEvent } from "react-native";
|
|
3
3
|
import { StyleSheet } from "react-native";
|
|
4
4
|
import Reanimated from "react-native-reanimated";
|
|
@@ -18,7 +18,7 @@ export interface FormActionBarProps {
|
|
|
18
18
|
onSubmit: () => void,
|
|
19
19
|
label: string | undefined,
|
|
20
20
|
isSubmitting: boolean,
|
|
21
|
-
) =>
|
|
21
|
+
) => ReactElement;
|
|
22
22
|
readonly secondaryActions?: SecondaryActionProp[];
|
|
23
23
|
readonly setSecondaryActionLoading?: (bool: boolean) => void;
|
|
24
24
|
}
|
|
@@ -32,7 +32,7 @@ export function FormActionBar({
|
|
|
32
32
|
setSaveButtonHeight,
|
|
33
33
|
secondaryActions,
|
|
34
34
|
setSecondaryActionLoading,
|
|
35
|
-
}: FormActionBarProps)
|
|
35
|
+
}: FormActionBarProps) {
|
|
36
36
|
const styles = useStyles();
|
|
37
37
|
|
|
38
38
|
const buttonStyle = StyleSheet.flatten([
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo } from "react";
|
|
1
|
+
import React, { type ReactElement, useMemo } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { useStyles } from "./FormBody.style";
|
|
4
4
|
import { useScreenInformation } from "../../hooks/useScreenInformation";
|
|
@@ -7,7 +7,7 @@ import { FormActionBar } from "../FormActionBar";
|
|
|
7
7
|
import { tokens } from "../../../utils/design";
|
|
8
8
|
|
|
9
9
|
interface FormBodyProps extends FormActionBarProps {
|
|
10
|
-
readonly children:
|
|
10
|
+
readonly children: ReactElement;
|
|
11
11
|
readonly shouldRenderActionBar?: boolean;
|
|
12
12
|
readonly saveButtonOffset?: number;
|
|
13
13
|
}
|
|
@@ -24,7 +24,7 @@ export function FormBody({
|
|
|
24
24
|
setSecondaryActionLoading,
|
|
25
25
|
setSaveButtonHeight,
|
|
26
26
|
saveButtonOffset,
|
|
27
|
-
}: FormBodyProps)
|
|
27
|
+
}: FormBodyProps) {
|
|
28
28
|
const paddingBottom = useBottomPadding();
|
|
29
29
|
const fullViewPadding = useMemo(() => ({ paddingBottom }), [paddingBottom]);
|
|
30
30
|
const styles = useStyles();
|
|
@@ -14,7 +14,7 @@ export function FormCache<T extends FieldValues>({
|
|
|
14
14
|
localCacheExclude,
|
|
15
15
|
localCacheKey,
|
|
16
16
|
setLocalCache,
|
|
17
|
-
}: FormCacheProps<T>)
|
|
17
|
+
}: FormCacheProps<T>) {
|
|
18
18
|
const { control, formState } = useFormContext<T>();
|
|
19
19
|
const { isDirty } = formState;
|
|
20
20
|
|
|
@@ -4,7 +4,7 @@ import { useStyles } from "./FormMask.style";
|
|
|
4
4
|
import { ActivityIndicator } from "../../../ActivityIndicator";
|
|
5
5
|
import { useAtlantisI18n } from "../../../hooks/useAtlantisI18n";
|
|
6
6
|
|
|
7
|
-
export function FormMask()
|
|
7
|
+
export function FormMask() {
|
|
8
8
|
const { t } = useAtlantisI18n();
|
|
9
9
|
const styles = useStyles();
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ let close: (() => void) | undefined;
|
|
|
17
17
|
* message to the user. Use `FormMessage.close()` to close the most
|
|
18
18
|
* recent message.
|
|
19
19
|
*/
|
|
20
|
-
export const FormMessage = ()
|
|
20
|
+
export const FormMessage = () => {
|
|
21
21
|
const [data, setData] = useState<FormMessageData[]>([]);
|
|
22
22
|
|
|
23
23
|
open = useCallback(
|
package/src/Form/components/FormMessage/components/InternalFormMessage/InternalFormMessage.tsx
CHANGED
|
@@ -15,7 +15,7 @@ interface FormMessageProps {
|
|
|
15
15
|
export function InternalFormMessage({
|
|
16
16
|
data,
|
|
17
17
|
onRequestClose,
|
|
18
|
-
}: FormMessageProps)
|
|
18
|
+
}: FormMessageProps) {
|
|
19
19
|
const { t } = useAtlantisI18n();
|
|
20
20
|
const styles = useStyles();
|
|
21
21
|
const emptyStateData: EmptyStateProps = useMemo(() => {
|
|
@@ -8,9 +8,7 @@ interface FormMessageBannerProps {
|
|
|
8
8
|
readonly bannerMessages?: FormBannerMessage[];
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function FormMessageBanner({
|
|
12
|
-
bannerMessages,
|
|
13
|
-
}: FormMessageBannerProps): JSX.Element {
|
|
11
|
+
export function FormMessageBanner({ bannerMessages }: FormMessageBannerProps) {
|
|
14
12
|
return (
|
|
15
13
|
<>
|
|
16
14
|
{bannerMessages?.map((message, index) => (
|
|
@@ -13,7 +13,7 @@ export function FormSaveButton({
|
|
|
13
13
|
setSecondaryActionLoading,
|
|
14
14
|
onOpenBottomSheet,
|
|
15
15
|
onCloseBottomSheet,
|
|
16
|
-
}: FormSaveButtonProps)
|
|
16
|
+
}: FormSaveButtonProps) {
|
|
17
17
|
const { t } = useAtlantisI18n();
|
|
18
18
|
const formContext = useFormContext();
|
|
19
19
|
const buttonActions = useButtonGroupAction(secondaryActions);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
2
|
import type { DeepPartial, FieldValues, UseFormReturn } from "react-hook-form";
|
|
3
3
|
|
|
4
4
|
export interface UseConfirmBeforeBackProps {
|
|
@@ -21,7 +21,7 @@ interface LocalCacheOptions {
|
|
|
21
21
|
export interface AtlantisFormContextProps {
|
|
22
22
|
useConfirmBeforeBack: (
|
|
23
23
|
props: UseConfirmBeforeBackProps,
|
|
24
|
-
) =>
|
|
24
|
+
) => RefObject<() => void>;
|
|
25
25
|
useInternalFormLocalCache: <TData extends FieldValues>(
|
|
26
26
|
formMethods: UseFormReturn<TData>,
|
|
27
27
|
cacheKey?: string,
|
|
@@ -4,15 +4,14 @@ import type { View } from "react-native";
|
|
|
4
4
|
import type { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
|
5
5
|
|
|
6
6
|
interface UseFormViewRefsReturn {
|
|
7
|
-
readonly scrollViewRef: RefObject<KeyboardAwareScrollView>;
|
|
8
|
-
readonly bottomViewRef: RefObject<View>;
|
|
7
|
+
readonly scrollViewRef: RefObject<KeyboardAwareScrollView | null>;
|
|
8
|
+
readonly bottomViewRef: RefObject<View | null>;
|
|
9
9
|
readonly scrollToTop: () => void;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function useFormViewRefs(): UseFormViewRefsReturn {
|
|
13
|
-
const scrollViewRef
|
|
14
|
-
|
|
15
|
-
const bottomViewRef: RefObject<View> = useRef<View>(null);
|
|
13
|
+
const scrollViewRef = useRef<KeyboardAwareScrollView>(null);
|
|
14
|
+
const bottomViewRef = useRef<View>(null);
|
|
16
15
|
const scrollToTop = useCallback(() => {
|
|
17
16
|
scrollViewRef.current?.scrollToPosition(0, 0);
|
|
18
17
|
}, [scrollViewRef]);
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
UseFormReturn,
|
|
6
6
|
} from "react-hook-form";
|
|
7
7
|
import { useForm } from "react-hook-form";
|
|
8
|
-
import type {
|
|
8
|
+
import type { RefObject } from "react";
|
|
9
9
|
import type { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
|
10
10
|
import { useAtlantisContext } from "../../AtlantisContext";
|
|
11
11
|
import { useAtlantisFormContext } from "../context/AtlantisFormContext";
|
|
@@ -20,8 +20,9 @@ type UseInternalFormProps<T extends FieldValues, SubmitResponseType> = Pick<
|
|
|
20
20
|
| "localCacheKey"
|
|
21
21
|
| "localCacheExclude"
|
|
22
22
|
| "localCacheId"
|
|
23
|
+
| "UNSAFE_allowDiscardLocalCacheWhenOffline"
|
|
23
24
|
> & {
|
|
24
|
-
scrollViewRef?: RefObject<KeyboardAwareScrollView>;
|
|
25
|
+
scrollViewRef?: RefObject<KeyboardAwareScrollView | null>;
|
|
25
26
|
readonly saveButtonHeight: number;
|
|
26
27
|
readonly messageBannerHeight: number;
|
|
27
28
|
};
|
|
@@ -31,7 +32,7 @@ interface UseInternalForm<T extends FieldValues> {
|
|
|
31
32
|
readonly handleSubmit: UseFormHandleSubmit<T>;
|
|
32
33
|
readonly isSubmitting: boolean;
|
|
33
34
|
readonly isDirty: boolean;
|
|
34
|
-
readonly removeListenerRef:
|
|
35
|
+
readonly removeListenerRef: RefObject<() => void>;
|
|
35
36
|
readonly setLocalCache: (data: DeepPartial<T>) => void;
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -45,6 +46,7 @@ export function useInternalForm<T extends FieldValues, SubmitResponseType>({
|
|
|
45
46
|
scrollViewRef,
|
|
46
47
|
saveButtonHeight,
|
|
47
48
|
messageBannerHeight,
|
|
49
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline = false,
|
|
48
50
|
}: UseInternalFormProps<T, SubmitResponseType>): UseInternalForm<T> {
|
|
49
51
|
const { useConfirmBeforeBack, useInternalFormLocalCache } =
|
|
50
52
|
useAtlantisFormContext();
|
|
@@ -82,11 +84,16 @@ export function useInternalForm<T extends FieldValues, SubmitResponseType>({
|
|
|
82
84
|
};
|
|
83
85
|
}
|
|
84
86
|
|
|
87
|
+
const shouldRemoveCacheOnBack = UNSAFE_allowDiscardLocalCacheWhenOffline
|
|
88
|
+
? true
|
|
89
|
+
: isOnline;
|
|
90
|
+
|
|
85
91
|
const removeListenerRef = useConfirmBeforeBack({
|
|
86
92
|
alwaysPreventBack: isSubmitting,
|
|
87
93
|
shouldShowAlert: isDirty,
|
|
88
|
-
onAcceptEvent:
|
|
89
|
-
showLostProgressMessage:
|
|
94
|
+
onAcceptEvent: shouldRemoveCacheOnBack ? removeLocalCache : undefined,
|
|
95
|
+
showLostProgressMessage:
|
|
96
|
+
shouldRemoveCacheOnBack || !clientSideSaveOn ? true : false,
|
|
90
97
|
});
|
|
91
98
|
|
|
92
99
|
return {
|
package/src/Form/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ReactElement, RefObject } from "react";
|
|
2
2
|
import type {
|
|
3
3
|
ControllerProps,
|
|
4
4
|
DefaultValues,
|
|
@@ -54,7 +54,7 @@ interface FormNoticeMessage {
|
|
|
54
54
|
|
|
55
55
|
export type FormRef<T extends FieldValues = FieldValues> =
|
|
56
56
|
| (UseFormReturn<T> & {
|
|
57
|
-
scrollViewRef?: RefObject<KeyboardAwareScrollView>;
|
|
57
|
+
scrollViewRef?: RefObject<KeyboardAwareScrollView | null>;
|
|
58
58
|
saveButtonHeight?: number;
|
|
59
59
|
messageBannerHeight?: number;
|
|
60
60
|
})
|
|
@@ -127,7 +127,7 @@ export interface FormProps<T extends FieldValues, SubmitResponseType> {
|
|
|
127
127
|
/**
|
|
128
128
|
* ref object to access react hook form methods and state
|
|
129
129
|
*/
|
|
130
|
-
formRef?:
|
|
130
|
+
formRef?: RefObject<FormRef<T> | undefined>;
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Label to be displayed for the save button
|
|
@@ -142,7 +142,7 @@ export interface FormProps<T extends FieldValues, SubmitResponseType> {
|
|
|
142
142
|
onSubmit: () => void,
|
|
143
143
|
label: string | undefined,
|
|
144
144
|
isSubmitting: boolean,
|
|
145
|
-
) =>
|
|
145
|
+
) => ReactElement;
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
* Adding a key will save a local copy of the form data that will be used to
|
|
@@ -171,6 +171,13 @@ 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
|
+
UNSAFE_allowDiscardLocalCacheWhenOffline?: boolean;
|
|
180
|
+
|
|
174
181
|
/**
|
|
175
182
|
* Secondary Action for ButtonGroup
|
|
176
183
|
*/
|
|
@@ -88,7 +88,7 @@ function FormatFileContent({
|
|
|
88
88
|
styleInGrid,
|
|
89
89
|
onUploadComplete,
|
|
90
90
|
isMedia,
|
|
91
|
-
}: FormatFileContentProps)
|
|
91
|
+
}: FormatFileContentProps) {
|
|
92
92
|
const styles = useStyles();
|
|
93
93
|
|
|
94
94
|
return (
|
|
@@ -204,7 +204,7 @@ export function FormatFile<T extends File | FileUpload>({
|
|
|
204
204
|
showFileTypeIndicator = true,
|
|
205
205
|
createThumbnail,
|
|
206
206
|
onPreviewPress,
|
|
207
|
-
}: FormatFileProps<T>)
|
|
207
|
+
}: FormatFileProps<T>) {
|
|
208
208
|
const onTapModified = onTap ? () => onTap(file) : () => undefined;
|
|
209
209
|
|
|
210
210
|
const formattedFile = parseFile(file, showFileTypeIndicator);
|
|
@@ -236,7 +236,7 @@ function FormatFileInternal({
|
|
|
236
236
|
onPreviewPress,
|
|
237
237
|
testID,
|
|
238
238
|
createThumbnail: createThumbnailProp,
|
|
239
|
-
}: FormatFileInternalProps)
|
|
239
|
+
}: FormatFileInternalProps) {
|
|
240
240
|
const [showOverlay, setShowOverlay] = useState<boolean>(
|
|
241
241
|
file.status !== StatusCode.Completed,
|
|
242
242
|
);
|
|
@@ -9,7 +9,7 @@ import { useAtlantisI18n } from "../../../hooks/useAtlantisI18n";
|
|
|
9
9
|
export type BottomSheetOptionsSuffix = "receipt" | "image" | "file" | "video";
|
|
10
10
|
|
|
11
11
|
interface FormatFileBottomSheetProps {
|
|
12
|
-
readonly bottomSheetRef: RefObject<BottomSheetRef>;
|
|
12
|
+
readonly bottomSheetRef: RefObject<BottomSheetRef | null>;
|
|
13
13
|
readonly onPreviewPress?: () => void;
|
|
14
14
|
readonly onRemovePress?: () => void;
|
|
15
15
|
readonly bottomSheetOptionsSuffix?: BottomSheetOptionsSuffix;
|
|
@@ -20,7 +20,7 @@ export const FormatFileBottomSheet = ({
|
|
|
20
20
|
onPreviewPress,
|
|
21
21
|
onRemovePress,
|
|
22
22
|
bottomSheetOptionsSuffix,
|
|
23
|
-
}: FormatFileBottomSheetProps)
|
|
23
|
+
}: FormatFileBottomSheetProps) => {
|
|
24
24
|
const { t } = useAtlantisI18n();
|
|
25
25
|
|
|
26
26
|
const handlePress = (onPressAction: () => void) => {
|