@playkit-js/transcript 3.2.0-canary.3-a35aaf1 → 3.2.0-canary.4-2b8a565

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.2.0-canary.3-a35aaf1",
3
+ "version": "3.2.0-canary.4-2b8a565",
4
4
  "main": "dist/playkit-transcript.js",
5
5
  "license": "AGPL-3.0",
6
6
  "private": false,
@@ -67,7 +67,8 @@
67
67
  "html5 player"
68
68
  ],
69
69
  "dependencies": {
70
- "@playkit-js/common": "^1.0.7",
70
+ "@playkit-js/common": "^1.0.18",
71
+ "@playkit-js/playkit-js-ui": "^0.73.0",
71
72
  "@playkit-js/ui-managers": "^1.3.2",
72
73
  "cypress": "^12.3.0",
73
74
  "stream-browserify": "^3.0.0"
@@ -0,0 +1,20 @@
1
+ @import '../../variables.scss';
2
+
3
+ .autoscroll-button {
4
+ opacity: 0;
5
+ position: absolute;
6
+ right: 12px;
7
+ bottom: 25px;
8
+ width: 32px;
9
+ height: 32px;
10
+ padding: 4px;
11
+ border-radius: $roundness-1;
12
+ border: none;
13
+ 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);
14
+ background-color: $primary-darker-color;
15
+ cursor: pointer;
16
+ z-index: 1;
17
+ &.autoscroll-button-visible {
18
+ opacity: 1;
19
+ }
20
+ }
@@ -0,0 +1,46 @@
1
+ import {h} from 'preact';
2
+ import * as styles from './autoscroll-button.scss';
3
+ import {A11yWrapper, OnClick} from '@playkit-js/common';
4
+
5
+ const {withText, Text} = KalturaPlayer.ui.preacti18n;
6
+ const {Tooltip} = KalturaPlayer.ui.components;
7
+
8
+ interface AutoscrollButtonProps {
9
+ onClick: OnClick;
10
+ isAutoScrollEnabled: boolean;
11
+ setAutoscrollButtonRef: (node: HTMLDivElement | null) => void;
12
+ autoScrollLabel?: string;
13
+ }
14
+
15
+ const translates = {
16
+ autoScrollLabel: <Text id="transcript.auto_scroll">Resume AutoScroll</Text>
17
+ };
18
+
19
+ export const AutoscrollButton = withText(translates)(
20
+ ({onClick, isAutoScrollEnabled, setAutoscrollButtonRef, autoScrollLabel}: AutoscrollButtonProps) => {
21
+ return (
22
+ <A11yWrapper onClick={onClick}>
23
+ <div
24
+ role="button"
25
+ className={`${styles.autoscrollButton} ${isAutoScrollEnabled ? '' : styles.autoscrollButtonVisible}`}
26
+ tabIndex={isAutoScrollEnabled ? -1 : 1}
27
+ aria-label={autoScrollLabel}
28
+ ref={setAutoscrollButtonRef}>
29
+ <Tooltip label={autoScrollLabel} type="left">
30
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
31
+ <path
32
+ 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"
33
+ fill="white"
34
+ />
35
+ <path
36
+ 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"
37
+ fill="white"
38
+ />
39
+ <rect x="10" y="10" width="4" height="4" rx="2" fill="white" />
40
+ </svg>
41
+ </Tooltip>
42
+ </div>
43
+ </A11yWrapper>
44
+ );
45
+ }
46
+ );
@@ -0,0 +1 @@
1
+ export * from './autoscroll-button';
@@ -6,7 +6,7 @@
6
6
  width: 100%;
7
7
  margin-bottom: 9px;
8
8
  margin-left: 8px;
9
- color: $white-color;
9
+ color: $tone-1-color;
10
10
  .caption-time {
11
11
  flex-shrink: 1;
12
12
  min-width: 48px;
@@ -15,7 +15,7 @@
15
15
  padding-top: 2px;
16
16
  text-align: right;
17
17
  font-size: 12px;
18
- color: $gray-color;
18
+ color: $tone-2-color;
19
19
  }
20
20
  .caption-content {
21
21
  flex-grow: 1;
@@ -25,20 +25,19 @@
25
25
  user-select: text;
26
26
  &:hover {
27
27
  .caption-span {
28
- background-color: $semigray-color;
28
+ background-color: $tone-6-color;
29
29
  }
30
30
  &.highlighted {
31
31
  .caption-span {
32
- color: $white-color;
33
- background-color: $main-color-darken;
32
+ background-color: $primary-darker-color;
34
33
  padding: 0 2px;
35
34
  }
36
35
  }
37
36
  }
38
37
  &.highlighted {
39
38
  .caption-span {
40
- color: $black-color;
41
- background-color: $main-color;
39
+ color: $primary-text-contrast-color;
40
+ background-color: $primary-color;
42
41
  padding: 0 2px;
43
42
  }
44
43
  }
@@ -51,27 +50,27 @@
51
50
  border-radius: 2px;
52
51
  cursor: pointer;
53
52
  &::selection {
54
- background-color: $text-selection-color;
53
+ background-color: $primary-brighter-color;
55
54
  padding: 0 2px;
56
55
  }
57
56
  & > span::selection {
58
- background-color: $text-selection-color;
57
+ background-color: $primary-brighter-color;
59
58
  }
60
59
  }
61
60
  .highlight-search {
62
- color: $black-color;
63
- background-color: $text-match-color;
61
+ color: $secondary-text-contrast-color;
62
+ background-color: $secondary-color;
64
63
  border-radius: 2px;
65
64
  &::selection {
66
- background-color: $text-selection-color;
65
+ background-color: $primary-brighter-color;
67
66
  }
68
67
  }
69
68
  .active-search {
70
- color: $black-color;
71
- background-color: $text-current-match-color;
69
+ color: $secondary-text-contrast-color;
70
+ background-color: $primary-darker-color;
72
71
  border-radius: 2px;
73
72
  &::selection {
74
- background-color: $text-selection-color;
73
+ background-color: $primary-brighter-color;
75
74
  }
76
75
  }
77
76
  }
@@ -1,6 +1,6 @@
1
1
  .close-btn {
2
2
  position: absolute;
3
- top: 13px;
3
+ top: 20px;
4
4
  right: 14px;
5
5
  width: 24px;
6
6
  height: 24px;
@@ -2,6 +2,6 @@
2
2
 
3
3
  .pluginButton {
4
4
  &.active {
5
- background-color: $darken-gray;
5
+ background-color: $tone-6-color;
6
6
  }
7
7
  }
@@ -19,8 +19,10 @@ export const PluginButton = ({isActive, onClick, label, id, icon, dataTestId}: P
19
19
  return (
20
20
  <Tooltip label={label} type="bottom">
21
21
  <A11yWrapper onClick={onClick}>
22
- <button aria-label={label} className={[ui.style.upperBarIcon, styles.pluginButton, isActive ? styles.active : ''].join(' ')}
23
- data-testid={dataTestId}>
22
+ <button
23
+ aria-label={label}
24
+ className={[ui.style.upperBarIcon, styles.pluginButton, isActive ? styles.active : ''].join(' ')}
25
+ data-testid={dataTestId}>
24
26
  <Icon id={id} height={icons.BigSize} width={icons.BigSize} viewBox={`0 0 ${icons.BigSize} ${icons.BigSize}`} path={icon} />
25
27
  </button>
26
28
  </A11yWrapper>
@@ -29,5 +31,5 @@ export const PluginButton = ({isActive, onClick, label, id, icon, dataTestId}: P
29
31
  };
30
32
 
31
33
  PluginButton.defaultProps = {
32
- dataTestId: "transcript_pluginButton"
33
- }
34
+ dataTestId: 'transcript_pluginButton'
35
+ };
@@ -1,8 +1,5 @@
1
1
  import {h, Component} from 'preact';
2
- import {A11yWrapper, OnClickEvent} from '@playkit-js/common';
3
- import * as styles from './search.scss';
4
- import {debounce} from '../../utils';
5
- const DEBOUNCE_TIMEOUT = 300;
2
+ import {InputField} from '@playkit-js/common';
6
3
 
7
4
  const {withText, Text} = KalturaPlayer.ui.preacti18n;
8
5
  const translates = ({activeSearchIndex, totalSearchResults}: SearchProps) => ({
@@ -24,12 +21,11 @@ const translates = ({activeSearchIndex, totalSearchResults}: SearchProps) => ({
24
21
 
25
22
  export interface SearchProps {
26
23
  onChange(value: string): void;
27
- searchQuery: string;
24
+ value: string;
28
25
  kitchenSinkActive: boolean;
29
26
  toggledWithEnter: boolean;
30
27
 
31
28
  onSearchIndexChange: (index: number) => void;
32
- value: string;
33
29
  activeSearchIndex: number;
34
30
  totalSearchResults: number;
35
31
 
@@ -40,36 +36,16 @@ export interface SearchProps {
40
36
  searchResultsLabel?: string;
41
37
  }
42
38
 
43
- interface SearchState {
44
- active: boolean;
45
- focused: boolean;
46
- }
47
-
48
- class SearchComponent extends Component<SearchProps, SearchState> {
49
- state: SearchState = {
50
- active: false,
51
- focused: false
52
- };
53
- private _inputRef: null | HTMLInputElement = null;
54
- private _focusedByMouse = false;
55
- private _debouncedOnChange: (value: string) => void;
56
- constructor(props: SearchProps) {
57
- super(props);
58
- this._debouncedOnChange = debounce(props.onChange, DEBOUNCE_TIMEOUT);
59
- this.state = {
60
- active: false,
61
- focused: false
62
- };
63
- }
39
+ class SearchComponent extends Component<SearchProps> {
40
+ private _inputField: InputField | null = null;
64
41
 
65
- shouldComponentUpdate(nextProps: Readonly<SearchProps>, nextState: Readonly<SearchState>) {
42
+ shouldComponentUpdate(nextProps: Readonly<SearchProps>) {
66
43
  const {value, activeSearchIndex, totalSearchResults, kitchenSinkActive} = this.props;
67
44
  if (
68
45
  value !== nextProps.value ||
69
46
  activeSearchIndex !== nextProps.activeSearchIndex ||
70
47
  totalSearchResults !== nextProps.totalSearchResults ||
71
- kitchenSinkActive !== nextProps.kitchenSinkActive ||
72
- this.state.active !== nextState.active
48
+ kitchenSinkActive !== nextProps.kitchenSinkActive
73
49
  ) {
74
50
  return true;
75
51
  }
@@ -78,176 +54,30 @@ class SearchComponent extends Component<SearchProps, SearchState> {
78
54
  componentDidUpdate(previousProps: Readonly<SearchProps>): void {
79
55
  const {kitchenSinkActive, toggledWithEnter} = this.props;
80
56
  if (!previousProps.kitchenSinkActive && kitchenSinkActive && toggledWithEnter) {
81
- this._inputRef?.focus();
57
+ this._inputField?.setFocus();
82
58
  }
83
59
  }
84
60
 
85
- private _handleOnChange = (e: any) => {
86
- this.props.onChange(e.target.value);
87
- };
88
-
89
- private _onClear = (event: OnClickEvent, byKeyboard?: boolean) => {
90
- if (!byKeyboard) {
91
- this._focusedByMouse = true;
92
- }
93
- this._inputRef?.focus();
94
- this.props.onChange('');
95
- };
96
-
97
- private _onFocus = () => {
98
- this.setState({
99
- active: true,
100
- focused: !this._focusedByMouse
101
- });
102
- this._focusedByMouse = false;
103
- };
104
-
105
- private _onBlur = () => {
106
- this.setState({
107
- active: false,
108
- focused: false
109
- });
110
- };
111
-
112
- private _goToNextSearchResult = () => {
113
- const {activeSearchIndex, totalSearchResults, onSearchIndexChange} = this.props;
114
- if (totalSearchResults === 0) {
115
- return;
116
- }
117
- let index = 0;
118
- if (activeSearchIndex !== totalSearchResults) {
119
- index = this.props.activeSearchIndex + 1;
120
- } else {
121
- index = 1;
122
- }
123
- onSearchIndexChange(index);
124
- };
125
- private _goToPrevSearchResult = () => {
126
- const {activeSearchIndex, totalSearchResults, onSearchIndexChange} = this.props;
127
- let index = 0;
128
- if (activeSearchIndex !== 1) {
129
- index = activeSearchIndex - 1;
130
- } else {
131
- index = totalSearchResults;
132
- }
133
- onSearchIndexChange(index);
134
- };
135
-
136
- _handleMouseDown = () => {
137
- this._focusedByMouse = true;
138
- };
139
-
140
61
  render() {
141
- const {searchQuery, totalSearchResults, activeSearchIndex} = this.props;
62
+ const {value, totalSearchResults, activeSearchIndex, onChange, onSearchIndexChange} = this.props;
142
63
  return (
143
- <div
144
- className={[styles.searchWrapper, searchQuery || this.state.active ? styles.active : '', this.state.focused ? styles.focused : ''].join(' ')}
145
- data-testid="transcript_searchBar">
146
- <div className={styles.searchIcon}>
147
- <svg
148
- width="32px"
149
- height="32px"
150
- viewBox="0 0 32 32"
151
- version="1.1"
152
- xmlns="http://www.w3.org/2000/svg"
153
- xmlnsXlink="http://www.w3.org/1999/xlink">
154
- <g id="Icons/32/serch" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
155
- <path
156
- d="M15.1578947,8 C19.1110908,8 22.3157895,11.2046986 22.3157895,15.1578947 C22.3157895,16.8311546 21.7416502,18.3703171 20.7796271,19.5891266 L24.5954583,23.4045417 C24.9243209,23.7334042 24.9243209,24.2665958 24.5954583,24.5954583 C24.2665958,24.9243209 23.7334042,24.9243209 23.4045417,24.5954583 L19.5891266,20.7796271 C18.3703171,21.7416502 16.8311546,22.3157895 15.1578947,22.3157895 C11.2046986,22.3157895 8,19.1110908 8,15.1578947 C8,11.2046986 11.2046986,8 15.1578947,8 Z M15.1578947,9.68421053 C12.1348624,9.68421053 9.68421053,12.1348624 9.68421053,15.1578947 C9.68421053,18.1809271 12.1348624,20.6315789 15.1578947,20.6315789 C18.1809271,20.6315789 20.6315789,18.1809271 20.6315789,15.1578947 C20.6315789,12.1348624 18.1809271,9.68421053 15.1578947,9.68421053 Z"
157
- id="Shape"
158
- fill="#cccccc"></path>
159
- </g>
160
- </svg>
161
- </div>
162
- <input
163
- className={styles.searchInput}
164
- aria-label={this.props.searchLabel}
165
- placeholder={this.props.searchLabel}
166
- value={searchQuery}
167
- onInput={this._handleOnChange}
168
- onFocus={this._onFocus}
169
- onBlur={this._onBlur}
170
- onMouseDown={this._handleMouseDown}
171
- tabIndex={0}
172
- ref={node => {
173
- this._inputRef = node;
174
- }}
175
- />
176
- {searchQuery && (
177
- <A11yWrapper onClick={this._onClear}>
178
- <button className={styles.clearIcon} tabIndex={0} aria-label={this.props.clearSearchLabel} data-testid="transcript_clearSearchButton">
179
- <svg
180
- width="32px"
181
- height="32px"
182
- viewBox="0 0 32 32"
183
- version="1.1"
184
- xmlns="http://www.w3.org/2000/svg"
185
- xmlnsXlink="http://www.w3.org/1999/xlink">
186
- <g id="Icons/32/Clere" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
187
- <path
188
- 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"
189
- id="Shape"
190
- fill="#cccccc"></path>
191
- </g>
192
- </svg>
193
- </button>
194
- </A11yWrapper>
195
- )}
196
- {searchQuery && (
197
- <div className={styles.searchResults} aria-live="polite" aria-label={this.props.searchResultsLabel} data-testid="transcript_searchResultLabel">{`${
198
- totalSearchResults > 0 ? `${activeSearchIndex}/${totalSearchResults}` : '0/0'
199
- }`}</div>
200
- )}
201
- <div className={styles.prevNextWrapper}>
202
- {searchQuery && (
203
- <A11yWrapper onClick={this._goToPrevSearchResult}>
204
- <button
205
- tabIndex={0}
206
- className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
207
- aria-label={this.props.prevMatchLabel}>
208
- <svg
209
- width="14px"
210
- height="12px"
211
- viewBox="1 0 14 12"
212
- version="1.1"
213
- xmlns="http://www.w3.org/2000/svg"
214
- xmlnsXlink="http://www.w3.org/1999/xlink">
215
- <g id="Icons/16/Arrow/-up" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
216
- <path
217
- 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"
218
- id="Path-2"
219
- fill="#cccccc"
220
- transform="translate(8.000000, 8.519717) scale(1, -1) translate(-8.000000, -8.519717) "></path>
221
- </g>
222
- </svg>
223
- </button>
224
- </A11yWrapper>
225
- )}
226
- {searchQuery && (
227
- <A11yWrapper onClick={this._goToNextSearchResult}>
228
- <button
229
- tabIndex={0}
230
- className={`${styles.prevNextButton} ${totalSearchResults === 0 ? styles.disabled : ''}`}
231
- aria-label={this.props.nextMatchLabel}>
232
- <svg
233
- width="14px"
234
- height="12px"
235
- viewBox="1 2 14 12"
236
- version="1.1"
237
- xmlns="http://www.w3.org/2000/svg"
238
- xmlnsXlink="http://www.w3.org/1999/xlink">
239
- <g id="Icons/16/Arrow/down" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
240
- <path
241
- 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"
242
- id="Path-2"
243
- fill="#cccccc"></path>
244
- </g>
245
- </svg>
246
- </button>
247
- </A11yWrapper>
248
- )}
249
- </div>
250
- </div>
64
+ <InputField
65
+ ref={node => {
66
+ this._inputField = node;
67
+ }}
68
+ value={value}
69
+ onChange={onChange}
70
+ placeholder={this.props.searchLabel}
71
+ clearSearchLabel={this.props.clearSearchLabel}
72
+ searchResults={{
73
+ activeSearchIndex,
74
+ totalSearchResults,
75
+ onSearchIndexChange,
76
+ nextMatchLabel: this.props.nextMatchLabel as string,
77
+ prevMatchLabel: this.props.prevMatchLabel as string,
78
+ searchResultsLabel: this.props.searchResultsLabel as string
79
+ }}
80
+ />
251
81
  );
252
82
  }
253
83
  }
@@ -1,52 +1,16 @@
1
- .transcript-spinner-ball {
2
- position: relative;
1
+ @import '../../variables.scss';
2
+
3
+ .transcript-loader {
3
4
  display: flex;
4
- align-items: center;
5
- width: 100%;
5
+ flex-direction: column;
6
6
  height: 100%;
7
- max-width: 184px;
8
- max-height: 184px;
9
- margin: 4px 0 8px 0;
10
- animation: icon-bounce 2s infinite ease-in-out;
11
- svg {
12
- position: absolute;
13
- top: 0;
14
- right: 0;
15
- }
16
- }
17
-
18
- .bounce-frame {
19
7
  width: 100%;
20
- height: 100%;
21
- min-width: 184px;
22
- min-height: 184px;
23
- border-radius: 50%;
24
- background-color: #cccccc;
25
- opacity: 0.2;
26
-
27
- -webkit-animation: frame-bounce 2s infinite ease-in-out;
8
+ color: $tone-3-color;
9
+ margin: 0;
28
10
  animation: frame-bounce 2s infinite ease-in-out;
29
- }
30
-
31
- @keyframes icon-bounce {
32
- 0%,
33
- 100% {
34
- opacity: 0.3;
35
- }
36
- 50% {
37
- opacity: 1;
38
- }
39
- }
40
-
41
- @-webkit-keyframes frame-bounce {
42
- 0%,
43
- 100% {
44
- -webkit-transform: scale(1);
45
- opacity: 0.1;
46
- }
47
- 50% {
48
- -webkit-transform: scale(1.3);
49
- opacity: 0.1;
11
+ overflow: hidden;
12
+ svg {
13
+ flex-shrink: 0;
50
14
  }
51
15
  }
52
16
 
@@ -54,12 +18,8 @@
54
18
  0%,
55
19
  100% {
56
20
  opacity: 0.1;
57
- transform: scale(1);
58
- -webkit-transform: scale(1);
59
21
  }
60
22
  50% {
61
23
  opacity: 0.25;
62
- transform: scale(1.3);
63
- -webkit-transform: scale(1.3);
64
24
  }
65
25
  }
@@ -1,61 +1,18 @@
1
1
  import {h, Component} from 'preact';
2
2
  import * as styles from './spinner.scss';
3
3
 
4
+ const DEFAULT_LINES = 20;
5
+
4
6
  export class Spinner extends Component {
5
7
  render() {
6
8
  return (
7
- <div className={styles.transcriptSpinnerBall}>
8
- <svg
9
- width="184px"
10
- height="184px"
11
- viewBox="0 0 184 184"
12
- version="1.1"
13
- xmlns="http://www.w3.org/2000/svg"
14
- xmlnsXlink="http://www.w3.org/1999/xlink">
15
- <g id="IL/-transcript/-loder" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
16
- <path
17
- d="M131,37 C133.688755,37 135.881818,39.1223067 135.99538,41.7831104 L136,42 L136,142 C136,144.688755 133.877693,146.881818 131.21689,146.99538 L131,147 L54,147 C51.3112453,147 49.1181819,144.877693 49.0046195,142.21689 L49,142 L49,42 C49,39.3112453 51.1223067,37.1181819 53.7831104,37.0046195 L54,37 L131,37 Z M101.454542,126.814926 L63.4545421,126.814926 C62.3499726,126.814926 61.4545421,127.710356 61.4545421,128.814926 C61.4545421,129.919495 62.3499726,130.814926 63.4545421,130.814926 L63.4545421,130.814926 L101.454542,130.814926 C102.559112,130.814926 103.454542,129.919495 103.454542,128.814926 C103.454542,127.710356 102.559112,126.814926 101.454542,126.814926 L101.454542,126.814926 Z M115.288711,116.850282 L63.2887108,116.850282 C62.1841413,116.850282 61.2887108,117.745712 61.2887108,118.850282 C61.2887108,119.904643 62.1045886,120.768447 63.1394485,120.844796 L63.2887108,120.850282 L115.288711,120.850282 C116.39328,120.850282 117.288711,119.954851 117.288711,118.850282 C117.288711,117.745712 116.39328,116.850282 115.288711,116.850282 Z M97.011063,106.163706 L64.011063,106.163706 C62.9064935,106.163706 62.011063,107.059136 62.011063,108.163706 C62.011063,109.218068 62.8269408,110.081871 63.8618007,110.15822 L64.011063,110.163706 L97.011063,110.163706 C98.1156325,110.163706 99.011063,109.268275 99.011063,108.163706 C99.011063,107.059136 98.1156325,106.163706 97.011063,106.163706 Z M112.011284,95.3010779 L64.0112838,95.3010779 C62.9067143,95.3010779 62.0112838,96.1965084 62.0112838,97.3010779 C62.0112838,98.3554397 62.8271616,99.219243 63.8620215,99.2955922 L64.0112838,99.3010779 L112.011284,99.3010779 C113.115853,99.3010779 114.011284,98.4056474 114.011284,97.3010779 C114.011284,96.1965084 113.115853,95.3010779 112.011284,95.3010779 Z M96.7184437,84.7881504 L63.7184437,84.7881504 C62.6138742,84.7881504 61.7184437,85.6835809 61.7184437,86.7881504 C61.7184437,87.8425122 62.5343215,88.7063156 63.5691814,88.7826647 L63.7184437,88.7881504 L96.7184437,88.7881504 C97.8230132,88.7881504 98.7184437,87.8927199 98.7184437,86.7881504 C98.7184437,85.6835809 97.8230132,84.7881504 96.7184437,84.7881504 Z M108.741453,73.6650501 L63.7414529,73.6650501 C62.6368834,73.6650501 61.7414529,74.5604806 61.7414529,75.6650501 C61.7414529,76.7194119 62.5573307,77.5832152 63.5921905,77.6595644 L63.7414529,77.6650501 L108.741453,77.6650501 C109.846022,77.6650501 110.741453,76.7696196 110.741453,75.6650501 C110.741453,74.5604806 109.846022,73.6650501 108.741453,73.6650501 Z M92.456209,63.0652986 L63.456209,63.0652986 C62.3516395,63.0652986 61.456209,63.9607291 61.456209,65.0652986 C61.456209,66.1196603 62.2720867,66.9834637 63.3069466,67.0598128 L63.456209,67.0652986 L92.456209,67.0652986 C93.5607785,67.0652986 94.456209,66.1698681 94.456209,65.0652986 C94.456209,63.9607291 93.5607785,63.0652986 92.456209,63.0652986 Z M102.320762,52.7533578 L63.3207622,52.7533578 C62.2161927,52.7533578 61.3207622,53.6487883 61.3207622,54.7533578 C61.3207622,55.8077196 62.13664,56.6715229 63.1714998,56.7478721 L63.3207622,56.7533578 L102.320762,56.7533578 C103.425332,56.7533578 104.320762,55.8579273 104.320762,54.7533578 C104.320762,53.6487883 103.425332,52.7533578 102.320762,52.7533578 Z"
18
- id="Combined-Shape"
19
- fill="#999999"
20
- transform="translate(92.500000, 92.000000) rotate(-10.000000) translate(-92.500000, -92.000000) "></path>
21
- <g id="Oval-2" opacity="0.5" transform="translate(38.000000, 147.000000)" fill="#999999">
22
- <path
23
- d="M3.3015873,6.64864865 C5.12500362,6.64864865 6.6031746,5.16029795 6.6031746,3.32432432 C6.6031746,1.4883507 5.12500362,0 3.3015873,0 C1.47817098,0 1.08002496e-12,1.4883507 1.08002496e-12,3.32432432 C1.08002496e-12,5.16029795 1.47817098,6.64864865 3.3015873,6.64864865 Z M3.3015873,4.64864865 C2.5858248,4.64864865 2,4.05878945 2,3.32432432 C2,2.5898592 2.5858248,2 3.3015873,2 C4.0173498,2 4.6031746,2.5898592 4.6031746,3.32432432 C4.6031746,4.05878945 4.0173498,4.64864865 3.3015873,4.64864865 Z"
24
- id="Oval"></path>
25
- </g>
26
- <g id="Oval-Copy-8" opacity="0.8" transform="translate(147.000000, 93.000000)" fill="#999999">
27
- <path
28
- d="M3.3015873,6.64864865 C5.12500362,6.64864865 6.6031746,5.16029795 6.6031746,3.32432432 C6.6031746,1.4883507 5.12500362,1.42108547e-14 3.3015873,1.42108547e-14 C1.47817098,1.42108547e-14 1.08002496e-12,1.4883507 1.08002496e-12,3.32432432 C1.08002496e-12,5.16029795 1.47817098,6.64864865 3.3015873,6.64864865 Z M3.3015873,4.64864865 C2.5858248,4.64864865 2,4.05878945 2,3.32432432 C2,2.5898592 2.5858248,2 3.3015873,2 C4.0173498,2 4.6031746,2.5898592 4.6031746,3.32432432 C4.6031746,4.05878945 4.0173498,4.64864865 3.3015873,4.64864865 Z"
29
- id="Oval-Copy"></path>
30
- </g>
31
- <g id="Oval-Copy-6" opacity="0.6" transform="translate(11.000000, 80.000000)" fill="#999999">
32
- <path
33
- d="M3.3015873,6.64864865 C5.12500362,6.64864865 6.6031746,5.16029795 6.6031746,3.32432432 C6.6031746,1.4883507 5.12500362,0 3.3015873,0 C1.47817098,0 1.08713039e-12,1.4883507 1.08713039e-12,3.32432432 C1.08713039e-12,5.16029795 1.47817098,6.64864865 3.3015873,6.64864865 Z M3.3015873,4.64864865 C2.5858248,4.64864865 2,4.05878945 2,3.32432432 C2,2.5898592 2.5858248,2 3.3015873,2 C4.0173498,2 4.6031746,2.5898592 4.6031746,3.32432432 C4.6031746,4.05878945 4.0173498,4.64864865 3.3015873,4.64864865 Z"
34
- id="Oval-Copy-2"></path>
35
- </g>
36
- <g id="Oval-Copy-5" opacity="0.3" transform="translate(56.000000, 25.000000)" fill="#999999">
37
- <path
38
- d="M3.3015873,6.64864865 C5.12500362,6.64864865 6.6031746,5.16029795 6.6031746,3.32432432 C6.6031746,1.4883507 5.12500362,-5.32907052e-15 3.3015873,-5.32907052e-15 C1.47817098,-5.32907052e-15 1.07647224e-12,1.4883507 1.07647224e-12,3.32432432 C1.07647224e-12,5.16029795 1.47817098,6.64864865 3.3015873,6.64864865 Z M3.3015873,4.64864865 C2.5858248,4.64864865 2,4.05878945 2,3.32432432 C2,2.5898592 2.5858248,2 3.3015873,2 C4.0173498,2 4.6031746,2.5898592 4.6031746,3.32432432 C4.6031746,4.05878945 4.0173498,4.64864865 3.3015873,4.64864865 Z"
39
- id="Oval-Copy-3"></path>
40
- </g>
41
- <g id="Path-2" opacity="0.4" transform="translate(88.000000, 164.000000)" fill="#999999">
42
- <polygon id="Path" points="5.5 2.5 8 2.5 8 5.5 5.5 5.5 5.5 8 2.5 8 2.5 5.5 0 5.5 0 2.5 2.5 2.5 2.5 0 5.5 0"></polygon>
43
- </g>
44
- <g id="Path-2-Copy-3" opacity="0.4" transform="translate(15.000000, 57.000000)" fill="#999999">
45
- <polygon id="Path" points="5.5 2.5 8 2.5 8 5.5 5.5 5.5 5.5 8 2.5 8 2.5 5.5 0 5.5 0 2.5 2.5 2.5 2.5 0 5.5 0"></polygon>
46
- </g>
47
- <g id="Path-Copy-5" opacity="0.3" transform="translate(129.000000, 155.000000)" fill="#999999">
48
- <polygon id="Path-Copy" points="5.5 2.5 8 2.5 8 5.5 5.5 5.5 5.5 8 2.5 8 2.5 5.5 0 5.5 0 2.5 2.5 2.5 2.5 0 5.5 0"></polygon>
49
- </g>
50
- <g id="Path-Copy-4" opacity="0.9" transform="translate(77.000000, 12.000000)" fill="#999999">
51
- <polygon id="Path-Copy-2" points="5.5 2.5 8 2.5 8 5.5 5.5 5.5 5.5 8 2.5 8 2.5 5.5 0 5.5 0 2.5 2.5 2.5 2.5 0 5.5 0"></polygon>
52
- </g>
53
- <g id="Path-Copy-6" opacity="0.9" transform="translate(146.000000, 56.000000)" fill="#999999">
54
- <polygon id="Path-Copy-2" points="5.5 2.5 8 2.5 8 5.5 5.5 5.5 5.5 8 2.5 8 2.5 5.5 0 5.5 0 2.5 2.5 2.5 2.5 0 5.5 0"></polygon>
55
- </g>
56
- </g>
57
- </svg>
58
- <div className={styles.bounceFrame} />
9
+ <div className={styles.transcriptLoader}>
10
+ {Array.apply(null, Array(DEFAULT_LINES)).map((el, index) => (
11
+ <svg key={index} width="100%" height="50" viewBox="0 0 100% 50" fill="none" xmlns="http://www.w3.org/2000/svg">
12
+ <rect x="16" y="8" width="90%" height="12" rx="4" fill="white" />
13
+ <rect x="16" y="30" width="60%" height="12" rx="4" fill="white" />
14
+ </svg>
15
+ ))}
59
16
  </div>
60
17
  );
61
18
  }