@applicaster/zapp-react-native-ui-components 12.0.3-alpha.5953460913 → 13.0.0-alpha.1102149799
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/BaseFocusable/index.tsx +28 -65
- package/Components/Cell/Cell.tsx +4 -8
- package/Components/Cell/CellWithFocusable.tsx +1 -1
- package/Components/Cell/TvOSCellComponent.tsx +3 -4
- package/Components/Focusable/Focusable.tsx +54 -0
- package/Components/NativeFocusables/{index.js → index.ts} +4 -2
- package/Decorators/Analytics/{index.js → index.tsx} +11 -11
- package/README.md +1 -13
- package/package.json +12 -6
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import * as R from "ramda";
|
|
3
2
|
|
|
4
3
|
import {
|
|
5
4
|
BaseFocusable as BaseFocusableInterface,
|
|
@@ -8,6 +7,7 @@ import {
|
|
|
8
7
|
|
|
9
8
|
import { createReactRef } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
10
9
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
10
|
+
import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
|
|
11
11
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
12
12
|
|
|
13
13
|
type ScrollDirection = FocusManager.IOS.Direction | FocusManager.Web.Direction;
|
|
@@ -131,6 +131,12 @@ export class BaseFocusable<
|
|
|
131
131
|
willLoseFocus: FocusManager.FocusEventCB = (focusable, scrollDirection) => {
|
|
132
132
|
const { willLoseFocus = noop } = this.props;
|
|
133
133
|
willLoseFocus(focusable, scrollDirection);
|
|
134
|
+
|
|
135
|
+
focusManager.invokeHandler?.(
|
|
136
|
+
FOCUS_EVENTS.WILL_LOSE_FOCUS,
|
|
137
|
+
this,
|
|
138
|
+
scrollDirection
|
|
139
|
+
);
|
|
134
140
|
};
|
|
135
141
|
|
|
136
142
|
willReceiveFocus: FocusManager.FocusEventCB = (
|
|
@@ -139,6 +145,12 @@ export class BaseFocusable<
|
|
|
139
145
|
) => {
|
|
140
146
|
const { willReceiveFocus = noop } = this.props;
|
|
141
147
|
willReceiveFocus(focusable, scrollDirection);
|
|
148
|
+
|
|
149
|
+
focusManager.invokeHandler?.(
|
|
150
|
+
FOCUS_EVENTS.WILL_RECEIVE_FOCUS,
|
|
151
|
+
this,
|
|
152
|
+
scrollDirection
|
|
153
|
+
);
|
|
142
154
|
};
|
|
143
155
|
|
|
144
156
|
/**
|
|
@@ -151,6 +163,8 @@ export class BaseFocusable<
|
|
|
151
163
|
const { onFocus = noop } = this.props;
|
|
152
164
|
this.setFocusedState(true);
|
|
153
165
|
onFocus(focusable, scrollDirection);
|
|
166
|
+
|
|
167
|
+
focusManager.invokeHandler?.(FOCUS_EVENTS.FOCUS, this, scrollDirection);
|
|
154
168
|
};
|
|
155
169
|
|
|
156
170
|
/**
|
|
@@ -165,6 +179,12 @@ export class BaseFocusable<
|
|
|
165
179
|
) => {
|
|
166
180
|
const { hasReceivedFocus = noop } = this.props;
|
|
167
181
|
hasReceivedFocus(focusable, scrollDirection);
|
|
182
|
+
|
|
183
|
+
focusManager.invokeHandler?.(
|
|
184
|
+
FOCUS_EVENTS.HAS_RECEIVED_FOCUS,
|
|
185
|
+
this,
|
|
186
|
+
scrollDirection
|
|
187
|
+
);
|
|
168
188
|
};
|
|
169
189
|
|
|
170
190
|
/**
|
|
@@ -176,6 +196,12 @@ export class BaseFocusable<
|
|
|
176
196
|
hasLostFocus: FocusManager.FocusEventCB = (focusable, scrollDirection) => {
|
|
177
197
|
const { hasLostFocus = noop } = this.props;
|
|
178
198
|
hasLostFocus(focusable, scrollDirection);
|
|
199
|
+
|
|
200
|
+
focusManager.invokeHandler?.(
|
|
201
|
+
FOCUS_EVENTS.HAS_LOST_FOCUS,
|
|
202
|
+
this,
|
|
203
|
+
scrollDirection
|
|
204
|
+
);
|
|
179
205
|
};
|
|
180
206
|
|
|
181
207
|
/**
|
|
@@ -202,6 +228,7 @@ export class BaseFocusable<
|
|
|
202
228
|
const { onBlur = noop } = this.props;
|
|
203
229
|
this.setFocusedState(false);
|
|
204
230
|
onBlur(focusable, scrollDirection);
|
|
231
|
+
focusManager.invokeHandler?.(FOCUS_EVENTS.BLUR, this, scrollDirection);
|
|
205
232
|
};
|
|
206
233
|
|
|
207
234
|
onPress = (keyEvent?: Nullable<React.MouseEvent>) => {
|
|
@@ -242,68 +269,4 @@ export class BaseFocusable<
|
|
|
242
269
|
this.setState({ focused });
|
|
243
270
|
}
|
|
244
271
|
};
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* will invoke the underlying component's focus method
|
|
248
|
-
* @param {Object} scrollDirection
|
|
249
|
-
* @returns {Promise}
|
|
250
|
-
*/
|
|
251
|
-
focus(_, scrollDirection) {
|
|
252
|
-
return this.onFocus(this, scrollDirection); // invokeComponentMethod(this, "onFocus", scrollDirection);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* will invoke the underlying component's blur method
|
|
257
|
-
* @param {Object} scrollDirection
|
|
258
|
-
* @returns {Promise}
|
|
259
|
-
*/
|
|
260
|
-
blur(
|
|
261
|
-
_,
|
|
262
|
-
scrollDirection?: FocusManager.Web.Direction | FocusManager.IOS.Direction
|
|
263
|
-
) {
|
|
264
|
-
return this.onBlur(this, scrollDirection);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Sets the focus on this item. Will trigger sequentially a sequence of
|
|
269
|
-
* functions (willReceiveFocus, focus, hasReceivedFocus). If these functions (defined in the Focusable
|
|
270
|
-
* Item underlying component) return promises, execution will wait before it proceeds to the next. This
|
|
271
|
-
* is useful for triggering sequential operations that specifically require to fully run before or after
|
|
272
|
-
* focus is actually set on that item.
|
|
273
|
-
* @param {string} scrollDirection string representation of the direction of the navigation which landed
|
|
274
|
-
* to this item being focused
|
|
275
|
-
*/
|
|
276
|
-
_executeFocusSequence(methodNames, scrollDirection) {
|
|
277
|
-
return R.reduce(
|
|
278
|
-
(sequence, methodName) => {
|
|
279
|
-
const method = this[methodName]; // Access the method by name
|
|
280
|
-
|
|
281
|
-
if (typeof method !== "function") {
|
|
282
|
-
throw new Error(
|
|
283
|
-
`Method '${methodName}' not found or not a function.`
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return sequence
|
|
288
|
-
.then(() => method.call(this, scrollDirection))
|
|
289
|
-
.catch((e) => {
|
|
290
|
-
throw e; // Re-throw for consistent error handling
|
|
291
|
-
});
|
|
292
|
-
},
|
|
293
|
-
Promise.resolve(),
|
|
294
|
-
methodNames
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
setFocus(scrollDirection) {
|
|
299
|
-
const focusMethods = ["willReceiveFocus", "focus", "hasReceivedFocus"];
|
|
300
|
-
|
|
301
|
-
return this._executeFocusSequence(focusMethods, scrollDirection);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
setBlur(scrollDirection) {
|
|
305
|
-
const blurMethods = ["willLoseFocus", "blur", "hasLostFocus"];
|
|
306
|
-
|
|
307
|
-
return this._executeFocusSequence(blurMethods, scrollDirection);
|
|
308
|
-
}
|
|
309
272
|
}
|
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -14,10 +14,7 @@ import { BaseFocusable } from "../BaseFocusable";
|
|
|
14
14
|
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
15
15
|
|
|
16
16
|
type Props = {
|
|
17
|
-
item:
|
|
18
|
-
id: string;
|
|
19
|
-
title: string;
|
|
20
|
-
};
|
|
17
|
+
item: ZappEntry;
|
|
21
18
|
index: number;
|
|
22
19
|
shouldScrollHorizontally: (arg1: [any]) => boolean | null | undefined;
|
|
23
20
|
shouldScrollVertically: (...args: any) => boolean | null | undefined;
|
|
@@ -33,10 +30,9 @@ type Props = {
|
|
|
33
30
|
id: string;
|
|
34
31
|
};
|
|
35
32
|
selected?: boolean;
|
|
36
|
-
CellRenderer: React.
|
|
37
|
-
item:
|
|
38
|
-
|
|
39
|
-
}> & { hasFocusableInside: (item: Record<string, string>) => boolean };
|
|
33
|
+
CellRenderer: React.FunctionComponent<any> & {
|
|
34
|
+
hasFocusableInside: (item: ZappEntry) => boolean;
|
|
35
|
+
};
|
|
40
36
|
preferredFocus: boolean;
|
|
41
37
|
navigator: {
|
|
42
38
|
push: (arg1: Record<any, any>) => void;
|
|
@@ -36,10 +36,9 @@ type Props = {
|
|
|
36
36
|
component_type: string;
|
|
37
37
|
};
|
|
38
38
|
selected: boolean;
|
|
39
|
-
CellRenderer: React.
|
|
40
|
-
item: any;
|
|
41
|
-
|
|
42
|
-
}> & { hasFocusableInside: (item: any) => boolean };
|
|
39
|
+
CellRenderer: React.FunctionComponent<any> & {
|
|
40
|
+
hasFocusableInside: (item: any) => boolean;
|
|
41
|
+
};
|
|
43
42
|
preferredFocus: boolean;
|
|
44
43
|
navigator: {
|
|
45
44
|
push: (arg1: Record<any, any>) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import * as R from "ramda";
|
|
2
3
|
|
|
3
4
|
import { BaseFocusable } from "../BaseFocusable";
|
|
4
5
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
@@ -41,6 +42,8 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
41
42
|
this.resetLongPressTimeout = this.resetLongPressTimeout.bind(this);
|
|
42
43
|
this.longPress = this.longPress.bind(this);
|
|
43
44
|
this.press = this.press.bind(this);
|
|
45
|
+
this.focus = this.focus.bind(this);
|
|
46
|
+
this.blur = this.blur.bind(this);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
/**
|
|
@@ -52,6 +55,37 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
52
55
|
return this.preferredFocus();
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Sets the focus on this item. Will trigger sequentially a sequence of
|
|
60
|
+
* functions (willReceiveFocus, focus, hasReceivedFocus). If these functions (defined in the Focusable
|
|
61
|
+
* Item underlying component) return promises, execution will wait before it proceeds to the next. This
|
|
62
|
+
* is useful for triggering sequential operations that specifically require to fully run before or after
|
|
63
|
+
* focus is actually set on that item.
|
|
64
|
+
* @param {string} scrollDirection string representation of the direction of the navigation which landed
|
|
65
|
+
* to this item being focused
|
|
66
|
+
*/
|
|
67
|
+
setFocus(scrollDirection) {
|
|
68
|
+
const focusMethods = [
|
|
69
|
+
this.willReceiveFocus,
|
|
70
|
+
this.focus,
|
|
71
|
+
this.hasReceivedFocus,
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
const self = this;
|
|
75
|
+
|
|
76
|
+
return R.reduce(
|
|
77
|
+
(sequence, method) => {
|
|
78
|
+
return sequence
|
|
79
|
+
.then(() => method.apply(self, [scrollDirection]))
|
|
80
|
+
.catch((e) => {
|
|
81
|
+
throw e;
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
Promise.resolve(),
|
|
85
|
+
focusMethods
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
55
89
|
startLongPressTimeout() {
|
|
56
90
|
this.longPressTimeout = setTimeout(() => {
|
|
57
91
|
this.longPress(null);
|
|
@@ -68,6 +102,26 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
68
102
|
}
|
|
69
103
|
}
|
|
70
104
|
|
|
105
|
+
/**
|
|
106
|
+
* will invoke the underlying component's focus method
|
|
107
|
+
* @param {Object} scrollDirection
|
|
108
|
+
* @returns {Promise}
|
|
109
|
+
*/
|
|
110
|
+
focus(scrollDirection) {
|
|
111
|
+
return this.onFocus(this, scrollDirection); // invokeComponentMethod(this, "onFocus", scrollDirection);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* will invoke the underlying component's blur method
|
|
116
|
+
* @param {Object} scrollDirection
|
|
117
|
+
* @returns {Promise}
|
|
118
|
+
*/
|
|
119
|
+
blur(
|
|
120
|
+
scrollDirection?: FocusManager.Web.Direction | FocusManager.IOS.Direction
|
|
121
|
+
) {
|
|
122
|
+
return this.onBlur(this, scrollDirection);
|
|
123
|
+
}
|
|
124
|
+
|
|
71
125
|
/**
|
|
72
126
|
* will invoke the underlying component's press method
|
|
73
127
|
* @param {Object} keyEvent
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { requireNativeComponent, View } from "react-native";
|
|
2
2
|
import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
|
|
3
3
|
|
|
4
|
+
// @TODO define the types
|
|
4
5
|
export const FocusableGroupNative = isAppleTV()
|
|
5
|
-
? requireNativeComponent("FocusableGroupViewModule"
|
|
6
|
+
? requireNativeComponent<any>("FocusableGroupViewModule")
|
|
6
7
|
: View;
|
|
7
8
|
|
|
9
|
+
// @TODO define the types
|
|
8
10
|
export const FocusableItemNative = isAppleTV()
|
|
9
|
-
? requireNativeComponent("FocusableViewModule"
|
|
11
|
+
? requireNativeComponent<any>("FocusableViewModule")
|
|
10
12
|
: View;
|
|
@@ -5,18 +5,18 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
|
5
5
|
|
|
6
6
|
type ComponentProps = {
|
|
7
7
|
component: {
|
|
8
|
-
id: string
|
|
9
|
-
rules: { item_limit: number
|
|
10
|
-
component_type: string
|
|
8
|
+
id: string;
|
|
9
|
+
rules: { item_limit: number; component_cells_selectable: boolean };
|
|
10
|
+
component_type: string;
|
|
11
11
|
styles: {
|
|
12
|
-
cell_style: string
|
|
13
|
-
header: { visible: boolean }
|
|
14
|
-
component_cells_selectable: boolean
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
zappPipesData: { url: string
|
|
18
|
-
selected: boolean
|
|
19
|
-
assets: { menu_button: string }
|
|
12
|
+
cell_style: string;
|
|
13
|
+
header: { visible: boolean };
|
|
14
|
+
component_cells_selectable: boolean;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
zappPipesData: { url: string; data: { title: string } };
|
|
18
|
+
selected: boolean;
|
|
19
|
+
assets: { menu_button: string };
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
function withAnalytics(Component) {
|
package/README.md
CHANGED
|
@@ -78,17 +78,6 @@ export default MyAwesomeComponent;
|
|
|
78
78
|
export { MyAwesomeComponent } from "./MyAwesomeComponent";
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
We provide flow types for component props - please use it to make sure your component will be compliant
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
import * as React from "react";
|
|
85
|
-
import type { ZappComponentProps } from "../../flow-types"; // in the root of the project
|
|
86
|
-
|
|
87
|
-
export class MyComponent extends React.Component<ZappComponentProps> {
|
|
88
|
-
/* ... */
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
81
|
## Connecting my component to Zapp Pipes
|
|
93
82
|
|
|
94
83
|
Zapp App components rely on [Zapp-Pipes](https://github.com/applicaster/zapp-pipes) to load data.
|
|
@@ -100,10 +89,9 @@ In order to connect your component to ZappPipes, you simply need to use the `Zap
|
|
|
100
89
|
import * as React from "react";
|
|
101
90
|
import { View, Text } from "react-native";
|
|
102
91
|
import { zappPipesDataConnector } from "../ZappPipesDataConnector";
|
|
103
|
-
import type { ZappComponentProps } from "../../flow-types";
|
|
104
92
|
|
|
105
93
|
@zappPipesDataConnector
|
|
106
|
-
export class MyComponent extends React.Component
|
|
94
|
+
export class MyComponent extends React.Component {
|
|
107
95
|
renderComponent = (data) => {
|
|
108
96
|
return (
|
|
109
97
|
<View>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0-alpha.1102149799",
|
|
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,20 +34,26 @@
|
|
|
34
34
|
"redux-mock-store": "^1.5.3"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@applicaster/applicaster-types": "
|
|
38
|
-
"@applicaster/zapp-react-native-bridge": "
|
|
39
|
-
"@applicaster/zapp-react-native-redux": "
|
|
40
|
-
"@applicaster/zapp-react-native-utils": "
|
|
37
|
+
"@applicaster/applicaster-types": "13.0.0-alpha.1102149799",
|
|
38
|
+
"@applicaster/zapp-react-native-bridge": "13.0.0-alpha.1102149799",
|
|
39
|
+
"@applicaster/zapp-react-native-redux": "13.0.0-alpha.1102149799",
|
|
40
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.1102149799",
|
|
41
41
|
"promise": "^8.3.0",
|
|
42
42
|
"react-router-native": "^5.1.2",
|
|
43
43
|
"url": "^0.11.0",
|
|
44
44
|
"uuid": "^3.3.2"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
+
"@applicaster/zapp-pipes-v2-client": "*",
|
|
47
48
|
"@react-native-community/netinfo": "*",
|
|
49
|
+
"@types/node": "*",
|
|
50
|
+
"immer": "*",
|
|
48
51
|
"react": "17.0.2",
|
|
49
52
|
"react-native": "0.68.6",
|
|
50
53
|
"react-native-safe-area-context": "*",
|
|
51
|
-
"react-native-svg": "*"
|
|
54
|
+
"react-native-svg": "*",
|
|
55
|
+
"uglify-js": "*",
|
|
56
|
+
"validate-color": "*",
|
|
57
|
+
"zustand": "*"
|
|
52
58
|
}
|
|
53
59
|
}
|