waveframe 0.1.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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Agradip <me@agradip.fyi>
4
+
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Waveframe
2
+
3
+ A customizable React audio player component with SoundCloud-style waveforms.
4
+
5
+ ## Features
6
+
7
+ - **SoundCloud-style Waveform**: Supports pre-calculated peak points for instant rendering.
8
+ - **Customizable UI**: Styled with Tailwind CSS, easy to theme and adapt.
9
+ - **Artwork Support**: Display track artwork prominently.
10
+ - **High Performance**: Built with Vite and TypeScript.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm add waveframe
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```tsx
21
+ import { WaveframePlayer } from 'waveframe';
22
+
23
+ const peaks = [0.1, 0.5, 0.8, 0.3, ...]; // 100-200 points recommended
24
+
25
+ function App() {
26
+ return (
27
+ <WaveframePlayer
28
+ audioUrl="path/to/audio.mp3"
29
+ peaks={peaks}
30
+ artworkUrl="path/to/artwork.jpg"
31
+ title="Track Title"
32
+ artist="Artist Name"
33
+ />
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## License
39
+
40
+ MIT
@@ -0,0 +1,2 @@
1
+ export * from './src/index'
2
+ export {}
@@ -0,0 +1,2 @@
1
+ declare function App(): import("react/jsx-runtime").JSX.Element;
2
+ export default App;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { default as React } from 'react';
2
+ interface CodeBlockProps {
3
+ code: string;
4
+ highlightFn: (code: string) => string[];
5
+ onCopy: () => void;
6
+ copied: boolean;
7
+ }
8
+ export declare const CodeBlock: React.FC<CodeBlockProps>;
9
+ export {};
@@ -0,0 +1,20 @@
1
+ import { default as React } from 'react';
2
+ import { WaveframeTheme } from '../types';
3
+ export interface WaveframePlayerProps {
4
+ audioUrl: string;
5
+ peaks?: number[];
6
+ artworkUrl?: string;
7
+ title?: string;
8
+ artist?: string;
9
+ waveColor?: string;
10
+ progressColor?: string;
11
+ height?: number;
12
+ className?: string;
13
+ style?: React.CSSProperties;
14
+ resolution?: number | 'auto';
15
+ barWidth?: number;
16
+ barGap?: number;
17
+ theme?: WaveframeTheme;
18
+ autoAnalyze?: boolean;
19
+ }
20
+ export declare const WaveframePlayer: React.FC<WaveframePlayerProps>;
@@ -0,0 +1,16 @@
1
+ export declare const useAudioPlayer: (url: string) => {
2
+ isPlaying: boolean;
3
+ currentTime: number;
4
+ duration: number;
5
+ togglePlay: (e?: React.MouseEvent) => void;
6
+ seek: (percentage: number) => void;
7
+ audioProps: {
8
+ ref: import('react').RefObject<HTMLAudioElement | null>;
9
+ src: string;
10
+ onTimeUpdate: () => void;
11
+ onLoadedMetadata: () => void;
12
+ onPlay: () => void;
13
+ onPause: () => void;
14
+ onEnded: () => void;
15
+ };
16
+ };
@@ -0,0 +1 @@
1
+ export declare const usePersistentSettings: (key: string, defaultValue: any) => any[];
@@ -0,0 +1 @@
1
+ export declare const useResampledPeaks: (peaks: number[], targetCount: number) => number[];
@@ -0,0 +1 @@
1
+ export declare const useResizeObserver: (ref: React.RefObject<HTMLElement | null>) => number;
@@ -0,0 +1 @@
1
+ export * from './components/WaveframePlayer';
File without changes
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ interface ArtworkOverlayProps {
3
+ artworkUrl?: string;
4
+ title?: string;
5
+ isPlaying: boolean;
6
+ onToggle: (e: React.MouseEvent) => void;
7
+ isLoading?: boolean;
8
+ }
9
+ export declare const ArtworkOverlay: React.FC<ArtworkOverlayProps>;
10
+ export {};
@@ -0,0 +1,18 @@
1
+ import { default as React } from 'react';
2
+ import { WaveframeTheme, TrackInfo, WaveformConfig } from '../types';
3
+ interface SettingsPanelProps {
4
+ theme: WaveframeTheme;
5
+ trackInfo: TrackInfo;
6
+ config: WaveformConfig;
7
+ scale: number;
8
+ isAnalyzing: boolean;
9
+ onAnalyze: () => void;
10
+ onThemeChange: (theme: Partial<WaveframeTheme>) => void;
11
+ onTrackChange: (track: Partial<TrackInfo>) => void;
12
+ onConfigChange: (config: Partial<WaveformConfig>) => void;
13
+ onScaleChange: (scale: number) => void;
14
+ onTogglePreset: (type: 'light' | 'dark') => void;
15
+ onClearPeaks: () => void;
16
+ }
17
+ export declare const SettingsPanel: React.FC<SettingsPanelProps>;
18
+ export {};
@@ -0,0 +1,15 @@
1
+ import { default as React } from 'react';
2
+ interface WaveformProps {
3
+ peaks: number[];
4
+ currentTime: number;
5
+ duration: number;
6
+ waveColor: string;
7
+ progressColor: string;
8
+ height: number;
9
+ onSeek: (percentage: number) => void;
10
+ resolution?: number | 'auto';
11
+ barWidth?: number;
12
+ barGap?: number;
13
+ }
14
+ export declare const Waveform: React.FC<WaveformProps>;
15
+ export {};
@@ -0,0 +1,19 @@
1
+ export interface WaveframeTheme {
2
+ bg: string;
3
+ primary: string;
4
+ text: string;
5
+ border: string;
6
+ }
7
+ export interface TrackInfo {
8
+ title: string;
9
+ artist: string;
10
+ artworkUrl: string;
11
+ audioUrl: string;
12
+ }
13
+ export type Resolution = number | 'auto';
14
+ export interface WaveformConfig {
15
+ resolution: Resolution;
16
+ barWidth: number;
17
+ barGap: number;
18
+ height: number;
19
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Advanced Audio Utilities using Web Audio API
3
+ */
4
+ /**
5
+ * Loads audio from a URL, decodes it, and generates a specific number of peaks (samples)
6
+ */
7
+ export declare const generatePeaks: (audioUrl: string, samples?: number) => Promise<number[]>;
8
+ /**
9
+ * Loads audio into memory as a Blob and returns a temporary Object URL
10
+ */
11
+ export declare const loadAudioToMemory: (url: string) => Promise<string>;
12
+ /**
13
+ * Cleanup function to prevent memory leaks from Object URLs
14
+ */
15
+ export declare const revokeAudioMemory: (url: string) => void;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Formats seconds into a M:SS string
3
+ */
4
+ export declare const formatTime: (seconds: number) => string;
5
+ /**
6
+ * Resamples an array of peaks to a target count using bucket-max or linear interpolation
7
+ */
8
+ export declare const resamplePeaks: (peaks: number[], targetCount: number) => number[];
9
+ /**
10
+ * High-performance token-based syntax highlighter for React snippets
11
+ */
12
+ export declare const highlightCode: (code: string) => string[];
13
+ export * from './audio';
@@ -0,0 +1,3 @@
1
+ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-green-400:oklch(79.2% .209 151.711);--color-blue-50:oklch(97% .014 254.604);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-4xl:56rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-medium:500;--font-weight-bold:700;--font-weight-black:900;--tracking-tighter:-.05em;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-md:12px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.-top-1\/2{top:-50%}.-left-1\/2{left:-50%}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mt-auto{margin-top:auto}.mr-4{margin-right:calc(var(--spacing) * 4)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-1{margin-left:calc(var(--spacing) * 1)}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.h-8{height:calc(var(--spacing) * 8)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-32{height:calc(var(--spacing) * 32)}.h-\[200\%\]{height:200%}.h-full{height:100%}.h-screen{height:100vh}.min-h-screen{min-height:100vh}.w-4{width:calc(var(--spacing) * 4)}.w-8{width:calc(var(--spacing) * 8)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-32{width:calc(var(--spacing) * 32)}.w-\[200\%\]{width:200%}.w-full{width:100%}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.scale-90{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x) var(--tw-scale-y)}.scale-110{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing) * 1)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-12{gap:calc(var(--spacing) * 12)}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\[var\(--wf-artwork-rounded\,0\.75rem\)\]{border-radius:var(--wf-artwork-rounded,.75rem)}.rounded-\[var\(--wf-rounded\,1rem\)\]{border-radius:var(--wf-rounded,1rem)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-\[\#333\]{border-color:#333}.border-\[var\(--wf-border-color\,\#f3f4f6\)\]{border-color:var(--wf-border-color,#f3f4f6)}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.border-white\/30{border-color:color-mix(in oklab, var(--color-white) 30%, transparent)}}.border-t-white{border-top-color:var(--color-white)}.bg-\[\#1e1e1e\]{background-color:#1e1e1e}.bg-\[\#252526\]{background-color:#252526}.bg-\[var\(--wf-bg-color\,white\)\]{background-color:var(--wf-bg-color,white)}.bg-\[var\(--wf-overlay-color\,rgba\(0\,0\,0\,0\.3\)\)\]{background-color:var(--wf-overlay-color,#0000004d)}.bg-\[var\(--wf-play-btn-bg\,\#f97316\)\]{background-color:var(--wf-play-btn-bg,#f97316)}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.bg-black\/10{background-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-gray-50\/50{background-color:#f9fafb80}@supports (color:color-mix(in lab, red, red)){.bg-gray-50\/50{background-color:color-mix(in oklab, var(--color-gray-50) 50%, transparent)}}.bg-gray-100{background-color:var(--color-gray-100)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-\[var\(--wf-placeholder-from\,\#fb923c\)\]{--tw-gradient-from:var(--wf-placeholder-from,#fb923c);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-\[var\(--wf-placeholder-to\,\#ec4899\)\]{--tw-gradient-to:var(--wf-placeholder-to,#ec4899);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pb-20{padding-bottom:calc(var(--spacing) * 20)}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[13px\]{font-size:13px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\[0\.2em\]{--tw-tracking:.2em;letter-spacing:.2em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-tighter{--tw-tracking:var(--tracking-tighter);letter-spacing:var(--tracking-tighter)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.whitespace-pre{white-space:pre}.text-\[\#4ec9b0\]{color:#4ec9b0}.text-\[\#9cdcfe\]{color:#9cdcfe}.text-\[\#b5cea8\]{color:#b5cea8}.text-\[\#ce9178\]{color:#ce9178}.text-\[var\(--wf-artist-color\,\#6b7280\)\]{color:var(--wf-artist-color,#6b7280)}.text-\[var\(--wf-play-btn-color\,white\)\]{color:var(--wf-play-btn-color,white)}.text-\[var\(--wf-time-color\,\#9ca3af\)\]{color:var(--wf-time-color,#9ca3af)}.text-\[var\(--wf-title-color\,\#111827\)\]{color:var(--wf-title-color,#111827)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-900{color:var(--color-gray-900)}.text-green-400{color:var(--color-green-400)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-dotted{text-decoration-style:dotted}.accent-blue-500{accent-color:var(--color-blue-500)}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.blur-md{--tw-blur:blur(var(--blur-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-\[1px\]{--tw-backdrop-blur:blur(1px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-\[var\(--wf-overlay-blur\,2px\)\]{--tw-backdrop-blur:blur(var(--wf-overlay-blur,2px));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.duration-700{--tw-duration:.7s;transition-duration:.7s}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\/artwork\:scale-100:is(:where(.group\/artwork):hover *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\/artwork\:scale-110:is(:where(.group\/artwork):hover *){--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\/artwork\:opacity-100:is(:where(.group\/artwork):hover *){opacity:1}.hover\:text-blue-300:hover{color:var(--color-blue-300)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:shadow-2xl:hover{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}@media (width>=48rem){.md\:h-40{height:calc(var(--spacing) * 40)}.md\:w-40{width:calc(var(--spacing) * 40)}.md\:flex-row{flex-direction:row}.md\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.md\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}}@media (width>=64rem){.lg\:w-96{width:calc(var(--spacing) * 96)}.lg\:flex-row{flex-direction:row}}}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}
3
+ /*$vite$:1*/
@@ -0,0 +1,435 @@
1
+ import e, { memo as t, useCallback as n, useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
2
+ //#region \0rolldown/runtime.js
3
+ var s = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), c = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
4
+ if (typeof require < "u") return require.apply(this, arguments);
5
+ throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
6
+ }), l = (e) => {
7
+ let t = a(null), [i, s] = o(!1), [c, l] = o(0), [u, d] = o(0);
8
+ r(() => {
9
+ t.current && t.current.readyState >= 1 && d(t.current.duration);
10
+ }, [e]);
11
+ let f = n((e) => {
12
+ e?.stopPropagation(), t.current && (i ? t.current.pause() : t.current.play().catch(console.error));
13
+ }, [i]), p = n(() => {
14
+ t.current && l(t.current.currentTime);
15
+ }, []), m = n(() => {
16
+ t.current && d(t.current.duration);
17
+ }, []);
18
+ return {
19
+ isPlaying: i,
20
+ currentTime: c,
21
+ duration: u,
22
+ togglePlay: f,
23
+ seek: n((e) => {
24
+ t.current && u && (t.current.currentTime = e * u);
25
+ }, [u]),
26
+ audioProps: {
27
+ ref: t,
28
+ src: e,
29
+ onTimeUpdate: p,
30
+ onLoadedMetadata: m,
31
+ onPlay: () => s(!0),
32
+ onPause: () => s(!1),
33
+ onEnded: () => s(!1)
34
+ }
35
+ };
36
+ }, u = async (e, t = 512) => {
37
+ let n = await (await fetch(e)).arrayBuffer(), r = (await new (window.AudioContext || window.webkitAudioContext)().decodeAudioData(n)).getChannelData(0), i = Math.floor(r.length / t), a = [];
38
+ for (let e = 0; e < t; e++) {
39
+ let t = 0, n = e * i, o = n + i;
40
+ for (let e = n; e < o; e++) {
41
+ let n = Math.abs(r[e]);
42
+ n > t && (t = n);
43
+ }
44
+ a.push(t);
45
+ }
46
+ let o = Math.max(...a);
47
+ return a.map((e) => e / (o || 1));
48
+ }, d = (e) => isNaN(e) ? "0:00" : `${Math.floor(e / 60)}:${Math.floor(e % 60).toString().padStart(2, "0")}`, f = (e, t) => {
49
+ if (e.length === 0) return [];
50
+ if (e.length === t) return e;
51
+ let n = Array(t), r = e.length / t;
52
+ if (r > 1) for (let i = 0; i < t; i++) {
53
+ let t = 0, a = Math.floor(i * r), o = Math.floor((i + 1) * r);
54
+ for (let n = a; n < o; n++) e[n] > t && (t = e[n]);
55
+ n[i] = t;
56
+ }
57
+ else for (let i = 0; i < t; i++) {
58
+ let t = i * r, a = Math.floor(t), o = Math.min(a + 1, e.length - 1), s = t - a;
59
+ n[i] = e[a] + (e[o] - e[a]) * s;
60
+ }
61
+ return n;
62
+ }, p = (e, t) => i(() => f(e, t), [e, t]), m = (e) => {
63
+ let [t, n] = o(0);
64
+ return r(() => {
65
+ if (!e.current) return;
66
+ let t = new ResizeObserver((e) => {
67
+ for (let t of e) n(t.contentRect.width);
68
+ });
69
+ return t.observe(e.current), () => t.disconnect();
70
+ }, [e]), t;
71
+ }, h = /* @__PURE__ */ s(((e) => {
72
+ var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment");
73
+ function r(e, n, r) {
74
+ var i = null;
75
+ if (r !== void 0 && (i = "" + r), n.key !== void 0 && (i = "" + n.key), "key" in n) for (var a in r = {}, n) a !== "key" && (r[a] = n[a]);
76
+ else r = n;
77
+ return n = r.ref, {
78
+ $$typeof: t,
79
+ type: e,
80
+ key: i,
81
+ ref: n === void 0 ? null : n,
82
+ props: r
83
+ };
84
+ }
85
+ e.Fragment = n, e.jsx = r, e.jsxs = r;
86
+ })), g = /* @__PURE__ */ s(((e) => {
87
+ process.env.NODE_ENV !== "production" && (function() {
88
+ function t(e) {
89
+ if (e == null) return null;
90
+ if (typeof e == "function") return e.$$typeof === k ? null : e.displayName || e.name || null;
91
+ if (typeof e == "string") return e;
92
+ switch (e) {
93
+ case v: return "Fragment";
94
+ case b: return "Profiler";
95
+ case y: return "StrictMode";
96
+ case w: return "Suspense";
97
+ case T: return "SuspenseList";
98
+ case O: return "Activity";
99
+ }
100
+ if (typeof e == "object") switch (typeof e.tag == "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), e.$$typeof) {
101
+ case _: return "Portal";
102
+ case S: return e.displayName || "Context";
103
+ case x: return (e._context.displayName || "Context") + ".Consumer";
104
+ case C:
105
+ var n = e.render;
106
+ return e = e.displayName, e ||= (e = n.displayName || n.name || "", e === "" ? "ForwardRef" : "ForwardRef(" + e + ")"), e;
107
+ case E: return n = e.displayName || null, n === null ? t(e.type) || "Memo" : n;
108
+ case D:
109
+ n = e._payload, e = e._init;
110
+ try {
111
+ return t(e(n));
112
+ } catch {}
113
+ }
114
+ return null;
115
+ }
116
+ function n(e) {
117
+ return "" + e;
118
+ }
119
+ function r(e) {
120
+ try {
121
+ n(e);
122
+ var t = !1;
123
+ } catch {
124
+ t = !0;
125
+ }
126
+ if (t) {
127
+ t = console;
128
+ var r = t.error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
129
+ return r.call(t, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", i), n(e);
130
+ }
131
+ }
132
+ function i(e) {
133
+ if (e === v) return "<>";
134
+ if (typeof e == "object" && e && e.$$typeof === D) return "<...>";
135
+ try {
136
+ var n = t(e);
137
+ return n ? "<" + n + ">" : "<...>";
138
+ } catch {
139
+ return "<...>";
140
+ }
141
+ }
142
+ function a() {
143
+ var e = A.A;
144
+ return e === null ? null : e.getOwner();
145
+ }
146
+ function o() {
147
+ return Error("react-stack-top-frame");
148
+ }
149
+ function s(e) {
150
+ if (j.call(e, "key")) {
151
+ var t = Object.getOwnPropertyDescriptor(e, "key").get;
152
+ if (t && t.isReactWarning) return !1;
153
+ }
154
+ return e.key !== void 0;
155
+ }
156
+ function l(e, t) {
157
+ function n() {
158
+ P || (P = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", t));
159
+ }
160
+ n.isReactWarning = !0, Object.defineProperty(e, "key", {
161
+ get: n,
162
+ configurable: !0
163
+ });
164
+ }
165
+ function u() {
166
+ var e = t(this.type);
167
+ return F[e] || (F[e] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")), e = this.props.ref, e === void 0 ? null : e;
168
+ }
169
+ function d(e, t, n, r, i, a) {
170
+ var o = n.ref;
171
+ return e = {
172
+ $$typeof: g,
173
+ type: e,
174
+ key: t,
175
+ props: n,
176
+ _owner: r
177
+ }, (o === void 0 ? null : o) === null ? Object.defineProperty(e, "ref", {
178
+ enumerable: !1,
179
+ value: null
180
+ }) : Object.defineProperty(e, "ref", {
181
+ enumerable: !1,
182
+ get: u
183
+ }), e._store = {}, Object.defineProperty(e._store, "validated", {
184
+ configurable: !1,
185
+ enumerable: !1,
186
+ writable: !0,
187
+ value: 0
188
+ }), Object.defineProperty(e, "_debugInfo", {
189
+ configurable: !1,
190
+ enumerable: !1,
191
+ writable: !0,
192
+ value: null
193
+ }), Object.defineProperty(e, "_debugStack", {
194
+ configurable: !1,
195
+ enumerable: !1,
196
+ writable: !0,
197
+ value: i
198
+ }), Object.defineProperty(e, "_debugTask", {
199
+ configurable: !1,
200
+ enumerable: !1,
201
+ writable: !0,
202
+ value: a
203
+ }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
204
+ }
205
+ function f(e, n, i, o, c, u) {
206
+ var f = n.children;
207
+ if (f !== void 0) if (o) if (M(f)) {
208
+ for (o = 0; o < f.length; o++) p(f[o]);
209
+ Object.freeze && Object.freeze(f);
210
+ } else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
211
+ else p(f);
212
+ if (j.call(n, "key")) {
213
+ f = t(e);
214
+ var m = Object.keys(n).filter(function(e) {
215
+ return e !== "key";
216
+ });
217
+ o = 0 < m.length ? "{key: someKey, " + m.join(": ..., ") + ": ...}" : "{key: someKey}", R[f + o] || (m = 0 < m.length ? "{" + m.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", o, f, m, f), R[f + o] = !0);
218
+ }
219
+ if (f = null, i !== void 0 && (r(i), f = "" + i), s(n) && (r(n.key), f = "" + n.key), "key" in n) for (var h in i = {}, n) h !== "key" && (i[h] = n[h]);
220
+ else i = n;
221
+ return f && l(i, typeof e == "function" ? e.displayName || e.name || "Unknown" : e), d(e, f, i, a(), c, u);
222
+ }
223
+ function p(e) {
224
+ m(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e && e.$$typeof === D && (e._payload.status === "fulfilled" ? m(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
225
+ }
226
+ function m(e) {
227
+ return typeof e == "object" && !!e && e.$$typeof === g;
228
+ }
229
+ var h = c("react"), g = Symbol.for("react.transitional.element"), _ = Symbol.for("react.portal"), v = Symbol.for("react.fragment"), y = Symbol.for("react.strict_mode"), b = Symbol.for("react.profiler"), x = Symbol.for("react.consumer"), S = Symbol.for("react.context"), C = Symbol.for("react.forward_ref"), w = Symbol.for("react.suspense"), T = Symbol.for("react.suspense_list"), E = Symbol.for("react.memo"), D = Symbol.for("react.lazy"), O = Symbol.for("react.activity"), k = Symbol.for("react.client.reference"), A = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, j = Object.prototype.hasOwnProperty, M = Array.isArray, N = console.createTask ? console.createTask : function() {
230
+ return null;
231
+ };
232
+ h = { react_stack_bottom_frame: function(e) {
233
+ return e();
234
+ } };
235
+ var P, F = {}, I = h.react_stack_bottom_frame.bind(h, o)(), L = N(i(o)), R = {};
236
+ e.Fragment = v, e.jsx = function(e, t, n) {
237
+ var r = 1e4 > A.recentlyCreatedOwnerStacks++;
238
+ return f(e, t, n, !1, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
239
+ }, e.jsxs = function(e, t, n) {
240
+ var r = 1e4 > A.recentlyCreatedOwnerStacks++;
241
+ return f(e, t, n, !0, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
242
+ };
243
+ })();
244
+ })), _ = (/* @__PURE__ */ s(((e, t) => {
245
+ process.env.NODE_ENV === "production" ? t.exports = h() : t.exports = g();
246
+ })))(), v = t(({ artworkUrl: e, title: t, isPlaying: n, onToggle: r, isLoading: i }) => /* @__PURE__ */ (0, _.jsxs)("div", {
247
+ className: "relative flex-shrink-0 w-32 h-32 md:w-40 md:h-40 overflow-hidden rounded-[var(--wf-artwork-rounded,0.75rem)] shadow-lg group/artwork",
248
+ children: [/* @__PURE__ */ (0, _.jsx)("div", {
249
+ className: `w-full h-full transition-all duration-700 ${i ? "blur-md scale-110" : ""}`,
250
+ children: e ? /* @__PURE__ */ (0, _.jsx)("img", {
251
+ src: e,
252
+ alt: t,
253
+ className: "w-full h-full object-cover transition-transform duration-500 group-hover/artwork:scale-110"
254
+ }) : /* @__PURE__ */ (0, _.jsx)("div", {
255
+ className: "w-full h-full bg-gradient-to-br from-[var(--wf-placeholder-from,#fb923c)] to-[var(--wf-placeholder-to,#ec4899)] flex items-center justify-center",
256
+ children: /* @__PURE__ */ (0, _.jsx)("svg", {
257
+ className: "w-16 h-16 text-white opacity-50",
258
+ fill: "currentColor",
259
+ viewBox: "0 0 24 24",
260
+ children: /* @__PURE__ */ (0, _.jsx)("path", { d: "M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z" })
261
+ })
262
+ })
263
+ }), i ? /* @__PURE__ */ (0, _.jsx)("div", {
264
+ className: "absolute inset-0 flex items-center justify-center bg-black/10 backdrop-blur-[1px]",
265
+ children: /* @__PURE__ */ (0, _.jsx)("div", { className: "w-8 h-8 border-4 border-white/30 border-t-white rounded-full animate-spin" })
266
+ }) : /* @__PURE__ */ (0, _.jsx)("button", {
267
+ className: "absolute inset-0 bg-[var(--wf-overlay-color,rgba(0,0,0,0.3))] backdrop-blur-[var(--wf-overlay-blur,2px)] opacity-0 group-hover/artwork:opacity-100 transition-opacity duration-300 flex items-center justify-center cursor-pointer border-none outline-none",
268
+ onClick: r,
269
+ "aria-label": n ? "Pause" : "Play",
270
+ children: /* @__PURE__ */ (0, _.jsx)("div", {
271
+ className: "w-14 h-14 flex items-center justify-center bg-[var(--wf-play-btn-bg,#f97316)] rounded-full text-[var(--wf-play-btn-color,white)] shadow-lg transform scale-90 group-hover/artwork:scale-100 transition-transform duration-300",
272
+ children: n ? /* @__PURE__ */ (0, _.jsx)("svg", {
273
+ className: "w-8 h-8",
274
+ fill: "currentColor",
275
+ viewBox: "0 0 24 24",
276
+ children: /* @__PURE__ */ (0, _.jsx)("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" })
277
+ }) : /* @__PURE__ */ (0, _.jsx)("svg", {
278
+ className: "w-8 h-8 ml-1",
279
+ fill: "currentColor",
280
+ viewBox: "0 0 24 24",
281
+ children: /* @__PURE__ */ (0, _.jsx)("path", { d: "M8 5v14l11-7z" })
282
+ })
283
+ })
284
+ })]
285
+ }));
286
+ v.displayName = "ArtworkOverlay";
287
+ //#endregion
288
+ //#region src/organisms/Waveform.tsx
289
+ var y = t(({ peaks: e, currentTime: t, duration: n, waveColor: i, progressColor: o, height: s, onSeek: c, resolution: l = "auto", barWidth: u = 2, barGap: d = 1 }) => {
290
+ let f = a(null), p = a(null), h = a(null), g = m(h);
291
+ r(() => {
292
+ let t = f.current, n = p.current;
293
+ if (!t || !n) return;
294
+ let r = t.getContext("2d"), a = n.getContext("2d");
295
+ if (!r || !a) return;
296
+ let s = window.devicePixelRatio || 1, c = t.getBoundingClientRect(), m = c.width * s, h = c.height * s;
297
+ [t, n].forEach((e) => {
298
+ (e.width !== m || e.height !== h) && (e.width = m, e.height = h);
299
+ }), (() => {
300
+ if (e.length === 0) return;
301
+ let { width: n, height: c } = t;
302
+ r.clearRect(0, 0, n, c), a.clearRect(0, 0, n, c);
303
+ let f = n / e.length, p = typeof l == "number" ? f * .7 : u * s, m = typeof l == "number" ? f * .3 : d * s;
304
+ r.lineCap = "round", r.lineWidth = p, a.lineCap = "round", a.lineWidth = p, e.forEach((e, t) => {
305
+ let n = t * (p + m) + p / 2, s = e * c * .8, l = (c - s) / 2, u = l + s;
306
+ r.beginPath(), r.strokeStyle = i, r.moveTo(n, l), r.lineTo(n, u), r.stroke(), a.beginPath(), a.strokeStyle = o, a.moveTo(n, l), a.lineTo(n, u), a.stroke();
307
+ });
308
+ })();
309
+ }, [
310
+ e,
311
+ i,
312
+ o,
313
+ l,
314
+ u,
315
+ d,
316
+ s
317
+ ]);
318
+ let v = (e) => {
319
+ if (h.current && n) {
320
+ let t = h.current.getBoundingClientRect(), n = e.clientX - t.left;
321
+ c(Math.max(0, Math.min(1, n / t.width)));
322
+ }
323
+ }, y = n ? t / n * 100 : 0;
324
+ return /* @__PURE__ */ (0, _.jsxs)("div", {
325
+ ref: h,
326
+ className: "relative w-full cursor-pointer overflow-hidden",
327
+ style: { height: `${s}px` },
328
+ onClick: v,
329
+ children: [/* @__PURE__ */ (0, _.jsx)("canvas", {
330
+ ref: f,
331
+ className: "absolute inset-0 w-full h-full"
332
+ }), /* @__PURE__ */ (0, _.jsx)("div", {
333
+ className: "absolute inset-0 h-full overflow-hidden transition-[width] duration-100 ease-linear pointer-events-none",
334
+ style: { width: `${y}%` },
335
+ children: /* @__PURE__ */ (0, _.jsx)("canvas", {
336
+ ref: p,
337
+ className: "absolute h-full",
338
+ style: { width: `${g}px` }
339
+ })
340
+ })]
341
+ });
342
+ });
343
+ y.displayName = "Waveform";
344
+ //#endregion
345
+ //#region src/components/WaveframePlayer.tsx
346
+ var b = t(({ audioUrl: t, peaks: n, artworkUrl: a, title: s, artist: c, waveColor: f, progressColor: h, height: g = 80, className: b = "", style: x, resolution: S = "auto", barWidth: C = 2, barGap: w = 1, theme: T, autoAnalyze: E = !0 }) => {
347
+ let { isPlaying: D, currentTime: O, duration: k, togglePlay: A, seek: j, audioProps: M } = l(t), N = e.useRef(null), P = m(N), [F, I] = o(void 0), [L, R] = o(!1);
348
+ r(() => {
349
+ !n && E && t ? (async () => {
350
+ R(!0);
351
+ try {
352
+ I(await u(t, 512));
353
+ } catch (e) {
354
+ console.error("Auto-analysis failed", e);
355
+ } finally {
356
+ R(!1);
357
+ }
358
+ })() : I(void 0);
359
+ }, [
360
+ t,
361
+ n,
362
+ E
363
+ ]);
364
+ let z = n || F || [], B = p(z, i(() => typeof S == "number" ? S : P > 0 ? Math.max(1, Math.floor(P / (C + w))) : z.length || 1, [
365
+ S,
366
+ P,
367
+ C,
368
+ w,
369
+ z.length
370
+ ])), V = i(() => f || (T ? T.bg === "#ffffff" ? "#e5e7eb" : "#374151" : "#e5e7eb"), [f, T]), H = h || T?.primary || "#3b82f6", U = i(() => ({
371
+ "--wf-bg-color": T?.bg || "white",
372
+ "--wf-border-color": T?.border || "#f3f4f6",
373
+ "--wf-title-color": T?.text || "#111827",
374
+ "--wf-artist-color": T?.text || "#6b7280",
375
+ "--wf-time-color": T?.text || "#9ca3af",
376
+ "--wf-play-btn-bg": T?.primary || "#3b82f6",
377
+ "--wf-placeholder-from": T?.primary || "#fb923c",
378
+ "--wf-placeholder-to": T?.bg || "#ec4899",
379
+ ...x
380
+ }), [T, x]);
381
+ return /* @__PURE__ */ (0, _.jsxs)("div", {
382
+ className: `group relative flex flex-col md:flex-row items-center gap-6 p-6 bg-[var(--wf-bg-color,white)] border border-[var(--wf-border-color,#f3f4f6)] rounded-[var(--wf-rounded,1rem)] shadow-xl hover:shadow-2xl transition-all duration-300 overflow-hidden ${b}`,
383
+ style: U,
384
+ children: [
385
+ /* @__PURE__ */ (0, _.jsx)(v, {
386
+ artworkUrl: a,
387
+ title: s,
388
+ isPlaying: D,
389
+ onToggle: A,
390
+ isLoading: L
391
+ }),
392
+ /* @__PURE__ */ (0, _.jsxs)("div", {
393
+ className: "flex-1 w-full flex flex-col justify-between py-1",
394
+ children: [/* @__PURE__ */ (0, _.jsxs)("div", {
395
+ className: "mb-4",
396
+ children: [/* @__PURE__ */ (0, _.jsxs)("div", {
397
+ className: "flex items-center justify-between mb-1",
398
+ children: [s && /* @__PURE__ */ (0, _.jsx)("h3", {
399
+ className: "text-xl md:text-2xl font-black text-[var(--wf-title-color,#111827)] tracking-tight line-clamp-1",
400
+ children: s
401
+ }), /* @__PURE__ */ (0, _.jsxs)("div", {
402
+ className: "text-xs font-mono text-[var(--wf-time-color,#9ca3af)] tabular-nums",
403
+ children: [
404
+ d(O),
405
+ " / ",
406
+ d(k)
407
+ ]
408
+ })]
409
+ }), c && /* @__PURE__ */ (0, _.jsx)("p", {
410
+ className: "text-sm md:text-base font-medium text-[var(--wf-artist-color,#6b7280)] line-clamp-1 tracking-wide",
411
+ children: c
412
+ })]
413
+ }), /* @__PURE__ */ (0, _.jsx)("div", {
414
+ ref: N,
415
+ children: /* @__PURE__ */ (0, _.jsx)(y, {
416
+ peaks: B,
417
+ currentTime: O,
418
+ duration: k,
419
+ waveColor: V,
420
+ progressColor: H,
421
+ height: g,
422
+ onSeek: j,
423
+ resolution: S,
424
+ barWidth: C,
425
+ barGap: w
426
+ })
427
+ })]
428
+ }),
429
+ /* @__PURE__ */ (0, _.jsx)("audio", { ...M })
430
+ ]
431
+ });
432
+ });
433
+ b.displayName = "WaveframePlayer";
434
+ //#endregion
435
+ export { b as WaveframePlayer };
@@ -0,0 +1,6 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`)):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.Waveframe={},e.React))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),l=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),l(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);var u=e=>{let n=(0,t.useRef)(null),[r,i]=(0,t.useState)(!1),[a,o]=(0,t.useState)(0),[s,c]=(0,t.useState)(0);(0,t.useEffect)(()=>{n.current&&n.current.readyState>=1&&c(n.current.duration)},[e]);let l=(0,t.useCallback)(e=>{e?.stopPropagation(),n.current&&(r?n.current.pause():n.current.play().catch(console.error))},[r]),u=(0,t.useCallback)(()=>{n.current&&o(n.current.currentTime)},[]),d=(0,t.useCallback)(()=>{n.current&&c(n.current.duration)},[]);return{isPlaying:r,currentTime:a,duration:s,togglePlay:l,seek:(0,t.useCallback)(e=>{n.current&&s&&(n.current.currentTime=e*s)},[s]),audioProps:{ref:n,src:e,onTimeUpdate:u,onLoadedMetadata:d,onPlay:()=>i(!0),onPause:()=>i(!1),onEnded:()=>i(!1)}}},d=async(e,t=512)=>{let n=await(await fetch(e)).arrayBuffer(),r=(await new(window.AudioContext||window.webkitAudioContext)().decodeAudioData(n)).getChannelData(0),i=Math.floor(r.length/t),a=[];for(let e=0;e<t;e++){let t=0,n=e*i,o=n+i;for(let e=n;e<o;e++){let n=Math.abs(r[e]);n>t&&(t=n)}a.push(t)}let o=Math.max(...a);return a.map(e=>e/(o||1))},f=e=>isNaN(e)?`0:00`:`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,`0`)}`,p=(e,t)=>{if(e.length===0)return[];if(e.length===t)return e;let n=Array(t),r=e.length/t;if(r>1)for(let i=0;i<t;i++){let t=0,a=Math.floor(i*r),o=Math.floor((i+1)*r);for(let n=a;n<o;n++)e[n]>t&&(t=e[n]);n[i]=t}else for(let i=0;i<t;i++){let t=i*r,a=Math.floor(t),o=Math.min(a+1,e.length-1),s=t-a;n[i]=e[a]+(e[o]-e[a])*s}return n},m=(e,n)=>(0,t.useMemo)(()=>p(e,n),[e,n]),h=e=>{let[n,r]=(0,t.useState)(0);return(0,t.useEffect)(()=>{if(!e.current)return;let t=new ResizeObserver(e=>{for(let t of e)r(t.contentRect.width)});return t.observe(e.current),()=>t.disconnect()},[e]),n},g=c((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),_=c((e=>{process.env.NODE_ENV!==`production`&&(function(){function t(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===O?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case _:return`Fragment`;case y:return`Profiler`;case v:return`StrictMode`;case C:return`Suspense`;case w:return`SuspenseList`;case D:return`Activity`}if(typeof e==`object`)switch(typeof e.tag==`number`&&console.error(`Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.`),e.$$typeof){case g:return`Portal`;case x:return e.displayName||`Context`;case b:return(e._context.displayName||`Context`)+`.Consumer`;case S:var n=e.render;return e=e.displayName,e||=(e=n.displayName||n.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case T:return n=e.displayName||null,n===null?t(e.type)||`Memo`:n;case E:n=e._payload,e=e._init;try{return t(e(n))}catch{}}return null}function n(e){return``+e}function r(e){try{n(e);var t=!1}catch{t=!0}if(t){t=console;var r=t.error,i=typeof Symbol==`function`&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||`Object`;return r.call(t,`The provided key is an unsupported type %s. This value must be coerced to a string before using it here.`,i),n(e)}}function i(e){if(e===_)return`<>`;if(typeof e==`object`&&e&&e.$$typeof===E)return`<...>`;try{var n=t(e);return n?`<`+n+`>`:`<...>`}catch{return`<...>`}}function a(){var e=k.A;return e===null?null:e.getOwner()}function o(){return Error(`react-stack-top-frame`)}function s(e){if(A.call(e,`key`)){var t=Object.getOwnPropertyDescriptor(e,`key`).get;if(t&&t.isReactWarning)return!1}return e.key!==void 0}function c(e,t){function n(){N||(N=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",t))}n.isReactWarning=!0,Object.defineProperty(e,`key`,{get:n,configurable:!0})}function l(){var e=t(this.type);return P[e]||(P[e]=!0,console.error(`Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.`)),e=this.props.ref,e===void 0?null:e}function u(e,t,n,r,i,a){var o=n.ref;return e={$$typeof:h,type:e,key:t,props:n,_owner:r},(o===void 0?null:o)===null?Object.defineProperty(e,`ref`,{enumerable:!1,value:null}):Object.defineProperty(e,`ref`,{enumerable:!1,get:l}),e._store={},Object.defineProperty(e._store,`validated`,{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,`_debugInfo`,{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,`_debugStack`,{configurable:!1,enumerable:!1,writable:!0,value:i}),Object.defineProperty(e,`_debugTask`,{configurable:!1,enumerable:!1,writable:!0,value:a}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function d(e,n,i,o,l,d){var p=n.children;if(p!==void 0)if(o)if(j(p)){for(o=0;o<p.length;o++)f(p[o]);Object.freeze&&Object.freeze(p)}else console.error(`React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.`);else f(p);if(A.call(n,`key`)){p=t(e);var m=Object.keys(n).filter(function(e){return e!==`key`});o=0<m.length?`{key: someKey, `+m.join(`: ..., `)+`: ...}`:`{key: someKey}`,L[p+o]||(m=0<m.length?`{`+m.join(`: ..., `)+`: ...}`:`{}`,console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,o,p,m,p),L[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===E&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require(`react`),h=Symbol.for(`react.transitional.element`),g=Symbol.for(`react.portal`),_=Symbol.for(`react.fragment`),v=Symbol.for(`react.strict_mode`),y=Symbol.for(`react.profiler`),b=Symbol.for(`react.consumer`),x=Symbol.for(`react.context`),S=Symbol.for(`react.forward_ref`),C=Symbol.for(`react.suspense`),w=Symbol.for(`react.suspense_list`),T=Symbol.for(`react.memo`),E=Symbol.for(`react.lazy`),D=Symbol.for(`react.activity`),O=Symbol.for(`react.client.reference`),k=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,A=Object.prototype.hasOwnProperty,j=Array.isArray,M=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var N,P={},F=m.react_stack_bottom_frame.bind(m,o)(),I=M(i(o)),L={};e.Fragment=_,e.jsx=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)},e.jsxs=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)}})()})),v=c(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=g():t.exports=_()}))(),y=(0,t.memo)(({artworkUrl:e,title:t,isPlaying:n,onToggle:r,isLoading:i})=>(0,v.jsxs)(`div`,{className:`relative flex-shrink-0 w-32 h-32 md:w-40 md:h-40 overflow-hidden rounded-[var(--wf-artwork-rounded,0.75rem)] shadow-lg group/artwork`,children:[(0,v.jsx)(`div`,{className:`w-full h-full transition-all duration-700 ${i?`blur-md scale-110`:``}`,children:e?(0,v.jsx)(`img`,{src:e,alt:t,className:`w-full h-full object-cover transition-transform duration-500 group-hover/artwork:scale-110`}):(0,v.jsx)(`div`,{className:`w-full h-full bg-gradient-to-br from-[var(--wf-placeholder-from,#fb923c)] to-[var(--wf-placeholder-to,#ec4899)] flex items-center justify-center`,children:(0,v.jsx)(`svg`,{className:`w-16 h-16 text-white opacity-50`,fill:`currentColor`,viewBox:`0 0 24 24`,children:(0,v.jsx)(`path`,{d:`M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z`})})})}),i?(0,v.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center bg-black/10 backdrop-blur-[1px]`,children:(0,v.jsx)(`div`,{className:`w-8 h-8 border-4 border-white/30 border-t-white rounded-full animate-spin`})}):(0,v.jsx)(`button`,{className:`absolute inset-0 bg-[var(--wf-overlay-color,rgba(0,0,0,0.3))] backdrop-blur-[var(--wf-overlay-blur,2px)] opacity-0 group-hover/artwork:opacity-100 transition-opacity duration-300 flex items-center justify-center cursor-pointer border-none outline-none`,onClick:r,"aria-label":n?`Pause`:`Play`,children:(0,v.jsx)(`div`,{className:`w-14 h-14 flex items-center justify-center bg-[var(--wf-play-btn-bg,#f97316)] rounded-full text-[var(--wf-play-btn-color,white)] shadow-lg transform scale-90 group-hover/artwork:scale-100 transition-transform duration-300`,children:n?(0,v.jsx)(`svg`,{className:`w-8 h-8`,fill:`currentColor`,viewBox:`0 0 24 24`,children:(0,v.jsx)(`path`,{d:`M6 19h4V5H6v14zm8-14v14h4V5h-4z`})}):(0,v.jsx)(`svg`,{className:`w-8 h-8 ml-1`,fill:`currentColor`,viewBox:`0 0 24 24`,children:(0,v.jsx)(`path`,{d:`M8 5v14l11-7z`})})})})]}));y.displayName=`ArtworkOverlay`;var b=(0,t.memo)(({peaks:e,currentTime:n,duration:r,waveColor:i,progressColor:a,height:o,onSeek:s,resolution:c=`auto`,barWidth:l=2,barGap:u=1})=>{let d=(0,t.useRef)(null),f=(0,t.useRef)(null),p=(0,t.useRef)(null),m=h(p);(0,t.useEffect)(()=>{let t=d.current,n=f.current;if(!t||!n)return;let r=t.getContext(`2d`),o=n.getContext(`2d`);if(!r||!o)return;let s=window.devicePixelRatio||1,p=t.getBoundingClientRect(),m=p.width*s,h=p.height*s;[t,n].forEach(e=>{(e.width!==m||e.height!==h)&&(e.width=m,e.height=h)}),(()=>{if(e.length===0)return;let{width:n,height:d}=t;r.clearRect(0,0,n,d),o.clearRect(0,0,n,d);let f=n/e.length,p=typeof c==`number`?f*.7:l*s,m=typeof c==`number`?f*.3:u*s;r.lineCap=`round`,r.lineWidth=p,o.lineCap=`round`,o.lineWidth=p,e.forEach((e,t)=>{let n=t*(p+m)+p/2,s=e*d*.8,c=(d-s)/2,l=c+s;r.beginPath(),r.strokeStyle=i,r.moveTo(n,c),r.lineTo(n,l),r.stroke(),o.beginPath(),o.strokeStyle=a,o.moveTo(n,c),o.lineTo(n,l),o.stroke()})})()},[e,i,a,c,l,u,o]);let g=e=>{if(p.current&&r){let t=p.current.getBoundingClientRect(),n=e.clientX-t.left;s(Math.max(0,Math.min(1,n/t.width)))}},_=r?n/r*100:0;return(0,v.jsxs)(`div`,{ref:p,className:`relative w-full cursor-pointer overflow-hidden`,style:{height:`${o}px`},onClick:g,children:[(0,v.jsx)(`canvas`,{ref:d,className:`absolute inset-0 w-full h-full`}),(0,v.jsx)(`div`,{className:`absolute inset-0 h-full overflow-hidden transition-[width] duration-100 ease-linear pointer-events-none`,style:{width:`${_}%`},children:(0,v.jsx)(`canvas`,{ref:f,className:`absolute h-full`,style:{width:`${m}px`}})})]})});b.displayName=`Waveform`;var x=(0,t.memo)(({audioUrl:e,peaks:n,artworkUrl:r,title:i,artist:a,waveColor:o,progressColor:s,height:c=80,className:l=``,style:p,resolution:g=`auto`,barWidth:_=2,barGap:x=1,theme:S,autoAnalyze:C=!0})=>{let{isPlaying:w,currentTime:T,duration:E,togglePlay:D,seek:O,audioProps:k}=u(e),A=t.default.useRef(null),j=h(A),[M,N]=(0,t.useState)(void 0),[P,F]=(0,t.useState)(!1);(0,t.useEffect)(()=>{!n&&C&&e?(async()=>{F(!0);try{N(await d(e,512))}catch(e){console.error(`Auto-analysis failed`,e)}finally{F(!1)}})():N(void 0)},[e,n,C]);let I=n||M||[],L=m(I,(0,t.useMemo)(()=>typeof g==`number`?g:j>0?Math.max(1,Math.floor(j/(_+x))):I.length||1,[g,j,_,x,I.length])),R=(0,t.useMemo)(()=>o||(S?S.bg===`#ffffff`?`#e5e7eb`:`#374151`:`#e5e7eb`),[o,S]),z=s||S?.primary||`#3b82f6`,B=(0,t.useMemo)(()=>({"--wf-bg-color":S?.bg||`white`,"--wf-border-color":S?.border||`#f3f4f6`,"--wf-title-color":S?.text||`#111827`,"--wf-artist-color":S?.text||`#6b7280`,"--wf-time-color":S?.text||`#9ca3af`,"--wf-play-btn-bg":S?.primary||`#3b82f6`,"--wf-placeholder-from":S?.primary||`#fb923c`,"--wf-placeholder-to":S?.bg||`#ec4899`,...p}),[S,p]);return(0,v.jsxs)(`div`,{className:`group relative flex flex-col md:flex-row items-center gap-6 p-6 bg-[var(--wf-bg-color,white)] border border-[var(--wf-border-color,#f3f4f6)] rounded-[var(--wf-rounded,1rem)] shadow-xl hover:shadow-2xl transition-all duration-300 overflow-hidden ${l}`,style:B,children:[(0,v.jsx)(y,{artworkUrl:r,title:i,isPlaying:w,onToggle:D,isLoading:P}),(0,v.jsxs)(`div`,{className:`flex-1 w-full flex flex-col justify-between py-1`,children:[(0,v.jsxs)(`div`,{className:`mb-4`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between mb-1`,children:[i&&(0,v.jsx)(`h3`,{className:`text-xl md:text-2xl font-black text-[var(--wf-title-color,#111827)] tracking-tight line-clamp-1`,children:i}),(0,v.jsxs)(`div`,{className:`text-xs font-mono text-[var(--wf-time-color,#9ca3af)] tabular-nums`,children:[f(T),` / `,f(E)]})]}),a&&(0,v.jsx)(`p`,{className:`text-sm md:text-base font-medium text-[var(--wf-artist-color,#6b7280)] line-clamp-1 tracking-wide`,children:a})]}),(0,v.jsx)(`div`,{ref:A,children:(0,v.jsx)(b,{peaks:L,currentTime:T,duration:E,waveColor:R,progressColor:z,height:c,onSeek:O,resolution:g,barWidth:_,barGap:x})})]}),(0,v.jsx)(`audio`,{...k})]})});x.displayName=`WaveframePlayer`,e.WaveframePlayer=x});
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "waveframe",
3
+ "version": "0.1.0",
4
+ "description": "A customizable React audio player component with SoundCloud-style waveforms.",
5
+ "type": "module",
6
+ "main": "./dist/waveframe.umd.js",
7
+ "module": "./dist/waveframe.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/waveframe.es.js",
13
+ "require": "./dist/waveframe.umd.js"
14
+ },
15
+ "./style.css": "./dist/waveframe.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "keywords": [],
21
+ "author": "",
22
+ "license": "ISC",
23
+ "devDependencies": {
24
+ "@eslint/js": "^10.0.1",
25
+ "@tailwindcss/postcss": "^4.3.0",
26
+ "@tailwindcss/vite": "^4.3.0",
27
+ "@testing-library/jest-dom": "^6.9.1",
28
+ "@testing-library/react": "^16.3.2",
29
+ "@types/react": "^19.2.14",
30
+ "@types/react-dom": "^19.2.3",
31
+ "@typescript-eslint/eslint-plugin": "^8.59.2",
32
+ "@typescript-eslint/parser": "^8.59.2",
33
+ "@vitejs/plugin-react": "^6.0.1",
34
+ "autoprefixer": "^10.5.0",
35
+ "cross-env": "^10.1.0",
36
+ "eslint": "^10.3.0",
37
+ "eslint-config-prettier": "^10.1.8",
38
+ "eslint-plugin-prettier": "^5.5.5",
39
+ "eslint-plugin-react": "^7.37.5",
40
+ "eslint-plugin-react-hooks": "^7.1.1",
41
+ "eslint-plugin-react-refresh": "^0.5.2",
42
+ "globals": "^17.6.0",
43
+ "jsdom": "^29.1.1",
44
+ "postcss": "^8.5.14",
45
+ "prettier": "^3.8.3",
46
+ "react": "^19.2.6",
47
+ "react-dom": "^19.2.6",
48
+ "tailwindcss": "^4.3.0",
49
+ "tsc-alias": "^1.8.17",
50
+ "typescript": "^6.0.3",
51
+ "vite": "^8.0.11",
52
+ "vite-plugin-dts": "^5.0.0",
53
+ "vitest": "^4.1.5"
54
+ },
55
+ "peerDependencies": {
56
+ "react": "^19.0.0",
57
+ "react-dom": "^19.0.0"
58
+ },
59
+ "scripts": {
60
+ "dev": "vite",
61
+ "build": "pnpm run build:lib && pnpm run build:app",
62
+ "build:lib": "tsc && vite build",
63
+ "build:app": "tsc && cross-env BUILD_MODE=app vite build",
64
+ "preview": "vite preview",
65
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
66
+ "lint:fix": "eslint . --ext ts,tsx --fix",
67
+ "format": "prettier --write \"src/**/*.{ts,tsx,css,md}\"",
68
+ "test": "vitest",
69
+ "type-check": "tsc --noEmit"
70
+ }
71
+ }