@applicaster/zapp-react-native-ui-components 12.0.0-rc.1 → 12.0.0-rc.100
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/Components/AnimatedInOut/index.tsx +18 -10
- package/Components/AudioPlayer/AudioPlayer.tsx +9 -1
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +5 -0
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/BaseFocusable/index.tsx +3 -3
- package/Components/Cell/Cell.tsx +32 -11
- package/Components/Cell/CellWithFocusable.tsx +40 -19
- package/Components/Cell/TvOSCellComponent.tsx +5 -9
- package/Components/ErrorScreen/index.tsx +1 -1
- package/Components/Focusable/Focusable.tsx +6 -1
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/FocusableGroup/index.tsx +11 -2
- package/Components/FocusableList/FocusableChild.ts +24 -14
- package/Components/FocusableList/FocusableItem.tsx +1 -1
- package/Components/FocusableList/FocusableListItemWrapper.tsx +76 -0
- package/Components/FocusableList/hooks/useCellState.android.ts +3 -1
- package/Components/FocusableList/index.tsx +26 -25
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +11 -8
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +4 -1
- package/Components/HookRenderer/index.tsx +1 -6
- package/Components/Image/Image.android.tsx +11 -2
- package/Components/Image/Image.tsx +18 -2
- package/Components/Image/utils/index.ts +39 -0
- package/Components/Layout/TV/ScreenContainer.tsx +79 -5
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
- package/Components/Layout/TV/__tests__/index.test.tsx +20 -108
- package/Components/Layout/TV/index.tsx +15 -84
- package/Components/Layout/TV/index.web.tsx +33 -0
- package/Components/Layout/index.tsx +15 -11
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +88 -113
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +37 -2
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
- package/Components/MasterCell/DefaultComponents/Toggle.tsx +9 -3
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +6 -10
- package/Components/MasterCell/dataAdapter.ts +21 -7
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/index.tsx +3 -1
- package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
- package/Components/MasterCell/utils/index.ts +33 -35
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
- package/Components/ModalComponent/Button/Item.tsx +82 -0
- package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
- package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
- package/Components/ModalComponent/Button/assets.ts +4 -0
- package/Components/ModalComponent/Button/index.tsx +111 -0
- package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
- package/Components/ModalComponent/Header/Title.tsx +70 -0
- package/Components/ModalComponent/Header/assets.ts +4 -0
- package/Components/ModalComponent/Header/index.tsx +71 -0
- package/Components/ModalComponent/Header/utils.ts +79 -0
- package/Components/ModalComponent/index.tsx +38 -0
- package/Components/ModalComponent/utils.ts +126 -0
- package/Components/Navigator/StackNavigator.tsx +57 -0
- package/Components/Navigator/index.ts +1 -0
- package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +4 -7
- package/Components/PlayerContainer/PlayerContainer.tsx +66 -31
- package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +97 -2
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/River.tsx +8 -5
- package/Components/River/TV/River.tsx +2 -25
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
- package/Components/River/__tests__/componentsMap.test.js +7 -0
- package/Components/River/useScreenConfiguration.ts +5 -6
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
- package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
- package/Components/RouteManager/index.tsx +4 -2
- package/Components/Screen/TV/hooks/index.ts +3 -0
- package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
- package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
- package/Components/Screen/TV/index.web.tsx +165 -0
- package/Components/Screen/__tests__/Screen.test.tsx +51 -36
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
- package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
- package/Components/Screen/index.tsx +110 -54
- package/Components/Screen/navigationHandler.ts +5 -82
- package/Components/Screen/orientationHandler.ts +1 -1
- package/Components/ScreenResolver/index.tsx +10 -13
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/TrackedView/index.tsx +6 -3
- package/Components/Transitioner/Scene.tsx +32 -26
- package/Components/Transitioner/Transitioner.tsx +21 -28
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +70 -14
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +132 -95
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +21 -29
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +66 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +355 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +161 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +456 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +182 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +302 -0
- package/Components/VideoModal/PlayerDetails.tsx +6 -3
- package/Components/VideoModal/PlayerWrapper.tsx +133 -100
- package/Components/VideoModal/VideoModal.tsx +23 -40
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +15 -3
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +262 -170
- package/Components/VideoModal/hooks/useModalSize.ts +23 -16
- package/Components/VideoModal/utils.ts +8 -5
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Components/ZappUIComponent/index.tsx +22 -12
- package/Components/index.js +2 -0
- package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
- package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
- package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
- package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
- package/Contexts/FocusableGroupContext/index.ts +7 -0
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
- package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
- package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
- package/Contexts/ScreenContext/index.tsx +95 -29
- package/Contexts/ScreenDataContext/index.tsx +20 -0
- package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
- package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
- package/Decorators/RiverResolver/index.tsx +0 -4
- package/Decorators/index.tsx +0 -4
- package/events/index.ts +1 -0
- package/package.json +5 -6
- package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
- /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -6,23 +6,23 @@ import { callOnChildren } from "../utils";
|
|
|
6
6
|
|
|
7
7
|
export function ViewportTracker(props) {
|
|
8
8
|
const viewportEvents = useViewportEventsContext();
|
|
9
|
-
const { children } = props;
|
|
10
|
-
const [width, setWidth] = React.useState(0);
|
|
11
|
-
const [height, setHeight] = React.useState(0);
|
|
12
|
-
const [offsetX, setOffsetX] = React.useState(0);
|
|
13
|
-
const [offsetY, setOffsetY] = React.useState(0);
|
|
14
9
|
const [nodeHandle, setNodeHandle] = React.useState(null);
|
|
15
10
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
const childrenRef = React.useRef(props.children);
|
|
12
|
+
|
|
13
|
+
const dimensionsRef = React.useRef({ width: 0, height: 0 });
|
|
14
|
+
const offsetRef = React.useRef({ offsetX: 0, offsetY: 0 });
|
|
15
|
+
|
|
16
|
+
const assignRef = React.useCallback((ref) => {
|
|
17
|
+
childrenRef.current?.ref?.(ref);
|
|
18
|
+
setNodeHandle(findNodeHandle(ref));
|
|
19
|
+
}, []);
|
|
23
20
|
|
|
24
21
|
const onViewportChange = React.useCallback(
|
|
25
|
-
(
|
|
22
|
+
({
|
|
23
|
+
event = { ...dimensionsRef.current, ...offsetRef.current },
|
|
24
|
+
shouldMeasureLayout = true,
|
|
25
|
+
} = {}) => {
|
|
26
26
|
if (nodeHandle && event?.width > 0 && event?.height > 0) {
|
|
27
27
|
viewportEvents?.notify?.({
|
|
28
28
|
parentHandle: nodeHandle,
|
|
@@ -36,54 +36,45 @@ export function ViewportTracker(props) {
|
|
|
36
36
|
|
|
37
37
|
const onLayout = React.useCallback(
|
|
38
38
|
(event) => {
|
|
39
|
-
callOnChildren(
|
|
40
|
-
|
|
41
|
-
setHeight(event?.nativeEvent?.layout?.height);
|
|
39
|
+
callOnChildren(childrenRef.current, "onLayout", event);
|
|
40
|
+
dimensionsRef.current = event?.nativeEvent?.layout;
|
|
42
41
|
|
|
43
|
-
onViewportChange(
|
|
44
|
-
width: event?.nativeEvent?.layout?.width,
|
|
45
|
-
height: event?.nativeEvent?.layout?.height,
|
|
46
|
-
offsetX,
|
|
47
|
-
offsetY,
|
|
48
|
-
});
|
|
42
|
+
onViewportChange();
|
|
49
43
|
},
|
|
50
|
-
[
|
|
44
|
+
[onViewportChange]
|
|
51
45
|
);
|
|
52
46
|
|
|
53
47
|
const onContentSizeChange = React.useCallback(
|
|
54
48
|
(contentWidth, contentHeight) => {
|
|
55
49
|
callOnChildren(
|
|
56
|
-
|
|
50
|
+
childrenRef.current,
|
|
57
51
|
"onContentSizeChange",
|
|
58
52
|
contentWidth,
|
|
59
53
|
contentHeight
|
|
60
54
|
);
|
|
61
55
|
|
|
62
|
-
onViewportChange(
|
|
56
|
+
onViewportChange();
|
|
63
57
|
},
|
|
64
|
-
[onViewportChange
|
|
58
|
+
[onViewportChange]
|
|
65
59
|
);
|
|
66
60
|
|
|
67
61
|
const onScroll = React.useCallback(
|
|
68
62
|
(event) => {
|
|
69
|
-
callOnChildren(
|
|
70
|
-
|
|
71
|
-
setOffsetY(event?.nativeEvent?.contentOffset?.y);
|
|
63
|
+
callOnChildren(childrenRef.current, "onScroll", event);
|
|
64
|
+
offsetRef.current = event?.nativeEvent?.contentOffset;
|
|
72
65
|
|
|
73
|
-
onViewportChange(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
height,
|
|
77
|
-
offsetX: event?.nativeEvent?.contentOffset?.x,
|
|
78
|
-
offsetY: event?.nativeEvent?.contentOffset?.y,
|
|
79
|
-
},
|
|
80
|
-
false
|
|
81
|
-
);
|
|
66
|
+
onViewportChange({
|
|
67
|
+
shouldMeasureLayout: false,
|
|
68
|
+
});
|
|
82
69
|
},
|
|
83
|
-
[onViewportChange
|
|
70
|
+
[onViewportChange]
|
|
84
71
|
);
|
|
85
72
|
|
|
86
|
-
|
|
73
|
+
React.useEffect(() => {
|
|
74
|
+
childrenRef.current = props.children;
|
|
75
|
+
}, [props.children]);
|
|
76
|
+
|
|
77
|
+
return React.cloneElement(React.Children.only(props.children), {
|
|
87
78
|
ref: assignRef,
|
|
88
79
|
onLayout,
|
|
89
80
|
onContentSizeChange,
|
|
@@ -5,11 +5,10 @@ import { ViewportEvents } from "../../ViewportEvents";
|
|
|
5
5
|
|
|
6
6
|
const TestComponent = () => <ScrollView />;
|
|
7
7
|
|
|
8
|
-
jest.mock("react-native", () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
});
|
|
8
|
+
jest.mock("react-native/Libraries/Renderer/shims/ReactNative", () => ({
|
|
9
|
+
...jest.requireActual("react-native/Libraries/Renderer/shims/ReactNative"),
|
|
10
|
+
findNodeHandle: () => 1234,
|
|
11
|
+
}));
|
|
13
12
|
|
|
14
13
|
const viewportEventsManager = new ViewportEvents(true);
|
|
15
14
|
|
|
@@ -6,6 +6,7 @@ import { ViewportEventContext, ViewportEvents } from "../ViewportEvents";
|
|
|
6
6
|
type Props = {
|
|
7
7
|
viewportEventsManager?: any;
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
+
flatListRef?: any; // this ref is used to bind to children component
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export function ViewportTracker(props: Props) {
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
|
|
3
3
|
export function callOnChildren(children, method, ...args) {
|
|
4
4
|
const childMethod = React.Children.only(children).props[method];
|
|
5
|
-
childMethod && childMethod(...args);
|
|
5
|
+
typeof childMethod === "function" && childMethod?.(...args);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function isInViewport(
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
|
|
11
11
|
import { Placeholder } from "./Placeholder";
|
|
12
12
|
import { useInitialLoading } from "./hooks";
|
|
13
|
-
import {
|
|
13
|
+
import { useFocusable } from "../Focusable/index.android";
|
|
14
14
|
|
|
15
15
|
type ReactComponent = React.ComponentType<any>;
|
|
16
16
|
|
|
@@ -26,13 +26,23 @@ type ZappUIComponentType = {
|
|
|
26
26
|
options?: Options;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
type RenderComponentProps = any;
|
|
30
|
+
|
|
31
|
+
const RenderComponent = (
|
|
32
|
+
Component: ReactComponent | undefined,
|
|
33
|
+
args: RenderComponentProps
|
|
34
|
+
) => {
|
|
35
|
+
const { component, parent } = args;
|
|
32
36
|
|
|
37
|
+
const contextValue = React.useMemo(
|
|
38
|
+
() => ({ ...component, parent }),
|
|
39
|
+
[component, parent]
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (Component) {
|
|
33
43
|
return (
|
|
34
|
-
<UIComponentContext.Provider value={
|
|
35
|
-
<Component {...
|
|
44
|
+
<UIComponentContext.Provider value={contextValue}>
|
|
45
|
+
<Component {...args} />
|
|
36
46
|
</UIComponentContext.Provider>
|
|
37
47
|
);
|
|
38
48
|
}
|
|
@@ -117,7 +127,7 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
|
|
|
117
127
|
props;
|
|
118
128
|
|
|
119
129
|
const parent = useUIComponentContext();
|
|
120
|
-
const { setIsFocusable } =
|
|
130
|
+
const { setIsFocusable } = useFocusable();
|
|
121
131
|
|
|
122
132
|
const isLoading = toBooleanWithDefaultFalse(zappPipesData?.loading);
|
|
123
133
|
const isInitialLoading = useInitialLoading(isLoading);
|
|
@@ -154,11 +164,11 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
|
|
|
154
164
|
}, [props.component?.rules?.component_cells_focusable]);
|
|
155
165
|
|
|
156
166
|
if (isDataSourceEmpty(props) && allowsEmptyDataSource) {
|
|
157
|
-
return
|
|
167
|
+
return RenderComponent(Component, componentProps);
|
|
158
168
|
}
|
|
159
169
|
|
|
160
|
-
if (isLoading && !zappPipesData
|
|
161
|
-
return
|
|
170
|
+
if (isLoading && !zappPipesData?.data && isInitialLoading) {
|
|
171
|
+
return RenderComponent(LoadingComponent || Placeholder, componentProps);
|
|
162
172
|
}
|
|
163
173
|
|
|
164
174
|
if (zappPipesData?.error) {
|
|
@@ -167,9 +177,9 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
|
|
|
167
177
|
index: componentIndex,
|
|
168
178
|
});
|
|
169
179
|
|
|
170
|
-
return
|
|
180
|
+
return RenderComponent(ErrorComponent, componentProps);
|
|
171
181
|
}
|
|
172
182
|
|
|
173
|
-
return
|
|
183
|
+
return RenderComponent(Component, componentProps);
|
|
174
184
|
};
|
|
175
185
|
}
|
package/Components/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { FocusableGroupContext } from "./FocusableGroupContext";
|
|
3
|
+
|
|
4
|
+
type ProviderArgs = {
|
|
5
|
+
id: string;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const FocusableGroupContextProvider = ({
|
|
10
|
+
id,
|
|
11
|
+
children,
|
|
12
|
+
}: ProviderArgs) => (
|
|
13
|
+
<FocusableGroupContext.Provider value={id}>
|
|
14
|
+
{children}
|
|
15
|
+
</FocusableGroupContext.Provider>
|
|
16
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, { useContext } from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
|
+
import { FocusableGroupContextProvider, FocusableGroupContext } from "../";
|
|
5
|
+
|
|
6
|
+
const MockComponent = () => {
|
|
7
|
+
const focusableContext = useContext(FocusableGroupContext) || "default";
|
|
8
|
+
|
|
9
|
+
return <Text testID={focusableContext} />;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe("FocusableGroupContextProvider", () => {
|
|
13
|
+
it("should provide focusable context to the wrapped component", () => {
|
|
14
|
+
const { getByTestId } = render(
|
|
15
|
+
<FocusableGroupContextProvider id="testId">
|
|
16
|
+
<MockComponent />
|
|
17
|
+
</FocusableGroupContextProvider>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
expect(getByTestId("testId")).toBeTruthy();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
|
+
import { withFocusableContext } from "../withFocusableContext";
|
|
5
|
+
import { FocusableGroupContext } from "../FocusableGroupContext";
|
|
6
|
+
|
|
7
|
+
const MockComponent = ({ groupId }: { groupId: string }) => (
|
|
8
|
+
<Text testID={groupId} />
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const WrappedComponent = withFocusableContext(MockComponent);
|
|
12
|
+
|
|
13
|
+
describe("withFocusableContext HOC", () => {
|
|
14
|
+
it("should provide focusable context to the wrapped component", () => {
|
|
15
|
+
const { getByTestId } = render(<WrappedComponent />, {
|
|
16
|
+
// eslint-disable-next-line react/display-name
|
|
17
|
+
wrapper: ({ children }: { children: React.ReactElement }) => (
|
|
18
|
+
<FocusableGroupContext.Provider value="test">
|
|
19
|
+
{children}
|
|
20
|
+
</FocusableGroupContext.Provider>
|
|
21
|
+
),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(getByTestId("test")).toBeTruthy();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FocusableGroupContext } from "./FocusableGroupContext";
|
|
3
|
+
import { FocusableGroupContextProvider } from "./FocusableGroupContextProvider";
|
|
4
|
+
|
|
5
|
+
export { FocusableGroupContext, FocusableGroupContextProvider };
|
|
6
|
+
|
|
7
|
+
export const useGroupId = () => React.useContext(FocusableGroupContext);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FocusableGroupContext } from "./FocusableGroupContext";
|
|
3
|
+
|
|
4
|
+
export const withFocusableContext = (Component) => {
|
|
5
|
+
// eslint-disable-next-line react/display-name
|
|
6
|
+
return ({ groupId, ...props }: Record<string, any>) => (
|
|
7
|
+
<FocusableGroupContext.Consumer>
|
|
8
|
+
{(groupIdContext: string) => {
|
|
9
|
+
// eslint-disable-next-line react/display-name
|
|
10
|
+
const propsGroupId = groupId || null;
|
|
11
|
+
const providedGroupId = propsGroupId || groupIdContext;
|
|
12
|
+
|
|
13
|
+
return <Component {...props} groupId={providedGroupId} />;
|
|
14
|
+
}}
|
|
15
|
+
</FocusableGroupContext.Consumer>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createContext } from "@applicaster/zapp-react-native-utils/reactUtils/createContext";
|
|
2
|
+
import React from "react";
|
|
2
3
|
|
|
3
4
|
const initialContext = { toggleMenu: {}, closeMenu: {}, openMenu: {} };
|
|
4
5
|
|
|
@@ -16,3 +17,18 @@ const stateValidator = ({ property }) =>
|
|
|
16
17
|
property === "openMenu";
|
|
17
18
|
|
|
18
19
|
export const MenuToggleContext = createContext(initialContext, stateValidator);
|
|
20
|
+
|
|
21
|
+
export type MenuToggleContextType = {
|
|
22
|
+
toggleMenu: any;
|
|
23
|
+
setToggleMenu: () => void;
|
|
24
|
+
openMenu: any;
|
|
25
|
+
setOpenMenu: () => void;
|
|
26
|
+
closeMenu: any;
|
|
27
|
+
setCloseMenu: () => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const useMenuToggleContext = () => {
|
|
31
|
+
return React.useContext<MenuToggleContextType>(
|
|
32
|
+
MenuToggleContext.ReactContext
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { render } from "@testing-library/react-native";
|
|
2
|
+
import { ScreenContext, ScreenContextProvider, withScreenContext } from "../";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
describe("ScreenContext", () => {
|
|
6
|
+
describe("ScreneContext context", () => {
|
|
7
|
+
it("should return the context", () => {
|
|
8
|
+
expect(ScreenContext).toBeDefined();
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe("ScreenContextProvider", () => {
|
|
13
|
+
it("should return the provider", () => {
|
|
14
|
+
expect(ScreenContextProvider).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("withScreenContext", () => {
|
|
19
|
+
it("should return the context", () => {
|
|
20
|
+
const Component = () => null;
|
|
21
|
+
const WrappedComponent = withScreenContext(Component);
|
|
22
|
+
const { toJSON } = render(<WrappedComponent />);
|
|
23
|
+
|
|
24
|
+
expect(toJSON()).toMatchSnapshot();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -1,34 +1,79 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
ReactNode,
|
|
4
|
+
useCallback,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
} from "react";
|
|
3
8
|
import {
|
|
4
9
|
useCurrentScreenData,
|
|
5
10
|
useNavigation,
|
|
6
11
|
useRoute,
|
|
12
|
+
isNavBarVisible,
|
|
7
13
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
8
14
|
import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
|
|
9
15
|
import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
|
|
10
|
-
import {
|
|
16
|
+
import { create, StoreApi, UseBoundStore } from "zustand";
|
|
17
|
+
import { useShallow } from "zustand/react/shallow";
|
|
18
|
+
import { Animated } from "react-native";
|
|
19
|
+
|
|
20
|
+
interface NavBarStoreState {
|
|
21
|
+
visible: boolean;
|
|
22
|
+
title: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
setVisible: (state: boolean) => void;
|
|
25
|
+
setTitle: (title: string) => void;
|
|
26
|
+
setSummary: (subtitle: string) => void;
|
|
27
|
+
height: number;
|
|
28
|
+
scrollState: number;
|
|
29
|
+
contentPosition: string;
|
|
30
|
+
scrollYAnimated: Animated.Value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface NavBarState {
|
|
34
|
+
visible: boolean;
|
|
35
|
+
title: string;
|
|
36
|
+
summary: string;
|
|
37
|
+
setVisible: (state: boolean) => void;
|
|
38
|
+
setTitle: (title: string) => void;
|
|
39
|
+
setSummary: (subtitle: string) => void;
|
|
40
|
+
}
|
|
11
41
|
|
|
12
42
|
type ScreenContextType = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
title: string;
|
|
16
|
-
summary: string;
|
|
17
|
-
setVisible: (state: boolean) => void;
|
|
18
|
-
setTitle: (title: string) => void;
|
|
19
|
-
setSummary: (subtitle: string) => void;
|
|
20
|
-
};
|
|
43
|
+
_navBarStore: UseBoundStore<StoreApi<NavBarStoreState>>;
|
|
44
|
+
navBar: NavBarState;
|
|
21
45
|
legacyFormatScreenData: LegacyNavigationScreenData | null;
|
|
22
46
|
};
|
|
23
47
|
|
|
48
|
+
const createStore = () =>
|
|
49
|
+
create<NavBarStoreState>((set) => ({
|
|
50
|
+
title: "",
|
|
51
|
+
summary: "",
|
|
52
|
+
visible: true,
|
|
53
|
+
height: 0,
|
|
54
|
+
scrollState: 0,
|
|
55
|
+
contentPosition: "",
|
|
56
|
+
scrollYAnimated: new Animated.Value(0),
|
|
57
|
+
setTitle(title) {
|
|
58
|
+
set({ title });
|
|
59
|
+
},
|
|
60
|
+
setSummary(summary) {
|
|
61
|
+
set({ summary });
|
|
62
|
+
},
|
|
63
|
+
setVisible(visible) {
|
|
64
|
+
set({ visible });
|
|
65
|
+
},
|
|
66
|
+
}));
|
|
67
|
+
|
|
24
68
|
export const ScreenContext = createContext<ScreenContextType>({
|
|
69
|
+
_navBarStore: createStore(),
|
|
25
70
|
navBar: {
|
|
26
71
|
visible: true,
|
|
27
72
|
title: "",
|
|
28
73
|
summary: "",
|
|
29
|
-
setVisible: (_state) =>
|
|
30
|
-
setTitle: (_title) =>
|
|
31
|
-
setSummary: (_subtitle) =>
|
|
74
|
+
setVisible: (_state) => void 0,
|
|
75
|
+
setTitle: (_title) => void 0,
|
|
76
|
+
setSummary: (_subtitle) => void 0,
|
|
32
77
|
},
|
|
33
78
|
legacyFormatScreenData: {} as LegacyNavigationScreenData,
|
|
34
79
|
});
|
|
@@ -42,8 +87,6 @@ export function ScreenContextProvider({
|
|
|
42
87
|
}) {
|
|
43
88
|
const { data, modalData, videoModalState, canGoBack } = useNavigation();
|
|
44
89
|
|
|
45
|
-
const { rivers: _rivers } = usePickFromState(["rivers", "plugins"]);
|
|
46
|
-
|
|
47
90
|
// There are 4 route scenarios
|
|
48
91
|
// For regular screens take date from navigator stack.
|
|
49
92
|
// is path is model grab screenData from modal state
|
|
@@ -56,9 +99,30 @@ export function ScreenContextProvider({
|
|
|
56
99
|
const isNested = useNestedNavigationContext();
|
|
57
100
|
const currentScreenScreenData = useCurrentScreenData();
|
|
58
101
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
102
|
+
const screenNavBarStateRef =
|
|
103
|
+
useRef<null | ReturnType<typeof createStore>>(null);
|
|
104
|
+
|
|
105
|
+
const getScreenNavBarState = useCallback(() => {
|
|
106
|
+
if (screenNavBarStateRef.current !== null) {
|
|
107
|
+
return screenNavBarStateRef.current;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const navBarState = createStore();
|
|
111
|
+
screenNavBarStateRef.current = navBarState;
|
|
112
|
+
|
|
113
|
+
return navBarState;
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
116
|
+
const screenNavBarState = getScreenNavBarState()(
|
|
117
|
+
useShallow((state) => ({
|
|
118
|
+
visible: state.visible,
|
|
119
|
+
title: state.title,
|
|
120
|
+
summary: state.summary,
|
|
121
|
+
setTitle: state.setTitle,
|
|
122
|
+
setSummary: state.setSummary,
|
|
123
|
+
setVisible: state.setVisible,
|
|
124
|
+
}))
|
|
125
|
+
);
|
|
62
126
|
|
|
63
127
|
const isHook = pathname.includes("hook");
|
|
64
128
|
|
|
@@ -76,26 +140,28 @@ export function ScreenContextProvider({
|
|
|
76
140
|
const isVisible = isNavBarVisible(
|
|
77
141
|
pathname,
|
|
78
142
|
currentScreenScreenData, // what fallback should be if currentScreenData is not available?
|
|
79
|
-
|
|
143
|
+
screenNavBarState.visible,
|
|
80
144
|
canGoBack(isHook, pathname),
|
|
81
145
|
videoModalState
|
|
82
146
|
);
|
|
83
147
|
|
|
84
|
-
const navBarState = useMemo(
|
|
85
|
-
|
|
86
|
-
title:
|
|
87
|
-
summary:
|
|
148
|
+
const navBarState = useMemo(
|
|
149
|
+
() => ({
|
|
150
|
+
title: screenNavBarState.title,
|
|
151
|
+
summary: screenNavBarState.summary,
|
|
88
152
|
visible: isVisible,
|
|
89
|
-
setTitle:
|
|
90
|
-
setSummary:
|
|
91
|
-
setVisible:
|
|
92
|
-
}
|
|
93
|
-
|
|
153
|
+
setTitle: screenNavBarState.setTitle,
|
|
154
|
+
setSummary: screenNavBarState.setSummary,
|
|
155
|
+
setVisible: screenNavBarState.setVisible,
|
|
156
|
+
}),
|
|
157
|
+
[isVisible, screenNavBarState.title, screenNavBarState.summary]
|
|
158
|
+
);
|
|
94
159
|
|
|
95
160
|
return (
|
|
96
161
|
<ScreenContext.Provider
|
|
97
162
|
value={useMemo(
|
|
98
163
|
() => ({
|
|
164
|
+
_navBarStore: getScreenNavBarState(),
|
|
99
165
|
navBar: navBarState,
|
|
100
166
|
legacyFormatScreenData: routeScreenData,
|
|
101
167
|
}),
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
3
|
+
|
|
4
|
+
export const ScreenDataContext = React.createContext<any>(null);
|
|
5
|
+
|
|
6
|
+
// Use this only to provide initial screenData context, before the Transitioner and Screen is rendered.
|
|
7
|
+
export const withScreenDataContextProvider = (Component: any) => {
|
|
8
|
+
return function ScreenDataContextProvider(props: any) {
|
|
9
|
+
const { activeRiver } = useNavigation();
|
|
10
|
+
|
|
11
|
+
// use only initial activeRiver as this context should only be used for "Home", initial route
|
|
12
|
+
const screenData = React.useMemo(() => ({ screen: activeRiver }), []);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<ScreenDataContext.Provider value={screenData}>
|
|
16
|
+
<Component {...props} />
|
|
17
|
+
</ScreenDataContext.Provider>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -12,11 +12,16 @@ export function withComponentsMapProvider(Component: React.ComponentType<any>) {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const setComponentHeightById = (id: string | number, height: number) => {
|
|
15
|
-
componentsHeightMapRef.current = {
|
|
15
|
+
componentsHeightMapRef.current = {
|
|
16
|
+
...componentsHeightMapRef.current,
|
|
17
|
+
[id]: height,
|
|
18
|
+
};
|
|
16
19
|
};
|
|
17
20
|
|
|
18
21
|
return (
|
|
19
|
-
<ComponentsMapProvider
|
|
22
|
+
<ComponentsMapProvider
|
|
23
|
+
{...{ setComponentHeightById, getComponentHeightById }}
|
|
24
|
+
>
|
|
20
25
|
<Component {...props} />
|
|
21
26
|
</ComponentsMapProvider>
|
|
22
27
|
);
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
ZappComponent,
|
|
5
|
-
ZappRivers,
|
|
6
|
-
} from "@applicaster/zapp-react-native-flow-types";
|
|
7
3
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
8
4
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
9
5
|
import { usePathname } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
package/Decorators/index.tsx
CHANGED