@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
@@ -14,13 +14,11 @@ IFocusable is an interface that should be implemented by anything that can be fo
14
14
  interface IFocusable {
15
15
  focus(options?: FocusOptions): void,
16
16
  hasDom?(element: HTMLElement): boolean,
17
- hasFocus?(): boolean,
18
17
  }
19
18
  ```
20
19
  - focus is the main function that is called when focusing component/element.
21
20
  - hasDom is optional optimization for components to help Layout components locate the currently
22
21
  focused child.
23
- - hasFocus is optional check if the component has focus inside or is itself focused.
24
22
 
25
23
  ## Layout components
26
24
  - Vertical: Use it to create focus between elements vertically (up/down)
@@ -42,7 +40,6 @@ to the focused element and its index. Ideal place to change other elements
42
40
  - onBeforeFocusChange: Optional callback just before focus change. It receives a reference
43
41
  to the focused element and its index. Ideal place for preparing for the change
44
42
  (e.g. moving the container to fit new element in the screen)
45
- - circular: makes focus circular, e.g. when pressing left at leftmost element focus will go to rightmost element
46
43
  - dir: Optional forceful setting of the component direction. Defaults to `'auto'` which follows
47
44
  the direction of the app.
48
45
  `'ltr'` always forces left-to-right layout,
@@ -131,16 +128,6 @@ const matrix = [
131
128
  ];
132
129
  ```
133
130
 
134
- ## Prevent blur on long press
135
- When the user holds a navigation key, he usually scrolls to the boundary of the layout
136
- and then releases the key. This operation is very quick and most of the time he releases
137
- the key too late, so the keydown event from the layout will propagate to another component
138
- or another layout. In some cases, we don't want this behavior and for those situations and
139
- to have better control above the layout navigation, there is a prop `preventBlurOnLongPress`.
140
- When the user scrolls to the boundary of the layout while holding a navigation key,
141
- he needs to release the key and press it again to propagate the event higher and focus
142
- another component or layout.
143
-
144
131
  ## Limitations
145
132
  For the div to properly receive keydown events it needs to have set `tabIndex`. If you do not set `tabIndex` then it won't receive keydown events and those will not propagate to the Vertical/Horizontal component.
146
133
 
@@ -315,11 +302,6 @@ Method to focus between multiple focusable components. The first existing (non-n
315
302
  const focusFirstExisting = (...toFocus: Reference<IFocusable>[]) => () => void;
316
303
  ```
317
304
 
318
- If you need to enable `preventScroll` in element focus options, wrap your reference with `preventScrollOnFocus` function like this:
319
- ```ts
320
- focusFirstExisting(this.navigation, preventScrollOnFocus(this.div))
321
- ```
322
-
323
305
  ## refocusAfterHashChange
324
306
  When the hash is changed, the browser automatically blurs the currently focused element and focuses body.
325
307
  This can be problematic when the overlay component is active (development tools, modals). Focus is lost and
@@ -331,18 +313,3 @@ outside of the component and not focused.
331
313
  ```ts
332
314
  const refocusAfterHashChange = (focusWrapperOrReference: HTMLElement | Reference<HTMLElement>) => void;
333
315
  ```
334
-
335
- ## hasFocus
336
- Test if the element (or element in the reference) has the `activeElement` inside or optionally,
337
- if the element itself is the `activeElement`.
338
-
339
- ```ts
340
- const hasFocus = (elementOrReference: HTMLElement | Reference<HTMLElement>, includeElementItself = false) => boolean;
341
- ```
342
-
343
- ## isFocused
344
- Test if the element (or element in the reference) is the `activeElement`.
345
-
346
- ```ts
347
- const isFocused = (elementOrReference: HTMLElement | Reference<HTMLElement>) => boolean;
348
- ```
@@ -1,5 +1,4 @@
1
1
  export interface IFocusable {
2
2
  focus(options?: FocusOptions): void,
3
3
  hasDom?(element: HTMLElement): boolean,
4
- hasFocus?(): boolean,
5
4
  }
@@ -1,22 +1,14 @@
1
1
  import { Component, DeclareProps, Reference } from '@24i/bigscreen-sdk/jsx';
2
2
  import { noop } from '@24i/bigscreen-sdk/utils/noop';
3
- import { stopEvent } from '@24i/bigscreen-sdk/utils/stopEvent';
4
3
  import { IFocusable } from '../IFocusable';
5
4
  import { Errors, hasValidDomRef } from './constants';
6
5
  import { SharedProps } from './types';
7
6
 
8
- const PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS = 2;
9
-
10
7
  export type Props = SharedProps & {
11
8
  focusOptions?: FocusOptions;
12
9
  focusableChildren: Array<Reference>,
13
10
  onFocusChanged?: (focused: Reference, index: number) => any,
14
11
  onBeforeFocusChange?: (focused: Reference, index: number) => any,
15
- circular?: boolean,
16
- preventBlurOnLongPress?: {
17
- forward?: boolean,
18
- backward?: boolean,
19
- }
20
12
  };
21
13
 
22
14
  export interface ILayout {
@@ -33,16 +25,12 @@ export const getLayoutBase = (onKeyDown: (event: KeyboardEvent, layout: ILayout)
33
25
  class Layout extends Component<Props> implements ILayout, IFocusable {
34
26
  index = 0;
35
27
 
36
- preventBlurCounter = 0;
37
-
38
28
  static defaultProps = {
39
29
  onFocusChanged: noop,
40
30
  onBeforeFocusChange: noop,
41
31
  focusOptions: { preventScroll: true },
42
32
  dir: 'auto',
43
- circular: false,
44
- preventBlurOnLongPress: {},
45
- } as const;
33
+ };
46
34
 
47
35
  declare props: DeclareProps<Props, typeof Layout.defaultProps>;
48
36
 
@@ -52,7 +40,6 @@ export const getLayoutBase = (onKeyDown: (event: KeyboardEvent, layout: ILayout)
52
40
  throw new Error(Errors.DOM_REF_ERROR);
53
41
  }
54
42
  domRef.current!.addEventListener('keydown', this.onKeyDown, false);
55
- window.document.addEventListener('keyup', this.onGlobalKeyUp, true);
56
43
  }
57
44
 
58
45
  componentWillUnmount() {
@@ -61,17 +48,12 @@ export const getLayoutBase = (onKeyDown: (event: KeyboardEvent, layout: ILayout)
61
48
  throw new Error(Errors.DOM_REF_ERROR);
62
49
  }
63
50
  domRef.current!.removeEventListener('keydown', this.onKeyDown, false);
64
- window.document.removeEventListener('keyup', this.onGlobalKeyUp, true);
65
51
  }
66
52
 
67
53
  onKeyDown = (e: KeyboardEvent) => {
68
54
  onKeyDown(e, this);
69
55
  };
70
56
 
71
- onGlobalKeyUp = () => {
72
- this.preventBlurCounter = 0;
73
- };
74
-
75
57
  getFromIndex(target: HTMLElement) {
76
58
  const { focusableChildren } = this.props;
77
59
  if (
@@ -96,42 +78,25 @@ export const getLayoutBase = (onKeyDown: (event: KeyboardEvent, layout: ILayout)
96
78
  }
97
79
 
98
80
  backward(e: KeyboardEvent) {
99
- const { focusableChildren, preventBlurOnLongPress, circular } = this.props;
100
81
  const { target } = e;
101
82
  const fromIndex = this.getFromIndex(target as HTMLElement);
102
- if (preventBlurOnLongPress.backward) {
103
- this.preventBlurCounter += 1;
104
- }
105
83
  if (fromIndex > 0) {
106
84
  this.setIndex(fromIndex - 1);
107
85
  this.focusCurrentIndex();
108
- stopEvent(e);
109
- } else if (circular) {
110
- this.setIndex(focusableChildren.length - 1);
111
- this.focusCurrentIndex();
112
- stopEvent(e);
113
- } else if (this.preventBlurCounter >= PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS) {
114
- stopEvent(e);
86
+ e.preventDefault();
87
+ e.stopPropagation();
115
88
  }
116
89
  }
117
90
 
118
91
  forward(e: KeyboardEvent) {
119
- const { focusableChildren, preventBlurOnLongPress, circular } = this.props;
92
+ const { focusableChildren } = this.props;
120
93
  const { target } = e;
121
94
  const fromIndex = this.getFromIndex(target as HTMLElement);
122
- if (preventBlurOnLongPress.forward) {
123
- this.preventBlurCounter += 1;
124
- }
125
95
  if (fromIndex < focusableChildren.length - 1) {
126
96
  this.setIndex(fromIndex + 1);
127
97
  this.focusCurrentIndex();
128
- stopEvent(e);
129
- } else if (circular) {
130
- this.setIndex(0);
131
- this.focusCurrentIndex();
132
- stopEvent(e);
133
- } else if (this.preventBlurCounter >= PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS) {
134
- stopEvent(e);
98
+ e.preventDefault();
99
+ e.stopPropagation();
135
100
  }
136
101
  }
137
102
 
@@ -8,8 +8,6 @@ import { isRtl } from './isRtl';
8
8
  import { Errors, hasValidDomRef } from './constants';
9
9
  import { SharedProps } from './types';
10
10
 
11
- const PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS = 2;
12
-
13
11
  // Used in binary operations for shorter checks
14
12
  export enum CircularDirection {
15
13
  NONE = 0,
@@ -23,13 +21,7 @@ export type Props = SharedProps & {
23
21
  matrix: Array<Array<Reference>>,
24
22
  onFocusChanged?: (focused: Reference, index: Index2D) => any,
25
23
  onBeforeFocusChange?: (focused: Reference, index: Index2D) => any,
26
- circular?: CircularDirection,
27
- preventBlurOnLongPress?: {
28
- left?: boolean,
29
- right?: boolean,
30
- up?: boolean,
31
- down?: boolean,
32
- },
24
+ circular?: CircularDirection;
33
25
  };
34
26
 
35
27
  export type Index2D = {
@@ -40,14 +32,11 @@ export type Index2D = {
40
32
  export class Matrix extends Component<Props> implements IFocusable {
41
33
  index: Index2D = { x: 0, y: 0 };
42
34
 
43
- preventBlurCounter = 0;
44
-
45
35
  static defaultProps = {
46
36
  onFocusChanged: noop,
47
37
  onBeforeFocusChange: noop,
48
38
  circular: CircularDirection.NONE,
49
39
  dir: 'auto',
50
- preventBlurOnLongPress: {},
51
40
  } as const;
52
41
 
53
42
  declare props: DeclareProps<Props, typeof Matrix.defaultProps>;
@@ -58,7 +47,6 @@ export class Matrix extends Component<Props> implements IFocusable {
58
47
  throw new Error(Errors.DOM_REF_ERROR);
59
48
  }
60
49
  domRef.current!.addEventListener('keydown', this.onKeyDown, false);
61
- window.document.addEventListener('keyup', this.onGlobalKeyUp, true);
62
50
  }
63
51
 
64
52
  componentWillUnmount() {
@@ -67,46 +55,26 @@ export class Matrix extends Component<Props> implements IFocusable {
67
55
  throw new Error(Errors.DOM_REF_ERROR);
68
56
  }
69
57
  domRef.current!.removeEventListener('keydown', this.onKeyDown, false);
70
- window.document.removeEventListener('keyup', this.onGlobalKeyUp, true);
71
58
  }
72
59
 
73
60
  onKeyDown = (e: KeyboardEvent) => {
74
- const { preventBlurOnLongPress } = this.props;
75
61
  let newIndex: Index2D | null = null;
76
62
  if (this.isDirectionLeft(e)) {
77
63
  newIndex = this.moveHorizontaly('left');
78
- if (preventBlurOnLongPress.left) {
79
- this.preventBlurCounter += 1;
80
- }
81
64
  } else if (this.isDirectionRight(e)) {
82
65
  newIndex = this.moveHorizontaly('right');
83
- if (preventBlurOnLongPress.right) {
84
- this.preventBlurCounter += 1;
85
- }
86
66
  } else if (device.isDirectionUp(e)) {
87
67
  newIndex = this.moveVerticaly('up');
88
- if (preventBlurOnLongPress.up) {
89
- this.preventBlurCounter += 1;
90
- }
91
68
  } else if (device.isDirectionDown(e)) {
92
69
  newIndex = this.moveVerticaly('down');
93
- if (preventBlurOnLongPress.down) {
94
- this.preventBlurCounter += 1;
95
- }
96
70
  }
97
71
  if (newIndex) {
98
72
  stopEvent(e);
99
73
  this.index = newIndex;
100
74
  this.focusCurrentIndex();
101
- } else if (this.preventBlurCounter >= PREVENT_BLUR_ON_LONG_PRESS_KEYDOWNS) {
102
- stopEvent(e);
103
75
  }
104
76
  };
105
77
 
106
- onGlobalKeyUp = () => {
107
- this.preventBlurCounter = 0;
108
- };
109
-
110
78
  getRefAt({ x, y }: Index2D): Reference {
111
79
  const { matrix } = this.props;
112
80
  if (matrix[y] && matrix[y][x]) return matrix[y][x];
@@ -144,6 +112,24 @@ export class Matrix extends Component<Props> implements IFocusable {
144
112
  return false;
145
113
  }
146
114
 
115
+ isDirectionLeft(event: KeyboardEvent) {
116
+ const { dir } = this.props;
117
+ const rtl = isRtl(dir);
118
+ return (
119
+ (!rtl && LEFT.is(event))
120
+ || (rtl && RIGHT.is(event))
121
+ );
122
+ }
123
+
124
+ isDirectionRight(event: KeyboardEvent) {
125
+ const { dir } = this.props;
126
+ const rtl = isRtl(dir);
127
+ return (
128
+ (!rtl && RIGHT.is(event))
129
+ || (rtl && LEFT.is(event))
130
+ );
131
+ }
132
+
147
133
  moveForwards = (isCircular: boolean) => (x: number, length: number) => {
148
134
  if (x === length - 1) {
149
135
  return isCircular ? 0 : length - 1;
@@ -186,24 +172,6 @@ export class Matrix extends Component<Props> implements IFocusable {
186
172
  return this.searchVertical(column, fromY, this.moveForwards(!!isCircular));
187
173
  };
188
174
 
189
- isDirectionLeft(event: KeyboardEvent) {
190
- const { dir } = this.props;
191
- const rtl = isRtl(dir);
192
- return (
193
- (!rtl && LEFT.is(event))
194
- || (rtl && RIGHT.is(event))
195
- );
196
- }
197
-
198
- isDirectionRight(event: KeyboardEvent) {
199
- const { dir } = this.props;
200
- const rtl = isRtl(dir);
201
- return (
202
- (!rtl && RIGHT.is(event))
203
- || (rtl && LEFT.is(event))
204
- );
205
- }
206
-
207
175
  isDifferentReferenceFromCurrent(index: Index2D): boolean {
208
176
  const { current } = this.getRefAt(this.index);
209
177
  const { current: searched } = this.getRefAt(index);
@@ -0,0 +1,180 @@
1
+ import { IFocusable } from '../../IFocusable';
2
+ import { getLayoutBase } from '../Base';
3
+ import { rootRef, refChildA, refChildB, refChildC, refChildD } from './shared';
4
+
5
+ const mockKeydown = jest.fn();
6
+ const mockEvent: any = {
7
+ target: null,
8
+ preventDefault: jest.fn(),
9
+ stopPropagation: jest.fn(),
10
+ };
11
+
12
+ const Base = getLayoutBase(mockKeydown);
13
+
14
+ describe('Focus Layout Base', () => {
15
+ let base: any;
16
+ beforeEach(() => {
17
+ base = new Base({
18
+ domRef: rootRef,
19
+ children: 'children',
20
+ focusableChildren: [refChildA, refChildB, refChildC],
21
+ onFocusChanged: jest.fn(),
22
+ onBeforeFocusChange: jest.fn(),
23
+ });
24
+ mockKeydown.mockClear();
25
+ refChildA.current!.focus.mockClear();
26
+ refChildB.current!.focus.mockClear();
27
+ refChildC.current!.focus.mockClear();
28
+ mockEvent.preventDefault.mockClear();
29
+ mockEvent.stopPropagation.mockClear();
30
+ });
31
+
32
+ it('should throw without domRef on componentDidMount', () => {
33
+ // @ts-ignore - the point of the test is to test possible runtime problem
34
+ const invalidBase = new Base({ domRef: null, children: [], focusableChildren: [] });
35
+ expect(() => invalidBase.componentDidMount()).toThrow();
36
+ });
37
+
38
+ it('should throw without domRef on componentWillUnmount', () => {
39
+ // @ts-ignore - the point of the test is to test possible runtime problem
40
+ const invalidBase = new Base({ domRef: null, children: [], focusableChildren: [] });
41
+ expect(() => invalidBase.componentWillUnmount()).toThrow();
42
+ });
43
+
44
+ it('should not throw with valid domRef on componentDidMount', () => {
45
+ expect(() => base.componentDidMount()).not.toThrow();
46
+ });
47
+
48
+ it('should not throw with valid domRef on componentWillUnmount', () => {
49
+ expect(() => base.componentWillUnmount()).not.toThrow();
50
+ });
51
+
52
+ it('should render children', () => {
53
+ expect(base.render()).toBe('children');
54
+ });
55
+
56
+ it('should return false when setting index out of range', () => {
57
+ expect(base.setIndex(4)).toBe(false);
58
+ });
59
+
60
+ it('should return true when setting index out of range', () => {
61
+ expect(base.setIndex(1)).toBe(true);
62
+ });
63
+
64
+ it('should increase index by one on forward', () => {
65
+ const oldIndex = base.index;
66
+ base.forward(mockEvent);
67
+ expect(base.index).toBe(oldIndex + 1);
68
+ });
69
+
70
+ it('should deecrease index by one on backward', () => {
71
+ base.index = 2;
72
+ const oldIndex = base.index;
73
+ base.backward(mockEvent);
74
+ expect(base.index).toBe(oldIndex - 1);
75
+ });
76
+
77
+ it('should not increase index above focusableChildren.length - 1', () => {
78
+ base.index = base.props.focusableChildren.length - 1;
79
+ base.forward(mockEvent);
80
+ expect(base.index).toBe(base.props.focusableChildren.length - 1);
81
+ });
82
+
83
+ it('should not decrease index below 0', () => {
84
+ base.index = 0;
85
+ base.backward(mockEvent);
86
+ expect(base.index).toBe(0);
87
+ });
88
+
89
+ it('should call focus on new element when going forward', () => {
90
+ base.forward(mockEvent);
91
+ expect(refChildB.current!.focus).toHaveBeenCalled();
92
+ });
93
+
94
+ it('should call focus on new element when going backward', () => {
95
+ base.index = 1;
96
+ base.backward(mockEvent);
97
+ expect(refChildA.current!.focus).toHaveBeenCalled();
98
+ });
99
+
100
+ it('should not call focus when can\'t go forward', () => {
101
+ base.index = 2;
102
+ base.forward(mockEvent);
103
+ expect(refChildC.current!.focus).not.toHaveBeenCalled();
104
+ });
105
+
106
+ it('should not call focus when can\'t go backward', () => {
107
+ base.backward(mockEvent);
108
+ expect(refChildA.current!.focus).not.toHaveBeenCalled();
109
+ });
110
+
111
+ it('should call preventDefault and stopPropagation when going forward', () => {
112
+ base.forward(mockEvent);
113
+ expect(mockEvent.preventDefault).toHaveBeenCalled();
114
+ expect(mockEvent.stopPropagation).toHaveBeenCalled();
115
+ });
116
+
117
+ it('should call preventDefault and stopPropagation when going backward', () => {
118
+ base.index = 1;
119
+ base.backward(mockEvent);
120
+ expect(mockEvent.preventDefault).toHaveBeenCalled();
121
+ expect(mockEvent.stopPropagation).toHaveBeenCalled();
122
+ });
123
+
124
+ it('should not call preventDefault and stopPropagation when can\'t go forward', () => {
125
+ base.index = 2;
126
+ base.forward(mockEvent);
127
+ expect(mockEvent.preventDefault).not.toHaveBeenCalled();
128
+ expect(mockEvent.stopPropagation).not.toHaveBeenCalled();
129
+ });
130
+
131
+ it('should not call preventDefault and stopPropagation when can\'t go backward', () => {
132
+ base.backward(mockEvent);
133
+ expect(mockEvent.preventDefault).not.toHaveBeenCalled();
134
+ expect(mockEvent.stopPropagation).not.toHaveBeenCalled();
135
+ });
136
+
137
+ it('should call onFocusChanged when focusing current index', () => {
138
+ base.focusCurrentIndex();
139
+ expect(base.props.onFocusChanged).toHaveBeenCalled();
140
+ });
141
+
142
+ it('should call onBeforeFocusChange when focusing current index', () => {
143
+ base.focusCurrentIndex();
144
+ expect(base.props.onBeforeFocusChange).toHaveBeenCalled();
145
+ });
146
+
147
+ it('should focus current index on focus', () => {
148
+ base.index = 2;
149
+ base.focus();
150
+ expect(refChildC.current!.focus).toHaveBeenCalled();
151
+ });
152
+
153
+ it('should call passed onKeyDown on onKeyDown', () => {
154
+ base.onKeyDown();
155
+ expect(mockKeydown).toHaveBeenCalled();
156
+ });
157
+
158
+ it('should throw in focusCurrentIndex when element does not implement focus', () => {
159
+ base.props.focusableChildren[2] = {};
160
+ base.index = 2;
161
+ expect(() => base.focusCurrentIndex()).toThrow();
162
+ });
163
+
164
+ it('should take result of hasDom into account of determining current focus position', () => {
165
+ base = new Base({
166
+ domRef: rootRef,
167
+ children: 'children',
168
+ focusableChildren: [refChildA, refChildB, refChildC, refChildD],
169
+ onFocusChanged: jest.fn(),
170
+ onBeforeFocusChange: jest.fn(),
171
+ });
172
+ ((refChildD.current as IFocusable).hasDom as jest.MockedFn<
173
+ Exclude<IFocusable['hasDom'], undefined>
174
+ >).mockReturnValueOnce(true);
175
+ base.backward(mockEvent);
176
+ expect(base.index).toBe(2);
177
+ base.backward(mockEvent);
178
+ expect(base.index).toBe(1);
179
+ });
180
+ });
@@ -0,0 +1,94 @@
1
+ import { isRtl } from '@24i/bigscreen-sdk/i18n';
2
+ import { Horizontal } from '../Horizontal';
3
+ import { rootRef, refChildA, refChildB, refChildC } from './shared';
4
+
5
+ jest.mock('@24i/bigscreen-sdk/i18n', () => ({
6
+ ...jest.requireActual('@24i/bigscreen-sdk/i18n'),
7
+ isRtl: jest.fn().mockReturnValue(false),
8
+ }));
9
+ const isRtlMock = isRtl as jest.MockedFn<typeof isRtl>;
10
+
11
+ const mockEvent = {
12
+ target: false,
13
+ preventDefault: jest.fn(),
14
+ stopPropagation: jest.fn(),
15
+ };
16
+ const mockLEFTEvent = {
17
+ code: 'ArrowLeft',
18
+ ...mockEvent,
19
+ };
20
+ const mockRIGHTEvent = {
21
+ code: 'ArrowRight',
22
+ ...mockEvent,
23
+ };
24
+
25
+ describe('Horizontal Focus Layout', () => {
26
+ let horizontal: any;
27
+ beforeEach(() => {
28
+ horizontal = new Horizontal({
29
+ domRef: rootRef,
30
+ children: 'children',
31
+ focusableChildren: [refChildA, refChildB, refChildC],
32
+ onFocusChanged: jest.fn(),
33
+ onBeforeFocusChange: jest.fn(),
34
+ });
35
+ horizontal.forward = jest.fn();
36
+ horizontal.backward = jest.fn();
37
+ });
38
+
39
+ it('should be a class component', () => {
40
+ expect(Horizontal.isClass).toBe(true);
41
+ });
42
+
43
+ it('should call forward on RIGHT', () => {
44
+ horizontal.onKeyDown(mockRIGHTEvent);
45
+ expect(horizontal.forward).toHaveBeenCalled();
46
+ });
47
+
48
+ it('should call backward on LEFT', () => {
49
+ horizontal.setIndex(1);
50
+ horizontal.onKeyDown(mockLEFTEvent);
51
+ expect(horizontal.backward).toHaveBeenCalled();
52
+ });
53
+
54
+ it('should call backward on RIGHT when RTL', () => {
55
+ isRtlMock.mockReturnValueOnce(true);
56
+ horizontal.setIndex(1);
57
+ horizontal.onKeyDown(mockRIGHTEvent);
58
+ expect(horizontal.backward).toHaveBeenCalled();
59
+ });
60
+
61
+ it('should call forward on LEFT when RTL', () => {
62
+ isRtlMock.mockReturnValueOnce(true);
63
+ horizontal.onKeyDown(mockLEFTEvent);
64
+ expect(horizontal.forward).toHaveBeenCalled();
65
+ });
66
+
67
+ it('should call backward on RIGHT when forced RTL', () => {
68
+ horizontal.props.dir = 'rtl';
69
+ horizontal.setIndex(1);
70
+ horizontal.onKeyDown(mockRIGHTEvent);
71
+ expect(horizontal.backward).toHaveBeenCalled();
72
+ });
73
+
74
+ it('should call forward on LEFT when forced RTL', () => {
75
+ horizontal.props.dir = 'rtl';
76
+ horizontal.onKeyDown(mockLEFTEvent);
77
+ expect(horizontal.forward).toHaveBeenCalled();
78
+ });
79
+
80
+ it('should call backward on LEFT when RTL and forced LTR', () => {
81
+ isRtlMock.mockReturnValueOnce(true);
82
+ horizontal.props.dir = 'ltr';
83
+ horizontal.setIndex(1);
84
+ horizontal.onKeyDown(mockLEFTEvent);
85
+ expect(horizontal.backward).toHaveBeenCalled();
86
+ });
87
+
88
+ it('should call forward on RIGHT when RTL and forced LTR', () => {
89
+ isRtlMock.mockReturnValueOnce(true);
90
+ horizontal.props.dir = 'ltr';
91
+ horizontal.onKeyDown(mockRIGHTEvent);
92
+ expect(horizontal.forward).toHaveBeenCalled();
93
+ });
94
+ });