@playkit-js/transcript 3.0.1 → 3.1.0-canary.0-0df319e
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 +14 -0
- package/dist/playkit-transcript.js +1 -1
- package/dist/playkit-transcript.js.map +1 -1
- package/package.json +5 -4
- package/src/components/caption/caption.tsx +48 -27
- package/src/components/caption-list/captionList.tsx +5 -5
- package/src/components/close-button/index.tsx +9 -3
- package/src/components/icons/index.ts +4 -0
- package/src/components/plugin-button/plugin-button.scss +0 -19
- package/src/components/plugin-button/plugin-button.tsx +7 -9
- package/src/components/search/search.tsx +94 -58
- package/src/components/transcript/transcript.tsx +42 -26
- package/src/transcript-plugin.tsx +153 -97
- package/src/types/types-ui.ts +0 -7
- package/src/utils/index.ts +0 -1
- package/src/utils/utils.ts +34 -0
- package/src/components/download-print-menu/download-print-icons.tsx +0 -23
- package/src/components/download-print-menu/download-print-menu.scss +0 -44
- package/src/components/download-print-menu/download-print-menu.tsx +0 -164
- package/src/components/download-print-menu/index.ts +0 -1
- package/src/components/popover-menu/index.ts +0 -1
- package/src/components/popover-menu/popover-menu.scss +0 -6
- package/src/components/popover-menu/popover-menu.tsx +0 -52
- package/src/utils/popover/popover.scss +0 -30
- package/src/utils/popover/popover.tsx +0 -178
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playkit-js/transcript",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.1.0-canary.0-0df319e",
|
|
4
4
|
"main": "dist/playkit-transcript.js",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"private": false,
|
|
@@ -75,14 +75,15 @@
|
|
|
75
75
|
"html5 player"
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@playkit-js/common": "^1.0.
|
|
78
|
+
"@playkit-js/common": "^1.0.7",
|
|
79
|
+
"@playkit-js/ui-managers": "^1.3.1",
|
|
79
80
|
"stream-browserify": "^3.0.0"
|
|
80
81
|
},
|
|
81
82
|
"kaltura": {
|
|
82
83
|
"name": "playkit-js-transcript",
|
|
83
84
|
"dependencies": {
|
|
84
|
-
"playkit-kaltura-cuepoints": "3.0.
|
|
85
|
-
"playkit-ui-managers": "1.
|
|
85
|
+
"playkit-kaltura-cuepoints": "3.0.2",
|
|
86
|
+
"playkit-ui-managers": "1.3.1"
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {Component, h} from 'preact';
|
|
2
|
+
import {A11yWrapper, OnClickEvent} from '@playkit-js/common';
|
|
2
3
|
import {secontsToTime} from '../../utils';
|
|
3
4
|
import {CuePointData} from '../../types';
|
|
4
|
-
|
|
5
|
-
const {ENTER, Space} = KalturaPlayer.ui.utils.KeyMap;
|
|
6
|
-
|
|
7
|
-
import {Component, h} from 'preact';
|
|
5
|
+
import * as styles from './caption.scss';
|
|
8
6
|
|
|
9
7
|
export interface CaptionProps {
|
|
10
8
|
showTime: boolean;
|
|
@@ -26,9 +24,15 @@ interface ExtendedCaptionProps extends CaptionProps {
|
|
|
26
24
|
isAutoScrollEnabled: boolean;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
interface CaptionState {
|
|
28
|
+
focused: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class Caption extends Component<ExtendedCaptionProps, CaptionState> {
|
|
30
32
|
private _hotspotRef: HTMLElement | null = null;
|
|
31
33
|
|
|
34
|
+
state = {focused: false};
|
|
35
|
+
|
|
32
36
|
componentDidUpdate() {
|
|
33
37
|
if (this._hotspotRef && this.props.shouldScroll) {
|
|
34
38
|
this.props.scrollTo(this._hotspotRef);
|
|
@@ -37,12 +41,12 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
shouldComponentUpdate(nextProps: ExtendedCaptionProps) {
|
|
44
|
+
shouldComponentUpdate(nextProps: ExtendedCaptionProps, nextState: CaptionState) {
|
|
41
45
|
const {indexMap, highlighted, isAutoScrollEnabled, activeSearchIndex, longerThanHour, caption} = this.props;
|
|
42
46
|
if (longerThanHour !== nextProps.longerThanHour) {
|
|
43
47
|
return true;
|
|
44
48
|
}
|
|
45
|
-
if (highlighted !== nextProps.highlighted) {
|
|
49
|
+
if (highlighted !== nextProps.highlighted || this.state.focused !== nextState.focused) {
|
|
46
50
|
return true;
|
|
47
51
|
}
|
|
48
52
|
if (highlighted && isAutoScrollEnabled !== nextProps.isAutoScrollEnabled) {
|
|
@@ -57,12 +61,10 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
57
61
|
return false;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
if (keyCode === ENTER || keyCode === Space) {
|
|
64
|
+
private _handleKeyDown = (event: OnClickEvent, byKeyboard?: boolean) => {
|
|
65
|
+
if (byKeyboard) {
|
|
63
66
|
event.preventDefault();
|
|
64
67
|
this._gotoCurrentTime();
|
|
65
|
-
return;
|
|
66
68
|
}
|
|
67
69
|
};
|
|
68
70
|
|
|
@@ -111,29 +113,48 @@ export class Caption extends Component<ExtendedCaptionProps> {
|
|
|
111
113
|
);
|
|
112
114
|
};
|
|
113
115
|
|
|
116
|
+
private _handleFocus = () => {
|
|
117
|
+
this.setState({
|
|
118
|
+
focused: true
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
private _handleBlur = () => {
|
|
123
|
+
this.setState({
|
|
124
|
+
focused: false
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
114
128
|
render() {
|
|
115
129
|
const {caption, highlighted, showTime, longerThanHour} = this.props;
|
|
116
130
|
const {startTime, id} = caption;
|
|
117
131
|
const isHighlighted = Object.keys(highlighted)[0] === id;
|
|
118
132
|
|
|
133
|
+
const captionA11yProps: Record<string, any> = {
|
|
134
|
+
role: isHighlighted ? 'text' : 'listitem',
|
|
135
|
+
ariaCurrent: isHighlighted,
|
|
136
|
+
onFocus: this._handleFocus,
|
|
137
|
+
onBlur: this._handleBlur,
|
|
138
|
+
tabIndex: 0,
|
|
139
|
+
ariaHidden: !(isHighlighted || this.state.focused)
|
|
140
|
+
};
|
|
141
|
+
|
|
119
142
|
return (
|
|
120
|
-
<
|
|
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>}
|
|
143
|
+
<A11yWrapper onClick={this._handleKeyDown}>
|
|
129
144
|
<div
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
{
|
|
145
|
+
className={styles.caption}
|
|
146
|
+
ref={node => {
|
|
147
|
+
this._hotspotRef = node;
|
|
148
|
+
}}
|
|
149
|
+
{...captionA11yProps}>
|
|
150
|
+
{showTime && <div className={styles.captionTime}>{secontsToTime(startTime, longerThanHour)}</div>}
|
|
151
|
+
<div
|
|
152
|
+
onClick={this._handleClick}
|
|
153
|
+
className={`${styles.captionContent} ${isHighlighted ? styles.highlighted : ''} ${showTime ? '' : styles.withoutTime}`}>
|
|
154
|
+
{this._renderText(caption.text)}
|
|
155
|
+
</div>
|
|
135
156
|
</div>
|
|
136
|
-
</
|
|
157
|
+
</A11yWrapper>
|
|
137
158
|
);
|
|
138
159
|
}
|
|
139
160
|
}
|
|
@@ -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} aria-live="polite">
|
|
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[captionData.id]) {
|
|
120
120
|
this._currentCaptionRef = node;
|
|
121
121
|
}
|
|
122
122
|
}}
|
|
@@ -3,14 +3,20 @@ 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
|
+
};
|
|
6
11
|
|
|
7
12
|
interface CloseButtonProps {
|
|
8
13
|
onClick: () => void;
|
|
14
|
+
closeLabel?: string;
|
|
9
15
|
}
|
|
10
16
|
|
|
11
|
-
export const CloseButton = (props: CloseButtonProps) => (
|
|
17
|
+
export const CloseButton = withText(translates)((props: CloseButtonProps) => (
|
|
12
18
|
<A11yWrapper onClick={props.onClick}>
|
|
13
|
-
<button className={styles.closeBtn} tabIndex={
|
|
19
|
+
<button className={styles.closeBtn} tabIndex={0} aria-label={props.closeLabel}>
|
|
14
20
|
<Icon
|
|
15
21
|
id="transcript-plugin-close-button"
|
|
16
22
|
height={icons.BigSize}
|
|
@@ -20,4 +26,4 @@ export const CloseButton = (props: CloseButtonProps) => (
|
|
|
20
26
|
/>
|
|
21
27
|
</button>
|
|
22
28
|
</A11yWrapper>
|
|
23
|
-
);
|
|
29
|
+
));
|
|
@@ -3,6 +3,10 @@ export namespace icons {
|
|
|
3
3
|
'M23.1111111,19 C23.6020309,19 24,19.4477153 24,20 C24,20.5522847 23.6020309,21 23.1111111,21 L8.88888889,21 C8.39796911,21 8,20.5522847 8,20 C8,19.4477153 8.39796911,19 8.88888889,19 L23.1111111,19 Z M24.8695652,3 C26.5984566,3 28,4.24720677 28,5.78571429 L28,26.2142857 C28,27.7527932 26.5984566,29 24.8695652,29 L7.13043478,29 C5.40154339,29 4,27.7527932 4,26.2142857 L4,5.78571429 C4,4.24720677 5.40154339,3 7.13043478,3 L24.8695652,3 Z M26,17 L6,17 L6,26.0833333 C6,26.5895944 6.47127921,27 7.05263158,27 L24.9473684,27 C25.5287208,27 26,26.5895944 26,26.0833333 L26,17 Z M8.88888889,23 L23.1111111,23 C23.6020309,23 24,23.4477153 24,24 C24,24.5128358 23.6568532,24.9355072 23.2147743,24.9932723 L23.1111111,25 L8.88888889,25 C8.39796911,25 8,24.5522847 8,24 C8,23.4871642 8.34314684,23.0644928 8.78522567,23.0067277 L8.88888889,23 L23.1111111,23 L8.88888889,23 Z M24.9473684,5 L7.05263158,5 C6.47127921,5 6,5.41040565 6,5.91666667 L6,15 L26,15 L26,5.91666667 C26,5.41040565 25.5287208,5 24.9473684,5 Z';
|
|
4
4
|
export const CLOSE_ICON =
|
|
5
5
|
'M17.9113162,16 L24.6072325,9.30408374 C25.1313645,8.77995172 25.1287183,7.92687249 24.6009229,7.3990771 C24.0694478,6.86760201 23.220227,6.86845682 22.6959163,7.39276754 L16,14.0886838 L9.30408374,7.39276754 C8.77995172,6.86863552 7.92687249,6.8712817 7.3990771,7.3990771 C6.86760201,7.93055219 6.86845682,8.77977302 7.39276754,9.30408374 L14.0886838,16 L7.39276754,22.6959163 C6.86863552,23.2200483 6.8712817,24.0731275 7.3990771,24.6009229 C7.93055219,25.132398 8.77977302,25.1315432 9.30408374,24.6072325 L16,17.9113162 L22.6959163,24.6072325 C23.2200483,25.1313645 24.0731275,25.1287183 24.6009229,24.6009229 C25.132398,24.0694478 25.1315432,23.220227 24.6072325,22.6959163 L17.9113162,16 Z';
|
|
6
|
+
export const DOWNLOAD_ICON =
|
|
7
|
+
'M26,25 C26.5522847,25 27,25.4477153 27,26 C27,26.5522847 26.5522847,27 26,27 L26,27 L7,27 C6.44771525,27 6,26.5522847 6,26 C6,25.4477153 6.44771525,25 7,25 L7,25 Z M15.897,20.797 L15.817,20.73 L15.8163834,20.7298413 L8.34305882,13.7298413 C7.93997861,13.3522902 7.91928313,12.7194636 8.29683417,12.3163834 C8.67438521,11.9133032 9.30721188,11.8926077 9.71029209,12.2701587 L15.4996721,17.693 L15.5,6 C15.5,5.48716416 15.8860402,5.06449284 16.3833789,5.00672773 L16.5,5 C17.0522847,5 17.5,5.44771525 17.5,6 L17.4996721,17.694 L23.2951711,12.2699211 C23.6673663,11.9215418 24.2352038,11.9125649 24.6172049,12.230382 L24.7086128,12.3166371 C25.0860237,12.7198486 25.0651082,13.352668 24.6618968,13.7300789 L17.1833629,20.7300789 L17.1610165,20.7503813 L17.1610165,20.7503813 C17.1421868,20.7669999 17.1224361,20.7831339 17.102079,20.7985075 C17.0891381,20.8082894 17.0764369,20.8174134 17.0635772,20.826204 C17.0434306,20.8399634 17.0223437,20.8532674 17.0007451,20.8657864 C16.9872099,20.8736423 16.9734873,20.8811624 16.959633,20.8883367 L16.8877511,20.9220455 L16.8877511,20.9220455 C16.8756318,20.927087 16.8632234,20.9320132 16.8507409,20.9366814 C16.83028,20.9444208 16.8097352,20.9513578 16.7889039,20.9576336 C16.7705976,20.9630349 16.752126,20.968019 16.7335525,20.9724647 C16.6585039,20.9905214 16.5803589,21 16.5,21 C16.4170842,21 16.3365254,20.9899086 16.2594848,20.9708871 C16.2500284,20.9684434 16.2399293,20.9657886 16.2298654,20.9629733 C16.2028024,20.9554899 16.1769173,20.947049 16.1515197,20.9376057 C16.1370523,20.9321598 16.1223107,20.9262914 16.1076867,20.9200585 C16.0832011,20.9096448 16.0596143,20.8984375 16.036557,20.886357 C16.025923,20.8807972 16.0148138,20.8747205 16.0037984,20.8684173 C15.9792921,20.8543502 15.955966,20.8396537 15.9333153,20.8240474 L15.898,20.798 L15.897,20.797 Z M15.867,20.774 L15.888,20.79 L15.8735171,20.7794831 L15.8735171,20.7794831 L15.867,20.774 Z M15.817,20.73 L15.9035191,20.8027045 C15.8784859,20.7840722 15.8543541,20.7642966 15.831201,20.7434548 L15.817,20.73 Z';
|
|
8
|
+
export const PRINT_ICON =
|
|
9
|
+
'M21,3 C22.0543618,3 22.9181651,3.81587779 22.9945143,4.85073766 L23,5 L23,9 L26,9 C27.1045695,9 28,9.8954305 28,11 L28,21 C28,22.1045695 27.1045695,23 26,23 L23,23 L23,28 C23,29.1045695 22.1045695,30 21,30 L11,30 C9.8954305,30 9,29.1045695 9,28 L9,23 L6,23 C4.8954305,23 4,22.1045695 4,21 L4,11 C4,9.8954305 4.8954305,9 6,9 L9,9 L9,5 C9,3.9456382 9.81587779,3.08183488 10.8507377,3.00548574 L11,3 L21,3 Z M21,19 L11,19 L11,28 L21,28 L21,19 Z M26,11 L6,11 L6,21 L9,21 L9,19 C8.44771525,19 8,18.5522847 8,18 C8,17.4477153 8.44771525,17 9,17 L23,17 C23.5522847,17 24,17.4477153 24,18 C24,18.5522847 23.5522847,19 23,19 L23,21 L26,21 L26,11 Z M21,5 L11,5 L11,9 L21,9 L21,5 Z';
|
|
6
10
|
export const BigSize = 32;
|
|
7
11
|
export const MediumSize = 24;
|
|
8
12
|
export const SmallSize = 16;
|
|
@@ -1,26 +1,7 @@
|
|
|
1
1
|
@import '../../variables.scss';
|
|
2
2
|
|
|
3
|
-
.navigationPluginButton,
|
|
4
|
-
.navigationPluginIcon {
|
|
5
|
-
min-height: 36px;
|
|
6
|
-
min-width: 36px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
3
|
.pluginButton {
|
|
10
|
-
display: flex;
|
|
11
|
-
width: 36px;
|
|
12
|
-
height: 36px;
|
|
13
|
-
padding: 0;
|
|
14
|
-
background: transparent;
|
|
15
|
-
border: none;
|
|
16
|
-
border-radius: 4px;
|
|
17
|
-
cursor: pointer;
|
|
18
4
|
&.active {
|
|
19
5
|
background-color: $darken-gray;
|
|
20
6
|
}
|
|
21
7
|
}
|
|
22
|
-
|
|
23
|
-
// TODO: remove once core team fix alignment of plugin icons
|
|
24
|
-
:global(.playkit-player .playkit-top-bar .playkit-right-controls) {
|
|
25
|
-
display: flex;
|
|
26
|
-
}
|
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
import {h} from 'preact';
|
|
2
2
|
import * as styles from './plugin-button.scss';
|
|
3
|
+
import {ui} from 'kaltura-player-js';
|
|
3
4
|
import {icons} from '../icons';
|
|
4
5
|
import {A11yWrapper, OnClick} from '@playkit-js/common';
|
|
6
|
+
|
|
5
7
|
const {Tooltip, Icon} = KalturaPlayer.ui.components;
|
|
6
8
|
|
|
7
9
|
interface PluginButtonProps {
|
|
8
10
|
isActive: boolean;
|
|
9
11
|
onClick: OnClick;
|
|
12
|
+
id: string;
|
|
13
|
+
icon: string;
|
|
10
14
|
label?: string;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
export const PluginButton = ({isActive, onClick, label}: PluginButtonProps) => {
|
|
17
|
+
export const PluginButton = ({isActive, onClick, label, id, icon}: PluginButtonProps) => {
|
|
14
18
|
return (
|
|
15
19
|
<Tooltip label={label} type="bottom">
|
|
16
20
|
<A11yWrapper onClick={onClick}>
|
|
17
|
-
<button aria-label={label} className={[styles.pluginButton, isActive ? styles.active : ''].join(' ')}>
|
|
18
|
-
<Icon
|
|
19
|
-
id="transcript-plugin-button"
|
|
20
|
-
height={icons.BigSize}
|
|
21
|
-
width={icons.BigSize}
|
|
22
|
-
viewBox={`0 0 ${icons.BigSize} ${icons.BigSize}`}
|
|
23
|
-
path={icons.PLUGIN_ICON}
|
|
24
|
-
/>
|
|
21
|
+
<button aria-label={label} className={[ui.style.upperBarIcon, styles.pluginButton, isActive ? styles.active : ''].join(' ')}>
|
|
22
|
+
<Icon id={id} height={icons.BigSize} width={icons.BigSize} viewBox={`0 0 ${icons.BigSize} ${icons.BigSize}`} path={icon} />
|
|
25
23
|
</button>
|
|
26
24
|
</A11yWrapper>
|
|
27
25
|
</Tooltip>
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import {h, Component} from 'preact';
|
|
2
|
+
import {A11yWrapper, OnClickEvent} from '@playkit-js/common';
|
|
2
3
|
import * as styles from './search.scss';
|
|
3
4
|
import {debounce} from '../../utils';
|
|
4
5
|
const DEBOUNCE_TIMEOUT = 300;
|
|
5
6
|
|
|
7
|
+
const {withText, Text} = KalturaPlayer.ui.preacti18n;
|
|
8
|
+
const translates = ({activeSearchIndex, totalSearchResults}: SearchProps) => ({
|
|
9
|
+
searchLabel: <Text id="transcript.search">Search in Transcript</Text>,
|
|
10
|
+
clearSearchLabel: <Text id="transcript.clear_search">Clear search</Text>,
|
|
11
|
+
nextMatchLabel: <Text id="transcript.next_search_match">Next</Text>,
|
|
12
|
+
prevMatchLabel: <Text id="transcript.prev_search_match">Previous</Text>,
|
|
13
|
+
searchResultsLabel: (
|
|
14
|
+
<Text
|
|
15
|
+
id="transcript.prev_search_match"
|
|
16
|
+
fields={{
|
|
17
|
+
current: totalSearchResults > 0 ? activeSearchIndex : 0,
|
|
18
|
+
total: totalSearchResults
|
|
19
|
+
}}>
|
|
20
|
+
{`Result ${totalSearchResults > 0 ? activeSearchIndex : 0} of ${totalSearchResults}`}
|
|
21
|
+
</Text>
|
|
22
|
+
)
|
|
23
|
+
});
|
|
24
|
+
|
|
6
25
|
export interface SearchProps {
|
|
7
26
|
onChange(value: string): void;
|
|
8
27
|
searchQuery: string;
|
|
@@ -13,6 +32,12 @@ export interface SearchProps {
|
|
|
13
32
|
value: string;
|
|
14
33
|
activeSearchIndex: number;
|
|
15
34
|
totalSearchResults: number;
|
|
35
|
+
|
|
36
|
+
searchLabel?: string;
|
|
37
|
+
clearSearchLabel?: string;
|
|
38
|
+
nextMatchLabel?: string;
|
|
39
|
+
prevMatchLabel?: string;
|
|
40
|
+
searchResultsLabel?: string;
|
|
16
41
|
}
|
|
17
42
|
|
|
18
43
|
interface SearchState {
|
|
@@ -20,7 +45,7 @@ interface SearchState {
|
|
|
20
45
|
focused: boolean;
|
|
21
46
|
}
|
|
22
47
|
|
|
23
|
-
|
|
48
|
+
class SearchComponent extends Component<SearchProps, SearchState> {
|
|
24
49
|
state: SearchState = {
|
|
25
50
|
active: false,
|
|
26
51
|
focused: false
|
|
@@ -61,8 +86,8 @@ export class Search extends Component<SearchProps, SearchState> {
|
|
|
61
86
|
this.props.onChange(e.target.value);
|
|
62
87
|
};
|
|
63
88
|
|
|
64
|
-
private _onClear = (event:
|
|
65
|
-
if (
|
|
89
|
+
private _onClear = (event: OnClickEvent, byKeyboard?: boolean) => {
|
|
90
|
+
if (!byKeyboard) {
|
|
66
91
|
this._focusedByMouse = true;
|
|
67
92
|
}
|
|
68
93
|
this._inputRef?.focus();
|
|
@@ -135,84 +160,95 @@ export class Search extends Component<SearchProps, SearchState> {
|
|
|
135
160
|
</div>
|
|
136
161
|
<input
|
|
137
162
|
className={styles.searchInput}
|
|
138
|
-
|
|
163
|
+
aria-label={this.props.searchLabel}
|
|
164
|
+
placeholder={this.props.searchLabel}
|
|
139
165
|
value={searchQuery}
|
|
140
166
|
onInput={this._handleOnChange}
|
|
141
167
|
onFocus={this._onFocus}
|
|
142
168
|
onBlur={this._onBlur}
|
|
143
169
|
onMouseDown={this._handleMouseDown}
|
|
144
|
-
tabIndex={
|
|
170
|
+
tabIndex={0}
|
|
145
171
|
ref={node => {
|
|
146
172
|
this._inputRef = node;
|
|
147
173
|
}}
|
|
148
174
|
/>
|
|
149
175
|
{searchQuery && (
|
|
150
|
-
<
|
|
151
|
-
<
|
|
152
|
-
width="32px"
|
|
153
|
-
height="32px"
|
|
154
|
-
viewBox="0 0 32 32"
|
|
155
|
-
version="1.1"
|
|
156
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
157
|
-
xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
158
|
-
<g id="Icons/32/Clere" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
159
|
-
<path
|
|
160
|
-
d="M16,8 C20.418278,8 24,11.581722 24,16 C24,20.418278 20.418278,24 16,24 C11.581722,24 8,20.418278 8,16 C8,11.581722 11.581722,8 16,8 Z M19.8665357,12.1334643 C19.6885833,11.9555119 19.4000655,11.9555119 19.2221131,12.1334643 L16,15.356 L12.7778869,12.1334643 L12.7064039,12.0750737 C12.5295326,11.9582924 12.2891726,11.977756 12.1334643,12.1334643 L12.0750737,12.2049473 C11.9582924,12.3818186 11.977756,12.6221786 12.1334643,12.7778869 L15.356,16 L12.1334643,19.2221131 C11.9555119,19.4000655 11.9555119,19.6885833 12.1334643,19.8665357 C12.3114167,20.0444881 12.5999345,20.0444881 12.7778869,19.8665357 L16,16.644 L19.2221131,19.8665357 L19.2935961,19.9249263 C19.4704674,20.0417076 19.7108274,20.022244 19.8665357,19.8665357 L19.9249263,19.7950527 C20.0417076,19.6181814 20.022244,19.3778214 19.8665357,19.2221131 L16.644,16 L19.8665357,12.7778869 C20.0444881,12.5999345 20.0444881,12.3114167 19.8665357,12.1334643 Z"
|
|
161
|
-
id="Shape"
|
|
162
|
-
fill="#cccccc"></path>
|
|
163
|
-
</g>
|
|
164
|
-
</svg>
|
|
165
|
-
</button>
|
|
166
|
-
)}
|
|
167
|
-
{searchQuery && (
|
|
168
|
-
<div className={styles.searchResults}>{`${totalSearchResults > 0 ? `${activeSearchIndex}/${totalSearchResults}` : '0/0'}`}</div>
|
|
169
|
-
)}
|
|
170
|
-
<div className={styles.prevNextWrapper}>
|
|
171
|
-
{searchQuery && (
|
|
172
|
-
<button
|
|
173
|
-
tabIndex={1}
|
|
174
|
-
className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
|
|
175
|
-
onClick={this._goToPrevSearchResult}>
|
|
176
|
+
<A11yWrapper onClick={this._onClear}>
|
|
177
|
+
<button className={styles.clearIcon} tabIndex={0} aria-label={this.props.clearSearchLabel}>
|
|
176
178
|
<svg
|
|
177
|
-
width="
|
|
178
|
-
height="
|
|
179
|
-
viewBox="
|
|
179
|
+
width="32px"
|
|
180
|
+
height="32px"
|
|
181
|
+
viewBox="0 0 32 32"
|
|
180
182
|
version="1.1"
|
|
181
183
|
xmlns="http://www.w3.org/2000/svg"
|
|
182
184
|
xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
183
|
-
<g id="Icons/
|
|
185
|
+
<g id="Icons/32/Clere" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
184
186
|
<path
|
|
185
|
-
d="
|
|
186
|
-
id="
|
|
187
|
-
fill="#cccccc"
|
|
188
|
-
transform="translate(8.000000, 8.519717) scale(1, -1) translate(-8.000000, -8.519717) "></path>
|
|
187
|
+
d="M16,8 C20.418278,8 24,11.581722 24,16 C24,20.418278 20.418278,24 16,24 C11.581722,24 8,20.418278 8,16 C8,11.581722 11.581722,8 16,8 Z M19.8665357,12.1334643 C19.6885833,11.9555119 19.4000655,11.9555119 19.2221131,12.1334643 L16,15.356 L12.7778869,12.1334643 L12.7064039,12.0750737 C12.5295326,11.9582924 12.2891726,11.977756 12.1334643,12.1334643 L12.0750737,12.2049473 C11.9582924,12.3818186 11.977756,12.6221786 12.1334643,12.7778869 L15.356,16 L12.1334643,19.2221131 C11.9555119,19.4000655 11.9555119,19.6885833 12.1334643,19.8665357 C12.3114167,20.0444881 12.5999345,20.0444881 12.7778869,19.8665357 L16,16.644 L19.2221131,19.8665357 L19.2935961,19.9249263 C19.4704674,20.0417076 19.7108274,20.022244 19.8665357,19.8665357 L19.9249263,19.7950527 C20.0417076,19.6181814 20.022244,19.3778214 19.8665357,19.2221131 L16.644,16 L19.8665357,12.7778869 C20.0444881,12.5999345 20.0444881,12.3114167 19.8665357,12.1334643 Z"
|
|
188
|
+
id="Shape"
|
|
189
|
+
fill="#cccccc"></path>
|
|
189
190
|
</g>
|
|
190
191
|
</svg>
|
|
191
192
|
</button>
|
|
193
|
+
</A11yWrapper>
|
|
194
|
+
)}
|
|
195
|
+
{searchQuery && (
|
|
196
|
+
<div className={styles.searchResults} aria-live="polite" aria-label={this.props.searchResultsLabel}>{`${
|
|
197
|
+
totalSearchResults > 0 ? `${activeSearchIndex}/${totalSearchResults}` : '0/0'
|
|
198
|
+
}`}</div>
|
|
199
|
+
)}
|
|
200
|
+
<div className={styles.prevNextWrapper}>
|
|
201
|
+
{searchQuery && (
|
|
202
|
+
<A11yWrapper onClick={this._goToPrevSearchResult}>
|
|
203
|
+
<button
|
|
204
|
+
tabIndex={0}
|
|
205
|
+
className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
|
|
206
|
+
aria-label={this.props.prevMatchLabel}>
|
|
207
|
+
<svg
|
|
208
|
+
width="14px"
|
|
209
|
+
height="12px"
|
|
210
|
+
viewBox="1 0 14 12"
|
|
211
|
+
version="1.1"
|
|
212
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
213
|
+
xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
214
|
+
<g id="Icons/16/Arrow/-up" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
215
|
+
<path
|
|
216
|
+
d="M4.78325732,5.37830235 C4.43990319,4.94572127 3.81088342,4.87338855 3.37830235,5.21674268 C2.94572127,5.56009681 2.87338855,6.18911658 3.21674268,6.62169765 L7.21674268,11.6611718 C7.61710439,12.165575 8.38289561,12.165575 8.78325732,11.6611718 L12.7832573,6.62169765 C13.1266115,6.18911658 13.0542787,5.56009681 12.6216977,5.21674268 C12.1891166,4.87338855 11.5600968,4.94572127 11.2167427,5.37830235 L8,9.43097528 L4.78325732,5.37830235 Z"
|
|
217
|
+
id="Path-2"
|
|
218
|
+
fill="#cccccc"
|
|
219
|
+
transform="translate(8.000000, 8.519717) scale(1, -1) translate(-8.000000, -8.519717) "></path>
|
|
220
|
+
</g>
|
|
221
|
+
</svg>
|
|
222
|
+
</button>
|
|
223
|
+
</A11yWrapper>
|
|
192
224
|
)}
|
|
193
225
|
{searchQuery && (
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
226
|
+
<A11yWrapper onClick={this._goToNextSearchResult}>
|
|
227
|
+
<button
|
|
228
|
+
tabIndex={0}
|
|
229
|
+
className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
|
|
230
|
+
aria-label={this.props.nextMatchLabel}>
|
|
231
|
+
<svg
|
|
232
|
+
width="14px"
|
|
233
|
+
height="12px"
|
|
234
|
+
viewBox="1 2 14 12"
|
|
235
|
+
version="1.1"
|
|
236
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
237
|
+
xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
238
|
+
<g id="Icons/16/Arrow/down" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
239
|
+
<path
|
|
240
|
+
d="M4.78325732,5.37830235 C4.43990319,4.94572127 3.81088342,4.87338855 3.37830235,5.21674268 C2.94572127,5.56009681 2.87338855,6.18911658 3.21674268,6.62169765 L7.21674268,11.6611718 C7.61710439,12.165575 8.38289561,12.165575 8.78325732,11.6611718 L12.7832573,6.62169765 C13.1266115,6.18911658 13.0542787,5.56009681 12.6216977,5.21674268 C12.1891166,4.87338855 11.5600968,4.94572127 11.2167427,5.37830235 L8,9.43097528 L4.78325732,5.37830235 Z"
|
|
241
|
+
id="Path-2"
|
|
242
|
+
fill="#cccccc"></path>
|
|
243
|
+
</g>
|
|
244
|
+
</svg>
|
|
245
|
+
</button>
|
|
246
|
+
</A11yWrapper>
|
|
213
247
|
)}
|
|
214
248
|
</div>
|
|
215
249
|
</div>
|
|
216
250
|
);
|
|
217
251
|
}
|
|
218
252
|
}
|
|
253
|
+
|
|
254
|
+
export const Search = withText(translates)(SearchComponent);
|