@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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +5 -5
- package/README.md +105 -8
- package/dist/3758875b5327755db91c.svg +3 -0
- package/dist/4e88e84bb6cd6f386467.svg +9 -0
- package/{src/components/moderation/assets/down.svg → dist/699b282225ecacccffd9.svg} +2 -2
- package/dist/f4a8c73d84c247e719f8.svg +3 -0
- package/dist/playkit-moderation.js +1 -23
- package/dist/playkit-moderation.js.map +1 -1
- package/package.json +49 -54
- package/src/components/a11y-wrapper/a11y-wrapper.tsx +26 -0
- package/src/components/a11y-wrapper/index.ts +1 -0
- package/src/components/icons/index.ts +9 -0
- package/src/components/moderation/moderation.scss +25 -7
- package/src/components/moderation/moderation.tsx +64 -104
- package/src/components/plugin-button/plugin-button.scss +14 -14
- package/src/components/plugin-button/plugin-button.tsx +26 -3
- package/src/components/popover/index.ts +1 -0
- package/src/components/popover/popover-menu.scss +4 -0
- package/src/components/popover/popover-menu.tsx +57 -0
- package/src/components/popover/popover.scss +30 -0
- package/src/components/popover/popover.tsx +224 -0
- package/src/contrib-services/common-types.ts +2 -0
- package/src/contrib-services/contrib-services.ts +80 -0
- package/src/contrib-services/contrib-utils.ts +16 -0
- package/src/contrib-services/events-manager.ts +59 -0
- package/src/contrib-services/floating-item-data.tsx +31 -0
- package/src/contrib-services/floating-item.tsx +116 -0
- package/src/contrib-services/floating-manager.tsx +224 -0
- package/src/contrib-services/index.ts +2 -0
- package/src/contrib-services/injected-component/index.ts +1 -0
- package/src/contrib-services/injected-component/injected-component.scss +5 -0
- package/src/contrib-services/injected-component/injected-component.tsx +58 -0
- package/src/contrib-services/kaltura-player-utils.ts +18 -0
- package/src/contrib-services/managed-component/_managed-component.scss +8 -0
- package/src/contrib-services/managed-component/index.ts +1 -0
- package/src/contrib-services/managed-component/managed-component.tsx +71 -0
- package/src/contrib-services/object-utils.ts +157 -0
- package/src/contrib-services/player-contrib-registry.ts +34 -0
- package/src/contrib-services/player-utils.ts +37 -0
- package/src/contrib-services/preset-item-data.tsx +43 -0
- package/src/contrib-services/preset-item.tsx +113 -0
- package/src/contrib-services/preset-manager.tsx +153 -0
- package/src/contrib-services/presets-utils.ts +27 -0
- package/src/contrib-services/toast/_toast.scss +93 -0
- package/src/contrib-services/toast/assets/close.svg +9 -0
- package/src/contrib-services/toast/index.ts +1 -0
- package/src/contrib-services/toast/toast.tsx +67 -0
- package/src/contrib-services/toast-manager.tsx +121 -0
- package/src/contrib-services/toasts-container/_toasts-container.scss +21 -0
- package/src/contrib-services/toasts-container/index.ts +1 -0
- package/src/contrib-services/toasts-container/toasts-container.tsx +23 -0
- package/src/contrib-services/ui-player-adapter/index.tsx +1 -0
- package/src/contrib-services/ui-player-adapter/ui-player-adapter.tsx +27 -0
- package/src/contrib-services/uuid.ts +6 -0
- package/src/global.d.ts +6 -6
- package/src/index.ts +13 -1
- package/src/moderation-plugin.scss +12 -12
- package/src/moderation-plugin.tsx +123 -160
- package/src/providers/index.ts +2 -0
- package/src/providers/report-loader.ts +69 -0
- package/src/providers/response-types/index.ts +2 -0
- package/src/providers/response-types/kaltura-moderation-flag-response.ts +13 -0
- package/src/providers/response-types/kaltura-moderation-flag.ts +51 -0
- package/src/variables.scss +4 -1
- package/src/assets/.gitkeep +0 -0
- package/src/assets/close.svg +0 -10
- package/src/assets/flag.svg +0 -6
- package/src/components/.gitkeep +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import {h, render} from 'preact';
|
|
2
|
+
import {PresetItemData, RelativeToTypes} from './preset-item-data';
|
|
3
|
+
import {ManagedComponent} from './managed-component';
|
|
4
|
+
import {InjectedComponent} from './injected-component';
|
|
5
|
+
export interface PresetItemOptions {
|
|
6
|
+
kalturaPlayer: KalturaPlayerTypes.Player;
|
|
7
|
+
data: PresetItemData;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PresetItemProps {}
|
|
11
|
+
|
|
12
|
+
export interface KalturaPlayerPresetComponent {
|
|
13
|
+
label: string;
|
|
14
|
+
presets: string[];
|
|
15
|
+
container: string;
|
|
16
|
+
get: () => () => ManagedComponent;
|
|
17
|
+
afterComponent?: string;
|
|
18
|
+
beforeComponent?: string;
|
|
19
|
+
replaceComponent?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class PresetItem {
|
|
23
|
+
private _options: PresetItemOptions;
|
|
24
|
+
|
|
25
|
+
constructor(options: PresetItemOptions) {
|
|
26
|
+
this._options = options;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get playerConfig(): KalturaPlayerPresetComponent[] {
|
|
30
|
+
const configs: KalturaPlayerPresetComponent[] = [];
|
|
31
|
+
|
|
32
|
+
for (const presetType in this._options.data.presetAreas) {
|
|
33
|
+
const presetContainer = this._options.data.presetAreas[presetType];
|
|
34
|
+
const {relativeTo} = this._options.data;
|
|
35
|
+
|
|
36
|
+
if (!presetContainer) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result: KalturaPlayerPresetComponent = {
|
|
41
|
+
label: this._options.data.label,
|
|
42
|
+
presets: [presetType],
|
|
43
|
+
container: presetContainer,
|
|
44
|
+
get: this._render,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (relativeTo) {
|
|
48
|
+
switch (relativeTo.type) {
|
|
49
|
+
case RelativeToTypes.After:
|
|
50
|
+
result['afterComponent'] = relativeTo.name;
|
|
51
|
+
break;
|
|
52
|
+
case RelativeToTypes.Before:
|
|
53
|
+
result['beforeComponent'] = relativeTo.name;
|
|
54
|
+
break;
|
|
55
|
+
case RelativeToTypes.Replace:
|
|
56
|
+
result['replaceComponent'] = relativeTo.name;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
configs.push(result);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return configs;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private _render = (): any => {
|
|
68
|
+
if (this._options.data.isolateComponent) {
|
|
69
|
+
const {
|
|
70
|
+
data: {label, fillContainer},
|
|
71
|
+
} = this._options;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<InjectedComponent
|
|
75
|
+
label={label}
|
|
76
|
+
fillContainer={fillContainer || false}
|
|
77
|
+
onCreate={this._onCreate}
|
|
78
|
+
onDestroy={this._onDestroy}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return this._options.data.renderChild();
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
private _onDestroy = (options: {
|
|
87
|
+
context?: any;
|
|
88
|
+
parent: HTMLElement;
|
|
89
|
+
}): void => {
|
|
90
|
+
// TODO sakal handle destroy
|
|
91
|
+
if (!options.parent) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
render(null, options.parent);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
private _onCreate = (options: {context?: any; parent: HTMLElement}): void => {
|
|
99
|
+
try {
|
|
100
|
+
if (!options.parent) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const child = this._options.data.renderChild();
|
|
104
|
+
|
|
105
|
+
if (!child) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
render(child, options.parent);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import {h} from 'preact';
|
|
2
|
+
import {PresetItemData} from './preset-item-data';
|
|
3
|
+
import {KalturaPlayerPresetComponent, PresetItem} from './preset-item';
|
|
4
|
+
import {EventsManager} from './events-manager';
|
|
5
|
+
import {UIPlayerAdapter} from './ui-player-adapter';
|
|
6
|
+
import {PresetsUtils} from './presets-utils';
|
|
7
|
+
import {getContribConfig} from './contrib-utils';
|
|
8
|
+
|
|
9
|
+
export interface PresetManagerOptions {
|
|
10
|
+
kalturaPlayer: KalturaPlayerTypes.Player;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export enum PresetManagerEventTypes {
|
|
14
|
+
PresetResizeEvent = 'PresetResizeEvent',
|
|
15
|
+
VideoResizeEvent = 'VideoResizeEvent',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PresetResizeEvent {
|
|
19
|
+
type: PresetManagerEventTypes.PresetResizeEvent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface VideoResizeEvent {
|
|
23
|
+
type: PresetManagerEventTypes.VideoResizeEvent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type PresetManagerEvents = PresetResizeEvent | VideoResizeEvent;
|
|
27
|
+
|
|
28
|
+
const acceptableTypes = ['PlayerArea'];
|
|
29
|
+
|
|
30
|
+
const defaultPresetConfig: any = {
|
|
31
|
+
presetAreasMapping: {
|
|
32
|
+
Playback: {
|
|
33
|
+
PlayerArea: 'PlayerArea',
|
|
34
|
+
},
|
|
35
|
+
Live: {
|
|
36
|
+
PlayerArea: 'PlayerArea',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export class PresetManager {
|
|
42
|
+
private _events: EventsManager<PresetManagerEvents> = new EventsManager<
|
|
43
|
+
PresetManagerEvents
|
|
44
|
+
>();
|
|
45
|
+
private _isLocked = false;
|
|
46
|
+
private _options: PresetManagerOptions;
|
|
47
|
+
private _items: PresetItem[] = [];
|
|
48
|
+
private _pendingItems: PresetItem[] = [];
|
|
49
|
+
private _presetConfig: any;
|
|
50
|
+
|
|
51
|
+
constructor(options: PresetManagerOptions) {
|
|
52
|
+
this._options = options;
|
|
53
|
+
|
|
54
|
+
this._presetConfig = getContribConfig(
|
|
55
|
+
this._options.kalturaPlayer,
|
|
56
|
+
'ui.preset',
|
|
57
|
+
defaultPresetConfig,
|
|
58
|
+
{
|
|
59
|
+
explicitMerge: ['presetAreasMapping'],
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const groupedPresets = PresetsUtils.groupPresetAreasByType({
|
|
64
|
+
presetAreasMapping: this._presetConfig.presetAreasMapping,
|
|
65
|
+
acceptableTypes,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
this.add({
|
|
69
|
+
label: 'preset-manager',
|
|
70
|
+
presetAreas: groupedPresets['PlayerArea'],
|
|
71
|
+
renderChild: () => (
|
|
72
|
+
<UIPlayerAdapter
|
|
73
|
+
onMount={this._registerToPlayer}
|
|
74
|
+
onUnmount={this._unregisterToPlayer}
|
|
75
|
+
/>
|
|
76
|
+
),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private _registerToPlayer = (player: KalturaPlayerTypes.Player) => {
|
|
81
|
+
player.addEventListener(
|
|
82
|
+
KalturaPlayer.ui.EventType.UI_PRESET_RESIZE,
|
|
83
|
+
this._notifyUIPresetResize
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
player.addEventListener(
|
|
87
|
+
KalturaPlayer.ui.EventType.VIDEO_RESIZE,
|
|
88
|
+
this._notifyVideoResize
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
private _notifyVideoResize = () => {
|
|
93
|
+
this._events.emit({
|
|
94
|
+
type: PresetManagerEventTypes.VideoResizeEvent,
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
private _notifyUIPresetResize = () => {
|
|
99
|
+
this._events.emit({
|
|
100
|
+
type: PresetManagerEventTypes.PresetResizeEvent,
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
private _unregisterToPlayer = (player: KalturaPlayerTypes.Player) => {
|
|
105
|
+
|
|
106
|
+
player.removeEventListener(
|
|
107
|
+
KalturaPlayer.ui.EventType.UI_PRESET_RESIZE,
|
|
108
|
+
this._notifyUIPresetResize
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
player.removeEventListener(
|
|
112
|
+
KalturaPlayer.ui.EventType.VIDEO_RESIZE,
|
|
113
|
+
this._notifyVideoResize
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
on: EventsManager<PresetManagerEvents>['on'] = this._events.on.bind(
|
|
118
|
+
this._events
|
|
119
|
+
);
|
|
120
|
+
off: EventsManager<PresetManagerEvents>['off'] = this._events.off.bind(
|
|
121
|
+
this._events
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
add<TProps>(data: PresetItemData): void {
|
|
125
|
+
if (this._isLocked) {
|
|
126
|
+
console.warn(
|
|
127
|
+
`cannot add new preset items once player completed its' setup phase`
|
|
128
|
+
);
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const component = new PresetItem({
|
|
133
|
+
kalturaPlayer: this._options.kalturaPlayer,
|
|
134
|
+
data,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
this._pendingItems.push(component);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
lockManager(): void {
|
|
141
|
+
this._isLocked = true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
registerComponents(): KalturaPlayerPresetComponent[] {
|
|
145
|
+
let configs: KalturaPlayerPresetComponent[] = [];
|
|
146
|
+
this._pendingItems.forEach(item => {
|
|
147
|
+
configs = [...configs, ...item.playerConfig];
|
|
148
|
+
});
|
|
149
|
+
this._items = [...this._items, ...this._pendingItems];
|
|
150
|
+
this._pendingItems = [];
|
|
151
|
+
return configs.filter(Boolean) as KalturaPlayerPresetComponent[];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface GroupPresetAreasOptions {
|
|
2
|
+
presetAreasMapping: any;
|
|
3
|
+
acceptableTypes: string[];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export class PresetsUtils {
|
|
7
|
+
public static groupPresetAreasByType(
|
|
8
|
+
options: GroupPresetAreasOptions
|
|
9
|
+
): any {
|
|
10
|
+
const {presetAreasMapping, acceptableTypes} = options;
|
|
11
|
+
|
|
12
|
+
const result = {};
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
acceptableTypes.forEach(presetType => (result[presetType] = {}));
|
|
15
|
+
Object.keys(presetAreasMapping).forEach(presetName => {
|
|
16
|
+
Object.keys(presetAreasMapping[presetName]).forEach(presetType => {
|
|
17
|
+
if (acceptableTypes.indexOf(presetType) === -1) {
|
|
18
|
+
} else {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
result[presetType][presetName] =
|
|
21
|
+
presetAreasMapping[presetName][presetType];
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
.toastWrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
min-width: 120px;
|
|
4
|
+
max-width: 264px;
|
|
5
|
+
height: 100%;
|
|
6
|
+
border-radius: 4px;
|
|
7
|
+
background-color: #222222;
|
|
8
|
+
border-left-style: solid;
|
|
9
|
+
border-left-width: 4px;
|
|
10
|
+
text-align: left;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.infoToast {
|
|
14
|
+
border-left-color: #01ACCD;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.successToast {
|
|
18
|
+
border-left-color: #009E48;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.warnToast {
|
|
22
|
+
border-left-color: #F9A71B;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.errorToast {
|
|
26
|
+
border-left-color: #E7585D;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.closeButton {
|
|
30
|
+
position: absolute;
|
|
31
|
+
background-color: transparent;
|
|
32
|
+
top: 0;
|
|
33
|
+
right: 0;
|
|
34
|
+
width: 16px;
|
|
35
|
+
height: 16px;
|
|
36
|
+
object-fit: contain;
|
|
37
|
+
background-repeat: no-repeat;
|
|
38
|
+
border: none;
|
|
39
|
+
background-image: url("./assets/close.svg");
|
|
40
|
+
|
|
41
|
+
&:hover {
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.title {
|
|
47
|
+
font-size: 12px;
|
|
48
|
+
font-weight: normal;
|
|
49
|
+
font-style: normal;
|
|
50
|
+
font-stretch: normal;
|
|
51
|
+
line-height: 1.17;
|
|
52
|
+
letter-spacing: normal;
|
|
53
|
+
color: #cccccc;
|
|
54
|
+
white-space: nowrap;
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
text-overflow: ellipsis;
|
|
57
|
+
padding-top: 4px;
|
|
58
|
+
padding-right: 16px;
|
|
59
|
+
padding-left: 12px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.toastBody {
|
|
63
|
+
position: relative;
|
|
64
|
+
width: 100%;
|
|
65
|
+
padding: 2px 16px 5px 12px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.iconContainer {
|
|
69
|
+
position: relative;
|
|
70
|
+
height: 16px;
|
|
71
|
+
width: 16px;
|
|
72
|
+
float: left;
|
|
73
|
+
margin-right: 7px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.iconWrapper {
|
|
77
|
+
height: 16px;
|
|
78
|
+
width: 16px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.text {
|
|
82
|
+
font-size: 14px;
|
|
83
|
+
font-weight: bold;
|
|
84
|
+
font-style: normal;
|
|
85
|
+
font-stretch: normal;
|
|
86
|
+
line-height: normal;
|
|
87
|
+
letter-spacing: normal;
|
|
88
|
+
color: #cccccc;
|
|
89
|
+
white-space: nowrap;
|
|
90
|
+
overflow: hidden;
|
|
91
|
+
text-overflow: ellipsis;
|
|
92
|
+
}
|
|
93
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
3
|
+
<!-- Generator: Sketch 57.1 (83088) - https://sketch.com -->
|
|
4
|
+
<title>Icons/16/Close</title>
|
|
5
|
+
<desc>Created with Sketch.</desc>
|
|
6
|
+
<g id="Icons/16/Close" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
7
|
+
<path d="M8.8497789,8 L11.824005,10.9742261 C12.058665,11.2088861 12.058665,11.5893451 11.824005,11.824005 C11.5893451,12.058665 11.2088861,12.058665 10.9742261,11.824005 L8,8.8497789 L5.02577387,11.824005 C4.7911139,12.058665 4.41065493,12.058665 4.17599497,11.824005 C3.94133501,11.5893451 3.94133501,11.2088861 4.17599497,10.9742261 L7.1502211,8 L4.17599497,5.02577387 C3.94133501,4.7911139 3.94133501,4.41065493 4.17599497,4.17599497 C4.41065493,3.94133501 4.7911139,3.94133501 5.02577387,4.17599497 L8,7.1502211 L10.9742261,4.17599497 C11.2088861,3.94133501 11.5893451,3.94133501 11.824005,4.17599497 C12.058665,4.41065493 12.058665,4.7911139 11.824005,5.02577387 L8.8497789,8 Z" id="Path" fill="#cccccc"></path>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {Toast} from './toast';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {Component, h} from 'preact';
|
|
2
|
+
import * as styles from './_toast.scss';
|
|
3
|
+
import {ToastSeverity} from '../toast-manager';
|
|
4
|
+
|
|
5
|
+
export interface ToastProps {
|
|
6
|
+
id: string;
|
|
7
|
+
title: string;
|
|
8
|
+
text: string;
|
|
9
|
+
icon: any;
|
|
10
|
+
severity: ToastSeverity;
|
|
11
|
+
onClose: (id: string) => void;
|
|
12
|
+
onClick: () => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ToastState {
|
|
16
|
+
isShown: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class Toast extends Component<ToastProps, ToastState> {
|
|
20
|
+
state = {
|
|
21
|
+
isShown: true,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
private _onClick = (e: any) => {
|
|
25
|
+
this.props.onClick();
|
|
26
|
+
this._onClose(e);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
private _onClose = (e: any) => {
|
|
30
|
+
e.stopPropagation();
|
|
31
|
+
this.setState({isShown: false});
|
|
32
|
+
this.props.onClose(this.props.id);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
private _getToastSeverityClass(): string {
|
|
36
|
+
switch (this.props.severity) {
|
|
37
|
+
case ToastSeverity.Success:
|
|
38
|
+
return styles.successToast;
|
|
39
|
+
case ToastSeverity.Warn:
|
|
40
|
+
return styles.warnToast;
|
|
41
|
+
case ToastSeverity.Error:
|
|
42
|
+
return styles.errorToast;
|
|
43
|
+
default:
|
|
44
|
+
//info
|
|
45
|
+
return styles.infoToast;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
render() {
|
|
50
|
+
const {text, title, icon} = this.props;
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
className={styles.toastWrapper + ' ' + this._getToastSeverityClass()}
|
|
55
|
+
onClick={this._onClick}>
|
|
56
|
+
<button className={styles.closeButton} onClick={this._onClose}></button>
|
|
57
|
+
<div className={styles.title}>{title}</div>
|
|
58
|
+
<div className={styles.toastBody}>
|
|
59
|
+
<div className={styles.iconContainer}>
|
|
60
|
+
<div className={styles.iconWrapper}>{icon}</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div className={styles.text}>{text}</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {UUID} from './uuid';
|
|
2
|
+
import {FloatingManager} from './floating-manager';
|
|
3
|
+
import {FloatingPositions, FloatingUIModes} from './floating-item-data';
|
|
4
|
+
import {FloatingItem} from './floating-item';
|
|
5
|
+
import {ToastProps} from './toast/toast';
|
|
6
|
+
import {ToastsContainer} from './toasts-container';
|
|
7
|
+
import {h} from 'preact';
|
|
8
|
+
|
|
9
|
+
export interface ToastManagerOptions {
|
|
10
|
+
floatingManager: FloatingManager;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export enum ToastSeverity {
|
|
14
|
+
Info = 'Info',
|
|
15
|
+
Success = 'Success',
|
|
16
|
+
Warn = 'Warn',
|
|
17
|
+
Error = 'Error'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ToastItemData {
|
|
21
|
+
title: string;
|
|
22
|
+
text: string;
|
|
23
|
+
icon: any;
|
|
24
|
+
severity: ToastSeverity;
|
|
25
|
+
duration: number;
|
|
26
|
+
onClick: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ManagedToasts {
|
|
30
|
+
timerSubscription: any;
|
|
31
|
+
duration: number;
|
|
32
|
+
toastProps: ToastProps;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class ToastManager {
|
|
36
|
+
private _options: ToastManagerOptions;
|
|
37
|
+
private _toasts: ManagedToasts[] = [];
|
|
38
|
+
private _floatingItem: FloatingItem | null = null;
|
|
39
|
+
|
|
40
|
+
constructor(private options: ToastManagerOptions) {
|
|
41
|
+
this._options = options;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
add(data: ToastItemData): void {
|
|
45
|
+
const {duration, ...props} = data;
|
|
46
|
+
if (!this._floatingItem) this._addToastsContainer();
|
|
47
|
+
const managedToast = {
|
|
48
|
+
toastProps: {
|
|
49
|
+
...props,
|
|
50
|
+
id: UUID.uuidV1(),
|
|
51
|
+
onClose: this._remove
|
|
52
|
+
},
|
|
53
|
+
duration: duration,
|
|
54
|
+
timerSubscription: null
|
|
55
|
+
};
|
|
56
|
+
this._toasts.push(managedToast);
|
|
57
|
+
this._updateToastsUI();
|
|
58
|
+
this._startDurationTimer(managedToast);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
reset(): void {
|
|
62
|
+
this._toasts.forEach(managedToast => {
|
|
63
|
+
this._remove(managedToast.toastProps.id);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private _startDurationTimer(managedToast: ManagedToasts): void {
|
|
68
|
+
managedToast.timerSubscription = setTimeout(() => {
|
|
69
|
+
this._remove(managedToast.toastProps.id);
|
|
70
|
+
}, managedToast.duration);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private _remove = (id: string): void => {
|
|
74
|
+
const index = this._findToastIndexById(id);
|
|
75
|
+
if (index === -1) return;
|
|
76
|
+
|
|
77
|
+
clearTimeout(this._toasts[index].timerSubscription);
|
|
78
|
+
this._toasts.splice(index, 1);
|
|
79
|
+
this._updateToastsUI();
|
|
80
|
+
if (this._toasts.length === 0) this._removeToastsContainer();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
private _addToastsContainer(): void {
|
|
84
|
+
this._floatingItem = this._options.floatingManager.add({
|
|
85
|
+
label: 'Toasts',
|
|
86
|
+
mode: FloatingUIModes.Immediate,
|
|
87
|
+
position: FloatingPositions.InteractiveArea,
|
|
88
|
+
renderContent: () => {
|
|
89
|
+
return (
|
|
90
|
+
<ToastsContainer
|
|
91
|
+
toasts={this._toasts.map(toast => {
|
|
92
|
+
return toast.toastProps;
|
|
93
|
+
})}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private _removeToastsContainer(): void {
|
|
101
|
+
if (!this._floatingItem) return;
|
|
102
|
+
|
|
103
|
+
this._options.floatingManager.remove(this._floatingItem);
|
|
104
|
+
this._floatingItem = null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private _updateToastsUI(): void {
|
|
108
|
+
if (this._floatingItem) this._floatingItem.update();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private _findToastIndexById(id: string): number {
|
|
112
|
+
let index = 0;
|
|
113
|
+
while (index < this._toasts.length) {
|
|
114
|
+
if (this._toasts[index].toastProps.id === id) {
|
|
115
|
+
return index;
|
|
116
|
+
}
|
|
117
|
+
index++;
|
|
118
|
+
}
|
|
119
|
+
return -1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.toastsContainer {
|
|
2
|
+
position: absolute;
|
|
3
|
+
right: 0;
|
|
4
|
+
top: 0;
|
|
5
|
+
padding: 8px 16px 0;
|
|
6
|
+
min-width: 120px;
|
|
7
|
+
max-width: 264px;
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.toastRow {
|
|
13
|
+
height: 42px;
|
|
14
|
+
min-width: 120px;
|
|
15
|
+
max-width: 264px;
|
|
16
|
+
margin-bottom: 8px;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
overflow-wrap: break-word;
|
|
19
|
+
text-overflow: ellipsis;
|
|
20
|
+
align-self: flex-end;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {ToastsContainer} from './toasts-container';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {Component, h} from 'preact';
|
|
2
|
+
import {Toast, ToastProps} from '../toast/toast';
|
|
3
|
+
import * as styles from './_toasts-container.scss';
|
|
4
|
+
|
|
5
|
+
export interface ToastsContainerProps {
|
|
6
|
+
toasts: ToastProps[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class ToastsContainer extends Component<ToastsContainerProps> {
|
|
10
|
+
render() {
|
|
11
|
+
return (
|
|
12
|
+
<div className={styles.toastsContainer}>
|
|
13
|
+
{this.props.toasts.map(toast => {
|
|
14
|
+
return (
|
|
15
|
+
<div className={styles.toastRow} key={toast.id}>
|
|
16
|
+
<Toast {...toast} />
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
})}
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ui-player-adapter';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {h, Component} from 'preact';
|
|
2
|
+
|
|
3
|
+
export interface UIPlayerAdapterProps {
|
|
4
|
+
player: KalturaPlayerTypes.Player;
|
|
5
|
+
onMount: (player: KalturaPlayerTypes.Player) => void;
|
|
6
|
+
onUnmount: (player: KalturaPlayerTypes.Player) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@KalturaPlayer.ui.components.withPlayer
|
|
10
|
+
export class UIPlayerAdapter extends Component<UIPlayerAdapterProps> {
|
|
11
|
+
static defaultProps = {
|
|
12
|
+
player: null,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
componentDidMount(): void {
|
|
16
|
+
|
|
17
|
+
this.props.onMount(this.props.player);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
componentWillUnmount(): void {
|
|
21
|
+
this.props.onUnmount(this.props.player);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
render(props: any) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/global.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/// <reference path="../node_modules/@playkit-js-contrib/common/global-types/index.d.ts" />
|
|
2
2
|
|
|
3
|
-
declare module
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
declare module '*.scss' {
|
|
4
|
+
const content: {[className: string]: string};
|
|
5
|
+
export = content;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
declare module
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
declare module '*.svg' {
|
|
9
|
+
const content: any;
|
|
10
|
+
export default content;
|
|
11
11
|
}
|