@playkit-js/transcript 3.0.1 → 3.1.0-canary.2-d22690c

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playkit-js/transcript",
3
- "version": "3.0.1",
3
+ "version": "3.1.0-canary.2-d22690c",
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.2",
78
+ "@playkit-js/common": "^1.0.7",
79
+ "@playkit-js/ui-managers": "^1.3.0",
79
80
  "stream-browserify": "^3.0.0"
80
81
  },
81
82
  "kaltura": {
82
83
  "name": "playkit-js-transcript",
83
84
  "dependencies": {
84
85
  "playkit-kaltura-cuepoints": "3.0.0",
85
- "playkit-ui-managers": "1.2.2"
86
+ "playkit-ui-managers": "1.3.0"
86
87
  }
87
88
  }
88
89
  }
@@ -1,10 +1,8 @@
1
- import * as styles from './caption.scss';
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;
@@ -57,12 +55,10 @@ export class Caption extends Component<ExtendedCaptionProps> {
57
55
  return false;
58
56
  }
59
57
 
60
- private _handleKeyPress = (event: KeyboardEvent) => {
61
- const keyCode = event.which || event.keyCode;
62
- if (keyCode === ENTER || keyCode === Space) {
58
+ private _handleKeyDown = (event: OnClickEvent, byKeyboard?: boolean) => {
59
+ if (byKeyboard) {
63
60
  event.preventDefault();
64
61
  this._gotoCurrentTime();
65
- return;
66
62
  }
67
63
  };
68
64
 
@@ -117,23 +113,23 @@ export class Caption extends Component<ExtendedCaptionProps> {
117
113
  const isHighlighted = Object.keys(highlighted)[0] === id;
118
114
 
119
115
  return (
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>}
116
+ <A11yWrapper onClick={this._handleKeyDown}>
129
117
  <div
130
- onClick={this._handleClick}
131
- className={`${styles.captionContent} ${isHighlighted ? styles.highlighted : ''} ${showTime ? '' : styles.withoutTime}`}
132
- role="button"
133
- >
134
- {this._renderText(caption.text)}
118
+ className={styles.caption}
119
+ tabIndex={1}
120
+ area-label={caption.text}
121
+ ref={node => {
122
+ this._hotspotRef = node;
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>
135
131
  </div>
136
- </div>
132
+ </A11yWrapper>
137
133
  );
138
134
  }
139
135
  }
@@ -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 {End, Home} = KalturaPlayer.ui.utils.KeyMap;
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 === End) {
98
+ if (event.keyCode === END) {
99
99
  this._lastCaptionRef?._hotspotRef?.focus();
100
- } else if (event.keyCode === Home) {
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} role="list">
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={1}>
19
+ <button className={styles.closeBtn} tabIndex={1} 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
- export class Search extends Component<SearchProps, SearchState> {
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: MouseEvent) => {
65
- if (event.x !== 0 && event.y !== 0) {
89
+ private _onClear = (event: OnClickEvent, byKeyboard?: boolean) => {
90
+ if (!byKeyboard) {
66
91
  this._focusedByMouse = true;
67
92
  }
68
93
  this._inputRef?.focus();
@@ -135,7 +160,8 @@ export class Search extends Component<SearchProps, SearchState> {
135
160
  </div>
136
161
  <input
137
162
  className={styles.searchInput}
138
- placeholder={'Search in Transcript'}
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}
@@ -147,72 +173,82 @@ export class Search extends Component<SearchProps, SearchState> {
147
173
  }}
148
174
  />
149
175
  {searchQuery && (
150
- <button className={styles.clearIcon} onClick={this._onClear} tabIndex={1}>
151
- <svg
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={1} aria-label={this.props.clearSearchLabel}>
176
178
  <svg
177
- width="14px"
178
- height="12px"
179
- viewBox="1 0 14 12"
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/16/Arrow/-up" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
185
+ <g id="Icons/32/Clere" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
184
186
  <path
185
- 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"
186
- id="Path-2"
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={1}
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
- <button
195
- tabIndex={1}
196
- className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
197
- onClick={this._goToNextSearchResult}>
198
- <svg
199
- width="14px"
200
- height="12px"
201
- viewBox="1 2 14 12"
202
- version="1.1"
203
- xmlns="http://www.w3.org/2000/svg"
204
- xmlnsXlink="http://www.w3.org/1999/xlink">
205
- <g id="Icons/16/Arrow/down" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
206
- <path
207
- 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"
208
- id="Path-2"
209
- fill="#cccccc"></path>
210
- </g>
211
- </svg>
212
- </button>
226
+ <A11yWrapper onClick={this._goToNextSearchResult}>
227
+ <button
228
+ tabIndex={1}
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);
@@ -5,10 +5,16 @@ import * as styles from './transcript.scss';
5
5
  import {Spinner} from '../spinner';
6
6
  import {Search} from '../search';
7
7
  import {CaptionList} from '../caption-list';
8
- import {HighlightedMap, CuePointData, PluginPositions} from '../../types';
8
+ import {HighlightedMap, CuePointData} from '../../types';
9
9
  import {CloseButton} from '../close-button';
10
10
  import {ErrorIcon} from './error-icon';
11
- const {ENTER, Space, Tab, Esc} = KalturaPlayer.ui.utils.KeyMap;
11
+
12
+ const {ENTER, SPACE, TAB, ESC} = KalturaPlayer.ui.utils.KeyMap;
13
+ const {withText, Text} = KalturaPlayer.ui.preacti18n;
14
+
15
+ const translates = {
16
+ autoScrollLabel: <Text id="transcript.auto_scroll">Enable auto scroll</Text>
17
+ };
12
18
 
13
19
  export interface TranscriptProps {
14
20
  onSeek(time: number): void;
@@ -26,8 +32,8 @@ export interface TranscriptProps {
26
32
  kitchenSinkActive: boolean;
27
33
  toggledWithEnter: boolean;
28
34
  highlightedMap: HighlightedMap;
29
- pluginMode: PluginPositions;
30
35
  onItemClicked: (n: number) => void;
36
+ autoScrollLabel?: string;
31
37
  }
32
38
 
33
39
  interface TranscriptState {
@@ -50,7 +56,7 @@ const initialSearch = {
50
56
 
51
57
  const SEARCHBAR_HEIGHT = 38; // height of search bar with margins
52
58
 
53
- export class Transcript extends Component<TranscriptProps, TranscriptState> {
59
+ export class TranscriptComponent extends Component<TranscriptProps, TranscriptState> {
54
60
  private _transcriptListRef: HTMLElement | null = null;
55
61
  private _captionListRef: any = null;
56
62
  private _skipTranscriptButtonRef: HTMLDivElement | null = null;
@@ -106,6 +112,7 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
106
112
  role="button"
107
113
  className={`${styles.autoscrollButton} ${isAutoScrollEnabled ? '' : styles.autoscrollButtonVisible}`}
108
114
  tabIndex={isAutoScrollEnabled ? -1 : 1}
115
+ aria-label={this.props.autoScrollLabel}
109
116
  ref={node => {
110
117
  this._autoscrollButtonRef = node;
111
118
  }}>
@@ -201,8 +208,13 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
201
208
  );
202
209
  };
203
210
 
211
+ private _handleClick = (event: MouseEvent | KeyboardEvent) => {
212
+ event.preventDefault();
213
+ this._autoscrollButtonRef?.focus();
214
+ };
215
+
204
216
  private _handleKeyDown = (event: KeyboardEvent) => {
205
- if (event.keyCode === Tab && !event.shiftKey) {
217
+ if (event.keyCode === TAB && !event.shiftKey) {
206
218
  this.setState({
207
219
  isAutoScrollEnabled: false
208
220
  });
@@ -211,9 +223,8 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
211
223
  event.preventDefault();
212
224
  captionRef.focus();
213
225
  }
214
- } else if (event.keyCode === ENTER || event.keyCode === Space) {
215
- event.preventDefault();
216
- this._autoscrollButtonRef?.focus();
226
+ } else if (event.keyCode === ENTER || event.keyCode === SPACE) {
227
+ this._handleClick(event);
217
228
  }
218
229
  };
219
230
 
@@ -226,6 +237,7 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
226
237
  }}
227
238
  className={styles.skipTranscriptButton}
228
239
  onKeyDown={this._handleKeyDown}
240
+ onClick={this._handleClick}
229
241
  tabIndex={1}>
230
242
  Skip transcript
231
243
  </div>
@@ -351,7 +363,7 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
351
363
  };
352
364
 
353
365
  private _handleEsc = (event: KeyboardEvent) => {
354
- if (event.keyCode === Esc) {
366
+ if (event.keyCode === ESC) {
355
367
  this.props.onClose();
356
368
  }
357
369
  };
@@ -386,3 +398,5 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
386
398
  );
387
399
  }
388
400
  }
401
+
402
+ export const Transcript = withText(translates)(TranscriptComponent);