@24i/bigscreen-sdk 1.0.0 → 1.0.1-alpha.2074

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 (54) hide show
  1. package/package.json +12 -11
  2. package/packages/developer-tools/src/EnvironmentSelection/styles/EnvironmentSelection.scss +1 -1
  3. package/packages/device/src/driver/index.vidaa.tv.ts +1 -0
  4. package/packages/device/src/resolver/resolver.ts +5 -0
  5. package/packages/driver-vidaa/src/DeviceVidaa.ts +134 -0
  6. package/packages/driver-vidaa/src/__mocks__/vidaa.ts +20 -0
  7. package/packages/driver-vidaa/src/formatUserAgent.ts +16 -0
  8. package/packages/driver-vidaa/src/index.ts +1 -0
  9. package/packages/driver-vidaa/src/keymap.ts +54 -0
  10. package/packages/driver-vidaa/src/types.ts +82 -0
  11. package/packages/grid/src/Base/Base.tsx +25 -6
  12. package/packages/grid/src/Base/MouseNavigation/MouseNavigation.tsx +58 -0
  13. package/packages/grid/src/Base/MouseNavigation/MouseNavigationFallback.ts +4 -0
  14. package/packages/grid/src/Base/MouseNavigation/index.tizen.tv.ts +1 -0
  15. package/packages/grid/src/Base/MouseNavigation/index.ts +1 -0
  16. package/packages/grid/src/Base/MouseNavigation/index.webos.tv.ts +1 -0
  17. package/packages/grid/src/Base/MouseNavigation/index.webtv.ts +1 -0
  18. package/packages/grid/src/Base/interface.ts +47 -0
  19. package/packages/grid/src/UnifiedGridController/UnifiedGridController.ts +4 -1
  20. package/packages/list/src/Base/Base.tsx +16 -5
  21. package/packages/list/src/Base/MouseNavigation/MouseNavigation.tsx +58 -0
  22. package/packages/list/src/Base/MouseNavigation/MouseNavigationFallback.ts +4 -0
  23. package/packages/list/src/Base/MouseNavigation/index.tizen.tv.ts +1 -0
  24. package/packages/list/src/Base/MouseNavigation/index.ts +1 -0
  25. package/packages/list/src/Base/MouseNavigation/index.webos.tv.ts +1 -0
  26. package/packages/list/src/Base/MouseNavigation/index.webtv.ts +1 -0
  27. package/packages/list/src/Base/interface.ts +39 -0
  28. package/packages/list/src/BasicList/BasicList.tsx +4 -1
  29. package/packages/list/src/EdgeOffsetList/EdgeOffsetList.tsx +4 -3
  30. package/packages/list/src/FirstOnlyList/FirstOnlyList.tsx +2 -2
  31. package/packages/list/src/FirstOnlyVariedList/FirstOnlyVariedList.tsx +2 -2
  32. package/packages/list/src/FixedToEndList/FixedToEndList.tsx +2 -2
  33. package/packages/list/src/interface.ts +2 -0
  34. package/packages/logger/README.md +1 -1
  35. package/packages/menu/src/MenuAndContentContainer/MenuAndContentContainer.tsx +3 -1
  36. package/packages/menu/src/MenuAndContentContainer/interface.ts +1 -1
  37. package/packages/mouse-navigation/src/MouseNavigation.tsx +2 -2
  38. package/packages/scroll-text/src/Base.tsx +5 -0
  39. package/utils/create-export-maps/src/__tests__/createExportMaps.spec.ts +2 -2
  40. package/utils/create-export-maps/src/createExportMaps.ts +1 -1
  41. package/packages/focus/src/__test__/candidate.spec.tsx +0 -245
  42. package/packages/focus/src/__test__/focusFirstExisting.spec.tsx +0 -21
  43. package/packages/focus/src/__test__/refocusAfterHashChange.spec.tsx +0 -41
  44. package/packages/focus/src/__test__/safeFocus.spec.tsx +0 -41
  45. package/packages/grid/src/Base/Base.mouse.tsx +0 -24
  46. package/packages/grid/src/Base/index.tizen.tv.ts +0 -1
  47. package/packages/grid/src/Base/index.webos.tv.ts +0 -1
  48. package/packages/grid/src/Base/index.webtv.ts +0 -1
  49. package/packages/list/src/Base/Base.mouse.tsx +0 -28
  50. package/packages/list/src/Base/index.tizen.tv.ts +0 -1
  51. package/packages/list/src/Base/index.webos.tv.ts +0 -1
  52. package/packages/list/src/Base/index.webtv.ts +0 -1
  53. package/packages/mouse-navigation/src/__test__/MouseElementWrapper.spec.tsx +0 -61
  54. package/packages/mouse-navigation/src/__test__/MouseNavigation.spec.tsx +0 -107
@@ -1,5 +1,4 @@
1
1
  import { createRef, Component, Reference, DeclareProps } from '@24i/bigscreen-sdk/jsx';
2
- import { MouseNavigation } from '@24i/bigscreen-sdk/mouse-navigation';
3
2
  import { device } from '@24i/bigscreen-sdk/device';
4
3
  import { Scroller } from '@24i/bigscreen-sdk/scroller';
5
4
  import { forEach } from '@24i/bigscreen-sdk/perf-utils/array';
@@ -10,8 +9,12 @@ import {
10
9
  ICounter,
11
10
  createTimeout,
12
11
  } from '@24i/bigscreen-sdk/utils';
12
+ import { MouseNavigation } from './MouseNavigation';
13
13
  import { FastFocusingOptimizer } from '../FastFocusingOptimizer/FastFocusingOptimizer';
14
14
  import { BasicProps, Item } from '../types';
15
+ import {
16
+ MouseNavigation as IMouseNavigation,
17
+ } from './interface';
15
18
 
16
19
  export type Props<T extends Item<U>, U> = BasicProps<T, U> & {
17
20
  forward: () => boolean,
@@ -21,7 +24,6 @@ export type Props<T extends Item<U>, U> = BasicProps<T, U> & {
21
24
  shouldShowMrcuForward?: () => boolean,
22
25
  shouldShowMrcuBackward?: () => boolean,
23
26
  adjustFocusFromTarget?: (itemRefIndex: number) => void,
24
- mrcuRef?: Reference<MouseNavigation>;
25
27
  limit?: number,
26
28
  shouldApplySlowdown?: () => boolean,
27
29
  };
@@ -45,6 +47,8 @@ export class ListBase<T extends Item<U>, U>
45
47
 
46
48
  scrollerDom = createRef<HTMLDivElement>();
47
49
 
50
+ mrcuRef = createRef<IMouseNavigation>();
51
+
48
52
  itemRefs: Reference<T>[] = [];
49
53
 
50
54
  index = 0;
@@ -123,15 +127,16 @@ export class ListBase<T extends Item<U>, U>
123
127
 
124
128
  onWheel = (event: WheelEvent) => {
125
129
  const {
126
- forward, backward, mrcuRef, shouldApplySlowdown,
130
+ horizontal, forward, backward, shouldApplySlowdown,
127
131
  } = this.props;
128
132
  let processed;
133
+ if (horizontal) return;
129
134
  if (event.deltaY > 0) processed = shouldApplySlowdown() || forward();
130
135
  else if (event.deltaY < 0) processed = shouldApplySlowdown() || backward();
131
136
  if (processed) {
132
137
  stopEvent(event);
133
138
  this.fastScrollingCounter?.add();
134
- mrcuRef?.current?.handleArrowState();
139
+ this.mrcuRef?.current?.handleArrowState();
135
140
  this.fakeWheelStop();
136
141
  } else if (processed === false) {
137
142
  this.fastFocusingOptimizer.stop();
@@ -348,7 +353,13 @@ export class ListBase<T extends Item<U>, U>
348
353
  onKeyDown={this.onKeyDown}
349
354
  horizontal={horizontal}
350
355
  >
351
- {this.renderData()}
356
+ <>{this.renderData()}</>
357
+ <MouseNavigation
358
+ // @ts-ignore - needed to convert fallback (false) to interface
359
+ ref={this.mrcuRef}
360
+ getMountingPoint={() => this.scroller.current!.wrapRef}
361
+ {...this.props}
362
+ />
352
363
  </Scroller>
353
364
  );
354
365
  }
@@ -0,0 +1,58 @@
1
+ import { Component, createRef } from '@24i/bigscreen-sdk/jsx';
2
+ import { MouseNavigation as MouseNavigationBase } from '@24i/bigscreen-sdk/mouse-navigation';
3
+ import { device } from '@24i/bigscreen-sdk/device';
4
+ import {
5
+ MouseNavigationProps as Props,
6
+ MouseNavigation as IMouseNavigation,
7
+ } from '../interface';
8
+
9
+ export class MouseNavigation extends Component<Props> implements IMouseNavigation {
10
+ private readonly div = createRef<HTMLDivElement>();
11
+
12
+ private readonly base = createRef<MouseNavigationBase>();
13
+
14
+ componentDidMount() {
15
+ if (device.isMouseUsed()) {
16
+ this.renderArrows();
17
+ }
18
+ }
19
+
20
+ handleArrowState() {
21
+ this.base?.current?.handleArrowState();
22
+ }
23
+
24
+ renderArrows() {
25
+ const {
26
+ horizontal,
27
+ forward,
28
+ backward,
29
+ shouldShowMrcuForward,
30
+ shouldShowMrcuBackward,
31
+ getMountingPoint,
32
+ } = this.props;
33
+
34
+ const direction = horizontal ? 'horizontal' : 'vertical';
35
+
36
+ this.appendMount(
37
+ <div ref={this.div} className="mouse-navigation">
38
+ <MouseNavigationBase
39
+ // @ts-ignore - needed to convert fallback (false) to interface
40
+ ref={this.base}
41
+ getMountingPoint={() => this.div}
42
+ direction={direction}
43
+ forward={forward}
44
+ backward={backward}
45
+ shouldShowMrcuForward={shouldShowMrcuForward}
46
+ shouldShowMrcuBackward={shouldShowMrcuBackward}
47
+ >
48
+ {null as unknown as JSX.Element}
49
+ </MouseNavigationBase>
50
+ </div>,
51
+ getMountingPoint(),
52
+ );
53
+ }
54
+
55
+ render() {
56
+ return null;
57
+ }
58
+ }
@@ -0,0 +1,4 @@
1
+ import { MouseNavigationProps as Props } from '../interface';
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
+ export const MouseNavigation = (props: Props) => false as unknown as JSX.Element;
@@ -0,0 +1 @@
1
+ export { MouseNavigation } from './MouseNavigation';
@@ -0,0 +1 @@
1
+ export { MouseNavigation } from './MouseNavigationFallback';
@@ -0,0 +1 @@
1
+ export { MouseNavigation } from './MouseNavigation';
@@ -0,0 +1 @@
1
+ export { MouseNavigation } from './MouseNavigation';
@@ -0,0 +1,39 @@
1
+ import { Reference, Component } from '@24i/bigscreen-sdk/jsx';
2
+
3
+ export type MouseNavigationProps = {
4
+ /**
5
+ * Function to call on the press of the right arrow.
6
+ */
7
+ forward(): boolean,
8
+ /**
9
+ * Function to call on the press of the left arrow.
10
+ */
11
+ backward(): boolean,
12
+ /**
13
+ * Function which determines whether to show the forward arrow.
14
+ */
15
+ shouldShowMrcuForward?(): boolean,
16
+ /**
17
+ * Function which determines whether to show the backward arrow.
18
+ */
19
+ shouldShowMrcuBackward?(): boolean,
20
+ /**
21
+ * Returns a reference to the element where your `children` should be rendered.
22
+ */
23
+ getMountingPoint(): Reference<HTMLElement>;
24
+ /**
25
+ * Property determines whether navigation is horizontal.
26
+ */
27
+ horizontal?: boolean,
28
+ };
29
+
30
+ export interface MouseNavigation extends Component<MouseNavigationProps> {
31
+ /**
32
+ * Function to disable showing an arrow in the given direction.
33
+ */
34
+ handleArrowState(): void,
35
+ }
36
+
37
+ export interface MouseNavigationComponent {
38
+ new (props: MouseNavigationProps): MouseNavigation,
39
+ }
@@ -103,7 +103,10 @@ export class BasicList<T extends Item<U>, U>
103
103
 
104
104
  shouldShowMrcuForward = () => {
105
105
  const { visibleItems, data } = this.props;
106
- return this.controller.scrollIndex < data.length - 1 - visibleItems + VISIBLE_ITEMS_OFFSET;
106
+ return (
107
+ this.controller.scrollIndex < data.length - 1 - visibleItems + VISIBLE_ITEMS_OFFSET
108
+ && data.length > visibleItems - 2
109
+ );
107
110
  };
108
111
 
109
112
  shouldShowMrcuBackward = () => this.controller.scrollIndex > 0;
@@ -93,11 +93,12 @@ export class EdgeOffsetList<T extends Item<U>, U>
93
93
  };
94
94
 
95
95
  shouldShowMrcuForward = () => {
96
- const { edgeOffset, visibleItems } = this.props;
96
+ const { data, edgeOffset, visibleItems } = this.props;
97
97
  const { scrollIndex } = this.controller;
98
- const list = this.base.current!;
98
+
99
99
  return (
100
- scrollIndex < list.data.length - visibleItems + VISIBLE_ITEMS_OFFSET - edgeOffset
100
+ scrollIndex < data.length - visibleItems + VISIBLE_ITEMS_OFFSET - edgeOffset
101
+ && data.length > visibleItems - 2
101
102
  );
102
103
  };
103
104
 
@@ -70,9 +70,9 @@ export class FirstOnlyList<T extends Item<U>, U>
70
70
  };
71
71
 
72
72
  shouldShowMrcuForward = () => {
73
- const { data } = this.props;
73
+ const { data, visibleItems } = this.props;
74
74
  const list = this.base.current!;
75
- return list.index < data.length - 1;
75
+ return list.index < data.length - 1 && data.length > visibleItems - 2;
76
76
  };
77
77
 
78
78
  shouldShowMrcuBackward = () => {
@@ -80,9 +80,9 @@ export class FirstOnlyVariedList<T extends Item<U>, U> extends Component<Props<T
80
80
  };
81
81
 
82
82
  shouldShowMrcuForward = () => {
83
- const { data } = this.props;
83
+ const { data, visibleItems } = this.props;
84
84
  const list = this.base.current!;
85
- return list.index < data.length - 1;
85
+ return list.index < data.length - 1 && data.length > visibleItems - 2;
86
86
  };
87
87
 
88
88
  shouldShowMrcuBackward = () => {
@@ -76,9 +76,9 @@ export class FixedToEndList<T extends Item<U>, U>
76
76
  };
77
77
 
78
78
  shouldShowMrcuForward = () => {
79
- const { visibleItems } = this.props;
79
+ const { data, visibleItems } = this.props;
80
80
  const list = this.base.current!;
81
- return list.index <= list.data.length - visibleItems + 1;
81
+ return list.index <= data.length - visibleItems + 1 && data.length > visibleItems - 2;
82
82
  };
83
83
 
84
84
  shouldShowMrcuBackward = () => this.controller.scrollIndex > 0;
@@ -1,10 +1,12 @@
1
1
  import { Component, Reference } from '@24i/bigscreen-sdk/jsx';
2
2
  import { IFocusable } from '@24i/bigscreen-sdk/focus';
3
3
  import { SharedProps, SharedVariedProps, Item } from './types';
4
+ import { ListBase } from './Base';
4
5
 
5
6
  export interface List<
6
7
  T extends Item<U>, U, V extends SharedProps<T, U> = SharedProps<T, U>,
7
8
  > extends IFocusable, Component<V> {
9
+ base: Reference<ListBase<T, U>>,
8
10
  appendData(data: U[]): void,
9
11
  prependData(data: U[]): void,
10
12
  scrollTo(index: number): void,
@@ -55,7 +55,7 @@ the output would be:
55
55
  ## Logger Manager
56
56
 
57
57
  Logger Manager is used for managing loggers. We are able to add individual loggers to the Logger Manager and perform various operations on them.
58
- All loggers that we want to add to the Logger Manager should inherit from the [LoggerBase](./src/loggers/LoggerBase/README.md) abstract class.
58
+ All loggers that we want to add to the Logger Manager should inherit from the [LoggerBase](./src/loggers/LoggerBase/README) abstract class.
59
59
 
60
60
  ### Methods
61
61
 
@@ -116,7 +116,9 @@ export class MenuAndContentContainer<T extends string = string>
116
116
  isMenuAvailable() {
117
117
  const { router: { current: router } } = this.props;
118
118
  const scene = router?.getActiveRoute()?.component.current as SceneWithMenuAvailability;
119
- return !!scene.constructor.isMenuEnabled;
119
+ const { isMenuEnabled } = scene.constructor;
120
+ if (typeof isMenuEnabled === 'function') return isMenuEnabled();
121
+ return !!isMenuEnabled;
120
122
  }
121
123
 
122
124
  /**
@@ -83,7 +83,7 @@ export type SceneWithMenuAvailability = IRoute & {
83
83
  /**
84
84
  * static flag - true for menu is enabled, undefined (missing) or false for disabled.
85
85
  */
86
- isMenuEnabled?: boolean,
86
+ isMenuEnabled?: boolean | (() => boolean),
87
87
  }
88
88
  };
89
89
 
@@ -8,8 +8,8 @@ type Props = {
8
8
  children: JSX.Element;
9
9
  getMountingPoint: () => Reference<HTMLElement>;
10
10
  direction: Direction;
11
- forward: () => void;
12
- backward: () => void;
11
+ forward: () => any;
12
+ backward: () => any;
13
13
  shouldShowMrcuForward?: () => boolean;
14
14
  shouldShowMrcuBackward?: () => boolean;
15
15
  };
@@ -78,6 +78,10 @@ export class ScrollTextBase extends Component<Props> implements IFocusable {
78
78
  if (processed) stopEvent(event);
79
79
  };
80
80
 
81
+ onMouseEnter = () => {
82
+ this.focus({ preventScroll: true });
83
+ };
84
+
81
85
  updateArrowNavigation(enable: boolean) {
82
86
  if (enable) {
83
87
  removeClass(this.arrowNavRef.current!.domRef, DISABLED_CLASS);
@@ -118,6 +122,7 @@ export class ScrollTextBase extends Component<Props> implements IFocusable {
118
122
  className={className}
119
123
  ref={this.domRef}
120
124
  onKeyDown={this.onKeyDown}
125
+ onMouseEnter={this.onMouseEnter}
121
126
  tabIndex={0}
122
127
  >
123
128
  <Scroller
@@ -37,14 +37,14 @@ describe('createExportMaps', () => {
37
37
  createExportMaps();
38
38
  expect(writeFileSync).toHaveBeenCalledWith(
39
39
  expect.stringContaining('package.json'),
40
- JSON.stringify({
40
+ `${JSON.stringify({
41
41
  name: 'mock-root-package',
42
42
  exports: {
43
43
  './adobe-heartbeat': './packages/adobe-heartbeat/src/index.ts',
44
44
  './animations/mock': './packages/animations/src/__mocks__/JSAnimations.ts',
45
45
  './animations': './packages/animations/src/index.ts',
46
46
  }
47
- }, null, 4),
47
+ }, null, 4)}\n`,
48
48
  );
49
49
  });
50
50
  });
@@ -52,7 +52,7 @@ const createPackageJsonMapping = () => {
52
52
  exports[`./${exportAlias}`] = `./packages/${exportPath}`;
53
53
  });
54
54
  (packageJson.exports as Record<string, string>) = exports;
55
- fs.writeFileSync(resolve('./package.json'), JSON.stringify(packageJson, null, 4));
55
+ fs.writeFileSync(resolve('./package.json'), `${JSON.stringify(packageJson, null, 4)}\n`);
56
56
  };
57
57
 
58
58
  export const createExportMaps = () => {
@@ -1,245 +0,0 @@
1
- import { Component, createRef, removeNode } from '@24i/bigscreen-sdk/jsx';
2
- import { shallow, MountedComponent } from '@24i/bigscreen-sdk/jsx/test-utils';
3
- import {
4
- focusCandidate,
5
- setFocusCandidate,
6
- setActiveElementAsFocusCandidate,
7
- setNextFocusCandidate,
8
- setCandidateFallback,
9
- getLastCandidate,
10
- getCandidateStack,
11
- clearCandidateStack,
12
- } from '../candidate';
13
-
14
- class MockComponent extends Component<{}> {
15
- wrapperRef = createRef<HTMLDivElement>();
16
-
17
- focus(options?: FocusOptions) {
18
- this.wrapperRef.current!.focus(options);
19
- }
20
-
21
- render() {
22
- return <div tabIndex={0} ref={this.wrapperRef} />;
23
- }
24
- }
25
-
26
- describe('Focus candidate', () => {
27
- let elementStructure: MountedComponent<HTMLDivElement>;
28
- const refs = {
29
- testElement: createRef<HTMLDivElement>(),
30
- testComponent1: createRef<MockComponent>(),
31
- testComponent2: createRef<MockComponent>(),
32
- };
33
-
34
- beforeEach(() => {
35
- elementStructure = shallow<HTMLDivElement>(
36
- <div tabIndex={0}>
37
- <div
38
- ref={refs.testElement}
39
- tabIndex={0}
40
- className="test-element"
41
- />
42
- <MockComponent ref={refs.testComponent1} />
43
- <MockComponent ref={refs.testComponent2} />
44
- </div>,
45
- );
46
- });
47
-
48
- afterEach(() => {
49
- jest.clearAllMocks();
50
- clearCandidateStack();
51
- elementStructure.unmount();
52
- });
53
-
54
- it('should register a candidate', () => {
55
- refs.testElement.current!.focus();
56
- setActiveElementAsFocusCandidate();
57
- expect(getLastCandidate()).toBe(refs.testElement.current!);
58
- });
59
-
60
- it('should register a manual candidate', () => {
61
- setFocusCandidate(refs.testComponent1.current!);
62
- expect(getLastCandidate()).toBe(refs.testComponent1.current!);
63
- });
64
-
65
- it('should register the next candidate', () => {
66
- setNextFocusCandidate(refs.testComponent1.current!);
67
- expect(getLastCandidate()).toBe(refs.testComponent1.current!);
68
- });
69
-
70
- it('should not register the same candidates twice', () => {
71
- refs.testElement.current!.focus();
72
- setActiveElementAsFocusCandidate();
73
- setActiveElementAsFocusCandidate();
74
- expect(getCandidateStack()).toEqual([
75
- refs.testElement.current!,
76
- ]);
77
- });
78
-
79
- it('should the focus candidate', () => {
80
- elementStructure.ref().focus();
81
- setActiveElementAsFocusCandidate();
82
- refs.testElement.current!.focus();
83
- focusCandidate();
84
- expect(document.activeElement).toBe(elementStructure.ref());
85
- });
86
-
87
- it('should fill and pop the candidate stack properly', () => {
88
- elementStructure.ref().focus();
89
- setActiveElementAsFocusCandidate();
90
- refs.testElement.current!.focus();
91
- setActiveElementAsFocusCandidate();
92
- refs.testComponent1.current!.focus();
93
- setActiveElementAsFocusCandidate();
94
- refs.testComponent2.current!.focus();
95
- setActiveElementAsFocusCandidate();
96
- expect(getCandidateStack()).toEqual([
97
- elementStructure.ref(),
98
- refs.testElement.current!,
99
- refs.testComponent1.current!.wrapperRef.current!,
100
- refs.testComponent2.current!.wrapperRef.current!,
101
- ]);
102
- // the last registered is skipped, because it's the current activeElement
103
- // so the method should be called only 3x
104
- focusCandidate();
105
- focusCandidate();
106
- focusCandidate();
107
- expect(getCandidateStack()).toEqual([]);
108
- });
109
-
110
- it('should focus candidates during stack popping', () => {
111
- elementStructure.ref().focus();
112
- setActiveElementAsFocusCandidate();
113
- refs.testElement.current!.focus();
114
- setActiveElementAsFocusCandidate();
115
- refs.testComponent1.current!.focus();
116
- setActiveElementAsFocusCandidate();
117
- refs.testComponent2.current!.focus();
118
- focusCandidate();
119
- expect(document.activeElement).toBe(refs.testComponent1.current!.wrapperRef.current!);
120
- focusCandidate();
121
- expect(document.activeElement).toBe(refs.testElement.current!);
122
- focusCandidate();
123
- expect(document.activeElement).toBe(elementStructure.ref());
124
- });
125
-
126
- it('should work with the next candidate', () => {
127
- elementStructure.ref().focus();
128
- setActiveElementAsFocusCandidate();
129
- setNextFocusCandidate(refs.testElement.current!);
130
- refs.testElement.current!.focus();
131
- focusCandidate();
132
- expect(document.activeElement).toBe(elementStructure.ref());
133
- });
134
-
135
- it('should work with the candidate as a component', () => {
136
- refs.testComponent1.current!.focus();
137
- setNextFocusCandidate(refs.testComponent1.current!);
138
- refs.testComponent2.current!.focus();
139
- setNextFocusCandidate(refs.testComponent2.current!);
140
- expect(getCandidateStack()).toEqual([
141
- refs.testComponent1.current!,
142
- refs.testComponent2.current!,
143
- ]);
144
- // last candidate shoul'd not be focused
145
- // because last focused candidate can't be currently focused element
146
- focusCandidate();
147
- expect(document.activeElement).toBe(refs.testComponent1.current!.wrapperRef.current!);
148
- });
149
-
150
- it('should work with the candidate as a reference', () => {
151
- refs.testComponent1.current!.focus();
152
- setNextFocusCandidate(refs.testComponent1);
153
- refs.testComponent2.current!.focus();
154
- setNextFocusCandidate(refs.testComponent2);
155
- expect(getCandidateStack()).toEqual([
156
- refs.testComponent1,
157
- refs.testComponent2,
158
- ]);
159
- focusCandidate();
160
- expect(document.activeElement).toBe(refs.testComponent1.current!.wrapperRef.current!);
161
- });
162
-
163
- it('should work with the candidate as multiple types and focus only unique elements', () => {
164
- refs.testElement.current!.focus();
165
- setActiveElementAsFocusCandidate();
166
- refs.testComponent1.current!.focus();
167
- setNextFocusCandidate(refs.testComponent1);
168
- refs.testComponent2.current!.focus();
169
- setNextFocusCandidate(refs.testComponent2.current!);
170
- expect(getCandidateStack()).toEqual([
171
- refs.testElement.current!,
172
- refs.testComponent1,
173
- refs.testComponent2.current!,
174
- ]);
175
- focusCandidate();
176
- expect(document.activeElement).toBe(refs.testComponent1.current!.wrapperRef.current!);
177
- focusCandidate();
178
- expect(document.activeElement).toBe(refs.testElement.current!);
179
- });
180
-
181
- it('should work with the next candidate as a component', () => {
182
- refs.testComponent1.current!.focus();
183
- setFocusCandidate(refs.testComponent1.current!);
184
- refs.testComponent2.current!.focus();
185
- setNextFocusCandidate(refs.testComponent2.current!);
186
- expect(getCandidateStack()).toEqual([
187
- refs.testComponent1.current!,
188
- refs.testComponent2.current!,
189
- ]);
190
- focusCandidate();
191
- expect(document.activeElement).toBe(refs.testComponent1.current!.wrapperRef.current!);
192
- });
193
-
194
- it('should not focus an unavailable candidate', () => {
195
- elementStructure.ref().focus();
196
- setActiveElementAsFocusCandidate();
197
- refs.testElement.current!.focus();
198
- setActiveElementAsFocusCandidate();
199
- refs.testComponent1.current!.focus();
200
- setFocusCandidate(refs.testComponent1.current!);
201
-
202
- refs.testElement.current!.style.display = 'none';
203
- removeNode(refs.testComponent1.current!.wrapperRef);
204
-
205
- focusCandidate();
206
- expect(document.activeElement).toBe(elementStructure.ref());
207
- });
208
-
209
- it('should set and work with a candidate fallback', () => {
210
- setCandidateFallback(elementStructure.ref());
211
-
212
- refs.testElement.current!.focus();
213
- setActiveElementAsFocusCandidate();
214
- refs.testComponent1.current!.focus();
215
- setActiveElementAsFocusCandidate();
216
- refs.testComponent2.current!.focus();
217
- setActiveElementAsFocusCandidate();
218
-
219
- refs.testElement.current!.style.display = 'none';
220
- removeNode(refs.testComponent1.current!.wrapperRef);
221
- removeNode(refs.testComponent2.current!.wrapperRef);
222
-
223
- focusCandidate();
224
- expect(document.activeElement).toBe(elementStructure.ref());
225
- });
226
-
227
- it('should clear the candidate stack', () => {
228
- elementStructure.ref().focus();
229
- setActiveElementAsFocusCandidate();
230
- refs.testElement.current!.focus();
231
- setActiveElementAsFocusCandidate();
232
- refs.testComponent1.current!.focus();
233
- setActiveElementAsFocusCandidate();
234
-
235
- expect(getCandidateStack()).toEqual([
236
- elementStructure.ref(),
237
- refs.testElement.current!,
238
- refs.testComponent2.current!.wrapperRef.current!,
239
- ]);
240
-
241
- clearCandidateStack();
242
-
243
- expect(getCandidateStack()).toEqual([]);
244
- });
245
- });
@@ -1,21 +0,0 @@
1
- import { focusFirstExisting } from '../focusFirstExisting';
2
-
3
- describe('focusFirstExisting', () => {
4
- const mockFocus1 = jest.fn();
5
- const mockFocus2 = jest.fn();
6
-
7
- it('should properly focus references', () => {
8
- focusFirstExisting(
9
- { current: { focus: mockFocus1 } },
10
- { current: { focus: mockFocus2 } },
11
- )();
12
- expect(mockFocus1).toHaveBeenCalledTimes(1);
13
- expect(mockFocus2).toHaveBeenCalledTimes(0);
14
- focusFirstExisting(
15
- { current: null },
16
- { current: { focus: mockFocus2 } },
17
- )();
18
- expect(mockFocus1).toHaveBeenCalledTimes(1);
19
- expect(mockFocus2).toHaveBeenCalledTimes(1);
20
- });
21
- });
@@ -1,41 +0,0 @@
1
- import { createRef } from '@24i/bigscreen-sdk/jsx';
2
- import { shallow } from '@24i/bigscreen-sdk/jsx/test-utils';
3
- import { refocusAfterHashChange } from '../refocusAfterHashChange';
4
-
5
- jest.useFakeTimers();
6
-
7
- describe('refocusAfterHashChange', () => {
8
- const wrapper = createRef<HTMLDivElement>();
9
- const elementInsideWrapper = createRef<HTMLDivElement>();
10
- const elementOutsideWrapper = createRef<HTMLDivElement>();
11
- shallow(
12
- <div>
13
- <div ref={wrapper}>
14
- <div ref={elementInsideWrapper} tabIndex={0} />
15
- </div>
16
- <div ref={elementOutsideWrapper} tabIndex={0} />
17
- </div>,
18
- );
19
-
20
- afterEach(() => {
21
- jest.clearAllMocks();
22
- });
23
-
24
- it('should refocus active element inside wrapper', () => {
25
- elementInsideWrapper.current!.focus();
26
- const activeElement = document.activeElement as HTMLElement;
27
- const spyOnFocus = jest.spyOn(activeElement, 'focus');
28
- refocusAfterHashChange(wrapper);
29
- jest.runAllTimers();
30
- expect(spyOnFocus).toHaveBeenCalledTimes(1);
31
- });
32
-
33
- it('should not refocus active element outside wrapper', () => {
34
- elementOutsideWrapper.current!.focus();
35
- const activeElement = document.activeElement as HTMLElement;
36
- const spyOnFocus = jest.spyOn(activeElement, 'focus');
37
- refocusAfterHashChange(wrapper);
38
- jest.runAllTimers();
39
- expect(spyOnFocus).toHaveBeenCalledTimes(0);
40
- });
41
- });