horeg-audio 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -0
- package/dist/horeg-audio.cjs +828 -0
- package/dist/horeg-audio.cjs.map +1 -0
- package/dist/horeg-audio.global.js +828 -0
- package/dist/horeg-audio.global.js.map +1 -0
- package/dist/horeg-audio.js +1677 -0
- package/dist/horeg-audio.js.map +1 -0
- package/dist/index.d.ts +152 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"horeg-audio.global.js","sources":["../src/styles.ts","../src/utils/time.ts","../src/AudioEngine.ts","../src/utils/dom.ts","../src/UI.ts","../src/visualizer.ts","../src/Player.ts"],"sourcesContent":["import { HoregTheme, ThemeVariant } from './types';\r\n\r\nexport const THEME_PRESETS: Record<ThemeVariant, Partial<HoregTheme>> = {\r\n 'horeg-classic': {\r\n primaryGlowColor: '#f59e0b',\r\n accentColor: '#ef4444',\r\n cardBackground: '#121214',\r\n textColor: '#f4f4f5',\r\n sliderProgressColor: '#f59e0b',\r\n borderRadius: '14px'\r\n },\r\n 'horeg-nightclub': {\r\n primaryGlowColor: '#06b6d4',\r\n accentColor: '#ec4899',\r\n cardBackground: '#0b0c10',\r\n textColor: '#f8fafc',\r\n sliderProgressColor: '#06b6d4',\r\n borderRadius: '14px'\r\n },\r\n 'horeg-stealth': {\r\n primaryGlowColor: '#94a3b8',\r\n accentColor: '#e2e8f0',\r\n cardBackground: '#0f1115',\r\n textColor: '#e2e8f0',\r\n sliderProgressColor: '#94a3b8',\r\n borderRadius: '8px'\r\n }\r\n};\r\n\r\n/**\r\n * Returns complete encapsulated CSS string for the Shadow DOM.\r\n */\r\nexport function generateStyles(theme: HoregTheme = {}): string {\r\n const variant = theme.variant || 'horeg-classic';\r\n const preset = THEME_PRESETS[variant] || THEME_PRESETS['horeg-classic'];\r\n\r\n const glow = theme.primaryGlowColor || preset.primaryGlowColor || '#f59e0b';\r\n const accent = theme.accentColor || preset.accentColor || '#ef4444';\r\n const bg = theme.cardBackground || preset.cardBackground || '#121214';\r\n const text = theme.textColor || preset.textColor || '#f4f4f5';\r\n const progress = theme.sliderProgressColor || preset.sliderProgressColor || glow;\r\n const radius = theme.borderRadius || preset.borderRadius || '14px';\r\n\r\n return `\r\n :host {\r\n --horeg-bg: ${bg};\r\n --horeg-surface: #18181b;\r\n --horeg-surface-hover: #222226;\r\n --horeg-border: #27272a;\r\n --horeg-glow: ${glow};\r\n --horeg-glow-rgb: 245, 158, 11;\r\n --horeg-accent: ${accent};\r\n --horeg-progress: ${progress};\r\n --horeg-text-main: ${text};\r\n --horeg-text-muted: #a1a1aa;\r\n --horeg-radius: ${radius};\r\n display: block;\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\r\n box-sizing: border-box;\r\n outline: none;\r\n user-select: none;\r\n -webkit-user-select: none;\r\n }\r\n\r\n *, *::before, *::after {\r\n box-sizing: border-box;\r\n margin: 0;\r\n padding: 0;\r\n }\r\n\r\n .horeg-player-box {\r\n background: var(--horeg-bg);\r\n border: 2px solid var(--horeg-border);\r\n border-radius: var(--horeg-radius);\r\n box-shadow: 0 16px 40px -10px rgba(0, 0, 0, 0.9), 0 0 20px -5px var(--horeg-glow);\r\n color: var(--horeg-text-main);\r\n position: relative;\r\n overflow: hidden;\r\n max-width: 520px;\r\n width: 100%;\r\n margin: 0 auto;\r\n transition: box-shadow 0.3s ease, border-color 0.3s ease;\r\n }\r\n\r\n /* Player Box active glow when focused within */\r\n :host(:focus) .horeg-player-box,\r\n :host(:focus-within) .horeg-player-box,\r\n .horeg-player-box:focus-within {\r\n border-color: var(--horeg-glow);\r\n box-shadow: 0 20px 48px -10px rgba(0, 0, 0, 0.95), 0 0 30px -2px var(--horeg-glow), 0 0 10px var(--horeg-glow);\r\n }\r\n\r\n :host(:focus) .horeg-player-box .horeg-bolt,\r\n :host(:focus-within) .horeg-player-box .horeg-bolt,\r\n .horeg-player-box:focus-within .horeg-bolt {\r\n box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.3), 0 0 4px var(--horeg-glow);\r\n }\r\n\r\n .horeg-speaker-grill {\r\n position: absolute;\r\n inset: 0;\r\n background-image: radial-gradient(#2c2d33 1.2px, transparent 1.2px);\r\n background-size: 8px 8px;\r\n opacity: 0.3;\r\n pointer-events: none;\r\n z-index: 1;\r\n }\r\n\r\n /* Metal Corner Brackets / Screws (Sound System Rig Rigging) */\r\n .horeg-bolt {\r\n position: absolute;\r\n width: 8px;\r\n height: 8px;\r\n background: #3f3f46;\r\n border: 1px solid #18181b;\r\n border-radius: 50%;\r\n box-shadow: inset 0 1px 1px rgba(255,255,255,0.2), 0 1px 2px rgba(0,0,0,0.8);\r\n z-index: 2;\r\n }\r\n .horeg-bolt::after {\r\n content: '';\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n width: 4px;\r\n height: 1px;\r\n background: #18181b;\r\n transform: translate(-50%, -50%) rotate(45deg);\r\n }\r\n .horeg-bolt.top-left { top: 7px; left: 7px; }\r\n .horeg-bolt.top-right { top: 7px; right: 7px; }\r\n .horeg-bolt.bottom-left { bottom: 7px; left: 7px; }\r\n .horeg-bolt.bottom-right { bottom: 7px; right: 7px; }\r\n\r\n .horeg-content-wrap {\r\n position: relative;\r\n z-index: 3;\r\n padding: 18px 20px 16px 20px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 14px;\r\n }\r\n\r\n /* Top Rig Header */\r\n .horeg-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n border-bottom: 1px solid #27272a;\r\n padding-bottom: 8px;\r\n }\r\n\r\n .horeg-rig-badge {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 10px;\r\n letter-spacing: 1.5px;\r\n text-transform: uppercase;\r\n font-weight: 800;\r\n color: var(--horeg-glow);\r\n text-shadow: 0 0 8px var(--horeg-glow);\r\n }\r\n\r\n .horeg-badge-led {\r\n width: 7px;\r\n height: 7px;\r\n background-color: var(--horeg-glow);\r\n border-radius: 50%;\r\n box-shadow: 0 0 6px var(--horeg-glow);\r\n animation: ledPulse 2s infinite ease-in-out;\r\n }\r\n\r\n @keyframes ledPulse {\r\n 0%, 100% { opacity: 0.5; transform: scale(0.9); }\r\n 50% { opacity: 1; transform: scale(1.1); box-shadow: 0 0 10px var(--horeg-glow); }\r\n }\r\n\r\n /* Track Display & Visualizer Section */\r\n .horeg-track-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 14px;\r\n }\r\n\r\n .horeg-cover-container {\r\n position: relative;\r\n width: 64px;\r\n height: 64px;\r\n min-width: 64px;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n background: #18181b;\r\n border: 1px solid #3f3f46;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n box-shadow: inset 0 0 10px rgba(0,0,0,0.8), 0 2px 6px rgba(0,0,0,0.6);\r\n }\r\n\r\n .horeg-cover-img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n }\r\n\r\n .horeg-cover-fallback {\r\n color: var(--horeg-glow);\r\n opacity: 0.7;\r\n }\r\n\r\n .horeg-track-info {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n\r\n .horeg-track-title {\r\n font-size: 15px;\r\n font-weight: 700;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n color: var(--horeg-text-main);\r\n letter-spacing: 0.2px;\r\n }\r\n\r\n .horeg-track-artist {\r\n font-size: 12px;\r\n font-weight: 500;\r\n color: var(--horeg-text-muted);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .horeg-track-album {\r\n font-size: 10px;\r\n color: #71717a;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n /* Mini EQ Visualizer */\r\n .horeg-eq-wrapper {\r\n display: flex;\r\n align-items: flex-end;\r\n gap: 2px;\r\n height: 24px;\r\n padding: 0 4px;\r\n }\r\n\r\n .horeg-eq-bar {\r\n width: 3px;\r\n height: 4px;\r\n background: var(--horeg-glow);\r\n border-radius: 1px;\r\n transition: height 0.1s ease;\r\n box-shadow: 0 0 4px var(--horeg-glow);\r\n }\r\n\r\n /* Scrubbing / Fader Progress Bar */\r\n .horeg-progress-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 5px;\r\n }\r\n\r\n .horeg-time-row {\r\n display: flex;\r\n justify-content: space-between;\r\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace;\r\n font-size: 11px;\r\n color: var(--horeg-text-muted);\r\n }\r\n\r\n .horeg-slider-track {\r\n position: relative;\r\n width: 100%;\r\n height: 7px;\r\n background: #27272a;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n overflow: hidden;\r\n box-shadow: inset 0 1px 3px rgba(0,0,0,0.8);\r\n }\r\n\r\n .horeg-buffer-bar {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n width: 0%;\r\n background: #3f3f46;\r\n border-radius: 4px;\r\n transition: width 0.2s linear;\r\n }\r\n\r\n .horeg-fill-bar {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n width: 0%;\r\n background: linear-gradient(90deg, var(--horeg-accent) 0%, var(--horeg-progress) 100%);\r\n border-radius: 4px;\r\n box-shadow: 0 0 8px var(--horeg-glow);\r\n transition: width 0.08s linear;\r\n }\r\n\r\n /* Controls Row */\r\n .horeg-controls-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding-top: 4px;\r\n }\r\n\r\n .horeg-side-controls {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n }\r\n\r\n .horeg-center-controls {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n\r\n .horeg-btn {\r\n background: transparent;\r\n border: none;\r\n outline: none;\r\n color: var(--horeg-text-muted);\r\n cursor: pointer;\r\n padding: 6px;\r\n border-radius: 8px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: all 0.15s ease;\r\n touch-action: manipulation;\r\n }\r\n\r\n .horeg-btn:hover {\r\n color: var(--horeg-text-main);\r\n background: var(--horeg-surface-hover);\r\n }\r\n\r\n .horeg-btn:active {\r\n transform: scale(0.92);\r\n filter: brightness(1.2);\r\n }\r\n\r\n .horeg-btn:focus-visible {\r\n outline: 2px solid var(--horeg-glow);\r\n outline-offset: 1px;\r\n }\r\n\r\n .horeg-btn.active {\r\n color: var(--horeg-glow);\r\n background: rgba(255, 255, 255, 0.06);\r\n text-shadow: 0 0 8px var(--horeg-glow);\r\n box-shadow: inset 0 0 8px rgba(255, 255, 255, 0.05);\r\n }\r\n\r\n /* Primary Play / Pause Button with Neon Glow Pulse */\r\n .horeg-btn-play {\r\n width: 44px;\r\n height: 44px;\r\n border-radius: 50%;\r\n background: #1f1f23;\r\n border: 2px solid var(--horeg-glow);\r\n color: var(--horeg-glow);\r\n box-shadow: 0 0 12px -2px var(--horeg-glow);\r\n transition: transform 0.12s ease, box-shadow 0.2s ease, background 0.2s ease;\r\n }\r\n\r\n .horeg-btn-play:hover {\r\n background: #27272a;\r\n transform: scale(1.06);\r\n box-shadow: 0 0 18px 2px var(--horeg-glow);\r\n }\r\n\r\n .horeg-btn-play:active {\r\n transform: scale(0.96);\r\n }\r\n\r\n .horeg-btn-play.playing {\r\n background: var(--horeg-glow);\r\n color: #09090b;\r\n box-shadow: 0 0 20px var(--horeg-glow), inset 0 0 8px rgba(255, 255, 255, 0.4);\r\n animation: playPulse 2.2s infinite ease-in-out;\r\n }\r\n\r\n @keyframes playPulse {\r\n 0%, 100% {\r\n box-shadow: 0 0 15px var(--horeg-glow);\r\n }\r\n 50% {\r\n box-shadow: 0 0 25px var(--horeg-glow), 0 0 8px #fff;\r\n }\r\n }\r\n\r\n /* Volume Slider Rel Mixer */\r\n .horeg-volume-wrap {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n\r\n .horeg-volume-slider {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 70px;\r\n height: 5px;\r\n background: #27272a;\r\n border-radius: 3px;\r\n outline: none;\r\n cursor: pointer;\r\n }\r\n\r\n .horeg-volume-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: var(--horeg-glow);\r\n border: 1px solid #18181b;\r\n box-shadow: 0 0 6px var(--horeg-glow);\r\n cursor: pointer;\r\n transition: transform 0.1s ease;\r\n }\r\n\r\n .horeg-volume-slider::-webkit-slider-thumb:hover {\r\n transform: scale(1.2);\r\n }\r\n\r\n .horeg-volume-slider::-moz-range-thumb {\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: var(--horeg-glow);\r\n border: 1px solid #18181b;\r\n box-shadow: 0 0 6px var(--horeg-glow);\r\n cursor: pointer;\r\n }\r\n\r\n /* Drag Over Highlight on main player */\r\n .horeg-player-box.drag-over {\r\n border-color: var(--horeg-glow);\r\n box-shadow: 0 0 25px var(--horeg-glow), 0 8px 32px rgba(0, 0, 0, 0.9);\r\n }\r\n\r\n /* Rack Mount Playlist Drawer */\r\n .horeg-drawer {\r\n max-height: 0;\r\n opacity: 0;\r\n overflow-y: auto;\r\n transition: max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s ease;\r\n background: #141416;\r\n border-top: 1px solid #27272a;\r\n border-radius: 0 0 calc(var(--horeg-radius) - 2px) calc(var(--horeg-radius) - 2px);\r\n scrollbar-width: thin;\r\n scrollbar-color: #3f3f46 #18181b;\r\n position: relative;\r\n z-index: 3;\r\n }\r\n\r\n .horeg-drawer.open {\r\n max-height: 220px;\r\n max-height: 380px;\r\n opacity: 1;\r\n }\r\n\r\n /* Drawer Header */\r\n .horeg-drawer-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 14px 8px 14px;\r\n border-bottom: 1px solid #27272a;\r\n position: sticky;\r\n top: 0;\r\n background: #141416;\r\n z-index: 2;\r\n }\r\n\r\n .horeg-drawer-heading {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 11px;\r\n font-weight: 700;\r\n letter-spacing: 0.8px;\r\n color: var(--horeg-text-muted);\r\n text-transform: uppercase;\r\n font-family: ui-monospace, monospace;\r\n }\r\n\r\n .horeg-drawer-count {\r\n padding: 1px 6px;\r\n background: #27272a;\r\n color: var(--horeg-glow);\r\n border-radius: 10px;\r\n font-size: 10px;\r\n font-weight: 700;\r\n }\r\n\r\n .horeg-btn-add-track {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 5px;\r\n padding: 4px 9px;\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--horeg-text-main);\r\n background: #1f1f23;\r\n border: 1px solid #3f3f46;\r\n border-radius: 5px;\r\n cursor: pointer;\r\n transition: all 0.15s ease;\r\n }\r\n\r\n .horeg-btn-add-track:hover {\r\n background: #27272a;\r\n border-color: var(--horeg-glow);\r\n color: var(--horeg-glow);\r\n box-shadow: 0 0 8px rgba(245, 158, 11, 0.2);\r\n }\r\n\r\n .horeg-btn-add-track.active {\r\n background: #27272a;\r\n border-color: var(--horeg-glow);\r\n color: var(--horeg-glow);\r\n box-shadow: 0 0 12px var(--horeg-glow);\r\n text-shadow: 0 0 6px var(--horeg-glow);\r\n }\r\n\r\n .horeg-btn-add-track:active {\r\n transform: scale(0.95);\r\n }\r\n\r\n /* Add Track Panel Form */\r\n .horeg-add-panel {\r\n display: none;\r\n flex-direction: column;\r\n gap: 10px;\r\n margin: 10px 12px;\r\n padding: 12px;\r\n background: #18181b;\r\n border: 1px solid #3f3f46;\r\n border-radius: 8px;\r\n box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);\r\n animation: fadeIn 0.2s ease;\r\n }\r\n\r\n .horeg-add-panel.open {\r\n display: flex;\r\n }\r\n\r\n .horeg-add-tabs {\r\n display: flex;\r\n gap: 6px;\r\n border-bottom: 1px solid #27272a;\r\n padding-bottom: 8px;\r\n }\r\n\r\n .horeg-tab-btn {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n padding: 6px 10px;\r\n font-size: 11px;\r\n font-weight: 600;\r\n background: #202024;\r\n color: var(--horeg-text-muted);\r\n border: 1px solid #2e2e33;\r\n border-radius: 5px;\r\n cursor: pointer;\r\n transition: all 0.15s ease;\r\n }\r\n\r\n .horeg-tab-btn:hover {\r\n color: var(--horeg-text-main);\r\n border-color: #52525b;\r\n }\r\n\r\n .horeg-tab-btn.active {\r\n background: #27272a;\r\n color: var(--horeg-glow);\r\n border-color: var(--horeg-glow);\r\n box-shadow: 0 0 10px var(--horeg-glow);\r\n text-shadow: 0 0 6px var(--horeg-glow);\r\n }\r\n\r\n .horeg-tab-btn:active {\r\n transform: scale(0.97);\r\n }\r\n\r\n .horeg-tab-pane {\r\n display: none;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n\r\n .horeg-tab-pane.active {\r\n display: flex;\r\n }\r\n\r\n /* Dropzone for local file */\r\n .horeg-dropzone {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n padding: 16px 10px;\r\n border: 2px dashed #3f3f46;\r\n border-radius: 6px;\r\n background: #141416;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n text-align: center;\r\n }\r\n\r\n .horeg-dropzone:hover,\r\n .horeg-dropzone.drag-active {\r\n border-color: var(--horeg-glow);\r\n background: rgba(245, 158, 11, 0.05);\r\n box-shadow: 0 0 10px rgba(245, 158, 11, 0.15);\r\n }\r\n\r\n .horeg-dropzone-icon {\r\n color: var(--horeg-glow);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n .horeg-dropzone-text {\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--horeg-text-main);\r\n }\r\n\r\n .horeg-dropzone-hint {\r\n font-size: 10px;\r\n color: var(--horeg-text-muted);\r\n }\r\n\r\n /* Inputs for URL / Meta */\r\n .horeg-input-field {\r\n width: 100%;\r\n box-sizing: border-box;\r\n padding: 7px 10px;\r\n font-size: 12px;\r\n background: #121214;\r\n border: 1px solid #3f3f46;\r\n border-radius: 5px;\r\n color: var(--horeg-text-main);\r\n outline: none;\r\n transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;\r\n }\r\n\r\n .horeg-input-field:focus {\r\n border-color: var(--horeg-glow);\r\n background: #18181b;\r\n box-shadow: 0 0 0 1px var(--horeg-glow), 0 0 10px var(--horeg-glow);\r\n outline: none;\r\n }\r\n\r\n .horeg-input-field::placeholder {\r\n color: #71717a;\r\n font-size: 11px;\r\n }\r\n\r\n .horeg-form-actions {\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-end;\r\n gap: 6px;\r\n margin-top: 4px;\r\n }\r\n\r\n .horeg-btn-submit {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 5px;\r\n padding: 6px 12px;\r\n font-size: 11px;\r\n font-weight: 700;\r\n background: var(--horeg-glow);\r\n color: #09090b;\r\n border: none;\r\n border-radius: 5px;\r\n cursor: pointer;\r\n transition: opacity 0.15s ease, transform 0.1s ease;\r\n }\r\n\r\n .horeg-btn-submit:hover {\r\n opacity: 0.9;\r\n transform: translateY(-1px);\r\n }\r\n\r\n .horeg-btn-submit:active {\r\n transform: scale(0.96);\r\n filter: brightness(1.15);\r\n }\r\n\r\n .horeg-btn-cancel {\r\n padding: 6px 10px;\r\n font-size: 11px;\r\n font-weight: 600;\r\n background: transparent;\r\n color: var(--horeg-text-muted);\r\n border: 1px solid transparent;\r\n border-radius: 5px;\r\n cursor: pointer;\r\n transition: color 0.15s ease, transform 0.1s ease;\r\n }\r\n\r\n .horeg-btn-cancel:hover {\r\n color: var(--horeg-text-main);\r\n }\r\n\r\n .horeg-btn-cancel:active {\r\n transform: scale(0.96);\r\n }\r\n\r\n .horeg-drawer-inner {\r\n padding: 6px 10px 10px 10px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n\r\n .horeg-track-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n padding: 8px 10px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n transition: background 0.15s ease;\r\n font-size: 13px;\r\n }\r\n\r\n .horeg-track-item:hover {\r\n background: #1f1f23;\r\n }\r\n\r\n .horeg-track-item.active {\r\n background: linear-gradient(90deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.02) 100%);\r\n color: var(--horeg-glow);\r\n border-left: 3px solid var(--horeg-glow);\r\n box-shadow: inset 3px 0 6px -2px var(--horeg-glow), 0 2px 8px rgba(0, 0, 0, 0.4);\r\n position: relative;\r\n }\r\n\r\n .horeg-track-item.active .horeg-track-num {\r\n color: var(--horeg-glow);\r\n font-weight: 700;\r\n text-shadow: 0 0 8px var(--horeg-glow);\r\n }\r\n\r\n .horeg-track-item.active .horeg-item-title {\r\n color: var(--horeg-glow);\r\n font-weight: 700;\r\n text-shadow: 0 0 8px var(--horeg-glow);\r\n }\r\n\r\n .horeg-track-item.active .horeg-item-artist {\r\n color: var(--horeg-text-main);\r\n opacity: 0.9;\r\n }\r\n\r\n .horeg-track-item.active .horeg-item-duration {\r\n color: var(--horeg-glow);\r\n opacity: 0.9;\r\n }\r\n\r\n .horeg-track-item:focus-visible {\r\n outline: 2px solid var(--horeg-glow);\r\n outline-offset: -1px;\r\n }\r\n\r\n .horeg-track-num {\r\n font-family: ui-monospace, monospace;\r\n font-size: 11px;\r\n color: var(--horeg-text-muted);\r\n width: 18px;\r\n }\r\n\r\n .horeg-track-details {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .horeg-item-title {\r\n font-weight: 600;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .horeg-item-artist {\r\n font-size: 11px;\r\n color: var(--horeg-text-muted);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .horeg-item-duration {\r\n font-family: ui-monospace, monospace;\r\n font-size: 11px;\r\n color: var(--horeg-text-muted);\r\n margin-right: 4px;\r\n }\r\n\r\n /* Track Item Actions (Remove button) */\r\n .horeg-track-actions {\r\n display: flex;\r\n align-items: center;\r\n opacity: 0.5;\r\n transition: opacity 0.15s ease;\r\n }\r\n\r\n .horeg-track-item:hover .horeg-track-actions {\r\n opacity: 1;\r\n }\r\n\r\n .horeg-btn-remove {\r\n background: transparent;\r\n border: none;\r\n color: var(--horeg-text-muted);\r\n cursor: pointer;\r\n padding: 4px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: all 0.15s ease;\r\n }\r\n\r\n .horeg-btn-remove:hover {\r\n color: #ef4444;\r\n background: rgba(239, 68, 68, 0.15);\r\n }\r\n\r\n .horeg-empty-playlist {\r\n padding: 24px 12px;\r\n text-align: center;\r\n color: var(--horeg-text-muted);\r\n font-size: 12px;\r\n font-style: italic;\r\n }\r\n `;\r\n}\r\n\r\n","/**\n * Formats a time in seconds to mm:ss or hh:mm:ss string.\n * @param seconds Time in seconds\n * @returns Formatted time string\n */\nexport function formatTime(seconds: number): string {\n if (isNaN(seconds) || !isFinite(seconds) || seconds < 0) {\n return '00:00';\n }\n\n const roundedSeconds = Math.floor(seconds);\n const hours = Math.floor(roundedSeconds / 3600);\n const minutes = Math.floor((roundedSeconds % 3600) / 60);\n const remainingSeconds = roundedSeconds % 60;\n\n const pad = (num: number) => num.toString().padStart(2, '0');\n\n if (hours > 0) {\n return `${hours}:${pad(minutes)}:${pad(remainingSeconds)}`;\n }\n\n return `${pad(minutes)}:${pad(remainingSeconds)}`;\n}\n\n/**\n * Clamps a number between a minimum and maximum value.\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n","import { Track, LoopMode, HoregPlayerOptions } from './types';\r\nimport { clamp } from './utils/time';\r\n\r\nexport interface AudioEngineCallbacks {\r\n onPlay?: (track: Track) => void;\r\n onPause?: () => void;\r\n onTrackChange?: (track: Track, index: number) => void;\r\n onPlaylistChange?: (playlist: Track[], currentIndex: number) => void;\r\n onTimeUpdate?: (currentTime: number, duration: number) => void;\r\n onBufferUpdate?: (bufferedPercent: number) => void;\r\n onEnded?: (track: Track) => void;\r\n onError?: (error: MediaError | Error) => void;\r\n onLoadingChange?: (isLoading: boolean) => void;\r\n}\r\n\r\nexport class AudioEngine {\r\n private audio: HTMLAudioElement;\r\n private playlist: Track[] = [];\r\n private currentIndex: number = 0;\r\n private loopMode: LoopMode = 'all';\r\n private shuffleMode: boolean = false;\r\n private volumeLevel: number = 0.8;\r\n private previousVolume: number = 0.8;\r\n private callbacks: AudioEngineCallbacks = {};\r\n\r\n constructor(options: HoregPlayerOptions, callbacks: AudioEngineCallbacks = {}) {\r\n this.audio = new Audio();\r\n this.playlist = [...(options.playlist || [])];\r\n this.currentIndex = options.initialIndex !== undefined ? clamp(options.initialIndex, 0, Math.max(0, this.playlist.length - 1)) : 0;\r\n this.loopMode = options.loop || 'all';\r\n this.shuffleMode = !!options.shuffle;\r\n this.volumeLevel = options.volume !== undefined ? clamp(options.volume, 0, 1) : 0.8;\r\n this.callbacks = callbacks || {\r\n onPlay: options.onPlay,\r\n onPause: options.onPause,\r\n onTrackChange: options.onTrackChange,\r\n onPlaylistChange: options.onPlaylistChange,\r\n onTimeUpdate: options.onTimeUpdate,\r\n onEnded: options.onEnded,\r\n onError: options.onError\r\n };\r\n\r\n this.audio.volume = this.volumeLevel;\r\n this.attachEvents();\r\n\r\n if (this.playlist.length > 0) {\r\n this.loadTrack(this.currentIndex, !!options.autoplay);\r\n }\r\n }\r\n\r\n private attachEvents(): void {\r\n this.audio.addEventListener('play', this.handlePlay);\r\n this.audio.addEventListener('pause', this.handlePause);\r\n this.audio.addEventListener('timeupdate', this.handleTimeUpdate);\r\n this.audio.addEventListener('progress', this.handleProgress);\r\n this.audio.addEventListener('ended', this.handleEnded);\r\n this.audio.addEventListener('error', this.handleError);\r\n this.audio.addEventListener('waiting', this.handleWaiting);\r\n this.audio.addEventListener('playing', this.handlePlaying);\r\n this.audio.addEventListener('loadedmetadata', this.handleLoadedMetadata);\r\n }\r\n\r\n private detachEvents(): void {\r\n this.audio.removeEventListener('play', this.handlePlay);\r\n this.audio.removeEventListener('pause', this.handlePause);\r\n this.audio.removeEventListener('timeupdate', this.handleTimeUpdate);\r\n this.audio.removeEventListener('progress', this.handleProgress);\r\n this.audio.removeEventListener('ended', this.handleEnded);\r\n this.audio.removeEventListener('error', this.handleError);\r\n this.audio.removeEventListener('waiting', this.handleWaiting);\r\n this.audio.removeEventListener('playing', this.handlePlaying);\r\n this.audio.removeEventListener('loadedmetadata', this.handleLoadedMetadata);\r\n }\r\n\r\n private handlePlay = (): void => {\r\n const current = this.getCurrentTrack();\r\n if (current && this.callbacks.onPlay) {\r\n this.callbacks.onPlay(current);\r\n }\r\n };\r\n\r\n private handlePause = (): void => {\r\n if (this.callbacks.onPause) {\r\n this.callbacks.onPause();\r\n }\r\n };\r\n\r\n private handleTimeUpdate = (): void => {\r\n const current = this.audio.currentTime || 0;\r\n const duration = this.getDuration();\r\n if (this.callbacks.onTimeUpdate) {\r\n this.callbacks.onTimeUpdate(current, duration);\r\n }\r\n };\r\n\r\n private handleProgress = (): void => {\r\n if (this.audio.buffered.length > 0 && this.audio.duration > 0) {\r\n const bufferedEnd = this.audio.buffered.end(this.audio.buffered.length - 1);\r\n const percent = clamp((bufferedEnd / this.audio.duration) * 100, 0, 100);\r\n if (this.callbacks.onBufferUpdate) {\r\n this.callbacks.onBufferUpdate(percent);\r\n }\r\n }\r\n };\r\n\r\n private handleLoadedMetadata = (): void => {\r\n const current = this.audio.currentTime || 0;\r\n const duration = this.getDuration();\r\n if (this.callbacks.onTimeUpdate) {\r\n this.callbacks.onTimeUpdate(current, duration);\r\n }\r\n this.handleProgress();\r\n };\r\n\r\n private handleWaiting = (): void => {\r\n if (this.callbacks.onLoadingChange) {\r\n this.callbacks.onLoadingChange(true);\r\n }\r\n };\r\n\r\n private handlePlaying = (): void => {\r\n if (this.callbacks.onLoadingChange) {\r\n this.callbacks.onLoadingChange(false);\r\n }\r\n };\r\n\r\n private handleEnded = (): void => {\r\n const current = this.getCurrentTrack();\r\n if (current && this.callbacks.onEnded) {\r\n this.callbacks.onEnded(current);\r\n }\r\n\r\n if (this.loopMode === 'one') {\r\n this.audio.currentTime = 0;\r\n this.play();\r\n } else {\r\n this.next(true);\r\n }\r\n };\r\n\r\n private handleError = (): void => {\r\n const err = this.audio.error || new Error('Unknown audio playback error');\r\n if (this.callbacks.onError) {\r\n this.callbacks.onError(err);\r\n }\r\n };\r\n\r\n public getCurrentTrack(): Track | undefined {\r\n return this.playlist[this.currentIndex];\r\n }\r\n\r\n public getCurrentIndex(): number {\r\n return this.currentIndex;\r\n }\r\n\r\n public getPlaylist(): Track[] {\r\n return this.playlist;\r\n }\r\n\r\n public setPlaylist(newPlaylist: Track[], startIndex: number = 0): void {\r\n this.playlist = [...newPlaylist];\r\n this.currentIndex = clamp(startIndex, 0, Math.max(0, this.playlist.length - 1));\r\n this.loadTrack(this.currentIndex, false);\r\n if (this.callbacks.onPlaylistChange) {\r\n this.callbacks.onPlaylistChange([...this.playlist], this.currentIndex);\r\n }\r\n if (this.playlist.length > 0) {\r\n this.loadTrack(this.currentIndex, false);\r\n } else {\r\n this.audio.pause();\r\n this.audio.src = '';\r\n if (this.callbacks.onTrackChange) {\r\n this.callbacks.onTrackChange({ title: 'No Track Loaded', src: '' }, 0);\r\n }\r\n }\r\n }\r\n\r\n public addTrack(track: Track, autoPlay: boolean = false): number {\r\n const wasEmpty = this.playlist.length === 0;\r\n this.playlist.push(track);\r\n const newIndex = this.playlist.length - 1;\r\n\r\n if (this.callbacks.onPlaylistChange) {\r\n this.callbacks.onPlaylistChange([...this.playlist], this.currentIndex);\r\n }\r\n\r\n if (wasEmpty) {\r\n this.loadTrack(0, autoPlay);\r\n } else if (autoPlay) {\r\n this.loadTrack(newIndex, true);\r\n }\r\n\r\n return newIndex;\r\n }\r\n\r\n public addTracks(tracks: Track[], autoPlay: boolean = false): void {\r\n if (!tracks || tracks.length === 0) return;\r\n const wasEmpty = this.playlist.length === 0;\r\n const firstAddedIndex = this.playlist.length;\r\n this.playlist.push(...tracks);\r\n\r\n if (this.callbacks.onPlaylistChange) {\r\n this.callbacks.onPlaylistChange([...this.playlist], this.currentIndex);\r\n }\r\n\r\n if (wasEmpty) {\r\n this.loadTrack(0, autoPlay);\r\n } else if (autoPlay) {\r\n this.loadTrack(firstAddedIndex, true);\r\n }\r\n }\r\n\r\n public removeTrack(index: number): void {\r\n if (index < 0 || index >= this.playlist.length) return;\r\n const isCurrentTrack = index === this.currentIndex;\r\n this.playlist.splice(index, 1);\r\n\r\n if (this.playlist.length === 0) {\r\n this.currentIndex = 0;\r\n this.audio.pause();\r\n this.audio.src = '';\r\n if (this.callbacks.onTrackChange) {\r\n this.callbacks.onTrackChange({ title: 'No Track Loaded', src: '' }, 0);\r\n }\r\n } else if (isCurrentTrack) {\r\n const nextIndex = clamp(index, 0, this.playlist.length - 1);\r\n this.loadTrack(nextIndex, false);\r\n } else if (index < this.currentIndex) {\r\n this.currentIndex--;\r\n }\r\n\r\n if (this.callbacks.onPlaylistChange) {\r\n this.callbacks.onPlaylistChange([...this.playlist], this.currentIndex);\r\n }\r\n }\r\n\r\n public getDuration(): number {\r\n const dur = this.audio.duration;\r\n if (dur && !isNaN(dur) && isFinite(dur)) {\r\n return dur;\r\n }\r\n const currentTrack = this.getCurrentTrack();\r\n return currentTrack?.duration || 0;\r\n }\r\n\r\n public getCurrentTime(): number {\r\n return this.audio.currentTime || 0;\r\n }\r\n\r\n public isPlaying(): boolean {\r\n return !this.audio.paused && !this.audio.ended;\r\n }\r\n\r\n public isMuted(): boolean {\r\n return this.audio.muted || this.audio.volume === 0;\r\n }\r\n\r\n public getVolume(): number {\r\n return this.audio.volume;\r\n }\r\n\r\n public getLoop(): LoopMode {\r\n return this.loopMode;\r\n }\r\n\r\n public isShuffle(): boolean {\r\n return this.shuffleMode;\r\n }\r\n\r\n public loadTrack(indexOrTrack: number | Track, autoPlay: boolean = false): void {\r\n let targetIndex: number;\r\n\r\n if (typeof indexOrTrack === 'number') {\r\n targetIndex = clamp(indexOrTrack, 0, Math.max(0, this.playlist.length - 1));\r\n } else {\r\n targetIndex = this.playlist.findIndex((t) => t.src === indexOrTrack.src);\r\n if (targetIndex === -1) {\r\n this.playlist.push(indexOrTrack);\r\n targetIndex = this.playlist.length - 1;\r\n }\r\n }\r\n\r\n this.currentIndex = targetIndex;\r\n const track = this.playlist[this.currentIndex];\r\n\r\n if (!track) return;\r\n\r\n this.audio.src = track.src;\r\n\r\n if (this.callbacks.onTrackChange) {\r\n this.callbacks.onTrackChange(track, this.currentIndex);\r\n }\r\n\r\n if (autoPlay) {\r\n this.play();\r\n }\r\n }\r\n\r\n public async play(): Promise<void> {\r\n try {\r\n await this.audio.play();\r\n } catch (err) {\r\n // Modern browser autoplay policy rejection handling\r\n // Prevents unhandled promise rejection error in developer console\r\n console.warn('[HoregAudio] Autoplay / Audio play was prevented by browser policy:', err);\r\n }\r\n }\r\n\r\n public pause(): void {\r\n this.audio.pause();\r\n }\r\n\r\n public toggle(): void {\r\n if (this.audio.paused) {\r\n this.play();\r\n } else {\r\n this.pause();\r\n }\r\n }\r\n\r\n public seek(seconds: number): void {\r\n const duration = this.getDuration();\r\n const clampedTime = clamp(seconds, 0, duration > 0 ? duration : Infinity);\r\n this.audio.currentTime = clampedTime;\r\n }\r\n\r\n public setVolume(level: number): void {\r\n const clamped = clamp(level, 0, 1);\r\n this.volumeLevel = clamped;\r\n this.audio.volume = clamped;\r\n if (clamped > 0) {\r\n this.audio.muted = false;\r\n this.previousVolume = clamped;\r\n }\r\n }\r\n\r\n public toggleMute(): boolean {\r\n if (this.isMuted()) {\r\n this.audio.muted = false;\r\n this.setVolume(this.previousVolume > 0 ? this.previousVolume : 0.5);\r\n return false;\r\n } else {\r\n this.previousVolume = this.audio.volume;\r\n this.audio.muted = true;\r\n return true;\r\n }\r\n }\r\n\r\n public next(isFromEnded: boolean = false): void {\r\n if (this.playlist.length === 0) return;\r\n\r\n if (this.shuffleMode && this.playlist.length > 1) {\r\n let randomIndex: number;\r\n do {\r\n randomIndex = Math.floor(Math.random() * this.playlist.length);\r\n } while (randomIndex === this.currentIndex);\r\n this.loadTrack(randomIndex, true);\r\n return;\r\n }\r\n\r\n const nextIndex = this.currentIndex + 1;\r\n if (nextIndex < this.playlist.length) {\r\n this.loadTrack(nextIndex, true);\r\n } else if (this.loopMode === 'all') {\r\n this.loadTrack(0, true);\r\n } else if (!isFromEnded) {\r\n this.loadTrack(0, true);\r\n } else {\r\n this.pause();\r\n }\r\n }\r\n\r\n public prev(): void {\r\n if (this.playlist.length === 0) return;\r\n\r\n // If more than 2 seconds in, restart track\r\n if (this.audio.currentTime > 2) {\r\n this.seek(0);\r\n return;\r\n }\r\n\r\n if (this.shuffleMode && this.playlist.length > 1) {\r\n let randomIndex: number;\r\n do {\r\n randomIndex = Math.floor(Math.random() * this.playlist.length);\r\n } while (randomIndex === this.currentIndex);\r\n this.loadTrack(randomIndex, true);\r\n return;\r\n }\r\n\r\n const prevIndex = this.currentIndex - 1;\r\n if (prevIndex >= 0) {\r\n this.loadTrack(prevIndex, true);\r\n } else if (this.loopMode === 'all') {\r\n this.loadTrack(this.playlist.length - 1, true);\r\n } else {\r\n this.seek(0);\r\n }\r\n }\r\n\r\n public setLoop(mode: LoopMode): void {\r\n this.loopMode = mode;\r\n }\r\n\r\n public setShuffle(shuffle: boolean): void {\r\n this.shuffleMode = shuffle;\r\n }\r\n\r\n public setCallbacks(callbacks: AudioEngineCallbacks): void {\r\n this.callbacks = { ...this.callbacks, ...callbacks };\r\n }\r\n\r\n public destroy(): void {\r\n this.detachEvents();\r\n this.audio.pause();\r\n this.audio.src = '';\r\n this.audio.load();\r\n }\r\n}\r\n\r\n","export const ICONS = {\r\n play: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"20\" height=\"20\"><path d=\"M8 5v14l11-7z\"/></svg>`,\r\n pause: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"20\" height=\"20\"><path d=\"M6 19h4V5H6v14zm8-14v14h4V5h-4z\"/></svg>`,\r\n prev: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"18\" height=\"18\"><path d=\"M6 6h2v12H6zm3.5 6l8.5 6V6z\"/></svg>`,\r\n next: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"18\" height=\"18\"><path d=\"M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z\"/></svg>`,\r\n volumeHigh: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"18\" height=\"18\"><path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>`,\r\n volumeMute: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"18\" height=\"18\"><path d=\"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27l4.73 4.73H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z\"/></svg>`,\r\n shuffle: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"16\" height=\"16\"><path d=\"M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z\"/></svg>`,\r\n repeat: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"16\" height=\"16\"><path d=\"M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z\"/></svg>`,\r\n repeatOne: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"16\" height=\"16\"><path d=\"M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4zm-4-2V9h-1l-2 1v1h1.5v4H13z\"/></svg>`,\r\n playlist: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"18\" height=\"18\"><path d=\"M3 10h11v2H3zm0-4h11v2H3zm0 8h7v2H3zm13-1v8l6-4-6-4z\"/></svg>`,\r\n speaker: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"14\" height=\"14\"><path d=\"M17 2H7c-1.1 0-2 .9-2 2v16c0 1.1.9 1.99 2 1.99L17 22c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm0 16c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z\"/></svg>`,\r\n plus: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"14\" height=\"14\"><path d=\"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"/></svg>`,\r\n trash: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"14\" height=\"14\"><path d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\"/></svg>`,\r\n upload: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"14\" height=\"14\"><path d=\"M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z\"/></svg>`,\r\n link: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"14\" height=\"14\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/></svg>`,\r\n close: `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"14\" height=\"14\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/></svg>`\r\n};\r\n\r\n/**\r\n * Creates an element with optional class names and attributes.\r\n */\r\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\r\n tagName: K,\r\n options?: {\r\n className?: string;\r\n attributes?: Record<string, string>;\r\n innerHTML?: string;\r\n textContent?: string;\r\n }\r\n): HTMLElementTagNameMap[K] {\r\n const el = document.createElement(tagName);\r\n if (options?.className) {\r\n el.className = options.className;\r\n }\r\n if (options?.attributes) {\r\n for (const [key, val] of Object.entries(options.attributes)) {\r\n el.setAttribute(key, val);\r\n }\r\n }\r\n if (options?.innerHTML) {\r\n el.innerHTML = options.innerHTML;\r\n } else if (options?.textContent) {\r\n el.textContent = options.textContent;\r\n }\r\n return el;\r\n}\r\n\r\n","import { Track, LoopMode } from './types';\r\nimport { formatTime, clamp } from './utils/time';\r\nimport { ICONS, createElement } from './utils/dom';\r\n\r\nexport interface UIEvents {\r\n onPlayPauseClick: () => void;\r\n onPrevClick: () => void;\r\n onNextClick: () => void;\r\n onSeek: (seconds: number) => void;\r\n onVolumeChange: (volume: number) => void;\r\n onMuteToggle: () => void;\r\n onShuffleToggle: () => void;\r\n onLoopToggle: () => void;\r\n onTrackSelect: (index: number) => void;\r\n onAddTrackFiles?: (files: File[]) => void;\r\n onAddTrackUrl?: (url: string, title?: string, artist?: string) => void;\r\n onRemoveTrack?: (index: number) => void;\r\n}\r\n\r\nexport class UI {\r\n public root: HTMLElement;\r\n public eqContainer: HTMLElement;\r\n\r\n private playBtn: HTMLButtonElement;\r\n private prevBtn: HTMLButtonElement;\r\n private nextBtn: HTMLButtonElement;\r\n private shuffleBtn: HTMLButtonElement;\r\n private loopBtn: HTMLButtonElement;\r\n private muteBtn: HTMLButtonElement;\r\n private drawerBtn: HTMLButtonElement;\r\n\r\n private titleEl: HTMLElement;\r\n private artistEl: HTMLElement;\r\n private albumEl: HTMLElement;\r\n private coverImgEl: HTMLImageElement | null = null;\r\n private coverContainer: HTMLElement;\r\n\r\n private currentTimeEl: HTMLElement;\r\n private durationEl: HTMLElement;\r\n private sliderTrack: HTMLElement;\r\n private fillBar: HTMLElement;\r\n private bufferBar: HTMLElement;\r\n\r\n private volumeSlider: HTMLInputElement;\r\n private drawerEl: HTMLElement;\r\n private drawerCountEl: HTMLElement;\r\n private addTrackBtn: HTMLButtonElement;\r\n private addPanelEl: HTMLElement;\r\n private fileInputEl: HTMLInputElement;\r\n private tabBtnFile: HTMLButtonElement;\r\n private tabBtnUrl: HTMLButtonElement;\r\n private tabPaneFile: HTMLElement;\r\n private tabPaneUrl: HTMLElement;\r\n private urlInput: HTMLInputElement;\r\n private titleInput: HTMLInputElement;\r\n private artistInput: HTMLInputElement;\r\n private submitUrlBtn: HTMLButtonElement;\r\n private cancelAddBtn: HTMLButtonElement;\r\n private dropzoneEl: HTMLElement;\r\n private drawerInner: HTMLElement;\r\n\r\n private isScrubbing: boolean = false;\r\n private currentDuration: number = 0;\r\n private events: UIEvents;\r\n\r\n constructor(events: UIEvents) {\r\n this.events = events;\r\n\r\n // Create main player container\r\n this.root = createElement('div', { className: 'horeg-player-box' });\r\n\r\n // Speaker grill overlay\r\n const grill = createElement('div', { className: 'horeg-speaker-grill' });\r\n this.root.appendChild(grill);\r\n\r\n // Rigging bolts\r\n ['top-left', 'top-right', 'bottom-left', 'bottom-right'].forEach((pos) => {\r\n this.root.appendChild(createElement('div', { className: `horeg-bolt ${pos}` }));\r\n });\r\n\r\n // Content wrapper\r\n const contentWrap = createElement('div', { className: 'horeg-content-wrap' });\r\n this.root.appendChild(contentWrap);\r\n\r\n // 1. Rig Header\r\n const header = createElement('div', { className: 'horeg-header' });\r\n const badge = createElement('div', {\r\n className: 'horeg-rig-badge',\r\n innerHTML: `<span class=\"horeg-badge-led\"></span> HOREG RIG • HIGH VOLTAGE`\r\n });\r\n header.appendChild(badge);\r\n contentWrap.appendChild(header);\r\n\r\n // 2. Track row (Cover art, metadata, visualizer)\r\n const trackRow = createElement('div', { className: 'horeg-track-row' });\r\n this.coverContainer = createElement('div', { className: 'horeg-cover-container' });\r\n this.coverContainer.innerHTML = `<span class=\"horeg-cover-fallback\">${ICONS.speaker}</span>`;\r\n trackRow.appendChild(this.coverContainer);\r\n\r\n const trackInfo = createElement('div', { className: 'horeg-track-info' });\r\n this.titleEl = createElement('div', { className: 'horeg-track-title', textContent: 'No Track Loaded' });\r\n this.artistEl = createElement('div', { className: 'horeg-track-artist', textContent: 'Unknown Artist' });\r\n this.albumEl = createElement('div', { className: 'horeg-track-album', textContent: '' });\r\n trackInfo.appendChild(this.titleEl);\r\n trackInfo.appendChild(this.artistEl);\r\n trackInfo.appendChild(this.albumEl);\r\n trackRow.appendChild(trackInfo);\r\n\r\n this.eqContainer = createElement('div', { className: 'horeg-eq-wrapper' });\r\n trackRow.appendChild(this.eqContainer);\r\n contentWrap.appendChild(trackRow);\r\n\r\n // 3. Progress / Scrubber Row\r\n const progressContainer = createElement('div', { className: 'horeg-progress-container' });\r\n const timeRow = createElement('div', { className: 'horeg-time-row' });\r\n this.currentTimeEl = createElement('span', { textContent: '00:00' });\r\n this.durationEl = createElement('span', { textContent: '00:00' });\r\n timeRow.appendChild(this.currentTimeEl);\r\n timeRow.appendChild(this.durationEl);\r\n progressContainer.appendChild(timeRow);\r\n\r\n this.sliderTrack = createElement('div', {\r\n className: 'horeg-slider-track',\r\n attributes: {\r\n role: 'slider',\r\n 'aria-label': 'Seek progress',\r\n 'aria-valuemin': '0',\r\n 'aria-valuemax': '100',\r\n 'aria-valuenow': '0',\r\n tabindex: '0'\r\n }\r\n });\r\n this.bufferBar = createElement('div', { className: 'horeg-buffer-bar' });\r\n this.fillBar = createElement('div', { className: 'horeg-fill-bar' });\r\n this.sliderTrack.appendChild(this.bufferBar);\r\n this.sliderTrack.appendChild(this.fillBar);\r\n progressContainer.appendChild(this.sliderTrack);\r\n contentWrap.appendChild(progressContainer);\r\n\r\n // 4. Controls Row\r\n const controlsRow = createElement('div', { className: 'horeg-controls-row' });\r\n\r\n // Side left: Shuffle & Repeat\r\n const leftControls = createElement('div', { className: 'horeg-side-controls' });\r\n this.shuffleBtn = createElement('button', {\r\n className: 'horeg-btn',\r\n attributes: { 'aria-label': 'Toggle shuffle', type: 'button' },\r\n innerHTML: ICONS.shuffle\r\n });\r\n this.loopBtn = createElement('button', {\r\n className: 'horeg-btn active',\r\n attributes: { 'aria-label': 'Toggle loop mode', type: 'button' },\r\n innerHTML: ICONS.repeat\r\n });\r\n leftControls.appendChild(this.shuffleBtn);\r\n leftControls.appendChild(this.loopBtn);\r\n controlsRow.appendChild(leftControls);\r\n\r\n // Center: Prev, Play, Next\r\n const centerControls = createElement('div', { className: 'horeg-center-controls' });\r\n this.prevBtn = createElement('button', {\r\n className: 'horeg-btn',\r\n attributes: { 'aria-label': 'Previous track', type: 'button' },\r\n innerHTML: ICONS.prev\r\n });\r\n this.playBtn = createElement('button', {\r\n className: 'horeg-btn horeg-btn-play',\r\n attributes: { 'aria-label': 'Play track', type: 'button' },\r\n innerHTML: ICONS.play\r\n });\r\n this.nextBtn = createElement('button', {\r\n className: 'horeg-btn',\r\n attributes: { 'aria-label': 'Next track', type: 'button' },\r\n innerHTML: ICONS.next\r\n });\r\n centerControls.appendChild(this.prevBtn);\r\n centerControls.appendChild(this.playBtn);\r\n centerControls.appendChild(this.nextBtn);\r\n controlsRow.appendChild(centerControls);\r\n\r\n // Side right: Volume & Drawer toggle\r\n const rightControls = createElement('div', { className: 'horeg-side-controls' });\r\n const volumeWrap = createElement('div', { className: 'horeg-volume-wrap' });\r\n this.muteBtn = createElement('button', {\r\n className: 'horeg-btn',\r\n attributes: { 'aria-label': 'Toggle mute', type: 'button' },\r\n innerHTML: ICONS.volumeHigh\r\n });\r\n this.volumeSlider = createElement('input', {\r\n className: 'horeg-volume-slider',\r\n attributes: {\r\n type: 'range',\r\n min: '0',\r\n max: '1',\r\n step: '0.01',\r\n value: '0.8',\r\n 'aria-label': 'Volume control'\r\n }\r\n });\r\n volumeWrap.appendChild(this.muteBtn);\r\n volumeWrap.appendChild(this.volumeSlider);\r\n rightControls.appendChild(volumeWrap);\r\n\r\n this.drawerBtn = createElement('button', {\r\n className: 'horeg-btn',\r\n attributes: { 'aria-label': 'Toggle playlist drawer', type: 'button' },\r\n innerHTML: ICONS.playlist\r\n });\r\n rightControls.appendChild(this.drawerBtn);\r\n controlsRow.appendChild(rightControls);\r\n\r\n contentWrap.appendChild(controlsRow);\r\n\r\n // 5. Drawer panel\r\n this.drawerEl = createElement('div', { className: 'horeg-drawer' });\r\n\r\n // Drawer Header with count & Add Track button\r\n const drawerHeader = createElement('div', { className: 'horeg-drawer-header' });\r\n const drawerHeading = createElement('div', { className: 'horeg-drawer-heading' });\r\n drawerHeading.innerHTML = `<span>PLAYLIST</span>`;\r\n this.drawerCountEl = createElement('span', { className: 'horeg-drawer-count', textContent: '0' });\r\n drawerHeading.appendChild(this.drawerCountEl);\r\n drawerHeader.appendChild(drawerHeading);\r\n\r\n this.addTrackBtn = createElement('button', {\r\n className: 'horeg-btn-add-track',\r\n attributes: { type: 'button', 'aria-label': 'Add track to playlist' },\r\n innerHTML: `${ICONS.plus} <span>Add Track</span>`\r\n });\r\n drawerHeader.appendChild(this.addTrackBtn);\r\n this.drawerEl.appendChild(drawerHeader);\r\n\r\n // Add Track Accordion Panel\r\n this.addPanelEl = createElement('div', { className: 'horeg-add-panel' });\r\n\r\n // Tabs\r\n const tabs = createElement('div', { className: 'horeg-add-tabs' });\r\n this.tabBtnFile = createElement('button', {\r\n className: 'horeg-tab-btn active',\r\n attributes: { type: 'button' },\r\n innerHTML: `${ICONS.upload} <span>File Lokal</span>`\r\n });\r\n this.tabBtnUrl = createElement('button', {\r\n className: 'horeg-tab-btn',\r\n attributes: { type: 'button' },\r\n innerHTML: `${ICONS.link} <span>Audio URL</span>`\r\n });\r\n tabs.appendChild(this.tabBtnFile);\r\n tabs.appendChild(this.tabBtnUrl);\r\n this.addPanelEl.appendChild(tabs);\r\n\r\n // Tab 1: Local File Dropzone & Hidden Input\r\n this.tabPaneFile = createElement('div', { className: 'horeg-tab-pane active' });\r\n this.fileInputEl = createElement('input', {\r\n attributes: { type: 'file', accept: 'audio/*', multiple: 'true', style: 'display: none;' }\r\n });\r\n this.dropzoneEl = createElement('div', { className: 'horeg-dropzone' });\r\n this.dropzoneEl.innerHTML = `\r\n <div class=\"horeg-dropzone-icon\">${ICONS.upload}</div>\r\n <div class=\"horeg-dropzone-text\">Pilih File Audio Komputer</div>\r\n <div class=\"horeg-dropzone-hint\">Klik di sini atau drag & drop file (.mp3, .wav, .flac, .ogg, .m4a)</div>\r\n `;\r\n this.tabPaneFile.appendChild(this.fileInputEl);\r\n this.tabPaneFile.appendChild(this.dropzoneEl);\r\n this.addPanelEl.appendChild(this.tabPaneFile);\r\n\r\n // Tab 2: URL Form\r\n this.tabPaneUrl = createElement('div', { className: 'horeg-tab-pane' });\r\n this.urlInput = createElement('input', {\r\n className: 'horeg-input-field',\r\n attributes: { type: 'url', placeholder: 'Audio URL (https://...mp3/wav)', required: 'true' }\r\n });\r\n this.titleInput = createElement('input', {\r\n className: 'horeg-input-field',\r\n attributes: { type: 'text', placeholder: 'Judul Lagu (Opsional)' }\r\n });\r\n this.artistInput = createElement('input', {\r\n className: 'horeg-input-field',\r\n attributes: { type: 'text', placeholder: 'Nama Artis (Opsional)' }\r\n });\r\n const formActions = createElement('div', { className: 'horeg-form-actions' });\r\n this.cancelAddBtn = createElement('button', {\r\n className: 'horeg-btn-cancel',\r\n attributes: { type: 'button' },\r\n textContent: 'Batal'\r\n });\r\n this.submitUrlBtn = createElement('button', {\r\n className: 'horeg-btn-submit',\r\n attributes: { type: 'button' },\r\n innerHTML: `${ICONS.plus} Tambah`\r\n });\r\n formActions.appendChild(this.cancelAddBtn);\r\n formActions.appendChild(this.submitUrlBtn);\r\n\r\n this.tabPaneUrl.appendChild(this.urlInput);\r\n this.tabPaneUrl.appendChild(this.titleInput);\r\n this.tabPaneUrl.appendChild(this.artistInput);\r\n this.tabPaneUrl.appendChild(formActions);\r\n this.addPanelEl.appendChild(this.tabPaneUrl);\r\n\r\n this.drawerEl.appendChild(this.addPanelEl);\r\n\r\n // Track list container\r\n this.drawerInner = createElement('div', { className: 'horeg-drawer-inner' });\r\n this.drawerEl.appendChild(this.drawerInner);\r\n this.root.appendChild(this.drawerEl);\r\n\r\n this.bindDOMEvents();\r\n }\r\n\r\n private bindDOMEvents(): void {\r\n this.playBtn.addEventListener('click', () => this.events.onPlayPauseClick());\r\n this.prevBtn.addEventListener('click', () => this.events.onPrevClick());\r\n this.nextBtn.addEventListener('click', () => this.events.onNextClick());\r\n this.shuffleBtn.addEventListener('click', () => this.events.onShuffleToggle());\r\n this.loopBtn.addEventListener('click', () => this.events.onLoopToggle());\r\n this.muteBtn.addEventListener('click', () => this.events.onMuteToggle());\r\n\r\n this.volumeSlider.addEventListener('input', () => {\r\n this.events.onVolumeChange(parseFloat(this.volumeSlider.value));\r\n });\r\n\r\n this.drawerBtn.addEventListener('click', () => {\r\n this.toggleDrawer();\r\n });\r\n\r\n // Toggle Add Track Form\r\n this.addTrackBtn.addEventListener('click', () => {\r\n const isOpen = this.addPanelEl.classList.toggle('open');\r\n this.addTrackBtn.classList.toggle('active', isOpen);\r\n if (isOpen) {\r\n this.toggleDrawer(true);\r\n }\r\n });\r\n\r\n // Tab Switchers\r\n this.tabBtnFile.addEventListener('click', () => {\r\n this.tabBtnFile.classList.add('active');\r\n this.tabBtnUrl.classList.remove('active');\r\n this.tabPaneFile.classList.add('active');\r\n this.tabPaneUrl.classList.remove('active');\r\n });\r\n\r\n this.tabBtnUrl.addEventListener('click', () => {\r\n this.tabBtnUrl.classList.add('active');\r\n this.tabBtnFile.classList.remove('active');\r\n this.tabPaneUrl.classList.add('active');\r\n this.tabPaneFile.classList.remove('active');\r\n this.urlInput.focus();\r\n });\r\n\r\n // Local file picker\r\n this.dropzoneEl.addEventListener('click', () => {\r\n this.fileInputEl.click();\r\n });\r\n\r\n this.fileInputEl.addEventListener('change', () => {\r\n if (this.fileInputEl.files && this.fileInputEl.files.length > 0) {\r\n const files = Array.from(this.fileInputEl.files);\r\n if (this.events.onAddTrackFiles) {\r\n this.events.onAddTrackFiles(files);\r\n }\r\n this.fileInputEl.value = '';\r\n this.closeAddPanel();\r\n }\r\n });\r\n\r\n // Dropzone drag-and-drop feedback\r\n this.dropzoneEl.addEventListener('dragover', (e) => {\r\n e.preventDefault();\r\n this.dropzoneEl.classList.add('drag-active');\r\n });\r\n\r\n this.dropzoneEl.addEventListener('dragleave', () => {\r\n this.dropzoneEl.classList.remove('drag-active');\r\n });\r\n\r\n this.dropzoneEl.addEventListener('drop', (e) => {\r\n e.preventDefault();\r\n this.dropzoneEl.classList.remove('drag-active');\r\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\r\n const audioFiles = Array.from(e.dataTransfer.files).filter(\r\n (f) => f.type.startsWith('audio/') || /\\.(mp3|wav|ogg|flac|m4a|aac)$/i.test(f.name)\r\n );\r\n if (audioFiles.length > 0 && this.events.onAddTrackFiles) {\r\n this.events.onAddTrackFiles(audioFiles);\r\n this.closeAddPanel();\r\n }\r\n }\r\n });\r\n\r\n // Whole player Drag & Drop listener\r\n this.root.addEventListener('dragover', (e) => {\r\n e.preventDefault();\r\n this.root.classList.add('drag-over');\r\n });\r\n\r\n this.root.addEventListener('dragleave', (e) => {\r\n if (!this.root.contains(e.relatedTarget as Node)) {\r\n this.root.classList.remove('drag-over');\r\n }\r\n });\r\n\r\n this.root.addEventListener('drop', (e) => {\r\n e.preventDefault();\r\n this.root.classList.remove('drag-over');\r\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\r\n const audioFiles = Array.from(e.dataTransfer.files).filter(\r\n (f) => f.type.startsWith('audio/') || /\\.(mp3|wav|ogg|flac|m4a|aac)$/i.test(f.name)\r\n );\r\n if (audioFiles.length > 0 && this.events.onAddTrackFiles) {\r\n this.events.onAddTrackFiles(audioFiles);\r\n this.closeAddPanel();\r\n }\r\n }\r\n });\r\n\r\n // URL Form Submission\r\n const handleUrlSubmit = () => {\r\n const url = this.urlInput.value.trim();\r\n if (!url) {\r\n this.urlInput.focus();\r\n return;\r\n }\r\n const title = this.titleInput.value.trim();\r\n const artist = this.artistInput.value.trim();\r\n if (this.events.onAddTrackUrl) {\r\n this.events.onAddTrackUrl(url, title || undefined, artist || undefined);\r\n }\r\n this.urlInput.value = '';\r\n this.titleInput.value = '';\r\n this.artistInput.value = '';\r\n this.closeAddPanel();\r\n };\r\n\r\n this.submitUrlBtn.addEventListener('click', handleUrlSubmit);\r\n const handleUrlInputKeyDown = (e: KeyboardEvent) => {\r\n // Allow space, arrows, and text navigation without triggering player shortcuts\r\n e.stopPropagation();\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleUrlSubmit();\r\n }\r\n };\r\n\r\n this.urlInput.addEventListener('keydown', handleUrlInputKeyDown);\r\n this.titleInput.addEventListener('keydown', handleUrlInputKeyDown);\r\n this.artistInput.addEventListener('keydown', handleUrlInputKeyDown);\r\n\r\n this.cancelAddBtn.addEventListener('click', () => {\r\n this.closeAddPanel();\r\n });\r\n\r\n // Scrubbing on slider track\r\n this.sliderTrack.addEventListener('mousedown', this.startScrubbing);\r\n this.sliderTrack.addEventListener('touchstart', this.startScrubbing, { passive: false });\r\n\r\n // Keyboard support on slider\r\n this.sliderTrack.addEventListener('keydown', (e: KeyboardEvent) => {\r\n if (!this.currentDuration) return;\r\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n const cur = (parseFloat(this.fillBar.style.width) / 100) * this.currentDuration;\r\n this.events.onSeek(Math.min(cur + 5, this.currentDuration));\r\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n const cur = (parseFloat(this.fillBar.style.width) / 100) * this.currentDuration;\r\n this.events.onSeek(Math.max(cur - 5, 0));\r\n }\r\n });\r\n }\r\n\r\n private startScrubbing = (e: MouseEvent | TouchEvent): void => {\r\n e.preventDefault();\r\n this.isScrubbing = true;\r\n this.handleScrubbingMove(e);\r\n\r\n const onMove = (moveEvent: MouseEvent | TouchEvent) => {\r\n if (this.isScrubbing) {\r\n this.handleScrubbingMove(moveEvent);\r\n }\r\n };\r\n\r\n const onUp = (upEvent: MouseEvent | TouchEvent) => {\r\n if (this.isScrubbing) {\r\n this.isScrubbing = false;\r\n this.finishScrubbing(upEvent);\r\n window.removeEventListener('mousemove', onMove);\r\n window.removeEventListener('mouseup', onUp);\r\n window.removeEventListener('touchmove', onMove);\r\n window.removeEventListener('touchend', onUp);\r\n }\r\n };\r\n\r\n window.addEventListener('mousemove', onMove);\r\n window.addEventListener('mouseup', onUp);\r\n window.addEventListener('touchmove', onMove, { passive: false });\r\n window.addEventListener('touchend', onUp);\r\n };\r\n\r\n private calculateProgressPercent(e: MouseEvent | TouchEvent): number {\r\n const rect = this.sliderTrack.getBoundingClientRect();\r\n const clientX = 'touches' in e ? (e.touches[0] || e.changedTouches[0]).clientX : e.clientX;\r\n const offsetX = clamp(clientX - rect.left, 0, rect.width);\r\n return rect.width > 0 ? (offsetX / rect.width) * 100 : 0;\r\n }\r\n\r\n private handleScrubbingMove(e: MouseEvent | TouchEvent): void {\r\n const percent = this.calculateProgressPercent(e);\r\n this.fillBar.style.width = `${percent}%`;\r\n if (this.currentDuration > 0) {\r\n const seekTime = (percent / 100) * this.currentDuration;\r\n this.currentTimeEl.textContent = formatTime(seekTime);\r\n }\r\n }\r\n\r\n private finishScrubbing(e: MouseEvent | TouchEvent): void {\r\n const percent = this.calculateProgressPercent(e);\r\n if (this.currentDuration > 0) {\r\n const targetSeconds = (percent / 100) * this.currentDuration;\r\n this.events.onSeek(targetSeconds);\r\n }\r\n }\r\n\r\n public updateTrackInfo(track: Track): void {\r\n this.titleEl.textContent = track.title || 'Untitled Track';\r\n this.artistEl.textContent = track.artist || 'Unknown Artist';\r\n this.albumEl.textContent = track.album || '';\r\n\r\n if (track.coverArt) {\r\n this.coverContainer.innerHTML = '';\r\n this.coverImgEl = createElement('img', {\r\n className: 'horeg-cover-img',\r\n attributes: {\r\n src: track.coverArt,\r\n alt: `${track.title} cover`\r\n }\r\n });\r\n this.coverImgEl.onerror = () => {\r\n this.coverContainer.innerHTML = `<span class=\"horeg-cover-fallback\">${ICONS.speaker}</span>`;\r\n };\r\n this.coverContainer.appendChild(this.coverImgEl);\r\n } else {\r\n this.coverContainer.innerHTML = `<span class=\"horeg-cover-fallback\">${ICONS.speaker}</span>`;\r\n }\r\n }\r\n\r\n public updatePlayState(isPlaying: boolean): void {\r\n if (isPlaying) {\r\n this.playBtn.classList.add('playing');\r\n this.playBtn.innerHTML = ICONS.pause;\r\n this.playBtn.setAttribute('aria-label', 'Pause track');\r\n } else {\r\n this.playBtn.classList.remove('playing');\r\n this.playBtn.innerHTML = ICONS.play;\r\n this.playBtn.setAttribute('aria-label', 'Play track');\r\n }\r\n }\r\n\r\n public updateProgress(currentTime: number, duration: number): void {\r\n this.currentDuration = duration;\r\n this.durationEl.textContent = formatTime(duration);\r\n\r\n if (!this.isScrubbing) {\r\n this.currentTimeEl.textContent = formatTime(currentTime);\r\n const percent = duration > 0 ? (currentTime / duration) * 100 : 0;\r\n this.fillBar.style.width = `${clamp(percent, 0, 100)}%`;\r\n this.sliderTrack.setAttribute('aria-valuenow', Math.round(percent).toString());\r\n }\r\n }\r\n\r\n public updateBuffer(percent: number): void {\r\n this.bufferBar.style.width = `${clamp(percent, 0, 100)}%`;\r\n }\r\n\r\n public updateVolume(volume: number, isMuted: boolean): void {\r\n this.volumeSlider.value = volume.toString();\r\n if (isMuted || volume === 0) {\r\n this.muteBtn.innerHTML = ICONS.volumeMute;\r\n this.muteBtn.setAttribute('aria-label', 'Unmute');\r\n } else {\r\n this.muteBtn.innerHTML = ICONS.volumeHigh;\r\n this.muteBtn.setAttribute('aria-label', 'Mute');\r\n }\r\n }\r\n\r\n public updateLoopState(mode: LoopMode): void {\r\n if (mode === 'none') {\r\n this.loopBtn.classList.remove('active');\r\n this.loopBtn.innerHTML = ICONS.repeat;\r\n } else if (mode === 'all') {\r\n this.loopBtn.classList.add('active');\r\n this.loopBtn.innerHTML = ICONS.repeat;\r\n } else if (mode === 'one') {\r\n this.loopBtn.classList.add('active');\r\n this.loopBtn.innerHTML = ICONS.repeatOne;\r\n }\r\n this.loopBtn.setAttribute('aria-label', `Repeat mode: ${mode}`);\r\n }\r\n\r\n public updateShuffleState(isShuffle: boolean): void {\r\n if (isShuffle) {\r\n this.shuffleBtn.classList.add('active');\r\n } else {\r\n this.shuffleBtn.classList.remove('active');\r\n }\r\n }\r\n\r\n public toggleDrawer(open?: boolean): void {\r\n const shouldOpen = open !== undefined ? open : !this.drawerEl.classList.contains('open');\r\n if (shouldOpen) {\r\n this.drawerEl.classList.add('open');\r\n this.drawerBtn.classList.add('active');\r\n } else {\r\n this.drawerEl.classList.remove('open');\r\n this.drawerBtn.classList.remove('active');\r\n this.closeAddPanel();\r\n }\r\n }\r\n\r\n public closeAddPanel(): void {\r\n this.addPanelEl.classList.remove('open');\r\n this.addTrackBtn.classList.remove('active');\r\n }\r\n\r\n public renderPlaylist(playlist: Track[], currentIndex: number): void {\r\n this.drawerCountEl.textContent = playlist.length.toString();\r\n this.drawerInner.innerHTML = '';\r\n\r\n if (playlist.length === 0) {\r\n const emptyEl = createElement('div', {\r\n className: 'horeg-empty-playlist',\r\n textContent: 'Playlist masih kosong. Klik \"Add Track\" untuk menambahkan lagu.'\r\n });\r\n this.drawerInner.appendChild(emptyEl);\r\n return;\r\n }\r\n\r\n playlist.forEach((track, idx) => {\r\n const item = createElement('div', {\r\n className: `horeg-track-item ${idx === currentIndex ? 'active' : ''}`\r\n });\r\n\r\n const num = createElement('div', {\r\n className: 'horeg-track-num',\r\n textContent: (idx + 1).toString().padStart(2, '0')\r\n });\r\n item.appendChild(num);\r\n\r\n const details = createElement('div', { className: 'horeg-track-details' });\r\n const title = createElement('div', {\r\n className: 'horeg-item-title',\r\n textContent: track.title\r\n });\r\n const artist = createElement('div', {\r\n className: 'horeg-item-artist',\r\n textContent: track.artist || 'Unknown Artist'\r\n });\r\n details.appendChild(title);\r\n details.appendChild(artist);\r\n item.appendChild(details);\r\n\r\n if (track.duration) {\r\n const dur = createElement('div', {\r\n className: 'horeg-item-duration',\r\n textContent: formatTime(track.duration)\r\n });\r\n item.appendChild(dur);\r\n }\r\n\r\n // Remove / delete button\r\n const actions = createElement('div', { className: 'horeg-track-actions' });\r\n const removeBtn = createElement('button', {\r\n className: 'horeg-btn-remove',\r\n attributes: { type: 'button', 'aria-label': 'Hapus lagu dari playlist' },\r\n innerHTML: ICONS.trash\r\n });\r\n removeBtn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n if (this.events.onRemoveTrack) {\r\n this.events.onRemoveTrack(idx);\r\n }\r\n });\r\n actions.appendChild(removeBtn);\r\n item.appendChild(actions);\r\n\r\n item.addEventListener('click', () => {\r\n this.events.onTrackSelect(idx);\r\n });\r\n\r\n this.drawerInner.appendChild(item);\r\n });\r\n }\r\n\r\n public destroy(): void {\r\n this.root.remove();\r\n }\r\n}\r\n\r\n","export interface VisualizerOptions {\n barCount?: number;\n container: HTMLElement;\n enableAnimation?: boolean;\n}\n\nexport class Visualizer {\n private container: HTMLElement;\n private bars: HTMLElement[] = [];\n private isRunning: boolean = false;\n private animFrameId: number | null = null;\n private isEnabled: boolean = true;\n private baseHeights: number[] = [];\n\n constructor(options: VisualizerOptions) {\n this.container = options.container;\n this.isEnabled = options.enableAnimation !== false;\n const barCount = options.barCount || 5;\n\n this.initBars(barCount);\n }\n\n private initBars(count: number): void {\n this.container.innerHTML = '';\n this.bars = [];\n this.baseHeights = [];\n\n for (let i = 0; i < count; i++) {\n const bar = document.createElement('span');\n bar.className = 'horeg-eq-bar';\n this.container.appendChild(bar);\n this.bars.push(bar);\n this.baseHeights.push(3 + (i % 2) * 2);\n bar.style.height = `${this.baseHeights[i]}px`;\n }\n }\n\n public setEnabled(enabled: boolean): void {\n this.isEnabled = enabled;\n if (!enabled) {\n this.stop();\n }\n }\n\n public start(): void {\n if (this.isRunning || !this.isEnabled) return;\n this.isRunning = true;\n this.loop();\n }\n\n public stop(): void {\n this.isRunning = false;\n if (this.animFrameId !== null) {\n cancelAnimationFrame(this.animFrameId);\n this.animFrameId = null;\n }\n // Smooth reset\n for (let i = 0; i < this.bars.length; i++) {\n this.bars[i].style.height = `${this.baseHeights[i] || 3}px`;\n }\n }\n\n private loop = (): void => {\n if (!this.isRunning) return;\n\n const time = Date.now() / 150;\n for (let i = 0; i < this.bars.length; i++) {\n // Horeg rhythmic bass / mid / high pulsation formula\n const wave1 = Math.sin(time * 1.8 + i * 1.2);\n const wave2 = Math.cos(time * 2.5 + i * 0.8);\n const intensity = Math.abs(wave1 * 0.6 + wave2 * 0.4);\n // Height between 4px and 22px\n const height = Math.floor(4 + intensity * 18);\n this.bars[i].style.height = `${height}px`;\n }\n\n this.animFrameId = requestAnimationFrame(this.loop);\n };\n\n public destroy(): void {\n this.stop();\n this.bars = [];\n this.container.innerHTML = '';\n }\n}\n\n","import { HoregPlayerOptions, HoregTheme, Track, LoopMode } from './types';\r\nimport { generateStyles } from './styles';\r\nimport { AudioEngine } from './AudioEngine';\r\nimport { UI } from './UI';\r\nimport { Visualizer } from './visualizer';\r\n\r\nexport class HoregAudio {\r\n private container: HTMLElement;\r\n private shadow: ShadowRoot;\r\n private styleEl: HTMLStyleElement;\r\n private audioEngine: AudioEngine;\r\n private ui: UI;\r\n private visualizer: Visualizer;\r\n private theme: HoregTheme;\r\n private boundKeyHandler: (e: KeyboardEvent) => void;\r\n\r\n constructor(options: HoregPlayerOptions) {\r\n if (typeof options.container === 'string') {\r\n const el = document.querySelector(options.container);\r\n if (!el) {\r\n throw new Error(`[HoregAudio] Container \"${options.container}\" not found in DOM.`);\r\n }\r\n this.container = el as HTMLElement;\r\n } else if (options.container instanceof HTMLElement) {\r\n this.container = options.container;\r\n } else {\r\n throw new Error('[HoregAudio] Invalid container option provided.');\r\n }\r\n\r\n this.theme = options.theme || { variant: 'horeg-classic' };\r\n\r\n // 1. Shadow DOM attachment\r\n this.shadow = this.container.attachShadow({ mode: 'open' });\r\n\r\n // 2. Inject encapsulated styles\r\n this.styleEl = document.createElement('style');\r\n this.styleEl.textContent = generateStyles(this.theme);\r\n this.shadow.appendChild(this.styleEl);\r\n\r\n // 3. Instantiate UI\r\n this.ui = new UI({\r\n onPlayPauseClick: () => this.toggle(),\r\n onPrevClick: () => this.prev(),\r\n onNextClick: () => this.next(),\r\n onSeek: (seconds) => this.seek(seconds),\r\n onVolumeChange: (vol) => this.setVolume(vol),\r\n onMuteToggle: () => {\r\n const isMuted = this.audioEngine.toggleMute();\r\n this.ui.updateVolume(this.audioEngine.getVolume(), isMuted);\r\n },\r\n onShuffleToggle: () => {\r\n const nextShuffle = !this.audioEngine.isShuffle();\r\n this.audioEngine.setShuffle(nextShuffle);\r\n this.ui.updateShuffleState(nextShuffle);\r\n },\r\n onLoopToggle: () => {\r\n const currentLoop = this.audioEngine.getLoop();\r\n const nextLoop: LoopMode = currentLoop === 'all' ? 'one' : currentLoop === 'one' ? 'none' : 'all';\r\n this.audioEngine.setLoop(nextLoop);\r\n this.ui.updateLoopState(nextLoop);\r\n },\r\n onTrackSelect: (index) => {\r\n this.loadTrack(index, true);\r\n },\r\n onAddTrackFiles: (files) => {\r\n this.addTrackFromFiles(files, false);\r\n },\r\n onAddTrackUrl: (url, title, artist) => {\r\n this.addTrackFromUrl(url, { title, artist }, false);\r\n },\r\n onRemoveTrack: (index) => {\r\n this.removeTrack(index);\r\n }\r\n });\r\n\r\n this.shadow.appendChild(this.ui.root);\r\n\r\n // 4. Initialize Visualizer\r\n this.visualizer = new Visualizer({\r\n container: this.ui.eqContainer,\r\n enableAnimation: this.theme.enableEqAnimation !== false\r\n });\r\n\r\n // 5. Initialize AudioEngine\r\n this.audioEngine = new AudioEngine(options, {\r\n onPlay: (track) => {\r\n this.ui.updatePlayState(true);\r\n this.visualizer.start();\r\n if (options.onPlay) options.onPlay(track);\r\n },\r\n onPause: () => {\r\n this.ui.updatePlayState(false);\r\n this.visualizer.stop();\r\n if (options.onPause) options.onPause();\r\n },\r\n onTrackChange: (track, index) => {\r\n this.ui.updateTrackInfo(track);\r\n const playlist = this.audioEngine ? this.audioEngine.getPlaylist() : (options.playlist || []);\r\n this.ui.renderPlaylist(playlist, index);\r\n this.ui.updateProgress(0, track.duration || 0);\r\n if (options.onTrackChange) options.onTrackChange(track, index);\r\n },\r\n onPlaylistChange: (playlist, index) => {\r\n this.ui.renderPlaylist(playlist, index);\r\n if (options.onPlaylistChange) options.onPlaylistChange(playlist, index);\r\n },\r\n onTimeUpdate: (currentTime, duration) => {\r\n this.ui.updateProgress(currentTime, duration);\r\n if (options.onTimeUpdate) options.onTimeUpdate(currentTime, duration);\r\n },\r\n onBufferUpdate: (percent) => {\r\n this.ui.updateBuffer(percent);\r\n },\r\n onEnded: (track) => {\r\n this.visualizer.stop();\r\n if (options.onEnded) options.onEnded(track);\r\n },\r\n onError: (err) => {\r\n this.ui.updatePlayState(false);\r\n this.visualizer.stop();\r\n if (options.onError) options.onError(err);\r\n }\r\n });\r\n\r\n // Initial states\r\n this.ui.updateVolume(this.audioEngine.getVolume(), this.audioEngine.isMuted());\r\n this.ui.updateLoopState(this.audioEngine.getLoop());\r\n this.ui.updateShuffleState(this.audioEngine.isShuffle());\r\n this.ui.renderPlaylist(this.audioEngine.getPlaylist(), this.audioEngine.getCurrentIndex());\r\n\r\n const currentTrack = this.audioEngine.getCurrentTrack();\r\n if (currentTrack) {\r\n this.ui.updateTrackInfo(currentTrack);\r\n this.ui.renderPlaylist(this.audioEngine.getPlaylist(), this.audioEngine.getCurrentIndex());\r\n }\r\n\r\n // Keyboard controls when container is active\r\n this.boundKeyHandler = this.handleKeyDown.bind(this);\r\n this.container.tabIndex = this.container.tabIndex >= 0 ? this.container.tabIndex : 0;\r\n this.container.addEventListener('keydown', this.boundKeyHandler);\r\n }\r\n\r\n private handleKeyDown(e: KeyboardEvent): void {\r\n const path = e.composedPath ? e.composedPath() : [];\r\n const target = (path.length > 0 ? path[0] : e.target) as HTMLElement | null;\r\n const activeEl = (this.shadow?.activeElement || document.activeElement) as HTMLElement | null;\r\n\r\n const isInputElement = (el: HTMLElement | null): boolean => {\r\n if (!el) return false;\r\n const tag = el.tagName;\r\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;\r\n };\r\n\r\n // Do not intercept if user is typing or interacting with form controls\r\n if (isInputElement(target) || isInputElement(activeEl)) {\r\n return;\r\n }\r\n\r\n if (e.code === 'Space') {\r\n // If a button is focused, let space trigger native button click\r\n if (target?.tagName === 'BUTTON' || activeEl?.tagName === 'BUTTON') {\r\n return;\r\n }\r\n e.preventDefault();\r\n this.toggle();\r\n } else if (e.key === 'ArrowRight' && !e.shiftKey) {\r\n e.preventDefault();\r\n this.seek(this.audioEngine.getCurrentTime() + 5);\r\n } else if (e.key === 'ArrowLeft' && !e.shiftKey) {\r\n e.preventDefault();\r\n this.seek(this.audioEngine.getCurrentTime() - 5);\r\n } else if (e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n this.setVolume(this.audioEngine.getVolume() + 0.05);\r\n } else if (e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n this.setVolume(this.audioEngine.getVolume() - 0.05);\r\n }\r\n }\r\n\r\n // --- Public API Methods ---\r\n\r\n public async play(): Promise<void> {\r\n await this.audioEngine.play();\r\n }\r\n\r\n public pause(): void {\r\n this.audioEngine.pause();\r\n }\r\n\r\n public toggle(): void {\r\n this.audioEngine.toggle();\r\n }\r\n\r\n public next(): void {\r\n this.audioEngine.next();\r\n }\r\n\r\n public prev(): void {\r\n this.audioEngine.prev();\r\n }\r\n\r\n public seek(seconds: number): void {\r\n this.audioEngine.seek(seconds);\r\n }\r\n\r\n public setVolume(level: number): void {\r\n this.audioEngine.setVolume(level);\r\n this.ui.updateVolume(this.audioEngine.getVolume(), this.audioEngine.isMuted());\r\n }\r\n\r\n public loadTrack(indexOrTrack: number | Track, autoPlay: boolean = false): void {\r\n this.audioEngine.loadTrack(indexOrTrack, autoPlay);\r\n }\r\n\r\n public addTrack(track: Track, autoPlay: boolean = false): number {\r\n const index = this.audioEngine.addTrack(track, autoPlay);\r\n this.ui.renderPlaylist(this.audioEngine.getPlaylist(), this.audioEngine.getCurrentIndex());\r\n return index;\r\n }\r\n\r\n public addTracks(tracks: Track[], autoPlay: boolean = false): void {\r\n this.audioEngine.addTracks(tracks, autoPlay);\r\n this.ui.renderPlaylist(this.audioEngine.getPlaylist(), this.audioEngine.getCurrentIndex());\r\n }\r\n\r\n public async addTrackFromFile(file: File, autoPlay: boolean = false): Promise<Track> {\r\n const src = URL.createObjectURL(file);\r\n const nameWithoutExt = file.name.replace(/\\.[^/.]+$/, '');\r\n const track: Track = {\r\n id: `local-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`,\r\n title: nameWithoutExt,\r\n artist: 'File Audio Lokal',\r\n src\r\n };\r\n\r\n try {\r\n const dur = await this.probeAudioDuration(src);\r\n if (dur > 0) {\r\n track.duration = dur;\r\n }\r\n } catch {\r\n // AudioEngine will pick up duration on loadedmetadata\r\n }\r\n\r\n this.addTrack(track, autoPlay);\r\n return track;\r\n }\r\n\r\n public async addTrackFromFiles(files: FileList | File[], autoPlay: boolean = false): Promise<Track[]> {\r\n const fileArray = Array.from(files);\r\n const addedTracks: Track[] = [];\r\n for (let i = 0; i < fileArray.length; i++) {\r\n const file = fileArray[i];\r\n const shouldAutoPlay = autoPlay && i === 0;\r\n const track = await this.addTrackFromFile(file, shouldAutoPlay);\r\n addedTracks.push(track);\r\n }\r\n return addedTracks;\r\n }\r\n\r\n public async addTrackFromUrl(url: string, meta: Partial<Track> = {}, autoPlay: boolean = false): Promise<Track> {\r\n let fallbackTitle = 'Online Track';\r\n try {\r\n const parsed = new URL(url);\r\n const pathname = parsed.pathname;\r\n const lastPart = pathname.substring(pathname.lastIndexOf('/') + 1);\r\n if (lastPart) {\r\n fallbackTitle = decodeURIComponent(lastPart).replace(/\\.[^/.]+$/, '');\r\n }\r\n } catch {\r\n // In case of non-standard URL or data URI\r\n }\r\n\r\n const track: Track = {\r\n id: meta.id || `url-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`,\r\n title: meta.title?.trim() || fallbackTitle,\r\n artist: meta.artist?.trim() || 'Audio Stream',\r\n album: meta.album,\r\n coverArt: meta.coverArt,\r\n src: url,\r\n duration: meta.duration\r\n };\r\n\r\n if (!track.duration) {\r\n try {\r\n const dur = await this.probeAudioDuration(url);\r\n if (dur > 0) {\r\n track.duration = dur;\r\n }\r\n } catch {\r\n // Fallback to loadedmetadata\r\n }\r\n }\r\n\r\n this.addTrack(track, autoPlay);\r\n return track;\r\n }\r\n\r\n public removeTrack(index: number): void {\r\n this.audioEngine.removeTrack(index);\r\n this.ui.renderPlaylist(this.audioEngine.getPlaylist(), this.audioEngine.getCurrentIndex());\r\n const current = this.audioEngine.getCurrentTrack();\r\n if (current) {\r\n this.ui.updateTrackInfo(current);\r\n } else {\r\n this.ui.updateTrackInfo({ title: 'No Track Loaded', src: '' });\r\n }\r\n }\r\n\r\n public getPlaylist(): Track[] {\r\n return this.audioEngine.getPlaylist();\r\n }\r\n\r\n private probeAudioDuration(src: string): Promise<number> {\r\n return new Promise((resolve) => {\r\n const tempAudio = new Audio();\r\n let isResolved = false;\r\n\r\n const finish = (dur: number) => {\r\n if (!isResolved) {\r\n isResolved = true;\r\n tempAudio.removeEventListener('loadedmetadata', onLoaded);\r\n tempAudio.removeEventListener('error', onError);\r\n tempAudio.src = '';\r\n resolve(dur);\r\n }\r\n };\r\n\r\n const onLoaded = () => {\r\n const d = tempAudio.duration;\r\n finish(d && !isNaN(d) && isFinite(d) ? d : 0);\r\n };\r\n\r\n const onError = () => finish(0);\r\n\r\n tempAudio.addEventListener('loadedmetadata', onLoaded);\r\n tempAudio.addEventListener('error', onError);\r\n tempAudio.src = src;\r\n\r\n setTimeout(() => finish(0), 3000);\r\n });\r\n }\r\n\r\n public setTheme(themeConfig: Partial<HoregTheme>): void {\r\n this.theme = { ...this.theme, ...themeConfig };\r\n this.styleEl.textContent = generateStyles(this.theme);\r\n if (this.theme.enableEqAnimation !== undefined) {\r\n this.visualizer.setEnabled(this.theme.enableEqAnimation);\r\n }\r\n }\r\n\r\n public getAudioEngine(): AudioEngine {\r\n return this.audioEngine;\r\n }\r\n\r\n public destroy(): void {\r\n this.container.removeEventListener('keydown', this.boundKeyHandler);\r\n this.audioEngine.destroy();\r\n this.visualizer.destroy();\r\n this.ui.destroy();\r\n this.shadow.innerHTML = '';\r\n }\r\n}\r\n\r\n"],"names":["THEME_PRESETS","generateStyles","theme","variant","preset","glow","accent","bg","text","progress","radius","formatTime","seconds","roundedSeconds","hours","minutes","remainingSeconds","pad","num","clamp","value","min","max","AudioEngine","options","callbacks","__publicField","current","duration","bufferedEnd","percent","err","newPlaylist","startIndex","track","autoPlay","wasEmpty","newIndex","tracks","firstAddedIndex","index","isCurrentTrack","nextIndex","dur","currentTrack","indexOrTrack","targetIndex","t","clampedTime","level","clamped","isFromEnded","randomIndex","prevIndex","mode","shuffle","ICONS","createElement","tagName","el","key","val","UI","events","onMove","moveEvent","onUp","upEvent","grill","pos","contentWrap","header","badge","trackRow","trackInfo","progressContainer","timeRow","controlsRow","leftControls","centerControls","rightControls","volumeWrap","drawerHeader","drawerHeading","tabs","formActions","isOpen","files","e","_a","audioFiles","f","handleUrlSubmit","url","title","artist","handleUrlInputKeyDown","cur","rect","clientX","offsetX","seekTime","targetSeconds","isPlaying","currentTime","volume","isMuted","isShuffle","open","playlist","currentIndex","emptyEl","idx","item","details","actions","removeBtn","Visualizer","time","wave1","wave2","intensity","height","barCount","count","bar","enabled","i","HoregAudio","vol","nextShuffle","currentLoop","nextLoop","path","target","activeEl","isInputElement","tag","file","src","nameWithoutExt","fileArray","addedTracks","shouldAutoPlay","meta","fallbackTitle","pathname","lastPart","_b","resolve","tempAudio","isResolved","finish","onLoaded","onError","d","themeConfig"],"mappings":"4MAEO,MAAMA,EAA2D,CACtE,gBAAiB,CACf,iBAAkB,UAClB,YAAa,UACb,eAAgB,UAChB,UAAW,UACX,oBAAqB,UACrB,aAAc,MAAA,EAEhB,kBAAmB,CACjB,iBAAkB,UAClB,YAAa,UACb,eAAgB,UAChB,UAAW,UACX,oBAAqB,UACrB,aAAc,MAAA,EAEhB,gBAAiB,CACf,iBAAkB,UAClB,YAAa,UACb,eAAgB,UAChB,UAAW,UACX,oBAAqB,UACrB,aAAc,KAAA,CAElB,EAKO,SAASC,EAAeC,EAAoB,GAAY,CAC7D,MAAMC,EAAUD,EAAM,SAAW,gBAC3BE,EAASJ,EAAcG,CAAO,GAAKH,EAAc,eAAe,EAEhEK,EAAOH,EAAM,kBAAoBE,EAAO,kBAAoB,UAC5DE,EAASJ,EAAM,aAAeE,EAAO,aAAe,UACpDG,EAAKL,EAAM,gBAAkBE,EAAO,gBAAkB,UACtDI,EAAON,EAAM,WAAaE,EAAO,WAAa,UAC9CK,EAAWP,EAAM,qBAAuBE,EAAO,qBAAuBC,EACtEK,EAASR,EAAM,cAAgBE,EAAO,cAAgB,OAE5D,MAAO;AAAA;AAAA,oBAEWG,CAAE;AAAA;AAAA;AAAA;AAAA,sBAIAF,CAAI;AAAA;AAAA,wBAEFC,CAAM;AAAA,0BACJG,CAAQ;AAAA,2BACPD,CAAI;AAAA;AAAA,wBAEPE,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA2yB9B,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"}
|