@libs-ui/components-audio 0.2.227 → 0.2.229
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.
|
@@ -461,13 +461,13 @@ export class MyComponent {
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAudioDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
464
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsAudioDemoComponent, isStandalone: true, selector: "lib-audio-demo", viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAudioComponent, selector: "libs_ui-components-audio", inputs: ["fileAudio", "checkPermissionDownloadAudio"], outputs: ["outFunctionsControl", "outVolumeControl", "outTimeUpdate", "outEnded", "outMute", "outPlay"] }] });
|
|
464
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsAudioDemoComponent, isStandalone: true, selector: "lib-audio-demo", viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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 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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAudioComponent, selector: "libs_ui-components-audio", inputs: ["fileAudio", "checkPermissionDownloadAudio"], outputs: ["outFunctionsControl", "outVolumeControl", "outTimeUpdate", "outEnded", "outMute", "outPlay"] }] });
|
|
465
465
|
}
|
|
466
466
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAudioDemoComponent, decorators: [{
|
|
467
467
|
type: Component,
|
|
468
|
-
args: [{ selector: 'lib-audio-demo', standalone: true, imports: [LibsUiComponentsAudioComponent], template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"] }]
|
|
468
|
+
args: [{ selector: 'lib-audio-demo', standalone: true, imports: [LibsUiComponentsAudioComponent], template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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 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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"] }]
|
|
469
469
|
}], propDecorators: { audioPlayer: [{
|
|
470
470
|
type: ViewChild,
|
|
471
471
|
args: ['audioPlayer']
|
|
472
472
|
}] } });
|
|
473
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaW8tZGVtby5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXVkaW8vc3JjL2RlbW8vYXVkaW8tZGVtby5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXVkaW8vc3JjL2RlbW8vYXVkaW8tZGVtby5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLG9CQUFvQixDQUFDOztBQVVwRSxNQUFNLE9BQU8sa0NBQWtDO0lBQ25CLFdBQVcsQ0FBa0M7SUFFdkUsc0JBQXNCO0lBQ2YsU0FBUyxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUNuQyxPQUFPLEdBQUcsTUFBTSxDQUFVLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sR0FBRyxNQUFNLENBQVMsR0FBRyxDQUFDLENBQUM7SUFDN0IsV0FBVyxHQUFHLE1BQU0sQ0FBUyxVQUFVLENBQUMsQ0FBQztJQUN6QyxRQUFRLEdBQUcsTUFBTSxDQUFTLFVBQVUsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsR0FBRyxNQUFNLENBQVMsQ0FBQyxDQUFDLENBQUM7SUFFcEMsMkNBQTJDO0lBQ3BDLGFBQWEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRWpFLHdCQUF3QjtJQUNqQixhQUFhLEdBQUcsTUFBTSxDQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLGtCQUFrQixHQUFHLE1BQU0sQ0FBUyxpSEFBaUgsQ0FBQyxDQUFDO0lBRTlKLDZCQUE2QjtJQUN0QixnQkFB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bmVudCwgVmlld0NoaWxkLCBjb21wdXRlZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQgfSBmcm9tICcuLi9hdWRpby5jb21wb25lbnQnO1xuaW1wb3J0IHsgSUF1ZGlvRnVuY3Rpb25Db250cm9sRXZlbnQgfSBmcm9tICcuLi9pbnRlcmZhY2VzL2Z1bmN0aW9uLWNvbnRyb2wtZXZlbnQuaW50ZXJmYWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLWF1ZGlvLWRlbW8nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0F1ZGlvQ29tcG9uZW50XSxcbiAgdGVtcGxhdGVVcmw6ICcuL2F1ZGlvLWRlbW8uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9hdWRpby1kZW1vLmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzQXVkaW9EZW1vQ29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgnYXVkaW9QbGF5ZXInKSBhdWRpb1BsYXllciE6IExpYnNVaUNvbXBvbmVudHNBdWRpb0NvbXBvbmVudDtcblxuICAvLyBTdGF0ZSB1c2luZyBzaWduYWxzXG4gIHB1YmxpYyBpc1BsYXlpbmcgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuICBwdWJsaWMgaXNNdXRlZCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHB1YmxpYyB2b2x1bWUgPSBzaWduYWw8bnVtYmVyPigxMDApO1xuICBwdWJsaWMgY3VycmVudFRpbWUgPSBzaWduYWw8c3RyaW5nPignMDA6MDA6MDAnKTtcbiAgcHVibGljIGR1cmF0aW9uID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwOjAwJyk7XG4gIHB1YmxpYyBwcm9ncmVzcyA9IHNpZ25hbDxudW1iZXI+KDApO1xuXG4gIC8vIENvbXB1dGVkIHByb3BlcnRpZXMgZm9yIHRlbXBsYXRlIGRpc3BsYXlcbiAgcHVibGljIHZvbHVtZVBlcmNlbnQgPSBjb21wdXRlZCgoKSA9PiBNYXRoLnJvdW5kKHRoaXMudm9sdW1lKCkpKTtcblxuICAvLyBTZWxlY3RlZCBhdWRpbyBzYW1wbGVcbiAgcHVibGljIHNlbGVjdGVkQXVkaW8gPSBzaWduYWw8bnVtYmVyPigxKTtcbiAgcHVibGljIGN1cnJlbnRBdWRpb1NvdXJjZSA9IHNpZ25hbDxzdHJpbmc+KCdodHRwczovL25oYWNjaHVvbmcxMjMuY29tL25oYWMtY2h1b25nL2FiY2RlZmdoL25oYWMtY2h1b25nLW5ndW9pLWF5LWRhdS1jby1kYW5nLWFraXJhLXBoYW4tbmd1eWVuLXZhbi1jaHVuZy5tcDMnKTtcblxuICAvLyBGdW5jdGlvbiBDb250cm9sIHZhcmlhYmxlc1xuICBwdWJsaWMgZnVuY3Rpb25Db250cm9sczogSUF1ZGlvRnVuY3Rpb25Db250cm9sRXZlbnQgfCBudWxsID0gbnVsbDtcblxuICAvLyBBdWRpbyBzYW1wbGVzIGZvciBkZW1vXG4gIHB1YmxpYyBhdWRpb1NhbXBsZXMgPSBzaWduYWw8QXJyYXk8eyBpZDogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIHNyYzogc3RyaW5nLCBkdXJhdGlvbjogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgaWQ6IDEsXG4gICAgICBuYW1lOiAnQuG6o24gbmjhuqFjIG3huqt1IDEnLFxuICAgICAgc3JjOiAnaHR0cHM6Ly9uaGFjY2h1b25nMTIzLmNvbS9uaGFjLWNodW9uZy9hYmNkZWZnaC9uaGFjLWNodW9uZy1uZ3VvaS1heS1kYXUtY28tZGFuZy1ha2lyYS1waGFuLW5ndXllbi12YW4tY2h1bmcubXAzJyxcbiAgICAgIGR1cmF0aW9uOiAnMDE6MzAnXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMixcbiAgICAgIG5hbWU6ICdC4bqjbiBuaOG6oWMgbeG6q3UgMicsXG4gICAgICBzcmM6ICdodHRwczovL3d3dy5zb3VuZGhlbGl4LmNvbS9leGFtcGxlcy9tcDMvU291bmRIZWxpeC1Tb25nLTEubXAzJyxcbiAgICAgIGR1cmF0aW9uOiAnMDI6MTUnXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMyxcbiAgICAgIG5hbWU6ICdC4bqjbiBuaOG6oWMgbeG6q3UgMycsXG4gICAgICBzcmM6ICdodHRwczovL2RsLmRyb3Bib3h1c2VyY29udGVudC5jb20vcy83NWpwbmdyZ25hdnl1MWYvVGhlLU5vaXN5LUZyZWFrcy5tcDMnLFxuICAgICAgZHVyYXRpb246ICcwMzo0NSdcbiAgICB9XG4gIF0pO1xuXG4gIC8vIEFQSSBEb2N1bWVudGF0aW9uIGRhdGFcbiAgcHVibGljIGlucHV0c0RvYyA9IHNpZ25hbDxBcnJheTx7IG5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBkZWZhdWx0OiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4+KFtcbiAgICB7XG4gICAgICBuYW1lOiAnZmlsZUF1ZGlvJyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgZGVmYXVsdDogJ0Lhuq90IGJ14buZYycsXG4gICAgICBkZXNjcmlwdGlvbjogJ1VSTCBj4bunYSBmaWxlIGF1ZGlvIGPhuqduIHBow6F0J1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW8nLFxuICAgICAgdHlwZTogJygpID0+IFByb21pc2U8Ym9vbGVhbj4nLFxuICAgICAgZGVmYXVsdDogJ0Lhuq90IGJ14buZYycsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Z1bmN0aW9uIHRy4bqjIHbhu4EgcHJvbWlzZSB24bubaSBr4bq/dCBxdeG6oyBib29sZWFuIGNobyBiaeG6v3QgbuG6v3UgxJHGsOG7o2MgcGjDqXAgZG93bmxvYWQnXG4gICAgfVxuICBdKTtcblxuICAvLyBPdXRwdXQgZG9jdW1lbnRhdGlvblxuICBwdWJsaWMgb3V0cHV0c0RvYyA9IHNpZ25hbDxBcnJheTx7IG5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgbmFtZTogJ291dEZ1bmN0aW9uc0NvbnRyb2wnLFxuICAgICAgdHlwZTogJ0lBdWRpb0Z1bmN0aW9uQ29udHJvbEV2ZW50JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW1pdHMgY8OhYyBow6BtIMSRaeG7gXUga2hp4buDbiBhdWRpbydcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdvdXRWb2x1bWVDb250cm9sJyxcbiAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgZGVzY3JpcHRpb246ICdFbWl0cyBnacOhIHRy4buLIMOibSBsxrDhu6NuZyBoaeG7h24gdOG6oWkgKDAtMTAwKSdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdvdXRUaW1lVXBkYXRlJyxcbiAgICAgIHR5cGU6ICd7IGN1cnJlbnRUaW1lOiBzdHJpbmcsIGR1cmF0aW9uOiBzdHJpbmcgfScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VtaXRzIHRow7RuZyB0aW4gdGjhu51pIGdpYW4gaGnhu4duIHThuqFpIHbDoCB04buVbmcgdGjhu51pIGdpYW4nXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnb3V0RW5kZWQnLFxuICAgICAgdHlwZTogJ3ZvaWQnLFxuICAgICAgZGVzY3JpcHRpb246ICdFbWl0cyBraGkgYXVkaW8ga+G6v3QgdGjDumMgcGjDoXQnXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnb3V0TXV0ZScsXG4gICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VtaXRzIHRy4bqhbmcgdGjDoWkgdOG6r3QvYuG6rXQgdGnhur9uZydcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdvdXRQbGF5JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW1pdHMgdHLhuqFuZyB0aMOhaSBwaMOhdC904bqhbSBk4burbmcnXG4gICAgfVxuICBdKTtcblxuICAvLyBJbnRlcmZhY2UgZG9jdW1lbnRhdGlvblxuICBwdWJsaWMgaW50ZXJmYWNlc0RvYyA9IHNpZ25hbDxBcnJheTx7IG5hbWU6IHN0cmluZywgZGVzY3JpcHRpb246IHN0cmluZywgcHJvcGVydGllczogQXJyYXk8eyBuYW1lOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgZGVzY3JpcHRpb246IHN0cmluZyB9PiB9Pj4oW1xuICAgIHtcbiAgICAgIG5hbWU6ICdJQXVkaW9GdW5jdGlvbkNvbnRyb2xFdmVudCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSBjaG8gY8OhYyBjaOG7qWMgbsSDbmcgxJFp4buBdSBraGnhu4NuIGF1ZGlvIMSRxrDhu6NjIGN1bmcgY+G6pXAgcXVhIG91dHB1dCBldmVudCcsXG4gICAgICBwcm9wZXJ0aWVzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAncGxheVBhdXNlJyxcbiAgICAgICAgICB0eXBlOiAnKGV2ZW50PzogRXZlbnQpID0+IHZvaWQnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnQuG6r3QgxJHhuqd1IGhv4bq3YyB04bqhbSBk4burbmcgcGjDoXQgYXVkaW8nXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAndG9nZ2xlTXV0ZScsXG4gICAgICAgICAgdHlwZTogJyhldmVudD86IEV2ZW50KSA9PiB2b2lkJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ0Lhuq10IGhv4bq3YyB04bqvdCDDom0gdGhhbmgnXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnc2V0Vm9sdW1lJyxcbiAgICAgICAgICB0eXBlOiAnKHZhbHVlOiBudW1iZXIpID0+IHZvaWQnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnxJBp4buBdSBjaOG7iW5oIMOibSBsxrDhu6NuZyAoZ2nDoSB0cuG7iyB04burIDAgxJHhur9uIDEwMCknXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnc2Vla1RvJyxcbiAgICAgICAgICB0eXBlOiAnKHZhbHVlOiBudW1iZXIpID0+IHZvaWQnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnRGkgY2h1eeG7g24gxJHhur9uIHbhu4sgdHLDrSBj4bulIHRo4buDIHRyb25nIGF1ZGlvIChnacOhIHRy4buLIHThu6sgMCDEkeG6v24gMTAwKSdcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdkb3dubG9hZCcsXG4gICAgICAgICAgdHlwZTogJyhldmVudD86IEV2ZW50KSA9PiB2b2lkJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1ThuqNpIHh14buRbmcgZmlsZSBhdWRpbydcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdpc1BsYXlpbmcnLFxuICAgICAgICAgIHR5cGU6ICcoKSA9PiBib29sZWFuJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ0tp4buDbSB0cmEgdHLhuqFuZyB0aMOhaSDEkWFuZyBwaMOhdCBhdWRpbydcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdpc011dGVkJyxcbiAgICAgICAgICB0eXBlOiAnKCkgPT4gYm9vbGVhbicsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdLaeG7g20gdHJhIHRy4bqhbmcgdGjDoWkgdOG6r3QgdGnhur9uZydcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH1cbiAgXSk7XG5cbiAgLy8gTWV0aG9kIGRvY3VtZW50YXRpb25cbiAgcHVibGljIG1ldGhvZHNEb2MgPSBzaWduYWw8QXJyYXk8eyBuYW1lOiBzdHJpbmcsIHBhcmFtczogc3RyaW5nLCByZXR1cm5UeXBlOiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4+KFtcbiAgICB7XG4gICAgICBuYW1lOiAncGxheVBhdXNlJyxcbiAgICAgIHBhcmFtczogJ2V2ZW50PzogRXZlbnQnLFxuICAgICAgcmV0dXJuVHlwZTogJ3ZvaWQnLFxuICAgICAgZGVzY3JpcHRpb246ICdQaMOhdCBob+G6t2MgdOG6oW0gZOG7q25nIGF1ZGlvJ1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ3RvZ2dsZU11dGUnLFxuICAgICAgcGFyYW1zOiAnZXZlbnQ/OiBFdmVudCcsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Lhuq10L3Thuq90IMOibSB0aGFuaCdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdzZWVrVG8nLFxuICAgICAgcGFyYW1zOiAndmFsdWU6IG51bWJlcicsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0RpIGNodXnhu4NuIMSR4bq/biB24buLIHRyw60gY+G7pSB0aOG7gyB0cm9uZyBhdWRpbyAoZ2nDoSB0cuG7iyB04burIDAtMTAwKSdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdzZXRWb2x1bWUnLFxuICAgICAgcGFyYW1zOiAndmFsdWU6IG51bWJlcicsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ8SQaeG7gXUgY2jhu4luaCDDom0gbMaw4bujbmcgKGdpw6EgdHLhu4sgdOG7qyAwLTEwMCknXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnZG93bmxvYWQnLFxuICAgICAgcGFyYW1zOiAnZXZlbnQ/OiBFdmVudCcsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ1ThuqNpIHh14buRbmcgZmlsZSBhdWRpbydcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdpc1BsYXlpbmcnLFxuICAgICAgcGFyYW1zOiAnJyxcbiAgICAgIHJldHVyblR5cGU6ICdib29sZWFuJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnS2nhu4NtIHRyYSBu4bq/dSBhdWRpbyDEkWFuZyBwaMOhdCdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdpc011dGVkJyxcbiAgICAgIHBhcmFtczogJycsXG4gICAgICByZXR1cm5UeXBlOiAnYm9vbGVhbicsXG4gICAgICBkZXNjcmlwdGlvbjogJ0tp4buDbSB0cmEgbuG6v3UgYXVkaW8gxJFhbmcgdOG6r3QgdGnhur9uZydcbiAgICB9XG4gIF0pO1xuXG4gIC8vIEZlYXR1cmVzIGRhdGFcbiAgcHVibGljIGZlYXR1cmVzID0gc2lnbmFsPEFycmF5PHsgaWQ6IG51bWJlciwgaWNvbjogc3RyaW5nLCB0aXRsZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgaWQ6IDEsXG4gICAgICBpY29uOiAn4pa277iPJyxcbiAgICAgIHRpdGxlOiAnxJBp4buBdSBraGnhu4NuIGF1ZGlvJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnxJBp4buBdSBraGnhu4NuIGF1ZGlvIGNvbXBvbmVudCBxdWEgY8OhYyBBUEknXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMixcbiAgICAgIGljb246ICfwn5SKJyxcbiAgICAgIHRpdGxlOiAnUXXhuqNuIGzDvSDDom0gbMaw4bujbmcnLFxuICAgICAgZGVzY3JpcHRpb246ICfEkGnhu4F1IGNo4buJbmggw6JtIGzGsOG7o25nIHbDoCB04bqvdCB0aeG6v25nIHbhu5tpIHRoYW5oIHRyxrDhu6N0IHRy4buxYyBxdWFuJ1xuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDMsXG4gICAgICBpY29uOiAn4o+x77iPJyxcbiAgICAgIHRpdGxlOiAnSGnhu4NuIHRo4buLIHRo4budaSBnaWFuJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnSGnhu4NuIHRo4buLIHRo4budaSBnaWFuIGhp4buHbiB04bqhaSB2w6AgdOG7lW5nIHRo4budaSBnaWFuIHRoZW8gxJHhu4tuaCBk4bqhbmcgSEg6TU06U1MnXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogNCxcbiAgICAgIGljb246ICfwn5OKJyxcbiAgICAgIHRpdGxlOiAnVGhhbmggdGnhur9uIMSR4buZJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhhbmggdGnhur9uIMSR4buZIGPDsyB0aOG7gyB0xrDGoW5nIHTDoWMgxJHhu4MgdHVhIG5oYW5oIGhv4bq3YyB0dWEgbOG6oWknXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogNSxcbiAgICAgIGljb246ICfwn5OlJyxcbiAgICAgIHRpdGxlOiAnVOG6o2kgeHXhu5FuZycsXG4gICAgICBkZXNjcmlwdGlvbjogJ0jhu5cgdHLhu6MgdOG6o2kgeHXhu5FuZyBmaWxlIMOibSB0aGFuaCB24bubaSBraeG7g20gc2/DoXQgcXV54buBbidcbiAgICB9XG4gIF0pO1xuXG4gIC8vIENvZGUgZXhhbXBsZXMgZGF0YVxuICBwdWJsaWMgY29kZUV4YW1wbGVzID0gc2lnbmFsPEFycmF5PHsgaWQ6IG51bWJlciwgdGl0bGU6IHN0cmluZywgY29kZTogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgaWQ6IDEsXG4gICAgICB0aXRsZTogJ0PDoGkgxJHhurd0IGPGoSBi4bqjbicsXG4gICAgICBjb2RlOiBgJmx0O2xpYnNfdWktY29tcG9uZW50cy1hdWRpb1xuICBbZmlsZUF1ZGlvXT1cIidwYXRoL3RvL2F1ZGlvLm1wMydcIlxuICBbY2hlY2tQZXJtaXNzaW9uRG93bmxvYWRBdWRpb109XCJjaGVja1Blcm1pc3Npb25cIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWF1ZGlvJmd0O2BcbiAgICB9LFxuICAgIHtcbiAgICAgIGlkOiAyLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyBGdW5jdGlvbiBDb250cm9sJyxcbiAgICAgIGNvZGU6IGBpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWF1ZGlvJztcbmltcG9ydCB7IElBdWRpb0Z1bmN0aW9uQ29udHJvbEV2ZW50IH0gZnJvbSAnQGxpYnMtdWkvY29tcG9uZW50cy1hdWRpbyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1teS1jb21wb25lbnQnLFxuICB0ZW1wbGF0ZTogXFxgXG4gICAgJmx0O2xpYnNfdWktY29tcG9uZW50cy1hdWRpb1xuICAgICAgI2F1ZGlvUGxheWVyXG4gICAgICBbZmlsZUF1ZGlvXT1cImF1ZGlvU291cmNlKClcIlxuICAgICAgW2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW9dPVwiY2hlY2tQZXJtaXNzaW9uXCJcbiAgICAgIChvdXRGdW5jdGlvbnNDb250cm9sKT1cInJlZ2lzdGVyRnVuY3Rpb25zKCRldmVudClcIiZndDtcbiAgICAmbHQ7L2xpYnNfdWktY29tcG9uZW50cy1hdWRpbyZndDtcbiAgICBcbiAgICAmbHQ7YnV0dG9uIChjbGljayk9XCJwbGF5QXVkaW8oKVwiJmd0O1Bow6F0L1ThuqFtIGThu6tuZyZsdDsvYnV0dG9uJmd0O1xuICBcXGBcbn0pXG5leHBvcnQgY2xhc3MgTXlDb21wb25lbnQge1xuICBAVmlld0NoaWxkKCdhdWRpb1BsYXllcicpIGF1ZGlvUGxheWVyITogTGlic1VpQ29tcG9uZW50c0F1ZGlvQ29tcG9uZW50O1xuICBhdWRpb1NvdXJjZSA9IHNpZ25hbDxzdHJpbmc+KCdwYXRoL3RvL2F1ZGlvLm1wMycpO1xuICBmdW5jdGlvbkNvbnRyb2xzOiBJQXVkaW9GdW5jdGlvbkNvbnRyb2xFdmVudCB8IG51bGwgPSBudWxsO1xuICBcbiAgcmVnaXN0ZXJGdW5jdGlvbnMoZXZlbnQ6IElBdWRpb0Z1bmN0aW9uQ29udHJvbEV2ZW50KSB7XG4gICAgdGhpcy5mdW5jdGlvbkNvbnRyb2xzID0gZXZlbnQ7XG4gIH1cbiAgXG4gIHBsYXlBdWRpbygpIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMucGxheVBhdXNlKCk7XG4gICAgfVxuICB9XG59YFxuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDMsXG4gICAgICB0aXRsZTogJ1Phu60gZOG7pW5nIEV2ZW50cyDEkeG7gyBj4bqtcCBuaOG6rXQgVUknLFxuICAgICAgY29kZTogYGltcG9ydCB7IENvbXBvbmVudCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWF1ZGlvJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLW15LWNvbXBvbmVudCcsXG4gIHRlbXBsYXRlOiBcXGBcbiAgICAmbHQ7bGlic191aS1jb21wb25lbnRzLWF1ZGlvXG4gICAgICBbZmlsZUF1ZGlvXT1cImF1ZGlvU291cmNlKClcIlxuICAgICAgW2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW9dPVwiY2hlY2tQZXJtaXNzaW9uXCJcbiAgICAgIChvdXRUaW1lVXBkYXRlKT1cImhhbmRsZVRpbWVVcGRhdGUoJGV2ZW50KVwiXG4gICAgICAob3V0Vm9sdW1lQ29udHJvbCk9XCJoYW5kbGVWb2x1bWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAob3V0UGxheSk9XCJoYW5kbGVQbGF5Q2hhbmdlKCRldmVudClcIlxuICAgICAgKG91dE11dGUpPVwiaGFuZGxlTXV0ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIChvdXRFbmRlZCk9XCJoYW5kbGVFbmRlZCgpXCImZ3Q7XG4gICAgJmx0Oy9saWJzX3VpLWNvbXBvbmVudHMtYXVkaW8mZ3Q7XG4gICAgXG4gICAgJmx0O2RpdiBjbGFzcz1cImF1ZGlvLWluZm9cIiZndDtcbiAgICAgICZsdDtwJmd0O1Ry4bqhbmcgdGjDoWk6IHt7IGlzUGxheWluZygpID8gJ8SQYW5nIHBow6F0JyA6ICdU4bqhbSBk4burbmcnIH19Jmx0Oy9wJmd0O1xuICAgICAgJmx0O3AmZ3Q7VGjhu51pIGdpYW4gaGnhu4duIHThuqFpOiB7eyBjdXJyZW50VGltZSgpIH19Jmx0Oy9wJmd0O1xuICAgICAgJmx0O3AmZ3Q7VOG7lW5nIHRo4budaSBnaWFuOiB7eyBkdXJhdGlvbigpIH19Jmx0Oy9wJmd0O1xuICAgICAgJmx0O3AmZ3Q7w4JtIGzGsOG7o25nOiB7eyB2b2x1bWVMZXZlbCgpIH19JSZsdDsvcCZndDtcbiAgICAmbHQ7L2RpdiZndDtcbiAgXFxgXG59KVxuZXhwb3J0IGNsYXNzIE15Q29tcG9uZW50IHtcbiAgYXVkaW9Tb3VyY2UgPSBzaWduYWw8c3RyaW5nPigncGF0aC90by9hdWRpby5tcDMnKTtcbiAgaXNQbGF5aW5nID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgaXNNdXRlZCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIGN1cnJlbnRUaW1lID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwOjAwJyk7XG4gIGR1cmF0aW9uID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwOjAwJyk7XG4gIHZvbHVtZUxldmVsID0gc2lnbmFsPG51bWJlcj4oMTAwKTtcbiAgXG4gIGNoZWNrUGVybWlzc2lvbiA9ICgpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICB9XG4gIFxuICBoYW5kbGVUaW1lVXBkYXRlKHRpbWVJbmZvOiB7IGN1cnJlbnRUaW1lOiBzdHJpbmcsIGR1cmF0aW9uOiBzdHJpbmcgfSkge1xuICAgIHRoaXMuY3VycmVudFRpbWUuc2V0KHRpbWVJbmZvLmN1cnJlbnRUaW1lKTtcbiAgICB0aGlzLmR1cmF0aW9uLnNldCh0aW1lSW5mby5kdXJhdGlvbik7XG4gIH1cbiAgXG4gIGhhbmRsZVZvbHVtZUNoYW5nZSh2b2x1bWU6IG51bWJlcikge1xuICAgIHRoaXMudm9sdW1lTGV2ZWwuc2V0KHZvbHVtZSk7XG4gIH1cbiAgXG4gIGhhbmRsZVBsYXlDaGFuZ2UoaXNQbGF5aW5nOiBib29sZWFuKSB7XG4gICAgdGhpcy5pc1BsYXlpbmcuc2V0KGlzUGxheWluZyk7XG4gIH1cbiAgXG4gIGhhbmRsZU11dGVDaGFuZ2UoaXNNdXRlZDogYm9vbGVhbikge1xuICAgIHRoaXMuaXNNdXRlZC5zZXQoaXNNdXRlZCk7XG4gIH1cbiAgXG4gIGhhbmRsZUVuZGVkKCkge1xuICAgIHRoaXMuaXNQbGF5aW5nLnNldChmYWxzZSk7XG4gIH1cbn1gXG4gICAgfVxuICBdKTtcblxuICAvLyBDb250cm9sIG1ldGhvZHNcbiAgcHVibGljIHBsYXlBdWRpbygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMucGxheVBhdXNlKCk7XG4gICAgICB0aGlzLmlzUGxheWluZy5zZXQodGhpcy5mdW5jdGlvbkNvbnRyb2xzLmlzUGxheWluZygpKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgdG9nZ2xlTXV0ZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMudG9nZ2xlTXV0ZSgpO1xuICAgICAgdGhpcy5pc011dGVkLnNldCh0aGlzLmZ1bmN0aW9uQ29udHJvbHMuaXNNdXRlZCgpKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgY2hhbmdlVm9sdW1lKGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmZ1bmN0aW9uQ29udHJvbHMgJiYgZXZlbnQudGFyZ2V0KSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHBhcnNlSW50KChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUpO1xuICAgICAgdGhpcy52b2x1bWUuc2V0KHZhbHVlKTtcbiAgICAgIHRoaXMuZnVuY3Rpb25Db250cm9scy5zZXRWb2x1bWUodmFsdWUpO1xuICAgICAgdGhpcy5pc011dGVkLnNldCh0aGlzLmZ1bmN0aW9uQ29udHJvbHMuaXNNdXRlZCgpKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZG93bmxvYWRBdWRpbygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMuZG93bmxvYWQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRm9ybWF0IHRo4budaSBnaWFuIHThu6sgZ2nDonkgc2FuZyBjaHXhu5dpIEhIOk1NOlNTXG4gICAqL1xuICBwdWJsaWMgZm9ybWF0VGltZSh0aW1lSW5TZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGlmIChpc05hTih0aW1lSW5TZWNvbmRzKSkgcmV0dXJuICcwMDowMDowMCc7XG5cbiAgICBjb25zdCBob3VycyA9IE1hdGguZmxvb3IodGltZUluU2Vjb25kcyAvIDM2MDApO1xuICAgIGNvbnN0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKCh0aW1lSW5TZWNvbmRzIC0gKGhvdXJzICogMzYwMCkpIC8gNjApO1xuICAgIGNvbnN0IHNlY29uZHMgPSBNYXRoLmZsb29yKHRpbWVJblNlY29uZHMgLSAoaG91cnMgKiAzNjAwKSAtIChtaW51dGVzICogNjApKTtcblxuICAgIHJldHVybiBgJHtob3Vycy50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9OiR7bWludXRlcy50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9OiR7c2Vjb25kcy50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYW8gY2jDqXAgdGV4dCB2w6BvIGNsaXBib2FyZFxuICAgKi9cbiAgcHVibGljIGNvcHlUb0NsaXBib2FyZCh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0ZXh0KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBhbGVydCgnxJDDoyBzYW8gY2jDqXAgdsOgbyBjbGlwYm9hcmQhJyk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBjb3B5OiAnLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogxJDEg25nIGvDvSBjw6FjIGZ1bmN0aW9uIGNvbnRyb2wgdOG7qyBjb21wb25lbnRcbiAgICovXG4gIHB1YmxpYyByZWdpc3RlckZ1bmN0aW9ucyhldmVudDogSUF1ZGlvRnVuY3Rpb25Db250cm9sRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMgPSBldmVudDtcblxuICAgIC8vIEluaXRpYWxpemUgc3RhdGVcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmlzUGxheWluZy5zZXQodGhpcy5mdW5jdGlvbkNvbnRyb2xzLmlzUGxheWluZygpKTtcbiAgICAgIHRoaXMuaXNNdXRlZC5zZXQodGhpcy5mdW5jdGlvbkNvbnRyb2xzLmlzTXV0ZWQoKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFjhu60gbMO9IHPhu7Ega2nhu4duIHRoYXkgxJHhu5VpIHRo4budaSBnaWFuXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlVGltZVVwZGF0ZSh0aW1lSW5mbzogeyBjdXJyZW50VGltZTogc3RyaW5nLCBkdXJhdGlvbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRUaW1lLnNldCh0aW1lSW5mby5jdXJyZW50VGltZSk7XG4gICAgdGhpcy5kdXJhdGlvbi5zZXQodGltZUluZm8uZHVyYXRpb24pO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHByb2dyZXNzIGJhc2VkIG9uIGN1cnJlbnRUaW1lIGFuZCBkdXJhdGlvblxuICAgIGNvbnN0IHJlZ2V4ID0gLyhcXGQrKTooXFxkKyk6KFxcZCspLztcbiAgICBjb25zdCBjdXJyZW50TWF0Y2hlcyA9IHRpbWVJbmZvLmN1cnJlbnRUaW1lLm1hdGNoKHJlZ2V4KTtcbiAgICBjb25zdCBkdXJhdGlvbk1hdGNoZXMgPSB0aW1lSW5mby5kdXJhdGlvbi5tYXRjaChyZWdleCk7XG5cbiAgICBpZiAoY3VycmVudE1hdGNoZXMgJiYgZHVyYXRpb25NYXRjaGVzKSB7XG4gICAgICBjb25zdCBjdXJyZW50U2Vjb25kcyA9XG4gICAgICAgIHBhcnNlSW50KGN1cnJlbnRNYXRjaGVzWzFdKSAqIDM2MDAgK1xuICAgICAgICBwYXJzZUludChjdXJyZW50TWF0Y2hlc1syXSkgKiA2MCArXG4gICAgICAgIHBhcnNlSW50KGN1cnJlbnRNYXRjaGVzWzNdKTtcblxuICAgICAgY29uc3QgdG90YWxTZWNvbmRzID1cbiAgICAgICAgcGFyc2VJbnQoZHVyYXRpb25NYXRjaGVzWzFdKSAqIDM2MDAgK1xuICAgICAgICBwYXJzZUludChkdXJhdGlvbk1hdGNoZXNbMl0pICogNjAgK1xuICAgICAgICBwYXJzZUludChkdXJhdGlvbk1hdGNoZXNbM10pO1xuXG4gICAgICBpZiAodG90YWxTZWNvbmRzID4gMCkge1xuICAgICAgICB0aGlzLnByb2dyZXNzLnNldChNYXRoLmZsb29yKChjdXJyZW50U2Vjb25kcyAvIHRvdGFsU2Vjb25kcykgKiAxMDApKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogWOG7rSBsw70gc+G7sSBraeG7h24gdGhheSDEkeG7lWkgw6JtIGzGsOG7o25nXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlVm9sdW1lQ2hhbmdlKHZvbHVtZTogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy52b2x1bWUuc2V0KHZvbHVtZSk7XG4gIH1cblxuICAvKipcbiAgICogWOG7rSBsw70gc+G7sSBraeG7h24gdGhheSDEkeG7lWkgdHLhuqFuZyB0aMOhaSBwaMOhdFxuICAgKi9cbiAgcHVibGljIGhhbmRsZVBsYXlDaGFuZ2UoaXNQbGF5aW5nOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pc1BsYXlpbmcuc2V0KGlzUGxheWluZyk7XG4gIH1cblxuICAvKipcbiAgICogWOG7rSBsw70gc+G7sSBraeG7h24gdGhheSDEkeG7lWkgdHLhuqFuZyB0aMOhaSB04bqvdCB0aeG6v25nXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlTXV0ZUNoYW5nZShpc011dGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pc011dGVkLnNldChpc011dGVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBY4butIGzDvSBz4buxIGtp4buHbiBr4bq/dCB0aMO6YyBwaMOhdFxuICAgKi9cbiAgcHVibGljIGhhbmRsZUVuZGVkKCk6IHZvaWQge1xuICAgIHRoaXMuaXNQbGF5aW5nLnNldChmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogQ2jhu41uIG3huqt1IMOibSB0aGFuaFxuICAgKi9cbiAgcHVibGljIHNlbGVjdEF1ZGlvKGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkQXVkaW8uc2V0KGlkKTtcbiAgICBjb25zdCBzYW1wbGUgPSB0aGlzLmF1ZGlvU2FtcGxlcygpLmZpbmQoYXVkaW8gPT4gYXVkaW8uaWQgPT09IGlkKTtcbiAgICBpZiAoc2FtcGxlKSB7XG4gICAgICAvLyBSZXNldCBhdWRpbyBzdGF0ZVxuICAgICAgdGhpcy5pc1BsYXlpbmcuc2V0KGZhbHNlKTtcbiAgICAgIHRoaXMucHJvZ3Jlc3Muc2V0KDApO1xuICAgICAgdGhpcy5jdXJyZW50VGltZS5zZXQoJzAwOjAwOjAwJyk7XG4gICAgICB0aGlzLmR1cmF0aW9uLnNldCgnMDA6MDA6MDAnKTtcblxuICAgICAgLy8gU2ltcGx5IHVwZGF0ZSB0aGUgc291cmNlIC0gdGhlIGNvbXBvbmVudCB3aWxsIGhhbmRsZSB0aGUgcmVsb2FkXG4gICAgICB0aGlzLmN1cnJlbnRBdWRpb1NvdXJjZS5zZXQoc2FtcGxlLnNyYyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEtp4buDbSB0cmEgcXV54buBbiB04bqjaSB4deG7kW5nXG4gICAqL1xuICBwdWJsaWMgY2hlY2tEb3dubG9hZFBlcm1pc3Npb24gPSAoKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGF5IMSR4buVaSB24buLIHRyw60gcGjDoXQgYuG6sW5nIGPDoWNoIGNsaWNrIHRy4buxYyB0aeG6v3AgdsOgbyB0aGFuaCB0aeG6v24gxJHhu5lcbiAgICovXG4gIHB1YmxpYyBzZWVrQXVkaW9CeUNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZnVuY3Rpb25Db250cm9scykge1xuICAgICAgY29uc3QgcHJvZ3Jlc3NCYXIgPSBldmVudC5jdXJyZW50VGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgY29uc3QgcmVjdCA9IHByb2dyZXNzQmFyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3Qgb2Zmc2V0WCA9IGV2ZW50LmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgICBjb25zdCBwZXJjZW50WCA9IChvZmZzZXRYIC8gcmVjdC53aWR0aCkgKiAxMDA7XG5cbiAgICAgIC8vIMSQ4bqjbSBi4bqjbyBnacOhIHRy4buLIG7hurFtIHRyb25nIGtob+G6o25nIDAtMTAwXG4gICAgICBjb25zdCBjbGFtcGVkUGVyY2VudCA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEwMCwgcGVyY2VudFgpKTtcbiAgICAgIHRoaXMucHJvZ3Jlc3Muc2V0KE1hdGgucm91bmQoY2xhbXBlZFBlcmNlbnQpKTtcblxuICAgICAgLy8gR+G7jWkgbWV0aG9kIHNlZWtUbyDEkeG7gyBj4bqtcCBuaOG6rXQgduG7iyB0csOtIHBow6F0XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMuc2Vla1RvKHRoaXMucHJvZ3Jlc3MoKSk7XG4gICAgfVxuICB9XG59IFxuIiwiPGRpdiBjbGFzcz1cIm1heC13LTd4bCBteC1hdXRvIHB4LTQgc206cHgtNiBsZzpweC04IGZvbnQtc2FucyB0ZXh0LWdyYXktODAwXCI+XG4gIDxoZWFkZXIgY2xhc3M9XCJ0ZXh0LWNlbnRlciBweS0xMCBiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdyBtYi04XCI+XG4gICAgPGgxIGNsYXNzPVwidGV4dC00eGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItMlwiPkRlbW8gVHLDrG5oIFBow6F0IMOCbSBUaGFuaDwvaDE+XG4gICAgPHAgY2xhc3M9XCJ0ZXh0LXhsIHRleHQtZ3JheS02MDBcIj5UaMawIHZp4buHbiBjb21wb25lbnQgY2hvIEFuZ3VsYXIgxJHhu4MgcGjDoXQgdsOgIMSRaeG7gXUga2hp4buDbiDDom0gdGhhbmg8L3A+XG4gIDwvaGVhZGVyPlxuXG4gIDxtYWluPlxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBzaGFkb3cgcC04IG1iLThcIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTQgcGItMiBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5HaeG7m2kgdGhp4buHdTwvaDI+XG4gICAgICA8cCBjbGFzcz1cInRleHQtbGdcIj5cbiAgICAgICAgPGNvZGUgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+JiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtYXVkaW88L2NvZGU+IGzDoCBt4buZdFxuICAgICAgICBjb21wb25lbnQgQW5ndWxhciBt4bqhbmggbeG6vSBjaG8gcGjDqXAgbmfGsOG7nWkgZMO5bmcgcGjDoXQsIHThuqFtIGThu6tuZyB2w6AgxJFp4buBdSBraGnhu4NuIGPDoWMgdOG7h3Agw6JtIHRoYW5oIHbhu5tpIG5oaeG7gXUgdMOtbmggbsSDbmcuXG4gICAgICA8L3A+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdyBwLTggbWItOFwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNCBwYi0yIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkPDoGkgxJHhurd0PC9oMj5cbiAgICAgIDxwPsSQ4buDIGPDoGkgxJHhurd0IHRoxrAgdmnhu4duLCBz4butIGThu6VuZyBucG0gaG/hurdjIHlhcm46PC9wPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwicmVsYXRpdmUgbXktNFwiPlxuICAgICAgICA8cHJlXG4gICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZCBvdmVyZmxvdy14LWF1dG8gbWItNFwiPjxjb2RlIGNsYXNzPVwiZm9udC1tb25vXCI+bnBtIGluc3RhbGwgJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtYXVkaW88L2NvZGU+PC9wcmU+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBjbGFzcz1cImFic29sdXRlIHRvcC0yIHJpZ2h0LTIgYmctYmx1ZS01MDAgdGV4dC13aGl0ZSBweC0zIHB5LTEgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWJsdWUtNjAwIHRyYW5zaXRpb25cIlxuICAgICAgICAgIChjbGljayk9XCJjb3B5VG9DbGlwYm9hcmQoJ25wbSBpbnN0YWxsIEBsaWJzLXVpL2NvbXBvbmVudHMtYXVkaW8nKVwiPlxuICAgICAgICAgIFNhbyBjaMOpcFxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8cD5Ib+G6t2MgduG7m2kgeWFybjo8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZSBteS00XCI+XG4gICAgICAgIDxwcmVcbiAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkIG92ZXJmbG93LXgtYXV0byBtYi00XCI+PGNvZGUgY2xhc3M9XCJmb250LW1vbm9cIj55YXJuIGFkZCAmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1hdWRpbzwvY29kZT48L3ByZT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiYWJzb2x1dGUgdG9wLTIgcmlnaHQtMiBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHB4LTMgcHktMSByb3VuZGVkIHRleHQtc20gaG92ZXI6YmctYmx1ZS02MDAgdHJhbnNpdGlvblwiXG4gICAgICAgICAgKGNsaWNrKT1cImNvcHlUb0NsaXBib2FyZCgneWFybiBhZGQgQGxpYnMtdWkvY29tcG9uZW50cy1hdWRpbycpXCI+XG4gICAgICAgICAgU2FvIGNow6lwXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdyBwLTggbWItOFwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNCBwYi0yIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkRlbW8gdHLhu7FjIHRp4bq/cDwvaDI+XG4gICAgICA8ZGl2IGNsYXNzPVwiYmctZ3JheS01MCBwLTYgcm91bmRlZC1sZ1wiPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTRcIj5UaOG7rSBuZ2hp4buHbSB0csOsbmggcGjDoXQgw6JtIHRoYW5oIHbhu5tpIGPDoWMgZmlsZSBt4bqrdTo8L3A+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTZcIj5cbiAgICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0zXCI+Q2jhu41uIGZpbGUgw6JtIHRoYW5oOjwvaDM+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTJcIj5cbiAgICAgICAgICAgIEBmb3IgKGF1ZGlvIG9mIGF1ZGlvU2FtcGxlcygpOyB0cmFjayBhdWRpby5pZCkge1xuICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGp1c3RpZnktYmV0d2VlbiBwLTMgYmctd2hpdGUgcm91bmRlZCBib3JkZXIgY3Vyc29yLXBvaW50ZXIgdHJhbnNpdGlvbiBob3ZlcjpiZy1ibHVlLTUwIGhvdmVyOmJvcmRlci1ibHVlLTUwMFwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmJnLWJsdWUtNTBdPVwic2VsZWN0ZWRBdWRpbygpID09PSBhdWRpby5pZFwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmJvcmRlci1ibHVlLTUwMF09XCJzZWxlY3RlZEF1ZGlvKCkgPT09IGF1ZGlvLmlkXCJcbiAgICAgICAgICAgICAgICBbY2xhc3MuZm9udC1tZWRpdW1dPVwic2VsZWN0ZWRBdWRpbygpID09PSBhdWRpby5pZFwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdEF1ZGlvKGF1ZGlvLmlkKVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGF1ZGlvLm5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPHNwYW4+e3sgYXVkaW8uZHVyYXRpb24gfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItNlwiPlxuICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5UcsOsbmggcGjDoXQ6PC9oMz5cbiAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF1ZGlvICNhdWRpb1BsYXllclxuICAgICAgICAgICAgW2ZpbGVBdWRpb109XCJjdXJyZW50QXVkaW9Tb3VyY2UoKVwiXG4gICAgICAgICAgICBbY2hlY2tQZXJtaXNzaW9uRG93bmxvYWRBdWRpb109XCJjaGVja0Rvd25sb2FkUGVybWlzc2lvblwiXG4gICAgICAgICAgICAob3V0RnVuY3Rpb25zQ29udHJvbCk9XCJyZWdpc3RlckZ1bmN0aW9ucygkZXZlbnQpXCJcbiAgICAgICAgICAgIChvdXRUaW1lVXBkYXRlKT1cImhhbmRsZVRpbWVVcGRhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgICAob3V0Vm9sdW1lQ29udHJvbCk9XCJoYW5kbGVWb2x1bWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAob3V0UGxheSk9XCJoYW5kbGVQbGF5Q2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgKG91dE11dGUpPVwiaGFuZGxlTXV0ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIChvdXRFbmRlZCk9XCJoYW5kbGVFbmRlZCgpXCI+XG4gICAgICAgICAgPC9saWJzX3VpLWNvbXBvbmVudHMtYXVkaW8+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtYi02XCI+XG4gICAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItM1wiPsSQaeG7gXUga2hp4buDbiBxdWEgRnVuY3Rpb24gQ29udHJvbDo8L2gzPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtd3JhcCBnYXAtMyBpdGVtcy1jZW50ZXIgYmctd2hpdGUgcC00IHJvdW5kZWQgYm9yZGVyXCI+XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwicHgtNCBweS0yIGJnLWJsdWUtNTAwIHRleHQtd2hpdGUgZm9udC1tZWRpdW0gcm91bmRlZCBob3ZlcjpiZy1ibHVlLTYwMCB0cmFuc2l0aW9uXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInBsYXlBdWRpbygpXCI+XG4gICAgICAgICAgICAgIFBow6F0L1ThuqFtIGThu6tuZ1xuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwicHgtNCBweS0yIGJnLWJsdWUtNTAwIHRleHQtd2hpdGUgZm9udC1tZWRpdW0gcm91bmRlZCBob3ZlcjpiZy1ibHVlLTYwMCB0cmFuc2l0aW9uXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZU11dGUoKVwiPlxuICAgICAgICAgICAgICB7eyBpc011dGVkKCkgPyAnQuG6rXQgdGnhur9uZycgOiAnVOG6r3QgdGnhur9uZycgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTIgbWwtMlwiPlxuICAgICAgICAgICAgICA8c3Bhbj7Dgm0gbMaw4bujbmc6PC9zcGFuPlxuICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInJhbmdlXCJcbiAgICAgICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJ2b2x1bWVQZXJjZW50KClcIlxuICAgICAgICAgICAgICAgIChpbnB1dCk9XCJjaGFuZ2VWb2x1bWUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ3LTI0IHZvbHVtZS1zbGlkZXJcIlxuICAgICAgICAgICAgICAgIFtzdHlsZS4tLXZvbHVtZS1wZXJjZW50LiVdPVwidm9sdW1lUGVyY2VudCgpXCI+XG4gICAgICAgICAgICAgIDxzcGFuPnt7IHZvbHVtZVBlcmNlbnQoKSB9fSU8L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInctZnVsbCBtdC0yXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPlRp4bq/biDEkeG7mTo8L3NwYW4+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlbGF0aXZlIGgtMiBiZy1ncmF5LTIwMCByb3VuZGVkLWZ1bGwgZmxleC0xIGN1cnNvci1wb2ludGVyXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWVrQXVkaW9CeUNsaWNrKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhYnNvbHV0ZSB0b3AtMCBsZWZ0LTAgaC1mdWxsIGJnLWJsdWUtNTAwIHJvdW5kZWQtZnVsbFwiXG4gICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC4lXT1cInByb2dyZXNzKClcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8c3Bhbj57eyBwcm9ncmVzcygpIH19JTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInB4LTQgcHktMiBiZy1ncmVlbi01MDAgdGV4dC13aGl0ZSBmb250LW1lZGl1bSByb3VuZGVkIGhvdmVyOmJnLWdyZWVuLTYwMCB0cmFuc2l0aW9uIG10LTRcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiZG93bmxvYWRBdWRpbygpXCI+XG4gICAgICAgICAgICAgIFThuqNpIHh14buRbmdcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTZcIj5cbiAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5UcuG6oW5nIHRow6FpOjwvaDM+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmctd2hpdGUgcC00IHJvdW5kZWQgYm9yZGVyXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0yXCI+XG4gICAgICAgICAgICAgICAgPHN0cm9uZz5UcuG6oW5nIHRow6FpOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzcy50ZXh0LWdyZWVuLTYwMF09XCJpc1BsYXlpbmcoKVwiXG4gICAgICAgICAgICAgICAgICBbY2xhc3MudGV4dC1yZWQtNjAwXT1cIiFpc1BsYXlpbmcoKVwiPlxuICAgICAgICAgICAgICAgICAge3sgaXNQbGF5aW5nKCkgPyAnxJBhbmcgcGjDoXQnIDogJ1ThuqFtIGThu6tuZycgfX1cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgICAgIDxzdHJvbmc+VGjhu51pIGdpYW4gaGnhu4duIHThuqFpOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGN1cnJlbnRUaW1lKCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgICAgIDxzdHJvbmc+VOG7lW5nIHRo4budaSBnaWFuOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGR1cmF0aW9uKCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgICAgIDxzdHJvbmc+VGnhur9uIMSR4buZOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IHByb2dyZXNzKCkgfX0lPC9zcGFuPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBzaGFkb3cgcC04IG1iLThcIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTQgcGItMiBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw6BpIGxp4buHdSBBUEk8L2gyPlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0zXCI+SW5wdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+S2nhu4N1IGThu68gbGnhu4d1PC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPk3hurdjIMSR4buLbmg8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+TcO0IHThuqM8L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgIEBmb3IgKGlucHV0IG9mIGlucHV0c0RvYygpOyB0cmFjayBpbnB1dC5uYW1lKSB7XG4gICAgICAgICAgICAgIDx0ciBjbGFzcz1cImJvcmRlci1iIGhvdmVyOmJnLWdyYXktNTBcIj5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHB4LTEgcHktMC41IHJvdW5kZWQgdGV4dC1zbSBmb250LW1vbm9cIj57eyBpbnB1dC5uYW1lIH19PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgaW5wdXQudHlwZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IGlucHV0LmRlZmF1bHQgfX08L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IGlucHV0LmRlc2NyaXB0aW9uIH19PC90ZD5cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5PdXRwdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+S2nhu4N1IGThu68gbGnhu4d1PC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPk3DtCB04bqjPC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICBAZm9yIChvdXRwdXQgb2Ygb3V0cHV0c0RvYygpOyB0cmFjayBvdXRwdXQubmFtZSkge1xuICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJib3JkZXItYiBob3ZlcjpiZy1ncmF5LTUwXCI+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgb3V0cHV0Lm5hbWUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHB4LTEgcHktMC41IHJvdW5kZWQgdGV4dC1zbSBmb250LW1vbm9cIj57eyBvdXRwdXQudHlwZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IG91dHB1dC5kZXNjcmlwdGlvbiB9fTwvdGQ+XG4gICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC90Ym9keT5cbiAgICAgICAgPC90YWJsZT5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0zXCI+RnVuY3Rpb24gQ29udHJvbCBNZXRob2RzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+VGhhbSBz4buRPC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPktp4buDdSB0cuG6oyB24buBPC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPk3DtCB04bqjPC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICBAZm9yIChtZXRob2Qgb2YgbWV0aG9kc0RvYygpOyB0cmFjayBtZXRob2QubmFtZSkge1xuICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJib3JkZXItYiBob3ZlcjpiZy1ncmF5LTUwXCI+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgbWV0aG9kLm5hbWUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHB4LTEgcHktMC41IHJvdW5kZWQgdGV4dC1zbSBmb250LW1vbm9cIj57eyBtZXRob2QucGFyYW1zIH19PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgbWV0aG9kLnJldHVyblR5cGUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj57eyBtZXRob2QuZGVzY3JpcHRpb24gfX08L3RkPlxuICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgIDwvdGFibGU+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItM1wiPkludGVyZmFjZXM8L2gzPlxuICAgICAgPGRpdiBjbGFzcz1cIm92ZXJmbG93LXgtYXV0byBtYi04XCI+XG4gICAgICAgIEBmb3IgKGludGVyZmFjZURvYyBvZiBpbnRlcmZhY2VzRG9jKCk7IHRyYWNrIGludGVyZmFjZURvYy5uYW1lKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTYgYmctd2hpdGUgcC00IHJvdW5kZWQgYm9yZGVyXCI+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJ0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0yXCI+e3sgaW50ZXJmYWNlRG9jLm5hbWUgfX08L2g0PlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi00XCI+e3sgaW50ZXJmYWNlRG9jLmRlc2NyaXB0aW9uIH19PC9wPlxuXG4gICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgICAgIDx0aGVhZCBjbGFzcz1cImJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPktp4buDdSBk4buvIGxp4buHdTwvdGg+XG4gICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+TcO0IHThuqM8L3RoPlxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgICAgICBAZm9yIChwcm9wIG9mIGludGVyZmFjZURvYy5wcm9wZXJ0aWVzOyB0cmFjayBwcm9wLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cImJvcmRlci1iIGhvdmVyOmJnLWdyYXktNTBcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYmctZ3JheS0xMDAgcHgtMSBweS0wLjUgcm91bmRlZCB0ZXh0LXNtIGZvbnQtbW9ub1wiPnt7IHByb3AubmFtZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgcHJvcC50eXBlIH19PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IHByb3AuZGVzY3JpcHRpb24gfX08L3RkPlxuICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICA8L3RhYmxlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L3NlY3Rpb24+XG5cbiAgICA8c2VjdGlvbiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgc2hhZG93IHAtOCBtYi04XCI+XG4gICAgICA8aDIgY2xhc3M9XCJ0ZXh0LTJ4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi00IHBiLTIgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+VMOtbmggbsSDbmc8L2gyPlxuICAgICAgPHVsIGNsYXNzPVwic3BhY2UteS02XCI+XG4gICAgICAgIEBmb3IgKGZlYXR1cmUgb2YgZmVhdHVyZXMoKTsgdHJhY2sgZmVhdHVyZS5pZCkge1xuICAgICAgICAgIDxsaSBjbGFzcz1cImZsZXggaXRlbXMtc3RhcnRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC0zeGwgbXItNCBtaW4tdy0xMCB0ZXh0LWNlbnRlclwiPnt7IGZlYXR1cmUuaWNvbiB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwXCI+e3sgZmVhdHVyZS50aXRsZSB9fTwvaDM+XG4gICAgICAgICAgICAgIDxwPnt7IGZlYXR1cmUuZGVzY3JpcHRpb24gfX08L3A+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2xpPlxuICAgICAgICB9XG4gICAgICA8L3VsPlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBzaGFkb3cgcC04IG1iLThcIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTQgcGItMiBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Dw6FjaCBz4butIGThu6VuZzwvaDI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtNFwiPlxuICAgICAgICBAZm9yIChleGFtcGxlIG9mIGNvZGVFeGFtcGxlcygpOyB0cmFjayBleGFtcGxlLmlkKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZC1sZyBwLTRcIj5cbiAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTJcIj57eyBleGFtcGxlLnRpdGxlIH19PC9oMz5cbiAgICAgICAgICAgIDxwcmVcbiAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZCBvdmVyZmxvdy14LWF1dG9cIj48Y29kZSBbaW5uZXJIVE1MXT1cImV4YW1wbGUuY29kZVwiIGNsYXNzPVwiZm9udC1tb25vXCI+PC9jb2RlPjwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L3NlY3Rpb24+XG4gIDwvbWFpbj5cbjwvZGl2PlxuIl19
|
|
473
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaW8tZGVtby5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXVkaW8vc3JjL2RlbW8vYXVkaW8tZGVtby5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXVkaW8vc3JjL2RlbW8vYXVkaW8tZGVtby5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLG9CQUFvQixDQUFDOztBQVVwRSxNQUFNLE9BQU8sa0NBQWtDO0lBQ25CLFdBQVcsQ0FBa0M7SUFFdkUsc0JBQXNCO0lBQ2YsU0FBUyxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUNuQyxPQUFPLEdBQUcsTUFBTSxDQUFVLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sR0FBRyxNQUFNLENBQVMsR0FBRyxDQUFDLENBQUM7SUFDN0IsV0FBVyxHQUFHLE1BQU0sQ0FBUyxVQUFVLENBQUMsQ0FBQztJQUN6QyxRQUFRLEdBQUcsTUFBTSxDQUFTLFVBQVUsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsR0FBRyxNQUFNLENBQVMsQ0FBQyxDQUFDLENBQUM7SUFFcEMsMkNBQTJDO0lBQ3BDLGFBQWEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRWpFLHdCQUF3QjtJQUNqQixhQUFhLEdBQUcsTUFBTSxDQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLGtCQUFrQixHQUFHLE1BQU0sQ0FBUyxpSEFBaUgsQ0FBQyxDQUFDO0lBRTlKLDZCQUE2QjtJQUN0QixnQkFB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bmVudCwgVmlld0NoaWxkLCBjb21wdXRlZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQgfSBmcm9tICcuLi9hdWRpby5jb21wb25lbnQnO1xuaW1wb3J0IHsgSUF1ZGlvRnVuY3Rpb25Db250cm9sRXZlbnQgfSBmcm9tICcuLi9pbnRlcmZhY2VzL2Z1bmN0aW9uLWNvbnRyb2wtZXZlbnQuaW50ZXJmYWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLWF1ZGlvLWRlbW8nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0F1ZGlvQ29tcG9uZW50XSxcbiAgdGVtcGxhdGVVcmw6ICcuL2F1ZGlvLWRlbW8uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9hdWRpby1kZW1vLmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzQXVkaW9EZW1vQ29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgnYXVkaW9QbGF5ZXInKSBhdWRpb1BsYXllciE6IExpYnNVaUNvbXBvbmVudHNBdWRpb0NvbXBvbmVudDtcblxuICAvLyBTdGF0ZSB1c2luZyBzaWduYWxzXG4gIHB1YmxpYyBpc1BsYXlpbmcgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuICBwdWJsaWMgaXNNdXRlZCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHB1YmxpYyB2b2x1bWUgPSBzaWduYWw8bnVtYmVyPigxMDApO1xuICBwdWJsaWMgY3VycmVudFRpbWUgPSBzaWduYWw8c3RyaW5nPignMDA6MDA6MDAnKTtcbiAgcHVibGljIGR1cmF0aW9uID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwOjAwJyk7XG4gIHB1YmxpYyBwcm9ncmVzcyA9IHNpZ25hbDxudW1iZXI+KDApO1xuXG4gIC8vIENvbXB1dGVkIHByb3BlcnRpZXMgZm9yIHRlbXBsYXRlIGRpc3BsYXlcbiAgcHVibGljIHZvbHVtZVBlcmNlbnQgPSBjb21wdXRlZCgoKSA9PiBNYXRoLnJvdW5kKHRoaXMudm9sdW1lKCkpKTtcblxuICAvLyBTZWxlY3RlZCBhdWRpbyBzYW1wbGVcbiAgcHVibGljIHNlbGVjdGVkQXVkaW8gPSBzaWduYWw8bnVtYmVyPigxKTtcbiAgcHVibGljIGN1cnJlbnRBdWRpb1NvdXJjZSA9IHNpZ25hbDxzdHJpbmc+KCdodHRwczovL25oYWNjaHVvbmcxMjMuY29tL25oYWMtY2h1b25nL2FiY2RlZmdoL25oYWMtY2h1b25nLW5ndW9pLWF5LWRhdS1jby1kYW5nLWFraXJhLXBoYW4tbmd1eWVuLXZhbi1jaHVuZy5tcDMnKTtcblxuICAvLyBGdW5jdGlvbiBDb250cm9sIHZhcmlhYmxlc1xuICBwdWJsaWMgZnVuY3Rpb25Db250cm9sczogSUF1ZGlvRnVuY3Rpb25Db250cm9sRXZlbnQgfCBudWxsID0gbnVsbDtcblxuICAvLyBBdWRpbyBzYW1wbGVzIGZvciBkZW1vXG4gIHB1YmxpYyBhdWRpb1NhbXBsZXMgPSBzaWduYWw8QXJyYXk8eyBpZDogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIHNyYzogc3RyaW5nLCBkdXJhdGlvbjogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgaWQ6IDEsXG4gICAgICBuYW1lOiAnQuG6o24gbmjhuqFjIG3huqt1IDEnLFxuICAgICAgc3JjOiAnaHR0cHM6Ly9uaGFjY2h1b25nMTIzLmNvbS9uaGFjLWNodW9uZy9hYmNkZWZnaC9uaGFjLWNodW9uZy1uZ3VvaS1heS1kYXUtY28tZGFuZy1ha2lyYS1waGFuLW5ndXllbi12YW4tY2h1bmcubXAzJyxcbiAgICAgIGR1cmF0aW9uOiAnMDE6MzAnXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMixcbiAgICAgIG5hbWU6ICdC4bqjbiBuaOG6oWMgbeG6q3UgMicsXG4gICAgICBzcmM6ICdodHRwczovL3d3dy5zb3VuZGhlbGl4LmNvbS9leGFtcGxlcy9tcDMvU291bmRIZWxpeC1Tb25nLTEubXAzJyxcbiAgICAgIGR1cmF0aW9uOiAnMDI6MTUnXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMyxcbiAgICAgIG5hbWU6ICdC4bqjbiBuaOG6oWMgbeG6q3UgMycsXG4gICAgICBzcmM6ICdodHRwczovL2RsLmRyb3Bib3h1c2VyY29udGVudC5jb20vcy83NWpwbmdyZ25hdnl1MWYvVGhlLU5vaXN5LUZyZWFrcy5tcDMnLFxuICAgICAgZHVyYXRpb246ICcwMzo0NSdcbiAgICB9XG4gIF0pO1xuXG4gIC8vIEFQSSBEb2N1bWVudGF0aW9uIGRhdGFcbiAgcHVibGljIGlucHV0c0RvYyA9IHNpZ25hbDxBcnJheTx7IG5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBkZWZhdWx0OiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4+KFtcbiAgICB7XG4gICAgICBuYW1lOiAnZmlsZUF1ZGlvJyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgZGVmYXVsdDogJ0Lhuq90IGJ14buZYycsXG4gICAgICBkZXNjcmlwdGlvbjogJ1VSTCBj4bunYSBmaWxlIGF1ZGlvIGPhuqduIHBow6F0J1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW8nLFxuICAgICAgdHlwZTogJygpID0+IFByb21pc2U8Ym9vbGVhbj4nLFxuICAgICAgZGVmYXVsdDogJ0Lhuq90IGJ14buZYycsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Z1bmN0aW9uIHRy4bqjIHbhu4EgcHJvbWlzZSB24bubaSBr4bq/dCBxdeG6oyBib29sZWFuIGNobyBiaeG6v3QgbuG6v3UgxJHGsOG7o2MgcGjDqXAgZG93bmxvYWQnXG4gICAgfVxuICBdKTtcblxuICAvLyBPdXRwdXQgZG9jdW1lbnRhdGlvblxuICBwdWJsaWMgb3V0cHV0c0RvYyA9IHNpZ25hbDxBcnJheTx7IG5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgbmFtZTogJ291dEZ1bmN0aW9uc0NvbnRyb2wnLFxuICAgICAgdHlwZTogJ0lBdWRpb0Z1bmN0aW9uQ29udHJvbEV2ZW50JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW1pdHMgY8OhYyBow6BtIMSRaeG7gXUga2hp4buDbiBhdWRpbydcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdvdXRWb2x1bWVDb250cm9sJyxcbiAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgZGVzY3JpcHRpb246ICdFbWl0cyBnacOhIHRy4buLIMOibSBsxrDhu6NuZyBoaeG7h24gdOG6oWkgKDAtMTAwKSdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdvdXRUaW1lVXBkYXRlJyxcbiAgICAgIHR5cGU6ICd7IGN1cnJlbnRUaW1lOiBzdHJpbmcsIGR1cmF0aW9uOiBzdHJpbmcgfScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VtaXRzIHRow7RuZyB0aW4gdGjhu51pIGdpYW4gaGnhu4duIHThuqFpIHbDoCB04buVbmcgdGjhu51pIGdpYW4nXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnb3V0RW5kZWQnLFxuICAgICAgdHlwZTogJ3ZvaWQnLFxuICAgICAgZGVzY3JpcHRpb246ICdFbWl0cyBraGkgYXVkaW8ga+G6v3QgdGjDumMgcGjDoXQnXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnb3V0TXV0ZScsXG4gICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VtaXRzIHRy4bqhbmcgdGjDoWkgdOG6r3QvYuG6rXQgdGnhur9uZydcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdvdXRQbGF5JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW1pdHMgdHLhuqFuZyB0aMOhaSBwaMOhdC904bqhbSBk4burbmcnXG4gICAgfVxuICBdKTtcblxuICAvLyBJbnRlcmZhY2UgZG9jdW1lbnRhdGlvblxuICBwdWJsaWMgaW50ZXJmYWNlc0RvYyA9IHNpZ25hbDxBcnJheTx7IG5hbWU6IHN0cmluZywgZGVzY3JpcHRpb246IHN0cmluZywgcHJvcGVydGllczogQXJyYXk8eyBuYW1lOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgZGVzY3JpcHRpb246IHN0cmluZyB9PiB9Pj4oW1xuICAgIHtcbiAgICAgIG5hbWU6ICdJQXVkaW9GdW5jdGlvbkNvbnRyb2xFdmVudCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSBjaG8gY8OhYyBjaOG7qWMgbsSDbmcgxJFp4buBdSBraGnhu4NuIGF1ZGlvIMSRxrDhu6NjIGN1bmcgY+G6pXAgcXVhIG91dHB1dCBldmVudCcsXG4gICAgICBwcm9wZXJ0aWVzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAncGxheVBhdXNlJyxcbiAgICAgICAgICB0eXBlOiAnKGV2ZW50PzogRXZlbnQpID0+IHZvaWQnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnQuG6r3QgxJHhuqd1IGhv4bq3YyB04bqhbSBk4burbmcgcGjDoXQgYXVkaW8nXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAndG9nZ2xlTXV0ZScsXG4gICAgICAgICAgdHlwZTogJyhldmVudD86IEV2ZW50KSA9PiB2b2lkJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ0Lhuq10IGhv4bq3YyB04bqvdCDDom0gdGhhbmgnXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnc2V0Vm9sdW1lJyxcbiAgICAgICAgICB0eXBlOiAnKHZhbHVlOiBudW1iZXIpID0+IHZvaWQnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnxJBp4buBdSBjaOG7iW5oIMOibSBsxrDhu6NuZyAoZ2nDoSB0cuG7iyB04burIDAgxJHhur9uIDEwMCknXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnc2Vla1RvJyxcbiAgICAgICAgICB0eXBlOiAnKHZhbHVlOiBudW1iZXIpID0+IHZvaWQnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnRGkgY2h1eeG7g24gxJHhur9uIHbhu4sgdHLDrSBj4bulIHRo4buDIHRyb25nIGF1ZGlvIChnacOhIHRy4buLIHThu6sgMCDEkeG6v24gMTAwKSdcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdkb3dubG9hZCcsXG4gICAgICAgICAgdHlwZTogJyhldmVudD86IEV2ZW50KSA9PiB2b2lkJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1ThuqNpIHh14buRbmcgZmlsZSBhdWRpbydcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdpc1BsYXlpbmcnLFxuICAgICAgICAgIHR5cGU6ICcoKSA9PiBib29sZWFuJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ0tp4buDbSB0cmEgdHLhuqFuZyB0aMOhaSDEkWFuZyBwaMOhdCBhdWRpbydcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdpc011dGVkJyxcbiAgICAgICAgICB0eXBlOiAnKCkgPT4gYm9vbGVhbicsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdLaeG7g20gdHJhIHRy4bqhbmcgdGjDoWkgdOG6r3QgdGnhur9uZydcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH1cbiAgXSk7XG5cbiAgLy8gTWV0aG9kIGRvY3VtZW50YXRpb25cbiAgcHVibGljIG1ldGhvZHNEb2MgPSBzaWduYWw8QXJyYXk8eyBuYW1lOiBzdHJpbmcsIHBhcmFtczogc3RyaW5nLCByZXR1cm5UeXBlOiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4+KFtcbiAgICB7XG4gICAgICBuYW1lOiAncGxheVBhdXNlJyxcbiAgICAgIHBhcmFtczogJ2V2ZW50PzogRXZlbnQnLFxuICAgICAgcmV0dXJuVHlwZTogJ3ZvaWQnLFxuICAgICAgZGVzY3JpcHRpb246ICdQaMOhdCBob+G6t2MgdOG6oW0gZOG7q25nIGF1ZGlvJ1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ3RvZ2dsZU11dGUnLFxuICAgICAgcGFyYW1zOiAnZXZlbnQ/OiBFdmVudCcsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Lhuq10L3Thuq90IMOibSB0aGFuaCdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdzZWVrVG8nLFxuICAgICAgcGFyYW1zOiAndmFsdWU6IG51bWJlcicsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0RpIGNodXnhu4NuIMSR4bq/biB24buLIHRyw60gY+G7pSB0aOG7gyB0cm9uZyBhdWRpbyAoZ2nDoSB0cuG7iyB04burIDAtMTAwKSdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdzZXRWb2x1bWUnLFxuICAgICAgcGFyYW1zOiAndmFsdWU6IG51bWJlcicsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ8SQaeG7gXUgY2jhu4luaCDDom0gbMaw4bujbmcgKGdpw6EgdHLhu4sgdOG7qyAwLTEwMCknXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnZG93bmxvYWQnLFxuICAgICAgcGFyYW1zOiAnZXZlbnQ/OiBFdmVudCcsXG4gICAgICByZXR1cm5UeXBlOiAndm9pZCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ1ThuqNpIHh14buRbmcgZmlsZSBhdWRpbydcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdpc1BsYXlpbmcnLFxuICAgICAgcGFyYW1zOiAnJyxcbiAgICAgIHJldHVyblR5cGU6ICdib29sZWFuJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnS2nhu4NtIHRyYSBu4bq/dSBhdWRpbyDEkWFuZyBwaMOhdCdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdpc011dGVkJyxcbiAgICAgIHBhcmFtczogJycsXG4gICAgICByZXR1cm5UeXBlOiAnYm9vbGVhbicsXG4gICAgICBkZXNjcmlwdGlvbjogJ0tp4buDbSB0cmEgbuG6v3UgYXVkaW8gxJFhbmcgdOG6r3QgdGnhur9uZydcbiAgICB9XG4gIF0pO1xuXG4gIC8vIEZlYXR1cmVzIGRhdGFcbiAgcHVibGljIGZlYXR1cmVzID0gc2lnbmFsPEFycmF5PHsgaWQ6IG51bWJlciwgaWNvbjogc3RyaW5nLCB0aXRsZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgaWQ6IDEsXG4gICAgICBpY29uOiAn4pa277iPJyxcbiAgICAgIHRpdGxlOiAnxJBp4buBdSBraGnhu4NuIGF1ZGlvJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnxJBp4buBdSBraGnhu4NuIGF1ZGlvIGNvbXBvbmVudCBxdWEgY8OhYyBBUEknXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMixcbiAgICAgIGljb246ICfwn5SKJyxcbiAgICAgIHRpdGxlOiAnUXXhuqNuIGzDvSDDom0gbMaw4bujbmcnLFxuICAgICAgZGVzY3JpcHRpb246ICfEkGnhu4F1IGNo4buJbmggw6JtIGzGsOG7o25nIHbDoCB04bqvdCB0aeG6v25nIHbhu5tpIHRoYW5oIHRyxrDhu6N0IHRy4buxYyBxdWFuJ1xuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDMsXG4gICAgICBpY29uOiAn4o+x77iPJyxcbiAgICAgIHRpdGxlOiAnSGnhu4NuIHRo4buLIHRo4budaSBnaWFuJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnSGnhu4NuIHRo4buLIHRo4budaSBnaWFuIGhp4buHbiB04bqhaSB2w6AgdOG7lW5nIHRo4budaSBnaWFuIHRoZW8gxJHhu4tuaCBk4bqhbmcgSEg6TU06U1MnXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogNCxcbiAgICAgIGljb246ICfwn5OKJyxcbiAgICAgIHRpdGxlOiAnVGhhbmggdGnhur9uIMSR4buZJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhhbmggdGnhur9uIMSR4buZIGPDsyB0aOG7gyB0xrDGoW5nIHTDoWMgxJHhu4MgdHVhIG5oYW5oIGhv4bq3YyB0dWEgbOG6oWknXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogNSxcbiAgICAgIGljb246ICfwn5OlJyxcbiAgICAgIHRpdGxlOiAnVOG6o2kgeHXhu5FuZycsXG4gICAgICBkZXNjcmlwdGlvbjogJ0jhu5cgdHLhu6MgdOG6o2kgeHXhu5FuZyBmaWxlIMOibSB0aGFuaCB24bubaSBraeG7g20gc2/DoXQgcXV54buBbidcbiAgICB9XG4gIF0pO1xuXG4gIC8vIENvZGUgZXhhbXBsZXMgZGF0YVxuICBwdWJsaWMgY29kZUV4YW1wbGVzID0gc2lnbmFsPEFycmF5PHsgaWQ6IG51bWJlciwgdGl0bGU6IHN0cmluZywgY29kZTogc3RyaW5nIH0+PihbXG4gICAge1xuICAgICAgaWQ6IDEsXG4gICAgICB0aXRsZTogJ0PDoGkgxJHhurd0IGPGoSBi4bqjbicsXG4gICAgICBjb2RlOiBgJmx0O2xpYnNfdWktY29tcG9uZW50cy1hdWRpb1xuICBbZmlsZUF1ZGlvXT1cIidwYXRoL3RvL2F1ZGlvLm1wMydcIlxuICBbY2hlY2tQZXJtaXNzaW9uRG93bmxvYWRBdWRpb109XCJjaGVja1Blcm1pc3Npb25cIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWF1ZGlvJmd0O2BcbiAgICB9LFxuICAgIHtcbiAgICAgIGlkOiAyLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyBGdW5jdGlvbiBDb250cm9sJyxcbiAgICAgIGNvZGU6IGBpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWF1ZGlvJztcbmltcG9ydCB7IElBdWRpb0Z1bmN0aW9uQ29udHJvbEV2ZW50IH0gZnJvbSAnQGxpYnMtdWkvY29tcG9uZW50cy1hdWRpbyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1teS1jb21wb25lbnQnLFxuICB0ZW1wbGF0ZTogXFxgXG4gICAgJmx0O2xpYnNfdWktY29tcG9uZW50cy1hdWRpb1xuICAgICAgI2F1ZGlvUGxheWVyXG4gICAgICBbZmlsZUF1ZGlvXT1cImF1ZGlvU291cmNlKClcIlxuICAgICAgW2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW9dPVwiY2hlY2tQZXJtaXNzaW9uXCJcbiAgICAgIChvdXRGdW5jdGlvbnNDb250cm9sKT1cInJlZ2lzdGVyRnVuY3Rpb25zKCRldmVudClcIiZndDtcbiAgICAmbHQ7L2xpYnNfdWktY29tcG9uZW50cy1hdWRpbyZndDtcbiAgICBcbiAgICAmbHQ7YnV0dG9uIChjbGljayk9XCJwbGF5QXVkaW8oKVwiJmd0O1Bow6F0L1ThuqFtIGThu6tuZyZsdDsvYnV0dG9uJmd0O1xuICBcXGBcbn0pXG5leHBvcnQgY2xhc3MgTXlDb21wb25lbnQge1xuICBAVmlld0NoaWxkKCdhdWRpb1BsYXllcicpIGF1ZGlvUGxheWVyITogTGlic1VpQ29tcG9uZW50c0F1ZGlvQ29tcG9uZW50O1xuICBhdWRpb1NvdXJjZSA9IHNpZ25hbDxzdHJpbmc+KCdwYXRoL3RvL2F1ZGlvLm1wMycpO1xuICBmdW5jdGlvbkNvbnRyb2xzOiBJQXVkaW9GdW5jdGlvbkNvbnRyb2xFdmVudCB8IG51bGwgPSBudWxsO1xuICBcbiAgcmVnaXN0ZXJGdW5jdGlvbnMoZXZlbnQ6IElBdWRpb0Z1bmN0aW9uQ29udHJvbEV2ZW50KSB7XG4gICAgdGhpcy5mdW5jdGlvbkNvbnRyb2xzID0gZXZlbnQ7XG4gIH1cbiAgXG4gIHBsYXlBdWRpbygpIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMucGxheVBhdXNlKCk7XG4gICAgfVxuICB9XG59YFxuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDMsXG4gICAgICB0aXRsZTogJ1Phu60gZOG7pW5nIEV2ZW50cyDEkeG7gyBj4bqtcCBuaOG6rXQgVUknLFxuICAgICAgY29kZTogYGltcG9ydCB7IENvbXBvbmVudCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzQXVkaW9Db21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWF1ZGlvJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLW15LWNvbXBvbmVudCcsXG4gIHRlbXBsYXRlOiBcXGBcbiAgICAmbHQ7bGlic191aS1jb21wb25lbnRzLWF1ZGlvXG4gICAgICBbZmlsZUF1ZGlvXT1cImF1ZGlvU291cmNlKClcIlxuICAgICAgW2NoZWNrUGVybWlzc2lvbkRvd25sb2FkQXVkaW9dPVwiY2hlY2tQZXJtaXNzaW9uXCJcbiAgICAgIChvdXRUaW1lVXBkYXRlKT1cImhhbmRsZVRpbWVVcGRhdGUoJGV2ZW50KVwiXG4gICAgICAob3V0Vm9sdW1lQ29udHJvbCk9XCJoYW5kbGVWb2x1bWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAob3V0UGxheSk9XCJoYW5kbGVQbGF5Q2hhbmdlKCRldmVudClcIlxuICAgICAgKG91dE11dGUpPVwiaGFuZGxlTXV0ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIChvdXRFbmRlZCk9XCJoYW5kbGVFbmRlZCgpXCImZ3Q7XG4gICAgJmx0Oy9saWJzX3VpLWNvbXBvbmVudHMtYXVkaW8mZ3Q7XG4gICAgXG4gICAgJmx0O2RpdiBjbGFzcz1cImF1ZGlvLWluZm9cIiZndDtcbiAgICAgICZsdDtwJmd0O1Ry4bqhbmcgdGjDoWk6IHt7IGlzUGxheWluZygpID8gJ8SQYW5nIHBow6F0JyA6ICdU4bqhbSBk4burbmcnIH19Jmx0Oy9wJmd0O1xuICAgICAgJmx0O3AmZ3Q7VGjhu51pIGdpYW4gaGnhu4duIHThuqFpOiB7eyBjdXJyZW50VGltZSgpIH19Jmx0Oy9wJmd0O1xuICAgICAgJmx0O3AmZ3Q7VOG7lW5nIHRo4budaSBnaWFuOiB7eyBkdXJhdGlvbigpIH19Jmx0Oy9wJmd0O1xuICAgICAgJmx0O3AmZ3Q7w4JtIGzGsOG7o25nOiB7eyB2b2x1bWVMZXZlbCgpIH19JSZsdDsvcCZndDtcbiAgICAmbHQ7L2RpdiZndDtcbiAgXFxgXG59KVxuZXhwb3J0IGNsYXNzIE15Q29tcG9uZW50IHtcbiAgYXVkaW9Tb3VyY2UgPSBzaWduYWw8c3RyaW5nPigncGF0aC90by9hdWRpby5tcDMnKTtcbiAgaXNQbGF5aW5nID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgaXNNdXRlZCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIGN1cnJlbnRUaW1lID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwOjAwJyk7XG4gIGR1cmF0aW9uID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwOjAwJyk7XG4gIHZvbHVtZUxldmVsID0gc2lnbmFsPG51bWJlcj4oMTAwKTtcbiAgXG4gIGNoZWNrUGVybWlzc2lvbiA9ICgpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICB9XG4gIFxuICBoYW5kbGVUaW1lVXBkYXRlKHRpbWVJbmZvOiB7IGN1cnJlbnRUaW1lOiBzdHJpbmcsIGR1cmF0aW9uOiBzdHJpbmcgfSkge1xuICAgIHRoaXMuY3VycmVudFRpbWUuc2V0KHRpbWVJbmZvLmN1cnJlbnRUaW1lKTtcbiAgICB0aGlzLmR1cmF0aW9uLnNldCh0aW1lSW5mby5kdXJhdGlvbik7XG4gIH1cbiAgXG4gIGhhbmRsZVZvbHVtZUNoYW5nZSh2b2x1bWU6IG51bWJlcikge1xuICAgIHRoaXMudm9sdW1lTGV2ZWwuc2V0KHZvbHVtZSk7XG4gIH1cbiAgXG4gIGhhbmRsZVBsYXlDaGFuZ2UoaXNQbGF5aW5nOiBib29sZWFuKSB7XG4gICAgdGhpcy5pc1BsYXlpbmcuc2V0KGlzUGxheWluZyk7XG4gIH1cbiAgXG4gIGhhbmRsZU11dGVDaGFuZ2UoaXNNdXRlZDogYm9vbGVhbikge1xuICAgIHRoaXMuaXNNdXRlZC5zZXQoaXNNdXRlZCk7XG4gIH1cbiAgXG4gIGhhbmRsZUVuZGVkKCkge1xuICAgIHRoaXMuaXNQbGF5aW5nLnNldChmYWxzZSk7XG4gIH1cbn1gXG4gICAgfVxuICBdKTtcblxuICAvLyBDb250cm9sIG1ldGhvZHNcbiAgcHVibGljIHBsYXlBdWRpbygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMucGxheVBhdXNlKCk7XG4gICAgICB0aGlzLmlzUGxheWluZy5zZXQodGhpcy5mdW5jdGlvbkNvbnRyb2xzLmlzUGxheWluZygpKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgdG9nZ2xlTXV0ZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMudG9nZ2xlTXV0ZSgpO1xuICAgICAgdGhpcy5pc011dGVkLnNldCh0aGlzLmZ1bmN0aW9uQ29udHJvbHMuaXNNdXRlZCgpKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgY2hhbmdlVm9sdW1lKGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmZ1bmN0aW9uQ29udHJvbHMgJiYgZXZlbnQudGFyZ2V0KSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHBhcnNlSW50KChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUpO1xuICAgICAgdGhpcy52b2x1bWUuc2V0KHZhbHVlKTtcbiAgICAgIHRoaXMuZnVuY3Rpb25Db250cm9scy5zZXRWb2x1bWUodmFsdWUpO1xuICAgICAgdGhpcy5pc011dGVkLnNldCh0aGlzLmZ1bmN0aW9uQ29udHJvbHMuaXNNdXRlZCgpKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZG93bmxvYWRBdWRpbygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMuZG93bmxvYWQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRm9ybWF0IHRo4budaSBnaWFuIHThu6sgZ2nDonkgc2FuZyBjaHXhu5dpIEhIOk1NOlNTXG4gICAqL1xuICBwdWJsaWMgZm9ybWF0VGltZSh0aW1lSW5TZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGlmIChpc05hTih0aW1lSW5TZWNvbmRzKSkgcmV0dXJuICcwMDowMDowMCc7XG5cbiAgICBjb25zdCBob3VycyA9IE1hdGguZmxvb3IodGltZUluU2Vjb25kcyAvIDM2MDApO1xuICAgIGNvbnN0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKCh0aW1lSW5TZWNvbmRzIC0gKGhvdXJzICogMzYwMCkpIC8gNjApO1xuICAgIGNvbnN0IHNlY29uZHMgPSBNYXRoLmZsb29yKHRpbWVJblNlY29uZHMgLSAoaG91cnMgKiAzNjAwKSAtIChtaW51dGVzICogNjApKTtcblxuICAgIHJldHVybiBgJHtob3Vycy50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9OiR7bWludXRlcy50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9OiR7c2Vjb25kcy50b1N0cmluZygpLnBhZFN0YXJ0KDIsICcwJyl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYW8gY2jDqXAgdGV4dCB2w6BvIGNsaXBib2FyZFxuICAgKi9cbiAgcHVibGljIGNvcHlUb0NsaXBib2FyZCh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0ZXh0KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBhbGVydCgnxJDDoyBzYW8gY2jDqXAgdsOgbyBjbGlwYm9hcmQhJyk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBjb3B5OiAnLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogxJDEg25nIGvDvSBjw6FjIGZ1bmN0aW9uIGNvbnRyb2wgdOG7qyBjb21wb25lbnRcbiAgICovXG4gIHB1YmxpYyByZWdpc3RlckZ1bmN0aW9ucyhldmVudDogSUF1ZGlvRnVuY3Rpb25Db250cm9sRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMgPSBldmVudDtcblxuICAgIC8vIEluaXRpYWxpemUgc3RhdGVcbiAgICBpZiAodGhpcy5mdW5jdGlvbkNvbnRyb2xzKSB7XG4gICAgICB0aGlzLmlzUGxheWluZy5zZXQodGhpcy5mdW5jdGlvbkNvbnRyb2xzLmlzUGxheWluZygpKTtcbiAgICAgIHRoaXMuaXNNdXRlZC5zZXQodGhpcy5mdW5jdGlvbkNvbnRyb2xzLmlzTXV0ZWQoKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFjhu60gbMO9IHPhu7Ega2nhu4duIHRoYXkgxJHhu5VpIHRo4budaSBnaWFuXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlVGltZVVwZGF0ZSh0aW1lSW5mbzogeyBjdXJyZW50VGltZTogc3RyaW5nLCBkdXJhdGlvbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRUaW1lLnNldCh0aW1lSW5mby5jdXJyZW50VGltZSk7XG4gICAgdGhpcy5kdXJhdGlvbi5zZXQodGltZUluZm8uZHVyYXRpb24pO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHByb2dyZXNzIGJhc2VkIG9uIGN1cnJlbnRUaW1lIGFuZCBkdXJhdGlvblxuICAgIGNvbnN0IHJlZ2V4ID0gLyhcXGQrKTooXFxkKyk6KFxcZCspLztcbiAgICBjb25zdCBjdXJyZW50TWF0Y2hlcyA9IHRpbWVJbmZvLmN1cnJlbnRUaW1lLm1hdGNoKHJlZ2V4KTtcbiAgICBjb25zdCBkdXJhdGlvbk1hdGNoZXMgPSB0aW1lSW5mby5kdXJhdGlvbi5tYXRjaChyZWdleCk7XG5cbiAgICBpZiAoY3VycmVudE1hdGNoZXMgJiYgZHVyYXRpb25NYXRjaGVzKSB7XG4gICAgICBjb25zdCBjdXJyZW50U2Vjb25kcyA9XG4gICAgICAgIHBhcnNlSW50KGN1cnJlbnRNYXRjaGVzWzFdKSAqIDM2MDAgK1xuICAgICAgICBwYXJzZUludChjdXJyZW50TWF0Y2hlc1syXSkgKiA2MCArXG4gICAgICAgIHBhcnNlSW50KGN1cnJlbnRNYXRjaGVzWzNdKTtcblxuICAgICAgY29uc3QgdG90YWxTZWNvbmRzID1cbiAgICAgICAgcGFyc2VJbnQoZHVyYXRpb25NYXRjaGVzWzFdKSAqIDM2MDAgK1xuICAgICAgICBwYXJzZUludChkdXJhdGlvbk1hdGNoZXNbMl0pICogNjAgK1xuICAgICAgICBwYXJzZUludChkdXJhdGlvbk1hdGNoZXNbM10pO1xuXG4gICAgICBpZiAodG90YWxTZWNvbmRzID4gMCkge1xuICAgICAgICB0aGlzLnByb2dyZXNzLnNldChNYXRoLmZsb29yKChjdXJyZW50U2Vjb25kcyAvIHRvdGFsU2Vjb25kcykgKiAxMDApKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogWOG7rSBsw70gc+G7sSBraeG7h24gdGhheSDEkeG7lWkgw6JtIGzGsOG7o25nXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlVm9sdW1lQ2hhbmdlKHZvbHVtZTogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy52b2x1bWUuc2V0KHZvbHVtZSk7XG4gIH1cblxuICAvKipcbiAgICogWOG7rSBsw70gc+G7sSBraeG7h24gdGhheSDEkeG7lWkgdHLhuqFuZyB0aMOhaSBwaMOhdFxuICAgKi9cbiAgcHVibGljIGhhbmRsZVBsYXlDaGFuZ2UoaXNQbGF5aW5nOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pc1BsYXlpbmcuc2V0KGlzUGxheWluZyk7XG4gIH1cblxuICAvKipcbiAgICogWOG7rSBsw70gc+G7sSBraeG7h24gdGhheSDEkeG7lWkgdHLhuqFuZyB0aMOhaSB04bqvdCB0aeG6v25nXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlTXV0ZUNoYW5nZShpc011dGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pc011dGVkLnNldChpc011dGVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBY4butIGzDvSBz4buxIGtp4buHbiBr4bq/dCB0aMO6YyBwaMOhdFxuICAgKi9cbiAgcHVibGljIGhhbmRsZUVuZGVkKCk6IHZvaWQge1xuICAgIHRoaXMuaXNQbGF5aW5nLnNldChmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogQ2jhu41uIG3huqt1IMOibSB0aGFuaFxuICAgKi9cbiAgcHVibGljIHNlbGVjdEF1ZGlvKGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkQXVkaW8uc2V0KGlkKTtcbiAgICBjb25zdCBzYW1wbGUgPSB0aGlzLmF1ZGlvU2FtcGxlcygpLmZpbmQoYXVkaW8gPT4gYXVkaW8uaWQgPT09IGlkKTtcbiAgICBpZiAoc2FtcGxlKSB7XG4gICAgICAvLyBSZXNldCBhdWRpbyBzdGF0ZVxuICAgICAgdGhpcy5pc1BsYXlpbmcuc2V0KGZhbHNlKTtcbiAgICAgIHRoaXMucHJvZ3Jlc3Muc2V0KDApO1xuICAgICAgdGhpcy5jdXJyZW50VGltZS5zZXQoJzAwOjAwOjAwJyk7XG4gICAgICB0aGlzLmR1cmF0aW9uLnNldCgnMDA6MDA6MDAnKTtcblxuICAgICAgLy8gU2ltcGx5IHVwZGF0ZSB0aGUgc291cmNlIC0gdGhlIGNvbXBvbmVudCB3aWxsIGhhbmRsZSB0aGUgcmVsb2FkXG4gICAgICB0aGlzLmN1cnJlbnRBdWRpb1NvdXJjZS5zZXQoc2FtcGxlLnNyYyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEtp4buDbSB0cmEgcXV54buBbiB04bqjaSB4deG7kW5nXG4gICAqL1xuICBwdWJsaWMgY2hlY2tEb3dubG9hZFBlcm1pc3Npb24gPSAoKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGF5IMSR4buVaSB24buLIHRyw60gcGjDoXQgYuG6sW5nIGPDoWNoIGNsaWNrIHRy4buxYyB0aeG6v3AgdsOgbyB0aGFuaCB0aeG6v24gxJHhu5lcbiAgICovXG4gIHB1YmxpYyBzZWVrQXVkaW9CeUNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZnVuY3Rpb25Db250cm9scykge1xuICAgICAgY29uc3QgcHJvZ3Jlc3NCYXIgPSBldmVudC5jdXJyZW50VGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgY29uc3QgcmVjdCA9IHByb2dyZXNzQmFyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3Qgb2Zmc2V0WCA9IGV2ZW50LmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgICBjb25zdCBwZXJjZW50WCA9IChvZmZzZXRYIC8gcmVjdC53aWR0aCkgKiAxMDA7XG5cbiAgICAgIC8vIMSQ4bqjbSBi4bqjbyBnacOhIHRy4buLIG7hurFtIHRyb25nIGtob+G6o25nIDAtMTAwXG4gICAgICBjb25zdCBjbGFtcGVkUGVyY2VudCA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEwMCwgcGVyY2VudFgpKTtcbiAgICAgIHRoaXMucHJvZ3Jlc3Muc2V0KE1hdGgucm91bmQoY2xhbXBlZFBlcmNlbnQpKTtcblxuICAgICAgLy8gR+G7jWkgbWV0aG9kIHNlZWtUbyDEkeG7gyBj4bqtcCBuaOG6rXQgduG7iyB0csOtIHBow6F0XG4gICAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbHMuc2Vla1RvKHRoaXMucHJvZ3Jlc3MoKSk7XG4gICAgfVxuICB9XG59IFxuIiwiPGRpdiBjbGFzcz1cIm1heC13LTd4bCBteC1hdXRvIHB4LTQgc206cHgtNiBsZzpweC04IGZvbnQtc2FucyB0ZXh0LWdyYXktODAwXCI+XG4gIDxoZWFkZXIgY2xhc3M9XCJ0ZXh0LWNlbnRlciBweS0xMCBiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdyBtYi04XCI+XG4gICAgPGgxIGNsYXNzPVwidGV4dC00eGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItMlwiPkRlbW8gVHLDrG5oIFBow6F0IMOCbSBUaGFuaDwvaDE+XG4gICAgPHAgY2xhc3M9XCJ0ZXh0LXhsIHRleHQtZ3JheS02MDBcIj5UaMawIHZp4buHbiBjb21wb25lbnQgY2hvIEFuZ3VsYXIgxJHhu4MgcGjDoXQgdsOgIMSRaeG7gXUga2hp4buDbiDDom0gdGhhbmg8L3A+XG4gIDwvaGVhZGVyPlxuXG4gIDxtYWluPlxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBzaGFkb3cgcC04IG1iLThcIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTQgcGItMiBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5HaeG7m2kgdGhp4buHdTwvaDI+XG4gICAgICA8cCBjbGFzcz1cInRleHQtbGdcIj5cbiAgICAgICAgPGNvZGUgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+JiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtYXVkaW88L2NvZGU+IGzDoCBt4buZdFxuICAgICAgICBjb21wb25lbnQgQW5ndWxhciBt4bqhbmggbeG6vSBjaG8gcGjDqXAgbmfGsOG7nWkgZMO5bmcgcGjDoXQsIHThuqFtIGThu6tuZyB2w6AgxJFp4buBdSBraGnhu4NuIGPDoWMgdOG7h3Agw6JtIHRoYW5oIHbhu5tpIG5oaeG7gXUgdMOtbmggbsSDbmcuXG4gICAgICA8L3A+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdyBwLTggbWItOFwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNCBwYi0yIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkPDoGkgxJHhurd0PC9oMj5cbiAgICAgIDxwPsSQ4buDIGPDoGkgxJHhurd0IHRoxrAgdmnhu4duLCBz4butIGThu6VuZyBucG0gaG/hurdjIHlhcm46PC9wPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwicmVsYXRpdmUgbXktNFwiPlxuICAgICAgICA8cHJlXG4gICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZCBvdmVyZmxvdy14LWF1dG8gbWItNFwiPjxjb2RlIGNsYXNzPVwiZm9udC1tb25vXCI+bnBtIGluc3RhbGwgJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtYXVkaW88L2NvZGU+PC9wcmU+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBjbGFzcz1cImFic29sdXRlIHRvcC0yIHJpZ2h0LTIgYmctYmx1ZS01MDAgdGV4dC13aGl0ZSBweC0zIHB5LTEgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWJsdWUtNjAwIHRyYW5zaXRpb25cIlxuICAgICAgICAgIChjbGljayk9XCJjb3B5VG9DbGlwYm9hcmQoJ25wbSBpbnN0YWxsIEBsaWJzLXVpL2NvbXBvbmVudHMtYXVkaW8nKVwiPlxuICAgICAgICAgIFNhbyBjaMOpcFxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8cD5Ib+G6t2MgduG7m2kgeWFybjo8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZSBteS00XCI+XG4gICAgICAgIDxwcmVcbiAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkIG92ZXJmbG93LXgtYXV0byBtYi00XCI+PGNvZGUgY2xhc3M9XCJmb250LW1vbm9cIj55YXJuIGFkZCAmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1hdWRpbzwvY29kZT48L3ByZT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiYWJzb2x1dGUgdG9wLTIgcmlnaHQtMiBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHB4LTMgcHktMSByb3VuZGVkIHRleHQtc20gaG92ZXI6YmctYmx1ZS02MDAgdHJhbnNpdGlvblwiXG4gICAgICAgICAgKGNsaWNrKT1cImNvcHlUb0NsaXBib2FyZCgneWFybiBhZGQgQGxpYnMtdWkvY29tcG9uZW50cy1hdWRpbycpXCI+XG4gICAgICAgICAgU2FvIGNow6lwXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdyBwLTggbWItOFwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNCBwYi0yIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkRlbW8gdHLhu7FjIHRp4bq/cDwvaDI+XG4gICAgICA8ZGl2IGNsYXNzPVwiYmctZ3JheS01MCBwLTYgcm91bmRlZC1sZ1wiPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTRcIj5UaOG7rSBuZ2hp4buHbSB0csOsbmggcGjDoXQgw6JtIHRoYW5oIHbhu5tpIGPDoWMgZmlsZSBt4bqrdTo8L3A+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTZcIj5cbiAgICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0zXCI+Q2jhu41uIGZpbGUgw6JtIHRoYW5oOjwvaDM+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTJcIj5cbiAgICAgICAgICAgIEBmb3IgKGF1ZGlvIG9mIGF1ZGlvU2FtcGxlcygpOyB0cmFjayBhdWRpby5pZCkge1xuICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGp1c3RpZnktYmV0d2VlbiBwLTMgYmctd2hpdGUgcm91bmRlZCBib3JkZXIgY3Vyc29yLXBvaW50ZXIgdHJhbnNpdGlvbiBob3ZlcjpiZy1ibHVlLTUwIGhvdmVyOmJvcmRlci1ibHVlLTUwMFwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmJnLWJsdWUtNTBdPVwic2VsZWN0ZWRBdWRpbygpID09PSBhdWRpby5pZFwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmJvcmRlci1ibHVlLTUwMF09XCJzZWxlY3RlZEF1ZGlvKCkgPT09IGF1ZGlvLmlkXCJcbiAgICAgICAgICAgICAgICBbY2xhc3MuZm9udC1tZWRpdW1dPVwic2VsZWN0ZWRBdWRpbygpID09PSBhdWRpby5pZFwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdEF1ZGlvKGF1ZGlvLmlkKVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGF1ZGlvLm5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPHNwYW4+e3sgYXVkaW8uZHVyYXRpb24gfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItNlwiPlxuICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5UcsOsbmggcGjDoXQ6PC9oMz5cbiAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF1ZGlvICNhdWRpb1BsYXllclxuICAgICAgICAgICAgW2ZpbGVBdWRpb109XCJjdXJyZW50QXVkaW9Tb3VyY2UoKVwiXG4gICAgICAgICAgICBbY2hlY2tQZXJtaXNzaW9uRG93bmxvYWRBdWRpb109XCJjaGVja0Rvd25sb2FkUGVybWlzc2lvblwiXG4gICAgICAgICAgICAob3V0RnVuY3Rpb25zQ29udHJvbCk9XCJyZWdpc3RlckZ1bmN0aW9ucygkZXZlbnQpXCJcbiAgICAgICAgICAgIChvdXRUaW1lVXBkYXRlKT1cImhhbmRsZVRpbWVVcGRhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgICAob3V0Vm9sdW1lQ29udHJvbCk9XCJoYW5kbGVWb2x1bWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAob3V0UGxheSk9XCJoYW5kbGVQbGF5Q2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgKG91dE11dGUpPVwiaGFuZGxlTXV0ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIChvdXRFbmRlZCk9XCJoYW5kbGVFbmRlZCgpXCI+XG4gICAgICAgICAgPC9saWJzX3VpLWNvbXBvbmVudHMtYXVkaW8+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtYi02XCI+XG4gICAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItM1wiPsSQaeG7gXUga2hp4buDbiBxdWEgRnVuY3Rpb24gQ29udHJvbDo8L2gzPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtd3JhcCBnYXAtMyBpdGVtcy1jZW50ZXIgYmctd2hpdGUgcC00IHJvdW5kZWQgYm9yZGVyXCI+XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwicHgtNCBweS0yIGJnLWJsdWUtNTAwIHRleHQtd2hpdGUgZm9udC1tZWRpdW0gcm91bmRlZCBob3ZlcjpiZy1ibHVlLTYwMCB0cmFuc2l0aW9uXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInBsYXlBdWRpbygpXCI+XG4gICAgICAgICAgICAgIFBow6F0L1ThuqFtIGThu6tuZ1xuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwicHgtNCBweS0yIGJnLWJsdWUtNTAwIHRleHQtd2hpdGUgZm9udC1tZWRpdW0gcm91bmRlZCBob3ZlcjpiZy1ibHVlLTYwMCB0cmFuc2l0aW9uXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZU11dGUoKVwiPlxuICAgICAgICAgICAgICB7eyBpc011dGVkKCkgPyAnQuG6rXQgdGnhur9uZycgOiAnVOG6r3QgdGnhur9uZycgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTIgbWwtMlwiPlxuICAgICAgICAgICAgICA8c3Bhbj7Dgm0gbMaw4bujbmc6PC9zcGFuPlxuICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInJhbmdlXCJcbiAgICAgICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJ2b2x1bWVQZXJjZW50KClcIlxuICAgICAgICAgICAgICAgIChpbnB1dCk9XCJjaGFuZ2VWb2x1bWUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ3LTI0IHZvbHVtZS1zbGlkZXJcIlxuICAgICAgICAgICAgICAgIFtzdHlsZS4tLXZvbHVtZS1wZXJjZW50LiVdPVwidm9sdW1lUGVyY2VudCgpXCI+XG4gICAgICAgICAgICAgIDxzcGFuPnt7IHZvbHVtZVBlcmNlbnQoKSB9fSU8L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInctZnVsbCBtdC0yXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPlRp4bq/biDEkeG7mTo8L3NwYW4+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlbGF0aXZlIGgtMiBiZy1ncmF5LTIwMCByb3VuZGVkLWZ1bGwgZmxleC0xIGN1cnNvci1wb2ludGVyXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWVrQXVkaW9CeUNsaWNrKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhYnNvbHV0ZSB0b3AtMCBsZWZ0LTAgaC1mdWxsIGJnLWJsdWUtNTAwIHJvdW5kZWQtZnVsbFwiXG4gICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC4lXT1cInByb2dyZXNzKClcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8c3Bhbj57eyBwcm9ncmVzcygpIH19JTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInB4LTQgcHktMiBiZy1ncmVlbi01MDAgdGV4dC13aGl0ZSBmb250LW1lZGl1bSByb3VuZGVkIGhvdmVyOmJnLWdyZWVuLTYwMCB0cmFuc2l0aW9uIG10LTRcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiZG93bmxvYWRBdWRpbygpXCI+XG4gICAgICAgICAgICAgIFThuqNpIHh14buRbmdcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTZcIj5cbiAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5UcuG6oW5nIHRow6FpOjwvaDM+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmctd2hpdGUgcC00IHJvdW5kZWQgYm9yZGVyXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtYi0yXCI+XG4gICAgICAgICAgICAgICAgPHN0cm9uZz5UcuG6oW5nIHRow6FpOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzcy50ZXh0LWdyZWVuLTYwMF09XCJpc1BsYXlpbmcoKVwiXG4gICAgICAgICAgICAgICAgICBbY2xhc3MudGV4dC1yZWQtNjAwXT1cIiFpc1BsYXlpbmcoKVwiPlxuICAgICAgICAgICAgICAgICAge3sgaXNQbGF5aW5nKCkgPyAnxJBhbmcgcGjDoXQnIDogJ1ThuqFtIGThu6tuZycgfX1cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgICAgIDxzdHJvbmc+VGjhu51pIGdpYW4gaGnhu4duIHThuqFpOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGN1cnJlbnRUaW1lKCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgICAgIDxzdHJvbmc+VOG7lW5nIHRo4budaSBnaWFuOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGR1cmF0aW9uKCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgICAgIDxzdHJvbmc+VGnhur9uIMSR4buZOjwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IHByb2dyZXNzKCkgfX0lPC9zcGFuPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBzaGFkb3cgcC04IG1iLThcIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTQgcGItMiBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw6BpIGxp4buHdSBBUEk8L2gyPlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0zXCI+SW5wdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+S2nhu4N1IGThu68gbGnhu4d1PC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPk3hurdjIMSR4buLbmg8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+TcO0IHThuqM8L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgIEBmb3IgKGlucHV0IG9mIGlucHV0c0RvYygpOyB0cmFjayBpbnB1dC5uYW1lKSB7XG4gICAgICAgICAgICAgIDx0ciBjbGFzcz1cImJvcmRlci1iIGhvdmVyOmJnLWdyYXktNTBcIj5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHB4LTEgcHktMC41IHJvdW5kZWQgdGV4dC1zbSBmb250LW1vbm9cIj57eyBpbnB1dC5uYW1lIH19PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgaW5wdXQudHlwZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IGlucHV0LmRlZmF1bHQgfX08L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IGlucHV0LmRlc2NyaXB0aW9uIH19PC90ZD5cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5PdXRwdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+S2nhu4N1IGThu68gbGnhu4d1PC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPk3DtCB04bqjPC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICBAZm9yIChvdXRwdXQgb2Ygb3V0cHV0c0RvYygpOyB0cmFjayBvdXRwdXQubmFtZSkge1xuICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJib3JkZXItYiBob3ZlcjpiZy1ncmF5LTUwXCI+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgb3V0cHV0Lm5hbWUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHB4LTEgcHktMC41IHJvdW5kZWQgdGV4dC1zbSBmb250LW1vbm9cIj57eyBvdXRwdXQudHlwZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IG91dHB1dC5kZXNjcmlwdGlvbiB9fTwvdGQ+XG4gICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC90Ym9keT5cbiAgICAgICAgPC90YWJsZT5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0zXCI+RnVuY3Rpb24gQ29udHJvbCBNZXRob2RzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgPHRoZWFkIGNsYXNzPVwiYmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+VGhhbSBz4buRPC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPktp4buDdSB0cuG6oyB24buBPC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPk3DtCB04bqjPC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICBAZm9yIChtZXRob2Qgb2YgbWV0aG9kc0RvYygpOyB0cmFjayBtZXRob2QubmFtZSkge1xuICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJib3JkZXItYiBob3ZlcjpiZy1ncmF5LTUwXCI+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgbWV0aG9kLm5hbWUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLWdyYXktMTAwIHB4LTEgcHktMC41IHJvdW5kZWQgdGV4dC1zbSBmb250LW1vbm9cIj57eyBtZXRob2QucGFyYW1zIH19PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgbWV0aG9kLnJldHVyblR5cGUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj57eyBtZXRob2QuZGVzY3JpcHRpb24gfX08L3RkPlxuICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgIDwvdGFibGU+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItM1wiPkludGVyZmFjZXM8L2gzPlxuICAgICAgPGRpdiBjbGFzcz1cIm92ZXJmbG93LXgtYXV0byBtYi04XCI+XG4gICAgICAgIEBmb3IgKGludGVyZmFjZURvYyBvZiBpbnRlcmZhY2VzRG9jKCk7IHRyYWNrIGludGVyZmFjZURvYy5uYW1lKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTYgYmctd2hpdGUgcC00IHJvdW5kZWQgYm9yZGVyXCI+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJ0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0yXCI+e3sgaW50ZXJmYWNlRG9jLm5hbWUgfX08L2g0PlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi00XCI+e3sgaW50ZXJmYWNlRG9jLmRlc2NyaXB0aW9uIH19PC9wPlxuXG4gICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlXCI+XG4gICAgICAgICAgICAgIDx0aGVhZCBjbGFzcz1cImJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IHRleHQtbGVmdFwiPktp4buDdSBk4buvIGxp4buHdTwvdGg+XG4gICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgdGV4dC1sZWZ0XCI+TcO0IHThuqM8L3RoPlxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgICAgICBAZm9yIChwcm9wIG9mIGludGVyZmFjZURvYy5wcm9wZXJ0aWVzOyB0cmFjayBwcm9wLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cImJvcmRlci1iIGhvdmVyOmJnLWdyYXktNTBcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMyBweC00XCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYmctZ3JheS0xMDAgcHgtMSBweS0wLjUgcm91bmRlZCB0ZXh0LXNtIGZvbnQtbW9ub1wiPnt7IHByb3AubmFtZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0zIHB4LTRcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJiZy1ncmF5LTEwMCBweC0xIHB5LTAuNSByb3VuZGVkIHRleHQtc20gZm9udC1tb25vXCI+e3sgcHJvcC50eXBlIH19PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTMgcHgtNFwiPnt7IHByb3AuZGVzY3JpcHRpb24gfX08L3RkPlxuICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICA8L3RhYmxlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L3NlY3Rpb24+XG5cbiAgICA8c2VjdGlvbiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgc2hhZG93IHAtOCBtYi04XCI+XG4gICAgICA8aDIgY2xhc3M9XCJ0ZXh0LTJ4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi00IHBiLTIgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+VMOtbmggbsSDbmc8L2gyPlxuICAgICAgPHVsIGNsYXNzPVwic3BhY2UteS02XCI+XG4gICAgICAgIEBmb3IgKGZlYXR1cmUgb2YgZmVhdHVyZXMoKTsgdHJhY2sgZmVhdHVyZS5pZCkge1xuICAgICAgICAgIDxsaSBjbGFzcz1cImZsZXggaXRlbXMtc3RhcnRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC0zeGwgbWluLXctMTAgdGV4dC1jZW50ZXJcIj57eyBmZWF0dXJlLmljb24gfX08L3NwYW4+XG4gICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPnt7IGZlYXR1cmUudGl0bGUgfX08L2gzPlxuICAgICAgICAgICAgICA8cD57eyBmZWF0dXJlLmRlc2NyaXB0aW9uIH19PC9wPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9saT5cbiAgICAgICAgfVxuICAgICAgPC91bD5cbiAgICA8L3NlY3Rpb24+XG5cbiAgICA8c2VjdGlvbiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgc2hhZG93IHAtOCBtYi04XCI+XG4gICAgICA8aDIgY2xhc3M9XCJ0ZXh0LTJ4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi00IHBiLTIgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+Q8OhY2ggc+G7rSBk4bulbmc8L2gyPlxuICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTRcIj5cbiAgICAgICAgQGZvciAoZXhhbXBsZSBvZiBjb2RlRXhhbXBsZXMoKTsgdHJhY2sgZXhhbXBsZS5pZCkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJib3JkZXIgYm9yZGVyLWdyYXktMjAwIHJvdW5kZWQtbGcgcC00XCI+XG4gICAgICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi0yXCI+e3sgZXhhbXBsZS50aXRsZSB9fTwvaDM+XG4gICAgICAgICAgICA8cHJlXG4gICAgICAgICAgICAgIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQgb3ZlcmZsb3cteC1hdXRvXCI+PGNvZGUgW2lubmVySFRNTF09XCJleGFtcGxlLmNvZGVcIiBjbGFzcz1cImZvbnQtbW9ub1wiPjwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuICA8L21haW4+XG48L2Rpdj5cbiJdfQ==
|
|
@@ -654,11 +654,11 @@ export class MyComponent {
|
|
|
654
654
|
}
|
|
655
655
|
}
|
|
656
656
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAudioDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
657
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsAudioDemoComponent, isStandalone: true, selector: "lib-audio-demo", viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAudioComponent, selector: "libs_ui-components-audio", inputs: ["fileAudio", "checkPermissionDownloadAudio"], outputs: ["outFunctionsControl", "outVolumeControl", "outTimeUpdate", "outEnded", "outMute", "outPlay"] }] });
|
|
657
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsAudioDemoComponent, isStandalone: true, selector: "lib-audio-demo", viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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 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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAudioComponent, selector: "libs_ui-components-audio", inputs: ["fileAudio", "checkPermissionDownloadAudio"], outputs: ["outFunctionsControl", "outVolumeControl", "outTimeUpdate", "outEnded", "outMute", "outPlay"] }] });
|
|
658
658
|
}
|
|
659
659
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAudioDemoComponent, decorators: [{
|
|
660
660
|
type: Component,
|
|
661
|
-
args: [{ selector: 'lib-audio-demo', standalone: true, imports: [LibsUiComponentsAudioComponent], template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"] }]
|
|
661
|
+
args: [{ selector: 'lib-audio-demo', standalone: true, imports: [LibsUiComponentsAudioComponent], template: "<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\u00ECnh Ph\u00E1t \u00C2m Thanh</h1>\n <p class=\"text-xl text-gray-600\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ph\u00E1t v\u00E0 \u0111i\u1EC1u khi\u1EC3n \u00E2m 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\u1EDBi thi\u1EC7u</h2>\n <p class=\"text-lg\">\n <code class=\"bg-gray-100 px-1 py-0.5 rounded text-sm font-mono\">@libs-ui/components-audio</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng ph\u00E1t, t\u1EA1m d\u1EEBng v\u00E0 \u0111i\u1EC1u khi\u1EC3n c\u00E1c t\u1EC7p \u00E2m thanh v\u1EDBi nhi\u1EC1u t\u00EDnh n\u0103ng.\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\u00E0i \u0111\u1EB7t</h2>\n <p>\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c 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 @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\u00E9p\n </button>\n </div>\n\n <p>Ho\u1EB7c v\u1EDBi 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 @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\u00E9p\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\u1EF1c ti\u1EBFp</h2>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <p class=\"mb-4\">Th\u1EED nghi\u1EC7m tr\u00ECnh ph\u00E1t \u00E2m thanh v\u1EDBi c\u00E1c file m\u1EABu:</p>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Ch\u1ECDn file \u00E2m 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\u00ECnh ph\u00E1t:</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\">\u0110i\u1EC1u khi\u1EC3n 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\u00E1t/T\u1EA1m d\u1EEBng\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\u1EADt ti\u1EBFng' : 'T\u1EAFt ti\u1EBFng' }}\n </button>\n\n <div class=\"flex items-center gap-2 ml-2\">\n <span>\u00C2m l\u01B0\u1EE3ng:</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\u1EBFn \u0111\u1ED9:</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\u1EA3i xu\u1ED1ng\n </button>\n </div>\n\n <div class=\"mt-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Tr\u1EA1ng th\u00E1i:</h3>\n <div class=\"bg-white p-4 rounded border\">\n <div class=\"mb-2\">\n <strong>Tr\u1EA1ng th\u00E1i:</strong>\n <span [class.text-green-600]=\"isPlaying()\"\n [class.text-red-600]=\"!isPlaying()\">\n {{ isPlaying() ? '\u0110ang ph\u00E1t' : 'T\u1EA1m d\u1EEBng' }}\n </span>\n </div>\n <div class=\"mb-2\">\n <strong>Th\u1EDDi gian hi\u1EC7n t\u1EA1i:</strong>\n <span>{{ currentTime() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>T\u1ED5ng th\u1EDDi gian:</strong>\n <span>{{ duration() }}</span>\n </div>\n <div class=\"mb-2\">\n <strong>Ti\u1EBFn \u0111\u1ED9:</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\u00E0i li\u1EC7u 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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Tham s\u1ED1</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u tr\u1EA3 v\u1EC1</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EAn</th>\n <th class=\"py-3 px-4 text-left\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 text-left\">M\u00F4 t\u1EA3</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\u00EDnh n\u0103ng</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 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\u00E1ch s\u1EED d\u1EE5ng</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", styles: ["input[type=range]{cursor:pointer;-webkit-appearance:none;appearance:none;height:6px;border-radius:999px;background-color:#e5e7eb;outline:none;width:100%}input[type=range].volume-slider{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range]::-webkit-slider-runnable-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-moz-range-track{width:100%;height:6px;background-color:#e5e7eb;border-radius:999px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;margin-top:-5px}input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background-color:#3b82f6;cursor:pointer;transition:background-color .2s ease;border:none}input[type=range]::-webkit-slider-thumb:hover{background-color:#2563eb}input[type=range]::-moz-range-thumb:hover{background-color:#2563eb}input[type=range].volume-slider::-webkit-slider-runnable-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}input[type=range].volume-slider::-moz-range-track{background:linear-gradient(to right,#3b82f6 var(--volume-percent, 50%),#e5e7eb var(--volume-percent, 50%))}.control-button:active{transform:scale(.95)}libs_ui-components-audio{display:block;width:100%}.transition{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}pre::-webkit-scrollbar{height:8px}pre::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}pre::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}pre::-webkit-scrollbar-thumb:hover{background:#a1a1a1}\n"] }]
|
|
662
662
|
}], propDecorators: { audioPlayer: [{
|
|
663
663
|
type: ViewChild,
|
|
664
664
|
args: ['audioPlayer']
|
|
@@ -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/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: `<libs_ui-components-audio\n [fileAudio]=\"'path/to/audio.mp3'\"\n [checkPermissionDownloadAudio]=\"checkPermission\">\n</libs_ui-components-audio>`\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 <libs_ui-components-audio\n #audioPlayer\n [fileAudio]=\"audioSource()\"\n [checkPermissionDownloadAudio]=\"checkPermission\"\n (outFunctionsControl)=\"registerFunctions($event)\">\n </libs_ui-components-audio>\n \n <button (click)=\"playAudio()\">Phát/Tạm dừng</button>\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 <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()\">\n </libs_ui-components-audio>\n \n <div class=\"audio-info\">\n <p>Trạng thái: {{ isPlaying() ? 'Đang phát' : 'Tạm dừng' }}</p>\n <p>Thời gian hiện tại: {{ currentTime() }}</p>\n <p>Tổng thời gian: {{ duration() }}</p>\n <p>Âm lượng: {{ volumeLevel() }}%</p>\n </div>\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\">@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 @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 @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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"}
|
|
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: `<libs_ui-components-audio\n [fileAudio]=\"'path/to/audio.mp3'\"\n [checkPermissionDownloadAudio]=\"checkPermission\">\n</libs_ui-components-audio>`\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 <libs_ui-components-audio\n #audioPlayer\n [fileAudio]=\"audioSource()\"\n [checkPermissionDownloadAudio]=\"checkPermission\"\n (outFunctionsControl)=\"registerFunctions($event)\">\n </libs_ui-components-audio>\n \n <button (click)=\"playAudio()\">Phát/Tạm dừng</button>\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 <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()\">\n </libs_ui-components-audio>\n \n <div class=\"audio-info\">\n <p>Trạng thái: {{ isPlaying() ? 'Đang phát' : 'Tạm dừng' }}</p>\n <p>Thời gian hiện tại: {{ currentTime() }}</p>\n <p>Tổng thời gian: {{ duration() }}</p>\n <p>Âm lượng: {{ volumeLevel() }}%</p>\n </div>\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\">@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 @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 @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 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":";;;;;MAea,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;;IAGrE,mBAAmB,GAAG,MAAM,EAA8B;IAC1D,gBAAgB,GAAG,MAAM,EAAU;IACnC,aAAa,GAAG,MAAM,EAA6C;IACnE,QAAQ,GAAG,MAAM,EAAQ;IACzB,OAAO,GAAG,MAAM,EAAW;IAC3B,OAAO,GAAG,MAAM,EAAW;AAEpC,IAAA,WAAA,GAAA;;QAEE,MAAM,CAAC,MAAK;YACV,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;;gBAEvC,UAAU,CAAC,MAAK;oBACd,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE;iBACrC,EAAE,CAAC,CAAC;;AAET,SAAC,CAAC;QACF,MAAM,CAAC,MAAK;YACV,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;AACrD,SAAC,CAAC;QACF,MAAM,CAAC,MAAK;YACV,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;AACvG,SAAC,CAAC;QACF,MAAM,CAAC,MAAK;YACV,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;AAClC,SAAC,CAAC;QACF,MAAM,CAAC,MAAK;YACV,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;AAClC,SAAC,CAAC;;IAGJ,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;;AAG7C,QAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;YAC5B,SAAS,EAAE,CAAC,KAAa,KAAK,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC;YAC/D,UAAU,EAAE,CAAC,KAAa,KAAK,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC;YAChE,MAAM,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1C,SAAS,EAAE,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;YAC9C,QAAQ,EAAE,CAAC,KAAa,KAAK,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;AACxD,YAAA,SAAS,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE;AAC9B,YAAA,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM;AAC3B,SAAA,CAAC;;;IAII,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,KAAa,EAAA;QACjD,IAAI,KAAK,EAAE;YACT,KAAK,CAAC,eAAe,EAAE;;QAGzB,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,KAAa,EAAA;QACjD,IAAI,KAAK,EAAE;YACT,KAAK,CAAC,eAAe,EAAE;;QAGzB,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,IAAI,KAAK,EAAE;YACT,KAAK,CAAC,eAAe,EAAE;;AAGzB,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,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1G,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,YAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE;;;IAI/B,MAAM,iBAAiB,CAAC,KAAa,EAAA;QAC7C,IAAI,KAAK,EAAE;YACT,KAAK,CAAC,eAAe,EAAE;;AAEzB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QAClE,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,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1G,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,IAAI,CAAC,CAAC,GAAG,GAAG;YAElI;;AAEF,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;;IAGxI,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,GAAG,GAAG,GAAG,IAAI,CAAC;AACd,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;;AAEF,QAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,WAAW,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,GAAG;AAC9G,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;AAClD,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC;QAChC,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,IAAI,KAAK,EAAE;YACT,KAAK,CAAC,eAAe,EAAE;;AAGzB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;;IAGZ,MAAM,eAAe,CAAC,CAAS,EAAA;AACvC,QAAA,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,4BAA4B,EAAE,EAAE,EAAE;YACxF;;QAGF,IAAI,CAAC,EAAE;YACL,CAAC,CAAC,eAAe,EAAE;;AAGrB,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;;wGAtNhB,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,OAAA,EAAA,EAAA,mBAAA,EAAA,qBAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,EAAA,SAAA,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,ECf3C,shEAoDA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDxCI,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;;;MEFU,kCAAkC,CAAA;AACnB,IAAA,WAAW;;AAG9B,IAAA,SAAS,GAAG,MAAM,CAAU,KAAK,CAAC;AAClC,IAAA,OAAO,GAAG,MAAM,CAAU,KAAK,CAAC;AAChC,IAAA,MAAM,GAAG,MAAM,CAAS,GAAG,CAAC;AAC5B,IAAA,WAAW,GAAG,MAAM,CAAS,UAAU,CAAC;AACxC,IAAA,QAAQ,GAAG,MAAM,CAAS,UAAU,CAAC;AACrC,IAAA,QAAQ,GAAG,MAAM,CAAS,CAAC,CAAC;;AAG5B,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;;AAGzD,IAAA,aAAa,GAAG,MAAM,CAAS,CAAC,CAAC;AACjC,IAAA,kBAAkB,GAAG,MAAM,CAAS,iHAAiH,CAAC;;IAGtJ,gBAAgB,GAAsC,IAAI;;IAG1D,YAAY,GAAG,MAAM,CAAqE;AAC/F,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,GAAG,EAAE,iHAAiH;AACtH,YAAA,QAAQ,EAAE;AACX,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,GAAG,EAAE,+DAA+D;AACpE,YAAA,QAAQ,EAAE;AACX,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,GAAG,EAAE,0EAA0E;AAC/E,YAAA,QAAQ,EAAE;AACX;AACF,KAAA,CAAC;;IAGK,SAAS,GAAG,MAAM,CAA8E;AACrG,QAAA;AACE,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,OAAO,EAAE,UAAU;AACnB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,8BAA8B;AACpC,YAAA,IAAI,EAAE,wBAAwB;AAC9B,YAAA,OAAO,EAAE,UAAU;AACnB,YAAA,WAAW,EAAE;AACd;AACF,KAAA,CAAC;;IAGK,UAAU,GAAG,MAAM,CAA6D;AACrF,QAAA;AACE,YAAA,IAAI,EAAE,qBAAqB;AAC3B,YAAA,IAAI,EAAE,4BAA4B;AAClC,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,kBAAkB;AACxB,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,eAAe;AACrB,YAAA,IAAI,EAAE,2CAA2C;AACjD,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,UAAU;AAChB,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,WAAW,EAAE;AACd;AACF,KAAA,CAAC;;IAGK,aAAa,GAAG,MAAM,CAAuH;AAClJ,QAAA;AACE,YAAA,IAAI,EAAE,4BAA4B;AAClC,YAAA,WAAW,EAAE,6EAA6E;AAC1F,YAAA,UAAU,EAAE;AACV,gBAAA;AACE,oBAAA,IAAI,EAAE,WAAW;AACjB,oBAAA,IAAI,EAAE,yBAAyB;AAC/B,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,IAAI,EAAE,YAAY;AAClB,oBAAA,IAAI,EAAE,yBAAyB;AAC/B,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,IAAI,EAAE,WAAW;AACjB,oBAAA,IAAI,EAAE,yBAAyB;AAC/B,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,IAAI,EAAE,QAAQ;AACd,oBAAA,IAAI,EAAE,yBAAyB;AAC/B,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,IAAI,EAAE,UAAU;AAChB,oBAAA,IAAI,EAAE,yBAAyB;AAC/B,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,IAAI,EAAE,WAAW;AACjB,oBAAA,IAAI,EAAE,eAAe;AACrB,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,IAAI,EAAE,SAAS;AACf,oBAAA,IAAI,EAAE,eAAe;AACrB,oBAAA,WAAW,EAAE;AACd;AACF;AACF;AACF,KAAA,CAAC;;IAGK,UAAU,GAAG,MAAM,CAAmF;AAC3G,QAAA;AACE,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,MAAM,EAAE,eAAe;AACvB,YAAA,UAAU,EAAE,MAAM;AAClB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,YAAY;AAClB,YAAA,MAAM,EAAE,eAAe;AACvB,YAAA,UAAU,EAAE,MAAM;AAClB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,MAAM,EAAE,eAAe;AACvB,YAAA,UAAU,EAAE,MAAM;AAClB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,MAAM,EAAE,eAAe;AACvB,YAAA,UAAU,EAAE,MAAM;AAClB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,UAAU;AAChB,YAAA,MAAM,EAAE,eAAe;AACvB,YAAA,UAAU,EAAE,MAAM;AAClB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,MAAM,EAAE,EAAE;AACV,YAAA,UAAU,EAAE,SAAS;AACrB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,MAAM,EAAE,EAAE;AACV,YAAA,UAAU,EAAE,SAAS;AACrB,YAAA,WAAW,EAAE;AACd;AACF,KAAA,CAAC;;IAGK,QAAQ,GAAG,MAAM,CAA0E;AAChG,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,KAAK,EAAE,kBAAkB;AACzB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,KAAK,EAAE,kBAAkB;AACzB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,KAAK,EAAE,oBAAoB;AAC3B,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,KAAK,EAAE,eAAe;AACtB,YAAA,WAAW,EAAE;AACd,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,IAAI,EAAE,IAAI;AACV,YAAA,KAAK,EAAE,WAAW;AAClB,YAAA,WAAW,EAAE;AACd;AACF,KAAA,CAAC;;IAGK,YAAY,GAAG,MAAM,CAAqD;AAC/E,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,KAAK,EAAE,gBAAgB;AACvB,YAAA,IAAI,EAAE,CAAA;;;AAGsB,iCAAA;AAC7B,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,KAAK,EAAE,0BAA0B;AACjC,YAAA,IAAI,EAAE,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BV,CAAA;AACG,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,CAAC;AACL,YAAA,KAAK,EAAE,+BAA+B;AACtC,YAAA,IAAI,EAAE,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDV,CAAA;AACG;AACF,KAAA,CAAC;;IAGK,SAAS,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE;AACjC,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC;;;IAIlD,UAAU,GAAA;AACf,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE;AAClC,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;;;AAI9C,IAAA,YAAY,CAAC,KAAY,EAAA;QAC9B,IAAI,IAAI,CAAC,gBAAgB,IAAI,KAAK,CAAC,MAAM,EAAE;YACzC,MAAM,KAAK,GAAG,QAAQ,CAAE,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;AAChE,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,YAAA,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC;AACtC,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;;;IAI9C,aAAa,GAAA;AAClB,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE;;;AAIpC;;AAEG;AACI,IAAA,UAAU,CAAC,aAAqB,EAAA;QACrC,IAAI,KAAK,CAAC,aAAa,CAAC;AAAE,YAAA,OAAO,UAAU;QAE3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;AAC9C,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACjE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,OAAO,GAAG,EAAE,CAAC,CAAC;AAE3E,QAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA,CAAA,EAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA,CAAA,EAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;;AAG7H;;AAEG;AACI,IAAA,eAAe,CAAC,IAAY,EAAA;AACjC,QAAA,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI;aAC/B,IAAI,CAAC,MAAK;YACT,KAAK,CAAC,4BAA4B,CAAC;AACrC,SAAC;aACA,KAAK,CAAC,GAAG,IAAG;AACX,YAAA,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC;AACxC,SAAC,CAAC;;AAGN;;AAEG;AACI,IAAA,iBAAiB,CAAC,KAAiC,EAAA;AACxD,QAAA,IAAI,CAAC,gBAAgB,GAAG,KAAK;;AAG7B,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC;AACrD,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;;;AAIrD;;AAEG;AACI,IAAA,gBAAgB,CAAC,QAAmD,EAAA;QACzE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;;QAGpC,MAAM,KAAK,GAAG,mBAAmB;QACjC,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC;QACxD,MAAM,eAAe,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;AAEtD,QAAA,IAAI,cAAc,IAAI,eAAe,EAAE;YACrC,MAAM,cAAc,GAClB,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;AAClC,gBAAA,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;AAChC,gBAAA,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YAE7B,MAAM,YAAY,GAChB,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;AACnC,gBAAA,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;AACjC,gBAAA,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAE9B,YAAA,IAAI,YAAY,GAAG,CAAC,EAAE;AACpB,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,cAAc,GAAG,YAAY,IAAI,GAAG,CAAC,CAAC;;;;AAK1E;;AAEG;AACI,IAAA,kBAAkB,CAAC,MAAc,EAAA;AACtC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;;AAGzB;;AAEG;AACI,IAAA,gBAAgB,CAAC,SAAkB,EAAA;AACxC,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;;AAG/B;;AAEG;AACI,IAAA,gBAAgB,CAAC,OAAgB,EAAA;AACtC,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;;AAG3B;;AAEG;IACI,WAAW,GAAA;AAChB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;;AAG3B;;AAEG;AACI,IAAA,WAAW,CAAC,EAAU,EAAA;AAC3B,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QACjE,IAAI,MAAM,EAAE;;AAEV,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACpB,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC;AAChC,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;;YAG7B,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;;;AAI3C;;AAEG;IACI,uBAAuB,GAAG,MAAuB;AACtD,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;AAC9B,KAAC;AAED;;AAEG;AACI,IAAA,gBAAgB,CAAC,KAAiB,EAAA;AACvC,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,MAAM,WAAW,GAAG,KAAK,CAAC,aAA4B;AACtD,YAAA,MAAM,IAAI,GAAG,WAAW,CAAC,qBAAqB,EAAE;YAChD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;YACzC,MAAM,QAAQ,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,GAAG;;AAG7C,YAAA,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC3D,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;;YAG7C,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;;;wGA7etC,kCAAkC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAlC,kCAAkC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,aAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,aAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECX/C,yqbAiSA,EAAA,MAAA,EAAA,CAAA,yvDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,ED1RY,8BAA8B,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,8BAAA,CAAA,EAAA,OAAA,EAAA,CAAA,qBAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAI7B,kCAAkC,EAAA,UAAA,EAAA,CAAA;kBAP9C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EACd,UAAA,EAAA,IAAI,EACP,OAAA,EAAA,CAAC,8BAA8B,CAAC,EAAA,QAAA,EAAA,yqbAAA,EAAA,MAAA,EAAA,CAAA,yvDAAA,CAAA,EAAA;8BAKf,WAAW,EAAA,CAAA;sBAApC,SAAS;uBAAC,aAAa;;;AEZ1B;;AAEG;;;;"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-audio",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.229",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/core": "^18.2.0",
|
|
6
|
-
"@libs-ui/components-inputs-range-slider": "^0.2.
|
|
6
|
+
"@libs-ui/components-inputs-range-slider": "^0.2.229",
|
|
7
7
|
"rxjs": "~7.8.0"
|
|
8
8
|
},
|
|
9
9
|
"sideEffects": false,
|