@playkit-js/transcript 2.1.4 → 2.1.5-canary.16-1ac3e09

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +5 -5
  3. package/README.md +122 -24
  4. package/dist/1501adfdf5c835667ce7.svg +9 -0
  5. package/dist/301e7a199b2cd06c2edf.svg +9 -0
  6. package/dist/33bce27c0f546e80478c.svg +36 -0
  7. package/dist/6a4867d3d9170cc2a24d.svg +9 -0
  8. package/dist/73bab0af28a1c7aed29f.svg +9 -0
  9. package/dist/84087eb1cff72e5e6bd3.svg +9 -0
  10. package/dist/95d7192dc427afb678d0.svg +9 -0
  11. package/dist/cea5d6a7f050cbd199a1.svg +9 -0
  12. package/dist/d93f06ff32cdfcd016df.svg +9 -0
  13. package/dist/e5496f4c01207db44ffc.svg +9 -0
  14. package/dist/playkit-transcript.js +1 -31
  15. package/dist/playkit-transcript.js.map +1 -1
  16. package/package.json +53 -50
  17. package/src/components/a11y-wrapper/a11y-wrapper.ts +26 -0
  18. package/src/components/a11y-wrapper/index.ts +1 -0
  19. package/src/components/caption/caption.scss +1 -1
  20. package/src/components/caption/caption.tsx +118 -140
  21. package/src/components/caption/index.ts +1 -1
  22. package/src/components/caption-list/captionList.scss +8 -8
  23. package/src/components/caption-list/captionList.tsx +115 -117
  24. package/src/components/caption-list/index.ts +1 -1
  25. package/src/components/close-button/close-button.scss +11 -0
  26. package/src/components/close-button/index.tsx +23 -0
  27. package/src/components/download-print-menu/download-print-menu.scss +49 -48
  28. package/src/components/download-print-menu/download-print-menu.tsx +147 -125
  29. package/src/components/download-print-menu/index.ts +1 -1
  30. package/src/components/icons/index.ts +11 -0
  31. package/src/components/plugin-button/plugin-button.scss +26 -0
  32. package/src/components/plugin-button/plugin-button.tsx +29 -0
  33. package/src/components/popover-menu/index.ts +1 -1
  34. package/src/components/popover-menu/popover-menu.scss +3 -3
  35. package/src/components/popover-menu/popover-menu.tsx +25 -25
  36. package/src/components/search/index.ts +1 -1
  37. package/src/components/search/search.scss +1 -1
  38. package/src/components/search/search.tsx +137 -144
  39. package/src/components/spinner/index.ts +1 -1
  40. package/src/components/spinner/spinner.scss +58 -50
  41. package/src/components/spinner/spinner.tsx +9 -9
  42. package/src/components/transcript/index.ts +1 -1
  43. package/src/components/transcript/transcript.scss +9 -33
  44. package/src/components/transcript/transcript.tsx +333 -454
  45. package/src/global.d.ts +6 -6
  46. package/src/index.ts +13 -1
  47. package/src/transcript-plugin.scss +3 -3
  48. package/src/transcript-plugin.tsx +210 -391
  49. package/src/types/index.ts +3 -0
  50. package/src/types/transcript-config.ts +11 -0
  51. package/src/types/transcript-item-data.ts +29 -0
  52. package/src/types/types-ui.ts +11 -0
  53. package/src/utils/debounce.ts +36 -0
  54. package/src/utils/index.ts +4 -0
  55. package/src/utils/object-utils.ts +34 -0
  56. package/src/utils/popover/popover.scss +30 -0
  57. package/src/utils/popover/popover.tsx +178 -0
  58. package/src/utils/utils.ts +86 -0
  59. package/src/variables.scss +14 -0
  60. package/src/assets/close.svg +0 -10
  61. package/src/utils.ts +0 -192
@@ -1,132 +1,130 @@
1
- import { h, Component } from "preact";
2
- import { ObjectUtils } from "@playkit-js-contrib/common";
3
- import { KeyboardKeys } from "@playkit-js-contrib/ui";
4
- import { Caption, CaptionProps } from "../caption";
5
- import * as styles from "./captionList.scss";
6
- import { CaptionItem, HOUR } from "../../utils";
1
+ import {h, Component} from 'preact';
2
+ import {HOUR} from '../../utils';
3
+ import {Caption} from '../caption';
4
+ import * as styles from './captionList.scss';
5
+ import {HighlightedMap, CuePointData} from '../../types';
7
6
 
8
- const { get } = ObjectUtils;
7
+ const {End, Home} = KalturaPlayer.ui.utils.KeyMap;
9
8
 
10
- interface CaptionListProps {
11
- highlightedMap: Record<number, true>;
12
- captions: CaptionItem[];
13
- seekTo(caption: CaptionItem): void;
14
- isAutoScrollEnabled: boolean;
15
- searchMap: Record<number, Record<string, number>>;
16
- activeSearchIndex: number;
17
- captionProps: CaptionProps;
9
+ export interface CaptionProps {
10
+ showTime: boolean;
11
+ searchLength: number;
12
+ scrollTo(el: HTMLElement): void;
13
+ scrollToSearchMatch(el: HTMLElement): void;
14
+ videoDuration: number;
18
15
  }
19
16
 
20
- export class CaptionList extends Component<CaptionListProps> {
21
- private _currentCaptionRef: any = null;
22
- private _firstCaptionRef: any = null;
23
- private _lastCaptionRef: any = null;
24
- shouldComponentUpdate(nextProps: Readonly<CaptionListProps>) {
25
- const {
26
- highlightedMap,
27
- captions,
28
- searchMap,
29
- activeSearchIndex,
30
- isAutoScrollEnabled,
31
- captionProps
32
- } = this.props
33
- if (
34
- highlightedMap !== nextProps.highlightedMap ||
35
- captions !== nextProps.captions ||
36
- searchMap !== nextProps.searchMap ||
37
- activeSearchIndex !== nextProps.activeSearchIndex ||
38
- isAutoScrollEnabled !== nextProps.isAutoScrollEnabled ||
39
- captionProps.videoDuration !== nextProps.captionProps.videoDuration
40
- ) {
41
- return true;
42
- }
43
- return false;
17
+ export interface Props {
18
+ data: Array<CuePointData>;
19
+ onSeek: (n: CuePointData) => void;
20
+ autoScroll?: boolean;
21
+ onScroll: (n: number) => void;
22
+ widgetWidth: number;
23
+ highlightedMap: HighlightedMap;
24
+ showItemsIcons: boolean;
25
+ listDataContainCaptions?: boolean;
26
+ searchActive: boolean;
27
+ isAutoScrollEnabled: boolean;
28
+ activeSearchIndex: number;
29
+ searchMap: Record<string, Record<string, number>>;
30
+ captionProps: CaptionProps;
31
+ }
32
+ export class CaptionList extends Component<Props> {
33
+ private _currentCaptionRef: any = null;
34
+ private _firstCaptionRef: any = null;
35
+ private _lastCaptionRef: any = null;
36
+ shouldComponentUpdate(nextProps: Readonly<Props>) {
37
+ const {highlightedMap, data, searchMap, activeSearchIndex, isAutoScrollEnabled, captionProps} = this.props;
38
+ if (
39
+ highlightedMap !== nextProps.highlightedMap ||
40
+ data !== nextProps.data ||
41
+ searchMap !== nextProps.searchMap ||
42
+ activeSearchIndex !== nextProps.activeSearchIndex ||
43
+ isAutoScrollEnabled !== nextProps.isAutoScrollEnabled ||
44
+ captionProps.videoDuration !== nextProps.captionProps.videoDuration
45
+ ) {
46
+ return true;
44
47
  }
48
+ return false;
49
+ }
45
50
 
46
- private _handleClick = (caption: CaptionItem) => () => {
47
- const { seekTo } = this.props;
48
- seekTo(caption);
49
- };
51
+ private _handleClick = (caption: CuePointData) => () => {
52
+ const {onSeek} = this.props;
53
+ onSeek(caption);
54
+ };
50
55
 
51
- private _getShouldScroll = (captionId: number) => {
52
- const { isAutoScrollEnabled, highlightedMap } = this.props;
53
- return isAutoScrollEnabled && highlightedMap[captionId];
54
- }
56
+ private _getShouldScroll = (captionId: string) => {
57
+ const {isAutoScrollEnabled, highlightedMap} = this.props;
58
+ return isAutoScrollEnabled && highlightedMap[captionId];
59
+ };
55
60
 
56
- private _getShouldScrollToSearchMatch = (captionId: number) => {
57
- const { isAutoScrollEnabled, searchMap, activeSearchIndex } = this.props;
58
- return !isAutoScrollEnabled && (searchMap[captionId] && searchMap[captionId][activeSearchIndex] !== undefined);
59
- }
61
+ private _getShouldScrollToSearchMatch = (captionId: string) => {
62
+ const {isAutoScrollEnabled, searchMap, activeSearchIndex} = this.props;
63
+ return !isAutoScrollEnabled && searchMap[captionId] && searchMap[captionId][activeSearchIndex] !== undefined;
64
+ };
60
65
 
61
- private _getSearchProps = (captionId: number) => {
62
- const { searchMap, activeSearchIndex, captionProps } = this.props;
63
- const searchProps: any = {};
64
- if (searchMap[captionId]) {
65
- searchProps.indexMap = searchMap[captionId];
66
- searchProps.activeSearchIndex = activeSearchIndex;
67
- searchProps.searchLength = captionProps.searchLength;
68
- }
69
- return searchProps;
66
+ private _getSearchProps = (captionId: string) => {
67
+ const {searchMap, activeSearchIndex, captionProps} = this.props;
68
+ const searchProps: any = {};
69
+ if (searchMap[captionId]) {
70
+ searchProps.indexMap = searchMap[captionId];
71
+ searchProps.activeSearchIndex = activeSearchIndex;
72
+ searchProps.searchLength = captionProps.searchLength;
70
73
  }
74
+ return searchProps;
75
+ };
71
76
 
72
- private _getCaptionProps = (captionData: CaptionItem) => {
73
- const {
74
- highlightedMap,
75
- captionProps,
76
- isAutoScrollEnabled
77
- } = this.props;
78
- const { id } = captionData;
79
- const newCaptionProps = {
80
- showTime: captionProps.showTime,
81
- scrollTo: captionProps.scrollTo,
82
- scrollToSearchMatch: captionProps.scrollToSearchMatch,
83
- key: id,
84
- onClick: this._handleClick(captionData),
85
- caption: captionData,
86
- highlighted: highlightedMap[id],
87
- longerThanHour: captionProps.videoDuration >= HOUR,
88
- shouldScroll: this._getShouldScroll(id),
89
- shouldScrollToSearchMatch: this._getShouldScrollToSearchMatch(id),
90
- isAutoScrollEnabled,
91
- ...this._getSearchProps(id)
92
- }
93
- return newCaptionProps;
94
- }
77
+ private _getCaptionProps = (captionData: CuePointData) => {
78
+ const {highlightedMap, captionProps, isAutoScrollEnabled} = this.props;
79
+ const {id}: {id: string} = captionData;
80
+ const newCaptionProps = {
81
+ showTime: captionProps.showTime,
82
+ scrollTo: captionProps.scrollTo,
83
+ scrollToSearchMatch: captionProps.scrollToSearchMatch,
84
+ key: id,
85
+ onClick: this._handleClick(captionData),
86
+ caption: captionData,
87
+ highlighted: highlightedMap,
88
+ longerThanHour: captionProps.videoDuration >= HOUR,
89
+ shouldScroll: this._getShouldScroll(id),
90
+ shouldScrollToSearchMatch: this._getShouldScrollToSearchMatch(id),
91
+ isAutoScrollEnabled,
92
+ ...this._getSearchProps(id)
93
+ };
94
+ return newCaptionProps;
95
+ };
95
96
 
96
- private _handleKeyUp = (event: KeyboardEvent) => {
97
- if (event.keyCode === KeyboardKeys.End) {
98
- this._lastCaptionRef?._hotspotRef?.focus();
99
- } else if (event.keyCode === KeyboardKeys.Home) {
100
- this._firstCaptionRef?._hotspotRef?.focus();
101
- }
97
+ private _handleKeyUp = (event: KeyboardEvent) => {
98
+ if (event.keyCode === End) {
99
+ this._lastCaptionRef?._hotspotRef?.focus();
100
+ } else if (event.keyCode === Home) {
101
+ this._firstCaptionRef?._hotspotRef?.focus();
102
102
  }
103
+ };
103
104
 
104
- render() {
105
- const { captions } = this.props;
106
- return (
107
- <div
108
- className={styles.transcriptWrapper}
109
- onKeyUp={this._handleKeyUp}
110
- >
111
- {captions.map((captionData, index) => {
112
- const captionProps = this._getCaptionProps(captionData);
113
- return (
114
- <Caption
115
- ref={node => {
116
- if (index === 0) {
117
- this._firstCaptionRef = node;
118
- } else if (index === captions.length - 1) {
119
- this._lastCaptionRef = node;
120
- }
121
- if (captionProps.highlighted) {
122
- this._currentCaptionRef = node;
123
- }
124
- }}
125
- {...captionProps}
126
- />
127
- )
128
- })}
129
- </div>
130
- );
131
- }
105
+ render() {
106
+ const {data} = this.props;
107
+ return (
108
+ <div className={styles.transcriptWrapper} onKeyUp={this._handleKeyUp}>
109
+ {data.map((captionData, index) => {
110
+ const captionProps = this._getCaptionProps(captionData);
111
+ return (
112
+ <Caption
113
+ ref={node => {
114
+ if (index === 0) {
115
+ this._firstCaptionRef = node;
116
+ } else if (index === data.length - 1) {
117
+ this._lastCaptionRef = node;
118
+ }
119
+ if (captionProps.highlighted) {
120
+ this._currentCaptionRef = node;
121
+ }
122
+ }}
123
+ {...captionProps}
124
+ />
125
+ );
126
+ })}
127
+ </div>
128
+ );
129
+ }
132
130
  }
@@ -1 +1 @@
1
- export * from "./captionList";
1
+ export * from './captionList';
@@ -0,0 +1,11 @@
1
+ .close-btn {
2
+ position: absolute;
3
+ top: 13px;
4
+ right: 14px;
5
+ width: 24px;
6
+ height: 24px;
7
+ padding: 0;
8
+ background-color: transparent;
9
+ border: none;
10
+ cursor: pointer;
11
+ }
@@ -0,0 +1,23 @@
1
+ import {h} from 'preact';
2
+ import * as styles from './close-button.scss';
3
+ import {A11yWrapper} from '../a11y-wrapper/a11y-wrapper';
4
+ import {icons} from '../icons';
5
+ const {Icon} = KalturaPlayer.ui.components;
6
+
7
+ interface CloseButtonProps {
8
+ onClick: () => void;
9
+ }
10
+
11
+ export const CloseButton = (props: CloseButtonProps) => (
12
+ <A11yWrapper onClick={props.onClick}>
13
+ <button className={styles.closeBtn} tabIndex={1}>
14
+ <Icon
15
+ id="transcript-plugin-close-button"
16
+ height={icons.BigSize}
17
+ width={icons.BigSize}
18
+ viewBox={`0 0 ${icons.BigSize} ${icons.BigSize}`}
19
+ path={icons.CLOSE_ICON}
20
+ />
21
+ </button>
22
+ </A11yWrapper>
23
+ );
@@ -1,55 +1,56 @@
1
- @import "../../variables.scss";
1
+ @import '../../variables.scss';
2
2
 
3
3
  .download-print-button {
4
- display: inline-block;
5
- width: 36px;
6
- height: 36px;
7
- color: $white-color;
8
- border: none;
9
- cursor: pointer;
10
- padding: 0;
11
- opacity: 0.8;
12
- background: none;
13
- &:hover,
4
+ display: inline-block;
5
+ width: 36px;
6
+ height: 36px;
7
+ color: $white-color;
8
+ border: none;
9
+ cursor: pointer;
10
+ padding: 0;
11
+ background: none;
12
+ border-radius: 4px;
13
+ outline-offset: 0 -1px;
14
+ &:hover,
15
+ &:active {
16
+ border-radius: 4px;
17
+ background-color: rgba(0, 0, 0, 0.8);
18
+ }
19
+ &:focus {
20
+ outline: 1px solid $focus-color;
21
+ }
22
+ .icon {
23
+ width: 100%;
24
+ height: 100%;
25
+ background-position: center;
26
+ background-size: cover;
27
+ }
28
+ .download-icon {
29
+ background-image: url('../../assets/download.svg');
14
30
  &:active {
15
- border-radius: 4px;
16
- background-color: rgba(0, 0, 0, 0.8);
17
- }
18
- &:focus {
19
- outline: 1px solid $focus-color;
20
- }
21
- .icon {
22
- width: 100%;
23
- height: 100%;
24
- background-position: center;
25
- background-size: cover;
31
+ background-image: url('../../assets/download-over.svg');
26
32
  }
27
- .download-icon {
28
- background-image: url('../../assets/download.svg');
29
- &:active {
30
- background-image: url('../../assets/download-over.svg');
31
- }
32
- }
33
- .print-icon {
34
- background-image: url('../../assets/print.svg');
35
- &:active {
36
- background-image: url('../../assets/print-over.svg');
37
- }
33
+ }
34
+ .print-icon {
35
+ background-image: url('../../assets/print.svg');
36
+ &:active {
37
+ background-image: url('../../assets/print-over.svg');
38
38
  }
39
+ }
39
40
  }
40
41
  .popover-menu-item {
41
- display: flex;
42
- align-items: center;
43
- padding: 9px 24px 9px 16px;
44
- white-space: nowrap;
45
- min-height: 30px;
46
- line-height: 18px;
47
- font-size: 15px;
48
- &:hover {
49
- cursor: pointer;
50
- background-color: $semigray-color;
51
- }
52
- &:focus {
53
- outline: 1px solid $focus-color;
54
- }
55
- }
42
+ display: flex;
43
+ align-items: center;
44
+ padding: 9px 24px 9px 16px;
45
+ white-space: nowrap;
46
+ min-height: 30px;
47
+ line-height: 18px;
48
+ font-size: 15px;
49
+ &:hover {
50
+ cursor: pointer;
51
+ background-color: $semigray-color;
52
+ }
53
+ &:focus {
54
+ outline: 1px solid $focus-color;
55
+ }
56
+ }