@playkit-js/transcript 3.0.1-canary.44-4c445bb → 3.0.1-canary.46-b1e939d
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 +1 -1
- package/dist/playkit-transcript.js +1 -1
- package/dist/playkit-transcript.js.map +1 -1
- package/package.json +2 -2
- package/src/components/caption/caption.tsx +24 -20
- package/src/components/caption-list/captionList.tsx +5 -5
- package/src/components/close-button/index.tsx +3 -9
- package/src/components/download-print-menu/download-print-menu.scss +16 -0
- package/src/components/download-print-menu/download-print-menu.tsx +84 -48
- package/src/components/plugin-button/plugin-button.tsx +2 -10
- package/src/components/popover-menu/index.ts +1 -0
- package/src/components/popover-menu/popover-menu.scss +6 -0
- package/src/components/popover-menu/popover-menu.tsx +52 -0
- package/src/components/search/search.tsx +57 -93
- package/src/components/transcript/transcript.tsx +7 -22
- package/src/transcript-plugin.tsx +31 -18
- package/src/utils/index.ts +1 -0
- package/src/utils/popover/popover.scss +30 -0
- package/src/utils/popover/popover.tsx +178 -0
- package/src/components/popover/index.ts +0 -1
- package/src/components/popover/popover.scss +0 -43
- package/src/components/popover/popover.tsx +0 -142
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playkit-js/transcript",
|
|
3
|
-
"version": "3.0.1-canary.
|
|
3
|
+
"version": "3.0.1-canary.46-b1e939d",
|
|
4
4
|
"main": "dist/playkit-transcript.js",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"private": false,
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"html5 player"
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@playkit-js/common": "^1.0.
|
|
78
|
+
"@playkit-js/common": "^1.0.2",
|
|
79
79
|
"stream-browserify": "^3.0.0"
|
|
80
80
|
},
|
|
81
81
|
"kaltura": {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {A11yWrapper, OnClickEvent} from '@playkit-js/common';
|
|
1
|
+
import * as styles from './caption.scss';
|
|
3
2
|
import {secontsToTime} from '../../utils';
|
|
4
3
|
import {CuePointData} from '../../types';
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
const {ENTER, Space} = KalturaPlayer.ui.utils.KeyMap;
|
|
6
|
+
|
|
7
|
+
import {Component, h} from 'preact';
|
|
6
8
|
|
|
7
9
|
export interface CaptionProps {
|
|
8
10
|
showTime: boolean;
|
|
@@ -55,10 +57,12 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
55
57
|
return false;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
private
|
|
59
|
-
|
|
60
|
+
private _handleKeyPress = (event: KeyboardEvent) => {
|
|
61
|
+
const keyCode = event.which || event.keyCode;
|
|
62
|
+
if (keyCode === ENTER || keyCode === Space) {
|
|
60
63
|
event.preventDefault();
|
|
61
64
|
this._gotoCurrentTime();
|
|
65
|
+
return;
|
|
62
66
|
}
|
|
63
67
|
};
|
|
64
68
|
|
|
@@ -113,23 +117,23 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
113
117
|
const isHighlighted = Object.keys(highlighted)[0] === id;
|
|
114
118
|
|
|
115
119
|
return (
|
|
116
|
-
<
|
|
120
|
+
<div
|
|
121
|
+
className={styles.caption}
|
|
122
|
+
tabIndex={1}
|
|
123
|
+
ref={node => {
|
|
124
|
+
this._hotspotRef = node;
|
|
125
|
+
}}
|
|
126
|
+
onKeyDown={this._handleKeyPress}
|
|
127
|
+
>
|
|
128
|
+
{showTime && <div className={styles.captionTime}>{secontsToTime(startTime, longerThanHour)}</div>}
|
|
117
129
|
<div
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}}
|
|
124
|
-
role="listitem">
|
|
125
|
-
{showTime && <div className={styles.captionTime}>{secontsToTime(startTime, longerThanHour)}</div>}
|
|
126
|
-
<div
|
|
127
|
-
onClick={this._handleClick}
|
|
128
|
-
className={`${styles.captionContent} ${isHighlighted ? styles.highlighted : ''} ${showTime ? '' : styles.withoutTime}`}>
|
|
129
|
-
{this._renderText(caption.text)}
|
|
130
|
-
</div>
|
|
130
|
+
onClick={this._handleClick}
|
|
131
|
+
className={`${styles.captionContent} ${isHighlighted ? styles.highlighted : ''} ${showTime ? '' : styles.withoutTime}`}
|
|
132
|
+
role="button"
|
|
133
|
+
>
|
|
134
|
+
{this._renderText(caption.text)}
|
|
131
135
|
</div>
|
|
132
|
-
</
|
|
136
|
+
</div>
|
|
133
137
|
);
|
|
134
138
|
}
|
|
135
139
|
}
|
|
@@ -4,7 +4,7 @@ import {Caption} from '../caption';
|
|
|
4
4
|
import * as styles from './captionList.scss';
|
|
5
5
|
import {HighlightedMap, CuePointData} from '../../types';
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const {End, Home} = KalturaPlayer.ui.utils.KeyMap;
|
|
8
8
|
|
|
9
9
|
export interface CaptionProps {
|
|
10
10
|
showTime: boolean;
|
|
@@ -95,9 +95,9 @@ export class CaptionList extends Component<Props> {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
private _handleKeyUp = (event: KeyboardEvent) => {
|
|
98
|
-
if (event.keyCode ===
|
|
98
|
+
if (event.keyCode === End) {
|
|
99
99
|
this._lastCaptionRef?._hotspotRef?.focus();
|
|
100
|
-
} else if (event.keyCode ===
|
|
100
|
+
} else if (event.keyCode === Home) {
|
|
101
101
|
this._firstCaptionRef?._hotspotRef?.focus();
|
|
102
102
|
}
|
|
103
103
|
};
|
|
@@ -105,7 +105,7 @@ export class CaptionList extends Component<Props> {
|
|
|
105
105
|
render() {
|
|
106
106
|
const {data} = this.props;
|
|
107
107
|
return (
|
|
108
|
-
<div className={styles.transcriptWrapper} onKeyUp={this._handleKeyUp}
|
|
108
|
+
<div className={styles.transcriptWrapper} onKeyUp={this._handleKeyUp}>
|
|
109
109
|
{data.map((captionData, index) => {
|
|
110
110
|
const captionProps = this._getCaptionProps(captionData);
|
|
111
111
|
return (
|
|
@@ -116,7 +116,7 @@ export class CaptionList extends Component<Props> {
|
|
|
116
116
|
} else if (index === data.length - 1) {
|
|
117
117
|
this._lastCaptionRef = node;
|
|
118
118
|
}
|
|
119
|
-
if (captionProps.highlighted
|
|
119
|
+
if (captionProps.highlighted) {
|
|
120
120
|
this._currentCaptionRef = node;
|
|
121
121
|
}
|
|
122
122
|
}}
|
|
@@ -3,20 +3,14 @@ import * as styles from './close-button.scss';
|
|
|
3
3
|
import {A11yWrapper} from '@playkit-js/common';
|
|
4
4
|
import {icons} from '../icons';
|
|
5
5
|
const {Icon} = KalturaPlayer.ui.components;
|
|
6
|
-
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
7
|
-
|
|
8
|
-
const translates = {
|
|
9
|
-
closeLabel: <Text id="transcript.hide_plugin">Hide Transcript</Text>
|
|
10
|
-
};
|
|
11
6
|
|
|
12
7
|
interface CloseButtonProps {
|
|
13
8
|
onClick: () => void;
|
|
14
|
-
closeLabel?: string;
|
|
15
9
|
}
|
|
16
10
|
|
|
17
|
-
export const CloseButton =
|
|
11
|
+
export const CloseButton = (props: CloseButtonProps) => (
|
|
18
12
|
<A11yWrapper onClick={props.onClick}>
|
|
19
|
-
<button className={styles.closeBtn} tabIndex={1}
|
|
13
|
+
<button className={styles.closeBtn} tabIndex={1}>
|
|
20
14
|
<Icon
|
|
21
15
|
id="transcript-plugin-close-button"
|
|
22
16
|
height={icons.BigSize}
|
|
@@ -26,4 +20,4 @@ export const CloseButton = withText(translates)((props: CloseButtonProps) => (
|
|
|
26
20
|
/>
|
|
27
21
|
</button>
|
|
28
22
|
</A11yWrapper>
|
|
29
|
-
)
|
|
23
|
+
);
|
|
@@ -26,3 +26,19 @@
|
|
|
26
26
|
background-size: cover;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
.popover-menu-item {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
padding: 9px 24px 9px 16px;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
min-height: 30px;
|
|
35
|
+
line-height: 18px;
|
|
36
|
+
font-size: 15px;
|
|
37
|
+
&:hover {
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
background-color: $semigray-color;
|
|
40
|
+
}
|
|
41
|
+
&:focus {
|
|
42
|
+
outline: 1px solid $focus-color;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {h, Component, VNode} from 'preact';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {h, Component, ComponentChild, VNode} from 'preact';
|
|
2
|
+
import {Popover, PopoverHorizontalPositions, PopoverVerticalPositions} from '../../utils';
|
|
3
|
+
import {PopoverMenu, PopoverMenuItem} from '../popover-menu';
|
|
4
4
|
import * as styles from './download-print-menu.scss';
|
|
5
5
|
import {DownloadIcon, PrintIcon} from './download-print-icons';
|
|
6
6
|
|
|
7
|
-
const {
|
|
8
|
-
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
7
|
+
const {ENTER, Esc} = KalturaPlayer.ui.utils.KeyMap;
|
|
9
8
|
|
|
10
9
|
export function downloadContent(content: string, name: string): void {
|
|
11
10
|
const blob = new Blob([content], {type: 'text/plain;charset=utf-8;'});
|
|
@@ -30,6 +29,7 @@ export function downloadContent(content: string, name: string): void {
|
|
|
30
29
|
anchor.click();
|
|
31
30
|
anchor.remove();
|
|
32
31
|
}
|
|
32
|
+
|
|
33
33
|
export function printContent(content: string): void {
|
|
34
34
|
const printWindow = window.open('', '', 'width=400,height=600');
|
|
35
35
|
if (printWindow) {
|
|
@@ -42,9 +42,9 @@ export function printContent(content: string): void {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
interface DownloadPrintMenuProps {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
dropdownAriaLabel: string;
|
|
46
|
+
printButtonAriaLabel: string;
|
|
47
|
+
downloadButtonAriaLabel: string;
|
|
48
48
|
onDownload: () => void;
|
|
49
49
|
onPrint: () => void;
|
|
50
50
|
downloadDisabled: boolean;
|
|
@@ -52,77 +52,113 @@ interface DownloadPrintMenuProps {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
interface ButtonProperties {
|
|
55
|
-
['aria-label']
|
|
55
|
+
['aria-label']: string;
|
|
56
|
+
buttonStyles: string;
|
|
57
|
+
onClick?: () => void;
|
|
56
58
|
tabIndex?: number;
|
|
59
|
+
iconStyles: string;
|
|
57
60
|
icon: VNode;
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
interface DownloadPrintMenuState {
|
|
64
|
+
popoverOpen: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class DownloadPrintMenu extends Component<DownloadPrintMenuProps, DownloadPrintMenuState> {
|
|
68
|
+
state: DownloadPrintMenuState = {
|
|
69
|
+
popoverOpen: false
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
private _onDownloadClicked = () => {
|
|
73
|
+
this.props.onDownload();
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
private _onPrintClicked = () => {
|
|
77
|
+
this.props.onPrint();
|
|
78
|
+
};
|
|
79
|
+
private _onKeyDown = (e: KeyboardEvent, callBack: Function) => {
|
|
80
|
+
if (e.keyCode !== ENTER && e.keyCode !== Esc) {
|
|
81
|
+
// don't stopPropagation on ESC and Enter pressed as it prevent the popup closing
|
|
82
|
+
e.stopPropagation();
|
|
83
|
+
}
|
|
84
|
+
switch (e.keyCode) {
|
|
85
|
+
case 13: // Enter pressed
|
|
86
|
+
callBack();
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
private _popoverMenuItemRenderer = (el: PopoverMenuItem) => (
|
|
91
|
+
<div
|
|
92
|
+
tabIndex={1}
|
|
93
|
+
role="button"
|
|
94
|
+
onClick={() => el.onMenuChosen()}
|
|
95
|
+
onKeyDown={(e: KeyboardEvent) => this._onKeyDown(e, el.onMenuChosen)}
|
|
96
|
+
className={styles.popoverMenuItem}>
|
|
97
|
+
{el.label}
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
65
100
|
|
|
66
|
-
|
|
67
|
-
private _getPopoverMenuOptions = (): Array<PopoverMenuItem> => {
|
|
101
|
+
private _getPopoverMenuOptions = () => {
|
|
68
102
|
return [
|
|
69
103
|
{
|
|
70
|
-
label: this.props.
|
|
71
|
-
onMenuChosen: this.
|
|
104
|
+
label: this.props.downloadButtonAriaLabel,
|
|
105
|
+
onMenuChosen: this._onDownloadClicked
|
|
72
106
|
},
|
|
73
107
|
{
|
|
74
|
-
label: this.props.
|
|
75
|
-
onMenuChosen: this.
|
|
108
|
+
label: this.props.printButtonAriaLabel,
|
|
109
|
+
onMenuChosen: this._onPrintClicked
|
|
76
110
|
}
|
|
77
111
|
];
|
|
78
112
|
};
|
|
79
113
|
|
|
80
|
-
private _renderIcon = ({tabIndex = 0, icon, ...props}: ButtonProperties):
|
|
114
|
+
private _renderIcon = ({buttonStyles, tabIndex = 0, iconStyles, icon, ...props}: ButtonProperties): ComponentChild => {
|
|
81
115
|
return (
|
|
82
|
-
<button className={
|
|
83
|
-
<div className={
|
|
116
|
+
<button className={buttonStyles} tabIndex={tabIndex} {...props}>
|
|
117
|
+
<div className={iconStyles}>{icon}</div>
|
|
84
118
|
</button>
|
|
85
119
|
);
|
|
86
120
|
};
|
|
87
121
|
|
|
122
|
+
private _popoverContent = () => {
|
|
123
|
+
return <PopoverMenu itemRenderer={this._popoverMenuItemRenderer} options={this._getPopoverMenuOptions()} />;
|
|
124
|
+
};
|
|
125
|
+
|
|
88
126
|
render(props: DownloadPrintMenuProps) {
|
|
89
|
-
const {downloadDisabled, printDisabled
|
|
127
|
+
const {downloadDisabled, printDisabled} = props;
|
|
90
128
|
if (!downloadDisabled && !printDisabled) {
|
|
91
129
|
return (
|
|
92
|
-
<Popover
|
|
130
|
+
<Popover
|
|
131
|
+
className="download-print-popover"
|
|
132
|
+
verticalPosition={PopoverVerticalPositions.Bottom}
|
|
133
|
+
horizontalPosition={PopoverHorizontalPositions.Left}
|
|
134
|
+
content={this._popoverContent()}>
|
|
93
135
|
{this._renderIcon({
|
|
94
|
-
['aria-label']:
|
|
136
|
+
['aria-label']: props.dropdownAriaLabel,
|
|
137
|
+
buttonStyles: styles.downloadPrintButton,
|
|
138
|
+
iconStyles: styles.icon,
|
|
95
139
|
icon: <DownloadIcon />
|
|
96
140
|
})}
|
|
97
141
|
</Popover>
|
|
98
142
|
);
|
|
99
143
|
}
|
|
100
144
|
if (!downloadDisabled && printDisabled) {
|
|
101
|
-
return (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
</A11yWrapper>
|
|
109
|
-
</Tooltip>
|
|
110
|
-
);
|
|
145
|
+
return this._renderIcon({
|
|
146
|
+
['aria-label']: props.downloadButtonAriaLabel,
|
|
147
|
+
buttonStyles: styles.downloadPrintButton,
|
|
148
|
+
iconStyles: styles.icon,
|
|
149
|
+
onClick: this._onDownloadClicked,
|
|
150
|
+
icon: <DownloadIcon />
|
|
151
|
+
});
|
|
111
152
|
}
|
|
112
153
|
if (downloadDisabled && !printDisabled) {
|
|
113
|
-
return (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
</A11yWrapper>
|
|
121
|
-
</Tooltip>
|
|
122
|
-
);
|
|
154
|
+
return this._renderIcon({
|
|
155
|
+
['aria-label']: props.printButtonAriaLabel,
|
|
156
|
+
buttonStyles: styles.downloadPrintButton,
|
|
157
|
+
iconStyles: styles.icon,
|
|
158
|
+
onClick: this._onPrintClicked,
|
|
159
|
+
icon: <PrintIcon />
|
|
160
|
+
});
|
|
123
161
|
}
|
|
124
162
|
return null;
|
|
125
163
|
}
|
|
126
164
|
}
|
|
127
|
-
|
|
128
|
-
export const DownloadPrintMenu = withText(translates)(DownloadPrintMenuComponent);
|
|
@@ -2,15 +2,7 @@ import {h} from 'preact';
|
|
|
2
2
|
import * as styles from './plugin-button.scss';
|
|
3
3
|
import {icons} from '../icons';
|
|
4
4
|
import {A11yWrapper, OnClick} from '@playkit-js/common';
|
|
5
|
-
|
|
6
5
|
const {Tooltip, Icon} = KalturaPlayer.ui.components;
|
|
7
|
-
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
8
|
-
|
|
9
|
-
const translates = ({isActive}: PluginButtonProps) => {
|
|
10
|
-
return {
|
|
11
|
-
label: isActive ? <Text id="transcript.hide_plugin">Hide Transcript</Text> : <Text id="transcript.show_plugin">Show Transcript</Text>
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
6
|
|
|
15
7
|
interface PluginButtonProps {
|
|
16
8
|
isActive: boolean;
|
|
@@ -18,7 +10,7 @@ interface PluginButtonProps {
|
|
|
18
10
|
label?: string;
|
|
19
11
|
}
|
|
20
12
|
|
|
21
|
-
export const PluginButton =
|
|
13
|
+
export const PluginButton = ({isActive, onClick, label}: PluginButtonProps) => {
|
|
22
14
|
return (
|
|
23
15
|
<Tooltip label={label} type="bottom">
|
|
24
16
|
<A11yWrapper onClick={onClick}>
|
|
@@ -34,4 +26,4 @@ export const PluginButton = withText(translates)(({isActive, onClick, label}: Pl
|
|
|
34
26
|
</A11yWrapper>
|
|
35
27
|
</Tooltip>
|
|
36
28
|
);
|
|
37
|
-
}
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './popover-menu';
|
|
@@ -0,0 +1,52 @@
|
|
|
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 className="popover-menu-item" onClick={() => el.onMenuChosen(el)}>
|
|
45
|
+
{el.label}
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
})}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|