@libs-ui/components-audio 0.2.190 → 0.2.192

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.
@@ -1 +1 @@
1
- {"version":3,"file":"libs-ui-components-audio.mjs","sources":["../../../../../libs-ui/components/audio/src/audio.component.ts","../../../../../libs-ui/components/audio/src/audio.component.html","../../../../../libs-ui/components/audio/src/demo.component.ts","../../../../../libs-ui/components/audio/src/libs-ui-components-audio.ts"],"sourcesContent":["import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, input, OnDestroy, signal, viewChild } from '@angular/core';\nimport { LibsUiComponentsInputsRangeSliderComponent } from '@libs-ui/components-inputs-range-slider';\nimport { fromEvent, merge, Observable, Subject, takeUntil, tap } from 'rxjs';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-audio',\n templateUrl: './audio.component.html',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n LibsUiComponentsInputsRangeSliderComponent\n ]\n})\nexport class LibsUiComponentsAudioComponent implements AfterViewInit, OnDestroy {\n // #region PROPERTY\n protected audioRatioValue = signal<number>(0);\n protected volumeRatioValue = signal<number>(100);\n protected isPlay = signal<boolean>(false);\n protected isMute = signal<boolean>(false);\n protected isSliderAudioPress = signal<boolean>(false);\n protected isDisable = signal<boolean>(true);\n protected audioTimeCurrent = signal<string>('_:_:_');\n protected audioTimeDuration = signal<string>('_:_:_');\n protected showFullControlVolume = signal<boolean>(false);\n private onDestroy = new Subject<void>();\n\n // #region INPUT\n readonly fileAudio = input.required<string>();\n readonly checkPermissionDownloadAudio = input.required<() => Promise<boolean>>();\n\n /* VIEW CHILD */\n readonly audioRef = viewChild.required<ElementRef>('audioRef');\n readonly volumeControlRef = viewChild.required<ElementRef>('volumeControlRef');\n\n ngAfterViewInit() {\n merge(\n this.initObservable(this.volumeControlRef().nativeElement, 'mouseenter').pipe(tap(() => this.showFullControlVolume.set(true))),\n this.initObservable(this.volumeControlRef().nativeElement, 'mouseleave').pipe(tap(() => this.showFullControlVolume.set(false)))\n ).pipe(takeUntil(this.onDestroy)).subscribe();\n }\n /* FUNCTIONS */\n private initObservable(el: HTMLElement, eventName: string): Observable<MouseEvent> {\n return fromEvent<MouseEvent>(el, eventName).pipe(\n tap(e => e.stopPropagation()),\n takeUntil(this.onDestroy)\n );\n }\n\n protected async handlerKeyPressAudio() {\n this.isSliderAudioPress.set(true);\n }\n\n protected async handlerAudioMuteMuted(event: Event) {\n event.stopPropagation();\n if (this.audioRef().nativeElement.muted === true) {\n this.audioRef().nativeElement.muted = false;\n this.isMute.set(false);\n this.volumeRatioValue.set(50);\n\n return;\n }\n this.volumeRatioValue.set(0);\n this.isMute.set(true);\n this.audioRef().nativeElement.muted = true;\n }\n\n protected async handlerAudioPausePlay(event: Event) {\n event.stopPropagation();\n const audioElement = this.audioRef().nativeElement;\n if (!audioElement.paused) {\n audioElement.pause();\n this.isPlay.set(false);\n return;\n }\n\n try {\n await audioElement.play();\n this.isPlay.set(true);\n } catch (error) {\n console.error('Error playing audio:', error);\n }\n }\n\n protected async handlerLoadedData(event: Event) {\n event.stopPropagation();\n if (this.audioRef().nativeElement) {\n this.audioTimeDuration.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.duration)));\n this.audioTimeCurrent.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.currentTime)));\n this.isDisable.set(false);\n }\n }\n\n protected async handlerTimeUpdate(event: Event) {\n event.stopPropagation();\n if (!this.audioRef().nativeElement) {\n return;\n }\n this.audioTimeDuration.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.duration)));\n this.audioTimeCurrent.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.currentTime)));\n if (this.isSliderAudioPress()) {\n this.audioRef().nativeElement.currentTime = this.audioRatioValue() * Math.floor(this.audioRef().nativeElement.duration) / 100;\n\n return;\n }\n this.audioRatioValue.set(Math.floor((this.audioRef().nativeElement.currentTime / this.audioRef().nativeElement.duration) * 100));\n }\n\n private async toHHMMSS(time: number) {\n const hours = Math.floor(time / 3600);\n const minutes = Math.floor((time - (hours * 3600)) / 60);\n const seconds = time - (hours * 3600) - (minutes * 60);\n\n const getLabel = ((val: number) => {\n return `${val < 10 ? '0' : ''}${val}`;\n });\n\n return `${getLabel(hours)}:${getLabel(minutes)}:${getLabel(seconds)}`;\n }\n\n protected async handlerChangeAudio(value: number) {\n if (value === this.audioRatioValue()) {\n return;\n }\n this.audioRef().nativeElement.currentTime = value * this.audioRef().nativeElement.duration / 100;\n this.audioRatioValue.set(value);\n this.isSliderAudioPress.set(false);\n }\n\n protected async handlerChangeVolume(value: number) {\n this.audioRef().nativeElement.volume = value / 100;\n\n if (this.audioRef().nativeElement.volume) {\n this.audioRef().nativeElement.muted = false;\n this.isMute.set(false);\n\n return;\n }\n this.audioRef().nativeElement.muted = true;\n this.isMute.set(true);\n }\n\n protected async handlerEnded(event: Event) {\n event.stopPropagation();\n this.isPlay.set(false);\n }\n\n protected async handlerDownload(e: Event) {\n if (!this.checkPermissionDownloadAudio() || !await this.checkPermissionDownloadAudio()()) {\n return;\n }\n e.stopPropagation();\n if (!this.fileAudio()) {\n return;\n }\n window.open(this.fileAudio(), `_blank`);\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n}\n","<audio controls\n #audioRef\n class=\"hidden\"\n (timeupdate)=\"handlerTimeUpdate($event)\"\n (loadeddata)=\"handlerLoadedData($event)\"\n (ended)=\"handlerEnded($event)\">\n <source [src]=\"fileAudio()\"\n type=\"audio/mpeg\">\n</audio>\n<div [class.libs-ui-disable]=\"isDisable()\"\n [class.pointer-events-none]=\"isDisable()\">\n <div class=\"flex justify-between items-center\">\n <div class=\"w-[70%] flex p-0 items-center \">\n <div class=\"flex mr-[16px] cursor-pointer\"\n (click)=\"handlerAudioPausePlay($event)\">\n <i class=\"text-[16px]\"\n [class.libs-ui-icon-play-solid]=\"!isPlay()\"\n [class.libs-ui-icon-pause-solid]=\"isPlay()\">\n </i>\n </div>\n <div class=\"libs-ui-font-h5r mr-[16px]\">{{ audioTimeCurrent() }} /{{ audioTimeDuration() }}</div>\n </div>\n <div class=\"w-[30%] flex p-0 items-center justify-end\">\n <div #volumeControlRef\n class=\"flex py-[3px] items-center rounded-[12px] h-[28px]\"\n [class.bg-[#e6e7ea]]='showFullControlVolume()'\n [class.px-[12px]]='showFullControlVolume()'>\n <i class=\"text-[16px] cursor-pointer\"\n [class.libs-ui-icon-speaker-on-solid]=\"!isMute()\"\n [class.libs-ui-icon-speaker-off-solid]=\"isMute()\"\n (click)=\"handlerAudioMuteMuted($event)\">\n </i>\n <libs_ui-components-inputs-range_slider [class.hidden]=\"!showFullControlVolume()\"\n [mode]=\"'audio'\"\n classInclude=\"flex items-center !w-[54px] cursor-pointer ml-[8px]\"\n [value]=\"volumeRatioValue()\"\n (outChange)=\"handlerChangeVolume($event)\" />\n </div>\n\n <i class=\"libs-ui-icon-download-solid ml-[16px] cursor-pointer\"\n (click)=\"handlerDownload($event)\">\n </i>\n </div>\n\n </div>\n <div class=\"h-[24px]\">\n <libs_ui-components-inputs-range_slider [mode]=\"'audio'\"\n [value]=\"audioRatioValue()\"\n [disable]='isDisable()'\n (outChange)=\"handlerChangeAudio($event)\" />\n </div>\n</div>\n","import { Component } from '@angular/core';\nimport { LibsUiComponentsAudioComponent } from './audio.component';\nimport { CommonModule } from '@angular/common';\n\n/**\n * Demo component hiển thị các ví dụ khác nhau của Audio component\n */\n@Component({\n selector: 'lib-audio-demo',\n standalone: true,\n imports: [LibsUiComponentsAudioComponent, CommonModule],\n styles: [`\n .demo-section {\n margin-bottom: 2rem;\n padding: 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 0.5rem;\n }\n \n .demo-title {\n font-size: 1.25rem;\n font-weight: 600;\n margin-bottom: 1rem;\n }\n \n .demo-description {\n margin-bottom: 1rem;\n color: #4b5563;\n }\n `],\n template: `\n <div class=\"p-4\">\n <h1 class=\"text-2xl font-bold mb-4\">Audio Component Demo</h1>\n \n <p class=\"mb-4\">\n Audio Component là một trình phát âm thanh tùy chỉnh với các controls đầy đủ như play/pause, \n volume control, progress bar và download button.\n </p>\n \n <div class=\"demo-section\">\n <div class=\"demo-title\">Basic Usage</div>\n <p class=\"demo-description\">Simple audio player với default settings</p>\n <libs_ui-components-audio\n fileAudio=\"https://nhacchuong123.com/nhac-chuong/abcdefgh/nhac-chuong-nguoi-ay-dau-co-dang-akira-phan-nguyen-van-chung.mp3\"\n [checkPermissionDownloadAudio]=\"basicPermissionCheck\"\n />\n </div>\n \n <div class=\"demo-section\">\n <div class=\"demo-title\">Disabled Download</div>\n <p class=\"demo-description\">Audio player không cho phép download</p>\n <libs_ui-components-audio\n fileAudio=\"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3\"\n [checkPermissionDownloadAudio]=\"denyPermissionCheck\"\n />\n </div>\n \n <div class=\"demo-section\">\n <div class=\"demo-title\">Long Audio File</div>\n <p class=\"demo-description\">Audio player với track có duration dài hơn</p>\n <libs_ui-components-audio\n fileAudio=\"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3\"\n [checkPermissionDownloadAudio]=\"basicPermissionCheck\"\n />\n </div>\n\n <div class=\"demo-section\">\n <div class=\"demo-title\">Delayed Permission Check</div>\n <p class=\"demo-description\">Mô phỏng permission check có delay, simulate API call</p>\n <libs_ui-components-audio\n fileAudio=\"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3\"\n [checkPermissionDownloadAudio]=\"delayedPermissionCheck\"\n />\n </div>\n </div>\n `\n})\nexport class LibsUiComponentsAudioDemoComponent {\n /**\n * Permission function luôn allow download\n */\n basicPermissionCheck(): Promise<boolean> {\n return Promise.resolve(true);\n }\n \n /**\n * Permission function không cho phép download\n */\n denyPermissionCheck(): Promise<boolean> {\n return Promise.resolve(false);\n }\n\n /**\n * Permission function có delay để mô phỏng API call\n */\n delayedPermissionCheck(): Promise<boolean> {\n return new Promise(resolve => {\n setTimeout(() => {\n resolve(true);\n }, 1500);\n });\n }\n} ","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAca,8BAA8B,CAAA;;AAE/B,IAAA,eAAe,GAAG,MAAM,CAAS,CAAC,CAAC;AACnC,IAAA,gBAAgB,GAAG,MAAM,CAAS,GAAG,CAAC;AACtC,IAAA,MAAM,GAAG,MAAM,CAAU,KAAK,CAAC;AAC/B,IAAA,MAAM,GAAG,MAAM,CAAU,KAAK,CAAC;AAC/B,IAAA,kBAAkB,GAAG,MAAM,CAAU,KAAK,CAAC;AAC3C,IAAA,SAAS,GAAG,MAAM,CAAU,IAAI,CAAC;AACjC,IAAA,gBAAgB,GAAG,MAAM,CAAS,OAAO,CAAC;AAC1C,IAAA,iBAAiB,GAAG,MAAM,CAAS,OAAO,CAAC;AAC3C,IAAA,qBAAqB,GAAG,MAAM,CAAU,KAAK,CAAC;AAChD,IAAA,SAAS,GAAG,IAAI,OAAO,EAAQ;;AAG9B,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAU;AACpC,IAAA,4BAA4B,GAAG,KAAK,CAAC,QAAQ,EAA0B;;AAGvE,IAAA,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAa,UAAU,CAAC;AACrD,IAAA,gBAAgB,GAAG,SAAS,CAAC,QAAQ,CAAa,kBAAkB,CAAC;IAE9E,eAAe,GAAA;AACb,QAAA,KAAK,CACH,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAC9H,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAChI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;;;IAGvC,cAAc,CAAC,EAAe,EAAE,SAAiB,EAAA;AACvD,QAAA,OAAO,SAAS,CAAa,EAAE,EAAE,SAAS,CAAC,CAAC,IAAI,CAC9C,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC,EAC7B,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAC1B;;AAGO,IAAA,MAAM,oBAAoB,GAAA;AAClC,QAAA,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC;;IAGzB,MAAM,qBAAqB,CAAC,KAAY,EAAA;QAChD,KAAK,CAAC,eAAe,EAAE;QACvB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,KAAK,IAAI,EAAE;YAChD,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,GAAG,KAAK;AAC3C,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,YAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAE7B;;AAEF,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5B,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QACrB,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,GAAG,IAAI;;IAGlC,MAAM,qBAAqB,CAAC,KAAY,EAAA;QAChD,KAAK,CAAC,eAAe,EAAE;QACvB,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa;AAClD,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;YACxB,YAAY,CAAC,KAAK,EAAE;AACpB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;YACtB;;AAGF,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,CAAC,IAAI,EAAE;AACzB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;;QACrB,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC;;;IAItC,MAAM,iBAAiB,CAAC,KAAY,EAAA;QAC5C,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE;YACjC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YACnG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;AACrG,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;;;IAInB,MAAM,iBAAiB,CAAC,KAAY,EAAA;QAC5C,KAAK,CAAC,eAAe,EAAE;QACvB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE;YAClC;;QAEF,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;AACrG,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE;AAC7B,YAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,GAAG;YAE7H;;AAEF,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC;;IAG1H,MAAM,QAAQ,CAAC,IAAY,EAAA;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;AACrC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;AACxD,QAAA,MAAM,OAAO,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,OAAO,GAAG,EAAE,CAAC;AAEtD,QAAA,MAAM,QAAQ,IAAI,CAAC,GAAW,KAAI;AAChC,YAAA,OAAO,CAAG,EAAA,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAG,EAAA,GAAG,EAAE;AACvC,SAAC,CAAC;AAEF,QAAA,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE;;IAG7D,MAAM,kBAAkB,CAAC,KAAa,EAAA;AAC9C,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,eAAe,EAAE,EAAE;YACpC;;QAEF,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,GAAG,GAAG;AAChG,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,QAAA,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC;;IAG1B,MAAM,mBAAmB,CAAC,KAAa,EAAA;QAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,MAAM,GAAG,KAAK,GAAG,GAAG;QAElD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE;YACxC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,GAAG,KAAK;AAC3C,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;YAEtB;;QAEF,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,GAAG,IAAI;AAC1C,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;;IAGb,MAAM,YAAY,CAAC,KAAY,EAAA;QACvC,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;;IAGd,MAAM,eAAe,CAAC,CAAQ,EAAA;AACtC,QAAA,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,4BAA4B,EAAE,EAAE,EAAE;YACxF;;QAEF,CAAC,CAAC,eAAe,EAAE;AACnB,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACrB;;QAEF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAQ,MAAA,CAAA,CAAC;;IAGzC,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;AACrB,QAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;;wGAlJhB,8BAA8B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA9B,8BAA8B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,4BAAA,EAAA,EAAA,iBAAA,EAAA,8BAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,UAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,UAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECd3C,shEAoDA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDzCI,0CAA0C,EAAA,QAAA,EAAA,wCAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,KAAA,EAAA,KAAA,EAAA,OAAA,EAAA,cAAA,EAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,sBAAA,EAAA,cAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAGjC,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBAV1C,SAAS;AAEE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,0BAA0B,cAExB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EACtC,OAAA,EAAA;wBACP;AACD,qBAAA,EAAA,QAAA,EAAA,shEAAA,EAAA;;;AERH;;AAEG;MAuEU,kCAAkC,CAAA;AAC7C;;AAEG;IACH,oBAAoB,GAAA;AAClB,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;;AAG9B;;AAEG;IACH,mBAAmB,GAAA;AACjB,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;;AAG/B;;AAEG;IACH,sBAAsB,GAAA;AACpB,QAAA,OAAO,IAAI,OAAO,CAAC,OAAO,IAAG;YAC3B,UAAU,CAAC,MAAK;gBACd,OAAO,CAAC,IAAI,CAAC;aACd,EAAE,IAAI,CAAC;AACV,SAAC,CAAC;;wGAvBO,kCAAkC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kCAAkC,EA/CnC,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CT,EAjES,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mNAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,8BAA8B,2HAAE,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAmE3C,kCAAkC,EAAA,UAAA,EAAA,CAAA;kBAtE9C,SAAS;+BACE,gBAAgB,EAAA,UAAA,EACd,IAAI,EACP,OAAA,EAAA,CAAC,8BAA8B,EAAE,YAAY,CAAC,EAoB7C,QAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,mNAAA,CAAA,EAAA;;;AC3EH;;AAEG;;;;"}
1
+ {"version":3,"file":"libs-ui-components-audio.mjs","sources":["../../../../../libs-ui/components/audio/src/audio.component.ts","../../../../../libs-ui/components/audio/src/audio.component.html","../../../../../libs-ui/components/audio/src/demo/audio-demo.component.ts","../../../../../libs-ui/components/audio/src/demo/audio-demo.component.html","../../../../../libs-ui/components/audio/src/libs-ui-components-audio.ts"],"sourcesContent":["import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, effect, input, OnDestroy, output, signal, viewChild } from '@angular/core';\nimport { LibsUiComponentsInputsRangeSliderComponent } from '@libs-ui/components-inputs-range-slider';\nimport { fromEvent, merge, Observable, Subject, takeUntil, tap } from 'rxjs';\nimport { IAudioFunctionControlEvent } from './interfaces/function-control-event.interface';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-audio',\n templateUrl: './audio.component.html',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n LibsUiComponentsInputsRangeSliderComponent\n ]\n})\nexport class LibsUiComponentsAudioComponent implements AfterViewInit, OnDestroy {\n // #region PROPERTY\n protected audioRatioValue = signal<number>(0);\n protected volumeRatioValue = signal<number>(100);\n protected isPlay = signal<boolean>(false);\n protected isMute = signal<boolean>(false);\n protected isSliderAudioPress = signal<boolean>(false);\n protected isDisable = signal<boolean>(true);\n protected audioTimeCurrent = signal<string>('_:_:_');\n protected audioTimeDuration = signal<string>('_:_:_');\n protected showFullControlVolume = signal<boolean>(false);\n private onDestroy = new Subject<void>();\n\n // #region INPUT\n readonly fileAudio = input.required<string>();\n readonly checkPermissionDownloadAudio = input.required<() => Promise<boolean>>();\n\n /* VIEW CHILD */\n readonly audioRef = viewChild.required<ElementRef>('audioRef');\n readonly volumeControlRef = viewChild.required<ElementRef>('volumeControlRef');\n\n /* OUTPUTS */\n readonly outFunctionsControl = output<IAudioFunctionControlEvent>();\n readonly outVolumeControl = output<number>();\n readonly outTimeUpdate = output<{ currentTime: string, duration: string }>();\n readonly outEnded = output<void>();\n readonly outMute = output<boolean>();\n readonly outPlay = output<boolean>();\n\n constructor() {\n // Watch for file audio changes\n effect(() => {\n if (this.fileAudio() && this.audioRef()) {\n // Skip initial setup, only reload on changes\n setTimeout(() => {\n this.audioRef().nativeElement.load();\n }, 0);\n }\n });\n effect(() => {\n this.outVolumeControl.emit(this.volumeRatioValue());\n });\n effect(() => {\n this.outTimeUpdate.emit({ currentTime: this.audioTimeCurrent(), duration: this.audioTimeDuration() });\n });\n effect(() => {\n this.outMute.emit(this.isMute());\n });\n effect(() => {\n this.outPlay.emit(this.isPlay());\n });\n }\n\n ngAfterViewInit() {\n merge(\n this.initObservable(this.volumeControlRef().nativeElement, 'mouseenter').pipe(tap(() => this.showFullControlVolume.set(true))),\n this.initObservable(this.volumeControlRef().nativeElement, 'mouseleave').pipe(tap(() => this.showFullControlVolume.set(false)))\n ).pipe(takeUntil(this.onDestroy)).subscribe();\n\n // Emit function control event after view is initialized\n this.outFunctionsControl.emit({\n playPause: (event?: Event) => this.handlerAudioPausePlay(event),\n toggleMute: (event?: Event) => this.handlerAudioMuteMuted(event),\n seekTo: this.handlerChangeAudio.bind(this),\n setVolume: this.handlerChangeVolume.bind(this),\n download: (event?: Event) => this.handlerDownload(event),\n isPlaying: () => this.isPlay(),\n isMuted: () => this.isMute()\n });\n }\n\n /* FUNCTIONS */\n private initObservable(el: HTMLElement, eventName: string): Observable<MouseEvent> {\n return fromEvent<MouseEvent>(el, eventName).pipe(\n tap(e => e.stopPropagation()),\n takeUntil(this.onDestroy)\n );\n }\n\n protected async handlerKeyPressAudio() {\n this.isSliderAudioPress.set(true);\n }\n\n protected async handlerAudioMuteMuted(event?: Event) {\n if (event) {\n event.stopPropagation();\n }\n\n if (this.audioRef().nativeElement.muted === true) {\n this.audioRef().nativeElement.muted = false;\n this.isMute.set(false);\n this.volumeRatioValue.set(50);\n\n return;\n }\n this.volumeRatioValue.set(0);\n this.isMute.set(true);\n this.audioRef().nativeElement.muted = true;\n }\n\n protected async handlerAudioPausePlay(event?: Event) {\n if (event) {\n event.stopPropagation();\n }\n\n const audioElement = this.audioRef().nativeElement;\n if (!audioElement.paused) {\n audioElement.pause();\n this.isPlay.set(false);\n return;\n }\n\n try {\n await audioElement.play();\n this.isPlay.set(true);\n } catch (error) {\n console.error('Error playing audio:', error);\n }\n }\n\n protected async handlerLoadedData(event: Event) {\n if (event) {\n event.stopPropagation();\n }\n\n if (this.audioRef().nativeElement) {\n this.audioTimeDuration.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.duration)));\n this.audioTimeCurrent.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.currentTime || 0)));\n this.isDisable.set(false);\n this.isPlay.set(false);\n this.audioRatioValue.set(0);\n this.audioRef().nativeElement.pause();\n }\n }\n\n protected async handlerTimeUpdate(event?: Event) {\n if (event) {\n event.stopPropagation();\n }\n this.isDisable.set(!(this.audioRef().nativeElement.duration || 0));\n if (!this.audioRef().nativeElement) {\n return;\n }\n this.audioTimeDuration.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.duration)));\n this.audioTimeCurrent.set(await this.toHHMMSS(Math.floor(this.audioRef().nativeElement.currentTime || 0)));\n if (this.isSliderAudioPress()) {\n this.audioRef().nativeElement.currentTime = this.audioRatioValue() * Math.floor(this.audioRef().nativeElement.duration || 0) / 100;\n\n return;\n }\n this.audioRatioValue.set(Math.floor(((this.audioRef().nativeElement.currentTime || 0) / (this.audioRef().nativeElement.duration || 1)) * 100));\n }\n\n private async toHHMMSS(time: number) {\n const hours = Math.floor(time / 3600);\n const minutes = Math.floor((time - (hours * 3600)) / 60);\n const seconds = time - (hours * 3600) - (minutes * 60);\n\n const getLabel = ((val: number) => {\n val = val || 0;\n return `${val < 10 ? '0' : ''}${val}`;\n });\n\n return `${getLabel(hours)}:${getLabel(minutes)}:${getLabel(seconds)}`;\n }\n\n protected async handlerChangeAudio(value: number) {\n if (value === this.audioRatioValue()) {\n return;\n }\n this.audioRef().nativeElement.currentTime = (value || 0) * (this.audioRef().nativeElement.duration || 0) / 100;\n this.audioRatioValue.set(value);\n this.isSliderAudioPress.set(false);\n }\n\n protected async handlerChangeVolume(value: number) {\n this.audioRef().nativeElement.volume = value / 100;\n this.volumeRatioValue.set(value);\n if (this.audioRef().nativeElement.volume) {\n this.audioRef().nativeElement.muted = false;\n this.isMute.set(false);\n\n return;\n }\n this.audioRef().nativeElement.muted = true;\n this.isMute.set(true);\n }\n\n protected async handlerEnded(event: Event) {\n if (event) {\n event.stopPropagation();\n }\n\n this.isPlay.set(false);\n this.outEnded.emit();\n }\n\n protected async handlerDownload(e?: Event) {\n if (!this.checkPermissionDownloadAudio() || !await this.checkPermissionDownloadAudio()()) {\n return;\n }\n\n if (e) {\n e.stopPropagation();\n }\n\n if (!this.fileAudio()) {\n return;\n }\n window.open(this.fileAudio(), `_blank`);\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n}\n","<audio controls\n #audioRef\n class=\"hidden\"\n (timeupdate)=\"handlerTimeUpdate($event)\"\n (loadeddata)=\"handlerLoadedData($event)\"\n (ended)=\"handlerEnded($event)\">\n <source [src]=\"fileAudio()\"\n type=\"audio/mpeg\">\n</audio>\n<div [class.libs-ui-disable]=\"isDisable()\"\n [class.pointer-events-none]=\"isDisable()\">\n <div class=\"flex justify-between items-center\">\n <div class=\"w-[70%] flex p-0 items-center \">\n <div class=\"flex mr-[16px] cursor-pointer\"\n (click)=\"handlerAudioPausePlay($event)\">\n <i class=\"text-[16px]\"\n [class.libs-ui-icon-play-solid]=\"!isPlay()\"\n [class.libs-ui-icon-pause-solid]=\"isPlay()\">\n </i>\n </div>\n <div class=\"libs-ui-font-h5r mr-[16px]\">{{ audioTimeCurrent() }} /{{ audioTimeDuration() }}</div>\n </div>\n <div class=\"w-[30%] flex p-0 items-center justify-end\">\n <div #volumeControlRef\n class=\"flex py-[3px] items-center rounded-[12px] h-[28px]\"\n [class.bg-[#e6e7ea]]='showFullControlVolume()'\n [class.px-[12px]]='showFullControlVolume()'>\n <i class=\"text-[16px] cursor-pointer\"\n [class.libs-ui-icon-speaker-on-solid]=\"!isMute()\"\n [class.libs-ui-icon-speaker-off-solid]=\"isMute()\"\n (click)=\"handlerAudioMuteMuted($event)\">\n </i>\n <libs_ui-components-inputs-range_slider [class.hidden]=\"!showFullControlVolume()\"\n [mode]=\"'audio'\"\n classInclude=\"flex items-center !w-[54px] cursor-pointer ml-[8px]\"\n [value]=\"volumeRatioValue()\"\n (outChange)=\"handlerChangeVolume($event)\" />\n </div>\n\n <i class=\"libs-ui-icon-download-solid ml-[16px] cursor-pointer\"\n (click)=\"handlerDownload($event)\">\n </i>\n </div>\n\n </div>\n <div class=\"h-[24px]\">\n <libs_ui-components-inputs-range_slider [mode]=\"'audio'\"\n [value]=\"audioRatioValue()\"\n [disable]='isDisable()'\n (outChange)=\"handlerChangeAudio($event)\" />\n </div>\n</div>\n","import { Component, ViewChild, computed, signal } from '@angular/core';\nimport { LibsUiComponentsAudioComponent } from '../audio.component';\nimport { IAudioFunctionControlEvent } from '../interfaces/function-control-event.interface';\n\n@Component({\n selector: 'lib-audio-demo',\n standalone: true,\n imports: [LibsUiComponentsAudioComponent],\n templateUrl: './audio-demo.component.html',\n styleUrls: ['./audio-demo.component.css']\n})\nexport class LibsUiComponentsAudioDemoComponent {\n @ViewChild('audioPlayer') audioPlayer!: LibsUiComponentsAudioComponent;\n\n // State using signals\n public isPlaying = signal<boolean>(false);\n public isMuted = signal<boolean>(false);\n public volume = signal<number>(100);\n public currentTime = signal<string>('00:00:00');\n public duration = signal<string>('00:00:00');\n public progress = signal<number>(0);\n\n // Computed properties for template display\n public volumePercent = computed(() => Math.round(this.volume()));\n\n // Selected audio sample\n public selectedAudio = signal<number>(1);\n public currentAudioSource = signal<string>('https://nhacchuong123.com/nhac-chuong/abcdefgh/nhac-chuong-nguoi-ay-dau-co-dang-akira-phan-nguyen-van-chung.mp3');\n\n // Function Control variables\n public functionControls: IAudioFunctionControlEvent | null = null;\n\n // Audio samples for demo\n public audioSamples = signal<Array<{ id: number, name: string, src: string, duration: string }>>([\n {\n id: 1,\n name: 'Bản nhạc mẫu 1',\n src: 'https://nhacchuong123.com/nhac-chuong/abcdefgh/nhac-chuong-nguoi-ay-dau-co-dang-akira-phan-nguyen-van-chung.mp3',\n duration: '01:30'\n },\n {\n id: 2,\n name: 'Bản nhạc mẫu 2',\n src: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',\n duration: '02:15'\n },\n {\n id: 3,\n name: 'Bản nhạc mẫu 3',\n src: 'https://dl.dropboxusercontent.com/s/75jpngrgnavyu1f/The-Noisy-Freaks.mp3',\n duration: '03:45'\n }\n ]);\n\n // API Documentation data\n public inputsDoc = signal<Array<{ name: string, type: string, default: string, description: string }>>([\n {\n name: 'fileAudio',\n type: 'string',\n default: 'Bắt buộc',\n description: 'URL của file audio cần phát'\n },\n {\n name: 'checkPermissionDownloadAudio',\n type: '() => Promise<boolean>',\n default: 'Bắt buộc',\n description: 'Function trả về promise với kết quả boolean cho biết nếu được phép download'\n }\n ]);\n\n // Output documentation\n public outputsDoc = signal<Array<{ name: string, type: string, description: string }>>([\n {\n name: 'outFunctionsControl',\n type: 'IAudioFunctionControlEvent',\n description: 'Emits các hàm điều khiển audio'\n },\n {\n name: 'outVolumeControl',\n type: 'number',\n description: 'Emits giá trị âm lượng hiện tại (0-100)'\n },\n {\n name: 'outTimeUpdate',\n type: '{ currentTime: string, duration: string }',\n description: 'Emits thông tin thời gian hiện tại và tổng thời gian'\n },\n {\n name: 'outEnded',\n type: 'void',\n description: 'Emits khi audio kết thúc phát'\n },\n {\n name: 'outMute',\n type: 'boolean',\n description: 'Emits trạng thái tắt/bật tiếng'\n },\n {\n name: 'outPlay',\n type: 'boolean',\n description: 'Emits trạng thái phát/tạm dừng'\n }\n ]);\n\n // Interface documentation\n public interfacesDoc = signal<Array<{ name: string, description: string, properties: Array<{ name: string, type: string, description: string }> }>>([\n {\n name: 'IAudioFunctionControlEvent',\n description: 'Interface cho các chức năng điều khiển audio được cung cấp qua output event',\n properties: [\n {\n name: 'playPause',\n type: '(event?: Event) => void',\n description: 'Bắt đầu hoặc tạm dừng phát audio'\n },\n {\n name: 'toggleMute',\n type: '(event?: Event) => void',\n description: 'Bật hoặc tắt âm thanh'\n },\n {\n name: 'setVolume',\n type: '(value: number) => void',\n description: 'Điều chỉnh âm lượng (giá trị từ 0 đến 100)'\n },\n {\n name: 'seekTo',\n type: '(value: number) => void',\n description: 'Di chuyển đến vị trí cụ thể trong audio (giá trị từ 0 đến 100)'\n },\n {\n name: 'download',\n type: '(event?: Event) => void',\n description: 'Tải xuống file audio'\n },\n {\n name: 'isPlaying',\n type: '() => boolean',\n description: 'Kiểm tra trạng thái đang phát audio'\n },\n {\n name: 'isMuted',\n type: '() => boolean',\n description: 'Kiểm tra trạng thái tắt tiếng'\n }\n ]\n }\n ]);\n\n // Method documentation\n public methodsDoc = signal<Array<{ name: string, params: string, returnType: string, description: string }>>([\n {\n name: 'playPause',\n params: 'event?: Event',\n returnType: 'void',\n description: 'Phát hoặc tạm dừng audio'\n },\n {\n name: 'toggleMute',\n params: 'event?: Event',\n returnType: 'void',\n description: 'Bật/tắt âm thanh'\n },\n {\n name: 'seekTo',\n params: 'value: number',\n returnType: 'void',\n description: 'Di chuyển đến vị trí cụ thể trong audio (giá trị từ 0-100)'\n },\n {\n name: 'setVolume',\n params: 'value: number',\n returnType: 'void',\n description: 'Điều chỉnh âm lượng (giá trị từ 0-100)'\n },\n {\n name: 'download',\n params: 'event?: Event',\n returnType: 'void',\n description: 'Tải xuống file audio'\n },\n {\n name: 'isPlaying',\n params: '',\n returnType: 'boolean',\n description: 'Kiểm tra nếu audio đang phát'\n },\n {\n name: 'isMuted',\n params: '',\n returnType: 'boolean',\n description: 'Kiểm tra nếu audio đang tắt tiếng'\n }\n ]);\n\n // Features data\n public features = signal<Array<{ id: number, icon: string, title: string, description: string }>>([\n {\n id: 1,\n icon: '▶️',\n title: 'Điều khiển audio',\n description: 'Điều khiển audio component qua các API'\n },\n {\n id: 2,\n icon: '🔊',\n title: 'Quản lý âm lượng',\n description: 'Điều chỉnh âm lượng và tắt tiếng với thanh trượt trực quan'\n },\n {\n id: 3,\n icon: '⏱️',\n title: 'Hiển thị thời gian',\n description: 'Hiển thị thời gian hiện tại và tổng thời gian theo định dạng HH:MM:SS'\n },\n {\n id: 4,\n icon: '📊',\n title: 'Thanh tiến độ',\n description: 'Thanh tiến độ có thể tương tác để tua nhanh hoặc tua lại'\n },\n {\n id: 5,\n icon: '📥',\n title: 'Tải xuống',\n description: 'Hỗ trợ tải xuống file âm thanh với kiểm soát quyền'\n }\n ]);\n\n // Code examples data\n public codeExamples = signal<Array<{ id: number, title: string, code: string }>>([\n {\n id: 1,\n title: 'Cài đặt cơ bản',\n code: `&lt;libs_ui-components-audio\n [fileAudio]=\"'path/to/audio.mp3'\"\n [checkPermissionDownloadAudio]=\"checkPermission\"&gt;\n&lt;/libs_ui-components-audio&gt;`\n },\n {\n id: 2,\n title: 'Sử dụng Function Control',\n code: `import { Component, ViewChild, signal } from '@angular/core';\nimport { LibsUiComponentsAudioComponent } from '@libs-ui/components-audio';\nimport { IAudioFunctionControlEvent } from '@libs-ui/components-audio';\n\n@Component({\n selector: 'app-my-component',\n template: \\`\n &lt;libs_ui-components-audio\n #audioPlayer\n [fileAudio]=\"audioSource()\"\n [checkPermissionDownloadAudio]=\"checkPermission\"\n (outFunctionsControl)=\"registerFunctions($event)\"&gt;\n &lt;/libs_ui-components-audio&gt;\n \n &lt;button (click)=\"playAudio()\"&gt;Phát/Tạm dừng&lt;/button&gt;\n \\`\n})\nexport class MyComponent {\n @ViewChild('audioPlayer') audioPlayer!: LibsUiComponentsAudioComponent;\n audioSource = signal<string>('path/to/audio.mp3');\n functionControls: IAudioFunctionControlEvent | null = null;\n \n registerFunctions(event: IAudioFunctionControlEvent) {\n this.functionControls = event;\n }\n \n playAudio() {\n if (this.functionControls) {\n this.functionControls.playPause();\n }\n }\n}`\n },\n {\n id: 3,\n title: 'Sử dụng Events để cập nhật UI',\n code: `import { Component, signal } from '@angular/core';\nimport { LibsUiComponentsAudioComponent } from '@libs-ui/components-audio';\n\n@Component({\n selector: 'app-my-component',\n template: \\`\n &lt;libs_ui-components-audio\n [fileAudio]=\"audioSource()\"\n [checkPermissionDownloadAudio]=\"checkPermission\"\n (outTimeUpdate)=\"handleTimeUpdate($event)\"\n (outVolumeControl)=\"handleVolumeChange($event)\"\n (outPlay)=\"handlePlayChange($event)\"\n (outMute)=\"handleMuteChange($event)\"\n (outEnded)=\"handleEnded()\"&gt;\n &lt;/libs_ui-components-audio&gt;\n \n &lt;div class=\"audio-info\"&gt;\n &lt;p&gt;Trạng thái: {{ isPlaying() ? 'Đang phát' : 'Tạm dừng' }}&lt;/p&gt;\n &lt;p&gt;Thời gian hiện tại: {{ currentTime() }}&lt;/p&gt;\n &lt;p&gt;Tổng thời gian: {{ duration() }}&lt;/p&gt;\n &lt;p&gt;Âm lượng: {{ volumeLevel() }}%&lt;/p&gt;\n &lt;/div&gt;\n \\`\n})\nexport class MyComponent {\n audioSource = signal<string>('path/to/audio.mp3');\n isPlaying = signal<boolean>(false);\n isMuted = signal<boolean>(false);\n currentTime = signal<string>('00:00:00');\n duration = signal<string>('00:00:00');\n volumeLevel = signal<number>(100);\n \n checkPermission = (): Promise<boolean> => {\n return Promise.resolve(true);\n }\n \n handleTimeUpdate(timeInfo: { currentTime: string, duration: string }) {\n this.currentTime.set(timeInfo.currentTime);\n this.duration.set(timeInfo.duration);\n }\n \n handleVolumeChange(volume: number) {\n this.volumeLevel.set(volume);\n }\n \n handlePlayChange(isPlaying: boolean) {\n this.isPlaying.set(isPlaying);\n }\n \n handleMuteChange(isMuted: boolean) {\n this.isMuted.set(isMuted);\n }\n \n handleEnded() {\n this.isPlaying.set(false);\n }\n}`\n }\n ]);\n\n // Control methods\n public playAudio(): void {\n if (this.functionControls) {\n this.functionControls.playPause();\n this.isPlaying.set(this.functionControls.isPlaying());\n }\n }\n\n public toggleMute(): void {\n if (this.functionControls) {\n this.functionControls.toggleMute();\n this.isMuted.set(this.functionControls.isMuted());\n }\n }\n\n public changeVolume(event: Event): void {\n if (this.functionControls && event.target) {\n const value = parseInt((event.target as HTMLInputElement).value);\n this.volume.set(value);\n this.functionControls.setVolume(value);\n this.isMuted.set(this.functionControls.isMuted());\n }\n }\n\n public downloadAudio(): void {\n if (this.functionControls) {\n this.functionControls.download();\n }\n }\n\n /**\n * Format thời gian từ giây sang chuỗi HH:MM:SS\n */\n public formatTime(timeInSeconds: number): string {\n if (isNaN(timeInSeconds)) return '00:00:00';\n\n const hours = Math.floor(timeInSeconds / 3600);\n const minutes = Math.floor((timeInSeconds - (hours * 3600)) / 60);\n const seconds = Math.floor(timeInSeconds - (hours * 3600) - (minutes * 60));\n\n return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;\n }\n\n /**\n * Sao chép text vào clipboard\n */\n public copyToClipboard(text: string): void {\n navigator.clipboard.writeText(text)\n .then(() => {\n alert('Đã sao chép vào clipboard!');\n })\n .catch(err => {\n console.error('Failed to copy: ', err);\n });\n }\n\n /**\n * Đăng ký các function control từ component\n */\n public registerFunctions(event: IAudioFunctionControlEvent): void {\n this.functionControls = event;\n\n // Initialize state\n if (this.functionControls) {\n this.isPlaying.set(this.functionControls.isPlaying());\n this.isMuted.set(this.functionControls.isMuted());\n }\n }\n\n /**\n * Xử lý sự kiện thay đổi thời gian\n */\n public handleTimeUpdate(timeInfo: { currentTime: string, duration: string }): void {\n this.currentTime.set(timeInfo.currentTime);\n this.duration.set(timeInfo.duration);\n\n // Calculate progress based on currentTime and duration\n const regex = /(\\d+):(\\d+):(\\d+)/;\n const currentMatches = timeInfo.currentTime.match(regex);\n const durationMatches = timeInfo.duration.match(regex);\n\n if (currentMatches && durationMatches) {\n const currentSeconds =\n parseInt(currentMatches[1]) * 3600 +\n parseInt(currentMatches[2]) * 60 +\n parseInt(currentMatches[3]);\n\n const totalSeconds =\n parseInt(durationMatches[1]) * 3600 +\n parseInt(durationMatches[2]) * 60 +\n parseInt(durationMatches[3]);\n\n if (totalSeconds > 0) {\n this.progress.set(Math.floor((currentSeconds / totalSeconds) * 100));\n }\n }\n }\n\n /**\n * Xử lý sự kiện thay đổi âm lượng\n */\n public handleVolumeChange(volume: number): void {\n this.volume.set(volume);\n }\n\n /**\n * Xử lý sự kiện thay đổi trạng thái phát\n */\n public handlePlayChange(isPlaying: boolean): void {\n this.isPlaying.set(isPlaying);\n }\n\n /**\n * Xử lý sự kiện thay đổi trạng thái tắt tiếng\n */\n public handleMuteChange(isMuted: boolean): void {\n this.isMuted.set(isMuted);\n }\n\n /**\n * Xử lý sự kiện kết thúc phát\n */\n public handleEnded(): void {\n this.isPlaying.set(false);\n }\n\n /**\n * Chọn mẫu âm thanh\n */\n public selectAudio(id: number): void {\n this.selectedAudio.set(id);\n const sample = this.audioSamples().find(audio => audio.id === id);\n if (sample) {\n // Reset audio state\n this.isPlaying.set(false);\n this.progress.set(0);\n this.currentTime.set('00:00:00');\n this.duration.set('00:00:00');\n\n // Simply update the source - the component will handle the reload\n this.currentAudioSource.set(sample.src);\n }\n }\n\n /**\n * Kiểm tra quyền tải xuống\n */\n public checkDownloadPermission = (): Promise<boolean> => {\n return Promise.resolve(true);\n }\n\n /**\n * Thay đổi vị trí phát bằng cách click trực tiếp vào thanh tiến độ\n */\n public seekAudioByClick(event: MouseEvent): void {\n if (this.functionControls) {\n const progressBar = event.currentTarget as HTMLElement;\n const rect = progressBar.getBoundingClientRect();\n const offsetX = event.clientX - rect.left;\n const percentX = (offsetX / rect.width) * 100;\n\n // Đảm bảo giá trị nằm trong khoảng 0-100\n const clampedPercent = Math.max(0, Math.min(100, percentX));\n this.progress.set(Math.round(clampedPercent));\n\n // Gọi method seekTo để cập nhật vị trí phát\n this.functionControls.seekTo(this.progress());\n }\n }\n} \n","<div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg shadow mb-8\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Trình Phát Âm Thanh</h1>\n <p class=\"text-xl text-gray-600\">Thư viện component cho Angular để phát và điều khiển âm thanh</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg shadow p-8 mb-8\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-4 pb-2 border-b border-gray-200\">Giới thiệu</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">&#64;libs-ui/components-audio</code> là một\n component Angular mạnh mẽ cho phép người dùng 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.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg shadow p-8 mb-8\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-4 pb-2 border-b border-gray-200\">Cài đặt</h2>\n <p>Để cài đặt thư viện, sử dụng npm hoặc yarn:</p>\n\n <div class=\"relative my-4\">\n <pre\n class=\"bg-gray-100 p-4 rounded overflow-x-auto mb-4\"><code class=\"font-mono\">npm install &#64;libs-ui/components-audio</code></pre>\n <button\n class=\"absolute top-2 right-2 bg-blue-500 text-white px-3 py-1 rounded text-sm hover:bg-blue-600 transition\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-audio')\">\n Sao chép\n </button>\n </div>\n\n <p>Hoặc với yarn:</p>\n\n <div class=\"relative my-4\">\n <pre\n class=\"bg-gray-100 p-4 rounded overflow-x-auto mb-4\"><code class=\"font-mono\">yarn add &#64;libs-ui/components-audio</code></pre>\n <button\n class=\"absolute top-2 right-2 bg-blue-500 text-white px-3 py-1 rounded text-sm hover:bg-blue-600 transition\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-audio')\">\n Sao chép\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg shadow p-8 mb-8\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-4 pb-2 border-b border-gray-200\">Demo trực tiếp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Thử nghiệm trình phát âm thanh với các file mẫu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Chọn file âm thanh:</h3>\n <div class=\"flex flex-col gap-2\">\n @for (audio of audioSamples(); track audio.id) {\n <div\n class=\"flex justify-between p-3 bg-white rounded border cursor-pointer transition hover:bg-blue-50 hover:border-blue-500\"\n [class.bg-blue-50]=\"selectedAudio() === audio.id\"\n [class.border-blue-500]=\"selectedAudio() === audio.id\"\n [class.font-medium]=\"selectedAudio() === audio.id\"\n (click)=\"selectAudio(audio.id)\">\n <span>{{ audio.name }}</span>\n <span>{{ audio.duration }}</span>\n </div>\n }\n </div>\n </div>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Trình phát:</h3>\n <libs_ui-components-audio #audioPlayer\n [fileAudio]=\"currentAudioSource()\"\n [checkPermissionDownloadAudio]=\"checkDownloadPermission\"\n (outFunctionsControl)=\"registerFunctions($event)\"\n (outTimeUpdate)=\"handleTimeUpdate($event)\"\n (outVolumeControl)=\"handleVolumeChange($event)\"\n (outPlay)=\"handlePlayChange($event)\"\n (outMute)=\"handleMuteChange($event)\"\n (outEnded)=\"handleEnded()\">\n </libs_ui-components-audio>\n </div>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Điều khiển qua Function Control:</h3>\n <div class=\"flex flex-wrap gap-3 items-center bg-white p-4 rounded border\">\n <button class=\"px-4 py-2 bg-blue-500 text-white font-medium rounded hover:bg-blue-600 transition\"\n (click)=\"playAudio()\">\n Phát/Tạm dừng\n </button>\n <button class=\"px-4 py-2 bg-blue-500 text-white font-medium rounded hover:bg-blue-600 transition\"\n (click)=\"toggleMute()\">\n {{ isMuted() ? 'Bật tiếng' : 'Tắt tiếng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>Âm lượng:</span>\n <input type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volumePercent()\"\n (input)=\"changeVolume($event)\"\n class=\"w-24 volume-slider\"\n [style.--volume-percent.%]=\"volumePercent()\">\n <span>{{ volumePercent() }}%</span>\n </div>\n\n <div class=\"w-full mt-2\">\n <div class=\"flex items-center gap-2\">\n <span>Tiến độ:</span>\n <div class=\"relative h-2 bg-gray-200 rounded-full flex-1 cursor-pointer\"\n (click)=\"seekAudioByClick($event)\">\n <div class=\"absolute top-0 left-0 h-full bg-blue-500 rounded-full\"\n [style.width.%]=\"progress()\"></div>\n </div>\n <span>{{ progress() }}%</span>\n </div>\n </div>\n\n <button class=\"px-4 py-2 bg-green-500 text-white font-medium rounded hover:bg-green-600 transition mt-4\"\n (click)=\"downloadAudio()\">\n Tải xuống\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Trạng thái:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Trạng thái:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? 'Đang phát' : 'Tạm dừng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Thời gian hiện tại:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Tổng thời gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Tiến độ:</strong>\n <span>{{ progress() }}%</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg shadow p-8 mb-8\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-4 pb-2 border-b border-gray-200\">Tài liệu API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white\">\n <thead class=\"bg-gray-100\">\n <tr>\n <th class=\"py-3 px-4 text-left\">Tên</th>\n <th class=\"py-3 px-4 text-left\">Kiểu dữ liệu</th>\n <th class=\"py-3 px-4 text-left\">Mặc định</th>\n <th class=\"py-3 px-4 text-left\">Mô tả</th>\n </tr>\n </thead>\n <tbody>\n @for (input of inputsDoc(); track input.name) {\n <tr class=\"border-b hover:bg-gray-50\">\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ input.name }}</code></td>\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ input.type }}</code></td>\n <td class=\"py-3 px-4\">{{ input.default }}</td>\n <td class=\"py-3 px-4\">{{ input.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white\">\n <thead class=\"bg-gray-100\">\n <tr>\n <th class=\"py-3 px-4 text-left\">Tên</th>\n <th class=\"py-3 px-4 text-left\">Kiểu dữ liệu</th>\n <th class=\"py-3 px-4 text-left\">Mô tả</th>\n </tr>\n </thead>\n <tbody>\n @for (output of outputsDoc(); track output.name) {\n <tr class=\"border-b hover:bg-gray-50\">\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ output.name }}</code></td>\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ output.type }}</code></td>\n <td class=\"py-3 px-4\">{{ output.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Function Control Methods</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white\">\n <thead class=\"bg-gray-100\">\n <tr>\n <th class=\"py-3 px-4 text-left\">Tên</th>\n <th class=\"py-3 px-4 text-left\">Tham số</th>\n <th class=\"py-3 px-4 text-left\">Kiểu trả về</th>\n <th class=\"py-3 px-4 text-left\">Mô tả</th>\n </tr>\n </thead>\n <tbody>\n @for (method of methodsDoc(); track method.name) {\n <tr class=\"border-b hover:bg-gray-50\">\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ method.name }}</code></td>\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ method.params }}</code></td>\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ method.returnType }}</code></td>\n <td class=\"py-3 px-4\">{{ method.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Interfaces</h3>\n <div class=\"overflow-x-auto mb-8\">\n @for (interfaceDoc of interfacesDoc(); track interfaceDoc.name) {\n <div class=\"mb-6 bg-white p-4 rounded border\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-2\">{{ interfaceDoc.name }}</h4>\n <p class=\"mb-4\">{{ interfaceDoc.description }}</p>\n\n <table class=\"min-w-full bg-white\">\n <thead class=\"bg-gray-100\">\n <tr>\n <th class=\"py-3 px-4 text-left\">Tên</th>\n <th class=\"py-3 px-4 text-left\">Kiểu dữ liệu</th>\n <th class=\"py-3 px-4 text-left\">Mô tả</th>\n </tr>\n </thead>\n <tbody>\n @for (prop of interfaceDoc.properties; track prop.name) {\n <tr class=\"border-b hover:bg-gray-50\">\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ prop.name }}</code></td>\n <td class=\"py-3 px-4\"><code\n class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">{{ prop.type }}</code></td>\n <td class=\"py-3 px-4\">{{ prop.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg shadow p-8 mb-8\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-4 pb-2 border-b border-gray-200\">Tính năng</h2>\n <ul class=\"space-y-6\">\n @for (feature of features(); track feature.id) {\n <li class=\"flex items-start\">\n <span class=\"text-3xl mr-4 min-w-10 text-center\">{{ feature.icon }}</span>\n <div>\n <h3 class=\"text-xl font-semibold text-gray-700\">{{ feature.title }}</h3>\n <p>{{ feature.description }}</p>\n </div>\n </li>\n }\n </ul>\n </section>\n\n <section class=\"bg-white rounded-lg shadow p-8 mb-8\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-4 pb-2 border-b border-gray-200\">Cách sử dụng</h2>\n <div class=\"flex flex-col gap-4\">\n @for (example of codeExamples(); track example.id) {\n <div class=\"border border-gray-200 rounded-lg p-4\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-2\">{{ example.title }}</h3>\n <pre\n class=\"bg-gray-100 p-4 rounded overflow-x-auto\"><code [innerHTML]=\"example.code\" class=\"font-mono\"></code></pre>\n </div>\n }\n </div>\n </section>\n </main>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './audio.component';
2
- export * from './demo.component';
2
+ export * from './interfaces/function-control-event.interface';
3
+ export * from './demo/audio-demo.component';
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Interface cho các chức năng điều khiển audio được cung cấp qua output event
3
+ * @description Cung cấp các method để điều khiển audio player từ component cha
4
+ */
5
+ export interface IAudioFunctionControlEvent {
6
+ /**
7
+ * Bắt đầu hoặc tạm dừng phát audio
8
+ * @param event Optional event object
9
+ * @returns void
10
+ */
11
+ playPause: (event?: Event) => void;
12
+ /**
13
+ * Bật hoặc tắt âm thanh
14
+ * @param event Optional event object
15
+ * @returns void
16
+ */
17
+ toggleMute: (event?: Event) => void;
18
+ /**
19
+ * Điều chỉnh âm lượng
20
+ * @param value Giá trị âm lượng từ 0 đến 100
21
+ * @returns void
22
+ */
23
+ setVolume: (value: number) => void;
24
+ /**
25
+ * Di chuyển đến vị trí cụ thể trong audio
26
+ * @param value Giá trị phần trăm từ 0 đến 100
27
+ * @returns void
28
+ */
29
+ seekTo: (value: number) => void;
30
+ /**
31
+ * Tải xuống file audio
32
+ * @param event Optional event object
33
+ * @returns void
34
+ */
35
+ download: (event?: Event) => void;
36
+ /**
37
+ * Kiểm tra trạng thái đang phát audio
38
+ * @returns boolean True nếu đang phát, False nếu đang tạm dừng
39
+ */
40
+ isPlaying: () => boolean;
41
+ /**
42
+ * Kiểm tra trạng thái tắt tiếng
43
+ * @returns boolean True nếu đang tắt tiếng, False nếu đang bật tiếng
44
+ */
45
+ isMuted: () => boolean;
46
+ }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@libs-ui/components-audio",
3
- "version": "0.2.190",
3
+ "version": "0.2.192",
4
4
  "peerDependencies": {
5
5
  "@angular/core": "^18.2.0",
6
- "@libs-ui/components-inputs-range-slider": "^0.2.190",
6
+ "@libs-ui/components-inputs-range-slider": "^0.2.192",
7
7
  "rxjs": "~7.8.0"
8
8
  },
9
9
  "sideEffects": false,
@@ -1,20 +0,0 @@
1
- import * as i0 from "@angular/core";
2
- /**
3
- * Demo component hiển thị các ví dụ khác nhau của Audio component
4
- */
5
- export declare class LibsUiComponentsAudioDemoComponent {
6
- /**
7
- * Permission function luôn allow download
8
- */
9
- basicPermissionCheck(): Promise<boolean>;
10
- /**
11
- * Permission function không cho phép download
12
- */
13
- denyPermissionCheck(): Promise<boolean>;
14
- /**
15
- * Permission function có delay để mô phỏng API call
16
- */
17
- delayedPermissionCheck(): Promise<boolean>;
18
- static ɵfac: i0.ɵɵFactoryDeclaration<LibsUiComponentsAudioDemoComponent, never>;
19
- static ɵcmp: i0.ɵɵComponentDeclaration<LibsUiComponentsAudioDemoComponent, "lib-audio-demo", never, {}, {}, never, never, true, never>;
20
- }
@@ -1,128 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { LibsUiComponentsAudioComponent } from './audio.component';
3
- import { CommonModule } from '@angular/common';
4
- import * as i0 from "@angular/core";
5
- /**
6
- * Demo component hiển thị các ví dụ khác nhau của Audio component
7
- */
8
- export class LibsUiComponentsAudioDemoComponent {
9
- /**
10
- * Permission function luôn allow download
11
- */
12
- basicPermissionCheck() {
13
- return Promise.resolve(true);
14
- }
15
- /**
16
- * Permission function không cho phép download
17
- */
18
- denyPermissionCheck() {
19
- return Promise.resolve(false);
20
- }
21
- /**
22
- * Permission function có delay để mô phỏng API call
23
- */
24
- delayedPermissionCheck() {
25
- return new Promise(resolve => {
26
- setTimeout(() => {
27
- resolve(true);
28
- }, 1500);
29
- });
30
- }
31
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAudioDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
32
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LibsUiComponentsAudioDemoComponent, isStandalone: true, selector: "lib-audio-demo", ngImport: i0, template: `
33
- <div class="p-4">
34
- <h1 class="text-2xl font-bold mb-4">Audio Component Demo</h1>
35
-
36
- <p class="mb-4">
37
- Audio Component là một trình phát âm thanh tùy chỉnh với các controls đầy đủ như play/pause,
38
- volume control, progress bar và download button.
39
- </p>
40
-
41
- <div class="demo-section">
42
- <div class="demo-title">Basic Usage</div>
43
- <p class="demo-description">Simple audio player với default settings</p>
44
- <libs_ui-components-audio
45
- fileAudio="https://nhacchuong123.com/nhac-chuong/abcdefgh/nhac-chuong-nguoi-ay-dau-co-dang-akira-phan-nguyen-van-chung.mp3"
46
- [checkPermissionDownloadAudio]="basicPermissionCheck"
47
- />
48
- </div>
49
-
50
- <div class="demo-section">
51
- <div class="demo-title">Disabled Download</div>
52
- <p class="demo-description">Audio player không cho phép download</p>
53
- <libs_ui-components-audio
54
- fileAudio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
55
- [checkPermissionDownloadAudio]="denyPermissionCheck"
56
- />
57
- </div>
58
-
59
- <div class="demo-section">
60
- <div class="demo-title">Long Audio File</div>
61
- <p class="demo-description">Audio player với track có duration dài hơn</p>
62
- <libs_ui-components-audio
63
- fileAudio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3"
64
- [checkPermissionDownloadAudio]="basicPermissionCheck"
65
- />
66
- </div>
67
-
68
- <div class="demo-section">
69
- <div class="demo-title">Delayed Permission Check</div>
70
- <p class="demo-description">Mô phỏng permission check có delay, simulate API call</p>
71
- <libs_ui-components-audio
72
- fileAudio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3"
73
- [checkPermissionDownloadAudio]="delayedPermissionCheck"
74
- />
75
- </div>
76
- </div>
77
- `, isInline: true, styles: [".demo-section{margin-bottom:2rem;padding:1rem;border:1px solid #e5e7eb;border-radius:.5rem}.demo-title{font-size:1.25rem;font-weight:600;margin-bottom:1rem}.demo-description{margin-bottom:1rem;color:#4b5563}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAudioComponent, selector: "libs_ui-components-audio", inputs: ["fileAudio", "checkPermissionDownloadAudio"] }, { kind: "ngmodule", type: CommonModule }] });
78
- }
79
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAudioDemoComponent, decorators: [{
80
- type: Component,
81
- args: [{ selector: 'lib-audio-demo', standalone: true, imports: [LibsUiComponentsAudioComponent, CommonModule], template: `
82
- <div class="p-4">
83
- <h1 class="text-2xl font-bold mb-4">Audio Component Demo</h1>
84
-
85
- <p class="mb-4">
86
- Audio Component là một trình phát âm thanh tùy chỉnh với các controls đầy đủ như play/pause,
87
- volume control, progress bar và download button.
88
- </p>
89
-
90
- <div class="demo-section">
91
- <div class="demo-title">Basic Usage</div>
92
- <p class="demo-description">Simple audio player với default settings</p>
93
- <libs_ui-components-audio
94
- fileAudio="https://nhacchuong123.com/nhac-chuong/abcdefgh/nhac-chuong-nguoi-ay-dau-co-dang-akira-phan-nguyen-van-chung.mp3"
95
- [checkPermissionDownloadAudio]="basicPermissionCheck"
96
- />
97
- </div>
98
-
99
- <div class="demo-section">
100
- <div class="demo-title">Disabled Download</div>
101
- <p class="demo-description">Audio player không cho phép download</p>
102
- <libs_ui-components-audio
103
- fileAudio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
104
- [checkPermissionDownloadAudio]="denyPermissionCheck"
105
- />
106
- </div>
107
-
108
- <div class="demo-section">
109
- <div class="demo-title">Long Audio File</div>
110
- <p class="demo-description">Audio player với track có duration dài hơn</p>
111
- <libs_ui-components-audio
112
- fileAudio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3"
113
- [checkPermissionDownloadAudio]="basicPermissionCheck"
114
- />
115
- </div>
116
-
117
- <div class="demo-section">
118
- <div class="demo-title">Delayed Permission Check</div>
119
- <p class="demo-description">Mô phỏng permission check có delay, simulate API call</p>
120
- <libs_ui-components-audio
121
- fileAudio="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3"
122
- [checkPermissionDownloadAudio]="delayedPermissionCheck"
123
- />
124
- </div>
125
- </div>
126
- `, styles: [".demo-section{margin-bottom:2rem;padding:1rem;border:1px solid #e5e7eb;border-radius:.5rem}.demo-title{font-size:1.25rem;font-weight:600;margin-bottom:1rem}.demo-description{margin-bottom:1rem;color:#4b5563}\n"] }]
127
- }] });
128
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVtby5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXVkaW8vc3JjL2RlbW8uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUMsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDOztBQUUvQzs7R0FFRztBQXVFSCxNQUFNLE9BQU8sa0NBQWtDO0lBQzdDOztPQUVHO0lBQ0gsb0JBQW9CO1FBQ2xCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxtQkFBbUI7UUFDakIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNILHNCQUFzQjtRQUNwQixPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQzNCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNYLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzt3R0F4QlUsa0NBQWtDOzRGQUFsQyxrQ0FBa0MsMEVBL0NuQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkNULDJSQWpFUyw4QkFBOEIsMkhBQUUsWUFBWTs7NEZBbUUzQyxrQ0FBa0M7a0JBdEU5QyxTQUFTOytCQUNFLGdCQUFnQixjQUNkLElBQUksV0FDUCxDQUFDLDhCQUE4QixFQUFFLFlBQVksQ0FBQyxZQW9CN0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZDVCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTGlic1VpQ29tcG9uZW50c0F1ZGlvQ29tcG9uZW50IH0gZnJvbSAnLi9hdWRpby5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuLyoqXG4gKiBEZW1vIGNvbXBvbmVudCBoaeG7g24gdGjhu4sgY8OhYyB2w60gZOG7pSBraMOhYyBuaGF1IGPhu6dhIEF1ZGlvIGNvbXBvbmVudFxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItYXVkaW8tZGVtbycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQsIENvbW1vbk1vZHVsZV0sXG4gIHN0eWxlczogW2BcbiAgICAuZGVtby1zZWN0aW9uIHtcbiAgICAgIG1hcmdpbi1ib3R0b206IDJyZW07XG4gICAgICBwYWRkaW5nOiAxcmVtO1xuICAgICAgYm9yZGVyOiAxcHggc29saWQgI2U1ZTdlYjtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDAuNXJlbTtcbiAgICB9XG4gICAgXG4gICAgLmRlbW8tdGl0bGUge1xuICAgICAgZm9udC1zaXplOiAxLjI1cmVtO1xuICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XG4gICAgfVxuICAgIFxuICAgIC5kZW1vLWRlc2NyaXB0aW9uIHtcbiAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XG4gICAgICBjb2xvcjogIzRiNTU2MztcbiAgICB9XG4gIGBdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJwLTRcIj5cbiAgICAgIDxoMSBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCBtYi00XCI+QXVkaW8gQ29tcG9uZW50IERlbW88L2gxPlxuICAgICAgXG4gICAgICA8cCBjbGFzcz1cIm1iLTRcIj5cbiAgICAgICAgQXVkaW8gQ29tcG9uZW50IGzDoCBt4buZdCB0csOsbmggcGjDoXQgw6JtIHRoYW5oIHTDuXkgY2jhu4luaCB24bubaSBjw6FjIGNvbnRyb2xzIMSR4bqneSDEkeG7pyBuaMawIHBsYXkvcGF1c2UsIFxuICAgICAgICB2b2x1bWUgY29udHJvbCwgcHJvZ3Jlc3MgYmFyIHbDoCBkb3dubG9hZCBidXR0b24uXG4gICAgICA8L3A+XG4gICAgICBcbiAgICAgIDxkaXYgY2xhc3M9XCJkZW1vLXNlY3Rpb25cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRlbW8tdGl0bGVcIj5CYXNpYyBVc2FnZTwvZGl2PlxuICAgICAgICA8cCBjbGFzcz1cImRlbW8tZGVzY3JpcHRpb25cIj5TaW1wbGUgYXVkaW8gcGxheWVyIHbhu5tpIGRlZmF1bHQgc2V0dGluZ3M8L3A+XG4gICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtYXVkaW9cbiAgICAgICAgICBmaWxlQXVkaW89XCJodHRwczovL25oYWNjaHVvbmcxMjMuY29tL25oYWMtY2h1b25nL2FiY2RlZmdoL25oYWMtY2h1b25nLW5ndW9pLWF5LWRhdS1jby1kYW5nLWFraXJhLXBoYW4tbmd1eWVuLXZhbi1jaHVuZy5tcDNcIlxuICAgICAgICAgIFtjaGVja1Blcm1pc3Npb25Eb3dubG9hZEF1ZGlvXT1cImJhc2ljUGVybWlzc2lvbkNoZWNrXCJcbiAgICAgICAgLz5cbiAgICAgIDwvZGl2PlxuICAgICAgXG4gICAgICA8ZGl2IGNsYXNzPVwiZGVtby1zZWN0aW9uXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkZW1vLXRpdGxlXCI+RGlzYWJsZWQgRG93bmxvYWQ8L2Rpdj5cbiAgICAgICAgPHAgY2xhc3M9XCJkZW1vLWRlc2NyaXB0aW9uXCI+QXVkaW8gcGxheWVyIGtow7RuZyBjaG8gcGjDqXAgZG93bmxvYWQ8L3A+XG4gICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtYXVkaW9cbiAgICAgICAgICBmaWxlQXVkaW89XCJodHRwczovL3d3dy5zb3VuZGhlbGl4LmNvbS9leGFtcGxlcy9tcDMvU291bmRIZWxpeC1Tb25nLTEubXAzXCJcbiAgICAgICAgICBbY2hlY2tQZXJtaXNzaW9uRG93bmxvYWRBdWRpb109XCJkZW55UGVybWlzc2lvbkNoZWNrXCJcbiAgICAgICAgLz5cbiAgICAgIDwvZGl2PlxuICAgICAgXG4gICAgICA8ZGl2IGNsYXNzPVwiZGVtby1zZWN0aW9uXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkZW1vLXRpdGxlXCI+TG9uZyBBdWRpbyBGaWxlPC9kaXY+XG4gICAgICAgIDxwIGNsYXNzPVwiZGVtby1kZXNjcmlwdGlvblwiPkF1ZGlvIHBsYXllciB24bubaSB0cmFjayBjw7MgZHVyYXRpb24gZMOgaSBoxqFuPC9wPlxuICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF1ZGlvXG4gICAgICAgICAgZmlsZUF1ZGlvPVwiaHR0cHM6Ly93d3cuc291bmRoZWxpeC5jb20vZXhhbXBsZXMvbXAzL1NvdW5kSGVsaXgtU29uZy0yLm1wM1wiXG4gICAgICAgICAgW2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW9dPVwiYmFzaWNQZXJtaXNzaW9uQ2hlY2tcIlxuICAgICAgICAvPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJkZW1vLXNlY3Rpb25cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRlbW8tdGl0bGVcIj5EZWxheWVkIFBlcm1pc3Npb24gQ2hlY2s8L2Rpdj5cbiAgICAgICAgPHAgY2xhc3M9XCJkZW1vLWRlc2NyaXB0aW9uXCI+TcO0IHBo4buPbmcgcGVybWlzc2lvbiBjaGVjayBjw7MgZGVsYXksIHNpbXVsYXRlIEFQSSBjYWxsPC9wPlxuICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF1ZGlvXG4gICAgICAgICAgZmlsZUF1ZGlvPVwiaHR0cHM6Ly93d3cuc291bmRoZWxpeC5jb20vZXhhbXBsZXMvbXAzL1NvdW5kSGVsaXgtU29uZy0zLm1wM1wiXG4gICAgICAgICAgW2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW9dPVwiZGVsYXllZFBlcm1pc3Npb25DaGVja1wiXG4gICAgICAgIC8+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYFxufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzQXVkaW9EZW1vQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFBlcm1pc3Npb24gZnVuY3Rpb24gbHXDtG4gYWxsb3cgZG93bmxvYWRcbiAgICovXG4gIGJhc2ljUGVybWlzc2lvbkNoZWNrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBQZXJtaXNzaW9uIGZ1bmN0aW9uIGtow7RuZyBjaG8gcGjDqXAgZG93bmxvYWRcbiAgICovXG4gIGRlbnlQZXJtaXNzaW9uQ2hlY2soKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogUGVybWlzc2lvbiBmdW5jdGlvbiBjw7MgZGVsYXkgxJHhu4MgbcO0IHBo4buPbmcgQVBJIGNhbGxcbiAgICovXG4gIGRlbGF5ZWRQZXJtaXNzaW9uQ2hlY2soKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICB9LCAxNTAwKTtcbiAgICB9KTtcbiAgfVxufSAiXX0=