@applicaster/zapp-react-native-ui-components 12.0.0-rc.7 → 12.0.0-rc.71
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/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 +1 -1
- package/Components/Cell/Cell.tsx +7 -7
- package/Components/Cell/CellWithFocusable.tsx +38 -19
- package/Components/Cell/TvOSCellComponent.tsx +2 -2
- package/Components/ErrorScreen/index.tsx +1 -1
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/FocusableGroup/index.tsx +1 -0
- 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 +3 -26
- package/Components/Image/Image.tsx +18 -2
- package/Components/Image/utils/index.ts +39 -0
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
- package/Components/Layout/TV/__tests__/index.test.tsx +18 -107
- package/Components/Layout/TV/index.tsx +9 -121
- package/Components/Layout/index.tsx +1 -9
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +80 -110
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- 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 +17 -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 +5 -1
- 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 +4 -1
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +6 -10
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/utils/index.ts +16 -5
- 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 +48 -0
- package/Components/Navigator/index.ts +1 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +64 -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 +179 -0
- package/Components/Screen/__tests__/Screen.test.tsx +48 -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 +103 -44
- package/Components/Screen/navigationHandler.ts +0 -82
- package/Components/Screen/orientationHandler.ts +1 -1
- package/Components/ScreenResolver/index.tsx +4 -2
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/TrackedView/index.tsx +6 -3
- package/Components/Transitioner/Scene.tsx +24 -19
- package/Components/Transitioner/Transitioner.tsx +9 -2
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +60 -14
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +81 -72
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
- package/Components/VideoModal/PlayerDetails.tsx +6 -3
- package/Components/VideoModal/PlayerWrapper.tsx +82 -50
- package/Components/VideoModal/VideoModal.tsx +23 -40
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +12 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
- package/Components/VideoModal/hooks/useModalSize.ts +13 -4
- package/Components/VideoModal/utils.ts +3 -3
- 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/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.ts +3 -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/Contexts/{index.js → index.ts} +0 -0
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
2
|
+
import RN from "react-native";
|
|
3
3
|
import { Provider } from "react-redux";
|
|
4
4
|
import TestRenderer from "react-test-renderer";
|
|
5
|
-
import
|
|
6
|
-
import CustomText from "../Text";
|
|
5
|
+
import configureStoreFn from "redux-mock-store";
|
|
7
6
|
|
|
8
|
-
const
|
|
7
|
+
const mockUseIsRTL = jest.fn(() => true);
|
|
8
|
+
const mockGetIsRTL = jest.fn(() => true);
|
|
9
|
+
const mockUseLocalizedStrings = jest.fn(() => ({}));
|
|
10
|
+
const mockGetUILanguage = jest.fn(() => "he-HE");
|
|
11
|
+
|
|
12
|
+
jest.mock("@applicaster/zapp-react-native-utils/localizationUtils", () => ({
|
|
13
|
+
useIsRTL: mockUseIsRTL,
|
|
14
|
+
getIsRTL: mockGetIsRTL,
|
|
15
|
+
useLocalizedStrings: mockUseLocalizedStrings,
|
|
16
|
+
getUILanguage: mockGetUILanguage,
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const CustomText = require("../Text").default;
|
|
20
|
+
const mockStore = configureStoreFn();
|
|
9
21
|
|
|
10
22
|
const defaultProps = {
|
|
11
23
|
entry: {},
|
|
@@ -22,7 +34,7 @@ const getRenderedText = (label: string, store: any) => {
|
|
|
22
34
|
</Provider>
|
|
23
35
|
);
|
|
24
36
|
|
|
25
|
-
return testRenderer.root.findByType(Text).props.children;
|
|
37
|
+
return testRenderer.root.findByType(RN.Text).props.children;
|
|
26
38
|
};
|
|
27
39
|
|
|
28
40
|
describe("RTL app: Hebrew text contains english word", () => {
|
|
@@ -34,7 +46,7 @@ describe("RTL app: Hebrew text contains english word", () => {
|
|
|
34
46
|
remoteConfigurations: { localizations: { he: {} } },
|
|
35
47
|
appData: {
|
|
36
48
|
languageCode: "he",
|
|
37
|
-
countryCode: "
|
|
49
|
+
countryCode: "IL",
|
|
38
50
|
},
|
|
39
51
|
});
|
|
40
52
|
|
|
@@ -47,18 +59,22 @@ describe("RTL app: Hebrew text contains english word", () => {
|
|
|
47
59
|
|
|
48
60
|
it("Hebrew text contains not first english word", () => {
|
|
49
61
|
const renderedText = getRenderedText(textWithNotFirstEnglishWord, store);
|
|
50
|
-
|
|
51
62
|
expect(renderedText).toEqual(textWithNotFirstEnglishWord);
|
|
52
63
|
});
|
|
53
64
|
|
|
54
65
|
it("Hebrew text doesn't contain english word", () => {
|
|
55
66
|
const renderedText = getRenderedText(textWithoutEnglishWord, store);
|
|
56
|
-
|
|
57
67
|
expect(renderedText).toEqual(textWithoutEnglishWord);
|
|
58
68
|
});
|
|
59
69
|
});
|
|
60
70
|
|
|
61
71
|
describe("LTR app: English text", () => {
|
|
72
|
+
beforeAll(() => {
|
|
73
|
+
mockUseIsRTL.mockReturnValue(false);
|
|
74
|
+
mockGetIsRTL.mockReturnValue(false);
|
|
75
|
+
mockGetUILanguage.mockReturnValue("en-US");
|
|
76
|
+
});
|
|
77
|
+
|
|
62
78
|
const englishText = "Test sentence";
|
|
63
79
|
|
|
64
80
|
const store = mockStore({
|
|
@@ -71,7 +87,6 @@ describe("LTR app: English text", () => {
|
|
|
71
87
|
|
|
72
88
|
it("English text", () => {
|
|
73
89
|
const renderedText = getRenderedText(englishText, store);
|
|
74
|
-
|
|
75
90
|
expect(renderedText).toEqual(englishText);
|
|
76
91
|
});
|
|
77
92
|
});
|
|
@@ -61,7 +61,10 @@ export function ButtonContainerView({
|
|
|
61
61
|
<View style={applyRTLStylesIfNeeded(style, isRTL)}>
|
|
62
62
|
{insertBetween(
|
|
63
63
|
(index) => (
|
|
64
|
-
<HorizontalSeparator
|
|
64
|
+
<HorizontalSeparator
|
|
65
|
+
key={`separator_${index}`}
|
|
66
|
+
width={horizontalGutter}
|
|
67
|
+
/>
|
|
65
68
|
),
|
|
66
69
|
cloneElementsWithIds(buttonIds, filteredChildren)
|
|
67
70
|
)}
|
|
@@ -29,7 +29,10 @@ export function ButtonContainerView({
|
|
|
29
29
|
<View style={style}>
|
|
30
30
|
{insertBetween(
|
|
31
31
|
(index) => (
|
|
32
|
-
<HorizontalSeparator
|
|
32
|
+
<HorizontalSeparator
|
|
33
|
+
key={`separator_${index}`}
|
|
34
|
+
width={horizontalGutter}
|
|
35
|
+
/>
|
|
33
36
|
),
|
|
34
37
|
filteredChildren
|
|
35
38
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { path
|
|
1
|
+
import { path } from "ramda";
|
|
2
2
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
3
3
|
import {
|
|
4
|
+
getColorFromData,
|
|
4
5
|
getKeyForLabel,
|
|
5
6
|
mapSelfAlignment,
|
|
6
7
|
} from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
@@ -48,15 +49,10 @@ export const CollapsibleTextContainer = ({
|
|
|
48
49
|
]),
|
|
49
50
|
{
|
|
50
51
|
func: (data) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return pathOr(value, value.split("."), data);
|
|
56
|
-
} else {
|
|
57
|
-
// return default value
|
|
58
|
-
return additionalStyles.backgroundColor;
|
|
59
|
-
}
|
|
52
|
+
return getColorFromData({
|
|
53
|
+
data,
|
|
54
|
+
valueFromLayout: additionalStyles.backgroundColor,
|
|
55
|
+
});
|
|
60
56
|
},
|
|
61
57
|
propName: "backgroundColor",
|
|
62
58
|
},
|
|
@@ -125,13 +125,24 @@ export const useFilterChildren = <
|
|
|
125
125
|
|
|
126
126
|
const filteredChildren = children.filter((child) => {
|
|
127
127
|
const item = child.props.item;
|
|
128
|
-
const
|
|
128
|
+
const actionIdentifier = child.props.pluginIdentifier;
|
|
129
|
+
const action = actions.actions[actionIdentifier];
|
|
130
|
+
|
|
129
131
|
// context value of specific plugin
|
|
130
|
-
|
|
132
|
+
if (action?.module && action.module.context) {
|
|
133
|
+
const currentValue = action.module.context._currentValue;
|
|
134
|
+
|
|
135
|
+
return currentValue?.isActionAvailable
|
|
136
|
+
? currentValue.isActionAvailable(item)
|
|
137
|
+
: true;
|
|
138
|
+
}
|
|
131
139
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
:
|
|
140
|
+
masterCellLogger.error({
|
|
141
|
+
message: `Action plugin for ${actionIdentifier} could not be found, check the configuration of your action button`,
|
|
142
|
+
data: { item, action: child.props.pluginIdentifier },
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return false;
|
|
135
146
|
});
|
|
136
147
|
|
|
137
148
|
return filteredChildren;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import { MeasurementPortalContext } from "./MeasurementsPortal";
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
5
6
|
Component: React.ElementType;
|
|
@@ -19,13 +20,16 @@ const _MeasurementsPortal = (
|
|
|
19
20
|
{ Component, onLayout, componentProps, containerStyle }: Props,
|
|
20
21
|
ref
|
|
21
22
|
) => (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
// hack for cell to determine if cell is in measurement mode
|
|
24
|
+
<MeasurementPortalContext.Provider value={{}}>
|
|
25
|
+
<View
|
|
26
|
+
onLayout={onLayout}
|
|
27
|
+
style={[styles.container, containerStyle]}
|
|
28
|
+
ref={ref}
|
|
29
|
+
>
|
|
30
|
+
<Component {...componentProps} />
|
|
31
|
+
</View>
|
|
32
|
+
</MeasurementPortalContext.Provider>
|
|
29
33
|
);
|
|
30
34
|
|
|
31
35
|
export const MeasurementsPortal = React.forwardRef(_MeasurementsPortal);
|
|
@@ -35,7 +35,16 @@ const MeasurementsPortal = ({ Component, onLayout, componentProps }: Props) => {
|
|
|
35
35
|
);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
type MeasurementPortalContextType = {
|
|
39
|
+
measureComponent?: (
|
|
40
|
+
comp: React.ElementType,
|
|
41
|
+
props: Record<any, any>
|
|
42
|
+
) => Promise<any>;
|
|
43
|
+
measuringInProgress?: boolean;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const MeasurementPortalContext =
|
|
47
|
+
React.createContext<null | MeasurementPortalContextType>(null);
|
|
39
48
|
|
|
40
49
|
const MeasurementsPortalContextProvider = ({ children }) => {
|
|
41
50
|
const Component = React.useRef(View);
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from "react";
|
|
8
|
+
import { View, LayoutChangeEvent, ScrollView } from "react-native";
|
|
9
|
+
import { Button } from "./Button";
|
|
10
|
+
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
|
+
import { ItemProps } from "./Button/Item";
|
|
12
|
+
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
13
|
+
import {
|
|
14
|
+
defaultItemIconProps,
|
|
15
|
+
defaultItemLabelProps,
|
|
16
|
+
defaultItemProps,
|
|
17
|
+
} from "./utils";
|
|
18
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
19
|
+
|
|
20
|
+
import { ModalHeader } from "./Header";
|
|
21
|
+
|
|
22
|
+
type ModalComponentProps = {
|
|
23
|
+
items: any[];
|
|
24
|
+
current_selection?: any;
|
|
25
|
+
onPress: (item: any) => void;
|
|
26
|
+
width: number;
|
|
27
|
+
currentRoute: boolean;
|
|
28
|
+
summary?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
maxHeight?: number;
|
|
31
|
+
dismiss: () => void;
|
|
32
|
+
buttonComponent?: React.ComponentType;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
36
|
+
const {
|
|
37
|
+
items,
|
|
38
|
+
currentRoute,
|
|
39
|
+
maxHeight,
|
|
40
|
+
current_selection = null,
|
|
41
|
+
onPress,
|
|
42
|
+
dismiss,
|
|
43
|
+
summary,
|
|
44
|
+
title,
|
|
45
|
+
buttonComponent: ButtonComponent = Button,
|
|
46
|
+
} = props;
|
|
47
|
+
|
|
48
|
+
const [headerHeight, setHeaderHeight] = useState(0);
|
|
49
|
+
const route = useRef(currentRoute);
|
|
50
|
+
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
51
|
+
|
|
52
|
+
const maxContentHeight = maxHeight
|
|
53
|
+
? maxHeight - headerHeight - Number(theme.modal_bottom_sheet_padding_top)
|
|
54
|
+
: undefined;
|
|
55
|
+
|
|
56
|
+
const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
|
|
57
|
+
setHeaderHeight(event.nativeEvent.layout.height);
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (currentRoute !== route.current) {
|
|
62
|
+
props.dismiss();
|
|
63
|
+
}
|
|
64
|
+
}, [currentRoute]);
|
|
65
|
+
|
|
66
|
+
const iconBaseProps = useMemo<ItemIconProps>(() => {
|
|
67
|
+
return defaultItemIconProps(theme);
|
|
68
|
+
}, [theme]);
|
|
69
|
+
|
|
70
|
+
const itemBaseProps = useMemo<ItemProps>(() => {
|
|
71
|
+
return defaultItemProps(theme, props.width);
|
|
72
|
+
}, [theme, props.width]);
|
|
73
|
+
|
|
74
|
+
const labelBaseProps = useMemo<ItemLabelProps>(() => {
|
|
75
|
+
return defaultItemLabelProps(theme, props.width);
|
|
76
|
+
}, [theme, props.width]);
|
|
77
|
+
|
|
78
|
+
const handlePress = (item: any) => {
|
|
79
|
+
onPress(item);
|
|
80
|
+
dismiss();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<View
|
|
85
|
+
style={{
|
|
86
|
+
paddingTop: Number(theme.modal_bottom_sheet_padding_top),
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
<ModalHeader
|
|
90
|
+
width={props.width}
|
|
91
|
+
dismiss={dismiss}
|
|
92
|
+
configuration={theme}
|
|
93
|
+
onLayout={onHeaderLayout}
|
|
94
|
+
summary={summary}
|
|
95
|
+
title={title}
|
|
96
|
+
/>
|
|
97
|
+
<ScrollView
|
|
98
|
+
bounces={false}
|
|
99
|
+
style={{ maxHeight: maxContentHeight }}
|
|
100
|
+
contentContainerStyle={{
|
|
101
|
+
paddingBottom: Number(theme.modal_bottom_sheet_padding_bottom),
|
|
102
|
+
paddingTop: Number(theme.modal_bottom_sheet_padding_top),
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
{items.map((item, index) => (
|
|
106
|
+
<ButtonComponent
|
|
107
|
+
key={index}
|
|
108
|
+
width={props.width}
|
|
109
|
+
configuration={theme}
|
|
110
|
+
selectedItem={current_selection}
|
|
111
|
+
item={item}
|
|
112
|
+
onPress={handlePress}
|
|
113
|
+
iconBaseProps={iconBaseProps}
|
|
114
|
+
itemBaseProps={itemBaseProps}
|
|
115
|
+
labelBaseProps={labelBaseProps}
|
|
116
|
+
/>
|
|
117
|
+
))}
|
|
118
|
+
</ScrollView>
|
|
119
|
+
</View>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React, { ReactChild } from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
|
|
4
|
+
export type ItemProps = {
|
|
5
|
+
backgroundColor: string;
|
|
6
|
+
focusedBackgroundColor: string;
|
|
7
|
+
selectedBackgroundColor?: string;
|
|
8
|
+
focusectedBackgroundColor?: string;
|
|
9
|
+
borderRadius: number;
|
|
10
|
+
marginBottom: number;
|
|
11
|
+
marginLeft: number;
|
|
12
|
+
marginRight: number;
|
|
13
|
+
marginTop: number;
|
|
14
|
+
paddingTop: number;
|
|
15
|
+
paddingBottom: number;
|
|
16
|
+
paddingRight: number;
|
|
17
|
+
paddingLeft: number;
|
|
18
|
+
focused?: boolean;
|
|
19
|
+
selected?: boolean;
|
|
20
|
+
children?: ReactChild[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const styles = StyleSheet.create({
|
|
24
|
+
container: {
|
|
25
|
+
flexDirection: "row",
|
|
26
|
+
justifyContent: "space-between",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function getBackgroundColor({
|
|
31
|
+
selected,
|
|
32
|
+
focused,
|
|
33
|
+
backgroundColor,
|
|
34
|
+
focusedBackgroundColor,
|
|
35
|
+
selectedBackgroundColor,
|
|
36
|
+
focusectedBackgroundColor,
|
|
37
|
+
}) {
|
|
38
|
+
switch (true) {
|
|
39
|
+
case selected && focused:
|
|
40
|
+
return focusectedBackgroundColor;
|
|
41
|
+
case selected && !focused:
|
|
42
|
+
return selectedBackgroundColor;
|
|
43
|
+
case !selected && focused:
|
|
44
|
+
return focusedBackgroundColor;
|
|
45
|
+
default:
|
|
46
|
+
return backgroundColor;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function Item(props: ItemProps) {
|
|
51
|
+
const {
|
|
52
|
+
backgroundColor,
|
|
53
|
+
focusedBackgroundColor,
|
|
54
|
+
focusectedBackgroundColor,
|
|
55
|
+
selectedBackgroundColor,
|
|
56
|
+
children,
|
|
57
|
+
focused,
|
|
58
|
+
selected,
|
|
59
|
+
...itemStyles
|
|
60
|
+
} = props;
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<View
|
|
64
|
+
style={[
|
|
65
|
+
styles.container,
|
|
66
|
+
itemStyles,
|
|
67
|
+
{
|
|
68
|
+
backgroundColor: getBackgroundColor({
|
|
69
|
+
selected,
|
|
70
|
+
focused,
|
|
71
|
+
focusectedBackgroundColor,
|
|
72
|
+
focusedBackgroundColor,
|
|
73
|
+
selectedBackgroundColor,
|
|
74
|
+
backgroundColor,
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
]}
|
|
78
|
+
>
|
|
79
|
+
{children}
|
|
80
|
+
</View>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { QBImage } from "@applicaster/zapp-react-native-ui-components/Components";
|
|
4
|
+
|
|
5
|
+
export type ItemIconProps = {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
asset?: string | string[] | CellActionAssetComponent;
|
|
9
|
+
flavour?: "flavour_1" | "flavour_2";
|
|
10
|
+
marginTop: number;
|
|
11
|
+
marginBottom: number;
|
|
12
|
+
marginLeft: number;
|
|
13
|
+
marginRight: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function isImageAsset(asset) {
|
|
17
|
+
return typeof asset === "string" || Array.isArray(asset);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getImageAsset(asset, flavour) {
|
|
21
|
+
if (typeof asset === "string") return asset;
|
|
22
|
+
|
|
23
|
+
if (flavour) {
|
|
24
|
+
const flavourIndex = Number(flavour.replace("flavour_", ""));
|
|
25
|
+
if (flavourIndex > -1) return asset?.[flavourIndex - 1];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return asset?.[0];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function ItemIcon(props: ItemIconProps) {
|
|
32
|
+
const { width, height, asset, flavour, ...styles } = props;
|
|
33
|
+
|
|
34
|
+
if (isImageAsset(asset)) {
|
|
35
|
+
const imageAsset = getImageAsset(asset, flavour);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<View style={styles}>
|
|
39
|
+
<QBImage
|
|
40
|
+
fadeDuration={0}
|
|
41
|
+
source={{ uri: imageAsset }}
|
|
42
|
+
style={{ width, height }}
|
|
43
|
+
/>
|
|
44
|
+
</View>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const AssetComponent = asset as CellActionAssetComponent;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View style={styles}>
|
|
52
|
+
<AssetComponent
|
|
53
|
+
width={width}
|
|
54
|
+
height={height}
|
|
55
|
+
style={styles}
|
|
56
|
+
flavour={flavour}
|
|
57
|
+
/>
|
|
58
|
+
</View>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
3
|
+
import { textTransform } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
4
|
+
|
|
5
|
+
export type ItemLabelProps = {
|
|
6
|
+
label?: string | Record<string, string>;
|
|
7
|
+
fontFamily: string;
|
|
8
|
+
letterSpacing: number;
|
|
9
|
+
fontSize: number;
|
|
10
|
+
color: string;
|
|
11
|
+
focusColor: string;
|
|
12
|
+
selectedColor?: string;
|
|
13
|
+
hoverSelectedColor?: string;
|
|
14
|
+
lineHeight: number;
|
|
15
|
+
marginBottom: number;
|
|
16
|
+
marginTop: number;
|
|
17
|
+
marginLeft: number;
|
|
18
|
+
marginRight: number;
|
|
19
|
+
transform: string;
|
|
20
|
+
maxWidth: number;
|
|
21
|
+
focused?: boolean;
|
|
22
|
+
selected?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const styles = StyleSheet.create({
|
|
26
|
+
container: {
|
|
27
|
+
justifyContent: "center",
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function getColor({
|
|
32
|
+
selected,
|
|
33
|
+
focused,
|
|
34
|
+
color,
|
|
35
|
+
selectedColor,
|
|
36
|
+
focusColor,
|
|
37
|
+
hoverSelectedColor,
|
|
38
|
+
}) {
|
|
39
|
+
switch (true) {
|
|
40
|
+
case selected && focused:
|
|
41
|
+
return hoverSelectedColor;
|
|
42
|
+
case selected && !focused:
|
|
43
|
+
return selectedColor;
|
|
44
|
+
case !selected && focused:
|
|
45
|
+
return focusColor;
|
|
46
|
+
default:
|
|
47
|
+
return color;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function ItemLabel(props: ItemLabelProps) {
|
|
52
|
+
const {
|
|
53
|
+
label,
|
|
54
|
+
fontFamily,
|
|
55
|
+
letterSpacing,
|
|
56
|
+
fontSize,
|
|
57
|
+
color,
|
|
58
|
+
selectedColor,
|
|
59
|
+
focusColor,
|
|
60
|
+
hoverSelectedColor,
|
|
61
|
+
lineHeight,
|
|
62
|
+
marginBottom,
|
|
63
|
+
marginTop,
|
|
64
|
+
marginLeft,
|
|
65
|
+
marginRight,
|
|
66
|
+
transform,
|
|
67
|
+
maxWidth,
|
|
68
|
+
focused,
|
|
69
|
+
selected,
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<View
|
|
74
|
+
style={[
|
|
75
|
+
styles.container,
|
|
76
|
+
{ marginBottom, marginLeft, marginRight, marginTop, maxWidth },
|
|
77
|
+
]}
|
|
78
|
+
>
|
|
79
|
+
<Text
|
|
80
|
+
style={{
|
|
81
|
+
fontFamily,
|
|
82
|
+
fontSize,
|
|
83
|
+
letterSpacing,
|
|
84
|
+
color: getColor({
|
|
85
|
+
selected,
|
|
86
|
+
focused,
|
|
87
|
+
color,
|
|
88
|
+
selectedColor,
|
|
89
|
+
hoverSelectedColor,
|
|
90
|
+
focusColor,
|
|
91
|
+
}),
|
|
92
|
+
lineHeight,
|
|
93
|
+
}}
|
|
94
|
+
numberOfLines={1}
|
|
95
|
+
ellipsizeMode="tail"
|
|
96
|
+
>
|
|
97
|
+
{textTransform(transform, label)}
|
|
98
|
+
</Text>
|
|
99
|
+
</View>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
|
|
3
|
+
export const defaultSelectedAsset: string =
|
|
4
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGsSURBVHgB7drdaYRAFIbhk2yuBTuwlXSQDrKdrOnErSSlpATBe0nOBxEMEXV+nDnjfg8MwiK4vKjMDIoQERERERERERHRY+j7vtHxJvTfb5wvHd/DMLyLpyc5IcTRw6eOZvrtcrlcq6q6i6PTBVqKM/GJdKpAa3EmrpGe5ST2xIFxHF/FwSnuoL1x1L2u66s4KD7QkXGg6EBHx4FiA6WIA0UGShUHiguUMg4UFSh1HCgmUI44UESgXHEgaCatf/wWslLeeY1GMsWBF/GEOHpodeouGkl8Vso7rtFIxjjg9YhNcea/+W4nrFyjkcxxwDnQUpxJrEhW4oBToLU4k9BIluKA60t6M6i+kzrfF7e1OODziLV6uG2d53onWYwDvi/pViJGshoHvCeKsSJZjgNBM+nQSNbjQPBSwzdSCXEgylrMNVIpcSDaYnVvJPWhA9OAZuO87HEg6mreIdIWE3Eg+nZHhEhm4sAh+0EBkUzFgcM2zDwimYsDh+4oOkQyGQcO33LdEclsHEiyJ70SyXScpBAJX3vNRif01yxSJ7SMH1USEREREREREREV7Ad//SBSU+GIIAAAAABJRU5ErkJggg==";
|