@24i/bigscreen-sdk 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -10
- package/packages/developer-tools/src/EnvironmentSelection/styles/EnvironmentSelection.scss +1 -1
- package/packages/device/src/driver/index.vidaa.tv.ts +1 -0
- package/packages/device/src/resolver/resolver.ts +5 -0
- package/packages/driver-vidaa/src/DeviceVidaa.ts +134 -0
- package/packages/driver-vidaa/src/__mocks__/vidaa.ts +20 -0
- package/packages/driver-vidaa/src/formatUserAgent.ts +16 -0
- package/packages/driver-vidaa/src/index.ts +1 -0
- package/packages/driver-vidaa/src/keymap.ts +54 -0
- package/packages/driver-vidaa/src/types.ts +82 -0
- package/packages/list/src/BasicList/BasicList.tsx +4 -1
- package/packages/list/src/EdgeOffsetList/EdgeOffsetList.tsx +4 -3
- package/packages/list/src/FirstOnlyList/FirstOnlyList.tsx +2 -2
- package/packages/list/src/FirstOnlyVariedList/FirstOnlyVariedList.tsx +2 -2
- package/packages/list/src/FixedToEndList/FixedToEndList.tsx +2 -2
- package/packages/logger/README.md +1 -1
- package/packages/scroll-text/src/Base.tsx +5 -0
- package/packages/focus/src/__test__/candidate.spec.tsx +0 -245
- package/packages/focus/src/__test__/focusFirstExisting.spec.tsx +0 -21
- package/packages/focus/src/__test__/refocusAfterHashChange.spec.tsx +0 -41
- package/packages/focus/src/__test__/safeFocus.spec.tsx +0 -41
- package/packages/mouse-navigation/src/__test__/MouseElementWrapper.spec.tsx +0 -61
- package/packages/mouse-navigation/src/__test__/MouseNavigation.spec.tsx +0 -107
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@24i/bigscreen-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "SmartApps BIGscreen SDK monorepo",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"homepage": "https://github.com/24i/smartapps-bigscreen-sdk#readme",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@24i/player-base": "6.10.0",
|
|
41
|
-
"@24i/smartapps-datalayer": "2.3.
|
|
42
|
-
"@sentry/browser": "^7.
|
|
41
|
+
"@24i/smartapps-datalayer": "2.3.2",
|
|
42
|
+
"@sentry/browser": "^7.8.0",
|
|
43
43
|
"@types/prop-types": "^15.7.5",
|
|
44
44
|
"@types/scheduler": "^0.16.1",
|
|
45
45
|
"csstype": "^3.1.0",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"@24i/bigscreen-sdk": "file:.",
|
|
51
51
|
"@24i/eslint-config-smartapps-bigscreen-linters": "file:./libs/linters",
|
|
52
52
|
"@24i/smartapps-bigscreen-changelog-generator": "0.17.0",
|
|
53
|
-
"@babel/core": "^7.18.
|
|
54
|
-
"@babel/preset-env": "^7.18.
|
|
53
|
+
"@babel/core": "^7.18.9",
|
|
54
|
+
"@babel/preset-env": "^7.18.9",
|
|
55
55
|
"@types/fs-extra": "^9.0.13",
|
|
56
56
|
"@types/inquirer": "^8.2.1",
|
|
57
|
-
"@types/jest": "^28.1.
|
|
57
|
+
"@types/jest": "^28.1.6",
|
|
58
58
|
"@types/minimist": "^1.2.2",
|
|
59
|
-
"@types/node": "^
|
|
59
|
+
"@types/node": "^18.6.3",
|
|
60
60
|
"@types/react": "^18.0.15",
|
|
61
61
|
"babel-jest": "^28.1.2",
|
|
62
62
|
"chalk": "^4.1.2",
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"fs-extra": "^10.1.0",
|
|
66
66
|
"full-icu": "^1.4.0",
|
|
67
67
|
"identity-obj-proxy": "^3.0.0",
|
|
68
|
-
"inquirer": "^9.0.
|
|
68
|
+
"inquirer": "^9.0.2",
|
|
69
69
|
"jest": "^28.1.2",
|
|
70
70
|
"jest-canvas-mock": "^2.4.0",
|
|
71
71
|
"jest-environment-jsdom": "^28.1.2",
|
|
72
72
|
"minimist": "^1.2.6",
|
|
73
73
|
"patch-package": "^6.2.1",
|
|
74
|
-
"sass": "^1.
|
|
74
|
+
"sass": "^1.54.0",
|
|
75
75
|
"sass-true": "^6.1.0",
|
|
76
|
-
"ts-jest": "^28.0.
|
|
76
|
+
"ts-jest": "^28.0.7",
|
|
77
77
|
"ts-node": "^10.8.2",
|
|
78
78
|
"tsconfig-paths-jest": "0.0.1",
|
|
79
79
|
"typescript": "^4.7.2"
|
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
"./driver-kreatv": "./packages/driver-kreatv/src/index.ts",
|
|
112
112
|
"./driver-saphi": "./packages/driver-saphi/src/index.ts",
|
|
113
113
|
"./driver-tizen": "./packages/driver-tizen/src/index.ts",
|
|
114
|
+
"./driver-vidaa": "./packages/driver-vidaa/src/index.ts",
|
|
114
115
|
"./driver-webos/scripts/template": "./packages/driver-webos/scripts/template.ts",
|
|
115
116
|
"./driver-webos/scripts/exportWebOSTVjs": "./packages/driver-webos/scripts/exportWebOSTVjs.ts",
|
|
116
117
|
"./driver-webos": "./packages/driver-webos/src/index.ts",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DeviceVidaa as Device } from '@24i/bigscreen-sdk/driver-vidaa';
|
|
@@ -5,6 +5,7 @@ import { DeviceHbbTV } from '@24i/bigscreen-sdk/driver-hbbtv';
|
|
|
5
5
|
import { DeviceKreaTV } from '@24i/bigscreen-sdk/driver-kreatv';
|
|
6
6
|
import { DeviceSaphi } from '@24i/bigscreen-sdk/driver-saphi';
|
|
7
7
|
import { DeviceTizen } from '@24i/bigscreen-sdk/driver-tizen';
|
|
8
|
+
import { DeviceVidaa } from '@24i/bigscreen-sdk/driver-vidaa';
|
|
8
9
|
import { DeviceWebos } from '@24i/bigscreen-sdk/driver-webos';
|
|
9
10
|
import { DeviceXbox } from '@24i/bigscreen-sdk/driver-xbox';
|
|
10
11
|
|
|
@@ -30,6 +31,10 @@ const getDevice = () => {
|
|
|
30
31
|
info('Saphi');
|
|
31
32
|
return new DeviceSaphi();
|
|
32
33
|
}
|
|
34
|
+
if (userAgent.match(/Hisense/)) {
|
|
35
|
+
info('VIDAA');
|
|
36
|
+
return new DeviceVidaa();
|
|
37
|
+
}
|
|
33
38
|
if (userAgent.match(/Ekioh/)) {
|
|
34
39
|
info('KreaTV');
|
|
35
40
|
return new DeviceKreaTV();
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DeviceBase,
|
|
3
|
+
ConnectionType,
|
|
4
|
+
ScreenSaverStatus,
|
|
5
|
+
VolumeRange,
|
|
6
|
+
} from '@24i/bigscreen-sdk/driver-base';
|
|
7
|
+
import { getPlatformInfo } from './formatUserAgent';
|
|
8
|
+
import { HisenseVidaaApi } from './types';
|
|
9
|
+
import { getKeyMap } from './keymap';
|
|
10
|
+
|
|
11
|
+
declare global {
|
|
12
|
+
interface Window extends HisenseVidaaApi {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class DeviceVidaa extends DeviceBase {
|
|
16
|
+
keyMap = getKeyMap();
|
|
17
|
+
|
|
18
|
+
platformInfo = getPlatformInfo(navigator.userAgent);
|
|
19
|
+
|
|
20
|
+
async initDevice(): Promise<void> {
|
|
21
|
+
this.initNetworkChangeListener();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
initNetworkChangeListener() {
|
|
25
|
+
window.addEventListener('online', () => {
|
|
26
|
+
this.triggerEvent('networkchange', { isConnected: true });
|
|
27
|
+
});
|
|
28
|
+
window.addEventListener('offline', () => {
|
|
29
|
+
this.triggerEvent('networkchange', { isConnected: false });
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
reboot(): void {
|
|
34
|
+
let rootPath = '';
|
|
35
|
+
const splitUrl = window.location.href.split('#');
|
|
36
|
+
if (splitUrl.length > 1) rootPath = splitUrl[0];
|
|
37
|
+
window.location.href = rootPath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exit(): void {
|
|
41
|
+
window.close();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async getManufacturerName(): Promise<string> {
|
|
45
|
+
return 'Hisense';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async getPlatformName(): Promise<string> {
|
|
49
|
+
return 'VIDAA';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async getPlatformVersion(): Promise<string> {
|
|
53
|
+
// platform version of Hisense VIDAA is defined on TV 2020 or later
|
|
54
|
+
return this.platformInfo.platformVersion || '';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getDeviceName(): Promise<string> {
|
|
58
|
+
return `Hisense VIDAA ${await this.getModelName()}`.trim();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getModelName(): Promise<string> {
|
|
62
|
+
return window.Hisense_GetModelName() || '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async getFirmware(): Promise<string> {
|
|
66
|
+
return window.Hisense_GetFirmWareVersion() || '';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async is4KSupported(): Promise<boolean> {
|
|
70
|
+
return window.Hisense_Get4KSupportState() || false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async is8KSupported(): Promise<boolean> {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async getUuid(): Promise<string> {
|
|
78
|
+
return window.Hisense_GetDeviceID() || '';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async getVolume(): Promise<number> {
|
|
82
|
+
return VolumeRange.UNSUPPORTED;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
86
|
+
async setVolume(volumePercentage: number): Promise<void> {
|
|
87
|
+
// not supported on Hisense VIDAA platform
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
91
|
+
async mute(mute: boolean): Promise<void> {
|
|
92
|
+
// not supported on Hisense VIDAA platform
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async isMute(): Promise<boolean> {
|
|
96
|
+
// not supported on Hisense VIDAA platform
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async getScreenSaver(): Promise<ScreenSaverStatus> {
|
|
101
|
+
// not supported on Hisense VIDAA platform
|
|
102
|
+
return { enabled: false };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
106
|
+
async setScreenSaver(status: ScreenSaverStatus): Promise<void> {
|
|
107
|
+
// not supported on Hisense VIDAA platform
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
111
|
+
async setUserAgent(userAgent: string): Promise<boolean> {
|
|
112
|
+
// not supported on Hisense VIDAA platform
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async isNetworkConnected(): Promise<boolean> {
|
|
117
|
+
return window.navigator.onLine;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async getConnectionType(): Promise<ConnectionType> {
|
|
121
|
+
// not supported on Hisense VIDAA platform
|
|
122
|
+
return 'unknown';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async getLocalIP(): Promise<string> {
|
|
126
|
+
// not supported on Hisense VIDAA platform
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async getMacAddress(): Promise<string> {
|
|
131
|
+
// not supported on Hisense VIDAA platform
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HisenseVidaaApi, HisenseVidaaKeys } from '../types';
|
|
2
|
+
|
|
3
|
+
export const mockHisenseVidaaApi: HisenseVidaaApi = {
|
|
4
|
+
Hisense_GetBrand: () => 'hisense',
|
|
5
|
+
Hisense_GetModelName: () => '5U61FQEVS',
|
|
6
|
+
Hisense_GetFirmWareVersion: () => 'V0000.01.00Q.L0301',
|
|
7
|
+
Hisense_Get4KSupportState: () => true,
|
|
8
|
+
Hisense_GetDeviceID: () => '861003009000001000000641123456789012',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Key constants are set to random number values
|
|
12
|
+
export const mockHisenseVidaaKeys = {
|
|
13
|
+
VK_LEFT: 0,
|
|
14
|
+
VK_RIGHT: 1,
|
|
15
|
+
VK_UP: 2,
|
|
16
|
+
VK_DOWN: 3,
|
|
17
|
+
VK_ENTER: 4,
|
|
18
|
+
VK_BACK_SPACE: 5,
|
|
19
|
+
// the rest of key constants is not needed for testing
|
|
20
|
+
} as HisenseVidaaKeys;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses platform info of VIDAA from user agent string.
|
|
3
|
+
* NOTE: Platform info of VIDAA is available in user agent of TVs 2020 or later.
|
|
4
|
+
*
|
|
5
|
+
* @param userAgent User agent string
|
|
6
|
+
* @returns object with platform info like platform name and platform version.
|
|
7
|
+
* If values are not not available, values of keys are set to undefined.
|
|
8
|
+
* Ex. for VIDAA platform string like "VIDAA/4.0" in user agent string , it returns
|
|
9
|
+
* object { platformName: "VIDAA", platformVersion: "4.0" }
|
|
10
|
+
*/
|
|
11
|
+
export const getPlatformInfo = (userAgent: string) => {
|
|
12
|
+
const [
|
|
13
|
+
, platformName, platformVersion,
|
|
14
|
+
] = userAgent.match(/(VIDAA)\/([\d.]+)/) || [] as Array<undefined>;
|
|
15
|
+
return { platformName, platformVersion };
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DeviceVidaa } from './DeviceVidaa';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
import { KeyMap } from '@24i/bigscreen-sdk/driver-base';
|
|
3
|
+
import { HisenseVidaaKeys } from './types';
|
|
4
|
+
|
|
5
|
+
declare const window: Window & HisenseVidaaKeys;
|
|
6
|
+
|
|
7
|
+
export const getKeyMap = () => {
|
|
8
|
+
KeyMap.overrideValues({
|
|
9
|
+
LEFT: { keyCode: window.VK_LEFT },
|
|
10
|
+
RIGHT: { keyCode: window.VK_RIGHT },
|
|
11
|
+
UP: { keyCode: window.VK_UP },
|
|
12
|
+
DOWN: { keyCode: window.VK_DOWN },
|
|
13
|
+
ENTER: { keyCode: window.VK_ENTER },
|
|
14
|
+
BACK: { keyCode: window.VK_BACK_SPACE },
|
|
15
|
+
|
|
16
|
+
RED: { keyCode: window.VK_RED },
|
|
17
|
+
GREEN: { keyCode: window.VK_GREEN },
|
|
18
|
+
YELLOW: { keyCode: window.VK_YELLOW },
|
|
19
|
+
BLUE: { keyCode: window.VK_BLUE },
|
|
20
|
+
|
|
21
|
+
PLAY: { keyCode: window.VK_PLAY },
|
|
22
|
+
PAUSE: { keyCode: window.VK_PAUSE },
|
|
23
|
+
PLAYPAUSE: { keyCode: window.VK_PLAY_PAUSE },
|
|
24
|
+
STOP: { keyCode: window.VK_STOP },
|
|
25
|
+
FF: { keyCode: window.VK_FAST_FWD },
|
|
26
|
+
REW: { keyCode: window.VK_REWIND },
|
|
27
|
+
|
|
28
|
+
NUM_0: { keyCode: window.VK_0 },
|
|
29
|
+
NUM_1: { keyCode: window.VK_1 },
|
|
30
|
+
NUM_2: { keyCode: window.VK_2 },
|
|
31
|
+
NUM_3: { keyCode: window.VK_3 },
|
|
32
|
+
NUM_4: { keyCode: window.VK_4 },
|
|
33
|
+
NUM_5: { keyCode: window.VK_5 },
|
|
34
|
+
NUM_6: { keyCode: window.VK_6 },
|
|
35
|
+
NUM_7: { keyCode: window.VK_7 },
|
|
36
|
+
NUM_8: { keyCode: window.VK_8 },
|
|
37
|
+
NUM_9: { keyCode: window.VK_9 },
|
|
38
|
+
KP_0: { keyCode: window.VK_NUMPAD0 },
|
|
39
|
+
KP_1: { keyCode: window.VK_NUMPAD1 },
|
|
40
|
+
KP_2: { keyCode: window.VK_NUMPAD2 },
|
|
41
|
+
KP_3: { keyCode: window.VK_NUMPAD3 },
|
|
42
|
+
KP_4: { keyCode: window.VK_NUMPAD4 },
|
|
43
|
+
KP_5: { keyCode: window.VK_NUMPAD5 },
|
|
44
|
+
KP_6: { keyCode: window.VK_NUMPAD6 },
|
|
45
|
+
KP_7: { keyCode: window.VK_NUMPAD7 },
|
|
46
|
+
KP_8: { keyCode: window.VK_NUMPAD8 },
|
|
47
|
+
KP_9: { keyCode: window.VK_NUMPAD9 },
|
|
48
|
+
|
|
49
|
+
CHANNEL_UP: { keyCode: window.VK_CHANNEL_UP || 427 },
|
|
50
|
+
CHANNEL_DOWN: { keyCode: window.VK_CHANNEL_DOWN || 428 },
|
|
51
|
+
INFO: { keyCode: window.VK_INFO },
|
|
52
|
+
});
|
|
53
|
+
return KeyMap.generateKeyCodeKeyMap();
|
|
54
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface HisenseVidaaApi {
|
|
2
|
+
/**
|
|
3
|
+
* This interface will retrieve Hisense Unique ID for the device.
|
|
4
|
+
* @return a 32bytes string that represents the device id.
|
|
5
|
+
* Example: 861003009000001000000641123456789012
|
|
6
|
+
*/
|
|
7
|
+
Hisense_GetDeviceID: () => string,
|
|
8
|
+
/**
|
|
9
|
+
* This interface will retrieve the firmware version for the device.
|
|
10
|
+
* @return a string that represents the firmware version.
|
|
11
|
+
* Example: V00.01.00a.F0116
|
|
12
|
+
*/
|
|
13
|
+
Hisense_GetFirmWareVersion: () => string,
|
|
14
|
+
/**
|
|
15
|
+
* This will retrieve the 4K support status for the device.
|
|
16
|
+
* @return true if 4K is supported otherwise returns false.
|
|
17
|
+
*/
|
|
18
|
+
Hisense_Get4KSupportState: () => boolean,
|
|
19
|
+
/**
|
|
20
|
+
* This will retrieve the TV brand for the device.
|
|
21
|
+
* @return a brand full name string that represents the TV brand.
|
|
22
|
+
* Example: hisense, sharp
|
|
23
|
+
*/
|
|
24
|
+
Hisense_GetBrand: () => string,
|
|
25
|
+
/**
|
|
26
|
+
* This will retrieve the TV model name (hardware version) for the device.
|
|
27
|
+
* @return a string that represents the TV model name.
|
|
28
|
+
*/
|
|
29
|
+
Hisense_GetModelName: () => string,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type HisenseVidaaKeys = {
|
|
33
|
+
readonly VK_UP: number,
|
|
34
|
+
readonly VK_RIGHT: number,
|
|
35
|
+
readonly VK_DOWN: number,
|
|
36
|
+
readonly VK_LEFT: number,
|
|
37
|
+
readonly VK_ENTER: number,
|
|
38
|
+
readonly VK_BACK_SPACE: number,
|
|
39
|
+
|
|
40
|
+
readonly VK_BLUE: number,
|
|
41
|
+
readonly VK_RED: number,
|
|
42
|
+
readonly VK_GREEN: number,
|
|
43
|
+
readonly VK_YELLOW: number,
|
|
44
|
+
|
|
45
|
+
readonly VK_MENU: number,
|
|
46
|
+
|
|
47
|
+
readonly VK_0: number,
|
|
48
|
+
readonly VK_1: number,
|
|
49
|
+
readonly VK_2: number,
|
|
50
|
+
readonly VK_3: number,
|
|
51
|
+
readonly VK_4: number,
|
|
52
|
+
readonly VK_5: number,
|
|
53
|
+
readonly VK_6: number,
|
|
54
|
+
readonly VK_7: number,
|
|
55
|
+
readonly VK_8: number,
|
|
56
|
+
readonly VK_9: number,
|
|
57
|
+
// keys VK_NUMPAD{X} are not introduced in Hisense VIDAA spec but exist in global scope
|
|
58
|
+
readonly VK_NUMPAD0: number,
|
|
59
|
+
readonly VK_NUMPAD1: number,
|
|
60
|
+
readonly VK_NUMPAD2: number,
|
|
61
|
+
readonly VK_NUMPAD3: number,
|
|
62
|
+
readonly VK_NUMPAD4: number,
|
|
63
|
+
readonly VK_NUMPAD5: number,
|
|
64
|
+
readonly VK_NUMPAD6: number,
|
|
65
|
+
readonly VK_NUMPAD7: number,
|
|
66
|
+
readonly VK_NUMPAD8: number,
|
|
67
|
+
readonly VK_NUMPAD9: number,
|
|
68
|
+
|
|
69
|
+
readonly VK_PLAY: number,
|
|
70
|
+
readonly VK_PAUSE: number,
|
|
71
|
+
readonly VK_PLAY_PAUSE: number,
|
|
72
|
+
readonly VK_STOP: number,
|
|
73
|
+
readonly VK_TRACK_NEXT: number,
|
|
74
|
+
readonly VK_TRACK_PREV: number,
|
|
75
|
+
readonly VK_FAST_FWD: number,
|
|
76
|
+
readonly VK_REWIND: number,
|
|
77
|
+
readonly VK_SUBTITLE: number,
|
|
78
|
+
readonly VK_INFO: number,
|
|
79
|
+
// VK_CHANNEL_{UP/DOWN} not introduced in Hisense VIDAA spec but exists in global scope
|
|
80
|
+
readonly VK_CHANNEL_UP: number,
|
|
81
|
+
readonly VK_CHANNEL_DOWN: number,
|
|
82
|
+
};
|
|
@@ -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
|
|
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
|
-
|
|
98
|
+
|
|
99
99
|
return (
|
|
100
|
-
scrollIndex <
|
|
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 <=
|
|
81
|
+
return list.index <= data.length - visibleItems + 1 && data.length > visibleItems - 2;
|
|
82
82
|
};
|
|
83
83
|
|
|
84
84
|
shouldShowMrcuBackward = () => this.controller.scrollIndex > 0;
|
|
@@ -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
|
|
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
|
|
|
@@ -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
|
|
@@ -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
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { createRef } from '@24i/bigscreen-sdk/jsx';
|
|
2
|
-
import { shallow } from '@24i/bigscreen-sdk/jsx/test-utils';
|
|
3
|
-
import { safeFocus } from '../safeFocus';
|
|
4
|
-
|
|
5
|
-
describe('safeFocus', () => {
|
|
6
|
-
const wrapperElement = createRef<HTMLDivElement>();
|
|
7
|
-
const element1 = createRef<HTMLDivElement>();
|
|
8
|
-
const element2 = createRef<HTMLDivElement>();
|
|
9
|
-
const testSafeFocus = safeFocus(wrapperElement);
|
|
10
|
-
|
|
11
|
-
shallow(
|
|
12
|
-
<div>
|
|
13
|
-
<div ref={wrapperElement} tabIndex={0}>
|
|
14
|
-
<div ref={element1} tabIndex={0} />
|
|
15
|
-
</div>
|
|
16
|
-
<div ref={element2} tabIndex={0} />
|
|
17
|
-
</div>,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
it('should focus element when activeElement is inside of the wrapperElement', () => {
|
|
21
|
-
wrapperElement.current!.focus();
|
|
22
|
-
testSafeFocus(element1.current!);
|
|
23
|
-
expect(document.activeElement === element1.current!).toBeTruthy();
|
|
24
|
-
testSafeFocus(wrapperElement.current!);
|
|
25
|
-
expect(document.activeElement === wrapperElement.current!).toBeTruthy();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should focus element when activeElement is body', () => {
|
|
29
|
-
document.body.focus();
|
|
30
|
-
testSafeFocus(element1.current!);
|
|
31
|
-
expect(document.activeElement === element1.current!).toBeTruthy();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should not focus element when activeElement is outside of the wrapperElement', () => {
|
|
35
|
-
element2.current!.focus();
|
|
36
|
-
testSafeFocus(element1.current!);
|
|
37
|
-
expect(document.activeElement === element1.current!).toBeFalsy();
|
|
38
|
-
testSafeFocus(wrapperElement.current!);
|
|
39
|
-
expect(document.activeElement === wrapperElement.current!).toBeFalsy();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { createRef } from '@24i/bigscreen-sdk/jsx';
|
|
2
|
-
import { getKeyMap } from '@24i/bigscreen-sdk/device';
|
|
3
|
-
import { MountedComponent, shallow, keydown } from '@24i/bigscreen-sdk/jsx/test-utils';
|
|
4
|
-
import { MouseElementWrapper } from '../MouseElementWrapper';
|
|
5
|
-
import { MouseNavigationInterface } from '../MouseNavigationInterface';
|
|
6
|
-
|
|
7
|
-
describe('MouseElementWrapper', () => {
|
|
8
|
-
const mPointRef = createRef<HTMLDivElement>();
|
|
9
|
-
let root: MountedComponent<HTMLDivElement>;
|
|
10
|
-
let nav: MountedComponent<MouseElementWrapper>;
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
jest.clearAllMocks();
|
|
14
|
-
root = shallow(<div className="mounting-point" ref={mPointRef} />);
|
|
15
|
-
nav = shallow(
|
|
16
|
-
<>
|
|
17
|
-
<MouseElementWrapper
|
|
18
|
-
getMountingPoint={() => mPointRef}
|
|
19
|
-
>
|
|
20
|
-
<div className="test-child" />
|
|
21
|
-
</MouseElementWrapper>
|
|
22
|
-
</>,
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
afterEach(() => {
|
|
27
|
-
nav.unmount();
|
|
28
|
-
root.unmount();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('should not render child immediately', () => {
|
|
32
|
-
expect(root.find('.test-child')).toBe(null);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('should handle key event correctly', () => {
|
|
36
|
-
|
|
37
|
-
const event = new MouseEvent('mousemove', {});
|
|
38
|
-
document.dispatchEvent(event);
|
|
39
|
-
|
|
40
|
-
expect(root.find('.mounting-point').firstElementChild)
|
|
41
|
-
.toBe(nav.ref().domRef.current);
|
|
42
|
-
|
|
43
|
-
keydown(document, getKeyMap().UP!);
|
|
44
|
-
expect(root.find('.mounting-point').firstElementChild).toBe(null);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should handle interface request to hide', () => {
|
|
48
|
-
const event = new MouseEvent('mousemove', {});
|
|
49
|
-
document.dispatchEvent(event);
|
|
50
|
-
|
|
51
|
-
expect(root.find('.mounting-point').firstElementChild)
|
|
52
|
-
.toBe(nav.ref().domRef.current);
|
|
53
|
-
|
|
54
|
-
MouseNavigationInterface.hide();
|
|
55
|
-
expect(root.find('.mounting-point').firstElementChild).toBe(null);
|
|
56
|
-
|
|
57
|
-
MouseNavigationInterface.show();
|
|
58
|
-
expect(root.find('.mounting-point').firstElementChild)
|
|
59
|
-
.toBe(nav.ref().domRef.current);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { createRef } from '@24i/bigscreen-sdk/jsx';
|
|
2
|
-
import { getKeyMap } from '@24i/bigscreen-sdk/device';
|
|
3
|
-
import { MountedComponent, shallow, keydown } from '@24i/bigscreen-sdk/jsx/test-utils';
|
|
4
|
-
import { MouseNavigation } from '../MouseNavigation';
|
|
5
|
-
import { MouseNavigationInterface } from '../MouseNavigationInterface';
|
|
6
|
-
|
|
7
|
-
const forwardMock = jest.fn();
|
|
8
|
-
const backwardMock = jest.fn();
|
|
9
|
-
const showForwardMock = jest.fn(() => true);
|
|
10
|
-
const showBackwardMock = jest.fn(() => true);
|
|
11
|
-
|
|
12
|
-
describe('MouseNavigation', () => {
|
|
13
|
-
const mPointRef = createRef<HTMLDivElement>();
|
|
14
|
-
let nav: MountedComponent<MouseNavigation>;
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
nav = shallow(
|
|
18
|
-
<MouseNavigation
|
|
19
|
-
getMountingPoint={() => mPointRef}
|
|
20
|
-
direction="vertical"
|
|
21
|
-
forward={forwardMock}
|
|
22
|
-
backward={backwardMock}
|
|
23
|
-
shouldShowMrcuForward={showForwardMock}
|
|
24
|
-
shouldShowMrcuBackward={showBackwardMock}
|
|
25
|
-
>
|
|
26
|
-
<>
|
|
27
|
-
<div className="test-child" />
|
|
28
|
-
<div className="mounting-point" ref={mPointRef} />
|
|
29
|
-
</>
|
|
30
|
-
</MouseNavigation>,
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
nav.unmount();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should handle key event correctly', () => {
|
|
39
|
-
|
|
40
|
-
const event = new MouseEvent('mousemove', {});
|
|
41
|
-
document.dispatchEvent(event);
|
|
42
|
-
|
|
43
|
-
expect(nav.find('.mounting-point').firstElementChild)
|
|
44
|
-
.toBe(nav.ref().arrows.current?.domRef.current);
|
|
45
|
-
|
|
46
|
-
keydown(document, getKeyMap().UP!);
|
|
47
|
-
|
|
48
|
-
expect(nav.find('.mounting-point').firstElementChild).toBe(null);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should render child', () => {
|
|
52
|
-
expect(nav.find('.test-child').className).not.toBe(null);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should return correct mapped direction', () => {
|
|
56
|
-
expect(nav.ref().mapDirectionToProps('horizontal').horizontal).toBe(true);
|
|
57
|
-
expect(nav.ref().mapDirectionToProps('vertical').vertical).toBe(true);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should handle interface request to hide', () => {
|
|
61
|
-
const event = new MouseEvent('mousemove', {});
|
|
62
|
-
document.dispatchEvent(event);
|
|
63
|
-
|
|
64
|
-
expect(nav.find('.mounting-point').firstElementChild)
|
|
65
|
-
.toBe(nav.ref().arrows.current?.domRef.current);
|
|
66
|
-
|
|
67
|
-
MouseNavigationInterface.hide();
|
|
68
|
-
|
|
69
|
-
expect(nav.find('.mounting-point').firstElementChild).toBe(null);
|
|
70
|
-
|
|
71
|
-
MouseNavigationInterface.show();
|
|
72
|
-
|
|
73
|
-
expect(nav.find('.mounting-point').firstElementChild)
|
|
74
|
-
.toBe(nav.ref().arrows.current?.domRef.current);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should propagate forward and backward', () => {
|
|
78
|
-
nav.ref().handleArrowState = jest.fn();
|
|
79
|
-
nav.ref().forward();
|
|
80
|
-
nav.ref().backward();
|
|
81
|
-
|
|
82
|
-
expect(forwardMock).toHaveBeenCalledTimes(1);
|
|
83
|
-
expect(backwardMock).toHaveBeenCalledTimes(1);
|
|
84
|
-
expect(nav.ref().handleArrowState).toHaveBeenCalledTimes(2);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should show/hide arrows as reported', () => {
|
|
88
|
-
nav.ref().arrows = {
|
|
89
|
-
current: {
|
|
90
|
-
enableArrow: jest.fn(),
|
|
91
|
-
disableArrow: jest.fn(),
|
|
92
|
-
},
|
|
93
|
-
} as any;
|
|
94
|
-
|
|
95
|
-
nav.ref().handleArrowState();
|
|
96
|
-
expect(nav.ref().arrows.current?.enableArrow).toHaveBeenNthCalledWith(1, 'down');
|
|
97
|
-
expect(nav.ref().arrows.current?.enableArrow).toHaveBeenNthCalledWith(2, 'up');
|
|
98
|
-
expect(nav.ref().arrows.current?.enableArrow).toHaveBeenCalledTimes(2);
|
|
99
|
-
|
|
100
|
-
showForwardMock.mockImplementationOnce(() => false);
|
|
101
|
-
showBackwardMock.mockImplementationOnce(() => false);
|
|
102
|
-
nav.ref().handleArrowState();
|
|
103
|
-
expect(nav.ref().arrows.current?.disableArrow).toHaveBeenNthCalledWith(1, 'down');
|
|
104
|
-
expect(nav.ref().arrows.current?.disableArrow).toHaveBeenNthCalledWith(2, 'up');
|
|
105
|
-
expect(nav.ref().arrows.current?.disableArrow).toHaveBeenCalledTimes(2);
|
|
106
|
-
});
|
|
107
|
-
});
|