@playkit-js/moderation 3.0.0 → 3.1.0-canary.10-08b2d40
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 +15 -0
- package/README.md +60 -7
- package/dist/playkit-moderation.js +1 -1
- package/dist/playkit-moderation.js.map +1 -1
- package/package.json +9 -2
- package/src/components/moderation/moderation.scss +31 -83
- package/src/components/moderation/moderation.tsx +87 -97
- package/src/components/plugin-button/plugin-button.tsx +2 -2
- package/src/components/popover/popover.scss +27 -0
- package/src/components/popover/popover.tsx +75 -157
- package/src/moderation-plugin.tsx +23 -13
- package/src/components/plugin-button/plugin-button.scss +0 -14
- package/src/components/popover/popover-menu.scss +0 -4
- package/src/components/popover/popover-menu.tsx +0 -57
- package/src/components/popover-menu/index.ts +0 -1
- package/src/components/popover-menu/popover-menu.scss +0 -4
- package/src/components/popover-menu/popover-menu.tsx +0 -52
|
@@ -1,169 +1,84 @@
|
|
|
1
|
-
import {h, Component,
|
|
1
|
+
import {h, Component, VNode} from 'preact';
|
|
2
|
+
import {A11yWrapper, OnClickEvent} from '@playkit-js/common';
|
|
2
3
|
import * as styles from './popover.scss';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
Top = 'top',
|
|
6
|
-
Bottom = 'bottom',
|
|
7
|
-
}
|
|
8
|
-
export enum PopoverHorizontalPositions {
|
|
9
|
-
Left = 'left',
|
|
10
|
-
Right = 'right',
|
|
11
|
-
}
|
|
12
|
-
export enum PopoverTriggerMode {
|
|
13
|
-
Click = 'click',
|
|
14
|
-
Hover = 'hover',
|
|
15
|
-
}
|
|
5
|
+
const {ESC, TAB} = KalturaPlayer.ui.utils.KeyMap;
|
|
16
6
|
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Tab = 9,
|
|
21
|
-
Space = 32,
|
|
22
|
-
End = 35,
|
|
23
|
-
Home = 36,
|
|
7
|
+
export interface PopoverMenuItem {
|
|
8
|
+
label?: string;
|
|
9
|
+
onMenuChosen: () => void;
|
|
24
10
|
}
|
|
25
11
|
|
|
26
|
-
const CLOSE_ON_HOVER_DELAY = 500;
|
|
27
|
-
|
|
28
|
-
const defaultProps = {
|
|
29
|
-
verticalPosition: PopoverVerticalPositions.Top,
|
|
30
|
-
horizontalPosition: PopoverHorizontalPositions.Left,
|
|
31
|
-
triggerMode: PopoverTriggerMode.Click,
|
|
32
|
-
className: 'popover',
|
|
33
|
-
closeOnEsc: true,
|
|
34
|
-
closeOnClick: true,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
12
|
interface PopoverProps {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
closeOnClick: boolean;
|
|
41
|
-
closeOnEsc: boolean;
|
|
42
|
-
verticalPosition: PopoverVerticalPositions;
|
|
43
|
-
horizontalPosition: PopoverHorizontalPositions;
|
|
44
|
-
className: string;
|
|
45
|
-
triggerMode: PopoverTriggerMode;
|
|
46
|
-
content: ComponentChild;
|
|
47
|
-
children: ComponentChild;
|
|
13
|
+
options: Array<PopoverMenuItem>;
|
|
14
|
+
children: VNode;
|
|
48
15
|
}
|
|
49
16
|
|
|
50
17
|
interface PopoverState {
|
|
51
18
|
open: boolean;
|
|
52
19
|
}
|
|
53
20
|
|
|
54
|
-
/**
|
|
55
|
-
* Popover renders popup with a target.
|
|
56
|
-
* Properties description:
|
|
57
|
-
* onOpen - function that will be executed when popover opens;
|
|
58
|
-
* onClose - function that will be executed when popover closes;
|
|
59
|
-
* closeOnClick - close the popover on mouse click;
|
|
60
|
-
* verticalPosition - vertical position of popover relative to target ("top" or "bottom"), default - "top";
|
|
61
|
-
* horizontalPosition - horizontal position of popover relative to target ("left" or "right"), default - "left";
|
|
62
|
-
* !!! known limitation of popover positions: if popover opens beyond the visible area of the player - the popover will be overlapped by player
|
|
63
|
-
* className - popover class, can be use for popover styling, default - 'popover';
|
|
64
|
-
* closeOnEsc - handle ESC keyboard pressed event and close popover, default - true;
|
|
65
|
-
* triggerMode - popover support 2 ways for opening: click (keyPress) and mouse hover ("click" or "hover"), default - "click";
|
|
66
|
-
* content - content of popover. Can be any valid Preact node, ex:
|
|
67
|
-
* <select>
|
|
68
|
-
* <option>Option 1</option>
|
|
69
|
-
* ...
|
|
70
|
-
* <option>Option n</option>
|
|
71
|
-
* </select>
|
|
72
|
-
* children - popover target. Can be any valid Preact node, ex:
|
|
73
|
-
* <button>
|
|
74
|
-
* <i className="icon" />
|
|
75
|
-
* </button>
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
21
|
export class Popover extends Component<PopoverProps, PopoverState> {
|
|
79
|
-
private
|
|
80
|
-
private
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
};
|
|
22
|
+
private _controlElementRef: HTMLDivElement | null = null;
|
|
23
|
+
private _popoverElementRef: HTMLDivElement | null = null;
|
|
24
|
+
private _optionsRefMap: Map<number, HTMLDivElement | null> = new Map();
|
|
25
|
+
|
|
84
26
|
state = {
|
|
85
|
-
open: false
|
|
27
|
+
open: false
|
|
86
28
|
};
|
|
87
29
|
|
|
88
30
|
componentWillUnmount() {
|
|
89
31
|
this._removeListeners();
|
|
32
|
+
this._optionsRefMap = new Map();
|
|
90
33
|
}
|
|
91
34
|
|
|
92
|
-
private _clearTimeout = () => {
|
|
93
|
-
clearTimeout(this._closeTimeout);
|
|
94
|
-
this._closeTimeout = null;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
35
|
private _handleMouseEvent = (event: MouseEvent) => {
|
|
98
|
-
if (
|
|
99
|
-
// @ts-ignore
|
|
100
|
-
!this._controlElement.contains(event.target) &&
|
|
101
|
-
this.props.closeOnClick
|
|
102
|
-
) {
|
|
36
|
+
if (!this._controlElementRef?.contains(event.target as Node | null)) {
|
|
103
37
|
this._closePopover();
|
|
104
38
|
}
|
|
105
39
|
};
|
|
106
40
|
|
|
107
41
|
private _handleKeyboardEvent = (event: KeyboardEvent) => {
|
|
108
|
-
if (
|
|
109
|
-
// @ts-ignore
|
|
110
|
-
this._controlElement.contains(event.target) &&
|
|
111
|
-
event.keyCode === KeyboardKeys.Enter
|
|
112
|
-
) {
|
|
113
|
-
// handle Enter key pressed on Target icon to prevent triggering of _closePopover twice
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (
|
|
117
|
-
(this.props.closeOnEsc && event.keyCode === KeyboardKeys.Esc) ||
|
|
118
|
-
event.keyCode === KeyboardKeys.Enter
|
|
119
|
-
) {
|
|
120
|
-
// handle if ESC or Enter button presesd
|
|
42
|
+
if (event.keyCode === ESC || !this._popoverElementRef?.contains(event.target as Node | null)) {
|
|
121
43
|
this._closePopover();
|
|
122
44
|
}
|
|
123
45
|
};
|
|
124
46
|
|
|
125
|
-
private
|
|
126
|
-
|
|
127
|
-
|
|
47
|
+
private _getOptionRef = (index: number) => {
|
|
48
|
+
return this._optionsRefMap.get(index);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
private _setOptionRef = (index: number, ref: HTMLDivElement | null) => {
|
|
52
|
+
return this._optionsRefMap.set(index, ref);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
private _handleUpKeyPressed = (currentIndex: number) => () => {
|
|
56
|
+
this._getOptionRef(currentIndex - 1)?.focus();
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
private _handleDownKeyPressed = (currentIndex: number) => () => {
|
|
60
|
+
this._getOptionRef(currentIndex + 1)?.focus();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
private _openPopover = (byKeyboard?: boolean) => {
|
|
128
64
|
this.setState({open: true}, () => {
|
|
129
65
|
this._addListeners();
|
|
130
|
-
if (
|
|
131
|
-
|
|
66
|
+
if (byKeyboard) {
|
|
67
|
+
this._getOptionRef(0)?.focus();
|
|
132
68
|
}
|
|
133
69
|
});
|
|
134
70
|
};
|
|
135
71
|
|
|
136
72
|
private _closePopover = () => {
|
|
137
|
-
|
|
138
|
-
this.
|
|
139
|
-
this.setState({open: false}, () => {
|
|
140
|
-
this._removeListeners();
|
|
141
|
-
if (onClose) {
|
|
142
|
-
onClose();
|
|
143
|
-
}
|
|
144
|
-
});
|
|
73
|
+
this._removeListeners();
|
|
74
|
+
this.setState({open: false});
|
|
145
75
|
};
|
|
146
76
|
|
|
147
|
-
private _togglePopover = (e: MouseEvent | KeyboardEvent) => {
|
|
77
|
+
private _togglePopover = (e: MouseEvent | KeyboardEvent, byKeyboard?: boolean) => {
|
|
148
78
|
if (this.state.open) {
|
|
149
79
|
this._closePopover();
|
|
150
80
|
} else {
|
|
151
|
-
this._openPopover();
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
private _handleMouseEnter = () => {
|
|
155
|
-
if (!this.state.open) {
|
|
156
|
-
this._openPopover();
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
private _handleMouseLeave = () => {
|
|
160
|
-
this._closeTimeout = setTimeout(this._closePopover, CLOSE_ON_HOVER_DELAY);
|
|
161
|
-
};
|
|
162
|
-
private _handleHoverOnPopover = () => {
|
|
163
|
-
if (this.state.open && this._closeTimeout) {
|
|
164
|
-
this._clearTimeout();
|
|
165
|
-
} else {
|
|
166
|
-
this._closePopover();
|
|
81
|
+
this._openPopover(byKeyboard);
|
|
167
82
|
}
|
|
168
83
|
};
|
|
169
84
|
private _addListeners = () => {
|
|
@@ -174,48 +89,51 @@ export class Popover extends Component<PopoverProps, PopoverState> {
|
|
|
174
89
|
document.removeEventListener('click', this._handleMouseEvent);
|
|
175
90
|
document.removeEventListener('keydown', this._handleKeyboardEvent);
|
|
176
91
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
onMouseEnter: this._handleMouseEnter,
|
|
182
|
-
onMouseLeave: this._handleMouseLeave,
|
|
183
|
-
},
|
|
184
|
-
popoverEvents: {
|
|
185
|
-
onMouseEnter: this._handleHoverOnPopover,
|
|
186
|
-
onMouseLeave: this._handleHoverOnPopover,
|
|
187
|
-
},
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
return {targetEvents: {onClick: this._togglePopover}, popoverEvents: {}};
|
|
92
|
+
|
|
93
|
+
private _handleClickOnOption = (cb: (byKeyboard?: boolean) => void) => (event: OnClickEvent, byKeyboard?: boolean) => {
|
|
94
|
+
this._closePopover();
|
|
95
|
+
cb(byKeyboard);
|
|
191
96
|
};
|
|
97
|
+
|
|
192
98
|
render(props: PopoverProps) {
|
|
193
|
-
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
const {targetEvents, popoverEvents} = this._getHoverEvents();
|
|
99
|
+
const {open} = this.state;
|
|
197
100
|
return (
|
|
198
101
|
<div className={styles.popoverContainer}>
|
|
199
102
|
<div
|
|
200
103
|
className="popover-anchor-container"
|
|
201
104
|
ref={node => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}}
|
|
205
|
-
{...targetEvents}>
|
|
206
|
-
{props.children}
|
|
105
|
+
this._controlElementRef = node;
|
|
106
|
+
}}>
|
|
107
|
+
<A11yWrapper onClick={this._togglePopover}>{props.children}</A11yWrapper>;
|
|
207
108
|
</div>
|
|
208
|
-
{
|
|
109
|
+
{open && (
|
|
209
110
|
<div
|
|
210
|
-
aria-expanded=
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
111
|
+
aria-expanded={open}
|
|
112
|
+
ref={node => {
|
|
113
|
+
this._popoverElementRef = node;
|
|
114
|
+
}}
|
|
115
|
+
className={[styles.reportPopover, styles.popoverComponent, styles.bottom, styles.right].join(' ')}>
|
|
116
|
+
<div role="menu" className={styles.popoverMenu}>
|
|
117
|
+
{props.options.map((el, index) => {
|
|
118
|
+
return (
|
|
119
|
+
<A11yWrapper
|
|
120
|
+
onClick={this._handleClickOnOption(el.onMenuChosen)}
|
|
121
|
+
onDownKeyPressed={this._handleDownKeyPressed(index)}
|
|
122
|
+
onUpKeyPressed={this._handleUpKeyPressed(index)}>
|
|
123
|
+
<div
|
|
124
|
+
tabIndex={0}
|
|
125
|
+
role="menuitem"
|
|
126
|
+
aria-label={el.label}
|
|
127
|
+
className={styles.popoverMenuItem}
|
|
128
|
+
ref={node => {
|
|
129
|
+
this._setOptionRef(index, node);
|
|
130
|
+
}}>
|
|
131
|
+
{el.label}
|
|
132
|
+
</div>
|
|
133
|
+
</A11yWrapper>
|
|
134
|
+
);
|
|
135
|
+
})}
|
|
136
|
+
</div>
|
|
219
137
|
</div>
|
|
220
138
|
)}
|
|
221
139
|
</div>
|
|
@@ -3,7 +3,9 @@ import {Moderation, ModerateOption} from './components/moderation';
|
|
|
3
3
|
import {PluginButton} from './components/plugin-button';
|
|
4
4
|
import * as styles from './moderation-plugin.scss';
|
|
5
5
|
import {ui} from 'kaltura-player-js';
|
|
6
|
+
import {icons} from './components/icons';
|
|
6
7
|
import {ContribServices, ToastSeverity, OnClickEvent} from '@playkit-js/common';
|
|
8
|
+
import {UpperBarManager} from '@playkit-js/ui-managers';
|
|
7
9
|
import {ReportLoader, KalturaModerationFlag} from './providers';
|
|
8
10
|
import {ErrorIcon} from './components/icons/error-icon';
|
|
9
11
|
import {SuccessIcon} from './components/icons/success-icon';
|
|
@@ -38,7 +40,7 @@ export class ModerationPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
38
40
|
private _moderationOverlay = null;
|
|
39
41
|
private _wasPlayed = false; // keep state of the player so we can resume if needed
|
|
40
42
|
private _removeActiveOverlay: null | Function = null;
|
|
41
|
-
private
|
|
43
|
+
private _pluginIcon = -1;
|
|
42
44
|
private _contribServices: ContribServices;
|
|
43
45
|
|
|
44
46
|
constructor(name: string, private _player: KalturaPlayerTypes.Player, config: ModerationPluginConfig) {
|
|
@@ -46,10 +48,15 @@ export class ModerationPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
46
48
|
this._contribServices = ContribServices.get({kalturaPlayer: _player});
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
get upperBarManager() {
|
|
52
|
+
return this.player.getService('upperBarManager') as UpperBarManager | undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
loadMedia(): void {
|
|
50
|
-
this.
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
if (!this.upperBarManager) {
|
|
57
|
+
this.logger.warn('upperBarManager service not registered');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
53
60
|
this._addPluginIcon();
|
|
54
61
|
}
|
|
55
62
|
|
|
@@ -177,14 +184,16 @@ export class ModerationPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
177
184
|
|
|
178
185
|
private _addPluginIcon(): void {
|
|
179
186
|
const {tooltipMessage} = this.config;
|
|
180
|
-
if (this.
|
|
187
|
+
if (this._pluginIcon > 0) {
|
|
181
188
|
return;
|
|
182
189
|
}
|
|
183
|
-
this.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
190
|
+
this.player.ready().then(() => {
|
|
191
|
+
this._pluginIcon = this.upperBarManager!.add({
|
|
192
|
+
label: 'Moderation',
|
|
193
|
+
component: () => <PluginButton onClick={this._toggleOverlay} label={tooltipMessage} />,
|
|
194
|
+
svgIcon: {path: icons.PLUGIN_ICON, viewBox: `0 0 ${icons.BigSize} ${icons.BigSize}`},
|
|
195
|
+
onClick: this._toggleOverlay
|
|
196
|
+
}) as number;
|
|
188
197
|
});
|
|
189
198
|
}
|
|
190
199
|
|
|
@@ -200,13 +209,14 @@ export class ModerationPlugin extends KalturaPlayer.core.BasePlugin {
|
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
reset(): void {
|
|
212
|
+
this._removeOverlay();
|
|
203
213
|
this._contribServices.reset();
|
|
204
214
|
}
|
|
205
215
|
|
|
206
216
|
destroy(): void {
|
|
207
|
-
this.
|
|
208
|
-
|
|
209
|
-
this.
|
|
217
|
+
if (this._pluginIcon > 0) {
|
|
218
|
+
this.upperBarManager!.remove(this._pluginIcon);
|
|
219
|
+
this._pluginIcon = -1;
|
|
210
220
|
}
|
|
211
221
|
}
|
|
212
222
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
.pluginButton {
|
|
2
|
-
display: flex;
|
|
3
|
-
width: 36px;
|
|
4
|
-
height: 36px;
|
|
5
|
-
padding: 0;
|
|
6
|
-
background: transparent;
|
|
7
|
-
border: none;
|
|
8
|
-
border-radius: 4px;
|
|
9
|
-
cursor: pointer;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
:global(.playkit-player .playkit-top-bar .playkit-right-controls) {
|
|
13
|
-
display: flex;
|
|
14
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {h, Component, ComponentChild} from 'preact';
|
|
2
|
-
import * as styles from './popover-menu.scss';
|
|
3
|
-
|
|
4
|
-
export interface PopoverMenuItem {
|
|
5
|
-
label?: string;
|
|
6
|
-
onMenuChosen?: Function;
|
|
7
|
-
customRenderer?: (el: PopoverMenuItem) => ComponentChild;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface PopoverMenuProps {
|
|
11
|
-
options: Array<PopoverMenuItem>;
|
|
12
|
-
itemRenderer?: (el: PopoverMenuItem) => ComponentChild;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Popover menu renders list of options.
|
|
17
|
-
* options example:
|
|
18
|
-
* [
|
|
19
|
-
* {label: 'option_1', onMenuChosen: () => console.log('selected first')},
|
|
20
|
-
* {label: 'option_2', onMenuChosen: () => console.log('selected second')}
|
|
21
|
-
* ]
|
|
22
|
-
* In case when 'itemRenderer' properdy hasn't provided - PopoverMenu renders
|
|
23
|
-
* div with class "popover-menu-item" that contain label for the current option.
|
|
24
|
-
* Default render of options can be changed by providing 'itemRenderer' - it should be
|
|
25
|
-
* function that takes current option and returns valid 'preact' node.
|
|
26
|
-
* If some option need to be rendered with a different method - specific render
|
|
27
|
-
* method can be provided with 'customRenderer' property for the current option.
|
|
28
|
-
* option example with specific render method:
|
|
29
|
-
* { label: 'specific render', onMenuChosen: () => {}, customRenderer: el => (<span>{el.label}</span>)}
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
export class PopoverMenu extends Component<PopoverMenuProps> {
|
|
33
|
-
render(props: any) {
|
|
34
|
-
return (
|
|
35
|
-
<div className={styles.popoverMenu}>
|
|
36
|
-
{props.options.map((el: PopoverMenuItem) => {
|
|
37
|
-
if (el.customRenderer) {
|
|
38
|
-
return el.customRenderer(el);
|
|
39
|
-
}
|
|
40
|
-
if (props.itemRenderer) {
|
|
41
|
-
return props.itemRenderer(el);
|
|
42
|
-
}
|
|
43
|
-
return (
|
|
44
|
-
<div
|
|
45
|
-
className="popover-menu-item"
|
|
46
|
-
onClick={() => {
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
el.onMenuChosen(el)
|
|
49
|
-
}}>
|
|
50
|
-
{el.label}
|
|
51
|
-
</div>
|
|
52
|
-
);
|
|
53
|
-
})}
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './popover-menu';
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { h, Component, ComponentChild } from "preact";
|
|
2
|
-
import * as styles from "./popover-menu.scss";
|
|
3
|
-
|
|
4
|
-
export interface PopoverMenuItem {
|
|
5
|
-
label: string;
|
|
6
|
-
onMenuChosen: Function;
|
|
7
|
-
customRenderer?: (el: PopoverMenuItem) => ComponentChild;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface PopoverMenuProps {
|
|
11
|
-
options: Array<PopoverMenuItem>;
|
|
12
|
-
itemRenderer?: (el: PopoverMenuItem) => ComponentChild;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Popover menu renders list of options.
|
|
17
|
-
* options example:
|
|
18
|
-
* [
|
|
19
|
-
* {label: 'option_1', onMenuChosen: () => console.log('selected first')},
|
|
20
|
-
* {label: 'option_2', onMenuChosen: () => console.log('selected second')}
|
|
21
|
-
* ]
|
|
22
|
-
* In case when 'itemRenderer' properdy hasn't provided - PopoverMenu renders
|
|
23
|
-
* div with class "popover-menu-item" that contain label for the current option.
|
|
24
|
-
* Default render of options can be changed by providing 'itemRenderer' - it should be
|
|
25
|
-
* function that takes current option and returns valid 'preact' node.
|
|
26
|
-
* If some option need to be rendered with a different method - specific render
|
|
27
|
-
* method can be provided with 'customRenderer' property for the current option.
|
|
28
|
-
* option example with specific render method:
|
|
29
|
-
* { label: 'specific render', onMenuChosen: () => {}, customRenderer: el => (<span>{el.label}</span>)}
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
export class PopoverMenu extends Component<PopoverMenuProps> {
|
|
33
|
-
render(props: PopoverMenuProps) {
|
|
34
|
-
return (
|
|
35
|
-
<div className={styles.popoverMenu}>
|
|
36
|
-
{props.options.map((el: PopoverMenuItem) => {
|
|
37
|
-
if (el.customRenderer) {
|
|
38
|
-
return el.customRenderer(el);
|
|
39
|
-
}
|
|
40
|
-
if (props.itemRenderer) {
|
|
41
|
-
return props.itemRenderer(el);
|
|
42
|
-
}
|
|
43
|
-
return (
|
|
44
|
-
<div className="popover-menu-item" onClick={() => el.onMenuChosen(el)}>
|
|
45
|
-
{el.label}
|
|
46
|
-
</div>
|
|
47
|
-
);
|
|
48
|
-
})}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
}
|