@playkit-js/transcript 3.4.4 → 3.5.0-canary.0-3275484

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.4.4",
3
+ "version": "3.5.0-canary.0-3275484",
4
4
  "main": "dist/playkit-transcript.js",
5
5
  "license": "AGPL-3.0",
6
6
  "private": false,
@@ -74,7 +74,7 @@
74
74
  "html5 player"
75
75
  ],
76
76
  "dependencies": {
77
- "@playkit-js/common": "^1.2.10",
77
+ "@playkit-js/common": "^1.2.13",
78
78
  "@playkit-js/playkit-js-ui": "^0.77.3",
79
79
  "@playkit-js/ui-managers": "^1.3.11",
80
80
  "stream-browserify": "^3.0.0"
@@ -11,11 +11,6 @@
11
11
 
12
12
  .autoscroll-button {
13
13
  opacity: 0;
14
- border-radius: $roundness-1;
15
- border: none;
16
- box-shadow: 0px 1px 0.75px rgba(0, 0, 0, 0.42), 0px 1px 0.5px rgba(0, 0, 0, 0.25), 0px 2px 3px rgba(0, 0, 0, 0.2);
17
- background-color: $primary-darker-color;
18
- cursor: pointer;
19
14
  z-index: 1;
20
15
  &.autoscroll-button-visible {
21
16
  opacity: 1;
@@ -1,10 +1,9 @@
1
1
  import {h} from 'preact';
2
2
  import * as styles from './autoscroll-button.scss';
3
- import {A11yWrapper, OnClick} from '@playkit-js/common/dist/hoc/a11y-wrapper';
4
- import {AutoScrollIcon} from "./AutoScrollIcon";
3
+ import {OnClick} from '@playkit-js/common/dist/hoc/a11y-wrapper';
4
+ import {Button, ButtonType} from '@playkit-js/common/dist/components/button';
5
5
 
6
6
  const {withText, Text} = KalturaPlayer.ui.preacti18n;
7
- const {Tooltip} = KalturaPlayer.ui.components;
8
7
 
9
8
  interface AutoscrollButtonProps {
10
9
  onClick: OnClick;
@@ -21,15 +20,14 @@ export const AutoscrollButton = withText(translates)(
21
20
  ({onClick, isAutoScrollEnabled, setAutoscrollButtonRef, autoScrollLabel}: AutoscrollButtonProps) => {
22
21
  return (
23
22
  <div className={styles.autoscrollRoot} tabIndex={isAutoScrollEnabled ? -1 : 1} aria-label={autoScrollLabel}>
24
- <Tooltip label={autoScrollLabel} type="left">
25
- <A11yWrapper onClick={onClick}>
26
- <button
27
- className={`${styles.autoscrollButton} ${isAutoScrollEnabled ? '' : styles.autoscrollButtonVisible}`}
28
- ref={setAutoscrollButtonRef}>
29
- <AutoScrollIcon/>
30
- </button>
31
- </A11yWrapper>
32
- </Tooltip>
23
+ <Button
24
+ onClick={onClick}
25
+ setRef={setAutoscrollButtonRef}
26
+ className={`${styles.autoscrollButton} ${isAutoScrollEnabled ? '' : styles.autoscrollButtonVisible}`}
27
+ type={ButtonType.primary}
28
+ icon="autoScroll"
29
+ tooltip={{label: autoScrollLabel!, type: 'left'}}
30
+ />
33
31
  </div>
34
32
  );
35
33
  }
@@ -7,6 +7,7 @@
7
7
  margin-bottom: 9px;
8
8
  margin-left: 8px;
9
9
  color: $tone-1-color;
10
+ cursor: pointer;
10
11
  .caption-time {
11
12
  flex-shrink: 1;
12
13
  min-width: 48px;
@@ -48,7 +49,6 @@
48
49
  user-select: text;
49
50
  -ms-user-select: text;
50
51
  border-radius: 2px;
51
- cursor: pointer;
52
52
  &::selection {
53
53
  background-color: $primary-brighter-color;
54
54
  padding: 0 2px;
@@ -1,6 +1,6 @@
1
1
  import {Component, h} from 'preact';
2
2
  import {A11yWrapper, OnClickEvent} from '@playkit-js/common/dist/hoc/a11y-wrapper';
3
- import {secontsToTime} from '../../utils';
3
+ import {secondsToTime} from '../../utils';
4
4
  import {CuePointData} from '../../types';
5
5
  import * as styles from './caption.scss';
6
6
 
@@ -24,15 +24,9 @@ interface ExtendedCaptionProps extends CaptionProps {
24
24
  isAutoScrollEnabled: boolean;
25
25
  }
26
26
 
27
- interface CaptionState {
28
- focused: boolean;
29
- }
30
-
31
- export class Caption extends Component<ExtendedCaptionProps, CaptionState> {
27
+ export class Caption extends Component<ExtendedCaptionProps> {
32
28
  private _hotspotRef: HTMLElement | null = null;
33
29
 
34
- state = {focused: false};
35
-
36
30
  componentDidUpdate() {
37
31
  if (this._hotspotRef && this.props.shouldScroll) {
38
32
  this.props.scrollTo(this._hotspotRef);
@@ -41,12 +35,12 @@ export class Caption extends Component<ExtendedCaptionProps, CaptionState> {
41
35
  }
42
36
  }
43
37
 
44
- shouldComponentUpdate(nextProps: ExtendedCaptionProps, nextState: CaptionState) {
45
- const {indexMap, highlighted, isAutoScrollEnabled, activeSearchIndex, longerThanHour, caption} = this.props;
38
+ shouldComponentUpdate(nextProps: ExtendedCaptionProps) {
39
+ const {indexMap, highlighted, isAutoScrollEnabled, activeSearchIndex, longerThanHour} = this.props;
46
40
  if (longerThanHour !== nextProps.longerThanHour) {
47
41
  return true;
48
42
  }
49
- if (highlighted !== nextProps.highlighted || this.state.focused !== nextState.focused) {
43
+ if (highlighted !== nextProps.highlighted) {
50
44
  return true;
51
45
  }
52
46
  if (highlighted && isAutoScrollEnabled !== nextProps.isAutoScrollEnabled) {
@@ -61,16 +55,7 @@ export class Caption extends Component<ExtendedCaptionProps, CaptionState> {
61
55
  return false;
62
56
  }
63
57
 
64
- private _handleKeyDown = (event: OnClickEvent, byKeyboard?: boolean) => {
65
- if (byKeyboard) {
66
- event.preventDefault();
67
- this._gotoCurrentTime();
68
- }
69
- };
70
-
71
- private _handleClick = (event: MouseEvent) => {
72
- event.stopPropagation();
73
- this._hotspotRef?.focus();
58
+ private _handleClick = () => {
74
59
  this._gotoCurrentTime();
75
60
  };
76
61
 
@@ -113,42 +98,34 @@ export class Caption extends Component<ExtendedCaptionProps, CaptionState> {
113
98
  );
114
99
  };
115
100
 
116
- private _handleFocus = () => {
117
- this.setState({
118
- focused: true
119
- });
120
- };
121
-
122
- private _handleBlur = () => {
123
- this.setState({
124
- focused: false
125
- });
126
- };
127
-
128
101
  render() {
129
102
  const {caption, highlighted, showTime, longerThanHour} = this.props;
130
103
  const {startTime, id} = caption;
131
104
  const isHighlighted = Object.keys(highlighted)[0] === id;
105
+ const time = showTime ? secondsToTime(startTime, longerThanHour) : '';
132
106
 
133
107
  const captionA11yProps: Record<string, any> = {
134
108
  ariaCurrent: isHighlighted,
135
- onFocus: this._handleFocus,
136
- onBlur: this._handleBlur,
137
109
  tabIndex: 0,
138
- ariaHidden: !(isHighlighted || this.state.focused)
110
+ ariaLabel: `${time}${showTime ? ' ' : ''}${caption.text}`,
111
+ role: 'button'
139
112
  };
140
113
 
141
114
  return (
142
- <A11yWrapper onClick={this._handleKeyDown} role={isHighlighted ? 'text' : 'listitem'}>
115
+ <A11yWrapper onClick={this._handleClick}>
143
116
  <div
144
117
  className={styles.caption}
145
118
  ref={node => {
146
119
  this._hotspotRef = node;
147
120
  }}
148
121
  {...captionA11yProps}>
149
- {showTime && <div className={styles.captionTime}>{secontsToTime(startTime, longerThanHour)}</div>}
122
+ {showTime && (
123
+ <div className={styles.captionTime} aria-hidden="true">
124
+ {time}
125
+ </div>
126
+ )}
150
127
  <div
151
- onClick={this._handleClick}
128
+ aria-hidden="true"
152
129
  className={`${styles.captionContent} ${isHighlighted ? styles.highlighted : ''} ${showTime ? '' : styles.withoutTime}`}>
153
130
  {this._renderText(caption.text)}
154
131
  </div>
@@ -0,0 +1 @@
1
+ export * from "./small-screen-slate";
@@ -0,0 +1,28 @@
1
+ .smallScreenWrapper {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 100%;
5
+ margin-top: -8px;
6
+ margin-right: -2px;
7
+ display: flex;
8
+ align-items: center;
9
+ .closeButton {
10
+ position: absolute;
11
+ right: 6px;
12
+ top: 0px;
13
+ }
14
+ .contentWrapper {
15
+ display: flex;
16
+ width: 100%;
17
+ flex-direction: column;
18
+ justify-content: center;
19
+ align-items: center;
20
+ .textContent {
21
+ margin-top: 8px;
22
+ font-size: 18px;
23
+ font-style: normal;
24
+ font-weight: 700;
25
+ line-height: 20px;
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,70 @@
1
+ import {h, Component} from 'preact';
2
+ import {OnClick} from '@playkit-js/common/dist/hoc/a11y-wrapper';
3
+ import {Button, ButtonType, ButtonSize} from '@playkit-js/common/dist/components/button';
4
+ import {Icon, IconSize} from '@playkit-js/common/dist/icon';
5
+ import {ui} from '@playkit-js/kaltura-player-js';
6
+ // @ts-ignore
7
+ const {withPlayer} = ui.Components;
8
+ const {connect} = ui.redux;
9
+ const {withText, Text} = ui.preacti18n;
10
+ import * as styles from './small-screen-slate.scss';
11
+
12
+ const mapStateToProps = (state: any) => ({
13
+ isMobile: state.shell.isMobile
14
+ });
15
+
16
+ interface SmallScreenSlateProps {
17
+ isMobile?: boolean;
18
+ toggledWithEnter?: boolean;
19
+ smallScreenText?: string;
20
+ smallScreenMobileText?: string;
21
+ hideTranscript?: string;
22
+ player?: any;
23
+ onClose: OnClick;
24
+ }
25
+
26
+ const translates = {
27
+ smallScreenText: <Text id="transcript.small_screen">To see the transcript, go to full screen</Text>,
28
+ smallScreenMobileText: <Text id="transcript.small_screen_mobile">To see the transcript, rotate the phone</Text>,
29
+ hideTranscript: <Text id="transcript.hide_plugin">Hide Transcript</Text>
30
+ };
31
+
32
+ @withText(translates)
33
+ @withPlayer
34
+ // @ts-ignore
35
+ @connect(mapStateToProps)
36
+ export class SmallScreenSlate extends Component<SmallScreenSlateProps> {
37
+ render() {
38
+ const {isMobile, smallScreenMobileText, smallScreenText, onClose, toggledWithEnter, player, hideTranscript} = this.props;
39
+ return (
40
+ <div className={styles.smallScreenWrapper} data-testid="transcript_smallScreenWrapper">
41
+ <Button
42
+ icon={'close'}
43
+ onClick={onClose}
44
+ type={ButtonType.borderless}
45
+ focusOnMount={toggledWithEnter}
46
+ className={styles.closeButton}
47
+ ariaLabel={hideTranscript}
48
+ testId="transcript_smallScreenClose"
49
+ />
50
+ <div className={styles.contentWrapper}>
51
+ {isMobile ? (
52
+ <Icon name={'screenRotation'} size={IconSize.large} />
53
+ ) : (
54
+ <Button
55
+ icon={'expand'}
56
+ onClick={() => player?.enterFullscreen()}
57
+ type={ButtonType.borderless}
58
+ size={ButtonSize.medium}
59
+ ariaLabel={smallScreenText}
60
+ testId="transcript_smallScreenFullscreen"
61
+ />
62
+ )}
63
+ <div className={styles.textContent} data-testid="transcript_smallScreenTextContent">
64
+ {isMobile ? smallScreenMobileText : smallScreenText}
65
+ </div>
66
+ </div>
67
+ </div>
68
+ );
69
+ }
70
+ }
@@ -1,4 +1,5 @@
1
1
  import {h, Component} from 'preact';
2
+ import {ui} from '@playkit-js/kaltura-player-js';
2
3
  import {debounce} from '../../utils';
3
4
  import * as styles from './transcript.scss';
4
5
  import {Spinner} from '../spinner';
@@ -8,12 +9,16 @@ import {HighlightedMap, CuePointData} from '../../types';
8
9
  import {ErrorIcon} from './error-icon';
9
10
  import {AutoscrollButton} from '../autoscroll-button';
10
11
  import {TranscriptMenu} from '../transcript-menu';
11
-
12
+ import {SmallScreenSlate} from '../small-screen-slate';
12
13
  import {Button, ButtonType, ButtonSize} from '@playkit-js/common/dist/components/button';
13
14
  import {OnClickEvent, OnClick} from '@playkit-js/common/dist/hoc/a11y-wrapper';
14
15
 
15
- const {ENTER, SPACE, TAB, ESC} = KalturaPlayer.ui.utils.KeyMap;
16
- const {withText, Text} = KalturaPlayer.ui.preacti18n;
16
+ const {ENTER, SPACE, TAB, ESC} = ui.utils.KeyMap;
17
+ const {withText, Text} = ui.preacti18n;
18
+
19
+ const {SidePanelModes} = ui;
20
+ const {PLAYER_BREAK_POINTS} = ui.Components;
21
+ const {connect} = ui.redux;
17
22
 
18
23
  const translates = {
19
24
  skipTranscript: <Text id="transcript.skip_transcript">Skip transcript</Text>,
@@ -45,6 +50,8 @@ export interface TranscriptProps {
45
50
  onDownload: () => void;
46
51
  printDisabled: boolean;
47
52
  onPrint: () => void;
53
+ smallScreen?: boolean;
54
+ expandMode?: string;
48
55
  }
49
56
 
50
57
  interface TranscriptState {
@@ -67,6 +74,12 @@ const initialSearch = {
67
74
 
68
75
  const SEARCHBAR_HEIGHT = 38; // height of search bar with margins
69
76
 
77
+ const mapStateToProps = (state: any, ownProps: Pick<TranscriptProps, 'expandMode'>) => ({
78
+ smallScreen: ownProps.expandMode === SidePanelModes.ALONGSIDE && state.shell.playerClientRect?.width < PLAYER_BREAK_POINTS.SMALL
79
+ });
80
+
81
+ // @ts-ignore
82
+ @connect(mapStateToProps)
70
83
  @withText(translates)
71
84
  export class Transcript extends Component<TranscriptProps, TranscriptState> {
72
85
  private _transcriptListRef: HTMLElement | null = null;
@@ -364,7 +377,7 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
364
377
  };
365
378
 
366
379
  render(props: TranscriptProps) {
367
- const {isLoading, kitchenSinkActive, hasError} = props;
380
+ const {isLoading, kitchenSinkActive, hasError, smallScreen, toggledWithEnter} = props;
368
381
  const renderTranscriptButtons = !(isLoading || hasError);
369
382
  return (
370
383
  <div
@@ -374,21 +387,25 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
374
387
  }}
375
388
  onKeyUp={this._handleEsc}
376
389
  data-testid="transcript_root">
377
- <div className={styles.globalContainer}>
378
- {this._renderHeader()}
379
-
380
- {renderTranscriptButtons && this._renderSkipTranscriptButton()}
381
- <div
382
- className={styles.body}
383
- onScroll={this._onScroll}
384
- ref={node => {
385
- this._transcriptListRef = node;
386
- }}
387
- data-testid="transcript_list">
388
- {isLoading ? this._renderLoading() : this._renderTranscript()}
390
+ {smallScreen ? (
391
+ <SmallScreenSlate onClose={this.props.onClose} toggledWithEnter={toggledWithEnter} />
392
+ ) : (
393
+ <div className={styles.globalContainer}>
394
+ {this._renderHeader()}
395
+
396
+ {renderTranscriptButtons && this._renderSkipTranscriptButton()}
397
+ <div
398
+ className={styles.body}
399
+ onScroll={this._onScroll}
400
+ ref={node => {
401
+ this._transcriptListRef = node;
402
+ }}
403
+ data-testid="transcript_list">
404
+ {isLoading ? this._renderLoading() : this._renderTranscript()}
405
+ </div>
406
+ {renderTranscriptButtons && this._renderScrollToButton()}
389
407
  </div>
390
- {renderTranscriptButtons && this._renderScrollToButton()}
391
- </div>
408
+ )}
392
409
  </div>
393
410
  );
394
411
  }
@@ -228,6 +228,7 @@ export class TranscriptPlugin extends KalturaPlayer.core.BasePlugin {
228
228
  highlightedMap={this._activeCuePointsMap}
229
229
  onSeek={this._seekTo}
230
230
  onItemClicked={this._seekTo}
231
+ expandMode={this.config.expandMode}
231
232
  captions={this._data}
232
233
  isLoading={this._isLoading}
233
234
  hasError={this._hasError}
@@ -32,7 +32,7 @@ const makeHoursString = (seconds: number): string => {
32
32
  return '';
33
33
  };
34
34
 
35
- export const secontsToTime = (seconds: number, longerThanHour: boolean): string => {
35
+ export const secondsToTime = (seconds: number, longerThanHour: boolean): string => {
36
36
  const date = new Date(0);
37
37
  date.setSeconds(seconds);
38
38
  return `${longerThanHour ? makeHoursString(seconds) : ''}${pad(date.getUTCMinutes())}:${pad(date.getUTCSeconds())}`;
@@ -14,7 +14,9 @@
14
14
  "auto_scroll": "Resume AutoScroll",
15
15
  "whoops": "Whoops!",
16
16
  "load_failed": "Failed to load transcript",
17
- "skip_transcript": "Skip transcript"
17
+ "skip_transcript": "Skip transcript",
18
+ "smallScreenText": "To see the transcript, go to full screen",
19
+ "smallScreenMobileText": "To see the transcript, rotate the phone"
18
20
  }
19
21
  }
20
22
  }
@@ -1,15 +0,0 @@
1
- import { h } from 'preact';
2
-
3
- export const AutoScrollIcon = () => (
4
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5
- <path
6
- d="M6.29289 15.2929C6.65338 14.9324 7.22061 14.9047 7.6129 15.2097L7.70711 15.2929L12 19.585L16.2929 15.2929C16.6534 14.9324 17.2206 14.9047 17.6129 15.2097L17.7071 15.2929C18.0676 15.6534 18.0953 16.2206 17.7903 16.6129L17.7071 16.7071L12.7071 21.7071C12.3466 22.0676 11.7794 22.0953 11.3871 21.7903L11.2929 21.7071L6.29289 16.7071C5.90237 16.3166 5.90237 15.6834 6.29289 15.2929Z"
7
- fill="white"
8
- />
9
- <path
10
- d="M17.7071 8.70711C17.3466 9.06759 16.7794 9.09532 16.3871 8.7903L16.2929 8.70711L12 4.415L7.70711 8.70711C7.34662 9.06759 6.77939 9.09532 6.3871 8.79029L6.29289 8.70711C5.93241 8.34662 5.90468 7.77939 6.2097 7.3871L6.29289 7.29289L11.2929 2.29289C11.6534 1.93241 12.2206 1.90468 12.6129 2.2097L12.7071 2.29289L17.7071 7.29289C18.0976 7.68342 18.0976 8.31658 17.7071 8.70711Z"
11
- fill="white"
12
- />
13
- <rect x="10" y="10" width="4" height="4" rx="2" fill="white" />
14
- </svg>
15
- );