@playkit-js/playkit-js-ui 0.83.9 → 0.83.10
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.
|
@@ -1,336 +1,352 @@
|
|
|
1
|
-
import style from '../../styles/style.scss';
|
|
2
|
-
import {h, Component, toChildArray, cloneElement, VNode} from 'preact';
|
|
3
|
-
import {connect} from 'react-redux';
|
|
4
|
-
import {withEventManager} from '../../event';
|
|
5
|
-
import {WithEventManagerProps} from '../../event/with-event-manager';
|
|
6
|
-
import {KeyMap} from '../../utils/key-map';
|
|
7
|
-
|
|
8
|
-
interface ReduxStateProps {
|
|
9
|
-
playerClientRect?: DOMRect;
|
|
10
|
-
guiClientRect?: DOMRect;
|
|
11
|
-
isMobile?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
type ToolTipPosition = 'top' | 'bottom' | 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'left' | 'right';
|
|
15
|
-
|
|
16
|
-
interface TooltipOwnProps {
|
|
17
|
-
type?: ToolTipPosition;
|
|
18
|
-
maxWidth?: string;
|
|
19
|
-
label: string;
|
|
20
|
-
strictPosition?: boolean;
|
|
21
|
-
className?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type TooltipProps = ReduxStateProps & TooltipOwnProps;
|
|
25
|
-
|
|
26
|
-
const PLAYER_MARGIN = 5;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* mapping state to props
|
|
30
|
-
* @param {*} state - redux store state
|
|
31
|
-
* @returns {Object} - mapped state to this component
|
|
32
|
-
*/
|
|
33
|
-
const mapStateToProps = state => ({
|
|
34
|
-
playerClientRect: state.shell.playerClientRect,
|
|
35
|
-
guiClientRect: state.shell.guiClientRect,
|
|
36
|
-
isMobile: state.shell.isMobile
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const TOOLTIP_SHOW_TIMEOUT: number = 750;
|
|
40
|
-
|
|
41
|
-
// notice the order represents the order of the alternative fallback
|
|
42
|
-
const ToolTipType: {[type: string]: ToolTipPosition} = {
|
|
43
|
-
Top: 'top',
|
|
44
|
-
Bottom: 'bottom',
|
|
45
|
-
TopRight: 'top-right',
|
|
46
|
-
TopLeft: 'top-left',
|
|
47
|
-
BottomRight: 'bottom-right',
|
|
48
|
-
BottomLeft: 'bottom-left',
|
|
49
|
-
Left: 'left',
|
|
50
|
-
Right: 'right'
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Tooltip component
|
|
55
|
-
*
|
|
56
|
-
* @class Tooltip
|
|
57
|
-
* @example <Tooltip>...</Tooltip>
|
|
58
|
-
* @extends {Component}
|
|
59
|
-
*/
|
|
60
|
-
@connect(mapStateToProps)
|
|
61
|
-
@withEventManager
|
|
62
|
-
class Tooltip extends Component<TooltipProps & WithEventManagerProps, any> {
|
|
63
|
-
_hoverTimeout: number | null = null;
|
|
64
|
-
textElement!: HTMLSpanElement;
|
|
65
|
-
tooltipElement!: HTMLDivElement;
|
|
66
|
-
lastAlternativeTypeIndex: number = -1;
|
|
67
|
-
_buttonRef: HTMLButtonElement | null = null;
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* default component props
|
|
71
|
-
* @type {Object}
|
|
72
|
-
* @memberof Tooltip
|
|
73
|
-
*/
|
|
74
|
-
static defaultProps = {
|
|
75
|
-
type: ToolTipType.Top,
|
|
76
|
-
maxWidth: '240px',
|
|
77
|
-
strictPosition: false
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* clear hover timeout
|
|
82
|
-
*
|
|
83
|
-
* @returns {void}
|
|
84
|
-
* @memberof Tooltip
|
|
85
|
-
*/
|
|
86
|
-
_clearHoverTimeout(): void {
|
|
87
|
-
if (this._hoverTimeout) {
|
|
88
|
-
clearTimeout(this._hoverTimeout);
|
|
89
|
-
this._hoverTimeout = null;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* displays tooltip.
|
|
95
|
-
* @memberof Tooltip
|
|
96
|
-
* @returns {void}
|
|
97
|
-
*/
|
|
98
|
-
showTooltip = (): void => {
|
|
99
|
-
this.setState({showTooltip: true});
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* hide tooltip.
|
|
104
|
-
* @memberof Tooltip
|
|
105
|
-
* @returns {void}
|
|
106
|
-
*/
|
|
107
|
-
hideTooltip = (): void => {
|
|
108
|
-
this.setState({showTooltip: false});
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* handle keyDown
|
|
113
|
-
* @memberof Tooltip
|
|
114
|
-
* @returns {void}
|
|
115
|
-
*/
|
|
116
|
-
handleKeyDown = (event: KeyboardEvent): void => {
|
|
117
|
-
if (event.keyCode === KeyMap.ESC) {
|
|
118
|
-
this.hideTooltip();
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* set button ref
|
|
124
|
-
* @memberof Tooltip
|
|
125
|
-
* @returns {void}
|
|
126
|
-
*/
|
|
127
|
-
setButtonRef = (element: HTMLButtonElement | null) => {
|
|
128
|
-
this._buttonRef = element;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* handle focus on wrapped element
|
|
133
|
-
* @memberof Tooltip
|
|
134
|
-
* @returns {void}
|
|
135
|
-
*/
|
|
136
|
-
handleFocusOnChildren = (): void => {
|
|
137
|
-
const {onFocus} = (this.props.children as VNode<any>).props;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
*
|
|
198
|
-
* @memberof Tooltip
|
|
199
|
-
* @returns {string}
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* @
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
} else if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
1
|
+
import style from '../../styles/style.scss';
|
|
2
|
+
import {h, Component, toChildArray, cloneElement, VNode} from 'preact';
|
|
3
|
+
import {connect} from 'react-redux';
|
|
4
|
+
import {withEventManager} from '../../event';
|
|
5
|
+
import {WithEventManagerProps} from '../../event/with-event-manager';
|
|
6
|
+
import {KeyMap} from '../../utils/key-map';
|
|
7
|
+
|
|
8
|
+
interface ReduxStateProps {
|
|
9
|
+
playerClientRect?: DOMRect;
|
|
10
|
+
guiClientRect?: DOMRect;
|
|
11
|
+
isMobile?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type ToolTipPosition = 'top' | 'bottom' | 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'left' | 'right';
|
|
15
|
+
|
|
16
|
+
interface TooltipOwnProps {
|
|
17
|
+
type?: ToolTipPosition;
|
|
18
|
+
maxWidth?: string;
|
|
19
|
+
label: string;
|
|
20
|
+
strictPosition?: boolean;
|
|
21
|
+
className?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type TooltipProps = ReduxStateProps & TooltipOwnProps;
|
|
25
|
+
|
|
26
|
+
const PLAYER_MARGIN = 5;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* mapping state to props
|
|
30
|
+
* @param {*} state - redux store state
|
|
31
|
+
* @returns {Object} - mapped state to this component
|
|
32
|
+
*/
|
|
33
|
+
const mapStateToProps = state => ({
|
|
34
|
+
playerClientRect: state.shell.playerClientRect,
|
|
35
|
+
guiClientRect: state.shell.guiClientRect,
|
|
36
|
+
isMobile: state.shell.isMobile
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const TOOLTIP_SHOW_TIMEOUT: number = 750;
|
|
40
|
+
|
|
41
|
+
// notice the order represents the order of the alternative fallback
|
|
42
|
+
const ToolTipType: {[type: string]: ToolTipPosition} = {
|
|
43
|
+
Top: 'top',
|
|
44
|
+
Bottom: 'bottom',
|
|
45
|
+
TopRight: 'top-right',
|
|
46
|
+
TopLeft: 'top-left',
|
|
47
|
+
BottomRight: 'bottom-right',
|
|
48
|
+
BottomLeft: 'bottom-left',
|
|
49
|
+
Left: 'left',
|
|
50
|
+
Right: 'right'
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Tooltip component
|
|
55
|
+
*
|
|
56
|
+
* @class Tooltip
|
|
57
|
+
* @example <Tooltip>...</Tooltip>
|
|
58
|
+
* @extends {Component}
|
|
59
|
+
*/
|
|
60
|
+
@connect(mapStateToProps)
|
|
61
|
+
@withEventManager
|
|
62
|
+
class Tooltip extends Component<TooltipProps & WithEventManagerProps, any> {
|
|
63
|
+
_hoverTimeout: number | null = null;
|
|
64
|
+
textElement!: HTMLSpanElement;
|
|
65
|
+
tooltipElement!: HTMLDivElement;
|
|
66
|
+
lastAlternativeTypeIndex: number = -1;
|
|
67
|
+
_buttonRef: HTMLButtonElement | null = null;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* default component props
|
|
71
|
+
* @type {Object}
|
|
72
|
+
* @memberof Tooltip
|
|
73
|
+
*/
|
|
74
|
+
static defaultProps = {
|
|
75
|
+
type: ToolTipType.Top,
|
|
76
|
+
maxWidth: '240px',
|
|
77
|
+
strictPosition: false
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* clear hover timeout
|
|
82
|
+
*
|
|
83
|
+
* @returns {void}
|
|
84
|
+
* @memberof Tooltip
|
|
85
|
+
*/
|
|
86
|
+
_clearHoverTimeout(): void {
|
|
87
|
+
if (this._hoverTimeout) {
|
|
88
|
+
clearTimeout(this._hoverTimeout);
|
|
89
|
+
this._hoverTimeout = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* displays tooltip.
|
|
95
|
+
* @memberof Tooltip
|
|
96
|
+
* @returns {void}
|
|
97
|
+
*/
|
|
98
|
+
showTooltip = (): void => {
|
|
99
|
+
this.setState({showTooltip: true});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* hide tooltip.
|
|
104
|
+
* @memberof Tooltip
|
|
105
|
+
* @returns {void}
|
|
106
|
+
*/
|
|
107
|
+
hideTooltip = (): void => {
|
|
108
|
+
this.setState({showTooltip: false});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* handle keyDown
|
|
113
|
+
* @memberof Tooltip
|
|
114
|
+
* @returns {void}
|
|
115
|
+
*/
|
|
116
|
+
handleKeyDown = (event: KeyboardEvent): void => {
|
|
117
|
+
if (event.keyCode === KeyMap.ESC) {
|
|
118
|
+
this.hideTooltip();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* set button ref
|
|
124
|
+
* @memberof Tooltip
|
|
125
|
+
* @returns {void}
|
|
126
|
+
*/
|
|
127
|
+
setButtonRef = (element: HTMLButtonElement | null) => {
|
|
128
|
+
this._buttonRef = element;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* handle focus on wrapped element
|
|
133
|
+
* @memberof Tooltip
|
|
134
|
+
* @returns {void}
|
|
135
|
+
*/
|
|
136
|
+
handleFocusOnChildren = (event: Event): void => {
|
|
137
|
+
const {onFocus} = (this.props.children as VNode<any>).props;
|
|
138
|
+
// SUP-52316: The A11y HOC (popup-keyboard-accessibility) sets a data attribute on the trigger
|
|
139
|
+
// element synchronously in componentWillUnmount, before the focusElement() setInterval fires.
|
|
140
|
+
// By the time the interval calls .focus() (~100ms later), the settings panel is already unmounted
|
|
141
|
+
// so relatedTarget is document.body — the closest() guard on relatedTarget cannot work.
|
|
142
|
+
// Instead, we consume the data attribute flag here: if it is present, this focus event is a
|
|
143
|
+
// programmatic focus-restore, not a deliberate user navigation, so we skip showing the tooltip.
|
|
144
|
+
const target = event.target as HTMLElement | null;
|
|
145
|
+
if (!target) {
|
|
146
|
+
if (onFocus) onFocus(event);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (target?.dataset?.kalturaFocusRestore) {
|
|
150
|
+
delete target.dataset.kalturaFocusRestore;
|
|
151
|
+
if (onFocus) onFocus(event);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
this.showTooltip();
|
|
155
|
+
if (onFocus) {
|
|
156
|
+
onFocus(event);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* handle blur on wrapped element
|
|
162
|
+
* @memberof Tooltip
|
|
163
|
+
* @returns {void}
|
|
164
|
+
*/
|
|
165
|
+
handleBlurOnChildren = (): void => {
|
|
166
|
+
const {onBlur} = (this.props.children as VNode<any>).props;
|
|
167
|
+
this.hideTooltip();
|
|
168
|
+
if (onBlur) {
|
|
169
|
+
onBlur();
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* on mouse over handler.
|
|
175
|
+
* @memberof Tooltip
|
|
176
|
+
* @returns {void}
|
|
177
|
+
*/
|
|
178
|
+
onMouseOver = (): void => {
|
|
179
|
+
this._clearHoverTimeout();
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
this._hoverTimeout = setTimeout(() => {
|
|
182
|
+
this.showTooltip();
|
|
183
|
+
}, TOOLTIP_SHOW_TIMEOUT);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* on mouse leave handler.
|
|
188
|
+
* @memberof Tooltip
|
|
189
|
+
* @returns {void}
|
|
190
|
+
*/
|
|
191
|
+
onMouseLeave = (): void => {
|
|
192
|
+
this.hideTooltip();
|
|
193
|
+
this._clearHoverTimeout();
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* brings another tooltip type which hasn't been marked as invalid
|
|
198
|
+
* @memberof Tooltip
|
|
199
|
+
* @returns {string} tooltip type
|
|
200
|
+
*/
|
|
201
|
+
getAlternateType(): string | undefined {
|
|
202
|
+
return Object.values<string>(ToolTipType).find((item, index) => {
|
|
203
|
+
if (index > this.lastAlternativeTypeIndex && item != this.props.type) {
|
|
204
|
+
this.lastAlternativeTypeIndex = index;
|
|
205
|
+
return true;
|
|
206
|
+
} else {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* checks if the current tooltip type is within the player boundaries
|
|
214
|
+
* @memberof Tooltip
|
|
215
|
+
* @returns {string} is in boundaries
|
|
216
|
+
*/
|
|
217
|
+
isToolTipInBoundaries(): boolean {
|
|
218
|
+
if (this.props.strictPosition) {
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
const tooltipBoundingRect = this.textElement.getBoundingClientRect();
|
|
222
|
+
const playerContainerRect = this.props.playerClientRect;
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
tooltipBoundingRect.top > playerContainerRect!.top + PLAYER_MARGIN &&
|
|
226
|
+
tooltipBoundingRect.bottom < playerContainerRect!.bottom - PLAYER_MARGIN &&
|
|
227
|
+
tooltipBoundingRect.right < playerContainerRect!.right - PLAYER_MARGIN &&
|
|
228
|
+
tooltipBoundingRect.left > playerContainerRect!.left + PLAYER_MARGIN
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* sets the requested type prop of the tooltip as a state cause it can change if is not valid
|
|
234
|
+
* @memberof Tooltip
|
|
235
|
+
* @returns {void}
|
|
236
|
+
*/
|
|
237
|
+
componentWillMount(): void {
|
|
238
|
+
this.setState({valid: false, type: this.props.type});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* after component mounted, set event listener to click outside the component
|
|
243
|
+
*
|
|
244
|
+
* @returns {void}
|
|
245
|
+
* @memberof Tooltip
|
|
246
|
+
*/
|
|
247
|
+
componentDidMount() {
|
|
248
|
+
const {eventManager} = this.props;
|
|
249
|
+
eventManager!.listen(document, 'click', e => this.handleClickOutside(e));
|
|
250
|
+
if (this._buttonRef?.addEventListener) {
|
|
251
|
+
eventManager!.listen(this._buttonRef, 'keydown', this.handleKeyDown);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* event listener for clicking outside handler.
|
|
257
|
+
*
|
|
258
|
+
* @param {*} e - click event
|
|
259
|
+
* @returns {void}
|
|
260
|
+
* @memberof Tooltip
|
|
261
|
+
*/
|
|
262
|
+
handleClickOutside(e: any) {
|
|
263
|
+
if (!this.tooltipElement?.contains(e.target) && this.state.showTooltip) {
|
|
264
|
+
this.hideTooltip();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
handleRef = (el: HTMLButtonElement | null) => {
|
|
269
|
+
this.setButtonRef(el);
|
|
270
|
+
|
|
271
|
+
// Forward the child’s original ref (callback or ref object)
|
|
272
|
+
// so Tooltip keeps its own ref without breaking the child’s.
|
|
273
|
+
const { ref } = (this.props.children as VNode<any>);
|
|
274
|
+
if (typeof ref === 'function') {
|
|
275
|
+
ref(el);
|
|
276
|
+
} else if (ref && typeof ref === 'object') {
|
|
277
|
+
(ref as any).current = el;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* checks if after the render the tooltip is within boundaries of the player
|
|
283
|
+
* if not it will try to set a new type which will be checked after the next render
|
|
284
|
+
* @param {Object} prevProps - previous component props
|
|
285
|
+
* @memberof Tooltip
|
|
286
|
+
* @returns {void}
|
|
287
|
+
*/
|
|
288
|
+
componentDidUpdate(prevProps: any): void {
|
|
289
|
+
if (this.props.guiClientRect !== prevProps.guiClientRect) {
|
|
290
|
+
this.lastAlternativeTypeIndex = -1;
|
|
291
|
+
this.setState({valid: false, type: this.props.type});
|
|
292
|
+
} else if (this.state.showTooltip) {
|
|
293
|
+
if (this.isToolTipInBoundaries()) {
|
|
294
|
+
if (!this.state.valid) {
|
|
295
|
+
this.setState({valid: true});
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
const alternative = this.getAlternateType();
|
|
299
|
+
if (alternative) {
|
|
300
|
+
this.setState({valid: false, type: alternative});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* after component unmount, clear timeouts
|
|
308
|
+
*
|
|
309
|
+
* @returns {void}
|
|
310
|
+
* @memberof Tooltip
|
|
311
|
+
*/
|
|
312
|
+
componentWillUnmount(): void {
|
|
313
|
+
this._clearHoverTimeout();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* render component
|
|
318
|
+
*
|
|
319
|
+
* @param {*} props - component props
|
|
320
|
+
* @returns {React$Element} - component element
|
|
321
|
+
* @memberof Tooltip
|
|
322
|
+
*/
|
|
323
|
+
render(props: any): VNode<any> {
|
|
324
|
+
const className = [style.tooltipLabel, style[`tooltip-${this.state.type}`]];
|
|
325
|
+
if (props.className) {
|
|
326
|
+
className.push(props.className);
|
|
327
|
+
}
|
|
328
|
+
this.state.showTooltip && this.state.valid ? className.push(style.show) : className.push(style.hide);
|
|
329
|
+
if (props.isMobile) {
|
|
330
|
+
return toChildArray(props.children)[0] as VNode<any>;
|
|
331
|
+
}
|
|
332
|
+
const children = cloneElement(props.children, {
|
|
333
|
+
onFocus: this.handleFocusOnChildren,
|
|
334
|
+
onBlur: this.handleBlurOnChildren,
|
|
335
|
+
ref: this.handleRef
|
|
336
|
+
});
|
|
337
|
+
return (
|
|
338
|
+
<div
|
|
339
|
+
className={style.tooltip}
|
|
340
|
+
onMouseOver={this.onMouseOver}
|
|
341
|
+
onMouseLeave={this.onMouseLeave}
|
|
342
|
+
ref={el => (el ? (this.tooltipElement = el) : undefined)}>
|
|
343
|
+
{children}
|
|
344
|
+
<span aria-hidden="true" style={{maxWidth: props.maxWidth}} ref={el => (el ? (this.textElement = el) : undefined)} className={className.join(' ')}>
|
|
345
|
+
{props.label}
|
|
346
|
+
</span>
|
|
347
|
+
</div>
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export {Tooltip, ToolTipType};
|