@applicaster/zapp-react-native-ui-components 13.0.0-alpha.1291347678 → 13.0.0-alpha.1313712178

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.
Files changed (69) hide show
  1. package/Components/AudioPlayer/AudioPlayer.tsx +7 -4
  2. package/Components/AudioPlayer/helpers.tsx +1 -1
  3. package/Components/Cell/Cell.tsx +3 -13
  4. package/Components/Cell/CellWithFocusable.tsx +21 -15
  5. package/Components/Cell/CellWrapper.tsx +18 -0
  6. package/Components/Cell/styles.ts +17 -0
  7. package/Components/CellRendererResolver/index.ts +2 -1
  8. package/Components/ErrorScreen/index.tsx +8 -0
  9. package/Components/FocusableCell/index.tsx +1 -1
  10. package/Components/FocusableGroup/FocusableTvOS.tsx +3 -6
  11. package/Components/FocusableGroup/index.tsx +0 -1
  12. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
  13. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +4 -2
  14. package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
  15. package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
  16. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  17. package/Components/Layout/TV/ScreenContainer.tsx +0 -1
  18. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  19. package/Components/Layout/TV/__tests__/index.test.tsx +8 -2
  20. package/Components/Layout/TV/index.tsx +6 -20
  21. package/Components/Layout/TV/index.web.tsx +4 -1
  22. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +4 -3
  23. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  24. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  25. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  26. package/Components/MasterCell/utils/behaviorProvider.ts +4 -1
  27. package/Components/MasterCell/utils/index.ts +6 -6
  28. package/Components/ModalComponent/BottomSheetModalContent.tsx +59 -43
  29. package/Components/ModalComponent/Button/Item.tsx +6 -5
  30. package/Components/ModalComponent/Button/assets.ts +1 -1
  31. package/Components/ModalComponent/Button/index.tsx +45 -62
  32. package/Components/ModalComponent/Header/index.tsx +9 -8
  33. package/Components/ModalComponent/utils.ts +55 -7
  34. package/Components/OfflineHandler/utils/index.ts +1 -1
  35. package/Components/PlayerContainer/PlayerContainer.tsx +25 -2
  36. package/Components/PlayerImageBackground/index.tsx +1 -1
  37. package/Components/River/ComponentsMap/ComponentsMap.tsx +14 -3
  38. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +3 -3
  39. package/Components/River/RiverItem.tsx +7 -4
  40. package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
  41. package/Components/Screen/TV/index.web.tsx +5 -6
  42. package/Components/Screen/__tests__/Screen.test.tsx +22 -14
  43. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -2
  44. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  45. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  46. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +35 -19
  47. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +3 -3
  48. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +38 -14
  49. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +10 -3
  50. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  51. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  52. package/Components/VideoModal/ModalAnimation/index.ts +2 -0
  53. package/Components/VideoModal/ModalAnimation/utils.ts +30 -0
  54. package/Components/VideoModal/PlayerDetails.tsx +9 -4
  55. package/Components/VideoModal/PlayerWrapper.tsx +35 -22
  56. package/Components/VideoModal/VideoModal.tsx +19 -4
  57. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  58. package/Components/VideoModal/utils.ts +3 -4
  59. package/Components/ZappUIComponent/index.tsx +4 -4
  60. package/Decorators/RiverResolver/index.tsx +5 -7
  61. package/Decorators/ZappPipesDataConnector/index.tsx +2 -1
  62. package/package.json +5 -6
  63. package/.babelrc +0 -8
  64. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  65. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  66. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  67. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  68. package/Components/Cell/CellStyles/colors.js +0 -40
  69. package/Components/Cell/CellStyles/index.js +0 -15
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { Image as RnImage, ImageStyle } from "react-native";
3
- import * as R from "ramda";
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, R.equals);
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
- {...R.omit(["source"], otherProps)}
52
+ {...omit(["source"], otherProps)}
52
53
  />
53
54
  );
54
55
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
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 = R.path(["source", "context"], otherProps);
12
- const uriState = R.path(["state"], otherProps);
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 = R.path(["source", "uri"], otherProps);
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 = R.path(["source", "uri"], otherProps);
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 = R.path(["source", "context"], otherProps);
76
- const uriState = R.path(["state"], otherProps);
79
+ const uriContext = getSourceContext(otherProps);
80
+ const uriState = getState(otherProps);
77
81
 
78
82
  const action = useActions(uriContext);
79
83
 
@@ -0,0 +1,3 @@
1
+ export const PREFIX = "tv_buttons";
2
+
3
+ export const BUTTON_PREFIX = `${PREFIX}_button`;
@@ -1,4 +1,4 @@
1
- import * as R from "ramda";
1
+ import { times } from "@applicaster/zapp-react-native-utils/utils";
2
2
  import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
3
3
 
4
4
  import { Button } from "./Button";
@@ -9,13 +9,14 @@ import {
9
9
  } from "./utils";
10
10
 
11
11
  import { compact } from "@applicaster/zapp-react-native-utils/cellUtils";
12
+ import { PREFIX, BUTTON_PREFIX } from "./const";
12
13
 
13
14
  export {
14
15
  insertButtonsBetweenLabels,
15
16
  insertButtonsBetweenLabelContainers,
16
17
  } from "./utils";
17
18
 
18
- const PREFIX = "tv_buttons";
19
+ const buttonId = (index: number) => `${BUTTON_PREFIX}_${index}`;
19
20
 
20
21
  type Props = {
21
22
  value: Function;
@@ -42,7 +43,6 @@ export const TvActionButtons = ({
42
43
  return null;
43
44
  }
44
45
 
45
- const prefix1Button = `${PREFIX}_button_1`;
46
46
  const independentStyles = value(`${PREFIX}_container_independent_styles`);
47
47
 
48
48
  return {
@@ -73,11 +73,11 @@ export const TvActionButtons = ({
73
73
  buttonsCount,
74
74
  },
75
75
  elements: compact(
76
- R.times((index) => {
77
- const prefixSpecificButton = `${PREFIX}_button_${index + 1}`;
76
+ times((index) => {
77
+ const prefixSpecificButton = buttonId(index + 1);
78
78
 
79
79
  return Button({
80
- prefix: independentStyles ? prefixSpecificButton : prefix1Button,
80
+ prefix: independentStyles ? prefixSpecificButton : buttonId(1),
81
81
  value,
82
82
  platformValue,
83
83
  pluginIdentifier: getPluginIdentifier(configuration, PREFIX, index),
@@ -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
- id: string | number,
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 = (id: string | number, behavior?: Behavior) => {
194
- return isCellSelected(id, behavior);
193
+ export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
194
+ return isCellSelected(item, behavior);
195
195
  };
196
196
 
197
197
  export const useCellState = ({
198
- id,
198
+ item,
199
199
  behavior,
200
200
  focused,
201
201
  }: {
202
- id: string | number;
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(id, behavior),
210
- [behavior, id, lastUpdate]
209
+ () => isSelected(item, behavior),
210
+ [behavior, item, lastUpdate]
211
211
  );
212
212
 
213
213
  return getCellState({ focused, selected: _isSelected });
@@ -1,23 +1,16 @@
1
- import React, {
2
- useCallback,
3
- useEffect,
4
- useMemo,
5
- useRef,
6
- useState,
7
- } from "react";
8
- import { View, LayoutChangeEvent, ScrollView } from "react-native";
1
+ import React, { useCallback, useEffect, useMemo, useRef } from "react";
2
+ import { View, ScrollView, StyleSheet, Platform } from "react-native";
9
3
  import { Button } from "./Button";
10
4
  import { ItemIconProps } from "./Button/ItemIcon";
11
5
  import { ItemProps } from "./Button/Item";
12
6
  import { ItemLabelProps } from "./Button/ItemLabel";
13
- import {
14
- defaultItemIconProps,
15
- defaultItemLabelProps,
16
- defaultItemProps,
17
- } from "./utils";
7
+ import { getItemIconProps, getItemLabelProps, getItemProps } from "./utils";
18
8
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
19
9
 
10
+ import type { PluginConfiguration } from "./";
11
+
20
12
  import { ModalHeader } from "./Header";
13
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
21
14
 
22
15
  type ModalComponentProps = {
23
16
  items: any[];
@@ -30,32 +23,48 @@ type ModalComponentProps = {
30
23
  maxHeight?: number;
31
24
  dismiss: () => void;
32
25
  buttonComponent?: React.ComponentType;
26
+ iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
27
+ itemProps?:
28
+ | ItemProps
29
+ | ((theme: PluginConfiguration, width: number) => ItemProps);
30
+ labelProps?:
31
+ | ItemLabelProps
32
+ | ((theme: PluginConfiguration, width: number) => ItemLabelProps);
33
+ getSelectedItemIcon: (
34
+ theme: PluginConfiguration
35
+ ) => ItemIconProps["asset"] | null;
36
+ getDefaultItemIcon: (
37
+ theme: PluginConfiguration
38
+ ) => ItemIconProps["asset"] | null;
39
+ iconPlacement?: "left" | "right";
33
40
  };
34
41
 
42
+ const styles = StyleSheet.create({
43
+ container: {
44
+ maxHeight: "100%",
45
+ },
46
+ });
47
+
35
48
  export function BottomSheetModalContent(props: ModalComponentProps) {
36
49
  const {
37
50
  items,
38
51
  currentRoute,
39
- maxHeight,
40
52
  current_selection = null,
41
53
  onPress,
42
54
  dismiss,
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
- const [headerHeight, setHeaderHeight] = useState(0);
49
64
  const route = useRef(currentRoute);
50
65
  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
- }, []);
66
+ const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
67
+ const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
59
68
 
60
69
  useEffect(() => {
61
70
  if (currentRoute !== route.current) {
@@ -64,55 +73,62 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
64
73
  }, [currentRoute]);
65
74
 
66
75
  const iconBaseProps = useMemo<ItemIconProps>(() => {
67
- return defaultItemIconProps(theme);
68
- }, [theme]);
76
+ return getItemIconProps(theme, props.iconProps);
77
+ }, [theme, props.iconProps]);
69
78
 
70
79
  const itemBaseProps = useMemo<ItemProps>(() => {
71
- return defaultItemProps(theme, props.width);
72
- }, [theme, props.width]);
80
+ return getItemProps(theme, props.width, props.itemProps);
81
+ }, [theme, props.width, props.itemProps]);
73
82
 
74
83
  const labelBaseProps = useMemo<ItemLabelProps>(() => {
75
- return defaultItemLabelProps(theme, props.width);
76
- }, [theme, props.width]);
84
+ return getItemLabelProps(theme, props.width, props.labelProps);
85
+ }, [theme, props.width, props.labelProps]);
86
+
87
+ const handlePress = useCallback(
88
+ (item: any) => {
89
+ onPress(item);
90
+ dismiss();
91
+ },
92
+ [onPress, dismiss]
93
+ );
77
94
 
78
- const handlePress = (item: any) => {
79
- onPress(item);
80
- dismiss();
81
- };
95
+ const bottomInset = useSafeAreaInsets().bottom;
82
96
 
83
97
  return (
84
98
  <View
85
- style={{
86
- paddingTop: Number(theme.modal_bottom_sheet_padding_top),
87
- }}
99
+ style={[
100
+ styles.container,
101
+ {
102
+ paddingTop: paddingTop,
103
+ },
104
+ ]}
88
105
  >
89
106
  <ModalHeader
90
- width={props.width}
91
107
  dismiss={dismiss}
92
108
  configuration={theme}
93
- onLayout={onHeaderLayout}
94
109
  summary={summary}
95
110
  title={title}
96
111
  />
97
112
  <ScrollView
98
- bounces={false}
99
- style={{ maxHeight: maxContentHeight }}
100
113
  contentContainerStyle={{
101
- paddingBottom: Number(theme.modal_bottom_sheet_padding_bottom),
102
- paddingTop: Number(theme.modal_bottom_sheet_padding_top),
114
+ paddingBottom:
115
+ Platform.OS === "ios" ? paddingBottom + bottomInset : paddingBottom,
103
116
  }}
104
117
  >
105
118
  {items.map((item, index) => (
106
119
  <ButtonComponent
107
120
  key={index}
108
- width={props.width}
109
121
  configuration={theme}
110
122
  selectedItem={current_selection}
111
123
  item={item}
112
124
  onPress={handlePress}
125
+ label={theme[item?.label] ?? item?.label}
113
126
  iconBaseProps={iconBaseProps}
114
127
  itemBaseProps={itemBaseProps}
115
128
  labelBaseProps={labelBaseProps}
129
+ selectedItemIcon={getSelectedItemIcon(theme)}
130
+ defaultItemIcon={getDefaultItemIcon(theme)}
131
+ iconPlacement={iconPlacement}
116
132
  />
117
133
  ))}
118
134
  </ScrollView>
@@ -5,7 +5,7 @@ export type ItemProps = {
5
5
  backgroundColor: string;
6
6
  focusedBackgroundColor: string;
7
7
  selectedBackgroundColor?: string;
8
- focusectedBackgroundColor?: string;
8
+ focusedSelectedBackgroundColor?: string;
9
9
  borderRadius: number;
10
10
  marginBottom: number;
11
11
  marginLeft: number;
@@ -15,6 +15,7 @@ export type ItemProps = {
15
15
  paddingBottom: number;
16
16
  paddingRight: number;
17
17
  paddingLeft: number;
18
+ maxWidth: number;
18
19
  focused?: boolean;
19
20
  selected?: boolean;
20
21
  children?: ReactChild[];
@@ -33,11 +34,11 @@ function getBackgroundColor({
33
34
  backgroundColor,
34
35
  focusedBackgroundColor,
35
36
  selectedBackgroundColor,
36
- focusectedBackgroundColor,
37
+ focusedSelectedBackgroundColor,
37
38
  }) {
38
39
  switch (true) {
39
40
  case selected && focused:
40
- return focusectedBackgroundColor;
41
+ return focusedSelectedBackgroundColor;
41
42
  case selected && !focused:
42
43
  return selectedBackgroundColor;
43
44
  case !selected && focused:
@@ -51,7 +52,7 @@ export function Item(props: ItemProps) {
51
52
  const {
52
53
  backgroundColor,
53
54
  focusedBackgroundColor,
54
- focusectedBackgroundColor,
55
+ focusedSelectedBackgroundColor,
55
56
  selectedBackgroundColor,
56
57
  children,
57
58
  focused,
@@ -68,7 +69,7 @@ export function Item(props: ItemProps) {
68
69
  backgroundColor: getBackgroundColor({
69
70
  selected,
70
71
  focused,
71
- focusectedBackgroundColor,
72
+ focusedSelectedBackgroundColor,
72
73
  focusedBackgroundColor,
73
74
  selectedBackgroundColor,
74
75
  backgroundColor,
@@ -1,4 +1,4 @@
1
1
  /* eslint-disable max-len */
2
2
 
3
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==";
4
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAA+0lEQVR4nO3a3QnCQBBF4ZRiSXZgKVqKnVnCQBpQwb0QJA752ZjszPlg3/JwOU8b2K4DAAAAAAAAkIOZnczsvPeOQypxHmb27Pv+sveeQxnG0SFSMRaHSIUXJ32kKXHKue+99e+I4yCOgzgO4jiI4yCOgzgO4jiajfMedd366t50nK3/b0LE2SpSqDi1I4WMUytSs3G6z/jbhOGLIzUdR7aKFCKO1I4UKo7UihQyjqyNFDqOLI2UIo7MjZQqjkyNVL7LFUdmRMoXRypEihtHVkSKH0cWRMoTR2ZEyhdHJkTKG0ecSMSRkUjE+TaIRJxfeFQJAAAAAAAANOwFT0Mt2UgcaMoAAAAASUVORK5CYII=";
@@ -3,12 +3,10 @@ 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 = {
10
9
  configuration: any;
11
- width: number;
12
10
  selectedItem?: any;
13
11
  item: any; // Adjust type as needed
14
12
  onPress: (item: any) => void; // Adjust type as needed
@@ -17,6 +15,9 @@ type ButtonProps = {
17
15
  labelBaseProps?: ItemLabelProps;
18
16
  disabled?: boolean;
19
17
  label?: string | Record<string, string>;
18
+ iconPlacement?: "left" | "right";
19
+ selectedItemIcon?: ItemIconProps["asset"];
20
+ defaultItemIcon?: ItemIconProps["asset"];
20
21
  };
21
22
 
22
23
  const styles = StyleSheet.create({
@@ -31,81 +32,63 @@ export function Button({
31
32
  item,
32
33
  onPress,
33
34
  configuration,
34
- width,
35
35
  iconBaseProps,
36
- itemBaseProps,
36
+ itemBaseProps: itemProps,
37
37
  labelBaseProps,
38
38
  label,
39
+ iconPlacement = "left",
40
+ defaultItemIcon,
41
+ selectedItemIcon,
39
42
  disabled = false,
40
43
  }: ButtonProps) {
41
44
  const [focused, setFocused] = useState(false);
42
45
 
43
- const selected = useMemo(
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
- );
46
+ const selected = selectedItem && item.value === selectedItem?.value;
55
47
 
56
- const itemIconProps = useMemo<ItemIconProps>(
57
- () => ({
58
- ...iconBaseProps,
59
- asset: configuration[item.asset] ?? assets[item.asset] ?? item.asset,
60
- }),
61
- [configuration, item.asset]
48
+ const itemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
49
+ () => configuration[item.asset] ?? item.asset ?? defaultItemIcon,
50
+ [item.asset, defaultItemIcon]
62
51
  );
63
52
 
64
- const selectedItemIconProps = useMemo<ItemIconProps>(
65
- () => ({
66
- ...iconBaseProps,
67
- asset:
68
- configuration["modal_bottom_sheet_item_selected_icon"] ||
69
- defaultSelectedAsset,
70
- marginRight: 10,
71
- }),
72
- [configuration]
53
+ const selectedItemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
54
+ () => selectedItemIcon || defaultSelectedAsset,
55
+ [selectedItemIcon]
73
56
  );
74
57
 
75
- const itemLabelProps = useMemo<ItemLabelProps>(
76
- () => ({
77
- ...labelBaseProps,
78
- label: label ?? configuration[item?.label] ?? item?.label ?? null,
79
- }),
80
- [configuration, item?.label]
81
- );
58
+ const renderItemIcon =
59
+ itemIconPropsAssets && itemIconPropsAssets.length > 0 ? (
60
+ <ItemIcon {...iconBaseProps} asset={itemIconPropsAssets} />
61
+ ) : null;
82
62
 
83
63
  if (disabled) return null;
84
64
 
85
65
  return (
86
- <View style={{ maxWidth: width }}>
87
- <TouchableOpacity
88
- activeOpacity={1}
89
- onPress={() => onPress(item)}
90
- onPressIn={() => setFocused(true)}
91
- onPressOut={() => setFocused(false)}
92
- >
93
- <Item {...itemProps} focused={focused} selected={selected}>
94
- <View style={styles.label_icon_container}>
95
- {itemIconProps.asset && itemIconProps.asset.length > 0 ? (
96
- <ItemIcon {...itemIconProps} />
97
- ) : null}
98
- {itemLabelProps.label ? (
99
- <ItemLabel
100
- {...itemLabelProps}
101
- focused={focused}
102
- selected={selected}
103
- />
104
- ) : null}
105
- </View>
106
- {selected ? <ItemIcon {...selectedItemIconProps} /> : null}
107
- </Item>
108
- </TouchableOpacity>
109
- </View>
66
+ <TouchableOpacity
67
+ activeOpacity={1}
68
+ onPress={() => onPress(item)}
69
+ onPressIn={() => setFocused(true)}
70
+ onPressOut={() => setFocused(false)}
71
+ >
72
+ <Item {...itemProps} focused={focused} selected={selected}>
73
+ <View style={styles.label_icon_container}>
74
+ {iconPlacement === "left" && renderItemIcon}
75
+
76
+ {label ? (
77
+ <ItemLabel
78
+ {...labelBaseProps}
79
+ label={label ?? null}
80
+ focused={focused}
81
+ selected={selected}
82
+ />
83
+ ) : null}
84
+ </View>
85
+
86
+ {selected ? (
87
+ <ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
88
+ ) : (
89
+ iconPlacement === "right" && renderItemIcon
90
+ )}
91
+ </Item>
92
+ </TouchableOpacity>
110
93
  );
111
94
  }
@@ -8,13 +8,18 @@ import { PluginConfiguration } from "../index";
8
8
  type Props = {
9
9
  dismiss: () => void;
10
10
  configuration: PluginConfiguration;
11
- width: number;
12
11
  onLayout?: (event: LayoutChangeEvent) => void;
13
12
  summary?: string;
14
13
  title?: string;
15
14
  };
16
15
 
17
16
  const styles = StyleSheet.create({
17
+ noFlex: {
18
+ flex: 0,
19
+ },
20
+ flex: {
21
+ flex: 1,
22
+ },
18
23
  container: {
19
24
  flexDirection: "row",
20
25
  alignItems: "center",
@@ -22,7 +27,7 @@ const styles = StyleSheet.create({
22
27
  });
23
28
 
24
29
  export function ModalHeader(props: Props) {
25
- const { configuration, dismiss, width, onLayout, summary, title } = props;
30
+ const { configuration, dismiss, onLayout, summary, title } = props;
26
31
 
27
32
  const closeButtonProps = useMemo<CloseButtonProps>(
28
33
  () => ({
@@ -55,15 +60,11 @@ export function ModalHeader(props: Props) {
55
60
 
56
61
  return (
57
62
  <View onLayout={onLayout} style={styles.container}>
58
- <View
59
- style={{
60
- width: width - buttonsContainerWidth,
61
- }}
62
- >
63
+ <View style={styles.flex}>
63
64
  {title ? <Title {...titleProps} /> : null}
64
65
  {summary ? <Title {...summaryProps} /> : null}
65
66
  </View>
66
- <View style={{ width: buttonsContainerWidth }}>
67
+ <View style={[styles.noFlex, { width: buttonsContainerWidth }]}>
67
68
  <CloseButton {...closeButtonProps} />
68
69
  </View>
69
70
  </View>