@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4201443043 → 12.0.0-alpha.4220424021

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 (74) hide show
  1. package/Components/BaseFocusable/index.tsx +2 -2
  2. package/Components/Cell/Cell.tsx +26 -5
  3. package/Components/Cell/CellWithFocusable.tsx +6 -4
  4. package/Components/Cell/TvOSCellComponent.tsx +3 -7
  5. package/Components/Focusable/Focusable.tsx +6 -1
  6. package/Components/FocusableGroup/index.tsx +10 -2
  7. package/Components/FreezeWithCallback/Freeze.tsx +31 -0
  8. package/Components/FreezeWithCallback/LICENSE +21 -0
  9. package/Components/FreezeWithCallback/Suspender.tsx +17 -0
  10. package/Components/FreezeWithCallback/__tests__/index.test.tsx +170 -0
  11. package/Components/FreezeWithCallback/index.tsx +3 -0
  12. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  13. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  14. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  15. package/Components/Layout/TV/__tests__/index.test.tsx +3 -2
  16. package/Components/Layout/TV/index.tsx +52 -9
  17. package/Components/Layout/TV/index.web.tsx +33 -0
  18. package/Components/Layout/index.tsx +15 -11
  19. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -1
  20. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +86 -116
  21. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  22. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +71 -0
  23. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +20 -0
  24. package/Components/MasterCell/DefaultComponents/index.ts +2 -0
  25. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +6 -1
  26. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +7 -1
  27. package/Components/MasterCell/dataAdapter.ts +21 -7
  28. package/Components/MasterCell/index.tsx +5 -3
  29. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  30. package/Components/MasterCell/utils/index.ts +17 -30
  31. package/Components/Navigator/StackNavigator.tsx +14 -5
  32. package/Components/PlayerContainer/PlayerContainer.tsx +2 -0
  33. package/Components/Screen/TV/hooks/index.ts +0 -2
  34. package/Components/Screen/TV/index.web.tsx +40 -41
  35. package/Components/Screen/__tests__/Screen.test.tsx +3 -49
  36. package/Components/Screen/index.tsx +55 -76
  37. package/Components/Screen/navigationHandler.ts +6 -3
  38. package/Components/Screen/orientationHandler.ts +18 -7
  39. package/Components/Screen/utils.ts +16 -0
  40. package/Components/ScreenResolver/index.tsx +6 -11
  41. package/Components/Transitioner/Scene.tsx +20 -12
  42. package/Components/Transitioner/Transitioner.tsx +40 -49
  43. package/Components/Transitioner/__tests__/Scene.test.js +7 -0
  44. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +8 -4
  45. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  46. package/Components/VideoLive/LiveImageManager.ts +10 -0
  47. package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
  48. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +26 -24
  49. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +2 -14
  50. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +79 -45
  51. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +47 -33
  52. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +121 -86
  53. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +32 -4
  54. package/Components/VideoModal/ModalAnimation/utils.ts +7 -4
  55. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  56. package/Components/VideoModal/PlayerWrapper.tsx +10 -10
  57. package/Components/VideoModal/VideoModal.tsx +4 -4
  58. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +80 -14
  59. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  60. package/Components/VideoModal/utils.ts +5 -2
  61. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -3
  62. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
  63. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  64. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  65. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  66. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  67. package/Contexts/FocusableGroupContext/index.ts +7 -0
  68. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  69. package/Contexts/ScreenDataContext/index.tsx +20 -0
  70. package/package.json +5 -5
  71. package/Components/Screen/TV/hooks/useRestoreFocus.ts +0 -22
  72. package/Contexts/ScreenDataContext/index.ts +0 -3
  73. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  74. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
@@ -1,14 +1,27 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { render } from "@testing-library/react-native";
3
+ import { render, waitFor } from "@testing-library/react-native";
4
+ import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
4
5
 
5
6
  import { ScreenLayoutContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenLayoutContext";
6
7
 
7
8
  const navigator_mock = {
8
9
  currentRoute: "/river/A1234",
9
10
  screenData: {},
11
+ activeRiver: {
12
+ navigations: {},
13
+ id: "A1234",
14
+ home: false,
15
+ },
10
16
  };
11
17
 
18
+ jest.mock("@applicaster/zapp-react-native-utils/navigationUtils", () => ({
19
+ ...jest.requireActual<any>(
20
+ "@applicaster/zapp-react-native-utils/navigationUtils"
21
+ ),
22
+ findMenuPlugin: () => ({}),
23
+ }));
24
+
12
25
  jest.mock("@applicaster/quick-brick-core/App/ActionSetters", () => ({
13
26
  useRiverInitialState: () => ({}),
14
27
  }));
@@ -17,13 +30,13 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
17
30
  useNavigation: () => navigator_mock,
18
31
  }));
19
32
 
20
- jest.mock("../../../River/useScreenConfiguration.ts", () => ({
33
+ jest.mock("../../../River/useScreenConfiguration", () => ({
21
34
  useScreenConfiguration: () => ({}),
22
35
  }));
23
36
 
24
- jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
25
- useCurrentScreenData: jest.fn(() => ({})),
26
- }));
37
+ jest.mock(
38
+ "@applicaster/zapp-react-native-utils/reactHooks/screen/useCurrentScreenData"
39
+ );
27
40
 
28
41
  jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
29
42
  useTheme: () => ({}),
@@ -44,42 +57,39 @@ describe("ScreenContainer", () => {
44
57
  const setScreenLayout = () => {};
45
58
 
46
59
  const wrapper = ({ children }) => (
47
- <ScreenLayoutContext.Provider value={{ ...screenLayout, setScreenLayout }}>
48
- {children}
49
- </ScreenLayoutContext.Provider>
60
+ <WrappedWithProviders>
61
+ <ScreenLayoutContext.Provider
62
+ value={{ ...screenLayout, setScreenLayout }}
63
+ >
64
+ <ScreenContainer NavBar={View}>{children}</ScreenContainer>
65
+ </ScreenLayoutContext.Provider>
66
+ </WrappedWithProviders>
50
67
  );
51
68
 
52
69
  const TestComp = () => <View testID="test-component" />;
53
70
 
54
71
  it("renders", () => {
55
- const { toJSON } = render(
56
- <ScreenContainer>
57
- <TestComp />
58
- </ScreenContainer>,
59
- { wrapper }
60
- );
72
+ const { toJSON } = render(<TestComp />, { wrapper });
61
73
 
62
74
  expect(toJSON()).toMatchSnapshot();
63
75
  });
64
76
 
65
- it("renders passed component", () => {
66
- const { getByTestId } = render(
67
- <ScreenContainer>
68
- <TestComp />
69
- </ScreenContainer>,
70
- { wrapper }
71
- );
77
+ it("renders passed component", async () => {
78
+ const { getByTestId } = render(<TestComp />, { wrapper });
79
+
80
+ await waitFor(() => {
81
+ return expect(getByTestId("screen-container")).toBeDefined();
82
+ });
72
83
 
73
84
  expect(getByTestId("test-component")).toBeDefined();
74
85
  });
75
86
 
76
- it("sets margins provided by the theme", () => {
77
- const { getByTestId } = render(
78
- <ScreenContainer>
79
- <TestComp />
80
- </ScreenContainer>,
81
- { wrapper }
82
- );
87
+ it("sets margins provided by the theme", async () => {
88
+ const { getByTestId } = render(<TestComp />, { wrapper });
89
+
90
+ await waitFor(() => {
91
+ return expect(getByTestId("screen-container")).toBeDefined();
92
+ });
83
93
 
84
94
  const screen = getByTestId("screen-container");
85
95
  expect(screen.props.style).toMatchSnapshot();
@@ -1,28 +1,40 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`ScreenContainer renders 1`] = `
4
- <View
4
+ <RNCSafeAreaProvider
5
+ onInsetsChange={[Function]}
5
6
  style={
6
7
  Array [
7
8
  Object {
8
9
  "flex": 1,
9
- "height": "100%",
10
- "width": "100%",
11
- },
12
- Object {
13
- "backgroundColor": "transparent",
14
- "marginBottom": 10,
15
- "paddingBottom": 0,
16
- "paddingTop": 0,
17
10
  },
11
+ undefined,
18
12
  ]
19
13
  }
20
- testID="screen-container"
21
14
  >
22
15
  <View
23
- testID="test-component"
24
- />
25
- </View>
16
+ style={
17
+ Array [
18
+ Object {
19
+ "position": "absolute",
20
+ "top": 0,
21
+ "width": 1920,
22
+ "zIndex": 10,
23
+ },
24
+ Object {
25
+ "maxHeight": 10,
26
+ },
27
+ ]
28
+ }
29
+ testID="nav-bar-container"
30
+ >
31
+ <View
32
+ isVisible={true}
33
+ menuPlugin={Object {}}
34
+ navigationProps={null}
35
+ />
36
+ </View>
37
+ </RNCSafeAreaProvider>
26
38
  `;
27
39
 
28
40
  exports[`ScreenContainer sets margins provided by the theme 1`] = `
@@ -12,7 +12,7 @@ jest.mock("../../../Screen/TV/index.web", () => ({
12
12
  Screen: View,
13
13
  }));
14
14
 
15
- const Layout = require("..").default;
15
+ const Layout = require("../index.web").default;
16
16
 
17
17
  const mockStore = configureStore()({
18
18
  appState: { appReady: true },
@@ -21,10 +21,11 @@ const mockStore = configureStore()({
21
21
  describe("Layout TV", () => {
22
22
  const navigator = {
23
23
  currentRoute: "/river/A1234",
24
+ canGoBack: jest.fn(),
24
25
  mainStack: [
25
26
  {
26
27
  route: "/river/A1234",
27
- state: "state",
28
+ state: { screen: {} },
28
29
  },
29
30
  ],
30
31
  };
@@ -1,32 +1,75 @@
1
1
  import * as React from "react";
2
- import { pathOr } from "ramda";
3
-
2
+ import * as R from "ramda";
4
3
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
5
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
6
+
7
+ import { getBackgroundImageUrl } from "../utils";
8
+ import { LayoutContainer } from "./LayoutContainer";
9
+ import { ScreenContainer } from "./ScreenContainer";
5
10
 
6
11
  import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
7
- import { StackNavigator } from "../../Navigator";
12
+ import { PathnameContext } from "../../../Contexts/PathnameContext";
13
+ import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
14
+ import { ScreenContextProvider } from "../../../Contexts/ScreenContext";
8
15
 
9
16
  type Components = {
10
17
  NavBar: React.ComponentType<any>;
11
18
  Background: React.ComponentType<any>;
12
19
  };
13
20
 
21
+ type ComponentsExtraProps = {
22
+ Background?: Record<string, any>;
23
+ NavBar?: Record<string, any>;
24
+ };
25
+
14
26
  type Props = {
15
27
  Components: Components;
28
+ ComponentsExtraProps?: ComponentsExtraProps;
29
+ children: React.ReactNode;
16
30
  };
17
31
 
18
- const Layout = ({ Components }: Props) => {
19
- const { appState } = usePickFromState(["appState"]);
20
- const appReady = pathOr(false, ["appReady"], appState);
32
+ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
33
+ const navigator = useNavigation();
34
+ const theme = useTheme();
35
+
36
+ const { appState: { appReady = false } = {}, remoteConfigurations } =
37
+ usePickFromState(["appState", "remoteConfigurations", "plugins"]);
38
+
39
+ const backgroundColor = React.useMemo(() => theme.app_background_color, []);
40
+
41
+ const backgroundImageUrl = React.useMemo(
42
+ () => getBackgroundImageUrl(remoteConfigurations),
43
+ [remoteConfigurations]
44
+ );
21
45
 
22
46
  if (!appReady) {
23
47
  return null;
24
48
  }
25
49
 
26
50
  return (
27
- <ScreenLayoutContextProvider>
28
- <StackNavigator Components={Components} />
29
- </ScreenLayoutContextProvider>
51
+ <LayoutContainer>
52
+ <ScreenLayoutContextProvider>
53
+ <Components.Background
54
+ backgroundColor={backgroundColor}
55
+ backgroundImageUrl={backgroundImageUrl}
56
+ {...R.omit(["ref"])(ComponentsExtraProps?.Background)}
57
+ >
58
+ <ScreenDataContext.Provider value={navigator.data}>
59
+ <PathnameContext.Provider value={navigator.currentRoute}>
60
+ <ScreenContextProvider pathname={navigator.currentRoute}>
61
+ <ScreenContainer
62
+ ComponentsExtraProps={ComponentsExtraProps}
63
+ NavBar={Components.NavBar}
64
+ >
65
+ {children}
66
+ </ScreenContainer>
67
+ </ScreenContextProvider>
68
+ </PathnameContext.Provider>
69
+ </ScreenDataContext.Provider>
70
+ </Components.Background>
71
+ </ScreenLayoutContextProvider>
72
+ </LayoutContainer>
30
73
  );
31
74
  };
32
75
 
@@ -0,0 +1,33 @@
1
+ import * as React from "react";
2
+ import { pathOr } from "ramda";
3
+
4
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
+
6
+ import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
7
+ import { StackNavigator } from "../../Navigator";
8
+
9
+ type Components = {
10
+ NavBar: React.ComponentType<any>;
11
+ Background: React.ComponentType<any>;
12
+ };
13
+
14
+ type Props = {
15
+ Components: Components;
16
+ };
17
+
18
+ const Layout = ({ Components }: Props) => {
19
+ const { appState } = usePickFromState(["appState"]);
20
+ const appReady = pathOr(false, ["appReady"], appState);
21
+
22
+ if (!appReady) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <ScreenLayoutContextProvider>
28
+ <StackNavigator Components={Components} />
29
+ </ScreenLayoutContextProvider>
30
+ );
31
+ };
32
+
33
+ export default Layout;
@@ -1,20 +1,24 @@
1
1
  import * as React from "react";
2
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
3
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
- import { ScreenContextProvider } from "../../Contexts/ScreenContext";
2
+ import {
3
+ isTV,
4
+ platformSelect,
5
+ } from "@applicaster/zapp-react-native-utils/reactUtils";
5
6
 
6
7
  import Mobile from "./Mobile";
7
- import TV from "./TV";
8
8
 
9
- export default function Layout(props) {
10
- const { currentRoute: pathname } = useNavigation();
9
+ import TVWeb from "./TV/index.web";
10
+ import TVDefault from "./TV/index";
11
+
12
+ const TV = platformSelect({
13
+ samsung_tv: TVWeb,
14
+ lg_tv: TVWeb,
15
+ web: TVWeb,
16
+ default: TVDefault,
17
+ });
11
18
 
19
+ export default function Layout(props) {
12
20
  if (isTV()) {
13
- return (
14
- <ScreenContextProvider pathname={pathname}>
15
- <TV {...props} />
16
- </ScreenContextProvider>
17
- );
21
+ return <TV {...props} />;
18
22
  } else {
19
23
  return <Mobile {...props} />;
20
24
  }
@@ -53,6 +53,7 @@ export function ActionButton(props: Props) {
53
53
  const { item, action, asset, flavour = "flavour_1", cellUUID } = props;
54
54
  const actionContext = useActions(action?.identifier);
55
55
 
56
+ // TODO: add subscription API for action availability
56
57
  const actionDisabled =
57
58
  typeof actionContext?.isActionAvailable === "function" &&
58
59
  !actionContext.isActionAvailable(item);
@@ -68,7 +69,7 @@ export function ActionButton(props: Props) {
68
69
  if (actionDisabled || !actionContext) return;
69
70
 
70
71
  setActionState(actionContext.initialEntryState(item));
71
- }, [actionDisabled, item?.id]);
72
+ }, [actionDisabled, item?.id, actionContext]);
72
73
 
73
74
  const onPress = useCallback(() => {
74
75
  actionContext.invokeAction(item, {
@@ -7,50 +7,28 @@ type BorderPosition = "inside" | "outside" | "center";
7
7
  interface Props {
8
8
  style: ImageStyle | ViewStyle;
9
9
  borderPosition: BorderPosition;
10
+ borderPaddingTop: number;
11
+ borderPaddingRight: number;
12
+ borderPaddingBottom: number;
13
+ borderPaddingLeft: number;
10
14
  children: React.ReactNode;
11
15
  }
12
16
 
13
- const MARGINS = [
14
- "marginTop",
15
- "marginBottom",
16
- "marginLeft",
17
- "marginRight",
18
- ] as const;
19
-
20
- const PADDINGS = [
21
- "paddingTop",
22
- "paddingBottom",
23
- "paddingLeft",
24
- "paddingRight",
25
- ] as const;
26
-
27
- const isPercentageValue = (value: number | string) => {
28
- if (typeof value === "string" && value.endsWith("%")) {
29
- return true;
30
- }
31
-
32
- return false;
33
- };
34
-
35
- const calculateContainerSpacing = ({
36
- spacingKey,
37
- style,
38
- additionalSpacing,
39
- }: {
40
- spacingKey: typeof MARGINS[number] | typeof PADDINGS[number];
41
- style: ImageStyle | ViewStyle;
42
- additionalSpacing: number;
43
- }) => {
44
- return {
45
- [spacingKey]:
46
- toNumberWithDefaultZero(style[spacingKey]) + additionalSpacing,
47
- };
48
- };
49
-
50
- const getContainerBorderWidth = (
51
- borderPosition: BorderPosition,
52
- borderWidth
53
- ) => {
17
+ const COLOR_TRANSPARENT = "transparent";
18
+
19
+ const styles = StyleSheet.create({
20
+ container: {
21
+ overflow: "visible",
22
+ borderWidth: 0,
23
+ borderColor: COLOR_TRANSPARENT,
24
+ },
25
+ border: {
26
+ ...StyleSheet.absoluteFillObject,
27
+ zIndex: 1,
28
+ },
29
+ });
30
+
31
+ const getBorderPadding = (borderPosition: BorderPosition, borderWidth) => {
54
32
  switch (borderPosition) {
55
33
  case "inside":
56
34
  return 0;
@@ -63,104 +41,96 @@ const getContainerBorderWidth = (
63
41
  }
64
42
  };
65
43
 
66
- const getContainerPadding = (borderPosition: BorderPosition, borderWidth) => {
67
- switch (borderPosition) {
68
- case "inside":
69
- return borderWidth;
70
- case "center":
71
- return borderWidth / 2;
72
- case "outside":
73
- return 0;
74
- default:
75
- return 0;
76
- }
77
- };
78
-
79
- const InsideBorder = ({
44
+ const Border = ({
80
45
  style,
46
+ padding,
81
47
  borderPosition,
82
48
  }: {
83
49
  style: ViewStyle;
50
+ padding: ViewStyle;
84
51
  borderPosition: BorderPosition;
85
52
  }) => {
86
- if (borderPosition === "outside") {
53
+ if (!borderPosition) {
87
54
  return null;
88
55
  }
89
56
 
90
- const insideBorderWidth =
91
- borderPosition === "center" ? style.borderWidth / 2 : style.borderWidth;
57
+ const borderWidth = toNumberWithDefaultZero(style.borderWidth);
58
+ const containerPadding = getBorderPadding(borderPosition, borderWidth);
59
+
60
+ const initialBorderRadius = toNumberWithDefaultZero(style.borderRadius);
61
+ const paddingTop = toNumberWithDefaultZero(padding.paddingTop);
62
+ const paddingRight = toNumberWithDefaultZero(padding.paddingRight);
63
+ const paddingBottom = toNumberWithDefaultZero(padding.paddingBottom);
64
+ const paddingLeft = toNumberWithDefaultZero(padding.paddingLeft);
65
+
66
+ const borderRadiusStyle = initialBorderRadius
67
+ ? {
68
+ borderTopLeftRadius:
69
+ initialBorderRadius +
70
+ containerPadding +
71
+ Math.min(paddingTop, paddingLeft),
72
+ borderTopRightRadius:
73
+ initialBorderRadius +
74
+ containerPadding +
75
+ Math.min(paddingTop, paddingRight),
76
+ borderBottomLeftRadius:
77
+ initialBorderRadius +
78
+ containerPadding +
79
+ Math.min(paddingBottom, paddingLeft),
80
+ borderBottomRightRadius:
81
+ initialBorderRadius +
82
+ containerPadding +
83
+ Math.min(paddingBottom, paddingRight),
84
+ }
85
+ : {
86
+ borderTopLeftRadius: 0,
87
+ borderTopRightRadius: 0,
88
+ borderBottomLeftRadius: 0,
89
+ borderBottomRightRadius: 0,
90
+ };
92
91
 
93
92
  return (
94
93
  <View
94
+ pointerEvents="none"
95
95
  style={{
96
- ...StyleSheet.absoluteFillObject,
97
- borderWidth: insideBorderWidth,
96
+ ...styles.border,
97
+ right: -containerPadding - paddingRight,
98
+ bottom: -containerPadding - paddingBottom,
99
+ left: -containerPadding - paddingLeft,
100
+ top: -containerPadding - paddingTop,
101
+ borderWidth,
98
102
  borderColor: style.borderColor,
99
- borderRadius: style.borderRadius,
103
+ ...borderRadiusStyle,
100
104
  }}
101
105
  />
102
106
  );
103
107
  };
104
108
 
105
109
  export const BorderContainerView = (props: Props) => {
106
- const { style, children } = props;
107
- // Return border position prop after re-implementing
108
- const borderPosition = "outside";
109
-
110
- const borderWidth = toNumberWithDefaultZero(style.borderWidth);
111
- const spacing = getContainerPadding(borderPosition, borderWidth);
112
-
113
- const borderStyleForMissingBorder =
114
- style?.borderWidth === 0 || !style?.borderColor ? { borderRadius: 0 } : {};
115
-
116
- const updatedMargins = MARGINS.reduce((acc, margin) => {
117
- const marginValue = calculateContainerSpacing({
118
- spacingKey: margin,
119
- style,
120
- additionalSpacing: spacing,
121
- });
122
-
123
- return { ...acc, ...marginValue };
124
- }, {});
125
-
126
- const updatedPaddings = PADDINGS.reduce((acc, padding) => {
127
- const paddingValue = calculateContainerSpacing({
128
- spacingKey: padding,
129
- style,
130
- additionalSpacing: spacing,
131
- });
132
-
133
- return { ...acc, ...paddingValue };
134
- }, {});
135
-
136
- const updatedWidth = style.width
137
- ? isPercentageValue(style.width)
138
- ? style.width
139
- : toNumberWithDefaultZero(style.width) - spacing * 2
140
- : undefined;
141
-
142
- const updatedHeight = style.height
143
- ? isPercentageValue(style.height)
144
- ? style.height
145
- : toNumberWithDefaultZero(style.height) - spacing * 2
146
- : undefined;
147
-
148
- const containerStyle = {
149
- borderWidth: getContainerBorderWidth(borderPosition, borderWidth),
150
- padding: spacing,
151
- ...updatedMargins,
152
- ...updatedPaddings,
153
- width: updatedWidth,
154
- height: updatedHeight,
155
- };
110
+ const {
111
+ borderPosition,
112
+ borderPaddingTop,
113
+ borderPaddingRight,
114
+ borderPaddingBottom,
115
+ borderPaddingLeft,
116
+ style,
117
+ children,
118
+ } = props;
119
+
120
+ const padding =
121
+ borderPosition === "outside"
122
+ ? {
123
+ paddingTop: borderPaddingTop,
124
+ paddingRight: borderPaddingRight,
125
+ paddingBottom: borderPaddingBottom,
126
+ paddingLeft: borderPaddingLeft,
127
+ }
128
+ : {};
156
129
 
157
130
  return (
158
- <View {...props} style={[style, containerStyle]}>
131
+ <View pointerEvents="box-none" {...props} style={[style, styles.container]}>
132
+ <Border style={style} padding={padding} borderPosition={borderPosition} />
159
133
  {children}
160
- <InsideBorder
161
- style={{ ...style, ...borderStyleForMissingBorder }}
162
- borderPosition={borderPosition}
163
- />
164
134
  </View>
165
135
  );
166
136
  };
@@ -4,6 +4,7 @@ import { Focusable } from "@applicaster/zapp-react-native-ui-components/Componen
4
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
5
5
  import * as R from "ramda";
6
6
  import { getXray } from "@applicaster/zapp-react-native-utils/logger";
7
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
7
8
 
8
9
  const { Logger } = getXray();
9
10
 
@@ -35,7 +36,9 @@ export function FocusableView({ style, children, item, ...otherProps }: Props) {
35
36
 
36
37
  const focusableId = getFocusableId(prefixId, suffixId);
37
38
 
38
- const focused = focusableId === focusedButtonId;
39
+ const focused =
40
+ focusableId === focusedButtonId ||
41
+ toBooleanWithDefaultFalse(otherProps.focused);
39
42
 
40
43
  const additionalStyles = focused ? focusedStyles : normalStyles;
41
44