@applicaster/zapp-react-native-ui-components 15.1.4 → 16.0.0-alpha.1042942411
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/BackgroundImage/index.ts +1 -8
- package/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/FocusableWrapper.tsx +3 -0
- package/Components/Cell/TvOSCellComponent.tsx +6 -3
- package/Components/CellRendererResolver/index.ts +1 -1
- 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 +30 -1
- package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +39 -0
- package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
- package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
- package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
- package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
- package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
- package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
- package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
- package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
- package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
- package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
- package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
- package/Components/GeneralContentScreen/index.ts +2 -0
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +13 -8
- 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/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +27 -48
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +213 -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/components/ActionButtonController.tsx +165 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +198 -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 +217 -46
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +50 -119
- package/Components/MasterCell/DefaultComponents/Button.tsx +50 -58
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.android.tv.tsx +58 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
- package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
- package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/__snapshots__/index.test.tsx.snap +18 -0
- package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/index.test.tsx +90 -0
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +13 -14
- package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
- package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +8 -2
- 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/ImageContainer/index.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +1 -2
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +54 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +46 -50
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +47 -39
- package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +19 -6
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +15 -0
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +45 -15
- package/Components/MasterCell/DefaultComponents/UIKitAdapters/Badge.tsx +49 -0
- package/Components/MasterCell/DefaultComponents/__tests__/ActionButton.test.tsx +122 -0
- package/Components/MasterCell/DefaultComponents/__tests__/Button.test.tsx +186 -0
- package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
- package/Components/MasterCell/DefaultComponents/__tests__/DynamicBadge.test.tsx +156 -0
- package/Components/MasterCell/DefaultComponents/__tests__/__snapshots__/ActionButton.test.tsx.snap +60 -0
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +196 -67
- package/Components/MasterCell/DefaultComponents/index.ts +13 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +189 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +33 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +33 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +159 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +18 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +39 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +402 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +141 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +354 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +129 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +123 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +238 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +89 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +47 -48
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +101 -144
- package/Components/MasterCell/MappingFunctions/index.js +3 -2
- package/Components/MasterCell/README.md +4 -0
- package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
- package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
- package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
- package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
- package/Components/MasterCell/dataAdapter.ts +4 -1
- package/Components/MasterCell/elementMapper.tsx +54 -7
- package/Components/MasterCell/hooks/index.ts +2 -0
- package/Components/MasterCell/hooks/usePressedState.ts +4 -0
- package/Components/MasterCell/index.tsx +20 -4
- package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
- package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
- package/Components/MasterCell/utils/index.ts +82 -16
- package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -69
- package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +25 -47
- package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +122 -39
- package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +257 -88
- package/Components/ModalComponent/AudioPlayer/Components/index.ts +6 -4
- package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
- package/Components/ModalComponent/BottomSheetModalContent.tsx +17 -10
- package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
- package/Components/OfflineHandler/__tests__/index.test.tsx +101 -32
- package/Components/OfflineHandler/hooks.ts +123 -0
- package/Components/OfflineHandler/index.tsx +51 -73
- package/Components/OfflineHandler/utils/index.ts +1 -13
- package/Components/PlayerContainer/PlayerContainer.tsx +6 -5
- package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +2 -4
- package/Components/PreloaderWrapper/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +8 -21
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
- package/Components/River/RefreshControl.tsx +19 -105
- package/Components/River/River.tsx +9 -82
- 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 +4 -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 +65 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +2 -3
- package/Components/Screen/index.tsx +2 -3
- package/Components/Screen/orientationHandler.ts +3 -3
- package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
- package/Components/ScreenResolver/index.tsx +9 -5
- package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +1 -1
- package/Components/Tabs/TabContent.tsx +7 -4
- package/Components/TopCutoffOverlay/__tests__/TopCutoffOverlay.test.tsx +201 -0
- 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/index.js +3 -3
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
- package/Components/VideoModal/utils.ts +12 -10
- 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/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
- package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
- package/Contexts/ScreenContext/index.tsx +25 -18
- package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
- 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/__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/package.json +5 -5
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -67
- package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
- package/Components/River/TV/withTVEventHandler.tsx +0 -36
- package/Helpers/DataSourceHelper/index.js +0 -19
- /package/Components/BackgroundImage/{BackgroundImage.tv.android.tsx → BackgroundImage.android.tv.tsx} +0 -0
- /package/Components/BackgroundImage/{BackgroundImage.tv.ios.tsx → BackgroundImage.ios.tv.tsx} +0 -0
- /package/Components/BackgroundImage/{BackgroundImage.tv.web.tsx → BackgroundImage.tsx} +0 -0
|
@@ -10,11 +10,11 @@ import { pathOr, get, isNil } from "@applicaster/zapp-react-native-utils/utils";
|
|
|
10
10
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
11
11
|
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
12
|
import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
|
|
13
|
-
|
|
14
13
|
import { isNotEmptyString } from "@applicaster/zapp-react-native-utils/stringUtils";
|
|
15
14
|
import { masterCellLogger } from "../logger";
|
|
16
15
|
import { getCellState } from "../../Cell/utils";
|
|
17
16
|
import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
|
|
17
|
+
import { DataProvider } from "../DefaultComponents/DataProvider";
|
|
18
18
|
|
|
19
19
|
const hasElementSpecificViewType = (viewType) => (element) => {
|
|
20
20
|
if (isNil(element)) {
|
|
@@ -166,10 +166,50 @@ export function isVideoPreviewEnabled({
|
|
|
166
166
|
return enable_video_preview && !R.isEmpty(player_screen_id);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
export const unwrapDataProviderChild = (
|
|
170
|
+
child: React.ReactElement
|
|
171
|
+
): React.ReactElement => {
|
|
172
|
+
if ((child as any)?.type !== DataProvider) {
|
|
173
|
+
return child;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const [wrappedChild] = React.Children.toArray((child as any).props.children);
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
React.isValidElement(wrappedChild) ? wrappedChild : child
|
|
180
|
+
) as React.ReactElement;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Resolves the entry value passed by DataProvider.
|
|
185
|
+
* Prefer the direct `entry` prop and fall back to `dataProviderProps[_dataKey]`
|
|
186
|
+
* for older wrappers that still read from namespaced provider props.
|
|
187
|
+
*/
|
|
188
|
+
const getEntryFromProps = (props: {
|
|
189
|
+
dataProviderProps?: {
|
|
190
|
+
_dataKey: string;
|
|
191
|
+
[key: string]: unknown;
|
|
192
|
+
};
|
|
193
|
+
entry?: any;
|
|
194
|
+
}) => {
|
|
195
|
+
const dataProviderProps = props.dataProviderProps;
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
props.entry ??
|
|
199
|
+
(dataProviderProps?._dataKey
|
|
200
|
+
? dataProviderProps[dataProviderProps._dataKey]
|
|
201
|
+
: undefined)
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
169
205
|
export const useFilterChildren = <
|
|
170
206
|
T extends {
|
|
171
207
|
props: {
|
|
172
|
-
|
|
208
|
+
dataProviderProps?: {
|
|
209
|
+
_dataKey: string;
|
|
210
|
+
[key: string]: unknown;
|
|
211
|
+
};
|
|
212
|
+
entry?: any;
|
|
173
213
|
pluginIdentifier: string;
|
|
174
214
|
};
|
|
175
215
|
},
|
|
@@ -179,8 +219,13 @@ export const useFilterChildren = <
|
|
|
179
219
|
const actions = useActions("");
|
|
180
220
|
|
|
181
221
|
const filteredChildren = children.filter((child) => {
|
|
182
|
-
const
|
|
183
|
-
|
|
222
|
+
const wrappedChild = unwrapDataProviderChild(
|
|
223
|
+
child as unknown as React.ReactElement
|
|
224
|
+
) as unknown as T;
|
|
225
|
+
|
|
226
|
+
const item = getEntryFromProps(wrappedChild.props);
|
|
227
|
+
|
|
228
|
+
const actionIdentifier = wrappedChild.props.pluginIdentifier;
|
|
184
229
|
const action = actions.actions[actionIdentifier];
|
|
185
230
|
|
|
186
231
|
// context value of specific plugin
|
|
@@ -194,7 +239,7 @@ export const useFilterChildren = <
|
|
|
194
239
|
|
|
195
240
|
masterCellLogger.error({
|
|
196
241
|
message: `Action plugin for ${actionIdentifier} could not be found, check the configuration of your action button`,
|
|
197
|
-
data: { item, action:
|
|
242
|
+
data: { item, action: wrappedChild.props.pluginIdentifier },
|
|
198
243
|
});
|
|
199
244
|
|
|
200
245
|
return false;
|
|
@@ -242,7 +287,7 @@ export const recursiveCloneElementsWithState = (focused: boolean, children) => {
|
|
|
242
287
|
const next = (currentIndex, items) => items[currentIndex + 1];
|
|
243
288
|
const previous = (currentIndex, items) => items[currentIndex - 1];
|
|
244
289
|
|
|
245
|
-
export const
|
|
290
|
+
export const cloneChildrenWithIds = (
|
|
246
291
|
ids: string[],
|
|
247
292
|
children: React.ReactElement[]
|
|
248
293
|
) => {
|
|
@@ -250,12 +295,34 @@ export const cloneElementsWithIds = (
|
|
|
250
295
|
return undefined;
|
|
251
296
|
}
|
|
252
297
|
|
|
253
|
-
return React.Children.map(children, (element, index) =>
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
298
|
+
return React.Children.map(children, (element, index) => {
|
|
299
|
+
const nextFocusLeft = previous(index, ids);
|
|
300
|
+
const nextFocusRight = next(index, ids);
|
|
301
|
+
|
|
302
|
+
if (element?.type !== DataProvider) {
|
|
303
|
+
return React.cloneElement(element, {
|
|
304
|
+
nextFocusLeft,
|
|
305
|
+
nextFocusRight,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const wrappedChild = unwrapDataProviderChild(element) as React.ReactElement<
|
|
310
|
+
Record<string, unknown>
|
|
311
|
+
>;
|
|
312
|
+
|
|
313
|
+
if (!React.isValidElement(wrappedChild)) {
|
|
314
|
+
return element;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const injectedWrappedChild = React.cloneElement(wrappedChild, {
|
|
318
|
+
nextFocusLeft,
|
|
319
|
+
nextFocusRight,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
return React.cloneElement(element, {
|
|
323
|
+
children: injectedWrappedChild,
|
|
324
|
+
});
|
|
325
|
+
});
|
|
259
326
|
};
|
|
260
327
|
|
|
261
328
|
export const getFocusedButtonId = (focusable) => {
|
|
@@ -295,10 +362,9 @@ export const useCellState = ({
|
|
|
295
362
|
export const hasFocusableInsideBuilder = (elementsBuilder) => (item) => {
|
|
296
363
|
const elements = elementsBuilder({ entry: item });
|
|
297
364
|
|
|
298
|
-
return R.anyPass([
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
])(elements);
|
|
365
|
+
return R.anyPass([hasElementsSpecificViewType("ButtonContainerView")])(
|
|
366
|
+
elements
|
|
367
|
+
);
|
|
302
368
|
};
|
|
303
369
|
|
|
304
370
|
export function getEntryState(state, selected) {
|
|
@@ -11,7 +11,14 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import React from "react";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
Image,
|
|
16
|
+
Platform,
|
|
17
|
+
Pressable,
|
|
18
|
+
StyleSheet,
|
|
19
|
+
Text,
|
|
20
|
+
View,
|
|
21
|
+
} from "react-native";
|
|
15
22
|
|
|
16
23
|
const styles = StyleSheet.create({
|
|
17
24
|
row: {
|
|
@@ -123,10 +130,11 @@ export type ActionData = {
|
|
|
123
130
|
showTrailingChevron?: boolean;
|
|
124
131
|
};
|
|
125
132
|
|
|
126
|
-
export type
|
|
133
|
+
export type AudioPlayerActionProps = {
|
|
127
134
|
configuration: ActionConfiguration;
|
|
128
135
|
data: ActionData;
|
|
129
136
|
focused?: boolean;
|
|
137
|
+
onPress?: () => void;
|
|
130
138
|
};
|
|
131
139
|
|
|
132
140
|
// ---------------------------------------------------------------------------
|
|
@@ -187,28 +195,32 @@ type ActionContainerProps = {
|
|
|
187
195
|
configuration: BackgroundConfiguration;
|
|
188
196
|
focused: boolean;
|
|
189
197
|
children: React.ReactNode;
|
|
198
|
+
onPress?: () => void;
|
|
190
199
|
};
|
|
191
200
|
|
|
192
201
|
function ActionContainer({
|
|
193
202
|
configuration,
|
|
194
203
|
focused,
|
|
195
204
|
children,
|
|
205
|
+
onPress,
|
|
196
206
|
}: ActionContainerProps) {
|
|
197
207
|
return (
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
208
|
+
<Pressable
|
|
209
|
+
onPress={onPress}
|
|
210
|
+
style={({ pressed }) => ({
|
|
211
|
+
backgroundColor:
|
|
212
|
+
pressed || focused
|
|
213
|
+
? configuration.focusedColor
|
|
214
|
+
: configuration.defaultColor,
|
|
203
215
|
borderRadius: configuration.cornerRadius,
|
|
204
216
|
paddingTop: CONTAINER_SPEC.paddingTop,
|
|
205
217
|
paddingRight: CONTAINER_SPEC.paddingRight,
|
|
206
218
|
paddingBottom: CONTAINER_SPEC.paddingBottom,
|
|
207
219
|
paddingLeft: CONTAINER_SPEC.paddingLeft,
|
|
208
|
-
}}
|
|
220
|
+
})}
|
|
209
221
|
>
|
|
210
222
|
{children}
|
|
211
|
-
</
|
|
223
|
+
</Pressable>
|
|
212
224
|
);
|
|
213
225
|
}
|
|
214
226
|
|
|
@@ -279,10 +291,15 @@ function ActionTrailingIcon({ configuration }: ActionTrailingIconProps) {
|
|
|
279
291
|
}
|
|
280
292
|
|
|
281
293
|
// ---------------------------------------------------------------------------
|
|
282
|
-
//
|
|
294
|
+
// AudioPlayerAction
|
|
283
295
|
// ---------------------------------------------------------------------------
|
|
284
296
|
|
|
285
|
-
export function
|
|
297
|
+
export function AudioPlayerAction({
|
|
298
|
+
configuration,
|
|
299
|
+
data,
|
|
300
|
+
focused = false,
|
|
301
|
+
onPress,
|
|
302
|
+
}: AudioPlayerActionProps) {
|
|
286
303
|
const { background, title, trailingIcon } = configuration;
|
|
287
304
|
const { title: label, leadingActionType, showTrailingChevron } = data;
|
|
288
305
|
|
|
@@ -290,7 +307,11 @@ export function Item({ configuration, data, focused = false }: ItemProps) {
|
|
|
290
307
|
const showTrailing = shouldShowTrailingIcon(showTrailingChevron);
|
|
291
308
|
|
|
292
309
|
return (
|
|
293
|
-
<ActionContainer
|
|
310
|
+
<ActionContainer
|
|
311
|
+
configuration={background}
|
|
312
|
+
focused={focused}
|
|
313
|
+
onPress={onPress}
|
|
314
|
+
>
|
|
294
315
|
<View style={styles.row}>
|
|
295
316
|
{showLeading ? (
|
|
296
317
|
<>
|
|
@@ -309,60 +330,3 @@ export function Item({ configuration, data, focused = false }: ItemProps) {
|
|
|
309
330
|
</ActionContainer>
|
|
310
331
|
);
|
|
311
332
|
}
|
|
312
|
-
|
|
313
|
-
// ---------------------------------------------------------------------------
|
|
314
|
-
// Demo
|
|
315
|
-
// ---------------------------------------------------------------------------
|
|
316
|
-
|
|
317
|
-
export default function App() {
|
|
318
|
-
return (
|
|
319
|
-
<View style={styles.demoScreen}>
|
|
320
|
-
<Text style={styles.demoHeading}>Modal Action Building Block</Text>
|
|
321
|
-
|
|
322
|
-
<Text style={styles.demoLabel}>
|
|
323
|
-
Leading icon + text — Add To Queue (focused)
|
|
324
|
-
</Text>
|
|
325
|
-
<Item
|
|
326
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
327
|
-
data={{ title: "Add To Queue", leadingActionType: "addToQueue" }}
|
|
328
|
-
focused
|
|
329
|
-
/>
|
|
330
|
-
|
|
331
|
-
<Text style={styles.demoLabel}>
|
|
332
|
-
Leading icon + text + trailing chevron — Add To Playlist
|
|
333
|
-
</Text>
|
|
334
|
-
<Item
|
|
335
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
336
|
-
data={{
|
|
337
|
-
title: "Add To Playlist",
|
|
338
|
-
leadingActionType: "addToPlaylist",
|
|
339
|
-
showTrailingChevron: true,
|
|
340
|
-
}}
|
|
341
|
-
/>
|
|
342
|
-
|
|
343
|
-
<Text style={styles.demoLabel}>Text only — Go To Playlist</Text>
|
|
344
|
-
<Item
|
|
345
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
346
|
-
data={{ title: "Go To Playlist" }}
|
|
347
|
-
/>
|
|
348
|
-
|
|
349
|
-
<Text style={styles.demoLabel}>Leading icon + text — Favorite</Text>
|
|
350
|
-
<Item
|
|
351
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
352
|
-
data={{ title: "Favorite", leadingActionType: "favorite" }}
|
|
353
|
-
/>
|
|
354
|
-
|
|
355
|
-
<Text style={styles.demoLabel}>Leading icon + text — Share</Text>
|
|
356
|
-
<Item
|
|
357
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
358
|
-
data={{ title: "Share", leadingActionType: "share" }}
|
|
359
|
-
/>
|
|
360
|
-
|
|
361
|
-
<Text style={styles.demoLabel}>Text only — Go To Artist</Text>
|
|
362
|
-
<Item
|
|
363
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
364
|
-
data={{ title: "Go To Artist" }}
|
|
365
|
-
/>
|
|
366
|
-
</View>
|
|
367
|
-
);
|
|
368
|
-
}
|
|
@@ -9,7 +9,14 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import React from "react";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
Image,
|
|
14
|
+
Platform,
|
|
15
|
+
Pressable,
|
|
16
|
+
StyleSheet,
|
|
17
|
+
Text,
|
|
18
|
+
View,
|
|
19
|
+
} from "react-native";
|
|
13
20
|
|
|
14
21
|
const styles = StyleSheet.create({
|
|
15
22
|
container: {
|
|
@@ -148,11 +155,12 @@ export type ButtonData = {
|
|
|
148
155
|
disabled?: boolean;
|
|
149
156
|
};
|
|
150
157
|
|
|
151
|
-
export type
|
|
158
|
+
export type AudioPlayerButtonProps = {
|
|
152
159
|
configuration: ButtonConfiguration;
|
|
153
160
|
data: ButtonData;
|
|
154
161
|
disabled?: boolean;
|
|
155
162
|
focused?: boolean;
|
|
163
|
+
onPress?: () => void;
|
|
156
164
|
};
|
|
157
165
|
|
|
158
166
|
// ---------------------------------------------------------------------------
|
|
@@ -170,7 +178,7 @@ const ACTION_ICON_ASSETS: Record<ButtonActionType, string> = {
|
|
|
170
178
|
confirm:
|
|
171
179
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAJElEQVR42mNgGAWjYBSQCv4TwKMWDHELho/hNE/3o2AUDDcAAPv0QMAyy1CtAAAAAElFTkSuQmCC",
|
|
172
180
|
cancel:
|
|
173
|
-
"data:image/png;base64,
|
|
181
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAASElEQVR42mNgGAWjGvynkVoUTf+pqA6nxv8UqiHbEooNx2cQ1QzHZiDVDcdlCcOQsoCmQUTTSKZpMqV5RqNLUUHTwm4UDBMAALBLQ73LTvoyAAAAAElFTkSuQmCC",
|
|
174
182
|
};
|
|
175
183
|
|
|
176
184
|
function getTextTransformStyle(
|
|
@@ -192,6 +200,7 @@ type ButtonContainerProps = {
|
|
|
192
200
|
disabled: boolean;
|
|
193
201
|
configuration: BackgroundConfiguration;
|
|
194
202
|
children: React.ReactNode;
|
|
203
|
+
onPress?: () => void;
|
|
195
204
|
};
|
|
196
205
|
|
|
197
206
|
function ButtonContainer({
|
|
@@ -199,19 +208,22 @@ function ButtonContainer({
|
|
|
199
208
|
disabled,
|
|
200
209
|
configuration,
|
|
201
210
|
children,
|
|
211
|
+
onPress,
|
|
202
212
|
}: ButtonContainerProps) {
|
|
203
|
-
const
|
|
213
|
+
const defaultBgColor = disabled
|
|
204
214
|
? configuration.inactiveColor
|
|
205
215
|
: focused
|
|
206
216
|
? configuration.focusedColor
|
|
207
217
|
: configuration.defaultColor;
|
|
208
218
|
|
|
209
219
|
return (
|
|
210
|
-
<
|
|
211
|
-
|
|
220
|
+
<Pressable
|
|
221
|
+
onPress={disabled ? undefined : onPress}
|
|
222
|
+
style={({ pressed }) => [
|
|
212
223
|
styles.container,
|
|
213
224
|
{
|
|
214
|
-
backgroundColor
|
|
225
|
+
backgroundColor:
|
|
226
|
+
pressed && !disabled ? configuration.focusedColor : defaultBgColor,
|
|
215
227
|
borderRadius: configuration.cornerRadius,
|
|
216
228
|
paddingTop: configuration.paddingTop,
|
|
217
229
|
paddingRight: configuration.paddingRight,
|
|
@@ -221,7 +233,7 @@ function ButtonContainer({
|
|
|
221
233
|
]}
|
|
222
234
|
>
|
|
223
235
|
{children}
|
|
224
|
-
</
|
|
236
|
+
</Pressable>
|
|
225
237
|
);
|
|
226
238
|
}
|
|
227
239
|
|
|
@@ -295,15 +307,16 @@ function ButtonLeadingIcon({
|
|
|
295
307
|
}
|
|
296
308
|
|
|
297
309
|
// ---------------------------------------------------------------------------
|
|
298
|
-
//
|
|
310
|
+
// AudioPlayerButton — single building block driven by configuration + data
|
|
299
311
|
// ---------------------------------------------------------------------------
|
|
300
312
|
|
|
301
|
-
export function
|
|
313
|
+
export function AudioPlayerButton({
|
|
302
314
|
configuration,
|
|
303
315
|
data,
|
|
304
316
|
disabled,
|
|
305
317
|
focused = false,
|
|
306
|
-
|
|
318
|
+
onPress,
|
|
319
|
+
}: AudioPlayerButtonProps) {
|
|
307
320
|
const {
|
|
308
321
|
background: backgroundConfiguration,
|
|
309
322
|
title: titleConfiguration,
|
|
@@ -321,6 +334,7 @@ export function Item({
|
|
|
321
334
|
focused={focused}
|
|
322
335
|
disabled={isDisabled}
|
|
323
336
|
configuration={backgroundConfiguration}
|
|
337
|
+
onPress={onPress}
|
|
324
338
|
>
|
|
325
339
|
<View style={styles.contentRow}>
|
|
326
340
|
{showIcon ? (
|
|
@@ -386,39 +400,3 @@ export const VARIANT_LARGE_ICON: ButtonConfiguration = {
|
|
|
386
400
|
},
|
|
387
401
|
},
|
|
388
402
|
};
|
|
389
|
-
|
|
390
|
-
export default function App() {
|
|
391
|
-
return (
|
|
392
|
-
<View style={styles.demoScreen}>
|
|
393
|
-
<Text style={styles.demoHeading}>Modal Button Building Block</Text>
|
|
394
|
-
|
|
395
|
-
<Text style={styles.demoLabel}>Variant 1 — Text only (confirmation)</Text>
|
|
396
|
-
<Item configuration={VARIANT_TEXT_ONLY} data={{ title: "Confirm" }} />
|
|
397
|
-
|
|
398
|
-
<Text style={styles.demoLabel}>Variant 2 — Leading icon + text</Text>
|
|
399
|
-
<Item
|
|
400
|
-
configuration={VARIANT_WITH_ICON}
|
|
401
|
-
data={{ title: "Add To Playlist" }}
|
|
402
|
-
/>
|
|
403
|
-
|
|
404
|
-
<Text style={styles.demoLabel}>Inactive state</Text>
|
|
405
|
-
<Item
|
|
406
|
-
configuration={VARIANT_TEXT_ONLY}
|
|
407
|
-
data={{ title: "Unavailable" }}
|
|
408
|
-
disabled
|
|
409
|
-
/>
|
|
410
|
-
|
|
411
|
-
<Text style={styles.demoLabel}>Custom title config — uppercase</Text>
|
|
412
|
-
<Item
|
|
413
|
-
configuration={VARIANT_UPPERCASE_TITLE}
|
|
414
|
-
data={{ title: "Save Changes" }}
|
|
415
|
-
/>
|
|
416
|
-
|
|
417
|
-
<Text style={styles.demoLabel}>Custom icons config — 32×32</Text>
|
|
418
|
-
<Item
|
|
419
|
-
configuration={VARIANT_LARGE_ICON}
|
|
420
|
-
data={{ title: "Add To Queue" }}
|
|
421
|
-
/>
|
|
422
|
-
</View>
|
|
423
|
-
);
|
|
424
|
-
}
|