@24i/bigscreen-sdk 1.1.0 → 2.1.1-alpha.2133

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 (256) hide show
  1. package/README.md +1 -1
  2. package/package.json +34 -53
  3. package/packages/adobe-heartbeat/src/AdobeHeartbeat.ts +9 -9
  4. package/packages/async-image/src/AsyncImage.tsx +10 -15
  5. package/packages/developer-tools/PlayerDebugWindow/README.md +1 -1
  6. package/packages/developer-tools/src/DeveloperToolsService/DeveloperToolsList.tsx +0 -11
  7. package/packages/developer-tools/src/PlayerDebugWindow/PlayerDebugWindow.tsx +5 -5
  8. package/packages/developer-tools/src/PlayerDebugWindow/constants.ts +0 -15
  9. package/packages/developer-tools/src/TechnicalInfo/TechnicalInfoDetail.tsx +1 -2
  10. package/packages/developer-tools/src/TechnicalInfo/TechnicalInfoProvider.ts +3 -34
  11. package/packages/developer-tools/src/TechnicalInfo/__mocks__/Device.ts +0 -4
  12. package/packages/developer-tools/src/TechnicalInfo/translations.ts +0 -4
  13. package/packages/device/src/getKeyDigit.ts +2 -2
  14. package/packages/device/src/resolver/resolver.ts +5 -18
  15. package/packages/digital-clock/src/DigitalClock.tsx +4 -15
  16. package/packages/driver-androidtv/src/DeviceAndroidTV.ts +9 -54
  17. package/packages/driver-androidtv/src/__mocks__/javaScriptBridge.ts +5 -29
  18. package/packages/driver-androidtv/src/keymap.ts +0 -18
  19. package/packages/driver-androidtv/src/types.ts +16 -102
  20. package/packages/driver-base/src/DeviceBase.ts +2 -61
  21. package/packages/driver-base/src/KeyMap/Key.ts +1 -8
  22. package/packages/driver-base/src/KeyMap/KeyMap.ts +0 -4
  23. package/packages/driver-base/src/KeyMap/interface.ts +0 -1
  24. package/packages/driver-base/src/KeyMap/overrideValues.ts +1 -2
  25. package/packages/driver-base/src/__mocks__/keyMap.ts +0 -1
  26. package/packages/driver-base/src/types/DeviceEvent.ts +0 -2
  27. package/packages/driver-base/src/types/KeycodeKeyMap.ts +0 -1
  28. package/packages/driver-browser/src/keymap.ts +0 -8
  29. package/packages/driver-entone/src/keymap.ts +0 -1
  30. package/packages/driver-tizen/src/TizenKeys.ts +0 -2
  31. package/packages/driver-vidaa/src/DeviceVidaa.ts +2 -3
  32. package/packages/driver-vidaa/src/__mocks__/vidaa.ts +1 -1
  33. package/packages/driver-vidaa/src/keymap.ts +0 -2
  34. package/packages/driver-webos/src/DeviceWebos.ts +0 -8
  35. package/packages/driver-webos/src/keymap.ts +1 -2
  36. package/packages/driver-xbox/src/keymap.ts +1 -1
  37. package/packages/epg/README.md +1 -3
  38. package/packages/epg/src/v2/Cell.tsx +2 -16
  39. package/packages/epg/src/v2/DataManager.ts +41 -112
  40. package/packages/epg/src/v2/DatePicker.tsx +3 -9
  41. package/packages/epg/src/v2/DateToast/DateToast.tsx +9 -12
  42. package/packages/epg/src/v2/Day.tsx +3 -6
  43. package/packages/epg/src/v2/Epg.tsx +5 -5
  44. package/packages/epg/src/v2/MockGenerator/generator.ts +2 -3
  45. package/packages/epg/src/v2/ProgramInfo/utils.ts +3 -4
  46. package/packages/epg/src/v2/Row.tsx +1 -3
  47. package/packages/epg/src/v2/TimelineSection.tsx +1 -4
  48. package/packages/epg/src/v2/basic/CellsManager.tsx +2 -7
  49. package/packages/epg/src/v2/basic/RowsManager.tsx +1 -3
  50. package/packages/epg/src/v2/interface.ts +0 -13
  51. package/packages/events-manager/src/EventsManager.ts +56 -1
  52. package/packages/focus/README.md +0 -33
  53. package/packages/focus/src/IFocusable.ts +0 -1
  54. package/packages/focus/src/Layout/Base.tsx +6 -41
  55. package/packages/focus/src/Layout/Matrix.tsx +19 -51
  56. package/packages/focus/src/Layout/__test__/Base.spec.ts +180 -0
  57. package/packages/focus/src/Layout/__test__/Horizontal.spec.ts +94 -0
  58. package/packages/focus/src/Layout/__test__/Matrix.spec.ts +261 -0
  59. package/packages/focus/src/Layout/__test__/Vertical.spec.ts +46 -0
  60. package/packages/focus/src/Layout/__test__/isRtl.spec.ts +23 -0
  61. package/packages/focus/src/Layout/__test__/shared.ts +19 -0
  62. package/packages/focus/src/focusFirstExisting.ts +1 -7
  63. package/packages/focus/src/index.ts +1 -2
  64. package/packages/gallup/src/Gallup.ts +3 -3
  65. package/packages/grid/src/Base/Base.tsx +10 -15
  66. package/packages/grid/src/FirstOnlyGrid/FirstOnlyGrid.tsx +2 -4
  67. package/packages/icon/src/Icon.tsx +5 -27
  68. package/packages/input/README.md +1 -4
  69. package/packages/input/src/Input.tsx +29 -65
  70. package/packages/input/src/handleOverflow.ts +29 -0
  71. package/packages/interactable/README.md +1 -2
  72. package/packages/interactable/src/Interactable.tsx +3 -9
  73. package/packages/interactable/src/interface.ts +0 -1
  74. package/packages/jsx/src/index.ts +1 -1
  75. package/packages/jsx/src/test-utils/index.ts +0 -1
  76. package/packages/keyboard/src/Backdrop/Backdrop.scss +0 -2
  77. package/packages/keyboard/src/KeyboardBase.tsx +4 -16
  78. package/packages/keyboard/src/WhitelabelKeyboard/Keyboard.scss +0 -4
  79. package/packages/keyboard/src/WhitelabelKeyboard/Keyboard.tsx +20 -28
  80. package/packages/keyboard/src/WhitelabelKeyboard/_sizes.1080.scss +0 -1
  81. package/packages/keyboard/src/WhitelabelKeyboard/_sizes.scss +0 -1
  82. package/packages/keyboard/src/WhitelabelKeyboard/layouts/index.ts +0 -11
  83. package/packages/keyboard/src/WhitelabelKeyboard/types.ts +0 -1
  84. package/packages/l10n/README.md +0 -18
  85. package/packages/l10n/src/date/common.ts +6 -18
  86. package/packages/l10n/src/date/cs.ts +8 -2
  87. package/packages/l10n/src/date/en-001.ts +3 -3
  88. package/packages/l10n/src/date/en-common.ts +4 -5
  89. package/packages/l10n/src/date/en-us.ts +3 -3
  90. package/packages/l10n/src/date/iso.ts +13 -12
  91. package/packages/l10n/src/date/types.ts +0 -9
  92. package/packages/l10n/src/l10n.ts +3 -61
  93. package/packages/list/src/Base/Base.tsx +9 -19
  94. package/packages/list/src/Base/interface.ts +2 -2
  95. package/packages/list/src/CenteredList/controller.ts +1 -0
  96. package/packages/list/src/EdgeOffsetList/EdgeOffsetList.tsx +3 -3
  97. package/packages/list/src/UnifiedListController/UnifiedListController.ts +2 -6
  98. package/packages/logger/src/loggers/SentryLogger/Sentry.ts +0 -1
  99. package/packages/logger/src/loggers/SentryLogger/SentryLogger.ts +2 -2
  100. package/packages/menu/src/MenuAndContentContainer/MenuAndContentContainer.tsx +3 -31
  101. package/packages/menu/src/MenuAndContentContainer/interface.ts +0 -8
  102. package/packages/modal-service/README.md +1 -4
  103. package/packages/modal-service/src/ModalService.tsx +5 -29
  104. package/packages/perf-utils/README.md +120 -1
  105. package/packages/perf-utils/src/array/filter.ts +54 -1
  106. package/packages/perf-utils/src/array/find.ts +43 -1
  107. package/packages/perf-utils/src/array/findIndex.ts +43 -1
  108. package/packages/perf-utils/src/array/forEach.ts +48 -1
  109. package/packages/perf-utils/src/array/includes.ts +41 -1
  110. package/packages/perf-utils/src/array/includesNaN.ts +32 -1
  111. package/packages/perf-utils/src/array/index.ts +7 -1
  112. package/packages/perf-utils/src/array/map.ts +52 -1
  113. package/packages/player-ui/README.md +1 -1
  114. package/packages/player-ui/src/CurrentTime.tsx +2 -2
  115. package/packages/player-ui/src/Duration.tsx +2 -2
  116. package/packages/player-ui/src/PauseButton.tsx +0 -8
  117. package/packages/player-ui/src/PlayerInteractable.tsx +0 -1
  118. package/packages/player-ui/src/PlayerTime.tsx +1 -3
  119. package/packages/player-ui/src/PlayerUI.tsx +35 -68
  120. package/packages/player-ui/src/RemainingTime.tsx +2 -2
  121. package/packages/player-ui/src/Seekbar.tsx +18 -110
  122. package/packages/player-ui/src/Seeking.ts +16 -57
  123. package/packages/player-ui/src/Subtitles.tsx +2 -2
  124. package/packages/player-ui/src/index.ts +0 -1
  125. package/packages/player-ui/src/mocks.ts +8 -32
  126. package/packages/player-ui/src/timeUtils.ts +3 -3
  127. package/packages/player-ui/src/types.ts +3 -9
  128. package/packages/router/src/Route.tsx +27 -61
  129. package/packages/router/src/Router.tsx +13 -59
  130. package/packages/router/src/history.ts +1 -8
  131. package/packages/router/src/index.ts +1 -1
  132. package/packages/router/src/utils.ts +4 -9
  133. package/packages/sass-utils/src/linear-gradient.scss +4 -9
  134. package/packages/sass-utils/src/scale.1080.scss +1 -3
  135. package/packages/sass-utils/src/scale.720.scss +1 -1
  136. package/packages/time/README.md +1 -4
  137. package/packages/time/src/Time.ts +13 -35
  138. package/packages/time/src/constants.ts +0 -1
  139. package/packages/toast/src/ToastService.tsx +5 -16
  140. package/packages/types-bigscreen-jsx/README.md +4 -5
  141. package/packages/types-bigscreen-jsx/index.d.ts +67 -72
  142. package/packages/utils/README.md +0 -27
  143. package/packages/utils/src/elementUtils.ts +0 -25
  144. package/packages/utils/src/index.ts +0 -8
  145. package/packages/utils/src/scaledImage.ts +3 -6
  146. package/packages/utils/src/textUtils.ts +14 -46
  147. package/packages/utils/src/wait.ts +1 -3
  148. package/packages/utils/src/xhr/xhrSend.ts +1 -3
  149. package/packages/utils/src/xhr/xhrSendRetry.ts +1 -3
  150. package/packages/zapping/src/ChannelZapping.ts +0 -9
  151. package/packages/zapping/src/Zapping.tsx +0 -10
  152. package/.vscode/settings.json +0 -6
  153. package/packages/analytics/README.md +0 -8
  154. package/packages/analytics/src/A.ts +0 -1
  155. package/packages/analytics/src/Analytics.ts +0 -1
  156. package/packages/analytics/src/analyticsOnScroll.ts +0 -1
  157. package/packages/analytics/src/clients/ConsoleAnalytics/ConsoleAnalytics.ts +0 -1
  158. package/packages/analytics/src/clients/ConsoleAnalytics/index.ts +0 -1
  159. package/packages/analytics/src/clients/GoogleAnalytics/GoogleAnalytics.ts +0 -200
  160. package/packages/analytics/src/clients/GoogleAnalytics/constants.ts +0 -118
  161. package/packages/analytics/src/clients/GoogleAnalytics/getUrl.ts +0 -17
  162. package/packages/analytics/src/clients/GoogleAnalytics/index.ts +0 -2
  163. package/packages/analytics/src/clients/GoogleAnalytics/interface.ts +0 -77
  164. package/packages/analytics/src/clients/GoogleAnalytics/mapPayload.ts +0 -50
  165. package/packages/analytics/src/clients/GoogleAnalytics/prepareBody.ts +0 -14
  166. package/packages/analytics/src/clients/TealiumAnalytics/TealiumAnalytics.ts +0 -169
  167. package/packages/analytics/src/clients/TealiumAnalytics/constants.ts +0 -102
  168. package/packages/analytics/src/clients/TealiumAnalytics/findIdForLanguage.ts +0 -9
  169. package/packages/analytics/src/clients/TealiumAnalytics/index.ts +0 -4
  170. package/packages/analytics/src/clients/TealiumAnalytics/interface.ts +0 -33
  171. package/packages/analytics/src/clients/TealiumAnalytics/mappers/__mocks__/mediaPayload.ts +0 -70
  172. package/packages/analytics/src/clients/TealiumAnalytics/mappers/helper.ts +0 -36
  173. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapAppError.ts +0 -13
  174. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapFavoriteAdd.ts +0 -11
  175. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapFavoriteRemove.ts +0 -11
  176. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapPlayerClose.ts +0 -15
  177. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapPlayerOpen.ts +0 -15
  178. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSceneView.ts +0 -18
  179. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSearch.ts +0 -18
  180. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSearchFailed.ts +0 -8
  181. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapSearchSuccess.ts +0 -8
  182. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoPause.ts +0 -15
  183. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoProgress.ts +0 -18
  184. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoResume.ts +0 -15
  185. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoStart.ts +0 -15
  186. package/packages/analytics/src/clients/TealiumAnalytics/mappers/mapVideoStop.ts +0 -15
  187. package/packages/analytics/src/clients/TealiumAnalytics/types.ts +0 -156
  188. package/packages/analytics/src/clients/TwentyFourIQ/TwentyFourIQClient.ts +0 -116
  189. package/packages/analytics/src/clients/TwentyFourIQ/constants.ts +0 -99
  190. package/packages/analytics/src/clients/TwentyFourIQ/helper.ts +0 -34
  191. package/packages/analytics/src/clients/TwentyFourIQ/index.ts +0 -2
  192. package/packages/analytics/src/clients/TwentyFourIQ/interface.ts +0 -31
  193. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapAdLoaded.ts +0 -13
  194. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapAdSkipped.ts +0 -16
  195. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapBase.ts +0 -21
  196. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapBuffering.ts +0 -15
  197. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapPlayerClose.ts +0 -24
  198. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapPlayerOpen.ts +0 -18
  199. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapSceneView.ts +0 -15
  200. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapScroll.ts +0 -17
  201. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoComplete.ts +0 -21
  202. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoPause.ts +0 -24
  203. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoProgress.ts +0 -24
  204. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoStart.ts +0 -34
  205. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoStop.ts +0 -32
  206. package/packages/analytics/src/clients/TwentyFourIQ/types.ts +0 -115
  207. package/packages/analytics/src/constants.ts +0 -1
  208. package/packages/analytics/src/index.ts +0 -3
  209. package/packages/analytics/src/interface.ts +0 -1
  210. package/packages/analytics/src/utils/generateSessionId.ts +0 -8
  211. package/packages/create-package/dist/createPackage.js +0 -66
  212. package/packages/create-package/dist/createPackage.js.map +0 -1
  213. package/packages/create-package/dist/index.js +0 -5
  214. package/packages/create-package/dist/index.js.map +0 -1
  215. package/packages/create-package/dist/questionnaire/questions.js +0 -35
  216. package/packages/create-package/dist/questionnaire/questions.js.map +0 -1
  217. package/packages/create-package/dist/settings/Settings.js +0 -10
  218. package/packages/create-package/dist/settings/Settings.js.map +0 -1
  219. package/packages/create-package/dist/types.js +0 -3
  220. package/packages/create-package/dist/types.js.map +0 -1
  221. package/packages/device/src/driver/index.firetv.ts +0 -1
  222. package/packages/device/src/driver/index.smartcast.tv.ts +0 -1
  223. package/packages/driver-firetv/src/DeviceFireTV.ts +0 -18
  224. package/packages/driver-firetv/src/__mocks__/javaScriptBridge.ts +0 -36
  225. package/packages/driver-firetv/src/index.ts +0 -1
  226. package/packages/driver-smartcast/src/DeviceSmartCast.ts +0 -317
  227. package/packages/driver-smartcast/src/__mocks__/api.ts +0 -49
  228. package/packages/driver-smartcast/src/index.ts +0 -1
  229. package/packages/driver-smartcast/src/keymap.ts +0 -9
  230. package/packages/driver-smartcast/src/types.ts +0 -65
  231. package/packages/focus/src/hasFocus.ts +0 -36
  232. package/packages/input/src/utils.ts +0 -71
  233. package/packages/jsx/src/test-utils/keyup.ts +0 -27
  234. package/packages/keyboard/src/WhitelabelKeyboard/layouts/arabic.ts +0 -27
  235. package/packages/keyboard/src/WhitelabelKeyboard/layouts/burmese.ts +0 -27
  236. package/packages/keyboard/src/WhitelabelKeyboard/layouts/dari.ts +0 -28
  237. package/packages/keyboard/src/WhitelabelKeyboard/layouts/korean.ts +0 -26
  238. package/packages/keyboard/src/WhitelabelKeyboard/layouts/pashto.ts +0 -27
  239. package/packages/keyboard/src/WhitelabelKeyboard/layouts/persian.ts +0 -27
  240. package/packages/keyboard/src/WhitelabelKeyboard/layouts/russian.ts +0 -27
  241. package/packages/keyboard/src/WhitelabelKeyboard/layouts/tibetan.ts +0 -26
  242. package/packages/keyboard/src/WhitelabelKeyboard/layouts/turkish.ts +0 -26
  243. package/packages/keyboard/src/WhitelabelKeyboard/layouts/ukrainian.ts +0 -27
  244. package/packages/keyboard/src/WhitelabelKeyboard/layouts/urdu.ts +0 -26
  245. package/packages/l10n/src/date/de.ts +0 -97
  246. package/packages/l10n/src/date/es.ts +0 -71
  247. package/packages/l10n/src/date/fr.ts +0 -94
  248. package/packages/l10n/src/date/he.ts +0 -101
  249. package/packages/time/src/adapters/24iMediaTimeApi.ts +0 -47
  250. package/packages/time/src/services/24iMediaTimeApi/24iMediaTimeApi.ts +0 -43
  251. package/packages/time/src/services/24iMediaTimeApi/index.ts +0 -6
  252. package/packages/utils/src/forceReflow.ts +0 -14
  253. package/packages/utils/src/keyPress/index.ts +0 -6
  254. package/packages/utils/src/keyPress/keyPressSimulator.ts +0 -74
  255. package/packages/utils/src/keyPress/simulateKeyPress.ts +0 -25
  256. package/utils/release/release.ts +0 -154
@@ -1,13 +1,8 @@
1
- import { dateFormatter, processYear, toTwoDigitLocaleTimeString } from './common';
2
- import { EN_MONTHS, EN_WEEKDAYS } from './en-common';
1
+ import { collonSeparatedHour24MinuteSecond, dateFormatter, processYear } from './common';
2
+ import { MONTHS, WEEKDAYS } from './en-common';
3
3
  import type { DateTimeFormatOptions, Day, Month, Weekday, Year } from './types';
4
4
 
5
- const processMonth = (
6
- dateParts: string[],
7
- month: Month | undefined,
8
- date: Date,
9
-
10
- ) => {
5
+ const processMonth = (dateParts: string[], month: Month | undefined, date: Date) => {
11
6
  if (typeof month === 'undefined') return;
12
7
  if (month === '2-digit' || month === 'numeric') {
13
8
  const strMonth = (date.getMonth() + 1).toString();
@@ -16,7 +11,7 @@ const processMonth = (
16
11
  strMonth.length === 1 ? `0${strMonth}` : strMonth,
17
12
  );
18
13
  } else {
19
- dateParts.push(EN_MONTHS[month][date.getMonth()]);
14
+ dateParts.push(MONTHS[month][date.getMonth()]);
20
15
  }
21
16
  };
22
17
 
@@ -34,7 +29,7 @@ const processWeekday = (
34
29
  && typeof month === 'undefined'
35
30
  && typeof day === 'undefined'
36
31
  );
37
- dateStringParts.push(`${EN_WEEKDAYS[weekday][date.getDay()]}${isOnlyWeekday ? '' : ','}`);
32
+ dateStringParts.push(`${WEEKDAYS[weekday][date.getDay()]}${isOnlyWeekday ? '' : ','}`);
38
33
  };
39
34
 
40
35
  const processDay = (dateParts: string[], day: Day | undefined, date: Date) => {
@@ -44,7 +39,7 @@ const processDay = (dateParts: string[], day: Day | undefined, date: Date) => {
44
39
  dateParts.push(strDate.length === 1 ? `0${strDate}` : strDate);
45
40
  };
46
41
 
47
- const toLocaleDateString = (date: Date) => (
42
+ export const toLocaleDateString = (date: Date) => (
48
43
  { weekday, year, month, day }: DateTimeFormatOptions = {
49
44
  year: 'numeric', month: '2-digit', day: '2-digit',
50
45
  },
@@ -60,4 +55,10 @@ const toLocaleDateString = (date: Date) => (
60
55
  return dateStringParts.join(' ');
61
56
  };
62
57
 
63
- export const isoDateFormatter = dateFormatter(toTwoDigitLocaleTimeString, toLocaleDateString);
58
+ const toLocaleTimeString = (date: Date) => (
59
+ options: DateTimeFormatOptions = {
60
+ hour: '2-digit', minute: '2-digit', second: '2-digit',
61
+ },
62
+ ) => collonSeparatedHour24MinuteSecond(date, options);
63
+
64
+ export const isoDateFormatter = dateFormatter(toLocaleTimeString, toLocaleDateString);
@@ -20,8 +20,6 @@ type TimeKeys = 'hour' | 'minute' | 'second';
20
20
 
21
21
  type DateKeys = 'weekday' | 'year' | 'month' | 'day';
22
22
 
23
- type FormatType = 'dateFormatLong' | 'dateFormatNumeric' | 'dateFormatShort' | 'timeFormat';
24
-
25
23
  export type DateTimeFormatOptions = {
26
24
  weekday?: Weekday,
27
25
  year?: Year,
@@ -30,7 +28,6 @@ export type DateTimeFormatOptions = {
30
28
  hour?: Hour,
31
29
  minute?: Minute,
32
30
  second?: Second,
33
- formatType?: FormatType,
34
31
  };
35
32
 
36
33
  export type DateFormatOptions = Pick<DateTimeFormatOptions, DateKeys>;
@@ -48,9 +45,3 @@ export type Props = {
48
45
  locale?: string,
49
46
  options?: DateTimeFormatOptions,
50
47
  };
51
-
52
- export type LocaleData = {
53
- narrow: string[];
54
- short: string[];
55
- long: string[];
56
- };
@@ -1,26 +1,11 @@
1
- import { format } from 'date-fns';
2
- import * as fnsLocales from 'date-fns/locale';
3
1
  import { EventsManager, IEvents } from '@24i/bigscreen-sdk/events-manager';
4
- import { csDateFormatter } from './date/cs';
5
- import { deDateFormatter } from './date/de';
6
- import { esDateFormatter } from './date/es';
7
- import { frDateFormatter } from './date/fr';
8
- import { heDateFormatter } from './date/he';
9
2
  import { isoDateFormatter } from './date/iso';
10
3
  import { Formatters } from './types';
11
- import { DateTimeFormatOptions } from './date/types';
12
4
 
13
5
  type Events = {
14
6
  'localechange': () => void,
15
7
  };
16
-
17
- type DateFnsConfig = Partial<
18
- Record<NonNullable<DateTimeFormatOptions['formatType']>, string | null>
19
- >;
20
-
21
8
  class L10n implements IEvents<Events> {
22
- private dateFnsConfig: DateFnsConfig = {};
23
-
24
9
  private readonly events = new EventsManager<Events>();
25
10
 
26
11
  addEventListener = this.events.addEventListener;
@@ -34,11 +19,6 @@ class L10n implements IEvents<Events> {
34
19
  private readonly formatters: Formatters = {
35
20
  date: {
36
21
  iso: isoDateFormatter,
37
- cs: csDateFormatter,
38
- fr: frDateFormatter,
39
- es: esDateFormatter,
40
- de: deDateFormatter,
41
- he: heDateFormatter,
42
22
  },
43
23
  };
44
24
 
@@ -53,53 +33,15 @@ class L10n implements IEvents<Events> {
53
33
  return this.formatters[formatter].iso;
54
34
  }
55
35
 
56
- init(config: DateFnsConfig) {
57
- this.dateFnsConfig = config;
58
- }
59
-
60
36
  setLocale(locale: string) {
61
37
  if (locale === this.locale) return;
62
38
  this.locale = locale;
63
39
  this.triggerEvent('localechange');
64
40
  }
65
41
 
66
- getDateFnsFormatter = (
67
- timestamp: number | Date,
68
- locale: string,
69
- fallbackCb: (options?: DateTimeFormatOptions) => string,
70
- fallbackFormatType?: DateTimeFormatOptions['formatType'],
71
- ) => (
72
- (options?: DateTimeFormatOptions): string => {
73
- const { formatType, ...baseOptions } = options || {};
74
- const dateFnsBsFormat = this.dateFnsConfig?.[formatType || fallbackFormatType!];
75
- if (!dateFnsBsFormat) {
76
- if (!options || Object.keys(baseOptions).length === 0) {
77
- return fallbackCb();
78
- }
79
- return fallbackCb(baseOptions);
80
- }
81
- return format(
82
- timestamp,
83
- dateFnsBsFormat,
84
- { locale: fnsLocales[locale as keyof typeof fnsLocales] },
85
- );
86
- }
87
- );
88
-
89
- date(timestamp: number | Date, locale: string = this.locale) {
90
- const formatter = this.getFormatterByLocale('date', locale)(timestamp);
91
-
92
- return {
93
- toLocaleString: this.getDateFnsFormatter(
94
- timestamp, locale, formatter.toLocaleString,
95
- ),
96
- toLocaleTimeString: this.getDateFnsFormatter(
97
- timestamp, locale, formatter.toLocaleTimeString, 'timeFormat',
98
- ),
99
- toLocaleDateString: this.getDateFnsFormatter(
100
- timestamp, locale, formatter.toLocaleDateString, 'dateFormatShort',
101
- ),
102
- };
42
+ date(timestamp: number | Date, locale?: string) {
43
+ const formatter = this.getFormatterByLocale('date', locale);
44
+ return formatter(timestamp);
103
45
  }
104
46
 
105
47
  addFormatter<T extends keyof Formatters, U extends keyof Formatters[T]>(
@@ -100,13 +100,11 @@ export class ListBase<T extends Item<U>, U>
100
100
  componentDidMount() {
101
101
  this.scrollerDom.current!.addEventListener('wheel', this.onWheel);
102
102
  this.scroller.current!.wrapRef.current!.addEventListener('keyup', this.onKeyUp);
103
- window.document.addEventListener('keyup', this.onGlobalKeyUp, true);
104
103
  }
105
104
 
106
105
  componentWillUnmount() {
107
106
  this.scrollerDom.current!.removeEventListener('wheel', this.onWheel);
108
107
  this.scroller.current!.wrapRef.current!.removeEventListener('keyup', this.onKeyUp);
109
- window.document.removeEventListener('keyup', this.onGlobalKeyUp, true);
110
108
  }
111
109
 
112
110
  onKeyDown = (event: KeyboardEvent) => {
@@ -132,9 +130,6 @@ export class ListBase<T extends Item<U>, U>
132
130
  onKeyUp = () => {
133
131
  this.stopFastScrolling();
134
132
  this.fastFocusingOptimizer.stop();
135
- };
136
-
137
- onGlobalKeyUp = () => {
138
133
  this.preventBlurCounter = 0;
139
134
  };
140
135
 
@@ -157,6 +152,14 @@ export class ListBase<T extends Item<U>, U>
157
152
  }
158
153
  };
159
154
 
155
+ shouldPreventBlur(event: KeyboardEvent) {
156
+ const { horizontal, preventBlurOnLongPress } = this.props;
157
+ return (this.preventBlurCounter >= PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS && (
158
+ (preventBlurOnLongPress.forward && isForward(event, horizontal))
159
+ || (preventBlurOnLongPress.backward && isBackward(event, horizontal))
160
+ ));
161
+ }
162
+
160
163
  getRefAtIndex(i: number): Reference<T> {
161
164
  const ref = this.itemRefs[i];
162
165
  if (!ref) {
@@ -198,14 +201,6 @@ export class ListBase<T extends Item<U>, U>
198
201
  this.fastScrollingCounter.reset();
199
202
  }
200
203
 
201
- shouldPreventBlur(event: KeyboardEvent) {
202
- const { horizontal, preventBlurOnLongPress } = this.props;
203
- return (this.preventBlurCounter >= PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS && (
204
- (preventBlurOnLongPress.forward && isForward(event, horizontal))
205
- || (preventBlurOnLongPress.backward && isBackward(event, horizontal))
206
- ));
207
- }
208
-
209
204
  animatedScrollStarted() {
210
205
  this.isAnimatedScrollRunning = true;
211
206
  }
@@ -365,10 +360,7 @@ export class ListBase<T extends Item<U>, U>
365
360
  }
366
361
 
367
362
  render() {
368
- const {
369
- horizontal, className,
370
- mrcuMountingPoint, mrcuForward, mrcuBackward, forward, backward,
371
- } = this.props;
363
+ const { horizontal, className, mrcuMountingPoint } = this.props;
372
364
  return (
373
365
  <Scroller
374
366
  className={className}
@@ -383,8 +375,6 @@ export class ListBase<T extends Item<U>, U>
383
375
  ref={this.mrcuRef}
384
376
  getMountingPoint={() => mrcuMountingPoint || this.scroller.current!.wrapRef}
385
377
  {...this.props}
386
- forward={mrcuForward || forward}
387
- backward={mrcuBackward || backward}
388
378
  />
389
379
  </Scroller>
390
380
  );
@@ -4,11 +4,11 @@ export type MouseNavigationProps = {
4
4
  /**
5
5
  * Function to call on the press of the right arrow.
6
6
  */
7
- forward(): void,
7
+ forward(): boolean,
8
8
  /**
9
9
  * Function to call on the press of the left arrow.
10
10
  */
11
- backward(): void,
11
+ backward(): boolean,
12
12
  /**
13
13
  * Function which determines whether to show the forward arrow.
14
14
  */
@@ -30,6 +30,7 @@ export class CenteredListController<T> extends UnifiedListController<T, Props<an
30
30
  this.scrollListScroller(-this.topOffset);
31
31
  if (initialFocusIndex !== 0) {
32
32
  base.index = initialFocusIndex!;
33
+ this.focusCurrentItem();
33
34
  this.scroll(base.index, false);
34
35
  }
35
36
  }
@@ -81,14 +81,14 @@ export class EdgeOffsetList<T extends Item<U>, U>
81
81
  const list = this.base.current!;
82
82
  list.index = Math.max(
83
83
  0,
84
- Math.min(scrollIndex + visibleItems - VISIBLE_ITEMS_OFFSET - 1, list.data.length - 1),
84
+ Math.min(scrollIndex + visibleItems - VISIBLE_ITEMS_OFFSET, list.data.length - 1),
85
85
  );
86
86
  this.forward();
87
87
  };
88
88
 
89
89
  mrcuBackward = () => {
90
90
  const list = this.base.current!;
91
- list.index = this.controller.scrollIndex + 1;
91
+ list.index = this.controller.scrollIndex;
92
92
  this.backward();
93
93
  };
94
94
 
@@ -148,7 +148,7 @@ export class EdgeOffsetList<T extends Item<U>, U>
148
148
  const { edgeOffset } = this.props;
149
149
  const list = this.base.current!;
150
150
  list.index = index;
151
- if (list.index <= this.controller.scrollIndex) {
151
+ if (list.index < this.controller.scrollIndex) {
152
152
  this.controller.scroll(list.index < edgeOffset ? 0 : list.index - edgeOffset);
153
153
  }
154
154
  }
@@ -144,16 +144,12 @@ extends SharedProps<any, any> = SharedProps<any, any>>
144
144
  if (backward) {
145
145
  nextScrollIndex = this.scrollPixelsToIndex(scrollValuePx, backward);
146
146
  if (this.lastScrollIndex !== nextScrollIndex) {
147
- for (let i = this.lastScrollIndex - 1; i >= nextScrollIndex; i--) {
148
- this.adjustItemsOffsetsBackward(i);
149
- }
147
+ this.adjustItemsOffsetsBackward(nextScrollIndex);
150
148
  }
151
149
  } else {
152
150
  nextScrollIndex = this.scrollPixelsToIndex(scrollValuePx, backward);
153
151
  if (this.lastScrollIndex !== nextScrollIndex) {
154
- for (let i = this.lastScrollIndex + 1; i <= nextScrollIndex; i++) {
155
- this.adjustItemsOffsetsForward(i);
156
- }
152
+ this.adjustItemsOffsetsForward(nextScrollIndex);
157
153
  }
158
154
  }
159
155
  this.lastScrollIndex = nextScrollIndex;
@@ -1,2 +1 @@
1
1
  export * as Sentry from '@sentry/browser';
2
- export { ErrorEvent } from '@sentry/types';
@@ -3,7 +3,7 @@ import { IStorage, Storage as DefaultStorage } from '@24i/bigscreen-sdk/storage'
3
3
  import { LogOptions, LogLevel, SentryLoggerEnvironment, XhrBreadcrumbData } from '../../types';
4
4
  import { getFormattedMemoryHeapInfo, getFormattedUsedLocalStorageSize } from '../../utils';
5
5
  import { LoggerBase, Config as LoggerBaseConfig } from '../LoggerBase';
6
- import { Sentry, ErrorEvent } from './Sentry';
6
+ import { Sentry } from './Sentry';
7
7
 
8
8
  type Config = {
9
9
  sentryOptions: Sentry.BrowserOptions;
@@ -46,7 +46,7 @@ export class SentryLogger extends LoggerBase {
46
46
  const { beforeSend, ...restOptions } = options;
47
47
  Sentry.init({
48
48
  ...restOptions,
49
- beforeSend: async (event: ErrorEvent, hint: Sentry.EventHint) => {
49
+ beforeSend: async (event: Sentry.Event, hint: Sentry.EventHint) => {
50
50
  if (this.mute) return null;
51
51
  await this.sendMemoryInfo(event);
52
52
  return beforeSend ? beforeSend(event, hint) : event;
@@ -100,7 +100,7 @@ export class MenuAndContentContainer<T extends string = string>
100
100
  * Handles opening with mouse.
101
101
  * @param event mouse event
102
102
  */
103
- onMouseDown = (event: MouseEvent) => {
103
+ onMouseMove = (event: MouseEvent) => {
104
104
  const menu = this.menu.current!;
105
105
  if (this.isMenuAvailable() && !menu.isOpen()) {
106
106
  menu.open();
@@ -108,30 +108,6 @@ export class MenuAndContentContainer<T extends string = string>
108
108
  }
109
109
  };
110
110
 
111
- /**
112
- * Handles hover with mouse.
113
- * @param event mouse event
114
- */
115
- onMouseEnter = (event: MouseEvent) => {
116
- const menu = this.menu.current!;
117
- if (this.isMenuAvailable() && !menu.isOpen() && menu.mrcuEnter) {
118
- menu.mrcuEnter();
119
- stopEvent(event);
120
- }
121
- };
122
-
123
- /**
124
- * Handles hover end with mouse.
125
- * @param event mouse event
126
- */
127
- onMouseLeave = (event: MouseEvent) => {
128
- const menu = this.menu.current!;
129
- if (this.isMenuAvailable() && !menu.isOpen() && menu.mrcuLeave) {
130
- menu.mrcuLeave();
131
- stopEvent(event);
132
- }
133
- };
134
-
135
111
  /**
136
112
  * Handles adding/removing mouse listeners based on whether the mouse is used or not.
137
113
  * @param event mouse active event
@@ -161,9 +137,7 @@ export class MenuAndContentContainer<T extends string = string>
161
137
  if (!this.listensToMouse) {
162
138
  this.listensToMouse = true;
163
139
  if (!this.menu.current!.isOpen()) this.mouseTriggerElementDisplayToggler.show();
164
- this.mouseTriggerElement.current!.addEventListener('mousedown', this.onMouseDown);
165
- this.mouseTriggerElement.current!.addEventListener('mouseenter', this.onMouseEnter);
166
- this.mouseTriggerElement.current!.addEventListener('mouseleave', this.onMouseLeave);
140
+ this.mouseTriggerElement.current!.addEventListener('mousemove', this.onMouseMove);
167
141
  }
168
142
  }
169
143
 
@@ -174,9 +148,7 @@ export class MenuAndContentContainer<T extends string = string>
174
148
  if (this.listensToMouse) {
175
149
  this.listensToMouse = false;
176
150
  if (!this.menu.current!.isOpen()) this.mouseTriggerElementDisplayToggler.hide();
177
- this.mouseTriggerElement.current!.removeEventListener('mousedown', this.onMouseDown);
178
- this.mouseTriggerElement.current!.removeEventListener('mouseenter', this.onMouseEnter);
179
- this.mouseTriggerElement.current!.removeEventListener('mouseleave', this.onMouseLeave);
151
+ this.mouseTriggerElement.current!.removeEventListener('mousemove', this.onMouseMove);
180
152
  }
181
153
  }
182
154
 
@@ -112,14 +112,6 @@ export interface Menu<
112
112
  * Function to close the menu.
113
113
  */
114
114
  close(): void,
115
- /**
116
- * Function for "hover" effect on the menu.
117
- */
118
- mrcuEnter?(): void,
119
- /**
120
- * Function for ending "hover" effect on the menu.
121
- */
122
- mrcuLeave?(): void,
123
115
  /**
124
116
  * Renders new menu items.
125
117
  * @param items new items to render
@@ -9,10 +9,7 @@ sidebar_label: Modal Service
9
9
  A component which helps managing modal windows. Handles rendering and focus management.
10
10
 
11
11
  ## Props
12
- - ```ref``` - the reference to the modal service instance
13
- - ```className``` - custom class name for modal service div
14
- - ```isFocusable``` - whether is modal focusable or not
15
- - ```onCloseLastModal``` - function called when the last modal is closed
12
+ - ref - the reference to the modal service instance
16
13
 
17
14
  ## Provided functionality
18
15
  - exports interface which needs to be implemented by the modal component
@@ -1,36 +1,27 @@
1
- import { Component, createRef, Reference, clearNode, DeclareProps } from '@24i/bigscreen-sdk/jsx';
1
+ import { Component, createRef, Reference, clearNode } from '@24i/bigscreen-sdk/jsx';
2
2
  import {
3
3
  setActiveElementAsFocusCandidate, focusCandidate, refocusAfterHashChange,
4
4
  } from '@24i/bigscreen-sdk/focus';
5
- import { noop } from '@24i/bigscreen-sdk/utils';
6
5
  import { IModal } from './IModal';
7
6
  import './ModalService.styles';
8
7
 
9
8
  type Props = {
10
9
  className?: string;
11
10
  isFocusable?: boolean;
12
- onCloseLastModal?: Function,
13
11
  };
14
12
 
15
- type RenderFunction = (ref:Reference) => JSX.Element;
16
-
17
13
  export class ModalService extends Component<Props> {
18
14
  private openState = false;
19
15
 
20
16
  private readonly rootRef = createRef<HTMLDivElement>();
21
17
 
22
- private readonly modalQueue: RenderFunction[] = [];
23
-
24
18
  modalRef = createRef<any>();
25
19
 
26
20
  static defaultProps = {
27
21
  className: '',
28
22
  isFocusable: true,
29
- onCloseLastModal: noop,
30
23
  };
31
24
 
32
- declare props: DeclareProps<Props, typeof ModalService.defaultProps>;
33
-
34
25
  componentDidMount() {
35
26
  window.addEventListener('hashchange', this.onHashChange);
36
27
  }
@@ -46,22 +37,10 @@ export class ModalService extends Component<Props> {
46
37
  };
47
38
 
48
39
  getMountedComponent() {
49
- return this.modalRef as Reference<IModal>;
50
- }
51
-
52
- private enqueueModal(modal: RenderFunction) {
53
- this.modalQueue.push(modal);
40
+ return this.modalRef;
54
41
  }
55
42
 
56
- private dequeueModal() {
57
- return this.modalQueue.shift();
58
- }
59
-
60
- open<T extends IModal>(render: (ref: Reference<T>) => JSX.Element, queueModal = false) {
61
- if (queueModal && this.openState) {
62
- this.enqueueModal(render);
63
- return;
64
- }
43
+ open<T extends IModal>(render: (ref: Reference<T>) => JSX.Element) {
65
44
  const { isFocusable } = this.props;
66
45
  this.openState = true;
67
46
  this.clearMount(
@@ -74,16 +53,13 @@ export class ModalService extends Component<Props> {
74
53
  }
75
54
  }
76
55
 
77
- close(ignoreQueue = false) {
78
- const { isFocusable, onCloseLastModal } = this.props;
56
+ close() {
57
+ const { isFocusable } = this.props;
79
58
  this.openState = false;
80
59
  clearNode(this.rootRef);
81
60
  if (isFocusable) {
82
61
  focusCandidate();
83
62
  }
84
- const modalFromQueue = this.dequeueModal();
85
- if (modalFromQueue && !ignoreQueue) this.open(modalFromQueue);
86
- if (!this.modalQueue.length) onCloseLastModal();
87
63
  }
88
64
 
89
65
  isOpen() {
@@ -5,4 +5,123 @@ hide_title: true
5
5
  sidebar_label: Performance Utils
6
6
  ---
7
7
 
8
- https://github.com/24i/appstage-shared-packages/blob/main/packages/perf-utils/README.md
8
+ # Performance Utils
9
+ Set of utilities that should increase a performance if they are used instead of a native way, mainly on older devices (e.g. Entone/Kamai set-top-boxes).
10
+
11
+ > **Please check the limitations of each performance utility You want to use in a code.**
12
+
13
+ ## Available perf utils
14
+ - **[Array](#array-perf-utils)**
15
+ - [filter](#filter)
16
+ - [forEach](#foreach)
17
+ - [includes](#includes)
18
+ - [includesNaN](#includesnan)
19
+ - [map](#map)
20
+
21
+ ## Array perf utils
22
+
23
+ > In general, each Array utility which requires a callback will iterate over all array items, even if array index hasn't been initialized yet (to understand the issue, see [An adventure in sparse arrays](https://remysharp.com/2018/06/26/an-adventure-in-sparse-arrays)).
24
+
25
+ ### filter()
26
+ > The filter() method creates a new array with all elements that pass the test implemented by the provided function.
27
+
28
+ For more info, please see [native **filter** method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).
29
+
30
+ #### Limitations against native implementation
31
+ - **`callback` is invoked for all indexes of the array** (not only for indexes with assigned values like [native filter implementation](http://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Description)).
32
+ - **Doesn't coerce returned value from a callback to `true` or `false`**, the callback has to return a boolean value directly.
33
+ - Doesn't accept the `scope` as last argument.
34
+
35
+ #### Usage
36
+ ```javascript
37
+ import { filter } from '@24i/bigscreen-sdk/perf-utils/array';
38
+
39
+ const array = ['spray', 'limit', 'elite', 'exuberant', 'destruction'];
40
+ //const result = array.filter(word => word.length > 6); // slower native solution
41
+ const result = filter(array, word => word.length > 6); // faster
42
+
43
+ console.log(result);
44
+ // expected output: Array ["exuberant", "destruction"]
45
+ ```
46
+
47
+ ### forEach()
48
+ > The forEach() method executes a provided function once for each array element.
49
+
50
+ For more info, please see [native **forEach** method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).
51
+
52
+ #### Limitations against native implementation
53
+ - **`callback` is invoked for all indexes of the array** (not only for indexes with assigned values like [native forEach implementation](http://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Description)).
54
+ - Doesn't accept the `scope` as last argument.
55
+
56
+ #### Usage
57
+ ```javascript
58
+ import { forEach } from '@24i/bigscreen-sdk/perf-utils/array';
59
+
60
+ const array = ['a', 'b', 'c'];
61
+ // array.forEach(item => console.log(item)); // slower native solution
62
+ forEach(array, item => console.log(item)); // faster
63
+
64
+ // expected output: "a"
65
+ // expected output: "b"
66
+ // expected output: "c"
67
+ ```
68
+
69
+ ### includes()
70
+ > The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.
71
+
72
+ For more info, please see [native **includes** method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes).
73
+
74
+ #### Limitations against native implementation
75
+ - **Doesn't work for searching NaN value!** For that purpose, please use [includesNaN()](#includesnan).
76
+ - Doesn't support negative indexes for `fromIndex` param - the entire array will be processed.
77
+
78
+ #### Usage
79
+ ```javascript
80
+ import { includes } from '@24i/bigscreen-sdk/perf-utils/array';
81
+
82
+ const array = ['item0', 'item1', 'item2'];
83
+
84
+ //console.log(array.includes('item1')); // slower native solution
85
+ console.log(includes(array, 'item1')); // faster
86
+ // expected output: true
87
+
88
+ //console.log(array.includes('item1')); // slower native solution
89
+ console.log(includes(array, 'item1', 2)); // faster
90
+ // expected output: false
91
+ ```
92
+
93
+ ### includesNaN()
94
+ > The includesNaN() method determines whether an array includes NaN value among its entries, returning true or false as appropriate.
95
+
96
+ #### Usage
97
+ ```javascript
98
+ import { includesNaN } from '@24i/bigscreen-sdk/perf-utils/array';
99
+
100
+ console.log(includesNaN([0, NaN, 1]));
101
+ // expected output: true
102
+
103
+ console.log(includesNaN([0, NaN, 1], 2));
104
+ // expected output: false
105
+ ```
106
+
107
+ ### map()
108
+ > The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
109
+
110
+ For more info, please see [native **map** method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
111
+
112
+ #### Limitations against native implementation
113
+ - **`callback` is invoked for all indexes of the array** (not only for indexes with assigned values like [native map implementation](http://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Description)).
114
+ - Doesn't accept the `scope` as last argument.
115
+
116
+ #### Usage
117
+ ```javascript
118
+ import { map } from '@24i/bigscreen-sdk/perf-utils/array';
119
+
120
+ const array = [1, 4, 9, 16];
121
+
122
+ // const mappedArray = array.map(x => x * 2); // slower native solution
123
+ const mappedArray = map(array, x => x * 2); // faster
124
+
125
+ console.log(mappedArray);
126
+ // expected output: Array [2, 8, 18, 32]
127
+ ```