@acorex/components 22.1.2 → 22.1.4
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/fesm2022/acorex-components-accordion.mjs +2 -2
- package/fesm2022/acorex-components-accordion.mjs.map +1 -1
- package/fesm2022/acorex-components-audio-wave.mjs +252 -277
- package/fesm2022/acorex-components-audio-wave.mjs.map +1 -1
- package/fesm2022/{acorex-components-conversation-acorex-components-conversation-BtkyQUlh.mjs → acorex-components-conversation-acorex-components-conversation-CdAHDQD1.mjs} +447 -133
- package/fesm2022/acorex-components-conversation-acorex-components-conversation-CdAHDQD1.mjs.map +1 -0
- package/fesm2022/{acorex-components-conversation-open-composer-picker-for-files-BKKO_8x6.mjs → acorex-components-conversation-open-composer-picker-for-files-DBWQaSVC.mjs} +2 -2
- package/fesm2022/{acorex-components-conversation-open-composer-picker-for-files-BKKO_8x6.mjs.map → acorex-components-conversation-open-composer-picker-for-files-DBWQaSVC.mjs.map} +1 -1
- package/fesm2022/{acorex-components-conversation-picker-rename-file-dialog.component-BNKFb5yO.mjs → acorex-components-conversation-picker-rename-file-dialog.component-swqLQ8g0.mjs} +2 -2
- package/fesm2022/{acorex-components-conversation-picker-rename-file-dialog.component-BNKFb5yO.mjs.map → acorex-components-conversation-picker-rename-file-dialog.component-swqLQ8g0.mjs.map} +1 -1
- package/fesm2022/acorex-components-conversation.mjs +1 -1
- package/fesm2022/acorex-components-file-viewer.mjs +84 -4
- package/fesm2022/acorex-components-file-viewer.mjs.map +1 -1
- package/package.json +5 -4
- package/types/acorex-components-audio-wave.d.ts +108 -73
- package/types/acorex-components-conversation.d.ts +89 -13
- package/types/acorex-components-file-viewer.d.ts +22 -3
- package/fesm2022/acorex-components-conversation-acorex-components-conversation-BtkyQUlh.mjs.map +0 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { AXComponent } from '@acorex/cdk/common';
|
|
2
|
-
import { AXSkeletonComponent
|
|
3
|
-
import { AXTranslatorPipe
|
|
4
|
-
import { isPlatformBrowser,
|
|
2
|
+
import { AXSkeletonComponent } from '@acorex/components/skeleton';
|
|
3
|
+
import { AXTranslatorPipe } from '@acorex/core/translation';
|
|
4
|
+
import { isPlatformBrowser, AsyncPipe } from '@angular/common';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
|
-
import { input, output, signal, inject, NgZone, PLATFORM_ID,
|
|
6
|
+
import { viewChild, input, output, signal, computed, inject, NgZone, PLATFORM_ID, DestroyRef, afterRenderEffect, ChangeDetectionStrategy, ViewEncapsulation, Component, NgModule } from '@angular/core';
|
|
7
7
|
import WaveSurfer from 'wavesurfer.js';
|
|
8
|
-
import { AXButtonModule } from '@acorex/components/button';
|
|
9
|
-
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
10
8
|
|
|
9
|
+
const DEFAULT_BAR_WIDTH = 2;
|
|
10
|
+
const DEFAULT_BAR_GAP = 2;
|
|
11
|
+
const DEFAULT_BAR_RADIUS = 2;
|
|
12
|
+
const DEFAULT_HEIGHT = 36;
|
|
13
|
+
const FALLBACK_RGB = '128, 128, 128';
|
|
11
14
|
/**
|
|
12
15
|
* Displays and interacts with audio waveform visualization.
|
|
13
16
|
*
|
|
@@ -15,9 +18,14 @@ import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
|
15
18
|
*/
|
|
16
19
|
class AXAudioWaveComponent {
|
|
17
20
|
/**
|
|
18
|
-
*
|
|
21
|
+
* @ignore
|
|
19
22
|
*/
|
|
20
23
|
constructor() {
|
|
24
|
+
/**
|
|
25
|
+
* @ignore
|
|
26
|
+
*/
|
|
27
|
+
this.wave = viewChild('wave', /* @ts-ignore */
|
|
28
|
+
...(ngDevMode ? [{ debugName: "wave" }] : /* istanbul ignore next */ []));
|
|
21
29
|
/**
|
|
22
30
|
* Configuration settings for the audio wave.
|
|
23
31
|
*/
|
|
@@ -29,58 +37,89 @@ class AXAudioWaveComponent {
|
|
|
29
37
|
* @event
|
|
30
38
|
*/
|
|
31
39
|
this.onStatusChanged = output();
|
|
32
|
-
|
|
40
|
+
/**
|
|
41
|
+
* @ignore
|
|
42
|
+
*/
|
|
43
|
+
this.audioState = signal('loading', /* @ts-ignore */
|
|
33
44
|
...(ngDevMode ? [{ debugName: "audioState" }] : /* istanbul ignore next */ []));
|
|
45
|
+
/**
|
|
46
|
+
* @ignore
|
|
47
|
+
*/
|
|
34
48
|
this.errorMessage = signal('', /* @ts-ignore */
|
|
35
49
|
...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
36
50
|
/**
|
|
37
|
-
*
|
|
51
|
+
* @ignore
|
|
52
|
+
*/
|
|
53
|
+
this.isWaveVisible = computed(() => {
|
|
54
|
+
const state = this.audioState();
|
|
55
|
+
return state === 'ready' || state === 'playing' || state === 'paused';
|
|
56
|
+
}, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "isWaveVisible" }] : /* istanbul ignore next */ []));
|
|
58
|
+
/**
|
|
59
|
+
* @ignore
|
|
60
|
+
*/
|
|
61
|
+
this.loadedUrl = '';
|
|
62
|
+
/**
|
|
63
|
+
* @ignore
|
|
64
|
+
*/
|
|
65
|
+
this.lastVisualKey = '';
|
|
66
|
+
/**
|
|
67
|
+
* @ignore
|
|
68
|
+
*/
|
|
69
|
+
this.isDestroyed = false;
|
|
70
|
+
/**
|
|
71
|
+
* @ignore
|
|
38
72
|
*/
|
|
39
73
|
this.ngZone = inject(NgZone);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
height: this.config()?.height || 36,
|
|
54
|
-
});
|
|
74
|
+
/**
|
|
75
|
+
* @ignore
|
|
76
|
+
*/
|
|
77
|
+
this.platformId = inject(PLATFORM_ID);
|
|
78
|
+
/**
|
|
79
|
+
* @ignore
|
|
80
|
+
*/
|
|
81
|
+
this.destroyRef = inject(DestroyRef);
|
|
82
|
+
afterRenderEffect(() => {
|
|
83
|
+
const container = this.wave()?.nativeElement;
|
|
84
|
+
const config = this.config();
|
|
85
|
+
if (this.isDestroyed || !isPlatformBrowser(this.platformId) || !container) {
|
|
86
|
+
return;
|
|
55
87
|
}
|
|
56
|
-
this.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
this.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
});
|
|
67
|
-
this.bindEvents();
|
|
88
|
+
if (!this.audio) {
|
|
89
|
+
this.createWaveSurfer(container, config);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.syncFromConfig(config);
|
|
93
|
+
});
|
|
94
|
+
this.destroyRef.onDestroy(() => {
|
|
95
|
+
this.isDestroyed = true;
|
|
96
|
+
this.audio?.destroy();
|
|
97
|
+
this.audio = undefined;
|
|
68
98
|
});
|
|
69
99
|
}
|
|
70
100
|
/**
|
|
71
101
|
* Loads the audio from the specified URL.
|
|
72
102
|
*
|
|
73
103
|
* @param url - The URL of the audio to load. Defaults to the URL from the config.
|
|
104
|
+
* @returns A promise that resolves when loading starts, or immediately when unavailable.
|
|
74
105
|
*/
|
|
75
|
-
load(url = this.config()
|
|
76
|
-
|
|
106
|
+
load(url = this.config()?.url) {
|
|
107
|
+
const nextUrl = url?.trim();
|
|
108
|
+
if (!this.audio || !nextUrl) {
|
|
109
|
+
return Promise.resolve();
|
|
110
|
+
}
|
|
111
|
+
this.loadedUrl = nextUrl;
|
|
112
|
+
this.audioState.set('loading');
|
|
113
|
+
this.errorMessage.set('');
|
|
114
|
+
return this.audio.load(nextUrl);
|
|
77
115
|
}
|
|
78
116
|
/**
|
|
79
117
|
* Plays the audio.
|
|
80
118
|
*
|
|
119
|
+
* @returns A promise that resolves when playback starts.
|
|
81
120
|
*/
|
|
82
121
|
play() {
|
|
83
|
-
return this.audio?.play();
|
|
122
|
+
return this.audio?.play() ?? Promise.resolve();
|
|
84
123
|
}
|
|
85
124
|
/**
|
|
86
125
|
* Pauses the audio.
|
|
@@ -89,21 +128,25 @@ class AXAudioWaveComponent {
|
|
|
89
128
|
this.audio?.pause();
|
|
90
129
|
}
|
|
91
130
|
/**
|
|
92
|
-
* Retrieves the duration of the audio.
|
|
131
|
+
* Retrieves the duration of the audio in seconds.
|
|
93
132
|
*
|
|
133
|
+
* @returns The audio duration, or `0` when unavailable.
|
|
94
134
|
*/
|
|
95
135
|
getDuration() {
|
|
96
136
|
return this.audio?.getDuration() ?? 0;
|
|
97
137
|
}
|
|
98
138
|
/**
|
|
99
|
-
* Retrieves the media element
|
|
139
|
+
* Retrieves the underlying HTML media element.
|
|
100
140
|
*
|
|
141
|
+
* @returns The media element used by WaveSurfer, or `undefined` when unavailable.
|
|
101
142
|
*/
|
|
102
143
|
getMediaElement() {
|
|
103
144
|
return this.audio?.getMediaElement();
|
|
104
145
|
}
|
|
105
146
|
/**
|
|
106
147
|
* Retrieves the current playback position in seconds.
|
|
148
|
+
*
|
|
149
|
+
* @returns The current time, or `0` when unavailable.
|
|
107
150
|
*/
|
|
108
151
|
getCurrentTime() {
|
|
109
152
|
return this.audio?.getCurrentTime() ?? this.getMediaElement()?.currentTime ?? 0;
|
|
@@ -114,7 +157,7 @@ class AXAudioWaveComponent {
|
|
|
114
157
|
* @param rate - The playback rate to set.
|
|
115
158
|
*/
|
|
116
159
|
setRate(rate) {
|
|
117
|
-
this.audio
|
|
160
|
+
this.audio?.setPlaybackRate(rate);
|
|
118
161
|
}
|
|
119
162
|
/**
|
|
120
163
|
* Mutes or unmutes the audio.
|
|
@@ -122,11 +165,7 @@ class AXAudioWaveComponent {
|
|
|
122
165
|
* @param muted - Whether the audio should be muted.
|
|
123
166
|
*/
|
|
124
167
|
setMuted(muted) {
|
|
125
|
-
|
|
126
|
-
if (media) {
|
|
127
|
-
media.muted = muted;
|
|
128
|
-
}
|
|
129
|
-
this.audio?.setVolume(muted ? 0 : 1);
|
|
168
|
+
this.audio?.setMuted(muted);
|
|
130
169
|
}
|
|
131
170
|
/**
|
|
132
171
|
* Indicates whether the audio is currently muted.
|
|
@@ -134,279 +173,215 @@ class AXAudioWaveComponent {
|
|
|
134
173
|
* @returns True when muted; otherwise false.
|
|
135
174
|
*/
|
|
136
175
|
isMuted() {
|
|
137
|
-
|
|
138
|
-
return media?.muted ?? this.audio?.getVolume() === 0;
|
|
176
|
+
return this.audio?.getMuted() ?? false;
|
|
139
177
|
}
|
|
140
178
|
/**
|
|
141
|
-
*
|
|
179
|
+
* @ignore
|
|
142
180
|
*/
|
|
143
|
-
|
|
144
|
-
this.
|
|
145
|
-
this.
|
|
146
|
-
this.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.handlePlay();
|
|
150
|
-
this.handlePause();
|
|
151
|
-
this.handleFinish();
|
|
152
|
-
this.handleTimeUpdate();
|
|
153
|
-
this.handleSeeking();
|
|
154
|
-
this.handleInteraction();
|
|
155
|
-
this.handleClick();
|
|
156
|
-
this.handleDrag();
|
|
157
|
-
this.handleScroll();
|
|
158
|
-
this.handleZoom();
|
|
159
|
-
this.handleDestroy();
|
|
160
|
-
this.handleError();
|
|
161
|
-
}
|
|
162
|
-
/** When audio starts loading */
|
|
163
|
-
handleLoad() {
|
|
164
|
-
this.audio?.on('load', (url) => {
|
|
165
|
-
this.ngZone.run(() => {
|
|
166
|
-
this.onStatusChanged.emit({
|
|
167
|
-
component: this,
|
|
168
|
-
data: { url: url },
|
|
169
|
-
status: 'load',
|
|
170
|
-
isUserInteraction: false,
|
|
171
|
-
});
|
|
172
|
-
});
|
|
181
|
+
createWaveSurfer(container, config) {
|
|
182
|
+
const visualOptions = this.resolveVisualOptions(config);
|
|
183
|
+
this.lastVisualKey = JSON.stringify(visualOptions);
|
|
184
|
+
this.audio = WaveSurfer.create({
|
|
185
|
+
container,
|
|
186
|
+
...visualOptions,
|
|
173
187
|
});
|
|
188
|
+
this.bindEvents();
|
|
189
|
+
this.applyUrlAndRate(config);
|
|
174
190
|
}
|
|
175
|
-
/**
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
191
|
+
/**
|
|
192
|
+
* @ignore
|
|
193
|
+
*/
|
|
194
|
+
syncFromConfig(config) {
|
|
195
|
+
if (!this.audio) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const visualOptions = this.resolveVisualOptions(config);
|
|
199
|
+
const visualKey = JSON.stringify(visualOptions);
|
|
200
|
+
if (visualKey !== this.lastVisualKey) {
|
|
201
|
+
this.lastVisualKey = visualKey;
|
|
202
|
+
this.audio.setOptions(visualOptions);
|
|
203
|
+
}
|
|
204
|
+
this.applyUrlAndRate(config);
|
|
187
205
|
}
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
206
|
+
/**
|
|
207
|
+
* @ignore
|
|
208
|
+
*/
|
|
209
|
+
applyUrlAndRate(config) {
|
|
210
|
+
const url = config?.url?.trim() ?? '';
|
|
211
|
+
if (url && url !== this.loadedUrl) {
|
|
212
|
+
this.loadedUrl = url;
|
|
213
|
+
void this.audio?.load(url);
|
|
214
|
+
}
|
|
215
|
+
else if (!url) {
|
|
216
|
+
queueMicrotask(() => {
|
|
217
|
+
if (!this.isDestroyed && !this.loadedUrl && this.audioState() === 'loading') {
|
|
218
|
+
this.audioState.set('paused');
|
|
219
|
+
}
|
|
198
220
|
});
|
|
199
|
-
}
|
|
221
|
+
}
|
|
222
|
+
if (config?.audioRate != null) {
|
|
223
|
+
this.audio?.setPlaybackRate(config.audioRate);
|
|
224
|
+
}
|
|
200
225
|
}
|
|
201
|
-
/**
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
226
|
+
/**
|
|
227
|
+
* @ignore
|
|
228
|
+
*/
|
|
229
|
+
resolveVisualOptions(config) {
|
|
230
|
+
const primary200 = this.readCssRgbVar('--ax-sys-color-primary-200');
|
|
231
|
+
const primary700 = this.readCssRgbVar('--ax-sys-color-primary-700');
|
|
232
|
+
return {
|
|
233
|
+
waveColor: config?.waveColor ?? `rgba(${primary200})`,
|
|
234
|
+
progressColor: config?.progressColor ?? `rgba(${primary700})`,
|
|
235
|
+
barWidth: config?.barWidth ?? DEFAULT_BAR_WIDTH,
|
|
236
|
+
barGap: config?.barGap ?? DEFAULT_BAR_GAP,
|
|
237
|
+
barRadius: config?.barRadius ?? DEFAULT_BAR_RADIUS,
|
|
238
|
+
height: config?.height ?? DEFAULT_HEIGHT,
|
|
239
|
+
};
|
|
213
240
|
}
|
|
214
|
-
/**
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
isUserInteraction: false,
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
});
|
|
241
|
+
/**
|
|
242
|
+
* @ignore
|
|
243
|
+
*/
|
|
244
|
+
readCssRgbVar(name) {
|
|
245
|
+
if (!isPlatformBrowser(this.platformId)) {
|
|
246
|
+
return FALLBACK_RGB;
|
|
247
|
+
}
|
|
248
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || FALLBACK_RGB;
|
|
226
249
|
}
|
|
227
|
-
/**
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
250
|
+
/**
|
|
251
|
+
* @ignore
|
|
252
|
+
*/
|
|
253
|
+
bindEvents() {
|
|
254
|
+
if (!this.audio) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.audio.on('load', (url) => {
|
|
258
|
+
this.emitStatus('load', { url }, false);
|
|
234
259
|
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
this.onStatusChanged.emit({ component: this, data: null, status: 'pause', isUserInteraction: false });
|
|
260
|
+
this.audio.on('loading', (percent) => {
|
|
261
|
+
this.runInZone(() => {
|
|
262
|
+
this.errorMessage.set('');
|
|
263
|
+
this.audioState.set('loading');
|
|
264
|
+
this.emitStatus('loading', { percent }, false, false);
|
|
241
265
|
});
|
|
242
266
|
});
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
handleFinish() {
|
|
246
|
-
this.audio?.on('finish', () => {
|
|
247
|
-
this.ngZone.run(() => {
|
|
248
|
-
this.onStatusChanged.emit({
|
|
249
|
-
component: this,
|
|
250
|
-
data: null,
|
|
251
|
-
status: 'finish',
|
|
252
|
-
isUserInteraction: false,
|
|
253
|
-
});
|
|
254
|
-
});
|
|
267
|
+
this.audio.on('decode', (duration) => {
|
|
268
|
+
this.emitStatus('decode', { duration }, false);
|
|
255
269
|
});
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
this.
|
|
262
|
-
component: this,
|
|
263
|
-
data: { currentTime: currentTime },
|
|
264
|
-
status: 'timeupdate',
|
|
265
|
-
isUserInteraction: false,
|
|
266
|
-
});
|
|
270
|
+
this.audio.on('ready', (duration) => {
|
|
271
|
+
this.runInZone(() => {
|
|
272
|
+
if (this.audioState() !== 'playing') {
|
|
273
|
+
this.audioState.set('ready');
|
|
274
|
+
}
|
|
275
|
+
this.emitStatus('ready', { duration }, false, false);
|
|
267
276
|
});
|
|
268
277
|
});
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
handleSeeking() {
|
|
272
|
-
this.audio?.on('seeking', (currentTime) => {
|
|
273
|
-
this.ngZone.run(() => {
|
|
274
|
-
this.onStatusChanged.emit({
|
|
275
|
-
component: this,
|
|
276
|
-
data: { currentTime: currentTime },
|
|
277
|
-
status: 'seeking',
|
|
278
|
-
isUserInteraction: false,
|
|
279
|
-
});
|
|
280
|
-
});
|
|
278
|
+
this.audio.on('redrawcomplete', () => {
|
|
279
|
+
this.emitStatus('redrawcomplete', null, false);
|
|
281
280
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
this.ngZone.run(() => {
|
|
287
|
-
this.onStatusChanged.emit({
|
|
288
|
-
component: this,
|
|
289
|
-
data: { newTime: newTime },
|
|
290
|
-
status: 'interaction',
|
|
291
|
-
isUserInteraction: false,
|
|
292
|
-
});
|
|
281
|
+
this.audio.on('play', () => {
|
|
282
|
+
this.runInZone(() => {
|
|
283
|
+
this.audioState.set('playing');
|
|
284
|
+
this.emitStatus('play', null, false, false);
|
|
293
285
|
});
|
|
294
286
|
});
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
this.
|
|
301
|
-
component: this,
|
|
302
|
-
data: { relativeX: relativeX },
|
|
303
|
-
status: 'click',
|
|
304
|
-
isUserInteraction: false,
|
|
305
|
-
});
|
|
287
|
+
this.audio.on('pause', () => {
|
|
288
|
+
this.runInZone(() => {
|
|
289
|
+
if (this.audioState() !== 'error') {
|
|
290
|
+
this.audioState.set('paused');
|
|
291
|
+
}
|
|
292
|
+
this.emitStatus('pause', null, false, false);
|
|
306
293
|
});
|
|
307
294
|
});
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
this.ngZone.run(() => {
|
|
313
|
-
this.onStatusChanged.emit({
|
|
314
|
-
component: this,
|
|
315
|
-
data: { relativeX: relativeX },
|
|
316
|
-
status: 'drag',
|
|
317
|
-
isUserInteraction: false,
|
|
318
|
-
});
|
|
295
|
+
this.audio.on('finish', () => {
|
|
296
|
+
this.runInZone(() => {
|
|
297
|
+
this.audioState.set('paused');
|
|
298
|
+
this.emitStatus('finish', null, false, false);
|
|
319
299
|
});
|
|
320
300
|
});
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
handleScroll() {
|
|
324
|
-
this.audio?.on('scroll', (visibleStartTime, visibleEndTime) => {
|
|
325
|
-
this.ngZone.run(() => {
|
|
326
|
-
this.onStatusChanged.emit({
|
|
327
|
-
component: this,
|
|
328
|
-
data: { visibleStartTime, visibleEndTime },
|
|
329
|
-
status: 'scroll',
|
|
330
|
-
isUserInteraction: false,
|
|
331
|
-
});
|
|
332
|
-
});
|
|
301
|
+
this.audio.on('timeupdate', (currentTime) => {
|
|
302
|
+
this.emitStatus('timeupdate', { currentTime }, false);
|
|
333
303
|
});
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
handleZoom() {
|
|
337
|
-
this.audio?.on('zoom', (minPxPerSec) => {
|
|
338
|
-
this.ngZone.run(() => {
|
|
339
|
-
this.onStatusChanged.emit({
|
|
340
|
-
component: this,
|
|
341
|
-
data: { minPxPerSec: minPxPerSec },
|
|
342
|
-
status: 'zoom',
|
|
343
|
-
isUserInteraction: false,
|
|
344
|
-
});
|
|
345
|
-
});
|
|
304
|
+
this.audio.on('seeking', (currentTime) => {
|
|
305
|
+
this.emitStatus('seeking', { currentTime }, true);
|
|
346
306
|
});
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
this.audio
|
|
351
|
-
this.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
307
|
+
this.audio.on('interaction', (newTime) => {
|
|
308
|
+
this.emitStatus('interaction', { newTime }, true);
|
|
309
|
+
});
|
|
310
|
+
this.audio.on('click', (relativeX, relativeY) => {
|
|
311
|
+
this.emitStatus('click', { relativeX, relativeY }, true);
|
|
312
|
+
});
|
|
313
|
+
this.audio.on('drag', (relativeX) => {
|
|
314
|
+
this.emitStatus('drag', { relativeX }, true);
|
|
315
|
+
});
|
|
316
|
+
this.audio.on('scroll', (visibleStartTime, visibleEndTime) => {
|
|
317
|
+
this.emitStatus('scroll', { visibleStartTime, visibleEndTime }, true);
|
|
318
|
+
});
|
|
319
|
+
this.audio.on('zoom', (minPxPerSec) => {
|
|
320
|
+
this.emitStatus('zoom', { minPxPerSec }, false);
|
|
321
|
+
});
|
|
322
|
+
this.audio.on('destroy', () => {
|
|
323
|
+
this.emitStatus('destroy', null, false);
|
|
324
|
+
});
|
|
325
|
+
this.audio.on('error', (error) => {
|
|
326
|
+
this.runInZone(() => {
|
|
327
|
+
const message = error?.message ?? '';
|
|
328
|
+
this.errorMessage.set(message);
|
|
329
|
+
this.audioState.set('error');
|
|
330
|
+
this.emitStatus('error', { message }, false, false);
|
|
358
331
|
});
|
|
359
332
|
});
|
|
360
333
|
}
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
334
|
+
/**
|
|
335
|
+
* @ignore
|
|
336
|
+
*/
|
|
337
|
+
emitStatus(status, data, isUserInteraction, wrapInZone = true) {
|
|
338
|
+
if (this.isDestroyed) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const emit = () => {
|
|
342
|
+
this.onStatusChanged.emit({
|
|
343
|
+
component: this,
|
|
344
|
+
data,
|
|
345
|
+
status,
|
|
346
|
+
isUserInteraction,
|
|
366
347
|
});
|
|
367
|
-
}
|
|
348
|
+
};
|
|
349
|
+
if (wrapInZone) {
|
|
350
|
+
this.runInZone(emit);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
emit();
|
|
368
354
|
}
|
|
369
|
-
|
|
370
|
-
|
|
355
|
+
/**
|
|
356
|
+
* @ignore
|
|
357
|
+
*/
|
|
358
|
+
runInZone(fn) {
|
|
359
|
+
if (this.isDestroyed) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
this.ngZone.run(fn);
|
|
371
363
|
}
|
|
372
364
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
373
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXAudioWaveComponent, isStandalone: true, selector: "ax-audio-wave", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onStatusChanged: "onStatusChanged" }, providers: [{ provide: AXComponent, useExisting: AXAudioWaveComponent }], viewQueries: [{ propertyName: "
|
|
365
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXAudioWaveComponent, isStandalone: true, selector: "ax-audio-wave", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onStatusChanged: "onStatusChanged" }, host: { properties: { "attr.aria-busy": "audioState() === \"loading\" || null", "attr.aria-invalid": "audioState() === \"error\" || null" } }, providers: [{ provide: AXComponent, useExisting: AXAudioWaveComponent }], viewQueries: [{ propertyName: "wave", first: true, predicate: ["wave"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ax-audio-wave-host\" [class.ax-audio-wave-host--loading]=\"audioState() === 'loading'\">\n <div class=\"ax-audio-wave\" #wave [class.ax-audio-wave--hidden]=\"!isWaveVisible()\"></div>\n\n @switch (audioState()) {\n @case ('loading') {\n <ax-skeleton class=\"ax-audio-wave-skeleton\"></ax-skeleton>\n }\n @case ('error') {\n <div class=\"ax-wave-message\">\n {{ '@acorex:error.message' | translate: { params: { message: errorMessage() } } | async }}\n </div>\n }\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-audio-wave{display:block;width:100%;flex:1}ax-audio-wave .ax-audio-wave-host{position:relative;display:block;width:100%}ax-audio-wave .ax-audio-wave-host--loading{min-height:1.25rem}ax-audio-wave .ax-audio-wave{width:100%}ax-audio-wave .ax-audio-wave--hidden{visibility:hidden}ax-audio-wave .ax-audio-wave-skeleton{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);top:50%;height:calc(var(--spacing, .25rem) * 5);width:100%;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);border-radius:calc(infinity * 1px)}ax-audio-wave .ax-wave-message{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);top:50%;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);padding-inline-start:calc(var(--spacing, .25rem) * 2)}}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
374
366
|
}
|
|
375
367
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveComponent, decorators: [{
|
|
376
368
|
type: Component,
|
|
377
|
-
args: [{ selector: 'ax-audio-wave', encapsulation: ViewEncapsulation.None, imports: [
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
369
|
+
args: [{ selector: 'ax-audio-wave', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe, AXTranslatorPipe, AXSkeletonComponent], providers: [{ provide: AXComponent, useExisting: AXAudioWaveComponent }], host: {
|
|
370
|
+
'[attr.aria-busy]': 'audioState() === "loading" || null',
|
|
371
|
+
'[attr.aria-invalid]': 'audioState() === "error" || null',
|
|
372
|
+
}, template: "<div class=\"ax-audio-wave-host\" [class.ax-audio-wave-host--loading]=\"audioState() === 'loading'\">\n <div class=\"ax-audio-wave\" #wave [class.ax-audio-wave--hidden]=\"!isWaveVisible()\"></div>\n\n @switch (audioState()) {\n @case ('loading') {\n <ax-skeleton class=\"ax-audio-wave-skeleton\"></ax-skeleton>\n }\n @case ('error') {\n <div class=\"ax-wave-message\">\n {{ '@acorex:error.message' | translate: { params: { message: errorMessage() } } | async }}\n </div>\n }\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-audio-wave{display:block;width:100%;flex:1}ax-audio-wave .ax-audio-wave-host{position:relative;display:block;width:100%}ax-audio-wave .ax-audio-wave-host--loading{min-height:1.25rem}ax-audio-wave .ax-audio-wave{width:100%}ax-audio-wave .ax-audio-wave--hidden{visibility:hidden}ax-audio-wave .ax-audio-wave-skeleton{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);top:50%;height:calc(var(--spacing, .25rem) * 5);width:100%;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);border-radius:calc(infinity * 1px)}ax-audio-wave .ax-wave-message{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);top:50%;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);padding-inline-start:calc(var(--spacing, .25rem) * 2)}}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
|
|
373
|
+
}], ctorParameters: () => [], propDecorators: { wave: [{ type: i0.ViewChild, args: ['wave', { isSignal: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], onStatusChanged: [{ type: i0.Output, args: ["onStatusChanged"] }] } });
|
|
382
374
|
|
|
383
375
|
class AXAudioWaveModule {
|
|
384
376
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
385
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveModule, imports: [
|
|
386
|
-
|
|
387
|
-
AXDecoratorModule,
|
|
388
|
-
AXSkeletonModule,
|
|
389
|
-
AXTranslationModule,
|
|
390
|
-
AXAudioWaveComponent], exports: [AXAudioWaveComponent] }); }
|
|
391
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveModule, imports: [CommonModule,
|
|
392
|
-
AXButtonModule,
|
|
393
|
-
AXDecoratorModule,
|
|
394
|
-
AXSkeletonModule,
|
|
395
|
-
AXTranslationModule,
|
|
396
|
-
AXAudioWaveComponent] }); }
|
|
377
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveModule, imports: [AXAudioWaveComponent], exports: [AXAudioWaveComponent] }); }
|
|
378
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveModule, imports: [AXAudioWaveComponent] }); }
|
|
397
379
|
}
|
|
398
380
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXAudioWaveModule, decorators: [{
|
|
399
381
|
type: NgModule,
|
|
400
382
|
args: [{
|
|
401
383
|
exports: [AXAudioWaveComponent],
|
|
402
|
-
imports: [
|
|
403
|
-
CommonModule,
|
|
404
|
-
AXButtonModule,
|
|
405
|
-
AXDecoratorModule,
|
|
406
|
-
AXSkeletonModule,
|
|
407
|
-
AXTranslationModule,
|
|
408
|
-
AXAudioWaveComponent,
|
|
409
|
-
],
|
|
384
|
+
imports: [AXAudioWaveComponent],
|
|
410
385
|
}]
|
|
411
386
|
}] });
|
|
412
387
|
|