@applicaster/zapp-react-native-utils 13.0.0-alpha.4135231530 → 13.0.0-alpha.4180140161

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 (91) hide show
  1. package/README.md +0 -10
  2. package/actionsExecutor/ActionExecutorContext.tsx +104 -6
  3. package/analyticsUtils/currentScreenProperities.ts +6 -4
  4. package/appUtils/HooksManager/Hook.ts +4 -0
  5. package/appUtils/HooksManager/index.ts +3 -1
  6. package/appUtils/__tests__/__snapshots__/localizationsHelper.test.ts.snap +151 -0
  7. package/appUtils/__tests__/allZappLocales.ts +79 -0
  8. package/appUtils/__tests__/{localizationsHelper.test.js → localizationsHelper.test.ts} +11 -0
  9. package/appUtils/contextKeysManager/contextResolver.ts +1 -12
  10. package/appUtils/contextKeysManager/index.ts +2 -2
  11. package/appUtils/contextKeysManager/utils/index.ts +2 -1
  12. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -0
  13. package/appUtils/focusManager/index.ts +22 -9
  14. package/appUtils/keyCodes/index.ts +11 -7
  15. package/appUtils/localizationsHelper.ts +31 -0
  16. package/appUtils/orientationHelper.ts +11 -13
  17. package/appUtils/platform/platformUtils.ts +30 -3
  18. package/appUtils/playerManager/index.ts +1 -1
  19. package/appUtils/playerManager/player.ts +24 -12
  20. package/appUtils/playerManager/playerNative.ts +18 -3
  21. package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +7 -1
  22. package/componentsUtils/__tests__/isFirstComponentGallery.test.ts +33 -0
  23. package/componentsUtils/__tests__/isFirstComponentScreenPicker.test.ts +33 -0
  24. package/componentsUtils/__tests__/isGallery.test.ts +33 -0
  25. package/componentsUtils/__tests__/isScreenPicker.test.ts +33 -0
  26. package/componentsUtils/index.ts +32 -0
  27. package/dateUtils/index.ts +19 -0
  28. package/equalUtils/__tests__/isEqual/combination.test.ts +263 -0
  29. package/equalUtils/index.ts +49 -30
  30. package/focusManager/FocusManager.ts +14 -2
  31. package/focusManager/index.ts +23 -4
  32. package/functionUtils/index.ts +46 -8
  33. package/index.d.ts +0 -12
  34. package/localizationUtils/index.ts +5 -10
  35. package/manifestUtils/__tests__/createConfig.test.js +0 -2
  36. package/manifestUtils/defaultManifestConfigurations/player.js +14 -0
  37. package/manifestUtils/fonts/index.js +5 -6
  38. package/manifestUtils/keys.js +9 -0
  39. package/manifestUtils/sharedConfiguration/screenPicker/__tests__/utils.test.js +304 -0
  40. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +875 -0
  41. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +130 -0
  42. package/modalState/__tests__/index.test.ts +51 -0
  43. package/modalState/index.ts +32 -2
  44. package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +1 -0
  45. package/navigationUtils/index.ts +3 -1
  46. package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +23 -3
  47. package/numberUtils/index.ts +11 -5
  48. package/package.json +4 -10
  49. package/playerUtils/configurationGenerator.ts +14 -0
  50. package/reactHooks/advertising/index.ts +5 -5
  51. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +5 -7
  52. package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
  53. package/reactHooks/feed/useFeedLoader.tsx +17 -8
  54. package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +39 -0
  55. package/reactHooks/layout/useDimensions/useDimensions.ts +8 -0
  56. package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
  57. package/reactHooks/navigation/__tests__/index.test.tsx +6 -17
  58. package/reactHooks/navigation/index.ts +13 -23
  59. package/reactHooks/navigation/useGetTabBarHeight.ts +1 -3
  60. package/reactHooks/navigation/useProfilerLogging.ts +15 -0
  61. package/reactHooks/navigation/useRoute.ts +4 -6
  62. package/reactHooks/state/useRefWithInitialValue.ts +14 -0
  63. package/reactHooks/state/useStateFromSubscribe.ts +23 -0
  64. package/reactUtils/__tests__/__snapshots__/reactUtilsHelpers.test.js.snap +16 -4
  65. package/reactUtils/__tests__/reactUtils.test.js +1 -19
  66. package/reactUtils/__tests__/reactUtilsHelpers.test.js +72 -71
  67. package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +6 -72
  68. package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -28
  69. package/reactUtils/createContext/__tests__/__snapshots__/withConsumer.test.js.snap +3 -4
  70. package/reactUtils/createContext/__tests__/__snapshots__/withProvider.test.js.snap +7 -3
  71. package/reactUtils/createContext/__tests__/helpers.test.js +107 -121
  72. package/reactUtils/createContext/__tests__/{index.test.js → index.test.ts} +2 -2
  73. package/reactUtils/createContext/__tests__/provider.test.js +4 -6
  74. package/reactUtils/createContext/__tests__/withConsumer.test.js +12 -12
  75. package/reactUtils/createContext/__tests__/withProvider.test.js +4 -4
  76. package/reactUtils/createContext/helpers.ts +6 -1
  77. package/reactUtils/createContext/index.ts +11 -25
  78. package/reactUtils/index.ts +0 -11
  79. package/services/js2native.ts +673 -0
  80. package/testUtils/index.tsx +0 -10
  81. package/time/BackgroundTimer.ts +55 -0
  82. package/time/Timer.ts +6 -6
  83. package/utils/README.md +30 -0
  84. package/utils/chunk.ts +5 -0
  85. package/utils/index.ts +5 -0
  86. package/utils/times.ts +5 -0
  87. package/zappFrameworkUtils/localStorageHelper.ts +6 -0
  88. package/zappFrameworkUtils/loginPluginUtils.ts +6 -2
  89. package/zappFrameworkUtils/types.ts +11 -0
  90. package/reactUtils/createContext/__tests__/index-no-react.test.js +0 -27
  91. /package/reactUtils/createContext/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
package/README.md CHANGED
@@ -376,16 +376,6 @@ useEffect(() => {
376
376
  }, []);
377
377
  ```
378
378
 
379
- ### testUtils
380
-
381
- `@applicaster/zapp-react-native-utils/testUtils`
382
-
383
- - `testIDEquals: (testId: any) => boolean | { width: number, height: number }` - Function to be used in tandem with enzyme findWhere
384
-
385
- ```javascript
386
- wrapper.findWhere(testIDEquals("text"));
387
- ```
388
-
389
379
  ### appUtils - contextKeysManager
390
380
 
391
381
  `@applicaster/zapp-react-native-utils/appUtils/contextKeyManager`
@@ -1,6 +1,6 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
3
- import React, { createContext, useMemo } from "react";
3
+ import React, { createContext, useEffect, useMemo } from "react";
4
4
  import {
5
5
  actionExecutor as _actionExecutor,
6
6
  ActionResult,
@@ -19,8 +19,15 @@ import {
19
19
  EntryResolver,
20
20
  resolveObjectValues,
21
21
  } from "../appUtils/contextKeysManager/contextResolver";
22
+ import { useNavigation } from "../reactHooks";
23
+ import { get } from "lodash";
22
24
 
23
- const { log_error, log_info } = createLogger({
25
+ import {
26
+ useContentTypes,
27
+ usePickFromState,
28
+ } from "@applicaster/zapp-react-native-redux/hooks";
29
+
30
+ export const { log_error, log_info, log_debug } = createLogger({
24
31
  subsystem: "ActionExecutorContext",
25
32
  category: "General",
26
33
  });
@@ -51,6 +58,22 @@ type Props = {
51
58
  children: React.ReactNode;
52
59
  };
53
60
 
61
+ function findParentComponent(
62
+ childId: string,
63
+ parent: ZappRiver | ZappUIComponent
64
+ ): ZappRiver | ZappUIComponent | null {
65
+ for (const child of parent.ui_components) {
66
+ if (child.id === childId) return parent;
67
+
68
+ if (child.ui_components) {
69
+ const found = findParentComponent(childId, child);
70
+ if (found) return found;
71
+ }
72
+ }
73
+
74
+ return null;
75
+ }
76
+
54
77
  const prepareDefaultActions = (actionExecutor) => {
55
78
  actionExecutor.registerAction("localStorageSet", async (action) => {
56
79
  const namespaces = action.options.content;
@@ -65,11 +88,13 @@ const prepareDefaultActions = (actionExecutor) => {
65
88
  async (_action, context) => {
66
89
  const dispatch = appStore.getDispatch();
67
90
 
68
- log_info("handleAction: refreshComponent event");
91
+ const dataSource =
92
+ context?.component?.data?.source ||
93
+ findParentComponent(context?.component.id, context?.screenData)?.data
94
+ ?.source;
69
95
 
70
- const dataSource = context?.component?.data?.source;
96
+ log_info(`handleAction: refreshComponent for dataSource:${dataSource}`);
71
97
 
72
- // TODO: Later we can pass component ids to do refresh instead of current one
73
98
  // TODO: In theory we should wait callback to complete, before completing the action, but now it's not needed
74
99
  // TODO: handle focused item removal
75
100
  dispatch(
@@ -169,8 +194,29 @@ const prepareDefaultActions = (actionExecutor) => {
169
194
  action: ActionType,
170
195
  context?: Record<string, any>
171
196
  ): Promise<ActionResult> => {
197
+ if (!context) {
198
+ log_error(
199
+ "handleAction: localStorageToggleFlag action missing context"
200
+ );
201
+
202
+ return ActionResult.Error;
203
+ }
204
+
205
+ const entry = context?.entry as ZappEntry;
206
+
207
+ if (!entry) {
208
+ log_error(
209
+ "handleAction: localStorageToggleFlag action missing entry. Entry is required to get the tag."
210
+ );
211
+
212
+ return ActionResult.Error;
213
+ }
214
+
215
+ const tag = action.options?.selector
216
+ ? get(entry, action.options.selector)
217
+ : (entry.extensions?.tag ?? entry.id);
218
+
172
219
  const keyNamespace = action.options?.key;
173
- const tag = context?.entry?.extensions?.tag;
174
220
 
175
221
  if (keyNamespace && tag) {
176
222
  const multiSelectProvider =
@@ -188,6 +234,16 @@ const prepareDefaultActions = (actionExecutor) => {
188
234
  if (selectedItems.includes(tag)) {
189
235
  await multiSelectProvider.removeItem(tag);
190
236
  } else {
237
+ const maxItems = action.options?.max_items;
238
+
239
+ if (maxItems && selectedItems.length >= maxItems) {
240
+ log_info(
241
+ `handleAction: localStorageToggleFlag event reached max items limit: ${maxItems}, cannot add tag: ${tag}`
242
+ );
243
+
244
+ return ActionResult.Cancel;
245
+ }
246
+
191
247
  await multiSelectProvider.addItem(tag);
192
248
  }
193
249
  } else {
@@ -211,6 +267,10 @@ export function withActionExecutor(Component) {
211
267
  prepareDefaultActions(_actionExecutor);
212
268
 
213
269
  return function ActionExecutorComponent(props: Props) {
270
+ const navigator = useNavigation();
271
+ const { rivers } = usePickFromState(["rivers"]);
272
+ const contentTypes = useContentTypes();
273
+
214
274
  const handlers = useMemo(() => {
215
275
  return {
216
276
  unregisterAction: _actionExecutor.unregisterAction,
@@ -221,6 +281,44 @@ export function withActionExecutor(Component) {
221
281
  };
222
282
  }, []);
223
283
 
284
+ useEffect(() => {
285
+ return _actionExecutor.registerAction(
286
+ "navigateToScreen",
287
+ async (action: ActionType, context?: Record<string, any>) => {
288
+ const screenType = action.options?.typeMapping;
289
+
290
+ if (!screenType) {
291
+ log_error("navigateToScreen: typeMapping option is missing");
292
+
293
+ return ActionResult.Error;
294
+ }
295
+
296
+ const screenId = contentTypes?.[screenType]?.screen_id || null;
297
+
298
+ if (!screenId) {
299
+ log_error(
300
+ `navigateToScreen: can not resolve screen type mapping: ${screenType}`
301
+ );
302
+
303
+ return ActionResult.Error;
304
+ }
305
+
306
+ const river = rivers[screenId];
307
+
308
+ if (!river) {
309
+ log_error("navigateToScreen: can not resolve river");
310
+
311
+ return ActionResult.Error;
312
+ }
313
+
314
+ context?.callback?.({ success: false, error: null, abort: true });
315
+ navigator.replace(river);
316
+
317
+ return ActionResult.Success;
318
+ }
319
+ );
320
+ }, [navigator, rivers, contentTypes]);
321
+
224
322
  return (
225
323
  <ActionExecutorContext.Provider value={handlers}>
226
324
  <Component {...props} />
@@ -72,12 +72,14 @@ const mappedScreenPropertiesScreen = (
72
72
  screenData
73
73
  ): AnalyticsScreenProperties => {
74
74
  return {
75
- screen_name: screenData?.targetScreen?.name,
75
+ screen_name: screenData?.targetScreen?.name || screenData?.name,
76
76
  screen_entry_title: screenData?.title,
77
77
  screen_entry_id: R.isNil(screenData?.type) ? null : screenData?.id,
78
- screen_layout_id: screenData?.targetScreen?.id,
79
- screen_type: screenData?.targetScreen?.type,
80
- home_screen: screenData?.targetScreen?.home,
78
+ screen_layout_id: screenData?.targetScreen?.id || screenData?.id,
79
+ screen_type: screenData?.targetScreen?.type || screenData?.type,
80
+ home_screen: !R.isNil(screenData?.targetScreen?.home)
81
+ ? screenData?.targetScreen?.home
82
+ : screenData?.home,
81
83
  };
82
84
  };
83
85
 
@@ -65,6 +65,10 @@ export class Hook implements HookInterface {
65
65
  event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
66
66
  ...args
67
67
  ) {
68
+ if (this.state === hookState(HOOKS_EVENTS.CANCEL)) {
69
+ return;
70
+ }
71
+
68
72
  this.state = hookState(event);
69
73
  this.manager.subscriber.invokeHandler(event, ...args);
70
74
  }
@@ -84,7 +84,7 @@ export function HooksManager({
84
84
  plugins,
85
85
  startUpHooksData = {},
86
86
  }: HookManagerArgs): HookManager {
87
- hooksManagerLogger.addContext({ targetScreen });
87
+ hooksManagerLogger.addContext({ targetScreenId: targetScreen.id });
88
88
 
89
89
  function logHookEvent(func, message, data) {
90
90
  func({
@@ -269,6 +269,7 @@ export function HooksManager({
269
269
  payload = initialPayload,
270
270
  callback: callbackArg,
271
271
  cancelled,
272
+ abort,
272
273
  }) {
273
274
  let callback = callbackArg;
274
275
 
@@ -308,6 +309,7 @@ export function HooksManager({
308
309
  hookPlugin.setStateAndNotify(HOOKS_EVENTS.CANCEL, {
309
310
  hookPlugin,
310
311
  payload,
312
+ abort,
311
313
  });
312
314
 
313
315
  const isHookInHomescreen = payload?.home;
@@ -0,0 +1,151 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`toDayJSLocaleMap [af] returns a valid dayjs locale 1`] = `"af"`;
4
+
5
+ exports[`toDayJSLocaleMap [ar] returns a valid dayjs locale 1`] = `"ar"`;
6
+
7
+ exports[`toDayJSLocaleMap [bg] returns a valid dayjs locale 1`] = `"bg"`;
8
+
9
+ exports[`toDayJSLocaleMap [bn] returns a valid dayjs locale 1`] = `"bn"`;
10
+
11
+ exports[`toDayJSLocaleMap [bo] returns a valid dayjs locale 1`] = `"bo"`;
12
+
13
+ exports[`toDayJSLocaleMap [ca] returns a valid dayjs locale 1`] = `"ca"`;
14
+
15
+ exports[`toDayJSLocaleMap [cs] returns a valid dayjs locale 1`] = `"cs"`;
16
+
17
+ exports[`toDayJSLocaleMap [da] returns a valid dayjs locale 1`] = `"da"`;
18
+
19
+ exports[`toDayJSLocaleMap [de] returns a valid dayjs locale 1`] = `"de"`;
20
+
21
+ exports[`toDayJSLocaleMap [el] returns a valid dayjs locale 1`] = `"el"`;
22
+
23
+ exports[`toDayJSLocaleMap [en] returns a valid dayjs locale 1`] = `"en"`;
24
+
25
+ exports[`toDayJSLocaleMap [en-GB] returns a valid dayjs locale 1`] = `"en-gb"`;
26
+
27
+ exports[`toDayJSLocaleMap [en-UK] returns a valid dayjs locale 1`] = `"en-gb"`;
28
+
29
+ exports[`toDayJSLocaleMap [es] returns a valid dayjs locale 1`] = `"es"`;
30
+
31
+ exports[`toDayJSLocaleMap [es-LA] returns a valid dayjs locale 1`] = `"es"`;
32
+
33
+ exports[`toDayJSLocaleMap [es-MX] returns a valid dayjs locale 1`] = `"es-mx"`;
34
+
35
+ exports[`toDayJSLocaleMap [es-US] returns a valid dayjs locale 1`] = `"es-us"`;
36
+
37
+ exports[`toDayJSLocaleMap [et] returns a valid dayjs locale 1`] = `"et"`;
38
+
39
+ exports[`toDayJSLocaleMap [eu] returns a valid dayjs locale 1`] = `"eu"`;
40
+
41
+ exports[`toDayJSLocaleMap [fa] returns a valid dayjs locale 1`] = `"fa"`;
42
+
43
+ exports[`toDayJSLocaleMap [fi] returns a valid dayjs locale 1`] = `"fi"`;
44
+
45
+ exports[`toDayJSLocaleMap [fj] returns a valid dayjs locale 1`] = `"en"`;
46
+
47
+ exports[`toDayJSLocaleMap [fr] returns a valid dayjs locale 1`] = `"fr"`;
48
+
49
+ exports[`toDayJSLocaleMap [ga] returns a valid dayjs locale 1`] = `"ga"`;
50
+
51
+ exports[`toDayJSLocaleMap [gu] returns a valid dayjs locale 1`] = `"gu"`;
52
+
53
+ exports[`toDayJSLocaleMap [he] returns a valid dayjs locale 1`] = `"he"`;
54
+
55
+ exports[`toDayJSLocaleMap [hi] returns a valid dayjs locale 1`] = `"hi"`;
56
+
57
+ exports[`toDayJSLocaleMap [hr] returns a valid dayjs locale 1`] = `"hr"`;
58
+
59
+ exports[`toDayJSLocaleMap [hu] returns a valid dayjs locale 1`] = `"hu"`;
60
+
61
+ exports[`toDayJSLocaleMap [hy] returns a valid dayjs locale 1`] = `"hy-am"`;
62
+
63
+ exports[`toDayJSLocaleMap [id] returns a valid dayjs locale 1`] = `"id"`;
64
+
65
+ exports[`toDayJSLocaleMap [is] returns a valid dayjs locale 1`] = `"is"`;
66
+
67
+ exports[`toDayJSLocaleMap [it] returns a valid dayjs locale 1`] = `"it"`;
68
+
69
+ exports[`toDayJSLocaleMap [ja] returns a valid dayjs locale 1`] = `"ja"`;
70
+
71
+ exports[`toDayJSLocaleMap [ka] returns a valid dayjs locale 1`] = `"ka"`;
72
+
73
+ exports[`toDayJSLocaleMap [km] returns a valid dayjs locale 1`] = `"km"`;
74
+
75
+ exports[`toDayJSLocaleMap [ko] returns a valid dayjs locale 1`] = `"ko"`;
76
+
77
+ exports[`toDayJSLocaleMap [la] returns a valid dayjs locale 1`] = `"en"`;
78
+
79
+ exports[`toDayJSLocaleMap [lt] returns a valid dayjs locale 1`] = `"lt"`;
80
+
81
+ exports[`toDayJSLocaleMap [lv] returns a valid dayjs locale 1`] = `"lv"`;
82
+
83
+ exports[`toDayJSLocaleMap [mi] returns a valid dayjs locale 1`] = `"mi"`;
84
+
85
+ exports[`toDayJSLocaleMap [mk] returns a valid dayjs locale 1`] = `"mk"`;
86
+
87
+ exports[`toDayJSLocaleMap [ml] returns a valid dayjs locale 1`] = `"ml"`;
88
+
89
+ exports[`toDayJSLocaleMap [mn] returns a valid dayjs locale 1`] = `"mn"`;
90
+
91
+ exports[`toDayJSLocaleMap [mr] returns a valid dayjs locale 1`] = `"mr"`;
92
+
93
+ exports[`toDayJSLocaleMap [ms] returns a valid dayjs locale 1`] = `"ms"`;
94
+
95
+ exports[`toDayJSLocaleMap [mt] returns a valid dayjs locale 1`] = `"mt"`;
96
+
97
+ exports[`toDayJSLocaleMap [ne] returns a valid dayjs locale 1`] = `"ne"`;
98
+
99
+ exports[`toDayJSLocaleMap [nl] returns a valid dayjs locale 1`] = `"nl"`;
100
+
101
+ exports[`toDayJSLocaleMap [no] returns a valid dayjs locale 1`] = `"en"`;
102
+
103
+ exports[`toDayJSLocaleMap [pa] returns a valid dayjs locale 1`] = `"pa-in"`;
104
+
105
+ exports[`toDayJSLocaleMap [pl] returns a valid dayjs locale 1`] = `"pl"`;
106
+
107
+ exports[`toDayJSLocaleMap [pt] returns a valid dayjs locale 1`] = `"pt"`;
108
+
109
+ exports[`toDayJSLocaleMap [pt-BR] returns a valid dayjs locale 1`] = `"pt-br"`;
110
+
111
+ exports[`toDayJSLocaleMap [qu] returns a valid dayjs locale 1`] = `"en"`;
112
+
113
+ exports[`toDayJSLocaleMap [ro] returns a valid dayjs locale 1`] = `"ro"`;
114
+
115
+ exports[`toDayJSLocaleMap [ru] returns a valid dayjs locale 1`] = `"ru"`;
116
+
117
+ exports[`toDayJSLocaleMap [sk] returns a valid dayjs locale 1`] = `"sk"`;
118
+
119
+ exports[`toDayJSLocaleMap [sl] returns a valid dayjs locale 1`] = `"sl"`;
120
+
121
+ exports[`toDayJSLocaleMap [sm] returns a valid dayjs locale 1`] = `"en"`;
122
+
123
+ exports[`toDayJSLocaleMap [sq] returns a valid dayjs locale 1`] = `"sq"`;
124
+
125
+ exports[`toDayJSLocaleMap [sr] returns a valid dayjs locale 1`] = `"sr"`;
126
+
127
+ exports[`toDayJSLocaleMap [sv] returns a valid dayjs locale 1`] = `"sv"`;
128
+
129
+ exports[`toDayJSLocaleMap [sw] returns a valid dayjs locale 1`] = `"sw"`;
130
+
131
+ exports[`toDayJSLocaleMap [ta] returns a valid dayjs locale 1`] = `"ta"`;
132
+
133
+ exports[`toDayJSLocaleMap [te] returns a valid dayjs locale 1`] = `"te"`;
134
+
135
+ exports[`toDayJSLocaleMap [th] returns a valid dayjs locale 1`] = `"th"`;
136
+
137
+ exports[`toDayJSLocaleMap [to] returns a valid dayjs locale 1`] = `"en"`;
138
+
139
+ exports[`toDayJSLocaleMap [tr] returns a valid dayjs locale 1`] = `"tr"`;
140
+
141
+ exports[`toDayJSLocaleMap [tt] returns a valid dayjs locale 1`] = `"en"`;
142
+
143
+ exports[`toDayJSLocaleMap [uk] returns a valid dayjs locale 1`] = `"uk"`;
144
+
145
+ exports[`toDayJSLocaleMap [ur] returns a valid dayjs locale 1`] = `"ur"`;
146
+
147
+ exports[`toDayJSLocaleMap [uz] returns a valid dayjs locale 1`] = `"uz"`;
148
+
149
+ exports[`toDayJSLocaleMap [vi] returns a valid dayjs locale 1`] = `"vi"`;
150
+
151
+ exports[`toDayJSLocaleMap [zh] returns a valid dayjs locale 1`] = `"zh"`;
@@ -0,0 +1,79 @@
1
+ export default [
2
+ // common locales from https://rubygems.org/gems/language_list
3
+ "en",
4
+ "fr",
5
+ "de",
6
+ "nl",
7
+ "ru",
8
+ "es",
9
+ "he",
10
+ "hy",
11
+ "sq",
12
+ "af",
13
+ "ar",
14
+ "eu",
15
+ "bn",
16
+ "bg",
17
+ "zh",
18
+ "cs",
19
+ "km",
20
+ "ca",
21
+ "hr",
22
+ "da",
23
+ "et",
24
+ "fj",
25
+ "fi",
26
+ "gu",
27
+ "ka",
28
+ "hu",
29
+ "hi",
30
+ "it",
31
+ "is",
32
+ "id",
33
+ "ga",
34
+ "ja",
35
+ "ko",
36
+ "la",
37
+ "lv",
38
+ "lt",
39
+ "ms",
40
+ "mi",
41
+ "mn",
42
+ "mt",
43
+ "mk",
44
+ "el",
45
+ "mr",
46
+ "ml",
47
+ "ne",
48
+ "no",
49
+ "pa",
50
+ "pl",
51
+ "pt",
52
+ "fa",
53
+ "qu",
54
+ "ro",
55
+ "sk",
56
+ "sm",
57
+ "sr",
58
+ "sw",
59
+ "sv",
60
+ "sl",
61
+ "to",
62
+ "tr",
63
+ "th",
64
+ "te",
65
+ "bo",
66
+ "tt",
67
+ "ta",
68
+ "uk",
69
+ "ur",
70
+ "uz",
71
+ "vi",
72
+ // Extra locales https://github.com/applicaster/zapp/blob/5604794f15cfd270ae494b0db85e542de4cebfaa/config/additional_languages.yml
73
+ "en-UK",
74
+ "en-GB",
75
+ "es-LA",
76
+ "pt-BR",
77
+ "es-MX",
78
+ "es-US",
79
+ ];
@@ -8,6 +8,7 @@ const {
8
8
  getLocale,
9
9
  getLanguageCode,
10
10
  getCountryCode,
11
+ toDayJSLocaleMap,
11
12
  } = require("../localizationsHelper");
12
13
 
13
14
  describe("getLocale", () => {
@@ -69,3 +70,13 @@ describe("getCountryCode", () => {
69
70
  expect(currentValue).toEqual(expectedValue);
70
71
  });
71
72
  });
73
+
74
+ describe("toDayJSLocaleMap", () => {
75
+ const allZappLocales: string[] = require("./allZappLocales").default;
76
+
77
+ it.each(allZappLocales)("[%s] returns a valid dayjs locale", (locale) => {
78
+ const dayJSLocale = toDayJSLocaleMap(locale);
79
+ expect(dayJSLocale).toBeDefined();
80
+ expect(dayJSLocale).toMatchSnapshot();
81
+ });
82
+ });
@@ -1,12 +1,6 @@
1
- import { createLogger } from "../../logger";
2
1
  import { ContextKeysManager } from "./index";
3
2
  import * as R from "ramda";
4
3
 
5
- const { log_error } = createLogger({
6
- subsystem: "contextResolver",
7
- category: "General",
8
- });
9
-
10
4
  interface IResolver {
11
5
  resolve: (string) => Promise<string | number | object>;
12
6
  }
@@ -64,12 +58,7 @@ export const resolveObjectValues = async (
64
58
  return [key, resolvedValue];
65
59
  }
66
60
 
67
- log_error("resolveObjectValues: invalid context string", {
68
- key,
69
- value,
70
- });
71
-
72
- return [key, null];
61
+ return [key, value];
73
62
  })
74
63
  );
75
64
 
@@ -16,12 +16,12 @@ import {
16
16
 
17
17
  export { StorageLevel };
18
18
 
19
- type KeyNameObj = {
19
+ export type KeyNameObj = {
20
20
  namespace: string;
21
21
  key: string;
22
22
  };
23
23
 
24
- type KeyName = string | KeyNameObj;
24
+ export type KeyName = string | KeyNameObj;
25
25
 
26
26
  type ParsedKeyAndNamespace = {
27
27
  namespace?: string;
@@ -1,10 +1,11 @@
1
1
  import * as R from "ramda";
2
2
  import { DEFAULT_NAMESPACE } from "../consts";
3
+ import { KeyName, KeyNameObj } from "../index";
3
4
 
4
5
  const lastDotRegex = /\.([^.]+)$/;
5
6
  const splitByLastDot = R.compose(R.init, R.split(lastDotRegex));
6
7
 
7
- export function getNamespaceAndKey(namespacedKey) {
8
+ export function getNamespaceAndKey(namespacedKey: KeyName): KeyNameObj {
8
9
  if (typeof namespacedKey !== "string") return namespacedKey;
9
10
 
10
11
  const namespacedKeyProps = namespacedKey.includes(".")
@@ -5,6 +5,7 @@ exports[`focusManager should be defined 1`] = `
5
5
  "blur": [Function],
6
6
  "disableFocus": [Function],
7
7
  "enableFocus": [Function],
8
+ "findPreferredFocusChild": [Function],
8
9
  "focusableTree": Tree {
9
10
  "loadingCounter": 0,
10
11
  "root": {
@@ -28,6 +29,7 @@ exports[`focusManager should be defined 1`] = `
28
29
  "moveFocus": [Function],
29
30
  "on": [Function],
30
31
  "press": [Function],
32
+ "pressIn": [Function],
31
33
  "pressOut": [Function],
32
34
  "recoverFocus": [Function],
33
35
  "register": [Function],
@@ -334,15 +334,14 @@ export const focusManager = (function () {
334
334
  return { success: false };
335
335
  }
336
336
 
337
- function treeLoaded(val, node) {
338
- logger.log({
339
- message: "treeLoaded",
340
- data: {
341
- val,
342
- node,
343
- currentFocusNode,
344
- },
345
- });
337
+ function treeLoaded(_val, _node) {}
338
+
339
+ function pressIn() {
340
+ const currentFocusable = getCurrentFocus();
341
+
342
+ if (currentFocusable) {
343
+ currentFocusable.pressIn(null);
344
+ }
346
345
  }
347
346
 
348
347
  /**
@@ -535,6 +534,18 @@ export const focusManager = (function () {
535
534
 
536
535
  const { on, invokeHandler, removeHandler } = eventHandler;
537
536
 
537
+ function findPreferredFocusChild(id) {
538
+ const node = getCurrentFocusNode(id);
539
+
540
+ const preferredFocus = findPriorityItem([node]);
541
+
542
+ if (isNilOrEmpty(preferredFocus)) {
543
+ return undefined;
544
+ }
545
+
546
+ return preferredFocus[0];
547
+ }
548
+
538
549
  /**
539
550
  * this is the list of the functions available externally
540
551
  * when importing the focus manager
@@ -552,6 +563,7 @@ export const focusManager = (function () {
552
563
  invokeHandler,
553
564
  removeHandler,
554
565
  longPress,
566
+ pressIn,
555
567
  pressOut,
556
568
  enableFocus,
557
569
  setInitialFocus,
@@ -563,5 +575,6 @@ export const focusManager = (function () {
563
575
  isGroupItemFocused,
564
576
  recoverFocus,
565
577
  isCurrentFocusOnTheTopScreen,
578
+ findPreferredFocusChild,
566
579
  };
567
580
  })();
@@ -1,5 +1,3 @@
1
- import * as R from "ramda";
2
-
3
1
  // more keys can be added here. Simply make sure
4
2
  // the key matches the code value
5
3
 
@@ -34,12 +32,18 @@ export function keyCode(key) {
34
32
  keyCode(keyEvent).matchesAny("Enter", "Backspace", KEYS.ArrowLeft, ...)
35
33
  */
36
34
 
37
- const matches = R.compose(
38
- R.either(R.eqProps("code", key), R.eqProps("keyCode", key)),
39
- R.when(R.is(String), R.prop(R.__, KEYS))
40
- );
35
+ const matches = (compareKey) => {
36
+ // If compareKey is a string, look it up in KEYS object
37
+ const keyToCompare =
38
+ typeof compareKey === "string" ? KEYS[compareKey] : compareKey;
39
+
40
+ // Compare either code or keyCode properties
41
+ return (
42
+ keyToCompare?.code === key.code || keyToCompare?.keyCode === key.keyCode
43
+ );
44
+ };
41
45
 
42
- const matchesAny = (...args) => R.any(matches, args);
46
+ const matchesAny = (...args) => args.some(matches);
43
47
 
44
48
  const direction = () =>
45
49
  matchesAny(...ARROW_KEYS) ? directionHelper(key) : null;
@@ -65,6 +65,37 @@ export function getUILanguage() {
65
65
  return getLanguageCode();
66
66
  }
67
67
 
68
+ /**
69
+ * fallback to en for missing dayjslocalization
70
+ * converts the locale code to a dayjs compatible locale code
71
+ * lowercase input code is expected, e.g. "en-GB" => "en-gb"
72
+ * @param {string} code - locale code, e.g. "en", "fr", "es-LA"
73
+ * */
74
+ export const toDayJSLocaleMap = (code) => {
75
+ const map = {
76
+ hy: "hy-am",
77
+ fj: null,
78
+ la: null,
79
+ no: null,
80
+ pa: "pa-in",
81
+ qu: null,
82
+ sm: null,
83
+ to: null,
84
+ xh: null,
85
+ tt: null,
86
+ "es-LA": "es",
87
+ "en-UK": "en-gb",
88
+ };
89
+
90
+ if (map[code] === null) {
91
+ return "en";
92
+ } else if (map[code]) {
93
+ return map[code];
94
+ } else {
95
+ return code.toLowerCase();
96
+ }
97
+ };
98
+
68
99
  /**
69
100
  * returns the localization for the app based on the locale. If the locale is null
70
101
  * or undefined, or if the given locale doesn't exist in the localizations,