@applicaster/zapp-react-native-ui-components 15.0.0-rc.14 → 15.0.0-rc.140
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 +69 -26
- package/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/Cell.tsx +14 -3
- package/Components/Cell/CellWithFocusable.tsx +9 -0
- package/Components/Cell/FocusableWrapper.tsx +3 -0
- package/Components/Cell/TvOSCellComponent.tsx +25 -6
- package/Components/Focusable/Focusable.tsx +4 -2
- package/Components/Focusable/FocusableTvOS.tsx +18 -1
- package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
- package/Components/FocusableGroup/FocusableTvOS.tsx +32 -1
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +39 -28
- package/Components/GeneralContentScreen/__tests__/GeneralContentScreen.test.tsx +104 -0
- package/Components/GeneralContentScreen/utils/__tests__/getScreenDataSource.test.ts +19 -0
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
- package/Components/GeneralContentScreen/utils/getScreenDataSource.ts +9 -0
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -6
- package/Components/HandlePlayable/HandlePlayable.tsx +33 -94
- package/Components/HandlePlayable/const.ts +3 -0
- package/Components/HandlePlayable/utils.ts +105 -0
- package/Components/HookRenderer/HookRenderer.tsx +40 -10
- package/Components/HookRenderer/__tests__/HookRenderer.test.tsx +60 -0
- package/Components/Layout/TV/LayoutBackground.tsx +5 -2
- package/Components/Layout/TV/NavBarContainer.tsx +1 -10
- package/Components/Layout/TV/ScreenContainer.tsx +2 -6
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
- package/Components/Layout/TV/index.tsx +3 -4
- package/Components/Layout/TV/index.web.tsx +3 -4
- package/Components/LinkHandler/LinkHandler.tsx +2 -2
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +187 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/selectors.test.ts +45 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/style.test.ts +49 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +170 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/selectors.ts +26 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/style.ts +29 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/types.ts +37 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +30 -2
- package/Components/MasterCell/DefaultComponents/Button.tsx +0 -15
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
- package/Components/MasterCell/DefaultComponents/LiveImage/__tests__/prepareEntry.test.ts +352 -0
- package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +136 -0
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +43 -22
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +261 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +40 -39
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +95 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +86 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/index.test.ts +141 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/index.ts +1 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +10 -14
- package/Components/MasterCell/DefaultComponents/index.ts +2 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +42 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +127 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ButtonContainerView.ts +23 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +16 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +32 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +195 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +140 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +222 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +104 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +118 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +73 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +86 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +35 -48
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +39 -144
- package/Components/MasterCell/elementMapper.tsx +1 -0
- package/Components/MasterCell/hoc/__tests__/withAsyncRender.test.tsx +219 -0
- package/Components/MasterCell/hoc/withAsyncRender.tsx +9 -7
- package/Components/MasterCell/index.tsx +2 -0
- package/Components/MasterCell/utils/__tests__/resolveColor.test.js +82 -3
- package/Components/MasterCell/utils/index.ts +61 -31
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +102 -87
- package/Components/MeasurmentsPortal/__tests__/MeasurementsPortal.test.tsx +355 -0
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +17 -9
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +16 -8
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
- package/Components/OfflineHandler/NotificationView/utils.ts +34 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
- package/Components/PlayerContainer/PlayerContainer.tsx +43 -64
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/PreloaderWrapper/__tests__/index.test.tsx +26 -0
- package/Components/PreloaderWrapper/index.tsx +15 -0
- package/Components/River/ComponentsMap/ComponentsMap.tsx +18 -16
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
- package/Components/River/RefreshControl.tsx +19 -82
- package/Components/River/River.tsx +9 -82
- package/Components/River/RiverItem.tsx +26 -20
- package/Components/River/TV/River.tsx +31 -14
- package/Components/River/TV/index.tsx +8 -4
- package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
- package/Components/River/TV/utils/index.ts +4 -0
- package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/River/__tests__/componentsMap.test.js +38 -0
- package/Components/River/hooks/__tests__/usePullToRefresh.test.ts +132 -0
- package/Components/River/hooks/index.ts +1 -0
- package/Components/River/hooks/usePullToRefresh.ts +51 -0
- package/Components/Screen/TV/index.web.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +66 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +75 -6
- package/Components/Screen/index.tsx +9 -4
- package/Components/Screen/navigationHandler.ts +49 -24
- package/Components/Screen/orientationHandler.ts +10 -13
- package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +46 -0
- package/Components/ScreenFeedLoader/__tests__/ScreenFeedLoader.test.tsx +94 -0
- package/Components/ScreenFeedLoader/index.ts +1 -0
- package/Components/ScreenResolver/__tests__/screenResolver.test.js +24 -0
- package/Components/ScreenResolver/hooks/index.ts +3 -0
- package/Components/ScreenResolver/hooks/useGetComponent.ts +15 -0
- package/Components/ScreenResolver/hooks/useScreenComponentResolver.tsx +90 -0
- package/Components/ScreenResolver/index.tsx +15 -111
- package/Components/ScreenResolver/utils/__tests__/getScreenTypeProps.test.ts +45 -0
- package/Components/ScreenResolver/utils/getScreenTypeProps.ts +43 -0
- package/Components/ScreenResolver/utils/index.ts +1 -0
- package/Components/ScreenResolver/withDefaultScreenContext.tsx +16 -0
- package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +25 -0
- package/Components/ScreenResolverFeedProvider/__tests__/ScreenResolverFeedProvider.test.tsx +44 -0
- package/Components/ScreenResolverFeedProvider/index.ts +1 -0
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +44 -26
- package/Components/Tabs/TV/Tabs.tsx +20 -3
- package/Components/Tabs/TabContent.tsx +7 -4
- package/Components/TopCutoffOverlay/hooks/__tests__/useMarginTop.test.ts +130 -0
- package/Components/TopCutoffOverlay/hooks/index.ts +1 -0
- package/Components/TopCutoffOverlay/hooks/useMarginTop.ts +59 -0
- package/Components/TopCutoffOverlay/index.tsx +55 -0
- package/Components/Transitioner/Scene.tsx +10 -3
- package/Components/Transitioner/index.js +3 -3
- package/Components/VideoLive/LiveImageManager.ts +199 -54
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -33
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +2 -17
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +118 -171
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerWrapper.tsx +14 -88
- package/Components/VideoModal/VideoModal.tsx +1 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
- package/Components/VideoModal/hooks/useModalSize.ts +10 -5
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +91 -0
- package/Components/VideoModal/utils.ts +19 -9
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
- package/Components/Viewport/ViewportAware/index.tsx +16 -7
- package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
- package/Components/ZappUIComponent/index.tsx +12 -6
- package/Components/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
- package/Components/index.js +1 -1
- package/Contexts/ScreenContext/__tests__/index.test.tsx +57 -0
- package/Contexts/ScreenContext/index.tsx +71 -19
- package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
- package/Contexts/ZappHookModalContext/index.tsx +37 -61
- package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
- package/Contexts/index.ts +0 -2
- package/Decorators/Analytics/index.tsx +6 -5
- package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
- package/Decorators/ConfigurationWrapper/const.ts +1 -0
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
- package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
- package/Helpers/DataSourceHelper/index.ts +19 -0
- package/events/index.ts +3 -0
- package/events/scrollEndReached.ts +15 -0
- package/index.d.ts +7 -0
- package/package.json +6 -5
- package/Components/MasterCell/DefaultComponents/Text/utils/__tests__/withAdjustedLineHeight.test.ts +0 -46
- package/Components/MasterCell/DefaultComponents/Text/utils/index.ts +0 -21
- package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +0 -57
- package/Components/PlayerContainer/ErrorDisplay/index.ts +0 -9
- package/Components/River/TV/withTVEventHandler.tsx +0 -27
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
- package/Helpers/DataSourceHelper/index.js +0 -19
- /package/Components/HookRenderer/{index.tsx → index.ts} +0 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { TouchableOpacity } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
5
|
+
|
|
6
|
+
import { masterCellLogger } from "../logger";
|
|
7
|
+
import {
|
|
8
|
+
buildLegacySelection,
|
|
9
|
+
resolveIsActive,
|
|
10
|
+
resolveLabelText,
|
|
11
|
+
} from "./mobile/MobileActionButtons/helpers";
|
|
12
|
+
|
|
13
|
+
type ChildElementProps = {
|
|
14
|
+
children?: React.ReactNode;
|
|
15
|
+
mobileActionRole?: string;
|
|
16
|
+
uri?: string;
|
|
17
|
+
state?: "default" | "focused";
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type Props = {
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
item: ZappEntry | ZappFeed;
|
|
23
|
+
action?: {
|
|
24
|
+
identifier?: string;
|
|
25
|
+
flavour?: "flavour_1" | "flavour_2";
|
|
26
|
+
};
|
|
27
|
+
style?: Record<string, unknown>;
|
|
28
|
+
focusedStyles?: Record<string, unknown>;
|
|
29
|
+
testID?: string;
|
|
30
|
+
accessibilityLabel?: string;
|
|
31
|
+
accessibilityHint?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const isValidElement = (
|
|
35
|
+
child: React.ReactNode
|
|
36
|
+
): child is React.ReactElement<ChildElementProps> =>
|
|
37
|
+
React.isValidElement(child);
|
|
38
|
+
|
|
39
|
+
/** retrieves asset uri for a given flavour,
|
|
40
|
+
* if flavour is not provided, returns the default asset from `asset` or selected state asset (if available)
|
|
41
|
+
* asset can be:
|
|
42
|
+
* provided as asset path,
|
|
43
|
+
* provided as [default || flavour_1, alternative || flavour_2] array.
|
|
44
|
+
* mobileButtonAssets asset can be:
|
|
45
|
+
* provided as asset path,
|
|
46
|
+
* provided as [default || flavour_1, alternative || flavour_2] array,
|
|
47
|
+
* provided as [[] as flavour_1, [] as flavour_2] array for multiple flavours, where each flavour can be either a path or [default, alternative] array.
|
|
48
|
+
*
|
|
49
|
+
* isActive reflect the state of the action and can be used to render different asset for active/inactive state if asset is provided as array
|
|
50
|
+
*
|
|
51
|
+
* */
|
|
52
|
+
const selectByAssetFlavour = (
|
|
53
|
+
actionState: {
|
|
54
|
+
asset?: string | [string, string];
|
|
55
|
+
mobileButtonAssets?: [string, string] | [string, string][];
|
|
56
|
+
},
|
|
57
|
+
flavour?: "flavour_1" | "flavour_2",
|
|
58
|
+
isActive?: boolean
|
|
59
|
+
) => {
|
|
60
|
+
if (actionState.mobileButtonAssets) {
|
|
61
|
+
if (flavour) {
|
|
62
|
+
if (flavour === "flavour_1") {
|
|
63
|
+
if (typeof actionState.mobileButtonAssets[0] === "string") {
|
|
64
|
+
return actionState.mobileButtonAssets[0];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (Array.isArray(actionState.mobileButtonAssets[0])) {
|
|
68
|
+
return actionState.mobileButtonAssets[0][isActive ? 1 : 0];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return actionState.mobileButtonAssets[0];
|
|
72
|
+
} else if (flavour === "flavour_2") {
|
|
73
|
+
if (typeof actionState.mobileButtonAssets[1] === "string") {
|
|
74
|
+
return actionState.mobileButtonAssets[1];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (Array.isArray(actionState.mobileButtonAssets[1])) {
|
|
78
|
+
return actionState.mobileButtonAssets[1][isActive ? 1 : 0];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return actionState.mobileButtonAssets[1];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return Array.isArray(actionState.mobileButtonAssets[0])
|
|
86
|
+
? actionState.mobileButtonAssets[0][isActive ? 1 : 0]
|
|
87
|
+
: actionState.mobileButtonAssets[0];
|
|
88
|
+
} else {
|
|
89
|
+
return typeof actionState?.asset === "string"
|
|
90
|
+
? actionState.asset
|
|
91
|
+
: actionState.asset[isActive ? 1 : 0];
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export function PressableView({
|
|
96
|
+
children,
|
|
97
|
+
item,
|
|
98
|
+
action,
|
|
99
|
+
style = {},
|
|
100
|
+
focusedStyles = {},
|
|
101
|
+
testID,
|
|
102
|
+
accessibilityLabel,
|
|
103
|
+
accessibilityHint,
|
|
104
|
+
}: Props) {
|
|
105
|
+
const actionContext = useActions(action?.identifier);
|
|
106
|
+
|
|
107
|
+
const actionDisabled =
|
|
108
|
+
typeof actionContext?.isActionAvailable === "function" &&
|
|
109
|
+
!actionContext.isActionAvailable(item);
|
|
110
|
+
|
|
111
|
+
const supportsEntryState =
|
|
112
|
+
typeof actionContext?.initialEntryState === "function" && !actionDisabled;
|
|
113
|
+
|
|
114
|
+
const [actionState, setActionState] = useState(() =>
|
|
115
|
+
supportsEntryState ? actionContext.initialEntryState(item) : null
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (supportsEntryState) {
|
|
120
|
+
setActionState(actionContext.initialEntryState(item));
|
|
121
|
+
}
|
|
122
|
+
}, [supportsEntryState, item, actionContext]);
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (typeof actionContext?.addListener === "function") {
|
|
126
|
+
return actionContext.addListener(String(item?.id), (nextState) => {
|
|
127
|
+
setActionState(nextState);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (typeof actionContext?.addListeners === "function") {
|
|
132
|
+
return actionContext.addListeners(({ entryState, entry }) => {
|
|
133
|
+
if (entry?.id === item?.id) {
|
|
134
|
+
setActionState(entryState);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return undefined;
|
|
140
|
+
}, [actionContext, item?.id]);
|
|
141
|
+
|
|
142
|
+
const legacySelected = useMemo(() => {
|
|
143
|
+
if (!actionContext || supportsEntryState) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return buildLegacySelection(item, actionContext);
|
|
148
|
+
}, [actionContext, supportsEntryState, item]);
|
|
149
|
+
|
|
150
|
+
const isActive = resolveIsActive(actionState, legacySelected);
|
|
151
|
+
|
|
152
|
+
const labelText = supportsEntryState
|
|
153
|
+
? resolveLabelText(actionState?.label)
|
|
154
|
+
: "";
|
|
155
|
+
|
|
156
|
+
const shouldRenderAsset = Boolean(
|
|
157
|
+
supportsEntryState
|
|
158
|
+
? actionState?.asset && actionState?.mobileButtonAssets
|
|
159
|
+
: false
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const shouldRenderLabel = Boolean(labelText);
|
|
163
|
+
|
|
164
|
+
const cloneChildrenWithState = (nodes?: React.ReactNode): React.ReactNode => {
|
|
165
|
+
return React.Children.map(nodes, (child) => {
|
|
166
|
+
if (!isValidElement(child)) {
|
|
167
|
+
return child;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const role = child.props.mobileActionRole;
|
|
171
|
+
const nextChildren = cloneChildrenWithState(child.props.children);
|
|
172
|
+
|
|
173
|
+
if (role === "asset" && !shouldRenderAsset) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (role === "label" && !shouldRenderLabel) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
role === "label_container" &&
|
|
183
|
+
React.Children.count(nextChildren) === 0
|
|
184
|
+
) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const nextProps: Partial<ChildElementProps> = {};
|
|
189
|
+
|
|
190
|
+
if (role === "asset") {
|
|
191
|
+
if (action.flavour) {
|
|
192
|
+
nextProps.uri = selectByAssetFlavour(
|
|
193
|
+
actionState,
|
|
194
|
+
action.flavour,
|
|
195
|
+
isActive
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (role === "label") {
|
|
201
|
+
nextProps.state = isActive ? "focused" : "default";
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (nextChildren !== child.props.children) {
|
|
205
|
+
nextProps.children = nextChildren;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return React.cloneElement(child, nextProps);
|
|
209
|
+
});
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const onPress = useCallback(async () => {
|
|
213
|
+
if (!actionContext) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (supportsEntryState) {
|
|
218
|
+
return actionContext.invokeAction(item, {
|
|
219
|
+
updateState: setActionState,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const favouritesAction = legacySelected
|
|
224
|
+
? actionContext.removeFavourite
|
|
225
|
+
: actionContext.addFavourite;
|
|
226
|
+
|
|
227
|
+
const toggleAction = actionContext?.invokeAction ?? favouritesAction;
|
|
228
|
+
|
|
229
|
+
return toggleAction?.(item);
|
|
230
|
+
}, [actionContext, supportsEntryState, item, legacySelected]);
|
|
231
|
+
|
|
232
|
+
if (!actionContext) {
|
|
233
|
+
masterCellLogger.warning(
|
|
234
|
+
`You're missing an action plugin(${action?.identifier}) required by your mobile action button.`
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (actionDisabled) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!shouldRenderAsset && !shouldRenderLabel) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<TouchableOpacity
|
|
250
|
+
activeOpacity={1}
|
|
251
|
+
onPress={onPress}
|
|
252
|
+
testID={testID || `${item?.id}`}
|
|
253
|
+
accessibilityLabel={accessibilityLabel || `${item?.id}`}
|
|
254
|
+
accessibilityHint={accessibilityHint}
|
|
255
|
+
accessible={!!(testID || accessibilityLabel)}
|
|
256
|
+
style={isActive ? { ...style, ...focusedStyles } : style}
|
|
257
|
+
>
|
|
258
|
+
{cloneChildrenWithState(children)}
|
|
259
|
+
</TouchableOpacity>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
@@ -3,8 +3,8 @@ import { isNil } from "ramda";
|
|
|
3
3
|
import { ImageStyle, View } from "react-native";
|
|
4
4
|
import {
|
|
5
5
|
FIT_POSITION,
|
|
6
|
-
IMAGE_SIZING_FIT,
|
|
7
6
|
IMAGE_SIZING_FILL,
|
|
7
|
+
IMAGE_SIZING_FIT,
|
|
8
8
|
} from "@applicaster/zapp-react-native-utils/manifestUtils/secondaryImage";
|
|
9
9
|
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
10
10
|
|
|
@@ -25,49 +25,51 @@ interface Props {
|
|
|
25
25
|
fitPosition: typeof FIT_POSITION;
|
|
26
26
|
fixedWidth: number;
|
|
27
27
|
fixedHeight: number;
|
|
28
|
-
onAsyncRender
|
|
28
|
+
onAsyncRender?: () => void;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/** Secondary Image Dynamic does not render until the image is loaded */
|
|
32
|
-
const SecondaryImageDynamic = (
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const SecondaryImageDynamic = withAsyncRenderHOC(
|
|
33
|
+
(props: Props & { onAsyncRender: () => void }) => {
|
|
34
|
+
const { uri, style, displayMode, imageSizing, fitPosition, onAsyncRender } =
|
|
35
|
+
props;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
const imageDimension = useGetImageDimensions(
|
|
38
|
+
uri,
|
|
39
|
+
style.width as number,
|
|
40
|
+
isImageSizingFit(imageSizing) ? undefined : (style.height as number)
|
|
41
|
+
);
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
const containerHeight = imageDimension?.height;
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
const containerWidth = style?.width;
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
if (isNil(imageDimension?.aspectRatio)) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
51
|
+
return (
|
|
52
|
+
<View style={style} onLayout={onAsyncRender}>
|
|
53
|
+
<Image
|
|
54
|
+
{...props}
|
|
55
|
+
source={{ uri }}
|
|
56
|
+
style={{
|
|
57
|
+
...getStyle({
|
|
58
|
+
imageSizing,
|
|
59
|
+
fitPosition,
|
|
60
|
+
displayMode,
|
|
61
|
+
imageDimension,
|
|
62
|
+
containerHeight,
|
|
63
|
+
containerWidth,
|
|
64
|
+
}),
|
|
65
|
+
borderRadius: style.borderRadius,
|
|
66
|
+
aspectRatio: imageDimension.aspectRatio,
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
69
|
+
</View>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
);
|
|
71
73
|
|
|
72
74
|
/** Secondary Image Fixed does not render the image until the image is loaded, but keep container rendered */
|
|
73
75
|
const SecondaryImageFixed = (props: Props) => {
|
|
@@ -79,7 +81,6 @@ const SecondaryImageFixed = (props: Props) => {
|
|
|
79
81
|
fitPosition,
|
|
80
82
|
fixedHeight,
|
|
81
83
|
fixedWidth,
|
|
82
|
-
onAsyncRender,
|
|
83
84
|
} = props;
|
|
84
85
|
|
|
85
86
|
const imageDimension = useGetImageDimensions(
|
|
@@ -89,7 +90,7 @@ const SecondaryImageFixed = (props: Props) => {
|
|
|
89
90
|
);
|
|
90
91
|
|
|
91
92
|
return (
|
|
92
|
-
<View style={style}
|
|
93
|
+
<View style={style}>
|
|
93
94
|
{isNil(imageDimension?.aspectRatio) ? null : (
|
|
94
95
|
<Image
|
|
95
96
|
{...props}
|
|
@@ -128,4 +129,4 @@ const SecondaryImageComponent = (props: Props) => {
|
|
|
128
129
|
);
|
|
129
130
|
};
|
|
130
131
|
|
|
131
|
-
export const SecondaryImage =
|
|
132
|
+
export const SecondaryImage = SecondaryImageComponent;
|
|
@@ -10,6 +10,10 @@ describe("SecondaryImage - Image", () => {
|
|
|
10
10
|
displayMode="dynamic"
|
|
11
11
|
uri={undefined}
|
|
12
12
|
style={{ width: 100 }}
|
|
13
|
+
imageSizing="fit"
|
|
14
|
+
fitPosition="center"
|
|
15
|
+
fixedWidth={0}
|
|
16
|
+
fixedHeight={0}
|
|
13
17
|
/>
|
|
14
18
|
);
|
|
15
19
|
|
|
@@ -23,6 +27,10 @@ describe("SecondaryImage - Image", () => {
|
|
|
23
27
|
displayMode="dynamic"
|
|
24
28
|
uri="someurl"
|
|
25
29
|
style={{ width: 100 }}
|
|
30
|
+
imageSizing="fit"
|
|
31
|
+
fitPosition="center"
|
|
32
|
+
fixedWidth={0}
|
|
33
|
+
fixedHeight={0}
|
|
26
34
|
/>
|
|
27
35
|
);
|
|
28
36
|
|
|
@@ -36,6 +44,93 @@ describe("SecondaryImage - Image", () => {
|
|
|
36
44
|
uri="someUrl"
|
|
37
45
|
displayMode="dynamic"
|
|
38
46
|
style={{ width: 100, height: 100, borderRadius: 10 }}
|
|
47
|
+
imageSizing="fill"
|
|
48
|
+
fitPosition="center"
|
|
49
|
+
fixedWidth={0}
|
|
50
|
+
fixedHeight={0}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(wrapper.toJSON()).not.toEqual(null);
|
|
55
|
+
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("SecondaryImage should render in fixed mode without image until loaded", async () => {
|
|
59
|
+
const wrapper = await render(
|
|
60
|
+
<SecondaryImage
|
|
61
|
+
displayMode="fixed"
|
|
62
|
+
uri="someurl"
|
|
63
|
+
style={{ width: 100, height: 100, borderRadius: 5 }}
|
|
64
|
+
imageSizing="fit"
|
|
65
|
+
fitPosition="center"
|
|
66
|
+
fixedWidth={100}
|
|
67
|
+
fixedHeight={100}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("SecondaryImage should not render in dynamic mode without image", async () => {
|
|
75
|
+
const wrapper = await render(
|
|
76
|
+
<SecondaryImage
|
|
77
|
+
displayMode="dynamic"
|
|
78
|
+
uri={null}
|
|
79
|
+
style={{ width: 100, height: 100 }}
|
|
80
|
+
imageSizing="fit"
|
|
81
|
+
fitPosition="center"
|
|
82
|
+
fixedWidth={0}
|
|
83
|
+
fixedHeight={0}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
expect(wrapper.toJSON()).toEqual(null);
|
|
88
|
+
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("SecondaryImage should render in fixed mode with known dimensions", async () => {
|
|
92
|
+
const wrapper = await render(
|
|
93
|
+
<SecondaryImage
|
|
94
|
+
uri="someUrl"
|
|
95
|
+
displayMode="fixed"
|
|
96
|
+
style={{ width: 100, height: 100, borderRadius: 10 }}
|
|
97
|
+
imageSizing="fill"
|
|
98
|
+
fitPosition="center"
|
|
99
|
+
fixedWidth={100}
|
|
100
|
+
fixedHeight={100}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
expect(wrapper.toJSON()).not.toEqual(null);
|
|
105
|
+
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("SecondaryImage dynamic mode should call onAsyncRender when provided", async () => {
|
|
109
|
+
const wrapper = await render(
|
|
110
|
+
<SecondaryImage
|
|
111
|
+
uri="someUrl"
|
|
112
|
+
displayMode="dynamic"
|
|
113
|
+
style={{ width: 100, height: 100, borderRadius: 10 }}
|
|
114
|
+
imageSizing="fill"
|
|
115
|
+
fitPosition="center"
|
|
116
|
+
fixedWidth={0}
|
|
117
|
+
fixedHeight={0}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
expect(wrapper.toJSON()).not.toEqual(null);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("SecondaryImage fixed mode should not use async render props", async () => {
|
|
125
|
+
const wrapper = await render(
|
|
126
|
+
<SecondaryImage
|
|
127
|
+
uri="someUrl"
|
|
128
|
+
displayMode="fixed"
|
|
129
|
+
style={{ width: 100, height: 100, borderRadius: 10 }}
|
|
130
|
+
imageSizing="fill"
|
|
131
|
+
fitPosition="center"
|
|
132
|
+
fixedWidth={100}
|
|
133
|
+
fixedHeight={100}
|
|
39
134
|
/>
|
|
40
135
|
);
|
|
41
136
|
|
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
+
exports[`SecondaryImage - Image SecondaryImage fixed mode should not use async render props 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
style={
|
|
6
|
+
{
|
|
7
|
+
"borderRadius": 10,
|
|
8
|
+
"height": 100,
|
|
9
|
+
"width": 100,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
>
|
|
13
|
+
<Image
|
|
14
|
+
displayMode="fixed"
|
|
15
|
+
fitPosition="center"
|
|
16
|
+
fixedHeight={100}
|
|
17
|
+
fixedWidth={100}
|
|
18
|
+
imageSizing="fill"
|
|
19
|
+
source={
|
|
20
|
+
{
|
|
21
|
+
"uri": "someUrl",
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
style={
|
|
25
|
+
{
|
|
26
|
+
"aspectRatio": 1,
|
|
27
|
+
"borderRadius": 10,
|
|
28
|
+
"height": 100,
|
|
29
|
+
"width": 100,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
uri="someUrl"
|
|
33
|
+
/>
|
|
34
|
+
</View>
|
|
35
|
+
`;
|
|
36
|
+
|
|
3
37
|
exports[`SecondaryImage - Image SecondaryImage should not render if no aspect ratio (dynamic) 1`] = `null`;
|
|
4
38
|
|
|
5
39
|
exports[`SecondaryImage - Image SecondaryImage should not render if no uri 1`] = `null`;
|
|
6
40
|
|
|
41
|
+
exports[`SecondaryImage - Image SecondaryImage should not render in dynamic mode without image 1`] = `null`;
|
|
42
|
+
|
|
7
43
|
exports[`SecondaryImage - Image SecondaryImage should render if known dimensions 1`] = `
|
|
8
44
|
<View
|
|
9
45
|
onLayout={[Function]}
|
|
@@ -17,6 +53,10 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
|
|
|
17
53
|
>
|
|
18
54
|
<Image
|
|
19
55
|
displayMode="dynamic"
|
|
56
|
+
fitPosition="center"
|
|
57
|
+
fixedHeight={0}
|
|
58
|
+
fixedWidth={0}
|
|
59
|
+
imageSizing="fill"
|
|
20
60
|
onAsyncRender={[Function]}
|
|
21
61
|
source={
|
|
22
62
|
{
|
|
@@ -35,3 +75,49 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
|
|
|
35
75
|
/>
|
|
36
76
|
</View>
|
|
37
77
|
`;
|
|
78
|
+
|
|
79
|
+
exports[`SecondaryImage - Image SecondaryImage should render in fixed mode with known dimensions 1`] = `
|
|
80
|
+
<View
|
|
81
|
+
style={
|
|
82
|
+
{
|
|
83
|
+
"borderRadius": 10,
|
|
84
|
+
"height": 100,
|
|
85
|
+
"width": 100,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
>
|
|
89
|
+
<Image
|
|
90
|
+
displayMode="fixed"
|
|
91
|
+
fitPosition="center"
|
|
92
|
+
fixedHeight={100}
|
|
93
|
+
fixedWidth={100}
|
|
94
|
+
imageSizing="fill"
|
|
95
|
+
source={
|
|
96
|
+
{
|
|
97
|
+
"uri": "someUrl",
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
style={
|
|
101
|
+
{
|
|
102
|
+
"aspectRatio": 1,
|
|
103
|
+
"borderRadius": 10,
|
|
104
|
+
"height": 100,
|
|
105
|
+
"width": 100,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
uri="someUrl"
|
|
109
|
+
/>
|
|
110
|
+
</View>
|
|
111
|
+
`;
|
|
112
|
+
|
|
113
|
+
exports[`SecondaryImage - Image SecondaryImage should render in fixed mode without image until loaded 1`] = `
|
|
114
|
+
<View
|
|
115
|
+
style={
|
|
116
|
+
{
|
|
117
|
+
"borderRadius": 5,
|
|
118
|
+
"height": 100,
|
|
119
|
+
"width": 100,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/>
|
|
123
|
+
`;
|