@playkit-js/transcript 3.4.1-canary.1-d2c93cc → 3.4.1-canary.5-8a9a5ea

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.1-canary.1-d2c93cc",
3
+ "version": "3.4.1-canary.5-8a9a5ea",
4
4
  "main": "dist/playkit-transcript.js",
5
5
  "license": "AGPL-3.0",
6
6
  "private": false,
@@ -2,7 +2,6 @@
2
2
 
3
3
  .popover-anchor-container {
4
4
  cursor: pointer;
5
- margin-left: 8px;
6
5
  border-radius: $roundness-1;
7
6
 
8
7
  &:hover {
@@ -54,8 +53,12 @@
54
53
  padding: 9px 24px 9px 16px;
55
54
  white-space: nowrap;
56
55
  margin: 4px;
56
+
57
+ &.popover-menu-item-disabled {
58
+ color: $tone-4-color;
59
+ }
57
60
 
58
- &:hover {
61
+ &:hover :not(.popover-menu-item-disabled) {
59
62
  background-color: $tone-6-color;
60
63
  border-radius: $roundness-1;
61
64
  cursor: pointer;
@@ -1,8 +1,10 @@
1
1
  import {A11yWrapper} from '@playkit-js/common/dist/hoc/a11y-wrapper';
2
2
  import {h, Component, VNode} from 'preact';
3
3
 
4
+ const {Tooltip} = KalturaPlayer.ui.components;
5
+
4
6
  const {withEventManager} = KalturaPlayer.ui.Event;
5
- const {ENTER, ESC, SPACE} = KalturaPlayer.ui.utils.KeyMap;
7
+ const {TAB} = KalturaPlayer.ui.utils.KeyMap;
6
8
 
7
9
  import * as styles from './popover-menu.scss';
8
10
 
@@ -10,9 +12,11 @@ interface PopoverMenuItemData {
10
12
  testId: string;
11
13
  label: string;
12
14
  onClick: () => void;
15
+ isDisabled?: boolean;
13
16
  }
14
17
 
15
18
  interface PopoverMenuProps {
19
+ label: string;
16
20
  eventManager?: any;
17
21
  children?: VNode;
18
22
  items: Array<PopoverMenuItemData>;
@@ -26,6 +30,7 @@ interface PopoverMenuState {
26
30
  class PopoverMenu extends Component<PopoverMenuProps, PopoverMenuState> {
27
31
  private _controlElementRef: HTMLDivElement | null = null;
28
32
  private _popoverElementRef: HTMLDivElement | null = null;
33
+ private _itemsRefMap: Map<number, HTMLDivElement | null> = new Map();
29
34
 
30
35
  eventManager: any;
31
36
 
@@ -34,7 +39,11 @@ class PopoverMenu extends Component<PopoverMenuProps, PopoverMenuState> {
34
39
  this.state = {isOpen: false};
35
40
 
36
41
  this.props.eventManager?.listen(document, 'click', this.handleMouseEvent);
37
- this.props.eventManager?.listen(document, 'keydown', this.handleKeyboardEvent);
42
+ this.props.eventManager?.listen(document, 'keydown', this.handleKeydownEvent);
43
+ }
44
+
45
+ componentWillUnmount() {
46
+ this._itemsRefMap = new Map();
38
47
  }
39
48
 
40
49
  private handleMouseEvent = (event: MouseEvent) => {
@@ -43,33 +52,57 @@ class PopoverMenu extends Component<PopoverMenuProps, PopoverMenuState> {
43
52
  }
44
53
  };
45
54
 
46
- private handleKeyboardEvent = (event: KeyboardEvent) => {
47
- if (this._controlElementRef?.contains(event.target as Node | null) && [ENTER, SPACE].includes(event.keyCode)) {
48
- // use handler of control element
49
- event.preventDefault();
50
- return;
51
- }
52
- if (this._popoverElementRef?.contains(event.target as Node | null) && event.keyCode !== ESC) {
53
- // use handler of popover element
54
- return;
55
+ private handleKeydownEvent = (event: KeyboardEvent) => {
56
+ const eventTarget = event.target as Node | null;
57
+ if (
58
+ this.state.isOpen &&
59
+ event.keyCode === TAB &&
60
+ !this._controlElementRef?.contains(eventTarget) &&
61
+ !this._popoverElementRef?.contains(eventTarget)
62
+ ) {
63
+ this.closePopover();
55
64
  }
56
- this.closePopover();
65
+ };
66
+
67
+ private _handleUpKeyPressed = (currentIndex: number) => () => {
68
+ this._getItemRef(currentIndex - 1)?.focus();
69
+ };
70
+
71
+ private _handleDownKeyPressed = (currentIndex: number) => () => {
72
+ this._getItemRef(currentIndex + 1)?.focus();
57
73
  };
58
74
 
59
75
  private closePopover() {
60
76
  this.setState({isOpen: false});
61
77
  }
62
78
 
63
- private togglePopover = () => {
64
- this.setState({isOpen: !this.state.isOpen});
79
+ private togglePopover = (focusFirstItem: boolean) => {
80
+ const isOpen = !this.state.isOpen;
81
+
82
+ this.setState({isOpen}, () => {
83
+ if (isOpen && focusFirstItem) {
84
+ const firstNonDisabledItem = this.props.items.findIndex((item: PopoverMenuItemData) => !item.isDisabled);
85
+ if (firstNonDisabledItem !== -1) {
86
+ this._getItemRef(firstNonDisabledItem)?.focus();
87
+ }
88
+ }
89
+ });
90
+ };
91
+
92
+ private _getItemRef = (index: number) => {
93
+ return this._itemsRefMap.get(index);
94
+ };
95
+
96
+ private _setItemRef = (index: number, ref: HTMLDivElement | null) => {
97
+ return this._itemsRefMap.set(index, ref);
65
98
  };
66
99
 
67
100
  render() {
68
- const {children, items} = this.props;
101
+ const {label, children, items} = this.props;
69
102
 
70
- return (
103
+ const popoverMenuContent = (
71
104
  <div className={styles.popoverContainer}>
72
- <A11yWrapper onClick={this.togglePopover}>
105
+ <A11yWrapper onClick={() => this.togglePopover(true)}>
73
106
  <div
74
107
  data-testid="popover-anchor-container"
75
108
  className={`${styles.popoverAnchorContainer} ${this.state.isOpen ? styles.active : ''}`}
@@ -80,17 +113,42 @@ class PopoverMenu extends Component<PopoverMenuProps, PopoverMenuState> {
80
113
  </div>
81
114
  </A11yWrapper>
82
115
 
83
- <div className={styles.popoverComponent} role="menu" aria-expanded={this.state.isOpen}>
116
+ <div
117
+ className={styles.popoverComponent}
118
+ role="menu"
119
+ aria-expanded={this.state.isOpen}
120
+ ref={node => {
121
+ this._popoverElementRef = node;
122
+ }}>
84
123
  {this.state.isOpen
85
- ? items.map(({label, onClick, testId}) => {
124
+ ? items.map(({label, onClick, testId, isDisabled}, index) => {
86
125
  return (
87
126
  <A11yWrapper
88
127
  onClick={() => {
89
- this.closePopover();
90
- onClick();
128
+ if (!isDisabled) {
129
+ this.closePopover();
130
+ onClick();
131
+ }
132
+ }}
133
+ onDownKeyPressed={() => {
134
+ if (!isDisabled) {
135
+ this._handleDownKeyPressed(index);
136
+ }
137
+ }}
138
+ onUpKeyPressed={() => {
139
+ if (!isDisabled) {
140
+ this._handleUpKeyPressed(index);
141
+ }
91
142
  }}>
92
143
  {
93
- <div tabIndex={0} role="menuitem" className={styles.popoverMenuItem} data-testid={testId}>
144
+ <div
145
+ tabIndex={isDisabled ? -1 : 0}
146
+ role="menuitem"
147
+ className={`${styles.popoverMenuItem} ${isDisabled ? styles.popoverMenuItemDisabled : ''}`}
148
+ data-testid={testId}
149
+ ref={node => {
150
+ this._setItemRef(index, node);
151
+ }}>
94
152
  {label}
95
153
  </div>
96
154
  }
@@ -101,6 +159,14 @@ class PopoverMenu extends Component<PopoverMenuProps, PopoverMenuState> {
101
159
  </div>
102
160
  </div>
103
161
  );
162
+
163
+ return this.state.isOpen ? (
164
+ popoverMenuContent
165
+ ) : (
166
+ <div>
167
+ <Tooltip label={label}>{popoverMenuContent}</Tooltip>
168
+ </div>
169
+ );
104
170
  }
105
171
  }
106
172
 
@@ -61,6 +61,8 @@
61
61
  padding-left: 16px;
62
62
  font-size: 16px;
63
63
  padding-right: 16px;
64
+ gap: 8px;
65
+ z-index: 2;
64
66
  }
65
67
 
66
68
  .body {
@@ -183,7 +183,7 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
183
183
  };
184
184
 
185
185
  private _renderHeader = () => {
186
- const {toggledWithEnter, kitchenSinkActive, downloadDisabled, onDownload, printDisabled, onPrint} = this.props;
186
+ const {toggledWithEnter, kitchenSinkActive, downloadDisabled, onDownload, printDisabled, onPrint, isLoading} = this.props;
187
187
  const {search, activeSearchIndex, totalSearchResults} = this.state;
188
188
  return (
189
189
  <div className={[styles.header, this._getHeaderStyles()].join(' ')} data-testid="transcript_header">
@@ -196,13 +196,14 @@ export class Transcript extends Component<TranscriptProps, TranscriptState> {
196
196
  toggledWithEnter={toggledWithEnter}
197
197
  kitchenSinkActive={kitchenSinkActive}
198
198
  />
199
- <TranscriptMenu {...{downloadDisabled, onDownload, printDisabled, onPrint}} />
199
+ <TranscriptMenu {...{downloadDisabled, onDownload, printDisabled, onPrint, isLoading}} />
200
200
  <div data-testid="transcriptCloseButton">
201
201
  <Button
202
202
  type={ButtonType.borderless}
203
203
  size={ButtonSize.medium}
204
204
  disabled={false}
205
205
  onClick={this.props.onClose}
206
+ ariaLabel={'Hide Transcript'}
206
207
  tooltip={{label: 'Hide Transcript'}}
207
208
  icon={'close'}></Button>
208
209
  </div>
@@ -12,10 +12,10 @@ interface TranscriptMenuProps {
12
12
  onPrint: () => void;
13
13
  downloadDisabled?: boolean;
14
14
  printDisabled?: boolean;
15
+ isLoading?: boolean;
15
16
  }
16
17
 
17
18
  interface TranscriptMenuState {
18
- isOpen: boolean;
19
19
  items: Array<PopoverMenuItemData>;
20
20
  }
21
21
 
@@ -23,13 +23,14 @@ class TranscriptMenu extends Component<TranscriptMenuProps, TranscriptMenuState>
23
23
  constructor(props: TranscriptMenuProps) {
24
24
  super();
25
25
 
26
- const {downloadDisabled, onDownload, printDisabled, onPrint, printDownloadAreaLabel, printTranscript, downloadTranscript} = props;
26
+ const {downloadDisabled, onDownload, printDisabled, onPrint, printDownloadAreaLabel, printTranscript, downloadTranscript, isLoading} = props;
27
27
  const items = [];
28
28
  if (!downloadDisabled) {
29
29
  items.push({
30
30
  testId: 'download-menu-item',
31
31
  label: 'Download transcript',
32
- onClick: onDownload
32
+ onClick: onDownload,
33
+ isDisabled: isLoading
33
34
  });
34
35
  }
35
36
 
@@ -37,16 +38,17 @@ class TranscriptMenu extends Component<TranscriptMenuProps, TranscriptMenuState>
37
38
  items.push({
38
39
  testId: 'print-menu-item',
39
40
  label: 'Print transcript',
40
- onClick: onPrint
41
+ onClick: onPrint,
42
+ isDisabled: isLoading
41
43
  });
42
44
  }
43
45
 
44
- this.state = {isOpen: false, items};
46
+ this.state = {items};
45
47
  }
46
48
 
47
49
  render() {
48
50
  return this.state.items.length ? (
49
- <PopoverMenu items={this.state.items}>
51
+ <PopoverMenu label={'More'} items={this.state.items}>
50
52
  <Button type={ButtonType.borderless} icon={'more'}></Button>
51
53
  </PopoverMenu>
52
54
  ) : null;