@applicaster/zapp-react-native-ui-components 13.0.0-alpha.6179233127 → 13.0.0-alpha.6400875052
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/Cell/Cell.tsx +3 -13
- package/Components/Cell/CellWithFocusable.tsx +18 -14
- package/Components/Cell/CellWrapper.ts +5 -0
- package/Components/Cell/styles.ts +17 -0
- package/Components/ErrorScreen/index.tsx +8 -0
- package/Components/FocusableCell/index.tsx +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +4 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
- package/Components/MasterCell/utils/behaviorProvider.ts +4 -1
- package/Components/MasterCell/utils/index.ts +6 -6
- package/Components/ModalComponent/BottomSheetModalContent.tsx +38 -15
- package/Components/ModalComponent/Button/Item.tsx +1 -0
- package/Components/ModalComponent/Button/assets.ts +1 -1
- package/Components/ModalComponent/Button/index.tsx +29 -42
- package/Components/ModalComponent/utils.ts +52 -4
- package/Components/OfflineHandler/utils/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +11 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +3 -0
- package/Components/Screen/TV/index.web.tsx +5 -6
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +4 -0
- package/Components/VideoModal/PlayerDetails.tsx +4 -4
- package/Components/VideoModal/PlayerWrapper.tsx +26 -3
- package/Components/VideoModal/VideoModal.tsx +19 -4
- package/Components/ZappUIComponent/index.tsx +4 -4
- package/Decorators/RiverResolver/index.tsx +5 -7
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -1
- package/package.json +5 -6
- package/.babelrc +0 -8
- package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
- package/Components/Cell/CellStyles/Hero/index.js +0 -111
- package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
- package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
- package/Components/Cell/CellStyles/colors.js +0 -40
- package/Components/Cell/CellStyles/index.js +0 -15
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
|
12
12
|
import { CellWithFocusable } from "./CellWithFocusable";
|
|
13
13
|
import { BaseFocusable } from "../BaseFocusable";
|
|
14
14
|
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
15
|
+
import { styles } from "./styles";
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
item: ZappEntry;
|
|
@@ -68,17 +69,6 @@ type State = {
|
|
|
68
69
|
hasFocusableInside: boolean;
|
|
69
70
|
};
|
|
70
71
|
|
|
71
|
-
const baseCellStyles = {
|
|
72
|
-
height: "100%",
|
|
73
|
-
display: "flex",
|
|
74
|
-
flex: 1,
|
|
75
|
-
} as const;
|
|
76
|
-
|
|
77
|
-
const touchableStyles = {
|
|
78
|
-
flex: 1,
|
|
79
|
-
height: "100%",
|
|
80
|
-
} as const;
|
|
81
|
-
|
|
82
72
|
export class CellComponent extends React.Component<Props, State> {
|
|
83
73
|
constructor(props) {
|
|
84
74
|
super(props);
|
|
@@ -252,7 +242,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
252
242
|
<View
|
|
253
243
|
testID={`${component?.id}-${id}`}
|
|
254
244
|
accessible={false}
|
|
255
|
-
style={
|
|
245
|
+
style={styles.touchableCell}
|
|
256
246
|
>
|
|
257
247
|
<Focusable
|
|
258
248
|
id={focusableId}
|
|
@@ -264,7 +254,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
264
254
|
hasReceivedFocus={hasReceivedFocus || this.hasReceivedFocus}
|
|
265
255
|
preferredFocus={preferredFocus}
|
|
266
256
|
offsetUpdater={offsetUpdater}
|
|
267
|
-
style={
|
|
257
|
+
style={styles.baseCell}
|
|
268
258
|
isFocusable={isFocusable}
|
|
269
259
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
270
260
|
>
|
|
@@ -5,6 +5,8 @@ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/
|
|
|
5
5
|
|
|
6
6
|
import { useCellState } from "../MasterCell/utils";
|
|
7
7
|
import { FocusableGroup } from "../FocusableGroup";
|
|
8
|
+
import { CellWrapper } from "./CellWrapper";
|
|
9
|
+
import { styles } from "./styles";
|
|
8
10
|
|
|
9
11
|
type Props = {
|
|
10
12
|
item: ZappEntry;
|
|
@@ -40,7 +42,7 @@ export function CellWithFocusable(props: Props) {
|
|
|
40
42
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
41
43
|
|
|
42
44
|
const state = useCellState({
|
|
43
|
-
|
|
45
|
+
item,
|
|
44
46
|
behavior,
|
|
45
47
|
focused: isFocused || toBooleanWithDefaultFalse(focused),
|
|
46
48
|
});
|
|
@@ -88,19 +90,21 @@ export function CellWithFocusable(props: Props) {
|
|
|
88
90
|
onBlur={onGroupBlur}
|
|
89
91
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
90
92
|
>
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
93
|
+
<CellWrapper style={styles.cellWrapper}>
|
|
94
|
+
<CellRenderer
|
|
95
|
+
testID={"cell-with-focusable-cell-renderer"}
|
|
96
|
+
item={item}
|
|
97
|
+
groupId={`focusable-cell-wrapper-${id}`}
|
|
98
|
+
onToggleFocus={handleToggleFocus}
|
|
99
|
+
state={state}
|
|
100
|
+
prefixId={id}
|
|
101
|
+
focusedButtonId={focusedButtonId}
|
|
102
|
+
preferredFocus={true}
|
|
103
|
+
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
104
|
+
isFocusable={isFocusable}
|
|
105
|
+
focused={focused}
|
|
106
|
+
/>
|
|
107
|
+
</CellWrapper>
|
|
104
108
|
</FocusableGroup>
|
|
105
109
|
);
|
|
106
110
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
|
|
3
|
+
export const styles = StyleSheet.create({
|
|
4
|
+
cellWrapper: {
|
|
5
|
+
flex: 0,
|
|
6
|
+
height: "100%",
|
|
7
|
+
},
|
|
8
|
+
baseCell: {
|
|
9
|
+
height: "100%",
|
|
10
|
+
display: "flex",
|
|
11
|
+
flex: 1,
|
|
12
|
+
},
|
|
13
|
+
touchableCell: {
|
|
14
|
+
flex: 1,
|
|
15
|
+
height: "100%",
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -105,6 +105,11 @@ const defaultProps = {
|
|
|
105
105
|
alignItems: "center",
|
|
106
106
|
justifyContent: "center",
|
|
107
107
|
},
|
|
108
|
+
focusedButton: {
|
|
109
|
+
backgroundColor: "#3a3a3a",
|
|
110
|
+
borderColor: "#ffffff",
|
|
111
|
+
borderWidth: 2,
|
|
112
|
+
},
|
|
108
113
|
buttonText: {
|
|
109
114
|
fontFamily: platformSelect({
|
|
110
115
|
ios: "SFProText-Medium",
|
|
@@ -116,6 +121,9 @@ const defaultProps = {
|
|
|
116
121
|
color: "rgba(255, 255, 255, 1)",
|
|
117
122
|
textTransform: "uppercase",
|
|
118
123
|
},
|
|
124
|
+
focusedText: {
|
|
125
|
+
color: "#ffffff",
|
|
126
|
+
},
|
|
119
127
|
},
|
|
120
128
|
};
|
|
121
129
|
|
|
@@ -23,7 +23,7 @@ export function FocusableCell(props: Props) {
|
|
|
23
23
|
behavior,
|
|
24
24
|
} = props;
|
|
25
25
|
|
|
26
|
-
const state = useCellState({
|
|
26
|
+
const state = useCellState({ item, behavior, focused });
|
|
27
27
|
|
|
28
28
|
React.useEffect(() => {
|
|
29
29
|
if (focused && scrollTo && !isAndroid) {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
-
import { ViewStyle } from "react-native";
|
|
4
3
|
import {
|
|
5
4
|
findPluginByType,
|
|
6
5
|
findPluginByIdentifier,
|
|
7
6
|
} from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
8
|
-
import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
|
|
9
7
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
10
|
-
import {
|
|
11
|
-
|
|
8
|
+
import {
|
|
9
|
+
useDimensions,
|
|
10
|
+
useNavigation,
|
|
11
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
12
|
|
|
13
13
|
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
14
14
|
import { PlayerContainer } from "../PlayerContainer";
|
|
15
|
+
import { useModalSize } from "../VideoModal/hooks";
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
item: ZappEntry;
|
|
@@ -78,12 +79,6 @@ const getPlayer = (
|
|
|
78
79
|
return getPlayerWithModuleProperties(PlayerModule);
|
|
79
80
|
};
|
|
80
81
|
|
|
81
|
-
const dimensionsContext: "window" | "screen" = platformSelect({
|
|
82
|
-
android_tv: "window",
|
|
83
|
-
amazon: "window",
|
|
84
|
-
default: "screen",
|
|
85
|
-
});
|
|
86
|
-
|
|
87
82
|
type PlayableComponent = {
|
|
88
83
|
Component: React.ComponentType<any>;
|
|
89
84
|
};
|
|
@@ -91,16 +86,11 @@ type PlayableComponent = {
|
|
|
91
86
|
export function HandlePlayable({
|
|
92
87
|
item,
|
|
93
88
|
isModal,
|
|
94
|
-
modalHeight,
|
|
95
|
-
modalWidth,
|
|
96
89
|
mode,
|
|
97
90
|
groupId,
|
|
98
91
|
}: Props): React.ReactElement | null {
|
|
99
92
|
const state = usePickFromState();
|
|
100
93
|
|
|
101
|
-
const { width: screenWidth, height: screenHeight } =
|
|
102
|
-
useDimensions(dimensionsContext);
|
|
103
|
-
|
|
104
94
|
const { closeVideoModal } = useNavigation();
|
|
105
95
|
|
|
106
96
|
const [Player, playerModuleProperties] = getPlayer(item, state);
|
|
@@ -118,9 +108,7 @@ export function HandlePlayable({
|
|
|
118
108
|
if (!isModal) {
|
|
119
109
|
closeVideoModal();
|
|
120
110
|
}
|
|
121
|
-
}, []);
|
|
122
111
|
|
|
123
|
-
React.useEffect(() => {
|
|
124
112
|
const castStateHandler = async () => {
|
|
125
113
|
const castState = await CastPlugin?.getCastState();
|
|
126
114
|
setCasting(castState === "Connected");
|
|
@@ -142,23 +130,29 @@ export function HandlePlayable({
|
|
|
142
130
|
}, []);
|
|
143
131
|
|
|
144
132
|
React.useEffect(() => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
setPlayable({ Component: PlayerContainer });
|
|
149
|
-
}
|
|
133
|
+
setPlayable({
|
|
134
|
+
Component: casting ? CastPlugin?.CastHandler : PlayerContainer,
|
|
135
|
+
});
|
|
150
136
|
}, [casting]);
|
|
151
137
|
|
|
152
|
-
const
|
|
138
|
+
const { width: screenWidth, height: screenHeight } = useDimensions("window");
|
|
139
|
+
|
|
140
|
+
const modalSize = useModalSize();
|
|
153
141
|
|
|
154
142
|
const style = React.useMemo(
|
|
155
143
|
() => ({
|
|
156
|
-
width: isModal ?
|
|
157
|
-
height: isModal
|
|
144
|
+
width: isModal ? modalSize.width : mode === "PIP" ? "100%" : screenWidth,
|
|
145
|
+
height: isModal
|
|
146
|
+
? modalSize.height
|
|
147
|
+
: mode === "PIP"
|
|
148
|
+
? "100%"
|
|
149
|
+
: screenHeight,
|
|
158
150
|
}),
|
|
159
|
-
[screenWidth, screenHeight,
|
|
151
|
+
[screenWidth, screenHeight, modalSize, isModal, mode]
|
|
160
152
|
);
|
|
161
153
|
|
|
154
|
+
const Component = playable?.Component;
|
|
155
|
+
|
|
162
156
|
if (Component) {
|
|
163
157
|
return (
|
|
164
158
|
<Component
|
|
@@ -174,5 +168,5 @@ export function HandlePlayable({
|
|
|
174
168
|
);
|
|
175
169
|
}
|
|
176
170
|
|
|
177
|
-
return !isModal ? <BufferAnimation videoStyle={style
|
|
171
|
+
return !isModal ? <BufferAnimation videoStyle={style} /> : null;
|
|
178
172
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Image as RnImage, ImageStyle } from "react-native";
|
|
3
|
-
import
|
|
3
|
+
import { equals, omit } from "ramda";
|
|
4
4
|
|
|
5
5
|
import { useImageSource } from "./hooks";
|
|
6
6
|
|
|
@@ -17,7 +17,7 @@ type Props = Record<string, any> & {
|
|
|
17
17
|
withDimensions: (source: Source) => Source;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const MemoizedImage = React.memo(RnImage,
|
|
20
|
+
const MemoizedImage = React.memo(RnImage, equals);
|
|
21
21
|
|
|
22
22
|
function Image({
|
|
23
23
|
style,
|
|
@@ -44,11 +44,12 @@ function Image({
|
|
|
44
44
|
|
|
45
45
|
return (
|
|
46
46
|
<MemoizedImage
|
|
47
|
+
key={_source?.uri || "no-image"}
|
|
47
48
|
style={style as ImageStyle}
|
|
48
49
|
onError={React.useCallback(() => setErrorState(true), [])}
|
|
49
50
|
// as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
|
|
50
51
|
source={_source?.uri ? _source : undefined}
|
|
51
|
-
{...
|
|
52
|
+
{...omit(["source"], otherProps)}
|
|
52
53
|
/>
|
|
53
54
|
);
|
|
54
55
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { path } from "ramda";
|
|
3
3
|
|
|
4
4
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
5
5
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
@@ -7,9 +7,13 @@ import { extractAsset } from "./utils";
|
|
|
7
7
|
|
|
8
8
|
type Return = { uri: string } | null;
|
|
9
9
|
|
|
10
|
+
const getSourceContext = path(["source", "context"]);
|
|
11
|
+
const getSourceUri = path(["source", "uri"]);
|
|
12
|
+
const getState = path(["state"]);
|
|
13
|
+
|
|
10
14
|
export const useImageSource = ({ uri, entry, otherProps }): Return => {
|
|
11
|
-
const uriContext =
|
|
12
|
-
const uriState =
|
|
15
|
+
const uriContext = getSourceContext(otherProps);
|
|
16
|
+
const uriState = getState(otherProps);
|
|
13
17
|
|
|
14
18
|
const action = useActions(uriContext);
|
|
15
19
|
|
|
@@ -34,7 +38,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
|
|
|
34
38
|
return { uri };
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
const uriFromSource =
|
|
41
|
+
const uriFromSource = getSourceUri(otherProps);
|
|
38
42
|
|
|
39
43
|
if (uriFromSource) {
|
|
40
44
|
return { uri: uriFromSource };
|
|
@@ -56,7 +60,7 @@ const getSource = (uri, showDefault, placeholderImage, otherProps) => {
|
|
|
56
60
|
return { uri };
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
const uriFromSource =
|
|
63
|
+
const uriFromSource = getSourceUri(otherProps);
|
|
60
64
|
|
|
61
65
|
if (uriFromSource) {
|
|
62
66
|
return { uri: uriFromSource };
|
|
@@ -72,8 +76,8 @@ export const useImageSourceWithDefault = ({
|
|
|
72
76
|
placeholderImage,
|
|
73
77
|
otherProps,
|
|
74
78
|
}): Return => {
|
|
75
|
-
const uriContext =
|
|
76
|
-
const uriState =
|
|
79
|
+
const uriContext = getSourceContext(otherProps);
|
|
80
|
+
const uriState = getState(otherProps);
|
|
77
81
|
|
|
78
82
|
const action = useActions(uriContext);
|
|
79
83
|
|
|
@@ -6,6 +6,7 @@ import React, { useEffect } from "react";
|
|
|
6
6
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
7
7
|
import { BehaviorSubject } from "rxjs";
|
|
8
8
|
import { masterCellLogger } from "../logger";
|
|
9
|
+
import get from "lodash/get";
|
|
9
10
|
|
|
10
11
|
const parseContextKey = (key: string): string | null => {
|
|
11
12
|
if (!key?.startsWith("@{ctx/")) return null;
|
|
@@ -72,11 +73,13 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
72
73
|
// We cant use async in this function (its inside render),
|
|
73
74
|
// so we rely on useBehaviorUpdate to update current value and trigger re-render
|
|
74
75
|
export const isCellSelected = (
|
|
75
|
-
|
|
76
|
+
item: ZappEntry,
|
|
76
77
|
behavior?: Behavior
|
|
77
78
|
): boolean => {
|
|
78
79
|
if (!behavior) return false;
|
|
79
80
|
|
|
81
|
+
const id = behavior.selector ? get(item, behavior.selector) : item.id;
|
|
82
|
+
|
|
80
83
|
if (behavior.selection_source === "now_playing") {
|
|
81
84
|
const player = playerManager.getActivePlayer();
|
|
82
85
|
|
|
@@ -190,24 +190,24 @@ export const getFocusedButtonId = (focusable) => {
|
|
|
190
190
|
});
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
export const isSelected = (
|
|
194
|
-
return isCellSelected(
|
|
193
|
+
export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
|
|
194
|
+
return isCellSelected(item, behavior);
|
|
195
195
|
};
|
|
196
196
|
|
|
197
197
|
export const useCellState = ({
|
|
198
|
-
|
|
198
|
+
item,
|
|
199
199
|
behavior,
|
|
200
200
|
focused,
|
|
201
201
|
}: {
|
|
202
|
-
|
|
202
|
+
item: ZappEntry;
|
|
203
203
|
behavior: Behavior;
|
|
204
204
|
focused: boolean;
|
|
205
205
|
}): CellState => {
|
|
206
206
|
const lastUpdate = useBehaviorUpdate(behavior);
|
|
207
207
|
|
|
208
208
|
const _isSelected = useMemo(
|
|
209
|
-
() => isSelected(
|
|
210
|
-
[behavior,
|
|
209
|
+
() => isSelected(item, behavior),
|
|
210
|
+
[behavior, item, lastUpdate]
|
|
211
211
|
);
|
|
212
212
|
|
|
213
213
|
return getCellState({ focused, selected: _isSelected });
|
|
@@ -10,13 +10,11 @@ import { Button } from "./Button";
|
|
|
10
10
|
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
11
|
import { ItemProps } from "./Button/Item";
|
|
12
12
|
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
13
|
-
import {
|
|
14
|
-
defaultItemIconProps,
|
|
15
|
-
defaultItemLabelProps,
|
|
16
|
-
defaultItemProps,
|
|
17
|
-
} from "./utils";
|
|
13
|
+
import { getItemIconProps, getItemLabelProps, getItemProps } from "./utils";
|
|
18
14
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
19
15
|
|
|
16
|
+
import type { PluginConfiguration } from "./";
|
|
17
|
+
|
|
20
18
|
import { ModalHeader } from "./Header";
|
|
21
19
|
|
|
22
20
|
type ModalComponentProps = {
|
|
@@ -30,6 +28,20 @@ type ModalComponentProps = {
|
|
|
30
28
|
maxHeight?: number;
|
|
31
29
|
dismiss: () => void;
|
|
32
30
|
buttonComponent?: React.ComponentType;
|
|
31
|
+
iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
|
|
32
|
+
itemProps?:
|
|
33
|
+
| ItemProps
|
|
34
|
+
| ((theme: PluginConfiguration, width: number) => ItemProps);
|
|
35
|
+
labelProps?:
|
|
36
|
+
| ItemLabelProps
|
|
37
|
+
| ((theme: PluginConfiguration, width: number) => ItemLabelProps);
|
|
38
|
+
getSelectedItemIcon: (
|
|
39
|
+
theme: PluginConfiguration
|
|
40
|
+
) => ItemIconProps["asset"] | null;
|
|
41
|
+
getDefaultItemIcon: (
|
|
42
|
+
theme: PluginConfiguration
|
|
43
|
+
) => ItemIconProps["asset"] | null;
|
|
44
|
+
iconPlacement?: "left" | "right";
|
|
33
45
|
};
|
|
34
46
|
|
|
35
47
|
export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
@@ -43,6 +55,10 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
43
55
|
summary,
|
|
44
56
|
title,
|
|
45
57
|
buttonComponent: ButtonComponent = Button,
|
|
58
|
+
getSelectedItemIcon = (theme) =>
|
|
59
|
+
theme.modal_bottom_sheet_item_selected_icon,
|
|
60
|
+
getDefaultItemIcon = () => null,
|
|
61
|
+
iconPlacement,
|
|
46
62
|
} = props;
|
|
47
63
|
|
|
48
64
|
const [headerHeight, setHeaderHeight] = useState(0);
|
|
@@ -64,21 +80,24 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
64
80
|
}, [currentRoute]);
|
|
65
81
|
|
|
66
82
|
const iconBaseProps = useMemo<ItemIconProps>(() => {
|
|
67
|
-
return
|
|
68
|
-
}, [theme]);
|
|
83
|
+
return getItemIconProps(theme, props.iconProps);
|
|
84
|
+
}, [theme, props.iconProps]);
|
|
69
85
|
|
|
70
86
|
const itemBaseProps = useMemo<ItemProps>(() => {
|
|
71
|
-
return
|
|
72
|
-
}, [theme, props.width]);
|
|
87
|
+
return getItemProps(theme, props.width, props.itemProps);
|
|
88
|
+
}, [theme, props.width, props.itemProps]);
|
|
73
89
|
|
|
74
90
|
const labelBaseProps = useMemo<ItemLabelProps>(() => {
|
|
75
|
-
return
|
|
76
|
-
}, [theme, props.width]);
|
|
91
|
+
return getItemLabelProps(theme, props.width, props.labelProps);
|
|
92
|
+
}, [theme, props.width, props.labelProps]);
|
|
77
93
|
|
|
78
|
-
const handlePress = (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
94
|
+
const handlePress = useCallback(
|
|
95
|
+
(item: any) => {
|
|
96
|
+
onPress(item);
|
|
97
|
+
dismiss();
|
|
98
|
+
},
|
|
99
|
+
[onPress, dismiss]
|
|
100
|
+
);
|
|
82
101
|
|
|
83
102
|
return (
|
|
84
103
|
<View
|
|
@@ -110,9 +129,13 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
110
129
|
selectedItem={current_selection}
|
|
111
130
|
item={item}
|
|
112
131
|
onPress={handlePress}
|
|
132
|
+
label={theme[item?.label] ?? item?.label}
|
|
113
133
|
iconBaseProps={iconBaseProps}
|
|
114
134
|
itemBaseProps={itemBaseProps}
|
|
115
135
|
labelBaseProps={labelBaseProps}
|
|
136
|
+
selectedItemIcon={getSelectedItemIcon(theme)}
|
|
137
|
+
defaultItemIcon={getDefaultItemIcon(theme)}
|
|
138
|
+
iconPlacement={iconPlacement}
|
|
116
139
|
/>
|
|
117
140
|
))}
|
|
118
141
|
</ScrollView>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
2
|
|
|
3
3
|
export const defaultSelectedAsset: string =
|
|
4
|
-
"data:image/png;base64,
|
|
4
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAA+0lEQVR4nO3a3QnCQBBF4ZRiSXZgKVqKnVnCQBpQwb0QJA752ZjszPlg3/JwOU8b2K4DAAAAAAAAkIOZnczsvPeOQypxHmb27Pv+sveeQxnG0SFSMRaHSIUXJ32kKXHKue+99e+I4yCOgzgO4jiI4yCOgzgO4jiajfMedd366t50nK3/b0LE2SpSqDi1I4WMUytSs3G6z/jbhOGLIzUdR7aKFCKO1I4UKo7UihQyjqyNFDqOLI2UIo7MjZQqjkyNVL7LFUdmRMoXRypEihtHVkSKH0cWRMoTR2ZEyhdHJkTKG0ecSMSRkUjE+TaIRJxfeFQJAAAAAAAANOwFT0Mt2UgcaMoAAAAASUVORK5CYII=";
|
|
@@ -3,7 +3,6 @@ import { StyleSheet, TouchableOpacity, View } from "react-native";
|
|
|
3
3
|
import { Item, ItemProps } from "./Item";
|
|
4
4
|
import { ItemIcon, ItemIconProps } from "./ItemIcon";
|
|
5
5
|
import { ItemLabel, ItemLabelProps } from "./ItemLabel";
|
|
6
|
-
import * as assets from "./assets";
|
|
7
6
|
import { defaultSelectedAsset } from "./assets";
|
|
8
7
|
|
|
9
8
|
type ButtonProps = {
|
|
@@ -17,6 +16,9 @@ type ButtonProps = {
|
|
|
17
16
|
labelBaseProps?: ItemLabelProps;
|
|
18
17
|
disabled?: boolean;
|
|
19
18
|
label?: string | Record<string, string>;
|
|
19
|
+
iconPlacement?: "left" | "right";
|
|
20
|
+
selectedItemIcon?: ItemIconProps["asset"];
|
|
21
|
+
defaultItemIcon?: ItemIconProps["asset"];
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const styles = StyleSheet.create({
|
|
@@ -33,52 +35,32 @@ export function Button({
|
|
|
33
35
|
configuration,
|
|
34
36
|
width,
|
|
35
37
|
iconBaseProps,
|
|
36
|
-
itemBaseProps,
|
|
38
|
+
itemBaseProps: itemProps,
|
|
37
39
|
labelBaseProps,
|
|
38
40
|
label,
|
|
41
|
+
iconPlacement = "left",
|
|
42
|
+
defaultItemIcon,
|
|
43
|
+
selectedItemIcon,
|
|
39
44
|
disabled = false,
|
|
40
45
|
}: ButtonProps) {
|
|
41
46
|
const [focused, setFocused] = useState(false);
|
|
42
47
|
|
|
43
|
-
const selected =
|
|
44
|
-
() => selectedItem && item.value === selectedItem?.value,
|
|
45
|
-
[selectedItem, selectedItem]
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const itemProps = useMemo<ItemProps>(
|
|
49
|
-
() => ({
|
|
50
|
-
...itemBaseProps,
|
|
51
|
-
width,
|
|
52
|
-
}),
|
|
53
|
-
[configuration, width]
|
|
54
|
-
);
|
|
48
|
+
const selected = selectedItem && item.value === selectedItem?.value;
|
|
55
49
|
|
|
56
|
-
const
|
|
57
|
-
() =>
|
|
58
|
-
|
|
59
|
-
asset: configuration[item.asset] ?? assets[item.asset] ?? item.asset,
|
|
60
|
-
}),
|
|
61
|
-
[configuration, item.asset]
|
|
50
|
+
const itemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
|
|
51
|
+
() => configuration[item.asset] ?? item.asset ?? defaultItemIcon,
|
|
52
|
+
[item.asset, defaultItemIcon]
|
|
62
53
|
);
|
|
63
54
|
|
|
64
|
-
const
|
|
65
|
-
() =>
|
|
66
|
-
|
|
67
|
-
asset:
|
|
68
|
-
configuration["modal_bottom_sheet_item_selected_icon"] ||
|
|
69
|
-
defaultSelectedAsset,
|
|
70
|
-
marginRight: 10,
|
|
71
|
-
}),
|
|
72
|
-
[configuration]
|
|
55
|
+
const selectedItemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
|
|
56
|
+
() => selectedItemIcon || defaultSelectedAsset,
|
|
57
|
+
[selectedItemIcon]
|
|
73
58
|
);
|
|
74
59
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
...
|
|
78
|
-
|
|
79
|
-
}),
|
|
80
|
-
[configuration, item?.label]
|
|
81
|
-
);
|
|
60
|
+
const renderItemIcon =
|
|
61
|
+
itemIconPropsAssets && itemIconPropsAssets.length > 0 ? (
|
|
62
|
+
<ItemIcon {...iconBaseProps} asset={itemIconPropsAssets} />
|
|
63
|
+
) : null;
|
|
82
64
|
|
|
83
65
|
if (disabled) return null;
|
|
84
66
|
|
|
@@ -92,18 +74,23 @@ export function Button({
|
|
|
92
74
|
>
|
|
93
75
|
<Item {...itemProps} focused={focused} selected={selected}>
|
|
94
76
|
<View style={styles.label_icon_container}>
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{itemLabelProps.label ? (
|
|
77
|
+
{iconPlacement === "left" && renderItemIcon}
|
|
78
|
+
|
|
79
|
+
{label ? (
|
|
99
80
|
<ItemLabel
|
|
100
|
-
{...
|
|
81
|
+
{...labelBaseProps}
|
|
82
|
+
label={label ?? null}
|
|
101
83
|
focused={focused}
|
|
102
84
|
selected={selected}
|
|
103
85
|
/>
|
|
104
86
|
) : null}
|
|
105
87
|
</View>
|
|
106
|
-
|
|
88
|
+
|
|
89
|
+
{selected ? (
|
|
90
|
+
<ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
|
|
91
|
+
) : (
|
|
92
|
+
iconPlacement === "right" && renderItemIcon
|
|
93
|
+
)}
|
|
107
94
|
</Item>
|
|
108
95
|
</TouchableOpacity>
|
|
109
96
|
</View>
|