@applicaster/zapp-react-native-ui-components 12.0.0-rc.29 → 12.0.0-rc.30

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.
@@ -1,28 +1,38 @@
1
1
  import * as React from "react";
2
2
  import { isEqual } from "@applicaster/zapp-react-native-utils/equalUtils";
3
- import { FocusableContext } from "../Focusable/index.android";
3
+ import { useFocusable } from "../Focusable/index.android";
4
4
  import { useCellState } from "./hooks/useCellState.android";
5
5
 
6
- function FocusableChildComponent(props) {
7
- const context = React.useContext(FocusableContext);
8
-
9
- const { setIsFocusable } = context || {};
10
-
11
- const nextFocusDown = props.nextFocusDown ?? context.nextFocusDown;
12
- const nextFocusUp = props.nextFocusUp ?? context.nextFocusUp;
13
- const nextFocusRight = props.nextFocusRight ?? context.nextFocusRight;
14
- const nextFocusLeft = props.nextFocusLeft ?? context.nextFocusLeft;
15
-
16
- const parentFocus = React.useMemo(
6
+ /**
7
+ * returns parent focus from prop or from context
8
+ * */
9
+ const useParentFocus = (
10
+ { nextFocusDown, nextFocusUp, nextFocusRight, nextFocusLeft },
11
+ context
12
+ ) =>
13
+ React.useMemo(
17
14
  () => ({
15
+ nextFocusRight: nextFocusRight ?? context.nextFocusRight,
16
+ nextFocusDown: nextFocusDown ?? context.nextFocusDown,
17
+ nextFocusLeft: nextFocusLeft ?? context.nextFocusLeft,
18
+ nextFocusUp: nextFocusUp ?? context.nextFocusUp,
19
+ }),
20
+ [
18
21
  nextFocusRight,
19
22
  nextFocusDown,
20
23
  nextFocusLeft,
21
24
  nextFocusUp,
22
- }),
23
- [nextFocusRight, nextFocusDown, nextFocusLeft, nextFocusUp]
25
+ context.nextFocusLeft,
26
+ context.nextFocusRight,
27
+ context.nextFocusUp,
28
+ context.nextFocusDown,
29
+ ]
24
30
  );
25
31
 
32
+ function FocusableChildComponent(props) {
33
+ const { setIsFocusable, ...focusableContext } = useFocusable();
34
+ const parentFocus = useParentFocus(props, focusableContext);
35
+
26
36
  const onLoadFailed = React.useCallback(() => {
27
37
  setIsFocusable(false);
28
38
  }, []);
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { Focusable } from "../Focusable";
2
+ import { Focusable } from "../Focusable/index.android";
3
3
  import { FocusableChild } from "./FocusableChild";
4
4
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
5
5
  import { IListRenderItem } from "./index";
@@ -0,0 +1,76 @@
1
+ import * as React from "react";
2
+ import { ListRenderItemInfo as IListRenderItemInfo } from "react-native";
3
+ import { FocusableItem } from "./FocusableItem";
4
+
5
+ export type IListRenderItem<ItemT> = (
6
+ info: IListRenderItemInfo<ItemT> & {
7
+ focused: boolean;
8
+ onLoadFinished: () => void;
9
+ onLoadFailed: () => void;
10
+ }
11
+ ) => React.ReactElement | null;
12
+
13
+ type Item = ZappEntry | ZappUIComponent | any;
14
+
15
+ type Props = {
16
+ item: Item;
17
+ onFocus: (
18
+ element: FocusManager.FocusableRef,
19
+ renderArgs: { item: Item; index: number },
20
+ direction: FocusManager.Android.FocusNavigationDirections
21
+ ) => void;
22
+ onListElementBlur?: (any, RenderItemProps, Direction) => void;
23
+ onListElementPress?: (any, RenderItemProps) => void;
24
+ onListElementLongPress?: (any, RenderItemProps) => void;
25
+ onListElementPressOut?: (any, RenderItemProps) => void;
26
+ focusableItemProps: any;
27
+ id: string;
28
+ index: number;
29
+ extraData: any;
30
+ extraChildrenData: any;
31
+ renderItem: IListRenderItem<any> | null | undefined;
32
+ getNextFocus: (index: number) => ParentFocus;
33
+ } & ParentFocus;
34
+
35
+ export const FocusableListItemWrapper = React.memo(
36
+ ({
37
+ onFocus,
38
+ onListElementBlur,
39
+ onListElementPress,
40
+ onListElementLongPress,
41
+ onListElementPressOut,
42
+ focusableItemProps,
43
+ id,
44
+ getNextFocus,
45
+ item,
46
+ index,
47
+ extraData,
48
+ extraChildrenData,
49
+ renderItem,
50
+ }: Props) => {
51
+ const nextFocus = getNextFocus(index);
52
+
53
+ return (
54
+ <FocusableItem
55
+ nextFocusDown={nextFocus.nextFocusDown}
56
+ nextFocusRight={nextFocus.nextFocusRight}
57
+ nextFocusLeft={nextFocus.nextFocusLeft}
58
+ nextFocusUp={nextFocus.nextFocusUp}
59
+ id={id}
60
+ focusableItemProps={focusableItemProps}
61
+ onFocus={onFocus}
62
+ item={item}
63
+ index={index}
64
+ renderItem={renderItem}
65
+ extraChildrenData={extraChildrenData}
66
+ extraData={extraData}
67
+ onListElementBlur={onListElementBlur}
68
+ onListElementPress={onListElementPress}
69
+ onListElementLongPress={onListElementLongPress}
70
+ onListElementPressOut={onListElementPressOut}
71
+ />
72
+ );
73
+ }
74
+ );
75
+
76
+ FocusableListItemWrapper.displayName = "FocusableListItemWrapper";
@@ -5,7 +5,9 @@ import { useFocusManager } from "@applicaster/zapp-react-native-utils/focusManag
5
5
  export const useCellState = (id: string) => {
6
6
  const focusManager = useFocusManager();
7
7
 
8
- const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
8
+ const [currentCellFocused, setCurrentCellFocused] = React.useState(
9
+ focusManager.isFocused(id)
10
+ );
9
11
 
10
12
  React.useEffect(() => {
11
13
  const handler = (focusable) => {
@@ -12,8 +12,9 @@ import { ChildrenFocusDeactivatorView } from "../ChildrenFocusDeactivatorView";
12
12
  import { useInitialFocus } from "@applicaster/zapp-react-native-utils/focusManager";
13
13
 
14
14
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
15
- import { FocusableItem } from "./FocusableItem";
15
+
16
16
  import { useParentFocus, useCheckItemIdsForUnique } from "./hooks";
17
+ import { FocusableListItemWrapper } from "./FocusableListItemWrapper";
17
18
 
18
19
  const mapIndexed = R.addIndex(R.map);
19
20
 
@@ -74,6 +75,8 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
74
75
  nextFocusLeft: parentNextFocusLeft,
75
76
  nextFocusUp: parentNextFocusUp,
76
77
 
78
+ numColumns,
79
+
77
80
  focused: parentFocused,
78
81
 
79
82
  focusableItemProps,
@@ -103,8 +106,8 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
103
106
  });
104
107
 
105
108
  const getFocusableEntryId = React.useCallback(
106
- (_entry: ZappEntry, index?: number) => {
107
- const entry = R.isNil(index) ? _entry : data[index];
109
+ (_entry: ZappEntry | null, index?: number) => {
110
+ const entry = R.isNil(index) ? _entry : data[index as number];
108
111
 
109
112
  return entry ? getFocusableId(props.id, index) : undefined;
110
113
  },
@@ -143,7 +146,6 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
143
146
  const getNextFocus = React.useCallback(
144
147
  (index) => {
145
148
  const itemCount = R.length(data);
146
- const { numColumns } = props;
147
149
 
148
150
  const getFocusableEntryIdForIndex = (entryIndex) =>
149
151
  getFocusableEntryId(null, entryIndex);
@@ -160,22 +162,23 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
160
162
  });
161
163
 
162
164
  const getGridFocus = () => {
163
- const numberOfRows = Math.ceil(itemCount / numColumns);
164
- const currentRowIndex = Math.floor(index / numColumns);
165
+ const _numColumns = toFiniteNumberWithDefault(1, numColumns);
166
+ const numberOfRows = Math.ceil(itemCount / _numColumns);
167
+ const currentRowIndex = Math.floor(index / _numColumns);
165
168
  const isFirstRow = currentRowIndex === 0;
166
169
  const isLastRow = currentRowIndex + 1 === numberOfRows;
167
- const isLeftEdge = index % numColumns === 0;
170
+ const isLeftEdge = index % _numColumns === 0;
168
171
 
169
172
  const isRightEdge =
170
- (index + 1) % numColumns === 0 || itemCount === index + 1;
173
+ (index + 1) % _numColumns === 0 || itemCount === index + 1;
171
174
 
172
175
  return {
173
176
  nextFocusUp: isFirstRow
174
177
  ? nextFocusUp
175
- : getFocusableEntryIdForIndex(index - numColumns),
178
+ : getFocusableEntryIdForIndex(index - _numColumns),
176
179
  nextFocusDown: isLastRow
177
180
  ? nextFocusDown
178
- : getFocusableEntryIdForIndex(index + numColumns),
181
+ : getFocusableEntryIdForIndex(index + _numColumns),
179
182
  nextFocusLeft: isLeftEdge
180
183
  ? nextFocusLeft
181
184
  : getFocusableEntryIdForIndex(index - 1),
@@ -215,26 +218,24 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
215
218
  const renderItem = React.useCallback(
216
219
  ({ item, index }) => {
217
220
  const id = getFocusableId(props.id, index);
218
- const nextFocus = getNextFocus(index);
219
221
 
220
222
  return (
221
- <FocusableItem
222
- nextFocusDown={nextFocus.nextFocusDown}
223
- nextFocusRight={nextFocus.nextFocusRight}
224
- nextFocusLeft={nextFocus.nextFocusLeft}
225
- nextFocusUp={nextFocus.nextFocusUp}
226
- id={id}
223
+ <FocusableListItemWrapper
224
+ {...{
225
+ onFocus,
226
+ onListElementBlur,
227
+ onListElementPress,
228
+ onListElementLongPress,
229
+ onListElementPressOut,
230
+ }}
231
+ renderItem={props.renderItem}
227
232
  focusableItemProps={focusableItemProps}
228
- onFocus={onFocus}
233
+ getNextFocus={getNextFocus}
234
+ id={id}
229
235
  item={item}
230
236
  index={index}
231
- renderItem={props.renderItem}
232
- extraChildrenData={props.extraChildrenData}
233
237
  extraData={props.extraData}
234
- onListElementBlur={onListElementBlur}
235
- onListElementPress={onListElementPress}
236
- onListElementLongPress={onListElementLongPress}
237
- onListElementPressOut={onListElementPressOut}
238
+ extraChildrenData={props.extraChildrenData}
238
239
  />
239
240
  );
240
241
  },
@@ -287,7 +288,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
287
288
  );
288
289
 
289
290
  const initialNumToRender = toFiniteNumberWithDefault(
290
- data.length,
291
+ 10,
291
292
  flatListProps.initialNumToRender
292
293
  );
293
294
 
@@ -98,13 +98,16 @@ export const GeneralContentScreen = ({
98
98
 
99
99
  const isReady = useRiverActionProviderReady();
100
100
 
101
+ const contextValue = React.useMemo(
102
+ () => whenMatchingType(Function, cellTapAction) || onCellTapAction,
103
+ [typeof cellTapAction === "function" ? cellTapAction : onCellTapAction]
104
+ );
105
+
101
106
  if (!isReady || isNilOrEmpty(components || uiComponents)) return null;
102
107
 
103
108
  return (
104
109
  <ScreenTrackedViewPositionsContext.Provider>
105
- <CellTapContext.Provider
106
- value={whenMatchingType(Function, cellTapAction) || onCellTapAction}
107
- >
110
+ <CellTapContext.Provider value={contextValue}>
108
111
  <ComponentsMap
109
112
  feed={feed}
110
113
  riverId={screenId}
@@ -1,6 +1,3 @@
1
- import * as R from "ramda";
2
-
3
- import { withNavigator } from "@applicaster/zapp-react-native-ui-components/Decorators/Navigator/";
4
1
  import { HookRenderer as HookRendererComponent } from "./HookRenderer";
5
2
 
6
- export const HookRenderer = R.compose(withNavigator)(HookRendererComponent);
3
+ export const HookRenderer = HookRendererComponent;
@@ -4,7 +4,6 @@ import * as React from "react";
4
4
  import { Text } from "react-native";
5
5
  import * as R from "ramda";
6
6
 
7
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
8
7
  import {
9
8
  useFeedLoader,
10
9
  useLayoutVersion,
@@ -20,6 +19,7 @@ import {
20
19
  useNavbarState,
21
20
  useSetNavbarState,
22
21
  } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
22
+ import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks/state";
23
23
 
24
24
  type Props = {
25
25
  screenId: string;
@@ -53,7 +53,7 @@ export const River = (props: Props) => {
53
53
 
54
54
  const navigationPluginData = useNavigationPluginData();
55
55
 
56
- const { rivers } = usePickFromState(["rivers"]);
56
+ const rivers = useRivers();
57
57
  const isV2 = useLayoutVersion({ isV2: true });
58
58
 
59
59
  const river = React.useMemo(() => rivers?.[screenId], [screenId]);
@@ -1,10 +1,10 @@
1
1
  import * as R from "ramda";
2
2
 
3
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
3
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
5
4
  import { toCamelCase } from "@applicaster/zapp-react-native-utils/stringUtils";
6
5
  import { useMemo } from "react";
7
6
  import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
7
+ import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks/state";
8
8
 
9
9
  type GeneralContentScreen = ZappRiver & {
10
10
  styles: {
@@ -46,7 +46,7 @@ const stylingKeys = [
46
46
  ];
47
47
 
48
48
  export function useScreenConfiguration(screenId: string): ScreenConfiguration {
49
- const { rivers } = usePickFromState(["rivers"]);
49
+ const rivers = useRivers();
50
50
  const isTablet = useIsTablet();
51
51
 
52
52
  return useMemo(() => {
@@ -91,7 +91,7 @@ export function ScreenResolverComponent(props: Props) {
91
91
  <HookRenderer
92
92
  screenData={screenData}
93
93
  focused={props.focused}
94
- parentFocus={props.parentFocus}
94
+ parentFocus={props.parentFocus as ParentFocus}
95
95
  />
96
96
  )
97
97
  );
@@ -10,7 +10,7 @@ import {
10
10
 
11
11
  import { Placeholder } from "./Placeholder";
12
12
  import { useInitialLoading } from "./hooks";
13
- import { FocusableContext } from "../Focusable/index.android";
13
+ import { useFocusable } from "../Focusable/index.android";
14
14
 
15
15
  type ReactComponent = React.ComponentType<any>;
16
16
 
@@ -26,13 +26,23 @@ type ZappUIComponentType = {
26
26
  options?: Options;
27
27
  };
28
28
 
29
- const renderComponent = (Component: ReactComponent | undefined, props) => {
30
- if (Component) {
31
- const { component, parent } = props;
29
+ type RenderComponentProps = any;
30
+
31
+ const RenderComponent = (
32
+ Component: ReactComponent | undefined,
33
+ args: RenderComponentProps
34
+ ) => {
35
+ const { component, parent } = args;
32
36
 
37
+ const contextValue = React.useMemo(
38
+ () => ({ ...component, parent }),
39
+ [component, parent]
40
+ );
41
+
42
+ if (Component) {
33
43
  return (
34
- <UIComponentContext.Provider value={{ ...component, parent }}>
35
- <Component {...props} />
44
+ <UIComponentContext.Provider value={contextValue}>
45
+ <Component {...args} />
36
46
  </UIComponentContext.Provider>
37
47
  );
38
48
  }
@@ -117,7 +127,7 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
117
127
  props;
118
128
 
119
129
  const parent = useUIComponentContext();
120
- const { setIsFocusable } = React.useContext(FocusableContext) || {};
130
+ const { setIsFocusable } = useFocusable();
121
131
 
122
132
  const isLoading = toBooleanWithDefaultFalse(zappPipesData?.loading);
123
133
  const isInitialLoading = useInitialLoading(isLoading);
@@ -154,11 +164,11 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
154
164
  }, [props.component?.rules?.component_cells_focusable]);
155
165
 
156
166
  if (isDataSourceEmpty(props) && allowsEmptyDataSource) {
157
- return renderComponent(Component, componentProps);
167
+ return RenderComponent(Component, componentProps);
158
168
  }
159
169
 
160
- if (isLoading && !zappPipesData.data && isInitialLoading) {
161
- return renderComponent(LoadingComponent || Placeholder, componentProps);
170
+ if (isLoading && !zappPipesData?.data && isInitialLoading) {
171
+ return RenderComponent(LoadingComponent || Placeholder, componentProps);
162
172
  }
163
173
 
164
174
  if (zappPipesData?.error) {
@@ -167,9 +177,9 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
167
177
  index: componentIndex,
168
178
  });
169
179
 
170
- return renderComponent(ErrorComponent, componentProps);
180
+ return RenderComponent(ErrorComponent, componentProps);
171
181
  }
172
182
 
173
- return renderComponent(Component, componentProps);
183
+ return RenderComponent(Component, componentProps);
174
184
  };
175
185
  }
@@ -1,5 +1,4 @@
1
1
  import React, { createContext, ReactNode, useMemo, useState } from "react";
2
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
2
  import {
4
3
  useCurrentScreenData,
5
4
  useNavigation,
@@ -42,8 +41,6 @@ export function ScreenContextProvider({
42
41
  }) {
43
42
  const { data, modalData, videoModalState, canGoBack } = useNavigation();
44
43
 
45
- const { rivers: _rivers } = usePickFromState(["rivers", "plugins"]);
46
-
47
44
  // There are 4 route scenarios
48
45
  // For regular screens take date from navigator stack.
49
46
  // is path is model grab screenData from modal state
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "12.0.0-rc.29",
3
+ "version": "12.0.0-rc.30",
4
4
  "description": "Applicaster Zapp React Native ui components for the Quick Brick App",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -34,10 +34,10 @@
34
34
  "redux-mock-store": "^1.5.3"
35
35
  },
36
36
  "dependencies": {
37
- "@applicaster/applicaster-types": "12.0.0-rc.29",
38
- "@applicaster/zapp-react-native-bridge": "12.0.0-rc.29",
39
- "@applicaster/zapp-react-native-redux": "12.0.0-rc.29",
40
- "@applicaster/zapp-react-native-utils": "12.0.0-rc.29",
37
+ "@applicaster/applicaster-types": "12.0.0-rc.30",
38
+ "@applicaster/zapp-react-native-bridge": "12.0.0-rc.30",
39
+ "@applicaster/zapp-react-native-redux": "12.0.0-rc.30",
40
+ "@applicaster/zapp-react-native-utils": "12.0.0-rc.30",
41
41
  "promise": "^8.3.0",
42
42
  "react-router-native": "^5.1.2",
43
43
  "url": "^0.11.0",