@playkit-js/moderation 2.1.1 → 2.2.0-canary.2-223f8a4

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 (69) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +5 -5
  3. package/README.md +105 -8
  4. package/dist/3758875b5327755db91c.svg +3 -0
  5. package/dist/4e88e84bb6cd6f386467.svg +9 -0
  6. package/{src/components/moderation/assets/down.svg → dist/699b282225ecacccffd9.svg} +2 -2
  7. package/dist/f4a8c73d84c247e719f8.svg +3 -0
  8. package/dist/playkit-moderation.js +1 -23
  9. package/dist/playkit-moderation.js.map +1 -1
  10. package/package.json +49 -54
  11. package/src/components/a11y-wrapper/a11y-wrapper.tsx +26 -0
  12. package/src/components/a11y-wrapper/index.ts +1 -0
  13. package/src/components/icons/index.ts +9 -0
  14. package/src/components/moderation/moderation.scss +25 -7
  15. package/src/components/moderation/moderation.tsx +64 -104
  16. package/src/components/plugin-button/plugin-button.scss +14 -14
  17. package/src/components/plugin-button/plugin-button.tsx +26 -3
  18. package/src/components/popover/index.ts +1 -0
  19. package/src/components/popover/popover-menu.scss +4 -0
  20. package/src/components/popover/popover-menu.tsx +57 -0
  21. package/src/components/popover/popover.scss +30 -0
  22. package/src/components/popover/popover.tsx +224 -0
  23. package/src/contrib-services/common-types.ts +2 -0
  24. package/src/contrib-services/contrib-services.ts +80 -0
  25. package/src/contrib-services/contrib-utils.ts +16 -0
  26. package/src/contrib-services/events-manager.ts +59 -0
  27. package/src/contrib-services/floating-item-data.tsx +31 -0
  28. package/src/contrib-services/floating-item.tsx +116 -0
  29. package/src/contrib-services/floating-manager.tsx +224 -0
  30. package/src/contrib-services/index.ts +2 -0
  31. package/src/contrib-services/injected-component/index.ts +1 -0
  32. package/src/contrib-services/injected-component/injected-component.scss +5 -0
  33. package/src/contrib-services/injected-component/injected-component.tsx +58 -0
  34. package/src/contrib-services/kaltura-player-utils.ts +18 -0
  35. package/src/contrib-services/managed-component/_managed-component.scss +8 -0
  36. package/src/contrib-services/managed-component/index.ts +1 -0
  37. package/src/contrib-services/managed-component/managed-component.tsx +71 -0
  38. package/src/contrib-services/object-utils.ts +157 -0
  39. package/src/contrib-services/player-contrib-registry.ts +34 -0
  40. package/src/contrib-services/player-utils.ts +37 -0
  41. package/src/contrib-services/preset-item-data.tsx +43 -0
  42. package/src/contrib-services/preset-item.tsx +113 -0
  43. package/src/contrib-services/preset-manager.tsx +153 -0
  44. package/src/contrib-services/presets-utils.ts +27 -0
  45. package/src/contrib-services/toast/_toast.scss +93 -0
  46. package/src/contrib-services/toast/assets/close.svg +9 -0
  47. package/src/contrib-services/toast/index.ts +1 -0
  48. package/src/contrib-services/toast/toast.tsx +67 -0
  49. package/src/contrib-services/toast-manager.tsx +121 -0
  50. package/src/contrib-services/toasts-container/_toasts-container.scss +21 -0
  51. package/src/contrib-services/toasts-container/index.ts +1 -0
  52. package/src/contrib-services/toasts-container/toasts-container.tsx +23 -0
  53. package/src/contrib-services/ui-player-adapter/index.tsx +1 -0
  54. package/src/contrib-services/ui-player-adapter/ui-player-adapter.tsx +27 -0
  55. package/src/contrib-services/uuid.ts +6 -0
  56. package/src/global.d.ts +6 -6
  57. package/src/index.ts +13 -1
  58. package/src/moderation-plugin.scss +12 -12
  59. package/src/moderation-plugin.tsx +123 -160
  60. package/src/providers/index.ts +2 -0
  61. package/src/providers/report-loader.ts +69 -0
  62. package/src/providers/response-types/index.ts +2 -0
  63. package/src/providers/response-types/kaltura-moderation-flag-response.ts +13 -0
  64. package/src/providers/response-types/kaltura-moderation-flag.ts +51 -0
  65. package/src/variables.scss +4 -1
  66. package/src/assets/.gitkeep +0 -0
  67. package/src/assets/close.svg +0 -10
  68. package/src/assets/flag.svg +0 -6
  69. package/src/components/.gitkeep +0 -0
@@ -0,0 +1,224 @@
1
+ import {FloatingItem} from './floating-item';
2
+ import {
3
+ FloatingItemData,
4
+ FloatingItemProps,
5
+ FloatingPositions,
6
+ } from './floating-item-data';
7
+ import {PresetManager, PresetManagerEventTypes} from './preset-manager';
8
+ import {ComponentChild, h} from 'preact';
9
+ import {PlayerSize, VideoSize} from './common-types';
10
+ import {getPlayerSize, getVideoSize} from './player-utils';
11
+ import {ManagedComponent} from './managed-component';
12
+ import {PresetsUtils} from './presets-utils';
13
+ import {getContribConfig} from './contrib-utils';
14
+
15
+ export interface FloatingManagerOptions {
16
+ kalturaPlayer: KalturaPlayerTypes.Player;
17
+ presetManager: PresetManager;
18
+ }
19
+
20
+ const defaultFloatingConfig: any = {
21
+ presetAreasMapping: {
22
+ Playback: {
23
+ VideoArea: 'VideoArea',
24
+ PresetArea: 'PresetArea',
25
+ InteractiveArea: 'InteractiveArea',
26
+ },
27
+ Live: {
28
+ VideoArea: 'VideoArea',
29
+ PresetArea: 'PresetArea',
30
+ InteractiveArea: 'InteractiveArea',
31
+ },
32
+ },
33
+ };
34
+
35
+ const acceptableTypes = ['VideoArea', 'PresetArea', 'InteractiveArea'];
36
+
37
+ export class FloatingManager {
38
+ private _items: Record<FloatingPositions, FloatingItem[]> = {
39
+ [FloatingPositions.VideoArea]: [],
40
+ [FloatingPositions.InteractiveArea]: [],
41
+ [FloatingPositions.PresetArea]: [],
42
+ };
43
+ private _componentRef: Record<FloatingPositions, ManagedComponent | null> = {
44
+ [FloatingPositions.InteractiveArea]: null,
45
+ [FloatingPositions.VideoArea]: null,
46
+ [FloatingPositions.PresetArea]: null,
47
+ };
48
+ private _cache: {
49
+ canvas: {
50
+ playerSize: PlayerSize;
51
+ videoSize: VideoSize;
52
+ };
53
+ } = {
54
+ canvas: {
55
+ playerSize: {width: 0, height: 0},
56
+ videoSize: {width: 0, height: 0},
57
+ },
58
+ };
59
+
60
+ private _floatingConfig: any;
61
+
62
+ constructor(private _options: FloatingManagerOptions) {
63
+ this._floatingConfig = getContribConfig(
64
+ this._options.kalturaPlayer,
65
+ 'ui.floating',
66
+ defaultFloatingConfig,
67
+ {
68
+ explicitMerge: ['presetAreasMapping'],
69
+ }
70
+ );
71
+
72
+ const groupedPresets = PresetsUtils.groupPresetAreasByType({
73
+ presetAreasMapping: this._floatingConfig.presetAreasMapping,
74
+ acceptableTypes,
75
+ });
76
+
77
+ Object.keys(groupedPresets).forEach(presetType => {
78
+ this._options.presetManager.add({
79
+ label: 'floating-manager',
80
+ presetAreas: groupedPresets[presetType],
81
+ // @ts-ignore
82
+ renderChild: () => this._renderChild(FloatingPositions[presetType]),
83
+ });
84
+ });
85
+ this._addPlayerBindings();
86
+ this._updateCachedCanvas();
87
+ }
88
+
89
+ /**
90
+ * initialize new floating ui item
91
+ * @param item
92
+ */
93
+ //TODO push new item to relevant position array according to its' FloatingPositions value
94
+ add(data: FloatingItemData): FloatingItem | null {
95
+ const {presetManager} = this._options;
96
+
97
+ const itemOptions = {
98
+ // @ts-ignore
99
+ presetManager,
100
+ ...this._options,
101
+ data,
102
+ };
103
+
104
+ const item = new FloatingItem(itemOptions);
105
+ this._items[data.position].push(item);
106
+ return item;
107
+ }
108
+
109
+ remove(item: FloatingItem) {
110
+ const positionItems = this._items[item.data.position];
111
+ const itemIndex = positionItems.indexOf(item);
112
+ if (itemIndex > -1) {
113
+ positionItems[itemIndex].destroy();
114
+ positionItems.splice(itemIndex, 1);
115
+ } else {
116
+ console.warn(`couldn't remove ${item} since it wasn't found`);
117
+ }
118
+ }
119
+
120
+ reset(): void {
121
+ const allItems = [
122
+ ...this._items.VideoArea,
123
+ ...this._items.InteractiveArea,
124
+ ...this._items.PresetArea,
125
+ ];
126
+ allItems.forEach(item => {
127
+ try {
128
+ item.destroy();
129
+ } catch (e) {
130
+ // TODO log error
131
+ console.warn(e);
132
+ }
133
+ });
134
+
135
+ this._items.VideoArea = [];
136
+ this._items.PresetArea = [];
137
+ this._items.InteractiveArea = [];
138
+ }
139
+
140
+ private _getRendererProps(
141
+ props: Partial<FloatingItemProps>
142
+ ): FloatingItemProps {
143
+ const {kalturaPlayer} = this._options;
144
+
145
+ return {
146
+ currentTime:
147
+ typeof props.currentTime !== 'undefined'
148
+ ? props.currentTime
149
+ : kalturaPlayer.currentTime * 1000,
150
+ canvas: this._cache.canvas,
151
+ };
152
+ }
153
+
154
+ private _updateCachedCanvas() {
155
+ this._cache.canvas = {
156
+ playerSize: getPlayerSize(this._options.kalturaPlayer),
157
+ videoSize: getVideoSize(this._options.kalturaPlayer),
158
+ };
159
+ }
160
+
161
+ private _renderItems = (position: FloatingPositions) => {
162
+ const props = this._getRendererProps({});
163
+ return this._items[position].map(item => item.renderFloatingChild(props));
164
+ };
165
+
166
+ private _renderChild = (position: FloatingPositions): ComponentChild => {
167
+ return (
168
+ <ManagedComponent
169
+ label={'floating-manager'}
170
+ renderChildren={() => this._renderItems(position)}
171
+ isShown={() => true}
172
+ ref={(ref: any) => (this._componentRef[position] = ref)}
173
+ />
174
+ );
175
+ };
176
+
177
+ private _updateComponents() {
178
+ if (this._componentRef.InteractiveArea) {
179
+ this._componentRef.InteractiveArea.update();
180
+ }
181
+
182
+ if (this._componentRef.PresetArea) {
183
+ this._componentRef.PresetArea.update();
184
+ }
185
+
186
+ if (this._componentRef.VideoArea) {
187
+ this._componentRef.VideoArea.update();
188
+ }
189
+ }
190
+
191
+ private _addPlayerBindings() {
192
+ const {kalturaPlayer} = this._options;
193
+
194
+ kalturaPlayer.addEventListener(kalturaPlayer.Event.TIME_UPDATE, () => {
195
+ this._updateComponents();
196
+ });
197
+
198
+ kalturaPlayer.addEventListener(kalturaPlayer.Event.MEDIA_LOADED, () => {
199
+ this._updateCachedCanvas();
200
+ this._updateComponents();
201
+ });
202
+
203
+ kalturaPlayer.addEventListener(kalturaPlayer.Event.LOADED_DATA, () => {
204
+ this._updateCachedCanvas();
205
+ this._updateComponents();
206
+ });
207
+
208
+ this._options.presetManager.on(
209
+ PresetManagerEventTypes.VideoResizeEvent,
210
+ () => {
211
+ this._updateCachedCanvas();
212
+ this._updateComponents();
213
+ }
214
+ );
215
+
216
+ this._options.presetManager.on(
217
+ PresetManagerEventTypes.PresetResizeEvent,
218
+ () => {
219
+ this._updateCachedCanvas();
220
+ this._updateComponents();
221
+ }
222
+ );
223
+ }
224
+ }
@@ -0,0 +1,2 @@
1
+ // TODO: remove toasts from Moderation plugin and use from UI managers once the toast-manager got implemented
2
+ export * from './contrib-services';
@@ -0,0 +1 @@
1
+ export {InjectedComponent} from './injected-component';
@@ -0,0 +1,5 @@
1
+ .fill-container {
2
+ width: 100%;
3
+ height: 100%;
4
+ overflow: hidden;
5
+ }
@@ -0,0 +1,58 @@
1
+ import {h, Component} from 'preact';
2
+ import * as styles from './injected-component.scss';
3
+
4
+ export interface InjectedComponentProps {
5
+ onCreate: (options: {parent: HTMLDivElement}) => void;
6
+ onDestroy: (options: {parent: HTMLDivElement}) => void;
7
+ label: string;
8
+ fillContainer: boolean;
9
+ }
10
+
11
+ class InjectedComponent extends Component<InjectedComponentProps> {
12
+ _root = null;
13
+
14
+ shouldComponentUpdate(): boolean {
15
+ return false;
16
+ }
17
+
18
+ componentDidMount(): void {
19
+ const {onCreate, label} = this.props;
20
+
21
+ if (!onCreate) {
22
+ return;
23
+ }
24
+
25
+ const parentElement = this._root;
26
+ if (!parentElement) {
27
+ return;
28
+ }
29
+
30
+ onCreate({parent: parentElement});
31
+ }
32
+
33
+ componentWillUnmount(): void {
34
+ const {onDestroy, label} = this.props;
35
+ const parentElement = this._root;
36
+
37
+ if (!parentElement || !onDestroy) {
38
+ return;
39
+ }
40
+
41
+ onDestroy({parent: parentElement});
42
+
43
+ }
44
+
45
+ render() {
46
+ const {label, fillContainer} = this.props;
47
+ const className = fillContainer ? styles.fillContainer : '';
48
+ return (
49
+ <div
50
+ data-contrib-injected={label}
51
+ className={className}
52
+ ref={(ref: any) => (this._root = ref)}
53
+ />
54
+ );
55
+ }
56
+ }
57
+
58
+ export {InjectedComponent};
@@ -0,0 +1,18 @@
1
+ import {ObjectUtils} from './object-utils';
2
+
3
+ export class KalturaPlayerUtils {
4
+ static getPlayerConfig<T>(
5
+ player: any,
6
+ configPath: string,
7
+ baseConfig: T,
8
+ options: {explicitMerge: string[]}
9
+ ): T {
10
+ const playerContribConfig = ObjectUtils.get(player.config, configPath, {});
11
+
12
+ return ObjectUtils.mergeDefaults<T>(
13
+ playerContribConfig as any,
14
+ baseConfig,
15
+ options
16
+ );
17
+ }
18
+ }
@@ -0,0 +1,8 @@
1
+ .fill-container {
2
+ width: 100%;
3
+ height: 100%;
4
+ }
5
+
6
+ .inline-container {
7
+ display: inline-block;
8
+ }
@@ -0,0 +1 @@
1
+ export * from './managed-component';
@@ -0,0 +1,71 @@
1
+ import {h, Component, ComponentChild, ComponentChildren} from 'preact';
2
+ import * as styles from './_managed-component.scss';
3
+ const {
4
+ redux: {connect},
5
+ } = KalturaPlayer.ui;
6
+
7
+ type ManagedComponentState = {
8
+ toggler: boolean;
9
+ };
10
+ type ManagedComponentProps = {
11
+ isShown: () => boolean;
12
+ renderChildren: (playerSize: string) => ComponentChildren;
13
+ label: string;
14
+ fillContainer: boolean;
15
+ playerSize?: string;
16
+ updateOnPlayerSizeChanged?: boolean;
17
+ };
18
+
19
+ const mapStateToProps = (state: Record<string, any>) => ({
20
+ playerSize: state.shell.playerSize,
21
+ });
22
+ @connect(mapStateToProps, null, null, {forwardRef: true})
23
+ export class ManagedComponent extends Component<
24
+ ManagedComponentProps,
25
+ ManagedComponentState
26
+ > {
27
+
28
+ static defaultProps = {
29
+ fillContainer: false,
30
+ };
31
+
32
+ update() {
33
+ this.setState((prev: ManagedComponentState) => {
34
+ return {
35
+ toggler: !prev.toggler,
36
+ };
37
+ });
38
+ }
39
+
40
+ shouldComponentUpdate(prevProps: Readonly<ManagedComponentProps>): boolean {
41
+ const {updateOnPlayerSizeChanged, playerSize} = this.props;
42
+ return (
43
+ (updateOnPlayerSizeChanged && prevProps.playerSize !== playerSize) ||
44
+ prevProps.playerSize === playerSize
45
+ );
46
+ }
47
+
48
+ componentDidMount(): void {
49
+ this.setState({
50
+ toggler: false,
51
+ });
52
+ }
53
+
54
+ render() {
55
+ const {fillContainer, isShown, playerSize} = this.props;
56
+ if (!isShown()) {
57
+ return null;
58
+ }
59
+
60
+ return (
61
+ <div
62
+ data-contrib-item={this.props.label}
63
+ className={[
64
+ `${fillContainer ? styles.fillContainer : ''}`,
65
+ styles.inlineContainer,
66
+ ].join(' ')}>
67
+ {this.props.renderChildren(playerSize!)}
68
+ </div>
69
+ );
70
+ }
71
+ }
@@ -0,0 +1,157 @@
1
+ export class ObjectUtils {
2
+ /**
3
+ * @param {T} data - The data to copy.
4
+ * @returns {T} - The copied data.
5
+ */
6
+ public static copyDeep<T extends Record<string, any>>(data: T): T {
7
+ // @ts-ignore
8
+ let node;
9
+ if (Array.isArray(data)) {
10
+ node = data.length > 0 ? data.slice(0) : [];
11
+ node.forEach((e, i) => {
12
+ if (
13
+ (typeof e === 'object' && e !== {}) ||
14
+ (Array.isArray(e) && e.length > 0)
15
+ ) {
16
+ node[i] = ObjectUtils.copyDeep(e);
17
+ }
18
+ });
19
+ } else if (typeof data === 'object') {
20
+ node = Object.assign({}, data);
21
+ Object.keys(node).forEach(key => {
22
+ if (
23
+ // @ts-ignore
24
+ (typeof node[key] === 'object' && node[key] !== {}) ||
25
+ // @ts-ignore
26
+ (Array.isArray(node[key]) && node[key].length > 0)
27
+ ) {
28
+ // @ts-ignore
29
+ node[key] = ObjectUtils.copyDeep(node[key]);
30
+ }
31
+ });
32
+ } else {
33
+ node = data;
34
+ }
35
+ // @ts-ignore
36
+ return node;
37
+ }
38
+
39
+ /**
40
+ * @param {T} item - The item to check.
41
+ * @returns {T} - Whether the item is an object.
42
+ */
43
+ public static isObject(item: any) {
44
+ return item && typeof item === 'object' && !Array.isArray(item);
45
+ }
46
+
47
+ /**
48
+ * @param {T} target - The target object.
49
+ * @param {T} sources - The objects to merge.
50
+ * @returns {T} - The merged object.
51
+ */
52
+ public static mergeDeep<T extends Record<string, any>>(
53
+ target: Partial<T>,
54
+ sources: Partial<T>[],
55
+ extra?: {explicitMerge?: string[]}
56
+ ): Partial<T> {
57
+ if (!sources.length) {
58
+ return target;
59
+ }
60
+
61
+ const explicitMerge: string[] = (extra ? extra.explicitMerge : null) || [];
62
+ const source = sources.shift();
63
+ if (ObjectUtils.isObject(target) && ObjectUtils.isObject(source)) {
64
+ for (const key in source) {
65
+ if (ObjectUtils.isObject(source[key])) {
66
+ if (!target[key]) Object.assign(target, {[key]: {}});
67
+
68
+ if (explicitMerge.indexOf(key) !== -1) {
69
+ target[key] = ObjectUtils.explicitFlatMerge<any>(
70
+ // @ts-ignore
71
+ target[key],
72
+ source[key]
73
+ );
74
+ } else {
75
+ // @ts-ignore
76
+ ObjectUtils.mergeDeep(target[key], [source[key]], extra);
77
+ }
78
+ } else {
79
+ Object.assign(target, {[key]: source[key]});
80
+ }
81
+ }
82
+ }
83
+ return ObjectUtils.mergeDeep(target, sources, extra);
84
+ }
85
+
86
+ public static mergeDefaults<T extends Record<string, any>>(
87
+ source: Partial<T>,
88
+ defaults: T,
89
+ extra?: {explicitMerge?: string[]}
90
+ ): T {
91
+ return ObjectUtils.mergeDeep({}, [defaults, source], extra) as T;
92
+ }
93
+
94
+ /**
95
+ * source properties will override all equivalent properties in target. null or empty objects properties in source
96
+ * will cause the removal of these properties in target.
97
+ * all other data will be merged
98
+ * @param initialObject
99
+ * @param source
100
+ */
101
+ public static explicitFlatMerge<T extends Record<string, any>>(
102
+ initialObject: Partial<T>,
103
+ source: Partial<T>
104
+ ): any {
105
+ const result = {...initialObject};
106
+ Object.keys(source).forEach(key => {
107
+ // @ts-ignore
108
+ if (source[key] === null || Object.keys(source[key]).length === 0) {
109
+ delete result[key];
110
+ } else {
111
+ // @ts-ignore
112
+ // https://github.com/microsoft/TypeScript/issues/31661
113
+ result[key] = source[key];
114
+ }
115
+ });
116
+ return result;
117
+ }
118
+
119
+ public static get(
120
+ obj: Record<string, any>,
121
+ path: string,
122
+ defaultValue: any
123
+ ): any {
124
+ function stringToPath(path: string) {
125
+ // @ts-ignore
126
+ const output = [];
127
+ // Split to an array with dot notation
128
+ path.split('.').forEach(item => {
129
+ // Split to an array with bracket notation
130
+ item.split(/\[([^}]+)\]/g).forEach(key => {
131
+ // Push to the new array
132
+ if (key.length > 0) {
133
+ output.push(key);
134
+ }
135
+ });
136
+ });
137
+ // @ts-ignore
138
+ return output;
139
+ }
140
+
141
+ // Get the path as an array
142
+ const pathArray = stringToPath(path);
143
+
144
+ let current = obj;
145
+
146
+ // For each item in the path, dig into the object
147
+ for (let i = 0; i < pathArray.length; i++) {
148
+ // If the item isn't found, return the default (or null)
149
+ if (!current[pathArray[i]]) return defaultValue;
150
+
151
+ // Otherwise, update the current value
152
+ current = current[pathArray[i]];
153
+ }
154
+
155
+ return current;
156
+ }
157
+ }
@@ -0,0 +1,34 @@
1
+ export class PlayerContribRegistry {
2
+ private _cache: Record<string, {instance: any}> = {};
3
+
4
+ static get(player: any): PlayerContribRegistry {
5
+ player.__contrib__ = player.__contrib__ || {};
6
+ player.__contrib__.services =
7
+ player.__contrib__.services || new PlayerContribRegistry();
8
+ return player.__contrib__.services;
9
+ }
10
+
11
+ private constructor() {}
12
+
13
+ public get(token: string): any {
14
+ const result = this._cache[token];
15
+
16
+ if (!result) {
17
+ throw new Error(`cannot find resource with token ${token}`);
18
+ }
19
+
20
+ return result;
21
+ }
22
+
23
+ public register<T>(token: string, creator: () => T): T {
24
+ let requestedResource = this._cache[token];
25
+
26
+ if (!requestedResource) {
27
+ requestedResource = this._cache[token] = {
28
+ instance: creator(),
29
+ };
30
+ }
31
+
32
+ return requestedResource.instance;
33
+ }
34
+ }
@@ -0,0 +1,37 @@
1
+ import {PlayerSize, VideoSize} from './common-types';
2
+
3
+ export function getPlayerSize(
4
+ kalturaPlayer: any
5
+ ): PlayerSize {
6
+ return kalturaPlayer ? kalturaPlayer.dimensions : {width: 0, height: 0};
7
+ }
8
+
9
+ export function getVideoSize(
10
+ kalturaPlayer: any
11
+ ): VideoSize {
12
+ if (!kalturaPlayer) {
13
+ return {width: 0, height: 0};
14
+ }
15
+
16
+ const videoTrack = kalturaPlayer.getActiveTracks().video;
17
+
18
+ if (
19
+ !videoTrack ||
20
+ videoTrack.width === undefined ||
21
+ videoTrack.height === undefined
22
+ ) {
23
+ // fallback - mainly for Safari
24
+ if (kalturaPlayer.getVideoElement()) {
25
+ return {
26
+ width: kalturaPlayer.getVideoElement().videoWidth,
27
+ height: kalturaPlayer.getVideoElement().videoHeight,
28
+ };
29
+ }
30
+ return {width: 0, height: 0};
31
+ }
32
+
33
+ return {
34
+ width: videoTrack.width,
35
+ height: videoTrack.height,
36
+ };
37
+ }
@@ -0,0 +1,43 @@
1
+ import {ComponentChild} from 'preact';
2
+
3
+ export enum ReservedPresetNames {
4
+ Playback = 'Playback',
5
+ Live = 'Live',
6
+ }
7
+
8
+ export enum ReservedPresetAreas {
9
+ 'PresetFloating' = 'PresetFloating',
10
+ 'BottomBarLeftControls' = 'BottomBarLeftControls',
11
+ 'BottomBarRightControls' = 'BottomBarRightControls',
12
+ 'TopBarLeftControls' = 'TopBarLeftControls',
13
+ 'TopBarRightControls' = 'TopBarRightControls',
14
+ 'SidePanelTop' = 'SidePanelTop',
15
+ 'SidePanelLeft' = 'SidePanelLeft',
16
+ 'SidePanelRight' = 'SidePanelRight',
17
+ 'SidePanelBottom' = 'SidePanelBottom',
18
+ 'PresetArea' = 'PresetArea',
19
+ 'InteractiveArea' = 'InteractiveArea',
20
+ 'PlayerArea' = 'PlayerArea',
21
+ 'VideoArea' = 'VideoArea',
22
+ }
23
+
24
+ export enum RelativeToTypes {
25
+ Before = 'Before',
26
+ After = 'After',
27
+ Replace = 'Replace',
28
+ }
29
+
30
+ export interface PresetItemData {
31
+ label: string;
32
+ fillContainer?: boolean;
33
+ isolateComponent?: boolean;
34
+ presetAreas: Record<
35
+ ReservedPresetNames | string,
36
+ ReservedPresetAreas | string
37
+ >;
38
+ renderChild: () => ComponentChild;
39
+ relativeTo?: {
40
+ type: RelativeToTypes;
41
+ name: string;
42
+ };
43
+ }