@libs-ui/components-audio 0.2.189 → 0.2.191

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/README.md CHANGED
@@ -1,3 +1,352 @@
1
- # audio
1
+ # Audio Component
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ ## Giới thiệu
4
+
5
+ `audio` là một component mạnh mẽ dùng để phát âm thanh trong ứng dụng Angular. Component này cung cấp giao diện đơn giản để phát, tạm dừng và điều khiển các tệp âm thanh với nhiều tính năng.
6
+
7
+ ## Tính năng
8
+
9
+ - Phát/tạm dừng âm thanh
10
+ - Điều chỉnh âm lượng với chức năng tắt/bật tiếng
11
+ - Hiển thị thời gian theo định dạng HH:MM:SS
12
+ - Thanh tiến độ với chức năng tua nhanh/tua lại
13
+ - Tải xuống audio với kiểm soát quyền
14
+ - Function Control API cho phép điều khiển từ bên ngoài
15
+ - Thiết kế responsive
16
+ - Source audio có thể cấu hình
17
+
18
+ ## Cài đặt
19
+
20
+ Để cài đặt component `audio`, sử dụng npm hoặc yarn:
21
+
22
+ ```bash
23
+ npm install @libs-ui/components-audio
24
+ ```
25
+
26
+ hoặc
27
+
28
+ ```bash
29
+ yarn add @libs-ui/components-audio
30
+ ```
31
+
32
+ ## Sử dụng
33
+
34
+ ### Import module
35
+
36
+ ```typescript
37
+ import { LibsUiComponentsAudioComponent } from '@libs-ui/components-audio';
38
+
39
+ @NgModule({
40
+ declarations: [
41
+ AppComponent
42
+ ],
43
+ imports: [
44
+ BrowserModule,
45
+ LibsUiComponentsAudioComponent
46
+ ],
47
+ bootstrap: [AppComponent]
48
+ })
49
+ export class AppModule { }
50
+ ```
51
+
52
+ Hoặc trong component standalone:
53
+
54
+ ```typescript
55
+ import { Component } from '@angular/core';
56
+ import { CommonModule } from '@angular/common';
57
+ import { LibsUiComponentsAudioComponent } from '@libs-ui/components-audio';
58
+ import { IAudioFunctionControlEvent } from '@libs-ui/components-audio';
59
+
60
+ @Component({
61
+ selector: 'app-example',
62
+ standalone: true,
63
+ imports: [CommonModule, LibsUiComponentsAudioComponent],
64
+ template: `
65
+ <libs_ui-components-audio
66
+ [fileAudio]="audioSource"
67
+ [checkPermissionDownloadAudio]="checkDownloadPermission"
68
+ (outFunctionsControl)="registerFunctions($event)">
69
+ </libs_ui-components-audio>
70
+
71
+ <div class="controls">
72
+ <button (click)="playAudio()">Phát/Tạm dừng</button>
73
+ <button (click)="toggleMute()">Bật/Tắt tiếng</button>
74
+ </div>
75
+ `
76
+ })
77
+ export class ExampleComponent {
78
+ audioSource = 'path/to/audio/file.mp3';
79
+ functionControls: IAudioFunctionControlEvent | null = null;
80
+
81
+ checkDownloadPermission(): Promise<boolean> {
82
+ // Kiểm tra quyền download
83
+ return Promise.resolve(true);
84
+ }
85
+
86
+ registerFunctions(event: IAudioFunctionControlEvent) {
87
+ this.functionControls = event;
88
+ }
89
+
90
+ playAudio() {
91
+ if (this.functionControls) {
92
+ this.functionControls.playPause();
93
+ }
94
+ }
95
+
96
+ toggleMute() {
97
+ if (this.functionControls) {
98
+ this.functionControls.toggleMute();
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## API Reference
105
+
106
+ ### Inputs
107
+
108
+ | Input | Type | Description |
109
+ |--------------------------------|---------------------|------------------------------------------------------|
110
+ | fileAudio | string | URL của file audio cần phát |
111
+ | checkPermissionDownloadAudio | () => Promise<boolean> | Function trả về promise với kết quả boolean cho biết nếu được phép download |
112
+
113
+ ### Outputs
114
+
115
+ | Output | Type | Description |
116
+ |---------------------|----------------------------|--------------------------------------------------|
117
+ | outFunctionsControl | IAudioFunctionControlEvent | Event chứa các hàm điều khiển của audio component |
118
+ | outVolumeControl | number | Phát ra giá trị âm lượng hiện tại (0-100) |
119
+ | outTimeUpdate | { currentTime: string, duration: string } | Phát ra thông tin thời gian hiện tại và tổng thời gian |
120
+ | outEnded | void | Phát ra khi audio kết thúc phát |
121
+ | outMute | boolean | Phát ra trạng thái tắt/bật tiếng |
122
+ | outPlay | boolean | Phát ra trạng thái phát/tạm dừng |
123
+
124
+ ### Methods (Available through outFunctionsControl)
125
+
126
+ | Method | Parameters | Return Type | Description |
127
+ |-------------------|---------------|-------------|-----------------------------------------------------|
128
+ | playPause | event?: Event | void | Bắt đầu/tạm dừng phát audio |
129
+ | toggleMute | event?: Event | void | Bật/tắt âm thanh |
130
+ | setVolume | value: number | void | Điều chỉnh âm lượng (từ 0 đến 100) |
131
+ | seekTo | value: number | void | Di chuyển đến vị trí cụ thể trong audio (0-100) |
132
+ | download | event?: Event | void | Tải xuống file audio |
133
+ | isPlaying | - | boolean | Kiểm tra trạng thái đang phát audio |
134
+ | isMuted | - | boolean | Kiểm tra trạng thái tắt tiếng |
135
+
136
+ ## Interfaces
137
+
138
+ ```typescript
139
+ // Audio Function Control Event
140
+ interface IAudioFunctionControlEvent {
141
+ playPause: (event?: Event) => void;
142
+ toggleMute: (event?: Event) => void;
143
+ setVolume: (value: number) => void;
144
+ seekTo: (value: number) => void;
145
+ download: (event?: Event) => void;
146
+ isPlaying: () => boolean;
147
+ isMuted: () => boolean;
148
+ }
149
+ ```
150
+
151
+ ## Styling Volume Slider
152
+
153
+ Để tạo hiệu ứng thanh trượt âm lượng có màu nền thay đổi theo giá trị, bạn có thể sử dụng CSS variables:
154
+
155
+ ```css
156
+ /* Định nghĩa thanh trượt âm lượng */
157
+ input[type="range"].volume-slider {
158
+ background: linear-gradient(to right, #3b82f6 var(--volume-percent, 50%), #e5e7eb var(--volume-percent, 50%));
159
+ }
160
+
161
+ /* Track styling cho WebKit browsers */
162
+ input[type="range"].volume-slider::-webkit-slider-runnable-track {
163
+ background: linear-gradient(to right, #3b82f6 var(--volume-percent, 50%), #e5e7eb var(--volume-percent, 50%));
164
+ }
165
+
166
+ /* Track styling cho Firefox */
167
+ input[type="range"].volume-slider::-moz-range-track {
168
+ background: linear-gradient(to right, #3b82f6 var(--volume-percent, 50%), #e5e7eb var(--volume-percent, 50%));
169
+ }
170
+ ```
171
+
172
+ Và trong template:
173
+
174
+ ```html
175
+ <input type="range"
176
+ min="0"
177
+ max="100"
178
+ [value]="volumePercent()"
179
+ (input)="changeVolume($event)"
180
+ class="volume-slider"
181
+ [style.--volume-percent.%]="volumePercent()">
182
+ ```
183
+
184
+ ## Ví dụ
185
+
186
+ ### Sử dụng Function Control
187
+
188
+ ```typescript
189
+ import { Component, signal, computed } from '@angular/core';
190
+ import { IAudioFunctionControlEvent } from '@libs-ui/components-audio';
191
+
192
+ @Component({
193
+ selector: 'app-example',
194
+ template: `
195
+ <libs_ui-components-audio
196
+ [fileAudio]="audioSource()"
197
+ [checkPermissionDownloadAudio]="checkDownloadPermission"
198
+ (outFunctionsControl)="registerFunctions($event)">
199
+ </libs_ui-components-audio>
200
+
201
+ <div class="audio-controls">
202
+ <button (click)="playPauseAudio()">{{ isPlaying() ? 'Tạm dừng' : 'Phát' }}</button>
203
+ <button (click)="toggleMuteAudio()">{{ isMuted() ? 'Bật tiếng' : 'Tắt tiếng' }}</button>
204
+ <div class="volume-control">
205
+ <span>Âm lượng:</span>
206
+ <input type="range"
207
+ min="0"
208
+ max="100"
209
+ [value]="volumePercent()"
210
+ (input)="changeVolume($event)"
211
+ class="volume-slider"
212
+ [style.--volume-percent.%]="volumePercent()">
213
+ <span>{{ volumePercent() }}%</span>
214
+ </div>
215
+ <div class="progress-control">
216
+ <span>Tiến độ:</span>
217
+ <input type="range"
218
+ min="0"
219
+ max="100"
220
+ [value]="progress()"
221
+ (input)="changeProgress($event)">
222
+ <span>{{ progress() }}%</span>
223
+ </div>
224
+ <button (click)="downloadAudio()">Tải xuống</button>
225
+ </div>
226
+ `
227
+ })
228
+ export class ExampleComponent {
229
+ audioSource = signal('path/to/audio.mp3');
230
+ functionControls: IAudioFunctionControlEvent | null = null;
231
+ isPlaying = signal(false);
232
+ isMuted = signal(false);
233
+ volume = signal(80);
234
+ progress = signal(0);
235
+
236
+ // Computed properties
237
+ volumePercent = computed(() => Math.round(this.volume()));
238
+
239
+ checkDownloadPermission = (): Promise<boolean> => {
240
+ return Promise.resolve(true);
241
+ }
242
+
243
+ registerFunctions(event: IAudioFunctionControlEvent) {
244
+ this.functionControls = event;
245
+
246
+ // Initialize state
247
+ if (this.functionControls) {
248
+ this.isPlaying.set(this.functionControls.isPlaying());
249
+ this.isMuted.set(this.functionControls.isMuted());
250
+ }
251
+ }
252
+
253
+ playPauseAudio() {
254
+ if (this.functionControls) {
255
+ this.functionControls.playPause();
256
+ this.isPlaying.set(this.functionControls.isPlaying());
257
+ }
258
+ }
259
+
260
+ toggleMuteAudio() {
261
+ if (this.functionControls) {
262
+ this.functionControls.toggleMute();
263
+ this.isMuted.set(this.functionControls.isMuted());
264
+ }
265
+ }
266
+
267
+ changeVolume(event: Event) {
268
+ if (this.functionControls && event.target) {
269
+ const value = parseInt((event.target as HTMLInputElement).value);
270
+ this.volume.set(value);
271
+ this.functionControls.setVolume(value / 100); // Convert to 0-1 range
272
+ }
273
+ }
274
+
275
+ changeProgress(event: Event) {
276
+ if (this.functionControls && event.target) {
277
+ const value = parseInt((event.target as HTMLInputElement).value);
278
+ this.progress.set(value);
279
+ this.functionControls.seekTo(value);
280
+ }
281
+ }
282
+
283
+ downloadAudio() {
284
+ if (this.functionControls) {
285
+ this.functionControls.download();
286
+ }
287
+ }
288
+ }
289
+ ```
290
+
291
+ ### Sử dụng Events
292
+
293
+ Sử dụng các events để phản ứng với thay đổi từ audio player:
294
+
295
+ ```typescript
296
+ import { Component, signal } from '@angular/core';
297
+
298
+ @Component({
299
+ selector: 'app-example',
300
+ template: `
301
+ <libs_ui-components-audio
302
+ [fileAudio]="audioSource()"
303
+ [checkPermissionDownloadAudio]="checkPermission"
304
+ (outTimeUpdate)="handleTimeUpdate($event)"
305
+ (outVolumeControl)="handleVolumeChange($event)"
306
+ (outPlay)="handlePlayChange($event)"
307
+ (outMute)="handleMuteChange($event)"
308
+ (outEnded)="handleEnded()">
309
+ </libs_ui-components-audio>
310
+
311
+ <div class="audio-info">
312
+ <p>Trạng thái: {{ isPlaying() ? 'Đang phát' : 'Tạm dừng' }}</p>
313
+ <p>Thời gian hiện tại: {{ currentTime() }}</p>
314
+ <p>Tổng thời gian: {{ duration() }}</p>
315
+ <p>Âm lượng: {{ volumeLevel() }}%</p>
316
+ </div>
317
+ `
318
+ })
319
+ export class ExampleComponent {
320
+ audioSource = signal('path/to/audio.mp3');
321
+ isPlaying = signal(false);
322
+ isMuted = signal(false);
323
+ currentTime = signal('00:00:00');
324
+ duration = signal('00:00:00');
325
+ volumeLevel = signal(100);
326
+
327
+ checkPermission = (): Promise<boolean> => {
328
+ return Promise.resolve(true);
329
+ }
330
+
331
+ handleTimeUpdate(timeInfo: { currentTime: string, duration: string }) {
332
+ this.currentTime.set(timeInfo.currentTime);
333
+ this.duration.set(timeInfo.duration);
334
+ }
335
+
336
+ handleVolumeChange(volume: number) {
337
+ this.volumeLevel.set(volume);
338
+ }
339
+
340
+ handlePlayChange(isPlaying: boolean) {
341
+ this.isPlaying.set(isPlaying);
342
+ }
343
+
344
+ handleMuteChange(isMuted: boolean) {
345
+ this.isMuted.set(isMuted);
346
+ }
347
+
348
+ handleEnded() {
349
+ this.isPlaying.set(false);
350
+ }
351
+ }
352
+ ```
@@ -1,4 +1,5 @@
1
1
  import { AfterViewInit, ElementRef, OnDestroy } from '@angular/core';
2
+ import { IAudioFunctionControlEvent } from './interfaces/function-control-event.interface';
2
3
  import * as i0 from "@angular/core";
3
4
  export declare class LibsUiComponentsAudioComponent implements AfterViewInit, OnDestroy {
4
5
  protected audioRatioValue: import("@angular/core").WritableSignal<number>;
@@ -12,22 +13,32 @@ export declare class LibsUiComponentsAudioComponent implements AfterViewInit, On
12
13
  protected showFullControlVolume: import("@angular/core").WritableSignal<boolean>;
13
14
  private onDestroy;
14
15
  readonly fileAudio: import("@angular/core").InputSignal<string>;
15
- checkPermissionDownloadAudio?: () => Promise<boolean>;
16
+ readonly checkPermissionDownloadAudio: import("@angular/core").InputSignal<() => Promise<boolean>>;
16
17
  readonly audioRef: import("@angular/core").Signal<ElementRef<any>>;
17
18
  readonly volumeControlRef: import("@angular/core").Signal<ElementRef<any>>;
19
+ readonly outFunctionsControl: import("@angular/core").OutputEmitterRef<IAudioFunctionControlEvent>;
20
+ readonly outVolumeControl: import("@angular/core").OutputEmitterRef<number>;
21
+ readonly outTimeUpdate: import("@angular/core").OutputEmitterRef<{
22
+ currentTime: string;
23
+ duration: string;
24
+ }>;
25
+ readonly outEnded: import("@angular/core").OutputEmitterRef<void>;
26
+ readonly outMute: import("@angular/core").OutputEmitterRef<boolean>;
27
+ readonly outPlay: import("@angular/core").OutputEmitterRef<boolean>;
28
+ constructor();
18
29
  ngAfterViewInit(): void;
19
30
  private initObservable;
20
31
  protected handlerKeyPressAudio(): Promise<void>;
21
- protected handlerAudioMuteMuted(event: Event): Promise<void>;
22
- protected handlerAudioPausePlay(event: Event): Promise<void>;
32
+ protected handlerAudioMuteMuted(event?: Event): Promise<void>;
33
+ protected handlerAudioPausePlay(event?: Event): Promise<void>;
23
34
  protected handlerLoadedData(event: Event): Promise<void>;
24
- protected handlerTimeUpdate(event: Event): Promise<void>;
35
+ protected handlerTimeUpdate(event?: Event): Promise<void>;
25
36
  private toHHMMSS;
26
37
  protected handlerChangeAudio(value: number): Promise<void>;
27
38
  protected handlerChangeVolume(value: number): Promise<void>;
28
39
  protected handlerEnded(event: Event): Promise<void>;
29
- protected handlerDownload(e: Event): Promise<void>;
40
+ protected handlerDownload(e?: Event): Promise<void>;
30
41
  ngOnDestroy(): void;
31
42
  static ɵfac: i0.ɵɵFactoryDeclaration<LibsUiComponentsAudioComponent, never>;
32
- static ɵcmp: i0.ɵɵComponentDeclaration<LibsUiComponentsAudioComponent, "libs_ui-components-audio", never, { "fileAudio": { "alias": "fileAudio"; "required": true; "isSignal": true; }; "checkPermissionDownloadAudio": { "alias": "checkPermissionDownloadAudio"; "required": true; }; }, {}, never, never, true, never>;
43
+ static ɵcmp: i0.ɵɵComponentDeclaration<LibsUiComponentsAudioComponent, "libs_ui-components-audio", never, { "fileAudio": { "alias": "fileAudio"; "required": true; "isSignal": true; }; "checkPermissionDownloadAudio": { "alias": "checkPermissionDownloadAudio"; "required": true; "isSignal": true; }; }, { "outFunctionsControl": "outFunctionsControl"; "outVolumeControl": "outVolumeControl"; "outTimeUpdate": "outTimeUpdate"; "outEnded": "outEnded"; "outMute": "outMute"; "outPlay": "outPlay"; }, never, never, true, never>;
33
44
  }
@@ -0,0 +1,112 @@
1
+ import { LibsUiComponentsAudioComponent } from '../audio.component';
2
+ import { IAudioFunctionControlEvent } from '../interfaces/function-control-event.interface';
3
+ import * as i0 from "@angular/core";
4
+ export declare class LibsUiComponentsAudioDemoComponent {
5
+ audioPlayer: LibsUiComponentsAudioComponent;
6
+ isPlaying: import("@angular/core").WritableSignal<boolean>;
7
+ isMuted: import("@angular/core").WritableSignal<boolean>;
8
+ volume: import("@angular/core").WritableSignal<number>;
9
+ currentTime: import("@angular/core").WritableSignal<string>;
10
+ duration: import("@angular/core").WritableSignal<string>;
11
+ progress: import("@angular/core").WritableSignal<number>;
12
+ volumePercent: import("@angular/core").Signal<number>;
13
+ selectedAudio: import("@angular/core").WritableSignal<number>;
14
+ currentAudioSource: import("@angular/core").WritableSignal<string>;
15
+ functionControls: IAudioFunctionControlEvent | null;
16
+ audioSamples: import("@angular/core").WritableSignal<{
17
+ id: number;
18
+ name: string;
19
+ src: string;
20
+ duration: string;
21
+ }[]>;
22
+ inputsDoc: import("@angular/core").WritableSignal<{
23
+ name: string;
24
+ type: string;
25
+ default: string;
26
+ description: string;
27
+ }[]>;
28
+ outputsDoc: import("@angular/core").WritableSignal<{
29
+ name: string;
30
+ type: string;
31
+ description: string;
32
+ }[]>;
33
+ interfacesDoc: import("@angular/core").WritableSignal<{
34
+ name: string;
35
+ description: string;
36
+ properties: Array<{
37
+ name: string;
38
+ type: string;
39
+ description: string;
40
+ }>;
41
+ }[]>;
42
+ methodsDoc: import("@angular/core").WritableSignal<{
43
+ name: string;
44
+ params: string;
45
+ returnType: string;
46
+ description: string;
47
+ }[]>;
48
+ features: import("@angular/core").WritableSignal<{
49
+ id: number;
50
+ icon: string;
51
+ title: string;
52
+ description: string;
53
+ }[]>;
54
+ codeExamples: import("@angular/core").WritableSignal<{
55
+ id: number;
56
+ title: string;
57
+ code: string;
58
+ }[]>;
59
+ playAudio(): void;
60
+ toggleMute(): void;
61
+ changeVolume(event: Event): void;
62
+ downloadAudio(): void;
63
+ /**
64
+ * Format thời gian từ giây sang chuỗi HH:MM:SS
65
+ */
66
+ formatTime(timeInSeconds: number): string;
67
+ /**
68
+ * Sao chép text vào clipboard
69
+ */
70
+ copyToClipboard(text: string): void;
71
+ /**
72
+ * Đăng ký các function control từ component
73
+ */
74
+ registerFunctions(event: IAudioFunctionControlEvent): void;
75
+ /**
76
+ * Xử lý sự kiện thay đổi thời gian
77
+ */
78
+ handleTimeUpdate(timeInfo: {
79
+ currentTime: string;
80
+ duration: string;
81
+ }): void;
82
+ /**
83
+ * Xử lý sự kiện thay đổi âm lượng
84
+ */
85
+ handleVolumeChange(volume: number): void;
86
+ /**
87
+ * Xử lý sự kiện thay đổi trạng thái phát
88
+ */
89
+ handlePlayChange(isPlaying: boolean): void;
90
+ /**
91
+ * Xử lý sự kiện thay đổi trạng thái tắt tiếng
92
+ */
93
+ handleMuteChange(isMuted: boolean): void;
94
+ /**
95
+ * Xử lý sự kiện kết thúc phát
96
+ */
97
+ handleEnded(): void;
98
+ /**
99
+ * Chọn mẫu âm thanh
100
+ */
101
+ selectAudio(id: number): void;
102
+ /**
103
+ * Kiểm tra quyền tải xuống
104
+ */
105
+ checkDownloadPermission: () => Promise<boolean>;
106
+ /**
107
+ * Thay đổi vị trí phát bằng cách click trực tiếp vào thanh tiến độ
108
+ */
109
+ seekAudioByClick(event: MouseEvent): void;
110
+ static ɵfac: i0.ɵɵFactoryDeclaration<LibsUiComponentsAudioDemoComponent, never>;
111
+ static ɵcmp: i0.ɵɵComponentDeclaration<LibsUiComponentsAudioDemoComponent, "lib-audio-demo", never, {}, {}, never, never, true, never>;
112
+ }