@lucaismyname/ginger 0.0.43 → 0.0.44
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/dist/analyzer/useGingerLiveAnalyzer.d.ts.map +1 -1
- package/dist/audio/GingerPlayer.d.ts.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +2 -2
- package/dist/context/GingerProvider.d.ts.map +1 -1
- package/dist/ginger-9lWCvbHv.cjs +2 -0
- package/dist/ginger-9lWCvbHv.cjs.map +1 -0
- package/dist/{ginger-B2DgE-2a.js → ginger-XgXdGRB-.js} +287 -294
- package/dist/ginger-XgXdGRB-.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/useGingerChapterProgress-Cqa9_CyH.cjs +2 -0
- package/dist/useGingerChapterProgress-Cqa9_CyH.cjs.map +1 -0
- package/dist/useGingerChapterProgress-DgqqoY5F.js +324 -0
- package/dist/useGingerChapterProgress-DgqqoY5F.js.map +1 -0
- package/package.json +1 -1
- package/dist/ginger-B2DgE-2a.js.map +0 -1
- package/dist/ginger-Dv3iO_xQ.cjs +0 -2
- package/dist/ginger-Dv3iO_xQ.cjs.map +0 -1
- package/dist/useGingerChapterProgress-D2pdmyjg.cjs +0 -2
- package/dist/useGingerChapterProgress-D2pdmyjg.cjs.map +0 -1
- package/dist/useGingerChapterProgress-wxAmN_uo.js +0 -323
- package/dist/useGingerChapterProgress-wxAmN_uo.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ginger-Dv3iO_xQ.cjs","sources":["../src/context/GingerContext.tsx","../src/audio/GingerPlayer.tsx","../src/context/GingerLocaleContext.tsx","../src/internal/formatTime.ts","../src/hooks/useControlBindings.ts","../src/components/icons/Wrapper.tsx","../src/components/icons/Pause.tsx","../src/components/icons/Play.tsx","../src/components/icons/RepeatGlyph.tsx","../src/components/icons/ShuffleIcon.tsx","../src/components/icons/SkipBack.tsx","../src/components/icons/SkipForward.tsx","../src/components/icons/Volume2.tsx","../src/components/icons/VolumeX.tsx","../src/components/controls/Controls.tsx","../src/components/current/createTextDisplay.tsx","../src/components/current/texts.ts","../src/components/current/Year.tsx","../src/components/current/Lyrics.tsx","../src/internal/lyrics.ts","../src/hooks/useGingerLyricsSync.ts","../src/components/current/LyricsSynced.tsx","../src/hooks/useGingerChapters.ts","../src/components/current/Chapters.tsx","../src/components/current/FileUrl.tsx","../src/components/current/Artwork.tsx","../src/components/current/QueueMeta.tsx","../src/components/current/Time.tsx","../src/components/current/Playback.tsx","../src/components/playlist/GingerPlaylist.tsx","../src/components/queue/QueueDisplay.tsx","../src/core/playbackReducer.ts","../src/media/useMediaSession.ts","../src/context/GingerProvider.tsx","../src/ginger.ts"],"sourcesContent":["import { type Dispatch, type MutableRefObject, createContext, useContext } from \"react\";\nimport type {\n GingerAction,\n GingerInitPayload,\n GingerState,\n PlaybackMode,\n PlaylistMeta,\n RepeatMode,\n Track,\n} from \"../types\";\n\nexport type GingerContextValue = {\n state: GingerState;\n dispatch: Dispatch<GingerAction>;\n audioRef: MutableRefObject<HTMLAudioElement | null>;\n notifyEnded: () => void;\n /** Full reset to match `createInitialState` / provider `initial*` props. */\n init: (payload: GingerInitPayload) => void;\n play: () => void;\n pause: () => void;\n togglePlayPause: () => void;\n seek: (timeSeconds: number) => void;\n setVolume: (volume: number) => void;\n setMuted: (muted: boolean) => void;\n toggleMute: () => void;\n setPlaybackRate: (rate: number) => void;\n next: () => void;\n prev: () => void;\n setRepeatMode: (mode: RepeatMode) => void;\n cycleRepeat: () => void;\n toggleShuffle: () => void;\n setQueue: (tracks: Track[], currentIndex?: number) => void;\n insertTrackAt: (track: Track, index?: number, autoPlay?: boolean) => void;\n removeTrackAt: (index: number) => void;\n moveTrack: (fromIndex: number, toIndex: number) => void;\n enqueueNext: (track: Track) => void;\n playTrackAt: (index: number) => void;\n selectTrackAt: (index: number) => void;\n setPlaylistMeta: (meta: PlaylistMeta | null) => void;\n setPlaybackMode: (mode: PlaybackMode) => void;\n};\n\nconst GingerContext = createContext<GingerContextValue | null>(null);\n\nexport function useGingerContext(): GingerContextValue {\n const ctx = useContext(GingerContext);\n if (!ctx) throw new Error(\"Ginger components must be used within <Ginger.Provider>\");\n return ctx;\n}\n\nexport { GingerContext };\n","import { type AudioHTMLAttributes, type CSSProperties, useEffect, useRef, useState } from \"react\";\nimport { useGingerContext } from \"../context/GingerContext\";\n\nexport type GingerPlayerProps = {\n className?: string;\n style?: CSSProperties;\n preload?: AudioHTMLAttributes<HTMLAudioElement>[\"preload\"];\n crossOrigin?: AudioHTMLAttributes<HTMLAudioElement>[\"crossOrigin\"];\n respectReducedMotion?: boolean;\n};\n\nfunction readBufferedFraction(el: HTMLAudioElement): number {\n const { buffered, duration } = el;\n if (!(duration > 0) || buffered.length === 0) return 0;\n return Math.min(1, buffered.end(buffered.length - 1) / duration);\n}\n\nexport function GingerPlayer({\n className,\n style,\n preload = \"metadata\",\n crossOrigin,\n respectReducedMotion = false,\n}: GingerPlayerProps) {\n const { audioRef, dispatch, state, notifyEnded } = useGingerContext();\n const url = state.tracks[state.currentIndex]?.fileUrl ?? \"\";\n const lastTimeSnapshotRef = useRef({\n currentTime: -1,\n duration: -1,\n bufferedFraction: -1,\n });\n /** Avoid MEDIA_SOURCE_CLEARED on first paint with an empty queue (no prior media). */\n const lastActiveUrlRef = useRef(\"\");\n\n const [reducedMotion, setReducedMotion] = useState(false);\n\n useEffect(() => {\n if (!respectReducedMotion || typeof window === \"undefined\") return;\n const mql = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const sync = () => setReducedMotion(mql.matches);\n sync();\n mql.addEventListener(\"change\", sync);\n return () => mql.removeEventListener(\"change\", sync);\n }, [respectReducedMotion]);\n\n const syncTime = (el: HTMLAudioElement, force = false) => {\n const next = {\n currentTime: el.currentTime,\n duration: el.duration,\n bufferedFraction: readBufferedFraction(el),\n };\n const prev = lastTimeSnapshotRef.current;\n const timeThreshold = reducedMotion ? 0.5 : 0.25;\n const changedEnough =\n Math.abs(next.currentTime - prev.currentTime) >= timeThreshold ||\n Math.abs(next.duration - prev.duration) >= 0.01 ||\n Math.abs(next.bufferedFraction - prev.bufferedFraction) >= 0.01;\n if (!force && !changedEnough) return;\n lastTimeSnapshotRef.current = next;\n dispatch({\n type: \"MEDIA_TIME_UPDATE\",\n payload: next,\n });\n };\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n el.volume = state.volume;\n el.muted = state.muted;\n }, [audioRef, state.volume, state.muted]);\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n if (!url) {\n el.removeAttribute(\"src\");\n lastTimeSnapshotRef.current = { currentTime: -1, duration: -1, bufferedFraction: -1 };\n if (lastActiveUrlRef.current !== \"\") {\n dispatch({ type: \"MEDIA_SOURCE_CLEARED\" });\n }\n lastActiveUrlRef.current = \"\";\n return;\n }\n if (el.getAttribute(\"src\") !== url) {\n el.src = url;\n el.load();\n lastTimeSnapshotRef.current = { currentTime: -1, duration: -1, bufferedFraction: -1 };\n }\n lastActiveUrlRef.current = url;\n }, [audioRef, dispatch, state.currentIndex, state.tracks, url]);\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n // Browsers reset playbackRate to 1.0 when source changes + load() runs.\n el.playbackRate = state.playbackRate;\n }, [audioRef, state.playbackRate, url]);\n\n return (\n <audio\n data-ginger-component=\"Player\"\n ref={audioRef}\n className={className}\n style={style}\n preload={preload}\n crossOrigin={crossOrigin}\n controls={false}\n playsInline\n onTimeUpdate={(e) => {\n syncTime(e.currentTarget);\n }}\n onLoadedMetadata={(e) => {\n const el = e.currentTarget;\n lastTimeSnapshotRef.current = { currentTime: -1, duration: -1, bufferedFraction: -1 };\n dispatch({\n type: \"MEDIA_LOADED_METADATA\",\n payload: {\n duration: el.duration,\n bufferedFraction: readBufferedFraction(el),\n },\n });\n }}\n onSeeking={(e) => syncTime(e.currentTarget, true)}\n onSeeked={(e) => syncTime(e.currentTarget, true)}\n onEnded={() => notifyEnded()}\n onPlay={() => dispatch({ type: \"MEDIA_PLAY\" })}\n onPause={() => dispatch({ type: \"MEDIA_PAUSE\" })}\n onWaiting={() => dispatch({ type: \"MEDIA_WAITING\" })}\n onCanPlay={() => dispatch({ type: \"MEDIA_CANPLAY\" })}\n onProgress={(e) => syncTime(e.currentTarget, true)}\n onVolumeChange={(e) => {\n const el = e.currentTarget;\n dispatch({\n type: \"MEDIA_VOLUME_SYNC\",\n payload: { volume: el.volume, muted: el.muted },\n });\n }}\n onError={() => {\n const el = audioRef.current;\n const code = el?.error?.code;\n const message =\n code === 1\n ? \"MEDIA_ERR_ABORTED\"\n : code === 2\n ? \"MEDIA_ERR_NETWORK\"\n : code === 3\n ? \"MEDIA_ERR_DECODE\"\n : code === 4\n ? \"MEDIA_ERR_SRC_NOT_SUPPORTED\"\n : \"MEDIA_ERR_UNKNOWN\";\n dispatch({ type: \"MEDIA_ERROR\", payload: { message } });\n }}\n />\n );\n}\n","import { type ReactNode, createContext, useContext } from \"react\";\nimport type { GingerLocaleMessages } from \"../types\";\n\nexport const defaultGingerLocale: GingerLocaleMessages = {\n seek: \"Seek\",\n volume: \"Volume\",\n playbackSpeed: \"Playback speed\",\n chaptersList: \"Chapters\",\n syncedLyricsList: \"Synced lyrics\",\n nextTrack: \"Next track\",\n previousTrack: \"Previous track\",\n shuffle: \"Shuffle\",\n mute: \"Mute\",\n unmute: \"Unmute\",\n play: \"Play\",\n pause: \"Pause\",\n repeat: {\n off: \"Repeat off\",\n all: \"Repeat all\",\n one: \"Repeat one\",\n },\n playbackRateNormal: \"1× normal\",\n playbackRateTimes: (rate) => `${rate}×`,\n};\n\nfunction mergeLocale(partial?: Partial<GingerLocaleMessages>): GingerLocaleMessages {\n if (!partial) return defaultGingerLocale;\n return {\n ...defaultGingerLocale,\n ...partial,\n repeat: { ...defaultGingerLocale.repeat, ...partial.repeat },\n };\n}\n\nconst GingerLocaleContext = createContext<GingerLocaleMessages>(defaultGingerLocale);\n\nexport function GingerLocaleProvider({\n locale,\n children,\n}: {\n locale?: Partial<GingerLocaleMessages>;\n children: ReactNode;\n}) {\n const value = mergeLocale(locale);\n return <GingerLocaleContext.Provider value={value}>{children}</GingerLocaleContext.Provider>;\n}\n\nexport function useGingerLocale(): GingerLocaleMessages {\n return useContext(GingerLocaleContext);\n}\n","export function formatMmSs(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return \"0:00\";\n const s = Math.floor(seconds % 60);\n const m = Math.floor(seconds / 60);\n return `${m}:${s.toString().padStart(2, \"0\")}`;\n}\n","import { useMemo } from \"react\";\nimport type { FormEvent } from \"react\";\nimport { useGingerLocale } from \"../context/GingerLocaleContext\";\nimport {\n gingerStateFromContextValues,\n useGingerMedia,\n useGingerPlayback,\n} from \"../context/GingerSplitContexts\";\nimport { formatMmSs } from \"../internal/formatTime\";\nimport { effectiveDuration } from \"../internal/selectors\";\nimport type { GingerState } from \"../types\";\n\nexport type SeekBarBinding = {\n state: GingerState;\n value: number;\n min: number;\n max: number;\n step: \"any\";\n ariaValueText: string;\n ariaLabel: string;\n onSeekInput: (e: FormEvent<HTMLInputElement>) => void;\n onSeekChange: (e: FormEvent<HTMLInputElement>) => void;\n};\n\n/** Headless seek slider: bind return value to `<input type=\"range\" />` or your own component. */\nexport function useSeekBarBinding(): SeekBarBinding {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n const locale = useGingerLocale();\n const state = useMemo(() => gingerStateFromContextValues(pb, md), [pb, md]);\n const duration = effectiveDuration(state);\n const value = duration > 0 ? state.currentTime : 0;\n const numericValue = Number.isFinite(value) ? value : 0;\n const ariaValueText =\n duration > 0\n ? `${formatMmSs(numericValue)} of ${formatMmSs(duration)}`\n : formatMmSs(numericValue);\n\n const onSeekInput = (e: FormEvent<HTMLInputElement>) => {\n md.seek(Number(e.currentTarget.value));\n };\n\n return {\n state,\n value: numericValue,\n min: 0,\n max: duration > 0 ? duration : 1,\n step: \"any\",\n ariaValueText,\n ariaLabel: locale.seek,\n onSeekInput,\n onSeekChange: onSeekInput,\n };\n}\n\nexport type VolumeBinding = {\n state: GingerState;\n value: number;\n min: number;\n max: number;\n step: \"any\";\n ariaValueText: string;\n ariaLabel: string;\n onVolumeInput: (e: FormEvent<HTMLInputElement>) => void;\n onVolumeChange: (e: FormEvent<HTMLInputElement>) => void;\n};\n\n/** Headless volume slider. */\nexport function useVolumeSlider(): VolumeBinding {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n const locale = useGingerLocale();\n const state = useMemo(() => gingerStateFromContextValues(pb, md), [pb, md]);\n\n const onVolumeInput = (e: FormEvent<HTMLInputElement>) => {\n md.setVolume(Number(e.currentTarget.value));\n };\n\n return {\n state,\n value: state.volume,\n min: 0,\n max: 1,\n step: \"any\",\n ariaValueText: `${Math.round(state.volume * 100)}%`,\n ariaLabel: locale.volume,\n onVolumeInput,\n onVolumeChange: onVolumeInput,\n };\n}\n\nexport type PlayPauseBinding = {\n isPaused: boolean;\n toggle: () => void;\n /** Resolved aria label for the button’s *next* action (play vs pause). */\n ariaLabel: string;\n};\n\n/** Headless play/pause control; use with `playAriaLabel` / `pauseAriaLabel` from locale or custom strings. */\nexport function usePlayPauseBinding(options?: {\n playAriaLabel?: string;\n pauseAriaLabel?: string;\n}): PlayPauseBinding {\n const pb = useGingerPlayback();\n const locale = useGingerLocale();\n const playL = options?.playAriaLabel ?? locale.play;\n const pauseL = options?.pauseAriaLabel ?? locale.pause;\n return {\n isPaused: pb.isPaused,\n toggle: pb.togglePlayPause,\n ariaLabel: pb.isPaused ? playL : pauseL,\n };\n}\n","import type { ReactNode, SVGProps } from \"react\";\n\nexport function Wrapper(\n props: SVGProps<SVGSVGElement> & {\n className?: string;\n width?: number;\n height?: number;\n viewBox?: string;\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n strokeLinecap?: string;\n strokeLinejoin?: string;\n children?: ReactNode;\n },\n) {\n const {\n className,\n width,\n height,\n viewBox,\n fill,\n stroke,\n strokeWidth,\n strokeLinecap,\n strokeLinejoin,\n children,\n ...rest\n } = props;\n return (\n <svg\n data-ginger-component=\"Wrapper\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width={width ?? 24}\n height={height ?? 24}\n viewBox={viewBox ?? \"0 0 24 24\"}\n fill=\"none\"\n stroke={stroke ?? \"currentColor\"}\n strokeWidth={strokeWidth ?? 2}\n strokeLinecap={strokeLinecap ?? \"round\"}\n strokeLinejoin={strokeLinejoin ?? \"round\"}\n className={className}\n aria-hidden\n role=\"presentation\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n","/** Path style aligned with Lucide `pause` (stroke). */\nimport { Wrapper } from \"./Wrapper\";\n\nexport function Pause() {\n return (\n <Wrapper>\n <path data-ginger-component=\"Pause\" d=\"M6 4h4v16H6zM14 4h4v16h-4z\" />\n </Wrapper>\n );\n}\n","/** Path style aligned with Lucide `play` (stroke). */\nimport { Wrapper } from \"./Wrapper\";\nexport function Play() {\n return (\n <Wrapper>\n <path data-ginger-component=\"Play\" d=\"M5 3L19 12 5 21 5 3z\" />\n </Wrapper>\n );\n}\n","/**\n * Path data from lucide-static (ISC, Lucide Icons). `off` uses the repeat glyph plus a strike line\n * (Lucide does not ship a dedicated repeat-off asset in lucide-static).\n */\nimport type { RepeatMode } from \"../../types\";\nimport { Wrapper } from \"./Wrapper\";\n\nfunction RepeatAllPaths() {\n return (\n <>\n <path d=\"m17 2 4 4-4 4\" />\n <path d=\"M3 11v-1a4 4 0 0 1 4-4h14\" />\n <path d=\"m7 22-4-4 4-4\" />\n <path d=\"M21 13v1a4 4 0 0 1-4 4H3\" />\n </>\n );\n}\n\nexport function RepeatGlyph({ mode }: { mode: RepeatMode }) {\n if (mode === \"one\") {\n return (\n <Wrapper>\n <RepeatAllPaths />\n <path data-ginger-component=\"RepeatGlyph\" d=\"M11 10h1v4\" />\n </Wrapper>\n );\n }\n if (mode === \"all\") {\n return (\n <Wrapper>\n <RepeatAllPaths />\n </Wrapper>\n );\n }\n return (\n <Wrapper>\n <RepeatAllPaths />\n <line data-ginger-component=\"RepeatGlyph\" x1=\"3\" x2=\"21\" y1=\"3\" y2=\"21\" />\n </Wrapper>\n );\n}\n","/** Path data from lucide-static (ISC, Lucide Icons). */\nimport { Wrapper } from \"./Wrapper\";\n\nexport function ShuffleIcon() {\n return (\n <Wrapper>\n <path d=\"m18 14 4 4-4 4\" />\n <path d=\"m18 2 4 4-4 4\" />\n <path\n data-ginger-component=\"ShuffleIcon\"\n d=\"M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22\"\n />\n <path d=\"M2 6h1.972a4 4 0 0 1 3.6 2.2\" />\n <path d=\"M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45\" />\n </Wrapper>\n );\n}\n","/** Path data from lucide-static (ISC, Lucide Icons). */\nimport { Wrapper } from \"./Wrapper\";\n\nexport function SkipBack() {\n return (\n <Wrapper>\n <path\n data-ginger-component=\"SkipBack\"\n d=\"M17.971 4.285A2 2 0 0 1 21 6v12a2 2 0 0 1-3.029 1.715l-9.997-5.998a2 2 0 0 1-.003-3.432z\"\n />\n <path d=\"M3 20V4\" />\n </Wrapper>\n );\n}\n","/** Path data from lucide-static (ISC, Lucide Icons). */\nimport { Wrapper } from \"./Wrapper\";\n\nexport function SkipForward() {\n return (\n <Wrapper>\n <path d=\"M21 4v16\" />\n <path\n data-ginger-component=\"SkipForward\"\n d=\"M6.029 4.285A2 2 0 0 0 3 6v12a2 2 0 0 0 3.029 1.715l9.997-5.998a2 2 0 0 0 .003-3.432z\"\n />\n </Wrapper>\n );\n}\n","/** Path data from lucide-static (ISC, Lucide Icons). */\nimport { Wrapper } from \"./Wrapper\";\n\nexport function Volume2() {\n return (\n <Wrapper>\n <path\n data-ginger-component=\"Volume2\"\n d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\"\n />\n <path d=\"M16 9a5 5 0 0 1 0 6\" />\n <path d=\"M19.364 18.364a9 9 0 0 0 0-12.728\" />\n </Wrapper>\n );\n}\n","/** Path data from lucide-static (ISC, Lucide Icons). */\nimport { Wrapper } from \"./Wrapper\";\n\nexport function VolumeX() {\n return (\n <Wrapper>\n <path\n data-ginger-component=\"VolumeX\"\n d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\"\n />\n <line x1=\"22\" x2=\"16\" y1=\"9\" y2=\"15\" />\n <line x1=\"16\" x2=\"22\" y1=\"9\" y2=\"15\" />\n </Wrapper>\n );\n}\n","import { useMemo } from \"react\";\nimport type {\n ButtonHTMLAttributes,\n CSSProperties,\n InputHTMLAttributes,\n ReactNode,\n SelectHTMLAttributes,\n} from \"react\";\nimport { useGingerLocale } from \"../../context/GingerLocaleContext\";\nimport { useGingerMedia, useGingerPlayback } from \"../../context/GingerSplitContexts\";\nimport {\n usePlayPauseBinding,\n useSeekBarBinding,\n useVolumeSlider,\n} from \"../../hooks/useControlBindings\";\nimport {\n Pause,\n Play,\n RepeatGlyph,\n ShuffleIcon,\n SkipBack,\n SkipForward,\n Volume2,\n VolumeX,\n} from \"../icons\";\n\nexport type PlayPauseProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n /** When `children` is omitted, defaults are Lucide-style icons; string labels feed `playAriaLabel` / `pauseAriaLabel` fallbacks. */\n playLabel?: ReactNode;\n pauseLabel?: ReactNode;\n /** Screen-reader label when paused (playing would start); defaults to match `playLabel` when it is a string */\n playAriaLabel?: string;\n /** Screen-reader label when playing (action would pause); defaults to match `pauseLabel` when it is a string */\n pauseAriaLabel?: string;\n children?: ReactNode;\n};\n\nexport function PlayPause({\n playLabel = \"Play\",\n pauseLabel = \"Pause\",\n playAriaLabel,\n pauseAriaLabel,\n children,\n type = \"button\",\n onClick,\n ...rest\n}: PlayPauseProps) {\n const locale = useGingerLocale();\n const defaultPlayAria = typeof playLabel === \"string\" ? playLabel : locale.play;\n const defaultPauseAria = typeof pauseLabel === \"string\" ? pauseLabel : locale.pause;\n const b = usePlayPauseBinding({\n playAriaLabel: playAriaLabel ?? defaultPlayAria,\n pauseAriaLabel: pauseAriaLabel ?? defaultPauseAria,\n });\n return (\n <button\n data-ginger-component=\"PlayPause\"\n {...rest}\n type={type}\n aria-label={b.ariaLabel}\n onClick={(e) => {\n b.toggle();\n onClick?.(e);\n }}\n >\n {children ?? (b.isPaused ? <Play /> : <Pause />)}\n </button>\n );\n}\n\nPlayPause.displayName = \"Ginger.Control.PlayPause\";\n\nexport type RepeatProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n ariaLabel?: string;\n children?: ReactNode;\n};\n\nexport function Repeat({ type = \"button\", ariaLabel, onClick, children, ...rest }: RepeatProps) {\n const { repeatMode, cycleRepeat } = useGingerPlayback();\n const locale = useGingerLocale();\n const label = locale.repeat[repeatMode];\n return (\n <button\n data-ginger-component=\"Repeat\"\n {...rest}\n type={type}\n aria-label={ariaLabel ?? label}\n onClick={(e) => {\n cycleRepeat();\n onClick?.(e);\n }}\n >\n {children ?? <RepeatGlyph mode={repeatMode} />}\n </button>\n );\n}\n\nRepeat.displayName = \"Ginger.Control.Repeat\";\n\nexport type NextProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n ariaLabel?: string;\n};\nexport function Next({ type = \"button\", children, ariaLabel, onClick, ...rest }: NextProps) {\n const { next } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button\n data-ginger-component=\"Next\"\n {...rest}\n type={type}\n aria-label={ariaLabel ?? locale.nextTrack}\n onClick={(e) => {\n next();\n onClick?.(e);\n }}\n >\n {children ?? <SkipForward />}\n </button>\n );\n}\nNext.displayName = \"Ginger.Control.Next\";\n\nexport type PreviousProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n ariaLabel?: string;\n};\nexport function Previous({\n type = \"button\",\n children,\n ariaLabel,\n onClick,\n ...rest\n}: PreviousProps) {\n const { prev } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button\n data-ginger-component=\"Previous\"\n {...rest}\n type={type}\n aria-label={ariaLabel ?? locale.previousTrack}\n onClick={(e) => {\n prev();\n onClick?.(e);\n }}\n >\n {children ?? <SkipBack />}\n </button>\n );\n}\nPrevious.displayName = \"Ginger.Control.Previous\";\n\nexport type ShuffleProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n ariaLabel?: string;\n};\nexport function Shuffle({ type = \"button\", children, ariaLabel, onClick, ...rest }: ShuffleProps) {\n const { isShuffled, toggleShuffle } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button\n data-ginger-component=\"Shuffle\"\n {...rest}\n type={type}\n aria-pressed={isShuffled}\n aria-label={ariaLabel ?? locale.shuffle}\n onClick={(e) => {\n toggleShuffle();\n onClick?.(e);\n }}\n >\n {children ?? <ShuffleIcon />}\n </button>\n );\n}\nShuffle.displayName = \"Ginger.Control.Shuffle\";\n\nexport type SeekBarProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"value\" | \"onChange\" | \"onInput\" | \"min\" | \"max\" | \"step\"\n> & {\n /** Remove default width style for fully custom styling. */\n unstyled?: boolean;\n ariaLabel?: string;\n inputStyle?: CSSProperties;\n};\n\nexport function SeekBar({ inputStyle, style, unstyled = false, ariaLabel, ...rest }: SeekBarProps) {\n const b = useSeekBarBinding();\n const mergedStyle = unstyled\n ? { ...style, ...inputStyle }\n : { width: \"100%\", ...style, ...inputStyle };\n return (\n <input\n data-ginger-component=\"SeekBar\"\n {...rest}\n type=\"range\"\n min={b.min}\n max={b.max}\n step={b.step}\n value={b.value}\n aria-label={ariaLabel ?? b.ariaLabel}\n aria-valuetext={b.ariaValueText}\n onInput={b.onSeekInput}\n onChange={b.onSeekChange}\n style={mergedStyle}\n />\n );\n}\n\nSeekBar.displayName = \"Ginger.Control.SeekBar\";\n\nexport type VolumeProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"value\" | \"onChange\" | \"onInput\" | \"min\" | \"max\" | \"step\"\n> & {\n /** Remove default width style for fully custom styling. */\n unstyled?: boolean;\n ariaLabel?: string;\n inputStyle?: CSSProperties;\n};\n\nexport function Volume({ inputStyle, style, unstyled = false, ariaLabel, ...rest }: VolumeProps) {\n const b = useVolumeSlider();\n const mergedStyle = unstyled\n ? { ...style, ...inputStyle }\n : { width: \"100%\", ...style, ...inputStyle };\n return (\n <input\n data-ginger-component=\"Volume\"\n {...rest}\n type=\"range\"\n min={b.min}\n max={b.max}\n step={b.step}\n value={b.value}\n aria-label={ariaLabel ?? b.ariaLabel}\n aria-valuetext={b.ariaValueText}\n onInput={b.onVolumeInput}\n onChange={b.onVolumeChange}\n style={mergedStyle}\n />\n );\n}\n\nVolume.displayName = \"Ginger.Control.Volume\";\n\nexport type MuteProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n ariaLabel?: string;\n muteLabel?: ReactNode;\n unmuteLabel?: ReactNode;\n children?: ReactNode;\n};\n\nexport function Mute({\n ariaLabel,\n muteLabel,\n unmuteLabel,\n type = \"button\",\n onClick,\n children,\n ...rest\n}: MuteProps) {\n const { muted, toggleMute } = useGingerMedia();\n const locale = useGingerLocale();\n return (\n <button\n data-ginger-component=\"Mute\"\n {...rest}\n type={type}\n aria-pressed={muted}\n aria-label={ariaLabel ?? (muted ? locale.unmute : locale.mute)}\n onClick={(e) => {\n toggleMute();\n onClick?.(e);\n }}\n >\n {children ?? (muted ? (unmuteLabel ?? <VolumeX />) : (muteLabel ?? <Volume2 />))}\n </button>\n );\n}\n\nMute.displayName = \"Ginger.Control.Mute\";\n\nconst defaultRates = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport type PlaybackRateProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n \"value\" | \"onChange\"\n> & {\n /** Playback speed options (default: 0.5 … 2) */\n rates?: readonly number[];\n ariaLabel?: string;\n children?: ReactNode;\n};\n\nexport function PlaybackRate({\n rates = defaultRates,\n style,\n ariaLabel,\n children,\n ...rest\n}: PlaybackRateProps) {\n const { playbackRate, setPlaybackRate } = useGingerMedia();\n const locale = useGingerLocale();\n const options = useMemo(\n () => Array.from(new Set([...rates, playbackRate])).sort((a, b) => a - b),\n [rates, playbackRate],\n );\n return (\n <select\n data-ginger-component=\"PlaybackRate\"\n {...rest}\n aria-label={ariaLabel ?? locale.playbackSpeed}\n value={String(playbackRate)}\n style={style}\n onChange={(e) => setPlaybackRate(Number(e.currentTarget.value))}\n >\n {children ??\n options.map((r) => (\n <option key={r} value={String(r)}>\n {r === 1 ? locale.playbackRateNormal : locale.playbackRateTimes(r)}\n </option>\n ))}\n </select>\n );\n}\n\nPlaybackRate.displayName = \"Ginger.Control.PlaybackRate\";\n","import type { ReactElement, ReactNode } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\nimport type { DisplayBaseProps, GingerState, Track } from \"../../types\";\n\nexport type TextDisplayProps = DisplayBaseProps & {\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function createTextDisplay(\n displayName: string,\n select: (state: GingerState) => string | undefined,\n): (props: TextDisplayProps) => ReactElement | null {\n function Comp(props: TextDisplayProps) {\n const state = useGingerState();\n const raw = select(state) ?? \"\";\n const value = raw.trim();\n const { className, style, fallback, empty, children } = props;\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n if (children)\n return (\n <span className={className} style={style}>\n {children(value, state)}\n </span>\n );\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n }\n Comp.displayName = displayName;\n return Comp;\n}\n\nexport function createTrackFieldDisplay(\n displayName: string,\n select: (track: Track | null) => string | undefined,\n): (props: TextDisplayProps) => ReactElement | null {\n return createTextDisplay(displayName, (state) => select(getCurrentTrack(state)));\n}\n","import { getCurrentTrack, resolvedAlbumLine } from \"../../internal/selectors\";\nimport { createTextDisplay, createTrackFieldDisplay } from \"./createTextDisplay\";\n\nexport const Title = createTrackFieldDisplay(\"Ginger.Current.Title\", (t) => t?.title);\nexport const Artist = createTrackFieldDisplay(\"Ginger.Current.Artist\", (t) => t?.artist);\nexport const Album = createTextDisplay(\"Ginger.Current.Album\", (s) => resolvedAlbumLine(s));\nexport const Description = createTrackFieldDisplay(\n \"Ginger.Current.Description\",\n (t) => t?.description,\n);\nexport const Copyright = createTextDisplay(\"Ginger.Current.Copyright\", (s) => {\n const t = getCurrentTrack(s);\n return t?.copyright ?? s.playlistMeta?.copyright;\n});\nexport const Genre = createTrackFieldDisplay(\"Ginger.Current.Genre\", (t) => t?.genre);\nexport const Label = createTrackFieldDisplay(\"Ginger.Current.Label\", (t) => t?.label);\nexport const Isrc = createTrackFieldDisplay(\"Ginger.Current.Isrc\", (t) => t?.isrc);\nexport const TrackNumber = createTrackFieldDisplay(\"Ginger.Current.TrackNumber\", (t) =>\n t?.trackNumber != null ? String(t.trackNumber) : undefined,\n);\n","import { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\nimport type { TextDisplayProps } from \"./createTextDisplay\";\n\nexport type YearProps = TextDisplayProps & {\n format?: (year: number) => string;\n};\n\nexport function Year({ className, style, fallback, empty, children, format }: YearProps) {\n const state = useGingerState();\n const y = getCurrentTrack(state)?.year;\n if (typeof y !== \"number\" || !Number.isFinite(y)) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"Year\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const text = format ? format(y) : String(y);\n if (children)\n return (\n <span data-ginger-component=\"Year\" className={className} style={style}>\n {children(text, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"Year\" className={className} style={style}>\n {text}\n </span>\n );\n}\n\nYear.displayName = \"Ginger.Current.Year\";\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\n\nexport type LyricsProps = DisplayBaseProps & {\n children?: (value: string, state: GingerState) => ReactNode;\n /** When true, preserves internal newlines; trims only leading/trailing whitespace */\n preserveWhitespace?: boolean;\n /** When true, skips default `whiteSpace: pre-wrap` when `preserveWhitespace` is true (use `className` / `style` instead). */\n unstyled?: boolean;\n};\n\nexport function Lyrics({\n className,\n style,\n fallback,\n empty,\n children,\n preserveWhitespace = true,\n unstyled = false,\n}: LyricsProps) {\n const state = useGingerState();\n const raw = getCurrentTrack(state)?.lyrics ?? \"\";\n const value = preserveWhitespace ? raw.replace(/^\\s+|\\s+$/g, \"\") : raw.trim();\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"Lyrics\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const whiteStyle: CSSProperties | undefined =\n !unstyled && preserveWhitespace ? { whiteSpace: \"pre-wrap\" } : undefined;\n if (children)\n return (\n <span className={className} style={{ ...whiteStyle, ...style }}>\n {children(value, state)}\n </span>\n );\n return (\n <span className={className} style={{ ...whiteStyle, ...style }}>\n {value}\n </span>\n );\n}\n\nLyrics.displayName = \"Ginger.Current.Lyrics\";\n","export type TimedLyricLine = {\n time: number;\n text: string;\n};\n\nconst lrcTag = /\\[(\\d{1,2}):(\\d{2})(?:\\.(\\d{1,3}))?\\]/g;\n\nexport function parseLrc(lrc: string): TimedLyricLine[] {\n const lines: TimedLyricLine[] = [];\n for (const rawLine of lrc.split(/\\r?\\n/)) {\n const matches = [...rawLine.matchAll(lrcTag)];\n if (matches.length === 0) continue;\n const text = rawLine.replace(lrcTag, \"\").trim();\n for (const m of matches) {\n const minutes = Number(m[1] ?? 0);\n const seconds = Number(m[2] ?? 0);\n const millis = Number((m[3] ?? \"0\").padEnd(3, \"0\"));\n const time = minutes * 60 + seconds + millis / 1000;\n if (Number.isFinite(time) && time >= 0) {\n lines.push({ time, text });\n }\n }\n }\n return lines.sort((a, b) => a.time - b.time);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { type TimedLyricLine, parseLrc } from \"../internal/lyrics\";\n\nexport type GingerLyricsSyncState = {\n lines: TimedLyricLine[];\n activeIndex: number;\n activeLine: TimedLyricLine | null;\n};\n\nexport function useGingerLyricsSync(): GingerLyricsSyncState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime } = useGingerMedia();\n const currentTrack = tracks[currentIndex];\n\n const lines = useMemo(() => {\n if (!currentTrack) return [];\n if (Array.isArray(currentTrack.lyricsTimed) && currentTrack.lyricsTimed.length > 0) {\n return [...currentTrack.lyricsTimed]\n .filter((line) => Number.isFinite(line.time) && line.time >= 0)\n .sort((a, b) => a.time - b.time);\n }\n if (typeof currentTrack.lyrics === \"string\") {\n return parseLrc(currentTrack.lyrics);\n }\n return [];\n }, [currentTrack]);\n\n const activeIndex = useMemo(() => {\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n if (currentTime >= lines[i]!.time) return i;\n }\n return -1;\n }, [currentTime, lines]);\n\n return {\n lines,\n activeIndex,\n activeLine: activeIndex >= 0 ? (lines[activeIndex] ?? null) : null,\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useGingerLocale } from \"../../context/GingerLocaleContext\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { useGingerLyricsSync } from \"../../hooks/useGingerLyricsSync\";\nimport type { TimedLyricLine } from \"../../internal/lyrics\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\n\nexport type LyricsSyncedProps = Omit<DisplayBaseProps, \"children\"> & {\n unstyled?: boolean;\n /** Class applied to the line that matches the current playback time. */\n activeClassName?: string;\n /** Class applied to every line. */\n lineClassName?: string;\n children?: (\n line: TimedLyricLine,\n index: number,\n active: boolean,\n state: GingerState,\n ) => ReactNode;\n};\n\nexport function LyricsSynced({\n className,\n style,\n fallback,\n empty,\n unstyled = false,\n activeClassName,\n lineClassName,\n children,\n}: LyricsSyncedProps) {\n const state = useGingerState();\n const locale = useGingerLocale();\n const { lines, activeIndex } = useGingerLyricsSync();\n\n if (lines.length === 0) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"LyricsSynced\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n\n const listStyle: CSSProperties = unstyled\n ? {}\n : {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n fontFamily: \"var(--ginger-font-family, system-ui, sans-serif)\",\n fontSize: \"var(--ginger-font-size, 14px)\",\n color: \"var(--ginger-primary-color, #111827)\",\n };\n\n return (\n <ul\n className={className}\n style={{ ...listStyle, ...style }}\n aria-label={locale.syncedLyricsList}\n >\n {lines.map((line, index) => {\n const active = index === activeIndex;\n return (\n <li\n key={`${line.time}-${index}`}\n aria-current={active ? \"true\" : undefined}\n data-ginger-active={active || undefined}\n className={\n [lineClassName, active ? activeClassName : undefined].filter(Boolean).join(\" \") ||\n undefined\n }\n style={\n unstyled\n ? undefined\n : {\n padding: \"var(--ginger-playlist-row-padding, 4px 8px)\",\n fontWeight: active ? 600 : 400,\n opacity: active ? 1 : 0.75,\n }\n }\n >\n {children ? children(line, index, active, state) : line.text}\n </li>\n );\n })}\n </ul>\n );\n}\n\nLyricsSynced.displayName = \"Ginger.Current.LyricsSynced\";\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerChapter = {\n title: string;\n startSeconds: number;\n};\n\nexport type GingerChapterState = {\n list: GingerChapter[];\n activeIndex: number;\n active: GingerChapter | null;\n seekTo: (index: number) => void;\n};\n\nexport function useGingerChapters(): GingerChapterState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime, seek } = useGingerMedia();\n\n const list = useMemo(() => {\n const chapters = tracks[currentIndex]?.chapters ?? [];\n return [...chapters]\n .filter((item) => item && Number.isFinite(item.startSeconds) && item.startSeconds >= 0)\n .sort((a, b) => a.startSeconds - b.startSeconds);\n }, [currentIndex, tracks]);\n\n const activeIndex = useMemo(() => {\n if (list.length === 0) return -1;\n for (let i = list.length - 1; i >= 0; i -= 1) {\n if (currentTime >= list[i]!.startSeconds) return i;\n }\n return -1;\n }, [currentTime, list]);\n\n return {\n list,\n activeIndex,\n active: activeIndex >= 0 ? (list[activeIndex] ?? null) : null,\n seekTo: (index: number) => {\n const chapter = list[index];\n if (chapter) seek(chapter.startSeconds);\n },\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useGingerLocale } from \"../../context/GingerLocaleContext\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { type GingerChapter, useGingerChapters } from \"../../hooks/useGingerChapters\";\nimport { formatMmSs } from \"../../internal/formatTime\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\n\nexport type ChaptersProps = Omit<DisplayBaseProps, \"children\"> & {\n /** Remove default list/row styles for fully custom styling. */\n unstyled?: boolean;\n /** Prefix before each chapter title (default: `formatMmSs(startSeconds)`). */\n formatStart?: (startSeconds: number) => string;\n children?: (\n chapter: GingerChapter,\n index: number,\n active: boolean,\n state: GingerState,\n ) => ReactNode;\n};\n\nexport function Chapters({\n className,\n style,\n fallback,\n empty,\n unstyled = false,\n formatStart = formatMmSs,\n children,\n}: ChaptersProps) {\n const state = useGingerState();\n const locale = useGingerLocale();\n const { list, activeIndex, seekTo } = useGingerChapters();\n\n if (list.length === 0) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"Chapters\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n\n const listStyle: CSSProperties = unstyled\n ? {}\n : {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n fontFamily: \"var(--ginger-font-family, system-ui, sans-serif)\",\n fontSize: \"var(--ginger-font-size, 14px)\",\n color: \"var(--ginger-primary-color, #111827)\",\n };\n\n return (\n <ul className={className} style={{ ...listStyle, ...style }} aria-label={locale.chaptersList}>\n {list.map((chapter, index) => {\n const active = index === activeIndex;\n return (\n <li key={`${chapter.startSeconds}-${chapter.title}`}>\n <button\n type=\"button\"\n aria-current={active ? \"true\" : undefined}\n data-ginger-active={active || undefined}\n onClick={() => seekTo(index)}\n style={{\n width: unstyled ? undefined : \"100%\",\n textAlign: unstyled ? undefined : \"left\",\n border: unstyled ? undefined : \"none\",\n background: unstyled\n ? undefined\n : active\n ? \"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))\"\n : \"transparent\",\n color: unstyled ? undefined : \"inherit\",\n font: unstyled ? undefined : \"inherit\",\n cursor: unstyled ? undefined : \"pointer\",\n padding: unstyled ? undefined : \"var(--ginger-playlist-row-padding, 6px 8px)\",\n }}\n >\n {children ? (\n children(chapter, index, active, state)\n ) : unstyled ? (\n <>\n {formatStart(chapter.startSeconds)} {chapter.title}\n </>\n ) : (\n <span>\n <span style={{ opacity: 0.75, marginRight: \"0.35em\" }}>\n {formatStart(chapter.startSeconds)}\n </span>\n {chapter.title}\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n );\n}\n\nChapters.displayName = \"Ginger.Current.Chapters\";\n","import { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\nimport type { TextDisplayProps } from \"./createTextDisplay\";\n\nexport type FileUrlProps = TextDisplayProps & {\n /** When false (default), renders nothing unless you explicitly opt in */\n visible?: boolean;\n};\n\nexport function FileUrl({\n visible = false,\n className,\n style,\n fallback,\n empty,\n children,\n}: FileUrlProps) {\n const state = useGingerState();\n if (!visible) return null;\n const value = getCurrentTrack(state)?.fileUrl ?? \"\";\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n if (children)\n return (\n <span data-ginger-component=\"FileUrl\" className={className} style={style}>\n {children(value, state)}\n </span>\n );\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n}\n\nFileUrl.displayName = \"Ginger.Current.FileUrl\";\n","import type { CSSProperties, ImgHTMLAttributes } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack, resolvedArtwork } from \"../../internal/selectors\";\nimport type { DisplayBaseProps } from \"../../types\";\n\nexport type ArtworkProps = DisplayBaseProps &\n Pick<ImgHTMLAttributes<HTMLImageElement>, \"sizes\" | \"loading\" | \"onError\" | \"decoding\"> & {\n /** Remove default wrapper/image styles for fully custom layout. */\n unstyled?: boolean;\n imgStyle?: CSSProperties;\n };\n\nexport function Artwork({\n className,\n style,\n fallback,\n empty,\n sizes,\n loading,\n onError,\n decoding,\n unstyled = false,\n imgStyle,\n}: ArtworkProps) {\n const state = useGingerState();\n const track = getCurrentTrack(state);\n const src = resolvedArtwork(state);\n if (!src) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const alt = [track?.title, track?.artist].filter(Boolean).join(\" — \") || \"Artwork\";\n return (\n <div\n data-ginger-component=\"Artwork\"\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n background: \"var(--ginger-artwork-bg, transparent)\",\n borderRadius: \"var(--ginger-artwork-radius, 0)\",\n overflow: \"hidden\",\n ...style,\n }\n }\n >\n <img\n src={src}\n alt={alt}\n sizes={sizes}\n loading={loading}\n decoding={decoding}\n onError={onError}\n style={{\n display: unstyled ? undefined : \"block\",\n width: unstyled ? undefined : \"100%\",\n height: unstyled ? undefined : \"100%\",\n objectFit: unstyled ? undefined : \"cover\",\n ...imgStyle,\n }}\n />\n </div>\n );\n}\n\nArtwork.displayName = \"Ginger.Current.Artwork\";\n","import type { ReactNode } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\n\nexport type QueueIndexProps = DisplayBaseProps & {\n base?: 0 | 1;\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function QueueIndex({\n base = 0,\n className,\n style,\n fallback,\n empty,\n children,\n}: QueueIndexProps) {\n const state = useGingerState();\n const len = state.tracks.length;\n if (len === 0) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"QueueIndex\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const value = String(state.currentIndex + base);\n if (children)\n return (\n <span data-ginger-component=\"QueueIndex\" className={className} style={style}>\n {children(value, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"QueueIndex\" className={className} style={style}>\n {value}\n </span>\n );\n}\n\nQueueIndex.displayName = \"Ginger.Current.QueueIndex\";\n\nexport type QueueLengthProps = DisplayBaseProps & {\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function QueueLength({ className, style, fallback, empty, children }: QueueLengthProps) {\n const state = useGingerState();\n const value = String(state.tracks.length);\n if (state.tracks.length === 0) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n if (children)\n return (\n <span data-ginger-component=\"QueueLength\" className={className} style={style}>\n {children(value, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"QueueLength\" className={className} style={style}>\n {value}\n </span>\n );\n}\n\nQueueLength.displayName = \"Ginger.Current.QueueLength\";\n\nexport type QueuePositionProps = DisplayBaseProps & {\n base?: 0 | 1;\n separator?: string;\n children?: (\n value: { index: string; length: string; label: string },\n state: GingerState,\n ) => ReactNode;\n};\n\nexport function QueuePosition({\n base = 0,\n separator = \" / \",\n className,\n style,\n fallback,\n empty,\n children,\n}: QueuePositionProps) {\n const state = useGingerState();\n const len = state.tracks.length;\n if (len === 0) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const index = String(state.currentIndex + base);\n const length = String(len);\n const label = `${index}${separator}${length}`;\n if (children)\n return (\n <span data-ginger-component=\"QueuePosition\" className={className} style={style}>\n {children({ index, length, label }, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"QueuePosition\" className={className} style={style}>\n {label}\n </span>\n );\n}\n\nQueuePosition.displayName = \"Ginger.Current.QueuePosition\";\n","import type { ReactElement, ReactNode } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { formatMmSs } from \"../../internal/formatTime\";\nimport { effectiveDuration, effectiveRemaining, progressFraction } from \"../../internal/selectors\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\n\nexport type TimeTextProps = DisplayBaseProps & {\n format?: (seconds: number) => string;\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nfunction renderTime(\n valueSeconds: number,\n state: GingerState,\n props: TimeTextProps,\n): ReactElement | null {\n const { className, style, fallback, empty, children, format = formatMmSs } = props;\n if (!(valueSeconds >= 0) || !Number.isFinite(valueSeconds)) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"TimeText\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const text = format(valueSeconds);\n if (children)\n return (\n <span data-ginger-component=\"TimeText\" className={className} style={style}>\n {children(text, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"TimeText\" className={className} style={style}>\n {text}\n </span>\n );\n}\n\nexport function Elapsed(props: TimeTextProps) {\n const state = useGingerState();\n return renderTime(state.currentTime, state, props);\n}\n\nElapsed.displayName = \"Ginger.Current.Elapsed\";\n\nexport function Duration(props: TimeTextProps) {\n const state = useGingerState();\n return renderTime(effectiveDuration(state), state, props);\n}\n\nDuration.displayName = \"Ginger.Current.Duration\";\n\nexport function Remaining(props: TimeTextProps) {\n const state = useGingerState();\n return renderTime(effectiveRemaining(state), state, props);\n}\n\nRemaining.displayName = \"Ginger.Current.Remaining\";\n\nexport type ProgressProps = DisplayBaseProps & {\n children?: (\n value: { fraction: number; currentTime: number; duration: number },\n state: GingerState,\n ) => ReactNode;\n};\n\nexport function Progress({ className, style, fallback, empty, children }: ProgressProps) {\n const state = useGingerState();\n const duration = effectiveDuration(state);\n const fraction = progressFraction(state);\n if (!(duration > 0)) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"Progress\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n if (children)\n return (\n <span data-ginger-component=\"Progress\" className={className} style={style}>\n {children({ fraction, currentTime: state.currentTime, duration }, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"Progress\" className={className} style={style}>\n {`${Math.round(fraction * 100)}%`}\n </span>\n );\n}\n\nProgress.displayName = \"Ginger.Current.Progress\";\n\nexport type TimeRailProps = DisplayBaseProps & {\n /** 0-1 height in px for the rail */\n height?: number;\n /** When true, shows a buffered range behind the progress fill (uses `bufferedFraction`). */\n showBuffered?: boolean;\n /** Remove default rail styles and render only inline width values. */\n unstyled?: boolean;\n};\n\nexport function TimeRail({\n className,\n style,\n height = 4,\n showBuffered = false,\n unstyled = false,\n}: TimeRailProps) {\n const state = useGingerState();\n const progressPct = `${Math.round(progressFraction(state) * 100)}%`;\n const bufPct = `${Math.round(Math.min(1, Math.max(0, state.bufferedFraction)) * 100)}%`;\n return (\n <div\n data-ginger-component=\"TimeRail\"\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n width: \"100%\",\n height,\n background: \"var(--ginger-muted-color, #e5e7eb)\",\n borderRadius: 999,\n overflow: \"hidden\",\n position: \"relative\",\n ...style,\n }\n }\n aria-hidden\n >\n {showBuffered ? (\n <div\n data-ginger-component=\"TimeRail\"\n style={{\n position: unstyled ? undefined : \"absolute\",\n left: unstyled ? undefined : 0,\n top: unstyled ? undefined : 0,\n height: unstyled ? undefined : \"100%\",\n width: bufPct,\n background: unstyled\n ? undefined\n : \"var(--ginger-buffer-color, rgba(107, 114, 128, 0.35))\",\n }}\n />\n ) : null}\n <div\n data-ginger-component=\"TimeRail\"\n style={{\n position: unstyled ? undefined : \"relative\",\n width: progressPct,\n height: unstyled ? undefined : \"100%\",\n background: unstyled ? undefined : \"var(--ginger-primary-color, #111827)\",\n }}\n />\n </div>\n );\n}\n\nTimeRail.displayName = \"Ginger.Current.TimeRail\";\n\nexport type BufferRailProps = DisplayBaseProps & {\n height?: number;\n /** Remove default rail styles and render only buffered width value. */\n unstyled?: boolean;\n};\n\n/** Buffered portion of the timeline (0…`bufferedFraction`); pair with `TimeRail` or use alone. */\nexport function BufferRail({ className, style, height = 4, unstyled = false }: BufferRailProps) {\n const state = useGingerState();\n const bufPct = `${Math.round(Math.min(1, Math.max(0, state.bufferedFraction)) * 100)}%`;\n return (\n <div\n data-ginger-component=\"BufferRail\"\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n width: \"100%\",\n height,\n background: \"var(--ginger-muted-color, #e5e7eb)\",\n borderRadius: 999,\n overflow: \"hidden\",\n ...style,\n }\n }\n aria-hidden\n >\n <div\n data-ginger-component=\"BufferRail\"\n style={{\n width: bufPct,\n height: unstyled ? undefined : \"100%\",\n background: unstyled\n ? undefined\n : \"var(--ginger-buffer-color, rgba(107, 114, 128, 0.35))\",\n }}\n />\n </div>\n );\n}\n\nBufferRail.displayName = \"Ginger.Current.BufferRail\";\n","import type { ReactNode } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { derivePlaybackUiState } from \"../../internal/selectors\";\nimport type { DisplayBaseProps, GingerState, PlaybackUiState } from \"../../types\";\n\nexport type PlaybackStateProps = DisplayBaseProps & {\n children?: (value: PlaybackUiState, state: GingerState) => ReactNode;\n};\n\nexport function PlaybackState({ className, style, fallback, empty, children }: PlaybackStateProps) {\n const state = useGingerState();\n const value = derivePlaybackUiState(state);\n if (children)\n return (\n <span data-ginger-component=\"PlaybackState\" className={className} style={style}>\n {children(value, state)}\n </span>\n );\n return (\n <span data-ginger-component=\"PlaybackState\" className={className} style={style}>\n {value}\n </span>\n );\n}\n\nPlaybackState.displayName = \"Ginger.Current.PlaybackState\";\n\nexport type ErrorMessageProps = DisplayBaseProps & {\n live?: \"polite\" | \"assertive\" | \"off\";\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function ErrorMessage({\n className,\n style,\n fallback,\n empty,\n live = \"polite\",\n children,\n}: ErrorMessageProps) {\n const state = useGingerState();\n const value = state.errorMessage ?? \"\";\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"ErrorMessage\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n if (children) {\n return (\n <span\n data-ginger-component=\"ErrorMessage\"\n className={className}\n style={style}\n aria-live={live}\n >\n {children(value, state)}\n </span>\n );\n }\n return (\n <span data-ginger-component=\"ErrorMessage\" className={className} style={style} aria-live={live}>\n {value}\n </span>\n );\n}\n\nErrorMessage.displayName = \"Ginger.Current.ErrorMessage\";\n","import {\n type ButtonHTMLAttributes,\n type CSSProperties,\n type HTMLAttributes,\n type LiHTMLAttributes,\n type ReactNode,\n createContext,\n useContext,\n} from \"react\";\nimport { useGingerPlayback } from \"../../context/GingerSplitContexts\";\nimport { trackIdentity } from \"../../core/queue\";\nimport type { Track } from \"../../types\";\n\nexport type GingerPlaylistConfig = {\n playOnSelect: boolean;\n};\n\nconst GingerPlaylistConfigContext = createContext<GingerPlaylistConfig | null>(null);\n\nfunction usePlaylistConfig(): GingerPlaylistConfig {\n const ctx = useContext(GingerPlaylistConfigContext);\n if (!ctx) {\n throw new Error(\"Ginger.Playlist.Track must be used inside <Ginger.Playlist>\");\n }\n return ctx;\n}\n\nexport type GingerPlaylistProps = Omit<HTMLAttributes<HTMLUListElement>, \"children\"> & {\n children?: ReactNode;\n /** Remove default list/row styles for fully custom playlist styling. */\n unstyled?: boolean;\n rowStyle?: CSSProperties;\n /**\n * Used only in **auto** mode (no custom `children`). Ignored when you pass custom `children`\n * (manual mode); use `Ginger.Playlist.Track` for each row instead.\n */\n renderTrack?: (track: Track, index: number, isActive: boolean) => ReactNode;\n /** When true (default), clicking a row selects that index and starts playback */\n playOnSelect?: boolean;\n};\n\n/**\n * - **Auto mode** (no `children`): maps `state.tracks` to rows (optional `renderTrack`).\n * - **Manual mode** (`children` defined): renders `<ul>{children}</ul>`; map `state.tracks` yourself\n * with `Ginger.Playlist.Track` for each index.\n */\nexport function GingerPlaylist({\n children,\n unstyled = false,\n rowStyle,\n renderTrack,\n playOnSelect = true,\n style,\n ...rest\n}: GingerPlaylistProps) {\n const { tracks, currentIndex, playTrackAt, selectTrackAt } = useGingerPlayback();\n\n const listStyle: CSSProperties = unstyled\n ? { ...style }\n : {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n fontFamily: \"var(--ginger-font-family, system-ui, sans-serif)\",\n fontSize: \"var(--ginger-font-size, 14px)\",\n color: \"var(--ginger-primary-color, #111827)\",\n ...style,\n };\n\n const manual = children !== undefined;\n\n if (manual) {\n return (\n <GingerPlaylistConfigContext.Provider value={{ playOnSelect }}>\n <ul data-ginger-component=\"Playlist\" style={listStyle} {...rest}>\n {children}\n </ul>\n </GingerPlaylistConfigContext.Provider>\n );\n }\n\n return (\n <GingerPlaylistConfigContext.Provider value={{ playOnSelect }}>\n <ul data-ginger-component=\"Playlist\" style={listStyle} {...rest}>\n {tracks.map((track, index) => {\n const active = index === currentIndex;\n return (\n <li key={`${index}-${trackIdentity(track)}`}>\n <button\n type=\"button\"\n onClick={() => {\n if (playOnSelect) playTrackAt(index);\n else selectTrackAt(index);\n }}\n style={{\n width: unstyled ? undefined : \"100%\",\n textAlign: unstyled ? undefined : \"left\",\n border: unstyled ? undefined : \"none\",\n background: unstyled\n ? undefined\n : active\n ? \"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))\"\n : \"transparent\",\n color: unstyled ? undefined : \"inherit\",\n font: unstyled ? undefined : \"inherit\",\n cursor: unstyled ? undefined : \"pointer\",\n padding: unstyled ? undefined : \"var(--ginger-playlist-row-padding, 6px 8px)\",\n ...rowStyle,\n }}\n >\n {renderTrack ? (\n renderTrack(track, index, active)\n ) : (\n <span>\n {track.title}\n {track.artist ? ` — ${track.artist}` : \"\"}\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n </GingerPlaylistConfigContext.Provider>\n );\n}\n\nGingerPlaylist.displayName = \"Ginger.Playlist\";\n\nexport type GingerPlaylistTrackProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"type\"> & {\n index: number;\n /** Remove default row button styles for fully custom styling. */\n unstyled?: boolean;\n /** Optional wrapper for the row; defaults to a plain `<li>` */\n liProps?: LiHTMLAttributes<HTMLLIElement>;\n};\n\nexport function GingerPlaylistTrack({\n index,\n unstyled = false,\n className,\n style,\n children,\n liProps,\n onClick,\n ...buttonRest\n}: GingerPlaylistTrackProps) {\n const { playOnSelect } = usePlaylistConfig();\n const { tracks, currentIndex, playTrackAt, selectTrackAt } = useGingerPlayback();\n const active = index === currentIndex;\n const track = tracks[index];\n const defaultLabel =\n track != null ? (\n <span data-ginger-component=\"PlaylistTrack\">\n {track.title}\n {track.artist ? ` — ${track.artist}` : \"\"}\n </span>\n ) : null;\n\n return (\n <li {...liProps} data-ginger-component=\"PlaylistTrack\">\n <button\n type=\"button\"\n data-ginger-component=\"PlaylistTrackButton\"\n aria-current={active ? \"true\" : undefined}\n data-ginger-active={active || undefined}\n className={className}\n style={{\n width: unstyled ? undefined : \"100%\",\n textAlign: unstyled ? undefined : \"left\",\n border: unstyled ? undefined : \"none\",\n background: unstyled\n ? undefined\n : active\n ? \"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))\"\n : \"transparent\",\n color: unstyled ? undefined : \"inherit\",\n font: unstyled ? undefined : \"inherit\",\n cursor: unstyled ? undefined : \"pointer\",\n padding: unstyled ? undefined : \"var(--ginger-playlist-row-padding, 6px 8px)\",\n ...style,\n }}\n {...buttonRest}\n onClick={(e) => {\n onClick?.(e);\n if (e.defaultPrevented) return;\n if (playOnSelect) playTrackAt(index);\n else selectTrackAt(index);\n }}\n >\n {children ?? defaultLabel}\n </button>\n </li>\n );\n}\n\nGingerPlaylistTrack.displayName = \"Ginger.Playlist.Track\";\n\nexport const GingerPlaylistCompound = Object.assign(GingerPlaylist, {\n Track: GingerPlaylistTrack,\n});\n","import type { CSSProperties } from \"react\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport type { DisplayBaseProps } from \"../../types\";\nimport { createTextDisplay } from \"../current/createTextDisplay\";\n\nexport const Title = createTextDisplay(\"Ginger.Queue.Title\", (s) => s.playlistMeta?.title);\nexport const Subtitle = createTextDisplay(\"Ginger.Queue.Subtitle\", (s) => s.playlistMeta?.subtitle);\nexport const Description = createTextDisplay(\n \"Ginger.Queue.Description\",\n (s) => s.playlistMeta?.description,\n);\nexport const Copyright = createTextDisplay(\n \"Ginger.Queue.Copyright\",\n (s) => s.playlistMeta?.copyright,\n);\n\nexport type QueueArtworkProps = DisplayBaseProps & {\n /** Remove default wrapper/image styles for fully custom layout. */\n unstyled?: boolean;\n imgStyle?: CSSProperties;\n};\n\nexport function Artwork({\n className,\n style,\n fallback,\n empty,\n unstyled = false,\n imgStyle,\n}: QueueArtworkProps) {\n const state = useGingerState();\n const src = state.playlistMeta?.artworkUrl;\n if (!src) {\n const node = empty ?? fallback ?? null;\n return node ? (\n <span data-ginger-component=\"Artwork\" className={className} style={style}>\n {node}\n </span>\n ) : null;\n }\n const alt = state.playlistMeta?.title ?? \"Playlist artwork\";\n return (\n <span\n data-ginger-component=\"Artwork\"\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n display: \"inline-block\",\n background: \"var(--ginger-artwork-bg, #f3f4f6)\",\n borderRadius: \"var(--ginger-artwork-radius, 6px)\",\n overflow: \"hidden\",\n ...style,\n }\n }\n >\n <img\n src={src}\n alt={alt}\n style={{\n display: unstyled ? undefined : \"block\",\n width: unstyled ? undefined : \"100%\",\n height: unstyled ? undefined : \"100%\",\n objectFit: unstyled ? undefined : \"cover\",\n ...imgStyle,\n }}\n />\n </span>\n );\n}\n\nArtwork.displayName = \"Ginger.Queue.Artwork\";\n","import type { GingerAction, GingerState, RepeatMode, Track } from \"../types\";\nimport {\n addNextTrack,\n clampIndex,\n findIndexByTrackIdentity,\n insertTrackAt,\n moveTrack,\n removeTrackAt,\n shuffleWithAnchor,\n} from \"./queue\";\nimport { computeNextIndex, computePrevIndex, cycleRepeatMode } from \"./transitions\";\n\nexport function clampVolume(v: number): number {\n if (!Number.isFinite(v)) return 1;\n return Math.min(1, Math.max(0, v));\n}\n\nexport function clampPlaybackRate(r: number): number {\n if (!Number.isFinite(r)) return 1;\n return Math.min(4, Math.max(0.25, r));\n}\n\n/** Reset when the active track / position changes; keeps volume / mute / speed */\nconst resetTimingOnly = {\n currentTime: 0,\n duration: 0,\n bufferedFraction: 0,\n isBuffering: false,\n errorMessage: null as string | null,\n};\n\nconst defaultMedia = {\n ...resetTimingOnly,\n volume: 1,\n muted: false,\n playbackRate: 1,\n};\n\nexport function createInitialState(params: {\n tracks: Track[];\n currentIndex?: number;\n playlistMeta?: GingerState[\"playlistMeta\"];\n isPaused?: boolean;\n isShuffled?: boolean;\n repeatMode?: RepeatMode;\n playbackMode?: GingerState[\"playbackMode\"];\n volume?: number;\n muted?: boolean;\n playbackRate?: number;\n}): GingerState {\n const tracks = [...params.tracks];\n let currentIndex = clampIndex(params.currentIndex ?? 0, tracks.length);\n let originalTracks: Track[] | null = null;\n let ordered = tracks;\n\n if (params.isShuffled && tracks.length > 1) {\n originalTracks = [...tracks];\n ordered = shuffleWithAnchor(tracks, currentIndex);\n currentIndex = 0;\n }\n\n return {\n tracks: ordered,\n currentIndex,\n playbackMode: params.playbackMode ?? \"playlist\",\n isPaused: params.isPaused ?? true,\n isShuffled: Boolean(params.isShuffled && ordered.length > 1),\n repeatMode: params.repeatMode ?? \"off\",\n originalTracks,\n playlistMeta: params.playlistMeta ?? null,\n ...defaultMedia,\n volume: clampVolume(params.volume ?? 1),\n muted: params.muted ?? false,\n playbackRate: clampPlaybackRate(params.playbackRate ?? 1),\n };\n}\n\nexport function gingerReducer(state: GingerState, action: GingerAction): GingerState {\n switch (action.type) {\n case \"INIT\": {\n const {\n tracks,\n currentIndex,\n playlistMeta,\n isPaused,\n isShuffled,\n repeatMode,\n playbackMode,\n volume,\n muted,\n playbackRate,\n } = action.payload;\n return createInitialState({\n tracks,\n currentIndex,\n playlistMeta: playlistMeta ?? null,\n isPaused: isPaused ?? true,\n isShuffled: isShuffled ?? false,\n repeatMode: repeatMode ?? \"off\",\n playbackMode: playbackMode ?? \"playlist\",\n volume,\n muted,\n playbackRate,\n });\n }\n case \"SET_QUEUE\": {\n const { tracks, currentIndex } = action.payload;\n const next = [...tracks];\n const idx = clampIndex(currentIndex ?? state.currentIndex, next.length);\n return {\n ...state,\n tracks: next,\n currentIndex: idx,\n isShuffled: false,\n originalTracks: null,\n ...resetTimingOnly,\n };\n }\n case \"INSERT_TRACK\": {\n const insertIndex = action.payload.index ?? state.tracks.length;\n const tracks = insertTrackAt(state.tracks, action.payload.track, insertIndex);\n if (action.payload.autoPlay) {\n const idx = clampIndex(insertIndex, tracks.length);\n return {\n ...state,\n tracks,\n currentIndex: idx,\n isShuffled: false,\n originalTracks: null,\n isPaused: false,\n ...resetTimingOnly,\n };\n }\n const currentIndex =\n insertIndex <= state.currentIndex ? state.currentIndex + 1 : state.currentIndex;\n // Mirror insert into originalTracks so shuffle order is preserved\n const originalTracks =\n state.isShuffled && state.originalTracks\n ? insertTrackAt(state.originalTracks, action.payload.track, state.originalTracks.length)\n : state.originalTracks;\n return {\n ...state,\n tracks,\n originalTracks,\n currentIndex: clampIndex(currentIndex, tracks.length),\n };\n }\n case \"REMOVE_TRACK\": {\n const index = action.payload.index;\n const tracks = removeTrackAt(state.tracks, index);\n const currentIndex =\n index < state.currentIndex\n ? state.currentIndex - 1\n : index === state.currentIndex\n ? Math.min(state.currentIndex, Math.max(0, tracks.length - 1))\n : state.currentIndex;\n // Mirror removal in originalTracks by track identity so shuffle order is preserved\n const originalTracks =\n state.isShuffled && state.originalTracks\n ? (() => {\n const removedTrack = state.tracks[index];\n const origIdx = findIndexByTrackIdentity(state.originalTracks, removedTrack);\n return removeTrackAt(state.originalTracks, origIdx);\n })()\n : state.originalTracks;\n const nextIsShuffled = state.isShuffled && tracks.length > 1;\n return {\n ...state,\n tracks,\n isShuffled: nextIsShuffled,\n originalTracks: nextIsShuffled ? originalTracks : null,\n currentIndex: clampIndex(currentIndex, tracks.length),\n ...(index === state.currentIndex ? resetTimingOnly : {}),\n };\n }\n case \"MOVE_TRACK\": {\n const { fromIndex, toIndex } = action.payload;\n const tracks = moveTrack(state.tracks, fromIndex, toIndex);\n let currentIndex = state.currentIndex;\n if (state.currentIndex === fromIndex) currentIndex = toIndex;\n else if (fromIndex < state.currentIndex && toIndex >= state.currentIndex) currentIndex -= 1;\n else if (fromIndex > state.currentIndex && toIndex <= state.currentIndex) currentIndex += 1;\n return {\n ...state,\n tracks,\n isShuffled: false,\n originalTracks: null,\n currentIndex: clampIndex(currentIndex, tracks.length),\n };\n }\n case \"ADD_NEXT\": {\n const tracks = addNextTrack(state.tracks, state.currentIndex, action.payload.track);\n // Mirror into originalTracks: insert after the current track's position in original order\n const originalTracks =\n state.isShuffled && state.originalTracks\n ? (() => {\n const currentTrack = state.tracks[state.currentIndex];\n const origCurrentIdx = findIndexByTrackIdentity(state.originalTracks, currentTrack);\n return addNextTrack(state.originalTracks, origCurrentIdx, action.payload.track);\n })()\n : state.originalTracks;\n return {\n ...state,\n tracks,\n originalTracks,\n };\n }\n case \"SET_INDEX\": {\n const idx = clampIndex(action.payload.index, state.tracks.length);\n const ap = action.payload.autoPlay;\n const isPaused = ap === true ? false : ap === false ? true : state.isPaused;\n return {\n ...state,\n currentIndex: idx,\n ...resetTimingOnly,\n isPaused,\n };\n }\n case \"PLAY\":\n return { ...state, isPaused: false };\n case \"PAUSE\":\n return { ...state, isPaused: true };\n case \"TOGGLE_PAUSE\":\n return { ...state, isPaused: !state.isPaused };\n case \"SET_REPEAT\":\n return { ...state, repeatMode: action.payload };\n case \"CYCLE_REPEAT\":\n return { ...state, repeatMode: cycleRepeatMode(state.repeatMode) };\n case \"TOGGLE_SHUFFLE\": {\n if (state.tracks.length <= 1) return { ...state, isShuffled: false, originalTracks: null };\n if (!state.isShuffled) {\n const snapshot = [...state.tracks];\n const shuffled = shuffleWithAnchor(snapshot, state.currentIndex);\n return {\n ...state,\n isShuffled: true,\n originalTracks: snapshot,\n tracks: shuffled,\n currentIndex: 0,\n };\n }\n const restored = state.originalTracks ? [...state.originalTracks] : [...state.tracks];\n const current = state.tracks[state.currentIndex];\n const newIndex = findIndexByTrackIdentity(restored, current);\n return {\n ...state,\n isShuffled: false,\n originalTracks: null,\n tracks: restored,\n currentIndex: clampIndex(newIndex, restored.length),\n };\n }\n case \"NEXT\": {\n const nextIndex = computeNextIndex(state);\n const same = nextIndex === state.currentIndex;\n return {\n ...state,\n currentIndex: nextIndex,\n ...(same ? {} : resetTimingOnly),\n isPaused: same ? state.isPaused : false,\n };\n }\n case \"PREV\": {\n const prevIndex = computePrevIndex(state);\n const same = prevIndex === state.currentIndex;\n return {\n ...state,\n currentIndex: prevIndex,\n ...(same ? {} : resetTimingOnly),\n isPaused: same ? state.isPaused : false,\n };\n }\n case \"MEDIA_TIME_UPDATE\":\n return {\n ...state,\n currentTime: action.payload.currentTime,\n duration: Number.isFinite(action.payload.duration)\n ? action.payload.duration\n : state.duration,\n bufferedFraction: action.payload.bufferedFraction,\n isBuffering: false,\n };\n case \"MEDIA_LOADED_METADATA\":\n return {\n ...state,\n duration: Number.isFinite(action.payload.duration)\n ? action.payload.duration\n : state.duration,\n bufferedFraction: action.payload.bufferedFraction,\n errorMessage: null,\n };\n case \"SET_PLAYLIST_META\":\n return { ...state, playlistMeta: action.payload };\n case \"SET_PLAYBACK_MODE\":\n return { ...state, playbackMode: action.payload };\n case \"MEDIA_ERROR\":\n return {\n ...state,\n errorMessage: action.payload.message,\n isPaused: true,\n isBuffering: false,\n };\n case \"MEDIA_WAITING\":\n return { ...state, isBuffering: true };\n case \"MEDIA_CANPLAY\":\n return { ...state, isBuffering: false, errorMessage: null };\n case \"MEDIA_PLAY\":\n return { ...state, isPaused: false, isBuffering: false };\n case \"MEDIA_PAUSE\":\n return { ...state, isPaused: true };\n case \"RESET_MEDIA_TIMES\":\n return { ...state, currentTime: 0, duration: 0, bufferedFraction: 0 };\n case \"MEDIA_SOURCE_CLEARED\":\n return { ...state, ...resetTimingOnly };\n case \"SET_VOLUME\":\n return { ...state, volume: clampVolume(action.payload) };\n case \"SET_MUTED\":\n return { ...state, muted: action.payload };\n case \"TOGGLE_MUTE\":\n return { ...state, muted: !state.muted };\n case \"SET_PLAYBACK_RATE\":\n return { ...state, playbackRate: clampPlaybackRate(action.payload) };\n case \"MEDIA_VOLUME_SYNC\": {\n const { volume, muted } = action.payload;\n const v = clampVolume(volume);\n if (v === state.volume && muted === state.muted) return state;\n return { ...state, volume: v, muted };\n }\n default: {\n const _exhaustive: never = action;\n void _exhaustive;\n return state;\n }\n }\n}\n","import { useEffect, useRef } from \"react\";\nimport { resolveArtworkUrl } from \"../core/transitions\";\nimport type { GingerMediaSessionOptions, GingerState } from \"../types\";\n\nexport type MediaSessionBridgeActions = {\n play: () => void;\n pause: () => void;\n next: () => void;\n prev: () => void;\n seek: (timeSeconds: number) => void;\n};\n\nfunction getMediaSession(): MediaSession | null {\n if (typeof navigator === \"undefined\" || !(\"mediaSession\" in navigator)) return null;\n return navigator.mediaSession;\n}\n\nexport function useMediaSessionBridge(\n enabled: boolean,\n state: GingerState,\n actions: MediaSessionBridgeActions,\n options: GingerMediaSessionOptions = {},\n): void {\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const track = state.tracks[state.currentIndex];\n const title = track?.title;\n const artist = track?.artist;\n const album = track?.album;\n const artworkUrl = resolveArtworkUrl(track, state.playlistMeta?.artworkUrl);\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms) return;\n ms.metadata = new MediaMetadata({\n title: title ?? \"Unknown track\",\n artist,\n album,\n artwork: artworkUrl ? [{ src: artworkUrl }] : undefined,\n });\n }, [enabled, title, artist, album, artworkUrl]);\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms) return;\n ms.playbackState = state.isPaused ? \"paused\" : \"playing\";\n }, [enabled, state.isPaused]);\n\n const seekForwardSeconds = options.seekForwardSeconds;\n const seekBackwardSeconds = options.seekBackwardSeconds;\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms) return;\n try {\n ms.setActionHandler(\"play\", actions.play);\n ms.setActionHandler(\"pause\", actions.pause);\n ms.setActionHandler(\"nexttrack\", actions.next);\n ms.setActionHandler(\"previoustrack\", actions.prev);\n ms.setActionHandler(\"seekto\", (details) => {\n if (typeof details.seekTime === \"number\" && Number.isFinite(details.seekTime)) {\n actions.seek(details.seekTime);\n }\n });\n\n if (typeof seekForwardSeconds === \"number\" && seekForwardSeconds > 0) {\n ms.setActionHandler(\"seekforward\", () => {\n const s = stateRef.current;\n const next = s.currentTime + seekForwardSeconds;\n const d = s.duration;\n const cap = Number.isFinite(d) && d > 0 ? d : next;\n actions.seek(Math.min(next, cap));\n });\n } else {\n ms.setActionHandler(\"seekforward\", null);\n }\n\n if (typeof seekBackwardSeconds === \"number\" && seekBackwardSeconds > 0) {\n ms.setActionHandler(\"seekbackward\", () => {\n const s = stateRef.current;\n actions.seek(Math.max(0, s.currentTime - seekBackwardSeconds));\n });\n } else {\n ms.setActionHandler(\"seekbackward\", null);\n }\n } catch {\n // Best-effort API support differs across browsers.\n }\n return () => {\n try {\n ms.setActionHandler(\"play\", null);\n ms.setActionHandler(\"pause\", null);\n ms.setActionHandler(\"nexttrack\", null);\n ms.setActionHandler(\"previoustrack\", null);\n ms.setActionHandler(\"seekto\", null);\n ms.setActionHandler(\"seekforward\", null);\n ms.setActionHandler(\"seekbackward\", null);\n } catch {\n // Ignore platforms that do not support clearing handlers.\n }\n };\n }, [enabled, actions, seekForwardSeconds, seekBackwardSeconds]);\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms || !options.positionState) return;\n const duration = state.duration;\n const position = state.currentTime;\n const rate = state.playbackRate;\n try {\n if (!Number.isFinite(duration) || duration <= 0) {\n ms.setPositionState?.();\n return;\n }\n ms.setPositionState?.({\n duration,\n playbackRate: Number.isFinite(rate) && rate > 0 ? rate : 1,\n position: Math.min(Math.max(0, position), duration),\n });\n } catch {\n // setPositionState is optional / flaky across browsers.\n }\n return () => {\n try {\n ms.setPositionState?.();\n } catch {\n // ignore\n }\n };\n }, [enabled, options.positionState, state.currentTime, state.duration, state.playbackRate]);\n}\n","import {\n type CSSProperties,\n Children,\n type ReactElement,\n cloneElement,\n isValidElement,\n useCallback,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n} from \"react\";\nimport {\n clampPlaybackRate,\n clampVolume,\n createInitialState,\n gingerReducer,\n} from \"../core/playbackReducer\";\nimport { trackIdentity } from \"../core/queue\";\nimport { computeEndedTransition } from \"../core/transitions\";\nimport { derivePlaybackUiState } from \"../internal/selectors\";\nimport { useMediaSessionBridge } from \"../media/useMediaSession\";\nimport type {\n GingerInitPayload,\n GingerProviderProps,\n PlaybackMode,\n PlaylistMeta,\n RepeatMode,\n Track,\n} from \"../types\";\nimport { GingerContext, type GingerContextValue } from \"./GingerContext\";\nimport { GingerLocaleProvider } from \"./GingerLocaleContext\";\nimport {\n GingerMediaContext,\n type GingerMediaContextValue,\n GingerPlaybackContext,\n type GingerPlaybackContextValue,\n} from \"./GingerSplitContexts\";\n\nconst defaultProviderStyle: CSSProperties = {\n [\"--ginger-primary-color\" as string]: \"#111827\",\n [\"--ginger-muted-color\" as string]: \"#6b7280\",\n [\"--ginger-font-size\" as string]: \"14px\",\n [\"--ginger-font-family\" as string]: \"system-ui, sans-serif\",\n [\"--ginger-playlist-row-padding\" as string]: \"6px 8px\",\n [\"--ginger-artwork-radius\" as string]: \"6px\",\n [\"--ginger-artwork-bg\" as string]: \"#f3f4f6\",\n [\"--ginger-playlist-active-bg\" as string]: \"rgba(17, 24, 39, 0.06)\",\n [\"--ginger-buffer-color\" as string]: \"rgba(107, 114, 128, 0.35)\",\n [\"--ginger-focus-ring\" as string]: \"0 0 0 2px rgba(59, 130, 246, 0.45)\",\n};\n\nexport function GingerProvider({\n children,\n initialTracks = [],\n initialIndex = 0,\n initialPlaylistMeta = null,\n initialShuffle = false,\n initialRepeatMode = \"off\",\n initialPlaybackMode = \"playlist\",\n initialPaused = true,\n initialVolume = 1,\n initialMuted = false,\n initialPlaybackRate = 1,\n initialStateKey,\n locale,\n mediaSession = false,\n beforePlay,\n onPlayBlocked,\n persistence,\n hydrateOnMount = false,\n resumeOnTrackChange = false,\n unstyled = false,\n asChild = false,\n className,\n style,\n dir: dirProp,\n prevRestartThresholdSeconds = 3,\n onTrackChange,\n onPlay,\n onPause,\n onQueueEnd,\n onError,\n onVolumeChange,\n onPlaybackRateChange,\n onSeek,\n}: GingerProviderProps) {\n const audioRef = useRef<HTMLAudioElement | null>(null);\n const [state, dispatch] = useReducer(gingerReducer, undefined, () =>\n createInitialState({\n tracks: initialTracks,\n currentIndex: initialIndex,\n playlistMeta: initialPlaylistMeta,\n isPaused: initialPaused,\n isShuffled: initialShuffle,\n repeatMode: initialRepeatMode,\n playbackMode: initialPlaybackMode,\n volume: initialVolume,\n muted: initialMuted,\n playbackRate: initialPlaybackRate,\n }),\n );\n const stateRef = useRef(state);\n\n const latestInitRef = useRef({\n tracks: initialTracks,\n currentIndex: initialIndex,\n playlistMeta: initialPlaylistMeta,\n isPaused: initialPaused,\n isShuffled: initialShuffle,\n repeatMode: initialRepeatMode,\n playbackMode: initialPlaybackMode,\n volume: initialVolume,\n muted: initialMuted,\n playbackRate: initialPlaybackRate,\n });\n latestInitRef.current = {\n tracks: initialTracks,\n currentIndex: initialIndex,\n playlistMeta: initialPlaylistMeta,\n isPaused: initialPaused,\n isShuffled: initialShuffle,\n repeatMode: initialRepeatMode,\n playbackMode: initialPlaybackMode,\n volume: initialVolume,\n muted: initialMuted,\n playbackRate: initialPlaybackRate,\n };\n\n const prevInitialStateKeyRef = useRef<typeof initialStateKey>(undefined);\n\n useEffect(() => {\n if (initialStateKey === undefined) {\n prevInitialStateKeyRef.current = undefined;\n return;\n }\n if (prevInitialStateKeyRef.current === undefined) {\n prevInitialStateKeyRef.current = initialStateKey;\n return;\n }\n if (prevInitialStateKeyRef.current === initialStateKey) return;\n prevInitialStateKeyRef.current = initialStateKey;\n const p = latestInitRef.current;\n dispatch({\n type: \"INIT\",\n payload: {\n tracks: p.tracks,\n currentIndex: p.currentIndex,\n playlistMeta: p.playlistMeta,\n isPaused: p.isPaused,\n isShuffled: p.isShuffled,\n repeatMode: p.repeatMode,\n playbackMode: p.playbackMode,\n volume: p.volume,\n muted: p.muted,\n playbackRate: p.playbackRate,\n },\n });\n }, [initialStateKey, dispatch]);\n\n useEffect(() => {\n stateRef.current = state;\n }, [state]);\n\n const currentTrack = state.tracks[state.currentIndex] ?? null;\n\n useEffect(() => {\n onTrackChange?.(currentTrack, state.currentIndex);\n }, [currentTrack, state.currentIndex, onTrackChange]);\n\n useEffect(() => {\n if (state.errorMessage) onError?.(state.errorMessage);\n }, [state.errorMessage, onError]);\n\n const prevPausedRef = useRef<boolean | undefined>(undefined);\n useEffect(() => {\n if (prevPausedRef.current === undefined) {\n prevPausedRef.current = state.isPaused;\n return;\n }\n if (prevPausedRef.current !== state.isPaused) {\n if (state.isPaused) onPause?.();\n else onPlay?.();\n }\n prevPausedRef.current = state.isPaused;\n }, [state.isPaused, onPause, onPlay]);\n\n const prevVolumeRef = useRef<number | undefined>(undefined);\n const prevMutedRef = useRef<boolean | undefined>(undefined);\n useEffect(() => {\n if (prevVolumeRef.current === undefined || prevMutedRef.current === undefined) {\n prevVolumeRef.current = state.volume;\n prevMutedRef.current = state.muted;\n return;\n }\n if (prevVolumeRef.current !== state.volume || prevMutedRef.current !== state.muted) {\n onVolumeChange?.(state.volume, state.muted);\n }\n prevVolumeRef.current = state.volume;\n prevMutedRef.current = state.muted;\n }, [state.volume, state.muted, onVolumeChange]);\n\n const prevPlaybackRateRef = useRef<number | undefined>(undefined);\n useEffect(() => {\n if (prevPlaybackRateRef.current === undefined) {\n prevPlaybackRateRef.current = state.playbackRate;\n return;\n }\n if (prevPlaybackRateRef.current !== state.playbackRate) {\n onPlaybackRateChange?.(state.playbackRate);\n }\n prevPlaybackRateRef.current = state.playbackRate;\n }, [state.playbackRate, onPlaybackRateChange]);\n\n const play = useCallback(() => {\n dispatch({ type: \"PLAY\" });\n }, []);\n\n const pause = useCallback(() => {\n dispatch({ type: \"PAUSE\" });\n audioRef.current?.pause();\n }, []);\n\n const togglePlayPause = useCallback(() => {\n if (state.isPaused) play();\n else pause();\n }, [pause, play, state.isPaused]);\n\n const seek = useCallback(\n (timeSeconds: number) => {\n const el = audioRef.current;\n if (!el) return;\n if (!Number.isFinite(timeSeconds)) return;\n el.currentTime = Math.max(0, timeSeconds);\n onSeek?.(Math.max(0, timeSeconds));\n },\n [onSeek],\n );\n\n const setVolume = useCallback((volume: number) => {\n dispatch({ type: \"SET_VOLUME\", payload: clampVolume(volume) });\n }, []);\n\n const setMuted = useCallback((muted: boolean) => {\n dispatch({ type: \"SET_MUTED\", payload: muted });\n }, []);\n\n const toggleMute = useCallback(() => {\n dispatch({ type: \"TOGGLE_MUTE\" });\n }, []);\n\n const setPlaybackRate = useCallback((rate: number) => {\n dispatch({ type: \"SET_PLAYBACK_RATE\", payload: clampPlaybackRate(rate) });\n }, []);\n\n const next = useCallback(() => {\n dispatch({ type: \"NEXT\" });\n }, []);\n\n const prev = useCallback(() => {\n const el = audioRef.current;\n const threshold = prevRestartThresholdSeconds ?? 3;\n if (el && threshold > 0 && el.currentTime > threshold) {\n el.currentTime = 0;\n onSeek?.(0);\n } else {\n dispatch({ type: \"PREV\" });\n }\n }, [prevRestartThresholdSeconds, onSeek]);\n\n const setRepeatMode = useCallback((mode: RepeatMode) => {\n dispatch({ type: \"SET_REPEAT\", payload: mode });\n }, []);\n\n const cycleRepeat = useCallback(() => {\n dispatch({ type: \"CYCLE_REPEAT\" });\n }, []);\n\n const toggleShuffle = useCallback(() => {\n dispatch({ type: \"TOGGLE_SHUFFLE\" });\n }, []);\n\n const setQueue = useCallback((tracks: Track[], currentIndex?: number) => {\n dispatch({ type: \"SET_QUEUE\", payload: { tracks, currentIndex } });\n }, []);\n\n const insertTrackAt = useCallback((track: Track, index?: number, autoPlay?: boolean) => {\n dispatch({ type: \"INSERT_TRACK\", payload: { track, index, autoPlay } });\n }, []);\n\n const removeTrackAt = useCallback((index: number) => {\n dispatch({ type: \"REMOVE_TRACK\", payload: { index } });\n }, []);\n\n const moveTrack = useCallback((fromIndex: number, toIndex: number) => {\n dispatch({ type: \"MOVE_TRACK\", payload: { fromIndex, toIndex } });\n }, []);\n\n const enqueueNext = useCallback((track: Track) => {\n dispatch({ type: \"ADD_NEXT\", payload: { track } });\n }, []);\n\n const playTrackAt = useCallback((index: number) => {\n dispatch({ type: \"SET_INDEX\", payload: { index, autoPlay: true } });\n }, []);\n\n const selectTrackAt = useCallback((index: number) => {\n dispatch({ type: \"SET_INDEX\", payload: { index, autoPlay: false } });\n }, []);\n\n const setPlaylistMeta = useCallback((meta: PlaylistMeta | null) => {\n dispatch({ type: \"SET_PLAYLIST_META\", payload: meta });\n }, []);\n\n const setPlaybackMode = useCallback((mode: PlaybackMode) => {\n dispatch({ type: \"SET_PLAYBACK_MODE\", payload: mode });\n }, []);\n\n const init = useCallback((payload: GingerInitPayload) => {\n dispatch({ type: \"INIT\", payload });\n }, []);\n\n useEffect(() => {\n if (!persistence || !hydrateOnMount) return;\n try {\n const volume = persistence.get(\"ginger:volume\");\n const muted = persistence.get(\"ginger:muted\");\n const playbackRate = persistence.get(\"ginger:playbackRate\");\n const repeatMode = persistence.get(\"ginger:repeatMode\");\n const currentIndex = persistence.get(\"ginger:currentIndex\");\n const p = latestInitRef.current;\n dispatch({\n type: \"INIT\",\n payload: {\n tracks: p.tracks,\n playlistMeta: p.playlistMeta,\n isPaused: p.isPaused,\n isShuffled: p.isShuffled,\n playbackMode: p.playbackMode,\n currentIndex: typeof currentIndex === \"number\" ? currentIndex : p.currentIndex,\n repeatMode:\n repeatMode === \"off\" || repeatMode === \"all\" || repeatMode === \"one\"\n ? repeatMode\n : p.repeatMode,\n volume: typeof volume === \"number\" ? volume : p.volume,\n muted: typeof muted === \"boolean\" ? muted : p.muted,\n playbackRate: typeof playbackRate === \"number\" ? playbackRate : p.playbackRate,\n },\n });\n } catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[@lucaismyname/ginger] persistence.get() threw during hydration:\", e);\n }\n }\n }, [hydrateOnMount, persistence]);\n\n useEffect(() => {\n if (!persistence) return;\n try {\n persistence.set(\"ginger:volume\", state.volume);\n persistence.set(\"ginger:muted\", state.muted);\n persistence.set(\"ginger:playbackRate\", state.playbackRate);\n persistence.set(\"ginger:repeatMode\", state.repeatMode);\n persistence.set(\"ginger:currentIndex\", state.currentIndex);\n } catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[@lucaismyname/ginger] persistence.set() threw:\", e);\n }\n }\n }, [\n persistence,\n state.volume,\n state.muted,\n state.playbackRate,\n state.repeatMode,\n state.currentIndex,\n ]);\n\n useEffect(() => {\n if (!persistence || !resumeOnTrackChange) return;\n const track = state.tracks[state.currentIndex];\n if (!track) return;\n const key = `ginger:resume:${trackIdentity(track)}`;\n try {\n const saved = persistence.get(key);\n if (typeof saved === \"number\" && Number.isFinite(saved)) {\n seek(saved);\n }\n } catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[@lucaismyname/ginger] persistence.get() threw during resume:\", e);\n }\n }\n }, [persistence, resumeOnTrackChange, state.currentIndex, state.tracks, seek]);\n\n useEffect(() => {\n if (!persistence || !resumeOnTrackChange) return;\n const track = state.tracks[state.currentIndex];\n if (!track || !(state.currentTime >= 0)) return;\n const key = `ginger:resume:${trackIdentity(track)}`;\n const id = setTimeout(() => {\n try {\n persistence.set(key, state.currentTime);\n } catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[@lucaismyname/ginger] persistence.set() threw during resume save:\", e);\n }\n }\n }, 250);\n return () => clearTimeout(id);\n }, [persistence, resumeOnTrackChange, state.currentIndex, state.tracks, state.currentTime]);\n\n const currentUrl = state.tracks[state.currentIndex]?.fileUrl;\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n if (state.isPaused) {\n el.pause();\n return;\n }\n // Guard against replay loops when a stale \"play\" state lands after queue-end.\n if (el.ended && computeEndedTransition(stateRef.current).kind === \"stop\") {\n dispatch({ type: \"PAUSE\" });\n return;\n }\n let cancelled = false;\n void (async () => {\n if (beforePlay) {\n let allowed = false;\n try {\n allowed = await beforePlay();\n } catch (error) {\n const message = error instanceof Error ? error.message : \"beforePlay rejected\";\n dispatch({ type: \"MEDIA_ERROR\", payload: { message } });\n return;\n }\n if (!allowed) {\n if (!cancelled) {\n dispatch({ type: \"PAUSE\" });\n onPlayBlocked?.();\n }\n return;\n }\n }\n if (cancelled) return;\n void el.play().catch((e: unknown) => {\n const msg =\n e instanceof Error\n ? e.message\n : typeof e === \"string\"\n ? e\n : \"Playback failed (e.g. autoplay blocked or unavailable source)\";\n dispatch({ type: \"MEDIA_ERROR\", payload: { message: msg } });\n });\n })();\n return () => {\n cancelled = true;\n };\n }, [beforePlay, currentUrl, onPlayBlocked, state.isPaused]);\n\n const notifyEnded = useCallback(() => {\n const transition = computeEndedTransition(stateRef.current);\n if (transition.kind === \"replay_same\") {\n const el = audioRef.current;\n if (el) {\n el.currentTime = 0;\n }\n dispatch({ type: \"PLAY\" });\n return;\n }\n if (transition.kind === \"stop\") {\n audioRef.current?.pause();\n dispatch({ type: \"PAUSE\" });\n onQueueEnd?.();\n return;\n }\n const nextIndex = transition.nextIndex;\n dispatch({ type: \"SET_INDEX\", payload: { index: nextIndex, autoPlay: true } });\n }, [onQueueEnd]);\n\n const mediaSessionActions = useMemo(\n () => ({ play, pause, next, prev, seek }),\n [play, pause, next, prev, seek],\n );\n const mediaSessionEnabled = typeof mediaSession === \"object\" ? true : Boolean(mediaSession);\n const mediaSessionBridgeOptions = useMemo(\n () => (typeof mediaSession === \"object\" ? mediaSession : {}),\n [mediaSession],\n );\n useMediaSessionBridge(mediaSessionEnabled, state, mediaSessionActions, mediaSessionBridgeOptions);\n\n const providerDir =\n dirProp ?? (locale?.seek && /[\\u0590-\\u08FF]/.test(locale.seek) ? \"rtl\" : \"ltr\");\n\n const value = useMemo<GingerContextValue>(\n () => ({\n state,\n dispatch,\n audioRef,\n notifyEnded,\n init,\n play,\n pause,\n togglePlayPause,\n seek,\n setVolume,\n setMuted,\n toggleMute,\n setPlaybackRate,\n next,\n prev,\n setRepeatMode,\n cycleRepeat,\n toggleShuffle,\n setQueue,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n playTrackAt,\n selectTrackAt,\n setPlaylistMeta,\n setPlaybackMode,\n }),\n [\n cycleRepeat,\n dispatch,\n init,\n next,\n notifyEnded,\n pause,\n play,\n playTrackAt,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n selectTrackAt,\n prev,\n seek,\n setMuted,\n setPlaybackRate,\n setQueue,\n setRepeatMode,\n setPlaylistMeta,\n setPlaybackMode,\n setVolume,\n state,\n toggleMute,\n togglePlayPause,\n toggleShuffle,\n ],\n );\n\n const playbackValue = useMemo<GingerPlaybackContextValue>(\n () => ({\n tracks: state.tracks,\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n isShuffled: state.isShuffled,\n repeatMode: state.repeatMode,\n originalTracks: state.originalTracks,\n playlistMeta: state.playlistMeta,\n init,\n play,\n pause,\n togglePlayPause,\n next,\n prev,\n setRepeatMode,\n cycleRepeat,\n toggleShuffle,\n playbackMode: state.playbackMode,\n setQueue,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n playTrackAt,\n selectTrackAt,\n setPlaylistMeta,\n setPlaybackMode,\n dispatch,\n }),\n [\n state.tracks,\n state.currentIndex,\n state.isPaused,\n state.isShuffled,\n state.repeatMode,\n state.playbackMode,\n state.originalTracks,\n state.playlistMeta,\n init,\n play,\n pause,\n togglePlayPause,\n next,\n prev,\n setRepeatMode,\n cycleRepeat,\n toggleShuffle,\n setQueue,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n playTrackAt,\n selectTrackAt,\n setPlaylistMeta,\n setPlaybackMode,\n dispatch,\n ],\n );\n\n const mediaValue = useMemo<GingerMediaContextValue>(\n () => ({\n currentTime: state.currentTime,\n duration: state.duration,\n bufferedFraction: state.bufferedFraction,\n isBuffering: state.isBuffering,\n errorMessage: state.errorMessage,\n volume: state.volume,\n muted: state.muted,\n playbackRate: state.playbackRate,\n seek,\n setVolume,\n setMuted,\n toggleMute,\n setPlaybackRate,\n audioRef,\n notifyEnded,\n dispatch,\n }),\n [\n state.currentTime,\n state.duration,\n state.bufferedFraction,\n state.isBuffering,\n state.errorMessage,\n state.volume,\n state.muted,\n state.playbackRate,\n seek,\n setVolume,\n setMuted,\n toggleMute,\n setPlaybackRate,\n audioRef,\n notifyEnded,\n dispatch,\n ],\n );\n\n const playbackUi = derivePlaybackUiState(state);\n\n const mergedStyle = useMemo(\n () => (unstyled ? style : { ...defaultProviderStyle, ...style }),\n [style, unstyled],\n );\n\n const shellProps = useMemo(\n () => ({\n className,\n style: mergedStyle,\n \"data-ginger-playback\": playbackUi,\n dir: providerDir,\n }),\n [className, mergedStyle, playbackUi, providerDir],\n );\n\n const shell = useMemo(() => {\n if (!asChild) {\n return (\n <div\n className={shellProps.className}\n style={shellProps.style}\n data-ginger-playback={shellProps[\"data-ginger-playback\"]}\n dir={shellProps.dir}\n >\n {children}\n </div>\n );\n }\n const only = Children.only(children);\n if (!isValidElement(only)) {\n throw new Error(\"Ginger.Provider asChild expects a single React element child.\");\n }\n const child = only as ReactElement<{ className?: string; style?: CSSProperties }>;\n const childStyle = child.props.style;\n return cloneElement(child as ReactElement<Record<string, unknown>>, {\n className: mergeClassNames(child.props.className, shellProps.className),\n style:\n childStyle && typeof childStyle === \"object\"\n ? { ...childStyle, ...shellProps.style }\n : shellProps.style,\n \"data-ginger-playback\": shellProps[\"data-ginger-playback\"],\n dir: shellProps.dir,\n });\n }, [asChild, children, shellProps]);\n\n return (\n <GingerLocaleProvider locale={locale}>\n <GingerPlaybackContext.Provider value={playbackValue}>\n <GingerMediaContext.Provider value={mediaValue}>\n <GingerContext.Provider value={value}>{shell}</GingerContext.Provider>\n </GingerMediaContext.Provider>\n </GingerPlaybackContext.Provider>\n </GingerLocaleProvider>\n );\n}\n\nfunction mergeClassNames(a?: string, b?: string): string | undefined {\n const merged = [a, b].filter(Boolean).join(\" \");\n return merged === \"\" ? undefined : merged;\n}\n","import { GingerPlayer } from \"./audio/GingerPlayer\";\nimport * as Control from \"./components/controls/Controls\";\nimport * as Current from \"./components/current\";\nimport * as Icon from \"./components/icons\";\nimport { GingerPlaylistCompound } from \"./components/playlist/GingerPlaylist\";\nimport * as Queue from \"./components/queue/QueueDisplay\";\nimport { GingerProvider } from \"./context/GingerProvider\";\n\nexport const Ginger = {\n Provider: GingerProvider,\n Player: GingerPlayer,\n Current: {\n Title: Current.Title,\n Artist: Current.Artist,\n Album: Current.Album,\n Description: Current.Description,\n Copyright: Current.Copyright,\n Genre: Current.Genre,\n Label: Current.Label,\n Isrc: Current.Isrc,\n TrackNumber: Current.TrackNumber,\n Year: Current.Year,\n Lyrics: Current.Lyrics,\n LyricsSynced: Current.LyricsSynced,\n Chapters: Current.Chapters,\n FileUrl: Current.FileUrl,\n Artwork: Current.Artwork,\n QueueIndex: Current.QueueIndex,\n QueueLength: Current.QueueLength,\n QueuePosition: Current.QueuePosition,\n Elapsed: Current.Elapsed,\n Duration: Current.Duration,\n Remaining: Current.Remaining,\n Progress: Current.Progress,\n TimeRail: Current.TimeRail,\n BufferRail: Current.BufferRail,\n PlaybackState: Current.PlaybackState,\n ErrorMessage: Current.ErrorMessage,\n },\n Queue: {\n Title: Queue.Title,\n Subtitle: Queue.Subtitle,\n Description: Queue.Description,\n Copyright: Queue.Copyright,\n Artwork: Queue.Artwork,\n },\n Control: {\n PlayPause: Control.PlayPause,\n Repeat: Control.Repeat,\n Next: Control.Next,\n Previous: Control.Previous,\n Shuffle: Control.Shuffle,\n SeekBar: Control.SeekBar,\n Volume: Control.Volume,\n Mute: Control.Mute,\n PlaybackRate: Control.PlaybackRate,\n },\n Icon: {\n Play: Icon.Play,\n Pause: Icon.Pause,\n SkipForward: Icon.SkipForward,\n SkipBack: Icon.SkipBack,\n Shuffle: Icon.ShuffleIcon,\n Volume2: Icon.Volume2,\n VolumeX: Icon.VolumeX,\n RepeatGlyph: Icon.RepeatGlyph,\n Wrapper: Icon.Wrapper,\n },\n Playlist: GingerPlaylistCompound,\n};\n"],"names":["GingerContext","createContext","useGingerContext","ctx","useContext","readBufferedFraction","el","buffered","duration","GingerPlayer","className","style","preload","crossOrigin","respectReducedMotion","audioRef","dispatch","state","notifyEnded","url","_a","lastTimeSnapshotRef","useRef","lastActiveUrlRef","reducedMotion","setReducedMotion","useState","useEffect","mql","sync","syncTime","force","next","prev","timeThreshold","changedEnough","jsx","e","code","defaultGingerLocale","rate","mergeLocale","partial","GingerLocaleContext","GingerLocaleProvider","locale","children","value","useGingerLocale","formatMmSs","seconds","s","useSeekBarBinding","pb","useGingerPlayback","md","useGingerMedia","useMemo","gingerStateFromContextValues","effectiveDuration","numericValue","ariaValueText","onSeekInput","useVolumeSlider","onVolumeInput","usePlayPauseBinding","options","playL","pauseL","Wrapper","props","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","rest","Pause","Play","RepeatAllPaths","jsxs","Fragment","RepeatGlyph","mode","ShuffleIcon","SkipBack","SkipForward","Volume2","VolumeX","PlayPause","playLabel","pauseLabel","playAriaLabel","pauseAriaLabel","type","onClick","defaultPlayAria","defaultPauseAria","b","Repeat","ariaLabel","repeatMode","cycleRepeat","label","Next","Previous","Shuffle","isShuffled","toggleShuffle","SeekBar","inputStyle","unstyled","mergedStyle","Volume","Mute","muteLabel","unmuteLabel","muted","toggleMute","defaultRates","PlaybackRate","rates","playbackRate","setPlaybackRate","a","r","createTextDisplay","displayName","select","Comp","useGingerState","fallback","empty","node","createTrackFieldDisplay","getCurrentTrack","Title","t","Artist","Album","resolvedAlbumLine","Description","Copyright","Genre","Label","Isrc","TrackNumber","Year","format","y","text","Lyrics","preserveWhitespace","raw","whiteStyle","lrcTag","parseLrc","lrc","lines","rawLine","matches","m","minutes","millis","time","useGingerLyricsSync","tracks","currentIndex","currentTime","currentTrack","line","activeIndex","i","LyricsSynced","activeClassName","lineClassName","listStyle","index","active","useGingerChapters","seek","list","item","chapter","Chapters","formatStart","seekTo","FileUrl","visible","Artwork","sizes","loading","onError","decoding","imgStyle","track","src","resolvedArtwork","alt","QueueIndex","base","QueueLength","QueuePosition","separator","len","length","renderTime","valueSeconds","Elapsed","Duration","Remaining","effectiveRemaining","Progress","fraction","progressFraction","TimeRail","showBuffered","progressPct","bufPct","BufferRail","PlaybackState","derivePlaybackUiState","ErrorMessage","live","GingerPlaylistConfigContext","usePlaylistConfig","GingerPlaylist","rowStyle","renderTrack","playOnSelect","playTrackAt","selectTrackAt","trackIdentity","GingerPlaylistTrack","liProps","buttonRest","defaultLabel","GingerPlaylistCompound","Subtitle","_b","clampVolume","v","clampPlaybackRate","resetTimingOnly","defaultMedia","createInitialState","params","clampIndex","originalTracks","ordered","shuffleWithAnchor","gingerReducer","action","playlistMeta","isPaused","playbackMode","volume","idx","insertIndex","insertTrackAt","removeTrackAt","removedTrack","origIdx","findIndexByTrackIdentity","nextIsShuffled","fromIndex","toIndex","moveTrack","addNextTrack","origCurrentIdx","ap","cycleRepeatMode","snapshot","shuffled","restored","current","newIndex","nextIndex","computeNextIndex","same","prevIndex","computePrevIndex","getMediaSession","useMediaSessionBridge","enabled","actions","stateRef","title","artist","album","artworkUrl","resolveArtworkUrl","ms","seekForwardSeconds","seekBackwardSeconds","details","d","cap","position","defaultProviderStyle","GingerProvider","initialTracks","initialIndex","initialPlaylistMeta","initialShuffle","initialRepeatMode","initialPlaybackMode","initialPaused","initialVolume","initialMuted","initialPlaybackRate","initialStateKey","mediaSession","beforePlay","onPlayBlocked","persistence","hydrateOnMount","resumeOnTrackChange","asChild","dirProp","prevRestartThresholdSeconds","onTrackChange","onPlay","onPause","onQueueEnd","onVolumeChange","onPlaybackRateChange","onSeek","useReducer","latestInitRef","prevInitialStateKeyRef","prevPausedRef","prevVolumeRef","prevMutedRef","prevPlaybackRateRef","play","useCallback","pause","togglePlayPause","timeSeconds","setVolume","setMuted","threshold","setRepeatMode","setQueue","autoPlay","enqueueNext","setPlaylistMeta","meta","setPlaybackMode","init","payload","p","key","saved","id","currentUrl","computeEndedTransition","cancelled","allowed","error","message","msg","transition","mediaSessionActions","mediaSessionEnabled","mediaSessionBridgeOptions","providerDir","playbackValue","mediaValue","playbackUi","shellProps","shell","only","Children","isValidElement","child","childStyle","cloneElement","mergeClassNames","GingerPlaybackContext","GingerMediaContext","merged","Ginger","Current.Title","Current.Artist","Current.Album","Current.Description","Current.Copyright","Current.Genre","Current.Label","Current.Isrc","Current.TrackNumber","Current.Year","Current.Lyrics","Current.LyricsSynced","Current.Chapters","Current.FileUrl","Current.Artwork","Current.QueueIndex","Current.QueueLength","Current.QueuePosition","Current.Elapsed","Current.Duration","Current.Remaining","Current.Progress","Current.TimeRail","Current.BufferRail","Current.PlaybackState","Current.ErrorMessage","Queue.Title","Queue.Subtitle","Queue.Description","Queue.Copyright","Queue.Artwork","Control.PlayPause","Control.Repeat","Control.Next","Control.Previous","Control.Shuffle","Control.SeekBar","Control.Volume","Control.Mute","Control.PlaybackRate","Icon.Play","Icon.Pause","Icon.SkipForward","Icon.SkipBack","Icon.ShuffleIcon","Icon.Volume2","Icon.VolumeX","Icon.RepeatGlyph","Icon.Wrapper"],"mappings":"mMA0CMA,GAAgBC,EAAAA,cAAyC,IAAI,EAE5D,SAASC,IAAuC,CACrD,MAAMC,EAAMC,EAAAA,WAAWJ,EAAa,EACpC,GAAI,CAACG,EAAK,MAAM,IAAI,MAAM,yDAAyD,EACnF,OAAOA,CACT,CCrCA,SAASE,GAAqBC,EAA8B,CAC1D,KAAM,CAAE,SAAAC,EAAU,SAAAC,CAAA,EAAaF,EAC/B,MAAI,EAAEE,EAAW,IAAMD,EAAS,SAAW,EAAU,EAC9C,KAAK,IAAI,EAAGA,EAAS,IAAIA,EAAS,OAAS,CAAC,EAAIC,CAAQ,CACjE,CAEO,SAASC,GAAa,CAC3B,UAAAC,EACA,MAAAC,EACA,QAAAC,EAAU,WACV,YAAAC,EACA,qBAAAC,EAAuB,EACzB,EAAsB,OACpB,KAAM,CAAE,SAAAC,EAAU,SAAAC,EAAU,MAAAC,EAAO,YAAAC,CAAA,EAAgBhB,GAAA,EAC7CiB,IAAMC,EAAAH,EAAM,OAAOA,EAAM,YAAY,IAA/B,YAAAG,EAAkC,UAAW,GACnDC,EAAsBC,EAAAA,OAAO,CACjC,YAAa,GACb,SAAU,GACV,iBAAkB,EAAA,CACnB,EAEKC,EAAmBD,EAAAA,OAAO,EAAE,EAE5B,CAACE,EAAeC,CAAgB,EAAIC,EAAAA,SAAS,EAAK,EAExDC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACb,GAAwB,OAAO,OAAW,IAAa,OAC5D,MAAMc,EAAM,OAAO,WAAW,kCAAkC,EAC1DC,EAAO,IAAMJ,EAAiBG,EAAI,OAAO,EAC/C,OAAAC,EAAA,EACAD,EAAI,iBAAiB,SAAUC,CAAI,EAC5B,IAAMD,EAAI,oBAAoB,SAAUC,CAAI,CACrD,EAAG,CAACf,CAAoB,CAAC,EAEzB,MAAMgB,EAAW,CAACxB,EAAsByB,EAAQ,KAAU,CACxD,MAAMC,EAAO,CACX,YAAa1B,EAAG,YAChB,SAAUA,EAAG,SACb,iBAAkBD,GAAqBC,CAAE,CAAA,EAErC2B,EAAOZ,EAAoB,QAC3Ba,EAAgBV,EAAgB,GAAM,IACtCW,EACJ,KAAK,IAAIH,EAAK,YAAcC,EAAK,WAAW,GAAKC,GACjD,KAAK,IAAIF,EAAK,SAAWC,EAAK,QAAQ,GAAK,KAC3C,KAAK,IAAID,EAAK,iBAAmBC,EAAK,gBAAgB,GAAK,IACzD,CAACF,GAAS,CAACI,IACfd,EAAoB,QAAUW,EAC9BhB,EAAS,CACP,KAAM,oBACN,QAASgB,CAAA,CACV,EACH,EAEAL,OAAAA,EAAAA,UAAU,IAAM,CACd,MAAMrB,EAAKS,EAAS,QACfT,IACLA,EAAG,OAASW,EAAM,OAClBX,EAAG,MAAQW,EAAM,MACnB,EAAG,CAACF,EAAUE,EAAM,OAAQA,EAAM,KAAK,CAAC,EAExCU,EAAAA,UAAU,IAAM,CACd,MAAMrB,EAAKS,EAAS,QACpB,GAAKT,EACL,IAAI,CAACa,EAAK,CACRb,EAAG,gBAAgB,KAAK,EACxBe,EAAoB,QAAU,CAAE,YAAa,GAAI,SAAU,GAAI,iBAAkB,EAAA,EAC7EE,EAAiB,UAAY,IAC/BP,EAAS,CAAE,KAAM,uBAAwB,EAE3CO,EAAiB,QAAU,GAC3B,MACF,CACIjB,EAAG,aAAa,KAAK,IAAMa,IAC7Bb,EAAG,IAAMa,EACTb,EAAG,KAAA,EACHe,EAAoB,QAAU,CAAE,YAAa,GAAI,SAAU,GAAI,iBAAkB,EAAA,GAEnFE,EAAiB,QAAUJ,EAC7B,EAAG,CAACJ,EAAUC,EAAUC,EAAM,aAAcA,EAAM,OAAQE,CAAG,CAAC,EAE9DQ,EAAAA,UAAU,IAAM,CACd,MAAMrB,EAAKS,EAAS,QACfT,IAELA,EAAG,aAAeW,EAAM,aAC1B,EAAG,CAACF,EAAUE,EAAM,aAAcE,CAAG,CAAC,EAGpCiB,EAAAA,IAAC,QAAA,CACC,wBAAsB,SACtB,IAAKrB,EACL,UAAAL,EACA,MAAAC,EACA,QAAAC,EACA,YAAAC,EACA,SAAU,GACV,YAAW,GACX,aAAewB,GAAM,CACnBP,EAASO,EAAE,aAAa,CAC1B,EACA,iBAAmBA,GAAM,CACvB,MAAM/B,EAAK+B,EAAE,cACbhB,EAAoB,QAAU,CAAE,YAAa,GAAI,SAAU,GAAI,iBAAkB,EAAA,EACjFL,EAAS,CACP,KAAM,wBACN,QAAS,CACP,SAAUV,EAAG,SACb,iBAAkBD,GAAqBC,CAAE,CAAA,CAC3C,CACD,CACH,EACA,UAAY+B,GAAMP,EAASO,EAAE,cAAe,EAAI,EAChD,SAAWA,GAAMP,EAASO,EAAE,cAAe,EAAI,EAC/C,QAAS,IAAMnB,EAAA,EACf,OAAQ,IAAMF,EAAS,CAAE,KAAM,aAAc,EAC7C,QAAS,IAAMA,EAAS,CAAE,KAAM,cAAe,EAC/C,UAAW,IAAMA,EAAS,CAAE,KAAM,gBAAiB,EACnD,UAAW,IAAMA,EAAS,CAAE,KAAM,gBAAiB,EACnD,WAAaqB,GAAMP,EAASO,EAAE,cAAe,EAAI,EACjD,eAAiBA,GAAM,CACrB,MAAM/B,EAAK+B,EAAE,cACbrB,EAAS,CACP,KAAM,oBACN,QAAS,CAAE,OAAQV,EAAG,OAAQ,MAAOA,EAAG,KAAA,CAAM,CAC/C,CACH,EACA,QAAS,IAAM,OACb,MAAMA,EAAKS,EAAS,QACduB,GAAOlB,EAAAd,GAAA,YAAAA,EAAI,QAAJ,YAAAc,EAAW,KAWxBJ,EAAS,CAAE,KAAM,cAAe,QAAS,CAAE,QATzCsB,IAAS,EACL,oBACAA,IAAS,EACP,oBACAA,IAAS,EACP,mBACAA,IAAS,EACP,8BACA,mBAC+B,EAAW,CACxD,CAAA,CAAA,CAGN,CCxJO,MAAMC,EAA4C,CACvD,KAAM,OACN,OAAQ,SACR,cAAe,iBACf,aAAc,WACd,iBAAkB,gBAClB,UAAW,aACX,cAAe,iBACf,QAAS,UACT,KAAM,OACN,OAAQ,SACR,KAAM,OACN,MAAO,QACP,OAAQ,CACN,IAAK,aACL,IAAK,aACL,IAAK,YAAA,EAEP,mBAAoB,YACpB,kBAAoBC,GAAS,GAAGA,CAAI,GACtC,EAEA,SAASC,GAAYC,EAA+D,CAClF,OAAKA,EACE,CACL,GAAGH,EACH,GAAGG,EACH,OAAQ,CAAE,GAAGH,EAAoB,OAAQ,GAAGG,EAAQ,MAAA,CAAO,EAJxCH,CAMvB,CAEA,MAAMI,GAAsB1C,EAAAA,cAAoCsC,CAAmB,EAE5E,SAASK,GAAqB,CACnC,OAAAC,EACA,SAAAC,CACF,EAGG,CACD,MAAMC,EAAQN,GAAYI,CAAM,EAChC,OAAOT,EAAAA,IAACO,GAAoB,SAApB,CAA6B,MAAAI,EAAe,SAAAD,CAAA,CAAS,CAC/D,CAEO,SAASE,GAAwC,CACtD,OAAO5C,EAAAA,WAAWuC,EAAmB,CACvC,CCjDO,SAASM,EAAWC,EAAyB,CAClD,GAAI,CAAC,OAAO,SAASA,CAAO,GAAKA,EAAU,EAAG,MAAO,OACrD,MAAMC,EAAI,KAAK,MAAMD,EAAU,EAAE,EAEjC,MAAO,GADG,KAAK,MAAMA,EAAU,EAAE,CACtB,IAAIC,EAAE,WAAW,SAAS,EAAG,GAAG,CAAC,EAC9C,CCoBO,SAASC,IAAoC,CAClD,MAAMC,EAAKC,EAAAA,kBAAA,EACLC,EAAKC,EAAAA,eAAA,EACLX,EAASG,EAAA,EACT/B,EAAQwC,UAAQ,IAAMC,+BAA6BL,EAAIE,CAAE,EAAG,CAACF,EAAIE,CAAE,CAAC,EACpE/C,EAAWmD,EAAAA,kBAAkB1C,CAAK,EAClC8B,EAAQvC,EAAW,EAAIS,EAAM,YAAc,EAC3C2C,EAAe,OAAO,SAASb,CAAK,EAAIA,EAAQ,EAChDc,EACJrD,EAAW,EACP,GAAGyC,EAAWW,CAAY,CAAC,OAAOX,EAAWzC,CAAQ,CAAC,GACtDyC,EAAWW,CAAY,EAEvBE,EAAezB,GAAmC,CACtDkB,EAAG,KAAK,OAAOlB,EAAE,cAAc,KAAK,CAAC,CACvC,EAEA,MAAO,CACL,MAAApB,EACA,MAAO2C,EACP,IAAK,EACL,IAAKpD,EAAW,EAAIA,EAAW,EAC/B,KAAM,MACN,cAAAqD,EACA,UAAWhB,EAAO,KAClB,YAAAiB,EACA,aAAcA,CAAA,CAElB,CAeO,SAASC,IAAiC,CAC/C,MAAMV,EAAKC,EAAAA,kBAAA,EACLC,EAAKC,EAAAA,eAAA,EACLX,EAASG,EAAA,EACT/B,EAAQwC,UAAQ,IAAMC,+BAA6BL,EAAIE,CAAE,EAAG,CAACF,EAAIE,CAAE,CAAC,EAEpES,EAAiB3B,GAAmC,CACxDkB,EAAG,UAAU,OAAOlB,EAAE,cAAc,KAAK,CAAC,CAC5C,EAEA,MAAO,CACL,MAAApB,EACA,MAAOA,EAAM,OACb,IAAK,EACL,IAAK,EACL,KAAM,MACN,cAAe,GAAG,KAAK,MAAMA,EAAM,OAAS,GAAG,CAAC,IAChD,UAAW4B,EAAO,OAClB,cAAAmB,EACA,eAAgBA,CAAA,CAEpB,CAUO,SAASC,GAAoBC,EAGf,CACnB,MAAMb,EAAKC,EAAAA,kBAAA,EACLT,EAASG,EAAA,EACTmB,GAAQD,GAAA,YAAAA,EAAS,gBAAiBrB,EAAO,KACzCuB,GAASF,GAAA,YAAAA,EAAS,iBAAkBrB,EAAO,MACjD,MAAO,CACL,SAAUQ,EAAG,SACb,OAAQA,EAAG,gBACX,UAAWA,EAAG,SAAWc,EAAQC,CAAA,CAErC,CC9GO,SAASC,EACdC,EAYA,CACA,KAAM,CACJ,UAAA5D,EACA,MAAA6D,EACA,OAAAC,EACA,QAAAC,EACA,KAAAC,EACA,OAAAC,EACA,YAAAC,EACA,cAAAC,EACA,eAAAC,EACA,SAAAhC,EACA,GAAGiC,CAAA,EACDT,EACJ,OACElC,EAAAA,IAAC,MAAA,CACC,wBAAsB,UACtB,MAAM,6BACN,MAAOmC,GAAS,GAChB,OAAQC,GAAU,GAClB,QAASC,GAAW,YACpB,KAAK,OACL,OAAQE,GAAU,eAClB,YAAaC,GAAe,EAC5B,cAAeC,GAAiB,QAChC,eAAgBC,GAAkB,QAClC,UAAApE,EACA,cAAW,GACX,KAAK,eACJ,GAAGqE,EAEH,SAAAjC,CAAA,CAAA,CAGP,CC9CO,SAASkC,IAAQ,CACtB,OACE5C,MAACiC,GACC,SAAAjC,EAAAA,IAAC,OAAA,CAAK,wBAAsB,QAAQ,EAAE,6BAA6B,CAAA,CACrE,CAEJ,CCPO,SAAS6C,IAAO,CACrB,OACE7C,MAACiC,GACC,SAAAjC,EAAAA,IAAC,OAAA,CAAK,wBAAsB,OAAO,EAAE,uBAAuB,CAAA,CAC9D,CAEJ,CCDA,SAAS8C,IAAiB,CACxB,OACEC,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAhD,EAAAA,IAAC,OAAA,CAAK,EAAE,eAAA,CAAgB,EACxBA,EAAAA,IAAC,OAAA,CAAK,EAAE,2BAAA,CAA4B,EACpCA,EAAAA,IAAC,OAAA,CAAK,EAAE,eAAA,CAAgB,EACxBA,EAAAA,IAAC,OAAA,CAAK,EAAE,0BAAA,CAA2B,CAAA,EACrC,CAEJ,CAEO,SAASiD,GAAY,CAAE,KAAAC,GAA8B,CAC1D,OAAIA,IAAS,aAERjB,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC8C,GAAA,EAAe,EAChB9C,EAAAA,IAAC,OAAA,CAAK,wBAAsB,cAAc,EAAE,YAAA,CAAa,CAAA,EAC3D,EAGAkD,IAAS,MAETlD,EAAAA,IAACiC,EAAA,CACC,SAAAjC,EAAAA,IAAC8C,GAAA,CAAA,CAAe,EAClB,SAIDb,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC8C,GAAA,EAAe,EAChB9C,EAAAA,IAAC,OAAA,CAAK,wBAAsB,cAAc,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,IAAA,CAAK,CAAA,EAC1E,CAEJ,CCrCO,SAASmD,IAAc,CAC5B,cACGlB,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC,OAAA,CAAK,EAAE,gBAAA,CAAiB,EACzBA,EAAAA,IAAC,OAAA,CAAK,EAAE,eAAA,CAAgB,EACxBA,EAAAA,IAAC,OAAA,CACC,wBAAsB,cACtB,EAAE,8DAAA,CAAA,EAEJA,EAAAA,IAAC,OAAA,CAAK,EAAE,8BAAA,CAA+B,EACvCA,EAAAA,IAAC,OAAA,CAAK,EAAE,2CAAA,CAA4C,CAAA,EACtD,CAEJ,CCbO,SAASoD,IAAW,CACzB,cACGnB,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC,OAAA,CACC,wBAAsB,WACtB,EAAE,0FAAA,CAAA,EAEJA,EAAAA,IAAC,OAAA,CAAK,EAAE,SAAA,CAAU,CAAA,EACpB,CAEJ,CCVO,SAASqD,IAAc,CAC5B,cACGpB,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC,OAAA,CAAK,EAAE,UAAA,CAAW,EACnBA,EAAAA,IAAC,OAAA,CACC,wBAAsB,cACtB,EAAE,uFAAA,CAAA,CACJ,EACF,CAEJ,CCVO,SAASsD,IAAU,CACxB,cACGrB,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC,OAAA,CACC,wBAAsB,UACtB,EAAE,0KAAA,CAAA,EAEJA,EAAAA,IAAC,OAAA,CAAK,EAAE,qBAAA,CAAsB,EAC9BA,EAAAA,IAAC,OAAA,CAAK,EAAE,mCAAA,CAAoC,CAAA,EAC9C,CAEJ,CCXO,SAASuD,IAAU,CACxB,cACGtB,EAAA,CACC,SAAA,CAAAjC,EAAAA,IAAC,OAAA,CACC,wBAAsB,UACtB,EAAE,0KAAA,CAAA,EAEJA,EAAAA,IAAC,QAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAA,CAAK,EACrCA,EAAAA,IAAC,QAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAA,CAAK,CAAA,EACvC,CAEJ,CCuBO,SAASwD,GAAU,CACxB,UAAAC,EAAY,OACZ,WAAAC,EAAa,QACb,cAAAC,EACA,eAAAC,EACA,SAAAlD,EACA,KAAAmD,EAAO,SACP,QAAAC,EACA,GAAGnB,CACL,EAAmB,CACjB,MAAMlC,EAASG,EAAA,EACTmD,EAAkB,OAAON,GAAc,SAAWA,EAAYhD,EAAO,KACrEuD,EAAmB,OAAON,GAAe,SAAWA,EAAajD,EAAO,MACxEwD,EAAIpC,GAAoB,CAC5B,cAAe8B,GAAiBI,EAChC,eAAgBH,GAAkBI,CAAA,CACnC,EACD,OACEhE,EAAAA,IAAC,SAAA,CACC,wBAAsB,YACrB,GAAG2C,EACJ,KAAAkB,EACA,aAAYI,EAAE,UACd,QAAUhE,GAAM,CACdgE,EAAE,OAAA,EACFH,GAAA,MAAAA,EAAU7D,EACZ,EAEC,aAAagE,EAAE,eAAYpB,GAAA,CAAA,CAAK,QAAMD,GAAA,EAAM,EAAA,CAAA,CAGnD,CAEAY,GAAU,YAAc,2BAOjB,SAASU,GAAO,CAAE,KAAAL,EAAO,SAAU,UAAAM,EAAW,QAAAL,EAAS,SAAApD,EAAU,GAAGiC,GAAqB,CAC9F,KAAM,CAAE,WAAAyB,EAAY,YAAAC,CAAA,EAAgBnD,oBAAA,EAE9BoD,EADS1D,EAAA,EACM,OAAOwD,CAAU,EACtC,OACEpE,EAAAA,IAAC,SAAA,CACC,wBAAsB,SACrB,GAAG2C,EACJ,KAAAkB,EACA,aAAYM,GAAaG,EACzB,QAAUrE,GAAM,CACdoE,EAAA,EACAP,GAAA,MAAAA,EAAU7D,EACZ,EAEC,SAAAS,GAAYV,EAAAA,IAACiD,GAAA,CAAY,KAAMmB,CAAA,CAAY,CAAA,CAAA,CAGlD,CAEAF,GAAO,YAAc,wBAKd,SAASK,GAAK,CAAE,KAAAV,EAAO,SAAU,SAAAnD,EAAU,UAAAyD,EAAW,QAAAL,EAAS,GAAGnB,GAAmB,CAC1F,KAAM,CAAE,KAAA/C,CAAA,EAASsB,oBAAA,EACXT,EAASG,EAAA,EACf,OACEZ,EAAAA,IAAC,SAAA,CACC,wBAAsB,OACrB,GAAG2C,EACJ,KAAAkB,EACA,aAAYM,GAAa1D,EAAO,UAChC,QAAUR,GAAM,CACdL,EAAA,EACAkE,GAAA,MAAAA,EAAU7D,EACZ,EAEC,SAAAS,SAAa2C,GAAA,CAAA,CAAY,CAAA,CAAA,CAGhC,CACAkB,GAAK,YAAc,sBAKZ,SAASC,GAAS,CACvB,KAAAX,EAAO,SACP,SAAAnD,EACA,UAAAyD,EACA,QAAAL,EACA,GAAGnB,CACL,EAAkB,CAChB,KAAM,CAAE,KAAA9C,CAAA,EAASqB,oBAAA,EACXT,EAASG,EAAA,EACf,OACEZ,EAAAA,IAAC,SAAA,CACC,wBAAsB,WACrB,GAAG2C,EACJ,KAAAkB,EACA,aAAYM,GAAa1D,EAAO,cAChC,QAAUR,GAAM,CACdJ,EAAA,EACAiE,GAAA,MAAAA,EAAU7D,EACZ,EAEC,SAAAS,SAAa0C,GAAA,CAAA,CAAS,CAAA,CAAA,CAG7B,CACAoB,GAAS,YAAc,0BAKhB,SAASC,GAAQ,CAAE,KAAAZ,EAAO,SAAU,SAAAnD,EAAU,UAAAyD,EAAW,QAAAL,EAAS,GAAGnB,GAAsB,CAChG,KAAM,CAAE,WAAA+B,EAAY,cAAAC,CAAA,EAAkBzD,oBAAA,EAChCT,EAASG,EAAA,EACf,OACEZ,EAAAA,IAAC,SAAA,CACC,wBAAsB,UACrB,GAAG2C,EACJ,KAAAkB,EACA,eAAca,EACd,aAAYP,GAAa1D,EAAO,QAChC,QAAUR,GAAM,CACd0E,EAAA,EACAb,GAAA,MAAAA,EAAU7D,EACZ,EAEC,SAAAS,SAAayC,GAAA,CAAA,CAAY,CAAA,CAAA,CAGhC,CACAsB,GAAQ,YAAc,yBAYf,SAASG,GAAQ,CAAE,WAAAC,EAAY,MAAAtG,EAAO,SAAAuG,EAAW,GAAO,UAAAX,EAAW,GAAGxB,GAAsB,CACjG,MAAMsB,EAAIjD,GAAA,EACJ+D,EAAcD,EAChB,CAAE,GAAGvG,EAAO,GAAGsG,GACf,CAAE,MAAO,OAAQ,GAAGtG,EAAO,GAAGsG,CAAA,EAClC,OACE7E,EAAAA,IAAC,QAAA,CACC,wBAAsB,UACrB,GAAG2C,EACJ,KAAK,QACL,IAAKsB,EAAE,IACP,IAAKA,EAAE,IACP,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,aAAYE,GAAaF,EAAE,UAC3B,iBAAgBA,EAAE,cAClB,QAASA,EAAE,YACX,SAAUA,EAAE,aACZ,MAAOc,CAAA,CAAA,CAGb,CAEAH,GAAQ,YAAc,yBAYf,SAASI,GAAO,CAAE,WAAAH,EAAY,MAAAtG,EAAO,SAAAuG,EAAW,GAAO,UAAAX,EAAW,GAAGxB,GAAqB,CAC/F,MAAMsB,EAAItC,GAAA,EACJoD,EAAcD,EAChB,CAAE,GAAGvG,EAAO,GAAGsG,GACf,CAAE,MAAO,OAAQ,GAAGtG,EAAO,GAAGsG,CAAA,EAClC,OACE7E,EAAAA,IAAC,QAAA,CACC,wBAAsB,SACrB,GAAG2C,EACJ,KAAK,QACL,IAAKsB,EAAE,IACP,IAAKA,EAAE,IACP,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,aAAYE,GAAaF,EAAE,UAC3B,iBAAgBA,EAAE,cAClB,QAASA,EAAE,cACX,SAAUA,EAAE,eACZ,MAAOc,CAAA,CAAA,CAGb,CAEAC,GAAO,YAAc,wBASd,SAASC,GAAK,CACnB,UAAAd,EACA,UAAAe,EACA,YAAAC,EACA,KAAAtB,EAAO,SACP,QAAAC,EACA,SAAApD,EACA,GAAGiC,CACL,EAAc,CACZ,KAAM,CAAE,MAAAyC,EAAO,WAAAC,CAAA,EAAejE,iBAAA,EACxBX,EAASG,EAAA,EACf,OACEZ,EAAAA,IAAC,SAAA,CACC,wBAAsB,OACrB,GAAG2C,EACJ,KAAAkB,EACA,eAAcuB,EACd,aAAYjB,IAAciB,EAAQ3E,EAAO,OAASA,EAAO,MACzD,QAAUR,GAAM,CACdoF,EAAA,EACAvB,GAAA,MAAAA,EAAU7D,EACZ,EAEC,SAAAS,IAAa0E,EAASD,GAAenF,EAAAA,IAACuD,KAAQ,EAAO2B,SAAc5B,GAAA,CAAA,CAAQ,EAAA,CAAA,CAGlF,CAEA2B,GAAK,YAAc,sBAEnB,MAAMK,GAAe,CAAC,GAAK,IAAM,EAAG,KAAM,IAAK,CAAC,EAYzC,SAASC,GAAa,CAC3B,MAAAC,EAAQF,GACR,MAAA/G,EACA,UAAA4F,EACA,SAAAzD,EACA,GAAGiC,CACL,EAAsB,CACpB,KAAM,CAAE,aAAA8C,EAAc,gBAAAC,CAAA,EAAoBtE,iBAAA,EACpCX,EAASG,EAAA,EACTkB,EAAUT,EAAAA,QACd,IAAM,MAAM,KAAK,IAAI,IAAI,CAAC,GAAGmE,EAAOC,CAAY,CAAC,CAAC,EAAE,KAAK,CAACE,EAAG1B,IAAM0B,EAAI1B,CAAC,EACxE,CAACuB,EAAOC,CAAY,CAAA,EAEtB,OACEzF,EAAAA,IAAC,SAAA,CACC,wBAAsB,eACrB,GAAG2C,EACJ,aAAYwB,GAAa1D,EAAO,cAChC,MAAO,OAAOgF,CAAY,EAC1B,MAAAlH,EACA,SAAW0B,GAAMyF,EAAgB,OAAOzF,EAAE,cAAc,KAAK,CAAC,EAE7D,SAAAS,GACCoB,EAAQ,IAAK8D,GACX5F,EAAAA,IAAC,SAAA,CAAe,MAAO,OAAO4F,CAAC,EAC5B,SAAAA,IAAM,EAAInF,EAAO,mBAAqBA,EAAO,kBAAkBmF,CAAC,CAAA,EADtDA,CAEb,CACD,CAAA,CAAA,CAGT,CAEAL,GAAa,YAAc,8BC7TpB,SAASM,EACdC,EACAC,EACkD,CAClD,SAASC,EAAK9D,EAAyB,CACrC,MAAMrD,EAAQoH,EAAAA,eAAA,EAERtF,GADMoF,EAAOlH,CAAK,GAAK,IACX,KAAA,EACZ,CAAE,UAAAP,EAAW,MAAAC,EAAO,SAAA2H,EAAU,MAAAC,EAAO,SAAAzF,GAAawB,EACxD,GAAI,CAACvB,EAAO,CACV,MAAMyF,EAAOD,GAASD,GAAY,KAClC,OAAOE,EACLpG,MAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,WACH,EACE,IACN,CACA,OAAImC,QAEC,OAAA,CAAK,UAAApC,EAAsB,MAAAC,EACzB,SAAAmC,EAASC,EAAO9B,CAAK,EACxB,EAGFmB,EAAAA,IAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,SAAAoC,EACH,CAEJ,CACA,OAAAqF,EAAK,YAAcF,EACZE,CACT,CAEO,SAASK,EACdP,EACAC,EACkD,CAClD,OAAOF,EAAkBC,EAAcjH,GAAUkH,EAAOO,EAAAA,gBAAgBzH,CAAK,CAAC,CAAC,CACjF,CC5CO,MAAM0H,GAAQF,EAAwB,uBAAyBG,GAAMA,GAAA,YAAAA,EAAG,KAAK,EACvEC,GAASJ,EAAwB,wBAA0BG,GAAMA,GAAA,YAAAA,EAAG,MAAM,EAC1EE,GAAQb,EAAkB,uBAAyB9E,GAAM4F,EAAAA,kBAAkB5F,CAAC,CAAC,EAC7E6F,GAAcP,EACzB,6BACCG,GAAMA,GAAA,YAAAA,EAAG,WACZ,EACaK,GAAYhB,EAAkB,2BAA6B9E,GAAM,OAC5E,MAAMyF,EAAIF,EAAAA,gBAAgBvF,CAAC,EAC3B,OAAOyF,GAAA,YAAAA,EAAG,cAAaxH,EAAA+B,EAAE,eAAF,YAAA/B,EAAgB,UACzC,CAAC,EACY8H,GAAQT,EAAwB,uBAAyBG,GAAMA,GAAA,YAAAA,EAAG,KAAK,EACvEO,GAAQV,EAAwB,uBAAyBG,GAAMA,GAAA,YAAAA,EAAG,KAAK,EACvEQ,GAAOX,EAAwB,sBAAwBG,GAAMA,GAAA,YAAAA,EAAG,IAAI,EACpES,GAAcZ,EAAwB,6BAA+BG,IAChFA,GAAA,YAAAA,EAAG,cAAe,KAAO,OAAOA,EAAE,WAAW,EAAI,MACnD,ECXO,SAASU,GAAK,CAAE,UAAA5I,EAAW,MAAAC,EAAO,SAAA2H,EAAU,MAAAC,EAAO,SAAAzF,EAAU,OAAAyG,GAAqB,OACvF,MAAMtI,EAAQoH,EAAAA,eAAA,EACRmB,GAAId,EAAAA,EAAAA,gBAAgBzH,CAAK,IAArByH,YAAAA,EAAwB,KAClC,GAAI,OAAOc,GAAM,UAAY,CAAC,OAAO,SAASA,CAAC,EAAG,CAChD,MAAMhB,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,OAAO,UAAA9H,EAAsB,MAAAC,EACtD,WACH,EACE,IACN,CACA,MAAM8I,EAAOF,EAASA,EAAOC,CAAC,EAAI,OAAOA,CAAC,EAC1C,OAAI1G,EAEAV,MAAC,QAAK,wBAAsB,OAAO,UAAA1B,EAAsB,MAAAC,EACtD,SAAAmC,EAAS2G,EAAMxI,CAAK,CAAA,CACvB,QAGD,OAAA,CAAK,wBAAsB,OAAO,UAAAP,EAAsB,MAAAC,EACtD,SAAA8I,EACH,CAEJ,CAEAH,GAAK,YAAc,sBCpBZ,SAASI,GAAO,CACrB,UAAAhJ,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAAzF,EACA,mBAAA6G,EAAqB,GACrB,SAAAzC,EAAW,EACb,EAAgB,OACd,MAAMjG,EAAQoH,EAAAA,eAAA,EACRuB,IAAMlB,EAAAA,EAAAA,gBAAgBzH,CAAK,IAArByH,YAAAA,EAAwB,SAAU,GACxC3F,EAAQ4G,EAAqBC,EAAI,QAAQ,aAAc,EAAE,EAAIA,EAAI,KAAA,EACvE,GAAI,CAAC7G,EAAO,CACV,MAAMyF,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,SAAS,UAAA9H,EAAsB,MAAAC,EACxD,WACH,EACE,IACN,CACA,MAAMkJ,EACJ,CAAC3C,GAAYyC,EAAqB,CAAE,WAAY,YAAe,OACjE,OAAI7G,EAEAV,EAAAA,IAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAO,CAAE,GAAGmJ,EAAY,GAAGlJ,CAAA,EACpD,SAAAmC,EAASC,EAAO9B,CAAK,CAAA,CACxB,EAGFmB,MAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAO,CAAE,GAAGmJ,EAAY,GAAGlJ,CAAA,EACpD,SAAAoC,CAAA,CACH,CAEJ,CAEA2G,GAAO,YAAc,wBC3CrB,MAAMI,GAAS,yCAER,SAASC,GAASC,EAA+B,CACtD,MAAMC,EAA0B,CAAA,EAChC,UAAWC,KAAWF,EAAI,MAAM,OAAO,EAAG,CACxC,MAAMG,EAAU,CAAC,GAAGD,EAAQ,SAASJ,EAAM,CAAC,EAC5C,GAAIK,EAAQ,SAAW,EAAG,SAC1B,MAAMV,EAAOS,EAAQ,QAAQJ,GAAQ,EAAE,EAAE,KAAA,EACzC,UAAWM,KAAKD,EAAS,CACvB,MAAME,EAAU,OAAOD,EAAE,CAAC,GAAK,CAAC,EAC1BlH,EAAU,OAAOkH,EAAE,CAAC,GAAK,CAAC,EAC1BE,EAAS,QAAQF,EAAE,CAAC,GAAK,KAAK,OAAO,EAAG,GAAG,CAAC,EAC5CG,EAAOF,EAAU,GAAKnH,EAAUoH,EAAS,IAC3C,OAAO,SAASC,CAAI,GAAKA,GAAQ,GACnCN,EAAM,KAAK,CAAE,KAAAM,EAAM,KAAAd,CAAA,CAAM,CAE7B,CACF,CACA,OAAOQ,EAAM,KAAK,CAAClC,EAAG1B,IAAM0B,EAAE,KAAO1B,EAAE,IAAI,CAC7C,CCdO,SAASmE,IAA6C,CAC3D,KAAM,CAAE,OAAAC,EAAQ,aAAAC,CAAA,EAAiBpH,oBAAA,EAC3B,CAAE,YAAAqH,CAAA,EAAgBnH,iBAAA,EAClBoH,EAAeH,EAAOC,CAAY,EAElCT,EAAQxG,EAAAA,QAAQ,IACfmH,EACD,MAAM,QAAQA,EAAa,WAAW,GAAKA,EAAa,YAAY,OAAS,EACxE,CAAC,GAAGA,EAAa,WAAW,EAChC,OAAQC,GAAS,OAAO,SAASA,EAAK,IAAI,GAAKA,EAAK,MAAQ,CAAC,EAC7D,KAAK,CAAC9C,EAAG1B,IAAM0B,EAAE,KAAO1B,EAAE,IAAI,EAE/B,OAAOuE,EAAa,QAAW,SAC1Bb,GAASa,EAAa,MAAM,EAE9B,CAAA,EATmB,CAAA,EAUzB,CAACA,CAAY,CAAC,EAEXE,EAAcrH,EAAAA,QAAQ,IAAM,CAChC,QAASsH,EAAId,EAAM,OAAS,EAAGc,GAAK,EAAGA,GAAK,EAC1C,GAAIJ,GAAeV,EAAMc,CAAC,EAAG,KAAM,OAAOA,EAE5C,MAAO,EACT,EAAG,CAACJ,EAAaV,CAAK,CAAC,EAEvB,MAAO,CACL,MAAAA,EACA,YAAAa,EACA,WAAYA,GAAe,EAAKb,EAAMa,CAAW,GAAK,KAAQ,IAAA,CAElE,CCnBO,SAASE,GAAa,CAC3B,UAAAtK,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAArB,EAAW,GACX,gBAAA+D,EACA,cAAAC,EACA,SAAApI,CACF,EAAsB,CACpB,MAAM7B,EAAQoH,EAAAA,eAAA,EACRxF,EAASG,EAAA,EACT,CAAE,MAAAiH,EAAO,YAAAa,CAAA,EAAgBN,GAAA,EAE/B,GAAIP,EAAM,SAAW,EAAG,CACtB,MAAMzB,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,eAAe,UAAA9H,EAAsB,MAAAC,EAC9D,WACH,EACE,IACN,CAEA,MAAMwK,EAA2BjE,EAC7B,GACA,CACE,UAAW,OACX,OAAQ,EACR,QAAS,EACT,WAAY,mDACZ,SAAU,gCACV,MAAO,sCAAA,EAGb,OACE9E,EAAAA,IAAC,KAAA,CACC,UAAA1B,EACA,MAAO,CAAE,GAAGyK,EAAW,GAAGxK,CAAA,EAC1B,aAAYkC,EAAO,iBAElB,SAAAoH,EAAM,IAAI,CAACY,EAAMO,IAAU,CAC1B,MAAMC,EAASD,IAAUN,EACzB,OACE1I,EAAAA,IAAC,KAAA,CAEC,eAAciJ,EAAS,OAAS,OAChC,qBAAoBA,GAAU,OAC9B,UACE,CAACH,EAAeG,EAASJ,EAAkB,MAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAC9E,OAEF,MACE/D,EACI,OACA,CACE,QAAS,8CACT,WAAYmE,EAAS,IAAM,IAC3B,QAASA,EAAS,EAAI,GAAA,EAI7B,WAAWvI,EAAS+H,EAAMO,EAAOC,EAAQpK,CAAK,EAAI4J,EAAK,IAAA,EAjBnD,GAAGA,EAAK,IAAI,IAAIO,CAAK,EAAA,CAoBhC,CAAC,CAAA,CAAA,CAGP,CAEAJ,GAAa,YAAc,8BC3EpB,SAASM,IAAwC,CACtD,KAAM,CAAE,OAAAb,EAAQ,aAAAC,CAAA,EAAiBpH,oBAAA,EAC3B,CAAE,YAAAqH,EAAa,KAAAY,CAAA,EAAS/H,iBAAA,EAExBgI,EAAO/H,EAAAA,QAAQ,IAAM,OAEzB,MAAO,CAAC,KADSrC,EAAAqJ,EAAOC,CAAY,IAAnB,YAAAtJ,EAAsB,WAAY,CAAA,CAChC,EAChB,OAAQqK,GAASA,GAAQ,OAAO,SAASA,EAAK,YAAY,GAAKA,EAAK,cAAgB,CAAC,EACrF,KAAK,CAAC1D,EAAG1B,IAAM0B,EAAE,aAAe1B,EAAE,YAAY,CACnD,EAAG,CAACqE,EAAcD,CAAM,CAAC,EAEnBK,EAAcrH,EAAAA,QAAQ,IAAM,CAChC,GAAI+H,EAAK,SAAW,EAAG,MAAO,GAC9B,QAAST,EAAIS,EAAK,OAAS,EAAGT,GAAK,EAAGA,GAAK,EACzC,GAAIJ,GAAea,EAAKT,CAAC,EAAG,aAAc,OAAOA,EAEnD,MAAO,EACT,EAAG,CAACJ,EAAaa,CAAI,CAAC,EAEtB,MAAO,CACL,KAAAA,EACA,YAAAV,EACA,OAAQA,GAAe,EAAKU,EAAKV,CAAW,GAAK,KAAQ,KACzD,OAASM,GAAkB,CACzB,MAAMM,EAAUF,EAAKJ,CAAK,EACtBM,GAASH,EAAKG,EAAQ,YAAY,CACxC,CAAA,CAEJ,CCvBO,SAASC,GAAS,CACvB,UAAAjL,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAArB,EAAW,GACX,YAAA0E,EAAc3I,EACd,SAAAH,CACF,EAAkB,CAChB,MAAM7B,EAAQoH,EAAAA,eAAA,EACRxF,EAASG,EAAA,EACT,CAAE,KAAAwI,EAAM,YAAAV,EAAa,OAAAe,CAAA,EAAWP,GAAA,EAEtC,GAAIE,EAAK,SAAW,EAAG,CACrB,MAAMhD,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,WAAW,UAAA9H,EAAsB,MAAAC,EAC1D,WACH,EACE,IACN,CAEA,MAAMwK,EAA2BjE,EAC7B,GACA,CACE,UAAW,OACX,OAAQ,EACR,QAAS,EACT,WAAY,mDACZ,SAAU,gCACV,MAAO,sCAAA,EAGb,aACG,KAAA,CAAG,UAAAxG,EAAsB,MAAO,CAAE,GAAGyK,EAAW,GAAGxK,CAAA,EAAS,aAAYkC,EAAO,aAC7E,WAAK,IAAI,CAAC6I,EAASN,IAAU,CAC5B,MAAMC,EAASD,IAAUN,EACzB,aACG,KAAA,CACC,SAAA1I,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,eAAciJ,EAAS,OAAS,OAChC,qBAAoBA,GAAU,OAC9B,QAAS,IAAMQ,EAAOT,CAAK,EAC3B,MAAO,CACL,MAAOlE,EAAW,OAAY,OAC9B,UAAWA,EAAW,OAAY,OAClC,OAAQA,EAAW,OAAY,OAC/B,WAAYA,EACR,OACAmE,EACE,2DACA,cACN,MAAOnE,EAAW,OAAY,UAC9B,KAAMA,EAAW,OAAY,UAC7B,OAAQA,EAAW,OAAY,UAC/B,QAASA,EAAW,OAAY,6CAAA,EAGjC,SAAApE,EACCA,EAAS4I,EAASN,EAAOC,EAAQpK,CAAK,EACpCiG,EACF/B,EAAAA,KAAAC,EAAAA,SAAA,CACG,SAAA,CAAAwG,EAAYF,EAAQ,YAAY,EAAE,IAAEA,EAAQ,KAAA,CAAA,CAC/C,SAEC,OAAA,CACC,SAAA,CAAAtJ,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,QAAS,IAAM,YAAa,QAAA,EACxC,SAAAwJ,EAAYF,EAAQ,YAAY,CAAA,CACnC,EACCA,EAAQ,KAAA,CAAA,CACX,CAAA,CAAA,GAjCG,GAAGA,EAAQ,YAAY,IAAIA,EAAQ,KAAK,EAoCjD,CAEJ,CAAC,CAAA,CACH,CAEJ,CAEAC,GAAS,YAAc,0BC5FhB,SAASG,GAAQ,CACtB,QAAAC,EAAU,GACV,UAAArL,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAAzF,CACF,EAAiB,OACf,MAAM7B,EAAQoH,EAAAA,eAAA,EACd,GAAI,CAAC0D,EAAS,OAAO,KACrB,MAAMhJ,IAAQ2F,EAAAA,EAAAA,gBAAgBzH,CAAK,IAArByH,YAAAA,EAAwB,UAAW,GACjD,GAAI,CAAC3F,EAAO,CACV,MAAMyF,EAAOD,GAASD,GAAY,KAClC,OAAOE,EACLpG,MAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,WACH,EACE,IACN,CACA,OAAImC,EAEAV,MAAC,QAAK,wBAAsB,UAAU,UAAA1B,EAAsB,MAAAC,EACzD,SAAAmC,EAASC,EAAO9B,CAAK,CAAA,CACxB,EAGFmB,EAAAA,IAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,SAAAoC,EACH,CAEJ,CAEA+I,GAAQ,YAAc,yBC7Bf,SAASE,GAAQ,CACtB,UAAAtL,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,MAAA0D,EACA,QAAAC,EACA,QAAAC,EACA,SAAAC,EACA,SAAAlF,EAAW,GACX,SAAAmF,CACF,EAAiB,CACf,MAAMpL,EAAQoH,EAAAA,eAAA,EACRiE,EAAQ5D,EAAAA,gBAAgBzH,CAAK,EAC7BsL,EAAMC,EAAAA,gBAAgBvL,CAAK,EACjC,GAAI,CAACsL,EAAK,CACR,MAAM/D,EAAOD,GAASD,GAAY,KAClC,OAAOE,EACLpG,MAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,WACH,EACE,IACN,CACA,MAAM8L,EAAM,CAACH,GAAA,YAAAA,EAAO,MAAOA,GAAA,YAAAA,EAAO,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,GAAK,UACzE,OACElK,EAAAA,IAAC,MAAA,CACC,wBAAsB,UACtB,UAAA1B,EACA,MACEwG,EACI,CAAE,GAAGvG,GACL,CACE,WAAY,wCACZ,aAAc,kCACd,SAAU,SACV,GAAGA,CAAA,EAIX,SAAAyB,EAAAA,IAAC,MAAA,CACC,IAAAmK,EACA,IAAAE,EACA,MAAAR,EACA,QAAAC,EACA,SAAAE,EACA,QAAAD,EACA,MAAO,CACL,QAASjF,EAAW,OAAY,QAChC,MAAOA,EAAW,OAAY,OAC9B,OAAQA,EAAW,OAAY,OAC/B,UAAWA,EAAW,OAAY,QAClC,GAAGmF,CAAA,CACL,CAAA,CACF,CAAA,CAGN,CAEAL,GAAQ,YAAc,yBC7Df,SAASU,GAAW,CACzB,KAAAC,EAAO,EACP,UAAAjM,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAAzF,CACF,EAAoB,CAClB,MAAM7B,EAAQoH,EAAAA,eAAA,EAEd,GADYpH,EAAM,OAAO,SACb,EAAG,CACb,MAAMuH,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,aAAa,UAAA9H,EAAsB,MAAAC,EAC5D,WACH,EACE,IACN,CACA,MAAMoC,EAAQ,OAAO9B,EAAM,aAAe0L,CAAI,EAC9C,OAAI7J,EAEAV,MAAC,QAAK,wBAAsB,aAAa,UAAA1B,EAAsB,MAAAC,EAC5D,SAAAmC,EAASC,EAAO9B,CAAK,CAAA,CACxB,QAGD,OAAA,CAAK,wBAAsB,aAAa,UAAAP,EAAsB,MAAAC,EAC5D,SAAAoC,EACH,CAEJ,CAEA2J,GAAW,YAAc,4BAMlB,SAASE,GAAY,CAAE,UAAAlM,EAAW,MAAAC,EAAO,SAAA2H,EAAU,MAAAC,EAAO,SAAAzF,GAA8B,CAC7F,MAAM7B,EAAQoH,EAAAA,eAAA,EACRtF,EAAQ,OAAO9B,EAAM,OAAO,MAAM,EACxC,GAAIA,EAAM,OAAO,SAAW,EAAG,CAC7B,MAAMuH,EAAOD,GAASD,GAAY,KAClC,OAAOE,EACLpG,MAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,WACH,EACE,IACN,CACA,OAAImC,EAEAV,MAAC,QAAK,wBAAsB,cAAc,UAAA1B,EAAsB,MAAAC,EAC7D,SAAAmC,EAASC,EAAO9B,CAAK,CAAA,CACxB,QAGD,OAAA,CAAK,wBAAsB,cAAc,UAAAP,EAAsB,MAAAC,EAC7D,SAAAoC,EACH,CAEJ,CAEA6J,GAAY,YAAc,6BAWnB,SAASC,GAAc,CAC5B,KAAAF,EAAO,EACP,UAAAG,EAAY,MACZ,UAAApM,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAAzF,CACF,EAAuB,CACrB,MAAM7B,EAAQoH,EAAAA,eAAA,EACR0E,EAAM9L,EAAM,OAAO,OACzB,GAAI8L,IAAQ,EAAG,CACb,MAAMvE,EAAOD,GAASD,GAAY,KAClC,OAAOE,EACLpG,MAAC,OAAA,CAAK,UAAA1B,EAAsB,MAAAC,EACzB,WACH,EACE,IACN,CACA,MAAMyK,EAAQ,OAAOnK,EAAM,aAAe0L,CAAI,EACxCK,EAAS,OAAOD,CAAG,EACnBrG,EAAQ,GAAG0E,CAAK,GAAG0B,CAAS,GAAGE,CAAM,GAC3C,OAAIlK,EAEAV,EAAAA,IAAC,OAAA,CAAK,wBAAsB,gBAAgB,UAAA1B,EAAsB,MAAAC,EAC/D,SAAAmC,EAAS,CAAE,MAAAsI,EAAO,OAAA4B,EAAQ,MAAAtG,CAAA,EAASzF,CAAK,EAC3C,QAGD,OAAA,CAAK,wBAAsB,gBAAgB,UAAAP,EAAsB,MAAAC,EAC/D,SAAA+F,EACH,CAEJ,CAEAmG,GAAc,YAAc,+BC1G5B,SAASI,GACPC,EACAjM,EACAqD,EACqB,CACrB,KAAM,CAAE,UAAA5D,EAAW,MAAAC,EAAO,SAAA2H,EAAU,MAAAC,EAAO,SAAAzF,EAAU,OAAAyG,EAAStG,GAAeqB,EAC7E,GAAI,EAAE4I,GAAgB,IAAM,CAAC,OAAO,SAASA,CAAY,EAAG,CAC1D,MAAM1E,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,WAAW,UAAA9H,EAAsB,MAAAC,EAC1D,WACH,EACE,IACN,CACA,MAAM8I,EAAOF,EAAO2D,CAAY,EAChC,OAAIpK,EAEAV,MAAC,QAAK,wBAAsB,WAAW,UAAA1B,EAAsB,MAAAC,EAC1D,SAAAmC,EAAS2G,EAAMxI,CAAK,CAAA,CACvB,QAGD,OAAA,CAAK,wBAAsB,WAAW,UAAAP,EAAsB,MAAAC,EAC1D,SAAA8I,EACH,CAEJ,CAEO,SAAS0D,GAAQ7I,EAAsB,CAC5C,MAAMrD,EAAQoH,EAAAA,eAAA,EACd,OAAO4E,GAAWhM,EAAM,YAAaA,EAAOqD,CAAK,CACnD,CAEA6I,GAAQ,YAAc,yBAEf,SAASC,GAAS9I,EAAsB,CAC7C,MAAMrD,EAAQoH,EAAAA,eAAA,EACd,OAAO4E,GAAWtJ,EAAAA,kBAAkB1C,CAAK,EAAGA,EAAOqD,CAAK,CAC1D,CAEA8I,GAAS,YAAc,0BAEhB,SAASC,GAAU/I,EAAsB,CAC9C,MAAMrD,EAAQoH,EAAAA,eAAA,EACd,OAAO4E,GAAWK,EAAAA,mBAAmBrM,CAAK,EAAGA,EAAOqD,CAAK,CAC3D,CAEA+I,GAAU,YAAc,2BASjB,SAASE,GAAS,CAAE,UAAA7M,EAAW,MAAAC,EAAO,SAAA2H,EAAU,MAAAC,EAAO,SAAAzF,GAA2B,CACvF,MAAM7B,EAAQoH,EAAAA,eAAA,EACR7H,EAAWmD,EAAAA,kBAAkB1C,CAAK,EAClCuM,EAAWC,EAAAA,iBAAiBxM,CAAK,EACvC,GAAI,EAAET,EAAW,GAAI,CACnB,MAAMgI,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,WAAW,UAAA9H,EAAsB,MAAAC,EAC1D,WACH,EACE,IACN,CACA,OAAImC,EAEAV,EAAAA,IAAC,OAAA,CAAK,wBAAsB,WAAW,UAAA1B,EAAsB,MAAAC,EAC1D,SAAAmC,EAAS,CAAE,SAAA0K,EAAU,YAAavM,EAAM,YAAa,SAAAT,CAAA,EAAYS,CAAK,EACzE,EAGFmB,EAAAA,IAAC,OAAA,CAAK,wBAAsB,WAAW,UAAA1B,EAAsB,MAAAC,EAC1D,SAAA,GAAG,KAAK,MAAM6M,EAAW,GAAG,CAAC,IAChC,CAEJ,CAEAD,GAAS,YAAc,0BAWhB,SAASG,GAAS,CACvB,UAAAhN,EACA,MAAAC,EACA,OAAA6D,EAAS,EACT,aAAAmJ,EAAe,GACf,SAAAzG,EAAW,EACb,EAAkB,CAChB,MAAMjG,EAAQoH,EAAAA,eAAA,EACRuF,EAAc,GAAG,KAAK,MAAMH,EAAAA,iBAAiBxM,CAAK,EAAI,GAAG,CAAC,IAC1D4M,EAAS,GAAG,KAAK,MAAM,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG5M,EAAM,gBAAgB,CAAC,EAAI,GAAG,CAAC,IACpF,OACEkE,EAAAA,KAAC,MAAA,CACC,wBAAsB,WACtB,UAAAzE,EACA,MACEwG,EACI,CAAE,GAAGvG,GACL,CACE,MAAO,OACP,OAAA6D,EACA,WAAY,qCACZ,aAAc,IACd,SAAU,SACV,SAAU,WACV,GAAG7D,CAAA,EAGX,cAAW,GAEV,SAAA,CAAAgN,EACCvL,EAAAA,IAAC,MAAA,CACC,wBAAsB,WACtB,MAAO,CACL,SAAU8E,EAAW,OAAY,WACjC,KAAMA,EAAW,OAAY,EAC7B,IAAKA,EAAW,OAAY,EAC5B,OAAQA,EAAW,OAAY,OAC/B,MAAO2G,EACP,WAAY3G,EACR,OACA,uDAAA,CACN,CAAA,EAEA,KACJ9E,EAAAA,IAAC,MAAA,CACC,wBAAsB,WACtB,MAAO,CACL,SAAU8E,EAAW,OAAY,WACjC,MAAO0G,EACP,OAAQ1G,EAAW,OAAY,OAC/B,WAAYA,EAAW,OAAY,sCAAA,CACrC,CAAA,CACF,CAAA,CAAA,CAGN,CAEAwG,GAAS,YAAc,0BAShB,SAASI,GAAW,CAAE,UAAApN,EAAW,MAAAC,EAAO,OAAA6D,EAAS,EAAG,SAAA0C,EAAW,IAA0B,CAC9F,MAAMjG,EAAQoH,EAAAA,eAAA,EACRwF,EAAS,GAAG,KAAK,MAAM,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG5M,EAAM,gBAAgB,CAAC,EAAI,GAAG,CAAC,IACpF,OACEmB,EAAAA,IAAC,MAAA,CACC,wBAAsB,aACtB,UAAA1B,EACA,MACEwG,EACI,CAAE,GAAGvG,GACL,CACE,MAAO,OACP,OAAA6D,EACA,WAAY,qCACZ,aAAc,IACd,SAAU,SACV,GAAG7D,CAAA,EAGX,cAAW,GAEX,SAAAyB,EAAAA,IAAC,MAAA,CACC,wBAAsB,aACtB,MAAO,CACL,MAAOyL,EACP,OAAQ3G,EAAW,OAAY,OAC/B,WAAYA,EACR,OACA,uDAAA,CACN,CAAA,CACF,CAAA,CAGN,CAEA4G,GAAW,YAAc,4BCnMlB,SAASC,GAAc,CAAE,UAAArN,EAAW,MAAAC,EAAO,SAAA2H,EAAU,MAAAC,EAAO,SAAAzF,GAAgC,CACjG,MAAM7B,EAAQoH,EAAAA,eAAA,EACRtF,EAAQiL,EAAAA,sBAAsB/M,CAAK,EACzC,OAAI6B,EAEAV,MAAC,QAAK,wBAAsB,gBAAgB,UAAA1B,EAAsB,MAAAC,EAC/D,SAAAmC,EAASC,EAAO9B,CAAK,CAAA,CACxB,QAGD,OAAA,CAAK,wBAAsB,gBAAgB,UAAAP,EAAsB,MAAAC,EAC/D,SAAAoC,EACH,CAEJ,CAEAgL,GAAc,YAAc,+BAOrB,SAASE,GAAa,CAC3B,UAAAvN,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,KAAA2F,EAAO,SACP,SAAApL,CACF,EAAsB,CACpB,MAAM7B,EAAQoH,EAAAA,eAAA,EACRtF,EAAQ9B,EAAM,cAAgB,GACpC,GAAI,CAAC8B,EAAO,CACV,MAAMyF,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,eAAe,UAAA9H,EAAsB,MAAAC,EAC9D,WACH,EACE,IACN,CACA,OAAImC,EAEAV,EAAAA,IAAC,OAAA,CACC,wBAAsB,eACtB,UAAA1B,EACA,MAAAC,EACA,YAAWuN,EAEV,SAAApL,EAASC,EAAO9B,CAAK,CAAA,CAAA,EAK1BmB,MAAC,QAAK,wBAAsB,eAAe,UAAA1B,EAAsB,MAAAC,EAAc,YAAWuN,EACvF,SAAAnL,CAAA,CACH,CAEJ,CAEAkL,GAAa,YAAc,8BCpD3B,MAAME,GAA8BlO,EAAAA,cAA2C,IAAI,EAEnF,SAASmO,IAA0C,CACjD,MAAMjO,EAAMC,EAAAA,WAAW+N,EAA2B,EAClD,GAAI,CAAChO,EACH,MAAM,IAAI,MAAM,6DAA6D,EAE/E,OAAOA,CACT,CAqBO,SAASkO,GAAe,CAC7B,SAAAvL,EACA,SAAAoE,EAAW,GACX,SAAAoH,EACA,YAAAC,EACA,aAAAC,EAAe,GACf,MAAA7N,EACA,GAAGoE,CACL,EAAwB,CACtB,KAAM,CAAE,OAAA0F,EAAQ,aAAAC,EAAc,YAAA+D,EAAa,cAAAC,CAAA,EAAkBpL,EAAAA,kBAAA,EAEvD6H,EAA2BjE,EAC7B,CAAE,GAAGvG,GACL,CACE,UAAW,OACX,OAAQ,EACR,QAAS,EACT,WAAY,mDACZ,SAAU,gCACV,MAAO,uCACP,GAAGA,CAAA,EAKT,OAFemC,IAAa,aAIvBqL,GAA4B,SAA5B,CAAqC,MAAO,CAAE,aAAAK,CAAA,EAC7C,SAAApM,EAAAA,IAAC,KAAA,CAAG,wBAAsB,WAAW,MAAO+I,EAAY,GAAGpG,EACxD,SAAAjC,EACH,EACF,EAKFV,EAAAA,IAAC+L,GAA4B,SAA5B,CAAqC,MAAO,CAAE,aAAAK,GAC7C,SAAApM,EAAAA,IAAC,KAAA,CAAG,wBAAsB,WAAW,MAAO+I,EAAY,GAAGpG,EACxD,WAAO,IAAI,CAACuH,EAAOlB,IAAU,CAC5B,MAAMC,EAASD,IAAUV,EACzB,aACG,KAAA,CACC,SAAAtI,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAM,CACToM,IAA0BpD,CAAK,IAChBA,CAAK,CAC1B,EACA,MAAO,CACL,MAAOlE,EAAW,OAAY,OAC9B,UAAWA,EAAW,OAAY,OAClC,OAAQA,EAAW,OAAY,OAC/B,WAAYA,EACR,OACAmE,EACE,2DACA,cACN,MAAOnE,EAAW,OAAY,UAC9B,KAAMA,EAAW,OAAY,UAC7B,OAAQA,EAAW,OAAY,UAC/B,QAASA,EAAW,OAAY,8CAChC,GAAGoH,CAAA,EAGJ,WACCC,EAAYjC,EAAOlB,EAAOC,CAAM,SAE/B,OAAA,CACE,SAAA,CAAAiB,EAAM,MACNA,EAAM,OAAS,MAAMA,EAAM,MAAM,GAAK,EAAA,CAAA,CACzC,CAAA,CAAA,GA7BG,GAAGlB,CAAK,IAAIuD,EAAAA,cAAcrC,CAAK,CAAC,EAgCzC,CAEJ,CAAC,EACH,EACF,CAEJ,CAEA+B,GAAe,YAAc,kBAUtB,SAASO,GAAoB,CAClC,MAAAxD,EACA,SAAAlE,EAAW,GACX,UAAAxG,EACA,MAAAC,EACA,SAAAmC,EACA,QAAA+L,EACA,QAAA3I,EACA,GAAG4I,CACL,EAA6B,CAC3B,KAAM,CAAE,aAAAN,CAAA,EAAiBJ,GAAA,EACnB,CAAE,OAAA3D,EAAQ,aAAAC,EAAc,YAAA+D,EAAa,cAAAC,CAAA,EAAkBpL,EAAAA,kBAAA,EACvD+H,EAASD,IAAUV,EACnB4B,EAAQ7B,EAAOW,CAAK,EACpB2D,EACJzC,GAAS,KACPnH,EAAAA,KAAC,OAAA,CAAK,wBAAsB,gBACzB,SAAA,CAAAmH,EAAM,MACNA,EAAM,OAAS,MAAMA,EAAM,MAAM,GAAK,EAAA,CAAA,CACzC,EACE,KAEN,OACElK,EAAAA,IAAC,KAAA,CAAI,GAAGyM,EAAS,wBAAsB,gBACrC,SAAAzM,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,wBAAsB,sBACtB,eAAciJ,EAAS,OAAS,OAChC,qBAAoBA,GAAU,OAC9B,UAAA3K,EACA,MAAO,CACL,MAAOwG,EAAW,OAAY,OAC9B,UAAWA,EAAW,OAAY,OAClC,OAAQA,EAAW,OAAY,OAC/B,WAAYA,EACR,OACAmE,EACE,2DACA,cACN,MAAOnE,EAAW,OAAY,UAC9B,KAAMA,EAAW,OAAY,UAC7B,OAAQA,EAAW,OAAY,UAC/B,QAASA,EAAW,OAAY,8CAChC,GAAGvG,CAAA,EAEJ,GAAGmO,EACJ,QAAUzM,GAAM,CACd6D,GAAA,MAAAA,EAAU7D,GACN,CAAAA,EAAE,mBACFmM,IAA0BpD,CAAK,IAChBA,CAAK,EAC1B,EAEC,SAAAtI,GAAYiM,CAAA,CAAA,EAEjB,CAEJ,CAEAH,GAAoB,YAAc,wBAE3B,MAAMI,GAAyB,OAAO,OAAOX,GAAgB,CAClE,MAAOO,EACT,CAAC,ECnMYjG,GAAQV,EAAkB,qBAAuB9E,GAAA,OAAM,OAAA/B,EAAA+B,EAAE,eAAF,YAAA/B,EAAgB,MAAK,EAC5E6N,GAAWhH,EAAkB,wBAA0B9E,GAAA,OAAM,OAAA/B,EAAA+B,EAAE,eAAF,YAAA/B,EAAgB,SAAQ,EACrF4H,GAAcf,EACzB,2BACC9E,GAAA,OAAM,OAAA/B,EAAA+B,EAAE,eAAF,YAAA/B,EAAgB,YACzB,EACa6H,GAAYhB,EACvB,yBACC9E,GAAA,OAAM,OAAA/B,EAAA+B,EAAE,eAAF,YAAA/B,EAAgB,UACzB,EAQO,SAAS4K,GAAQ,CACtB,UAAAtL,EACA,MAAAC,EACA,SAAA2H,EACA,MAAAC,EACA,SAAArB,EAAW,GACX,SAAAmF,CACF,EAAsB,SACpB,MAAMpL,EAAQoH,EAAAA,eAAA,EACRkE,GAAMnL,EAAAH,EAAM,eAAN,YAAAG,EAAoB,WAChC,GAAI,CAACmL,EAAK,CACR,MAAM/D,EAAOD,GAASD,GAAY,KAClC,OAAOE,QACJ,OAAA,CAAK,wBAAsB,UAAU,UAAA9H,EAAsB,MAAAC,EACzD,WACH,EACE,IACN,CACA,MAAM8L,IAAMyC,EAAAjO,EAAM,eAAN,YAAAiO,EAAoB,QAAS,mBACzC,OACE9M,EAAAA,IAAC,OAAA,CACC,wBAAsB,UACtB,UAAA1B,EACA,MACEwG,EACI,CAAE,GAAGvG,GACL,CACE,QAAS,eACT,WAAY,oCACZ,aAAc,oCACd,SAAU,SACV,GAAGA,CAAA,EAIX,SAAAyB,EAAAA,IAAC,MAAA,CACC,IAAAmK,EACA,IAAAE,EACA,MAAO,CACL,QAASvF,EAAW,OAAY,QAChC,MAAOA,EAAW,OAAY,OAC9B,OAAQA,EAAW,OAAY,OAC/B,UAAWA,EAAW,OAAY,QAClC,GAAGmF,CAAA,CACL,CAAA,CACF,CAAA,CAGN,CAEAL,GAAQ,YAAc,uBC5Df,SAASmD,EAAYC,EAAmB,CAC7C,OAAK,OAAO,SAASA,CAAC,EACf,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGA,CAAC,CAAC,EADD,CAElC,CAEO,SAASC,GAAkBrH,EAAmB,CACnD,OAAK,OAAO,SAASA,CAAC,EACf,KAAK,IAAI,EAAG,KAAK,IAAI,IAAMA,CAAC,CAAC,EADJ,CAElC,CAGA,MAAMsH,EAAkB,CACtB,YAAa,EACb,SAAU,EACV,iBAAkB,EAClB,YAAa,GACb,aAAc,IAChB,EAEMC,GAAe,CACnB,GAAGD,EACH,OAAQ,EACR,MAAO,GACP,aAAc,CAChB,EAEO,SAASE,GAAmBC,EAWnB,CACd,MAAMhF,EAAS,CAAC,GAAGgF,EAAO,MAAM,EAChC,IAAI/E,EAAegF,EAAAA,WAAWD,EAAO,cAAgB,EAAGhF,EAAO,MAAM,EACjEkF,EAAiC,KACjCC,EAAUnF,EAEd,OAAIgF,EAAO,YAAchF,EAAO,OAAS,IACvCkF,EAAiB,CAAC,GAAGlF,CAAM,EAC3BmF,EAAUC,EAAAA,kBAAkBpF,EAAQC,CAAY,EAChDA,EAAe,GAGV,CACL,OAAQkF,EACR,aAAAlF,EACA,aAAc+E,EAAO,cAAgB,WACrC,SAAUA,EAAO,UAAY,GAC7B,WAAY,GAAQA,EAAO,YAAcG,EAAQ,OAAS,GAC1D,WAAYH,EAAO,YAAc,MACjC,eAAAE,EACA,aAAcF,EAAO,cAAgB,KACrC,GAAGF,GACH,OAAQJ,EAAYM,EAAO,QAAU,CAAC,EACtC,MAAOA,EAAO,OAAS,GACvB,aAAcJ,GAAkBI,EAAO,cAAgB,CAAC,CAAA,CAE5D,CAEO,SAASK,GAAc7O,EAAoB8O,EAAmC,CACnF,OAAQA,EAAO,KAAA,CACb,IAAK,OAAQ,CACX,KAAM,CACJ,OAAAtF,EACA,aAAAC,EACA,aAAAsF,EACA,SAAAC,EACA,WAAAnJ,EACA,WAAAN,EACA,aAAA0J,EACA,OAAAC,EACA,MAAA3I,EACA,aAAAK,CAAA,EACEkI,EAAO,QACX,OAAOP,GAAmB,CACxB,OAAA/E,EACA,aAAAC,EACA,aAAcsF,GAAgB,KAC9B,SAAUC,GAAY,GACtB,WAAYnJ,GAAc,GAC1B,WAAYN,GAAc,MAC1B,aAAc0J,GAAgB,WAC9B,OAAAC,EACA,MAAA3I,EACA,aAAAK,CAAA,CACD,CACH,CACA,IAAK,YAAa,CAChB,KAAM,CAAE,OAAA4C,EAAQ,aAAAC,CAAA,EAAiBqF,EAAO,QAClC/N,EAAO,CAAC,GAAGyI,CAAM,EACjB2F,EAAMV,EAAAA,WAAWhF,GAAgBzJ,EAAM,aAAce,EAAK,MAAM,EACtE,MAAO,CACL,GAAGf,EACH,OAAQe,EACR,aAAcoO,EACd,WAAY,GACZ,eAAgB,KAChB,GAAGd,CAAA,CAEP,CACA,IAAK,eAAgB,CACnB,MAAMe,EAAcN,EAAO,QAAQ,OAAS9O,EAAM,OAAO,OACnDwJ,EAAS6F,EAAAA,cAAcrP,EAAM,OAAQ8O,EAAO,QAAQ,MAAOM,CAAW,EAC5E,GAAIN,EAAO,QAAQ,SAAU,CAC3B,MAAMK,EAAMV,EAAAA,WAAWW,EAAa5F,EAAO,MAAM,EACjD,MAAO,CACL,GAAGxJ,EACH,OAAAwJ,EACA,aAAc2F,EACd,WAAY,GACZ,eAAgB,KAChB,SAAU,GACV,GAAGd,CAAA,CAEP,CACA,MAAM5E,EACJ2F,GAAepP,EAAM,aAAeA,EAAM,aAAe,EAAIA,EAAM,aAE/D0O,EACJ1O,EAAM,YAAcA,EAAM,eACtBqP,EAAAA,cAAcrP,EAAM,eAAgB8O,EAAO,QAAQ,MAAO9O,EAAM,eAAe,MAAM,EACrFA,EAAM,eACZ,MAAO,CACL,GAAGA,EACH,OAAAwJ,EACA,eAAAkF,EACA,aAAcD,EAAAA,WAAWhF,EAAcD,EAAO,MAAM,CAAA,CAExD,CACA,IAAK,eAAgB,CACnB,MAAMW,EAAQ2E,EAAO,QAAQ,MACvBtF,EAAS8F,EAAAA,cAActP,EAAM,OAAQmK,CAAK,EAC1CV,EACJU,EAAQnK,EAAM,aACVA,EAAM,aAAe,EACrBmK,IAAUnK,EAAM,aACd,KAAK,IAAIA,EAAM,aAAc,KAAK,IAAI,EAAGwJ,EAAO,OAAS,CAAC,CAAC,EAC3DxJ,EAAM,aAER0O,EACJ1O,EAAM,YAAcA,EAAM,gBACrB,IAAM,CACL,MAAMuP,EAAevP,EAAM,OAAOmK,CAAK,EACjCqF,EAAUC,EAAAA,yBAAyBzP,EAAM,eAAgBuP,CAAY,EAC3E,OAAOD,gBAActP,EAAM,eAAgBwP,CAAO,CACpD,GAAA,EACAxP,EAAM,eACN0P,EAAiB1P,EAAM,YAAcwJ,EAAO,OAAS,EAC3D,MAAO,CACL,GAAGxJ,EACH,OAAAwJ,EACA,WAAYkG,EACZ,eAAgBA,EAAiBhB,EAAiB,KAClD,aAAcD,EAAAA,WAAWhF,EAAcD,EAAO,MAAM,EACpD,GAAIW,IAAUnK,EAAM,aAAeqO,EAAkB,CAAA,CAAC,CAE1D,CACA,IAAK,aAAc,CACjB,KAAM,CAAE,UAAAsB,EAAW,QAAAC,CAAA,EAAYd,EAAO,QAChCtF,EAASqG,EAAAA,UAAU7P,EAAM,OAAQ2P,EAAWC,CAAO,EACzD,IAAInG,EAAezJ,EAAM,aACzB,OAAIA,EAAM,eAAiB2P,EAAWlG,EAAemG,EAC5CD,EAAY3P,EAAM,cAAgB4P,GAAW5P,EAAM,aAAcyJ,GAAgB,EACjFkG,EAAY3P,EAAM,cAAgB4P,GAAW5P,EAAM,eAAcyJ,GAAgB,GACnF,CACL,GAAGzJ,EACH,OAAAwJ,EACA,WAAY,GACZ,eAAgB,KAChB,aAAciF,EAAAA,WAAWhF,EAAcD,EAAO,MAAM,CAAA,CAExD,CACA,IAAK,WAAY,CACf,MAAMA,EAASsG,eAAa9P,EAAM,OAAQA,EAAM,aAAc8O,EAAO,QAAQ,KAAK,EAE5EJ,EACJ1O,EAAM,YAAcA,EAAM,gBACrB,IAAM,CACL,MAAM2J,EAAe3J,EAAM,OAAOA,EAAM,YAAY,EAC9C+P,EAAiBN,EAAAA,yBAAyBzP,EAAM,eAAgB2J,CAAY,EAClF,OAAOmG,EAAAA,aAAa9P,EAAM,eAAgB+P,EAAgBjB,EAAO,QAAQ,KAAK,CAChF,GAAA,EACA9O,EAAM,eACZ,MAAO,CACL,GAAGA,EACH,OAAAwJ,EACA,eAAAkF,CAAA,CAEJ,CACA,IAAK,YAAa,CAChB,MAAMS,EAAMV,EAAAA,WAAWK,EAAO,QAAQ,MAAO9O,EAAM,OAAO,MAAM,EAC1DgQ,EAAKlB,EAAO,QAAQ,SACpBE,EAAWgB,IAAO,GAAO,GAAQA,IAAO,GAAQ,GAAOhQ,EAAM,SACnE,MAAO,CACL,GAAGA,EACH,aAAcmP,EACd,GAAGd,EACH,SAAAW,CAAA,CAEJ,CACA,IAAK,OACH,MAAO,CAAE,GAAGhP,EAAO,SAAU,EAAA,EAC/B,IAAK,QACH,MAAO,CAAE,GAAGA,EAAO,SAAU,EAAA,EAC/B,IAAK,eACH,MAAO,CAAE,GAAGA,EAAO,SAAU,CAACA,EAAM,QAAA,EACtC,IAAK,aACH,MAAO,CAAE,GAAGA,EAAO,WAAY8O,EAAO,OAAA,EACxC,IAAK,eACH,MAAO,CAAE,GAAG9O,EAAO,WAAYiQ,EAAAA,gBAAgBjQ,EAAM,UAAU,CAAA,EACjE,IAAK,iBAAkB,CACrB,GAAIA,EAAM,OAAO,QAAU,EAAG,MAAO,CAAE,GAAGA,EAAO,WAAY,GAAO,eAAgB,IAAA,EACpF,GAAI,CAACA,EAAM,WAAY,CACrB,MAAMkQ,EAAW,CAAC,GAAGlQ,EAAM,MAAM,EAC3BmQ,EAAWvB,EAAAA,kBAAkBsB,EAAUlQ,EAAM,YAAY,EAC/D,MAAO,CACL,GAAGA,EACH,WAAY,GACZ,eAAgBkQ,EAChB,OAAQC,EACR,aAAc,CAAA,CAElB,CACA,MAAMC,EAAWpQ,EAAM,eAAiB,CAAC,GAAGA,EAAM,cAAc,EAAI,CAAC,GAAGA,EAAM,MAAM,EAC9EqQ,EAAUrQ,EAAM,OAAOA,EAAM,YAAY,EACzCsQ,EAAWb,EAAAA,yBAAyBW,EAAUC,CAAO,EAC3D,MAAO,CACL,GAAGrQ,EACH,WAAY,GACZ,eAAgB,KAChB,OAAQoQ,EACR,aAAc3B,EAAAA,WAAW6B,EAAUF,EAAS,MAAM,CAAA,CAEtD,CACA,IAAK,OAAQ,CACX,MAAMG,EAAYC,EAAAA,iBAAiBxQ,CAAK,EAClCyQ,EAAOF,IAAcvQ,EAAM,aACjC,MAAO,CACL,GAAGA,EACH,aAAcuQ,EACd,GAAIE,EAAO,CAAA,EAAKpC,EAChB,SAAUoC,EAAOzQ,EAAM,SAAW,EAAA,CAEtC,CACA,IAAK,OAAQ,CACX,MAAM0Q,EAAYC,EAAAA,iBAAiB3Q,CAAK,EAClCyQ,EAAOC,IAAc1Q,EAAM,aACjC,MAAO,CACL,GAAGA,EACH,aAAc0Q,EACd,GAAID,EAAO,CAAA,EAAKpC,EAChB,SAAUoC,EAAOzQ,EAAM,SAAW,EAAA,CAEtC,CACA,IAAK,oBACH,MAAO,CACL,GAAGA,EACH,YAAa8O,EAAO,QAAQ,YAC5B,SAAU,OAAO,SAASA,EAAO,QAAQ,QAAQ,EAC7CA,EAAO,QAAQ,SACf9O,EAAM,SACV,iBAAkB8O,EAAO,QAAQ,iBACjC,YAAa,EAAA,EAEjB,IAAK,wBACH,MAAO,CACL,GAAG9O,EACH,SAAU,OAAO,SAAS8O,EAAO,QAAQ,QAAQ,EAC7CA,EAAO,QAAQ,SACf9O,EAAM,SACV,iBAAkB8O,EAAO,QAAQ,iBACjC,aAAc,IAAA,EAElB,IAAK,oBACH,MAAO,CAAE,GAAG9O,EAAO,aAAc8O,EAAO,OAAA,EAC1C,IAAK,oBACH,MAAO,CAAE,GAAG9O,EAAO,aAAc8O,EAAO,OAAA,EAC1C,IAAK,cACH,MAAO,CACL,GAAG9O,EACH,aAAc8O,EAAO,QAAQ,QAC7B,SAAU,GACV,YAAa,EAAA,EAEjB,IAAK,gBACH,MAAO,CAAE,GAAG9O,EAAO,YAAa,EAAA,EAClC,IAAK,gBACH,MAAO,CAAE,GAAGA,EAAO,YAAa,GAAO,aAAc,IAAA,EACvD,IAAK,aACH,MAAO,CAAE,GAAGA,EAAO,SAAU,GAAO,YAAa,EAAA,EACnD,IAAK,cACH,MAAO,CAAE,GAAGA,EAAO,SAAU,EAAA,EAC/B,IAAK,oBACH,MAAO,CAAE,GAAGA,EAAO,YAAa,EAAG,SAAU,EAAG,iBAAkB,CAAA,EACpE,IAAK,uBACH,MAAO,CAAE,GAAGA,EAAO,GAAGqO,CAAA,EACxB,IAAK,aACH,MAAO,CAAE,GAAGrO,EAAO,OAAQkO,EAAYY,EAAO,OAAO,CAAA,EACvD,IAAK,YACH,MAAO,CAAE,GAAG9O,EAAO,MAAO8O,EAAO,OAAA,EACnC,IAAK,cACH,MAAO,CAAE,GAAG9O,EAAO,MAAO,CAACA,EAAM,KAAA,EACnC,IAAK,oBACH,MAAO,CAAE,GAAGA,EAAO,aAAcoO,GAAkBU,EAAO,OAAO,CAAA,EACnE,IAAK,oBAAqB,CACxB,KAAM,CAAE,OAAAI,EAAQ,MAAA3I,CAAA,EAAUuI,EAAO,QAC3BX,EAAID,EAAYgB,CAAM,EAC5B,OAAIf,IAAMnO,EAAM,QAAUuG,IAAUvG,EAAM,MAAcA,EACjD,CAAE,GAAGA,EAAO,OAAQmO,EAAG,MAAA5H,CAAA,CAChC,CACA,QAGE,OAAOvG,CACT,CAEJ,CClUA,SAAS4Q,IAAuC,CAC9C,OAAI,OAAO,UAAc,KAAe,EAAE,iBAAkB,WAAmB,KACxE,UAAU,YACnB,CAEO,SAASC,GACdC,EACA9Q,EACA+Q,EACA9N,EAAqC,CAAA,EAC/B,OACN,MAAM+N,EAAW3Q,EAAAA,OAAOL,CAAK,EAC7BgR,EAAS,QAAUhR,EAEnB,MAAMqL,EAAQrL,EAAM,OAAOA,EAAM,YAAY,EACvCiR,EAAQ5F,GAAA,YAAAA,EAAO,MACf6F,EAAS7F,GAAA,YAAAA,EAAO,OAChB8F,EAAQ9F,GAAA,YAAAA,EAAO,MACf+F,EAAaC,EAAAA,kBAAkBhG,GAAOlL,EAAAH,EAAM,eAAN,YAAAG,EAAoB,UAAU,EAE1EO,EAAAA,UAAU,IAAM,CACd,MAAM4Q,EAAKV,GAAA,EACP,CAACE,GAAW,CAACQ,IACjBA,EAAG,SAAW,IAAI,cAAc,CAC9B,MAAOL,GAAS,gBAChB,OAAAC,EACA,MAAAC,EACA,QAASC,EAAa,CAAC,CAAE,IAAKA,CAAA,CAAY,EAAI,MAAA,CAC/C,EACH,EAAG,CAACN,EAASG,EAAOC,EAAQC,EAAOC,CAAU,CAAC,EAE9C1Q,EAAAA,UAAU,IAAM,CACd,MAAM4Q,EAAKV,GAAA,EACP,CAACE,GAAW,CAACQ,IACjBA,EAAG,cAAgBtR,EAAM,SAAW,SAAW,UACjD,EAAG,CAAC8Q,EAAS9Q,EAAM,QAAQ,CAAC,EAE5B,MAAMuR,EAAqBtO,EAAQ,mBAC7BuO,EAAsBvO,EAAQ,oBAEpCvC,EAAAA,UAAU,IAAM,CACd,MAAM4Q,EAAKV,GAAA,EACX,GAAI,GAACE,GAAW,CAACQ,GACjB,IAAI,CACFA,EAAG,iBAAiB,OAAQP,EAAQ,IAAI,EACxCO,EAAG,iBAAiB,QAASP,EAAQ,KAAK,EAC1CO,EAAG,iBAAiB,YAAaP,EAAQ,IAAI,EAC7CO,EAAG,iBAAiB,gBAAiBP,EAAQ,IAAI,EACjDO,EAAG,iBAAiB,SAAWG,GAAY,CACrC,OAAOA,EAAQ,UAAa,UAAY,OAAO,SAASA,EAAQ,QAAQ,GAC1EV,EAAQ,KAAKU,EAAQ,QAAQ,CAEjC,CAAC,EAEG,OAAOF,GAAuB,UAAYA,EAAqB,EACjED,EAAG,iBAAiB,cAAe,IAAM,CACvC,MAAMpP,EAAI8O,EAAS,QACbjQ,EAAOmB,EAAE,YAAcqP,EACvBG,EAAIxP,EAAE,SACNyP,EAAM,OAAO,SAASD,CAAC,GAAKA,EAAI,EAAIA,EAAI3Q,EAC9CgQ,EAAQ,KAAK,KAAK,IAAIhQ,EAAM4Q,CAAG,CAAC,CAClC,CAAC,EAEDL,EAAG,iBAAiB,cAAe,IAAI,EAGrC,OAAOE,GAAwB,UAAYA,EAAsB,EACnEF,EAAG,iBAAiB,eAAgB,IAAM,CACxC,MAAMpP,EAAI8O,EAAS,QACnBD,EAAQ,KAAK,KAAK,IAAI,EAAG7O,EAAE,YAAcsP,CAAmB,CAAC,CAC/D,CAAC,EAEDF,EAAG,iBAAiB,eAAgB,IAAI,CAE5C,MAAQ,CAER,CACA,MAAO,IAAM,CACX,GAAI,CACFA,EAAG,iBAAiB,OAAQ,IAAI,EAChCA,EAAG,iBAAiB,QAAS,IAAI,EACjCA,EAAG,iBAAiB,YAAa,IAAI,EACrCA,EAAG,iBAAiB,gBAAiB,IAAI,EACzCA,EAAG,iBAAiB,SAAU,IAAI,EAClCA,EAAG,iBAAiB,cAAe,IAAI,EACvCA,EAAG,iBAAiB,eAAgB,IAAI,CAC1C,MAAQ,CAER,CACF,EACF,EAAG,CAACR,EAASC,EAASQ,EAAoBC,CAAmB,CAAC,EAE9D9Q,EAAAA,UAAU,IAAM,SACd,MAAM4Q,EAAKV,GAAA,EACX,GAAI,CAACE,GAAW,CAACQ,GAAM,CAACrO,EAAQ,cAAe,OAC/C,MAAM1D,EAAWS,EAAM,SACjB4R,EAAW5R,EAAM,YACjBuB,EAAOvB,EAAM,aACnB,GAAI,CACF,GAAI,CAAC,OAAO,SAAST,CAAQ,GAAKA,GAAY,EAAG,EAC/CY,EAAAmR,EAAG,mBAAH,MAAAnR,EAAA,KAAAmR,GACA,MACF,EACArD,EAAAqD,EAAG,mBAAH,MAAArD,EAAA,KAAAqD,EAAsB,CACpB,SAAA/R,EACA,aAAc,OAAO,SAASgC,CAAI,GAAKA,EAAO,EAAIA,EAAO,EACzD,SAAU,KAAK,IAAI,KAAK,IAAI,EAAGqQ,CAAQ,EAAGrS,CAAQ,CAAA,EAEtD,MAAQ,CAER,CACA,MAAO,IAAM,OACX,GAAI,EACFY,EAAAmR,EAAG,mBAAH,MAAAnR,EAAA,KAAAmR,EACF,MAAQ,CAER,CACF,CACF,EAAG,CAACR,EAAS7N,EAAQ,cAAejD,EAAM,YAAaA,EAAM,SAAUA,EAAM,YAAY,CAAC,CAC5F,CC5FA,MAAM6R,GAAsC,CACzC,yBAAqC,UACrC,uBAAmC,UACnC,qBAAiC,OACjC,uBAAmC,wBACnC,gCAA4C,UAC5C,0BAAsC,MACtC,sBAAkC,UAClC,8BAA0C,yBAC1C,wBAAoC,4BACpC,sBAAkC,oCACrC,EAEO,SAASC,GAAe,CAC7B,SAAAjQ,EACA,cAAAkQ,EAAgB,CAAA,EAChB,aAAAC,EAAe,EACf,oBAAAC,EAAsB,KACtB,eAAAC,EAAiB,GACjB,kBAAAC,EAAoB,MACpB,oBAAAC,EAAsB,WACtB,cAAAC,EAAgB,GAChB,cAAAC,EAAgB,EAChB,aAAAC,EAAe,GACf,oBAAAC,EAAsB,EACtB,gBAAAC,EACA,OAAA7Q,EACA,aAAA8Q,EAAe,GACf,WAAAC,EACA,cAAAC,EACA,YAAAC,EACA,eAAAC,EAAiB,GACjB,oBAAAC,EAAsB,GACtB,SAAA9M,EAAW,GACX,QAAA+M,EAAU,GACV,UAAAvT,EACA,MAAAC,GACA,IAAKuT,GACL,4BAAAC,GAA8B,EAC9B,cAAAC,EACA,OAAAC,EACA,QAAAC,EACA,WAAAC,GACA,QAAApI,GACA,eAAAqI,GACA,qBAAAC,GACA,OAAAC,CACF,EAAwB,QACtB,MAAM3T,EAAWO,EAAAA,OAAgC,IAAI,EAC/C,CAACL,EAAOD,CAAQ,EAAI2T,EAAAA,WAAW7E,GAAe,OAAW,IAC7DN,GAAmB,CACjB,OAAQwD,EACR,aAAcC,EACd,aAAcC,EACd,SAAUI,EACV,WAAYH,EACZ,WAAYC,EACZ,aAAcC,EACd,OAAQE,EACR,MAAOC,EACP,aAAcC,CAAA,CACf,CAAA,EAEGxB,GAAW3Q,EAAAA,OAAOL,CAAK,EAEvB2T,GAAgBtT,EAAAA,OAAO,CAC3B,OAAQ0R,EACR,aAAcC,EACd,aAAcC,EACd,SAAUI,EACV,WAAYH,EACZ,WAAYC,EACZ,aAAcC,EACd,OAAQE,EACR,MAAOC,EACP,aAAcC,CAAA,CACf,EACDmB,GAAc,QAAU,CACtB,OAAQ5B,EACR,aAAcC,EACd,aAAcC,EACd,SAAUI,EACV,WAAYH,EACZ,WAAYC,EACZ,aAAcC,EACd,OAAQE,EACR,MAAOC,EACP,aAAcC,CAAA,EAGhB,MAAMoB,EAAyBvT,EAAAA,OAA+B,MAAS,EAEvEK,EAAAA,UAAU,IAAM,CACd,GAAI+R,IAAoB,OAAW,CACjCmB,EAAuB,QAAU,OACjC,MACF,CACA,GAAIA,EAAuB,UAAY,OAAW,CAChDA,EAAuB,QAAUnB,EACjC,MACF,CACA,GAAImB,EAAuB,UAAYnB,EAAiB,OACxDmB,EAAuB,QAAUnB,EACjC,MAAM,EAAIkB,GAAc,QACxB5T,EAAS,CACP,KAAM,OACN,QAAS,CACP,OAAQ,EAAE,OACV,aAAc,EAAE,aAChB,aAAc,EAAE,aAChB,SAAU,EAAE,SACZ,WAAY,EAAE,WACd,WAAY,EAAE,WACd,aAAc,EAAE,aAChB,OAAQ,EAAE,OACV,MAAO,EAAE,MACT,aAAc,EAAE,YAAA,CAClB,CACD,CACH,EAAG,CAAC0S,EAAiB1S,CAAQ,CAAC,EAE9BW,EAAAA,UAAU,IAAM,CACdsQ,GAAS,QAAUhR,CACrB,EAAG,CAACA,CAAK,CAAC,EAEV,MAAM2J,GAAe3J,EAAM,OAAOA,EAAM,YAAY,GAAK,KAEzDU,EAAAA,UAAU,IAAM,CACdyS,GAAA,MAAAA,EAAgBxJ,GAAc3J,EAAM,aACtC,EAAG,CAAC2J,GAAc3J,EAAM,aAAcmT,CAAa,CAAC,EAEpDzS,EAAAA,UAAU,IAAM,CACVV,EAAM,eAAckL,IAAA,MAAAA,GAAUlL,EAAM,cAC1C,EAAG,CAACA,EAAM,aAAckL,EAAO,CAAC,EAEhC,MAAM2I,GAAgBxT,EAAAA,OAA4B,MAAS,EAC3DK,EAAAA,UAAU,IAAM,CACd,GAAImT,GAAc,UAAY,OAAW,CACvCA,GAAc,QAAU7T,EAAM,SAC9B,MACF,CACI6T,GAAc,UAAY7T,EAAM,WAC9BA,EAAM,SAAUqT,GAAA,MAAAA,IACfD,GAAA,MAAAA,KAEPS,GAAc,QAAU7T,EAAM,QAChC,EAAG,CAACA,EAAM,SAAUqT,EAASD,CAAM,CAAC,EAEpC,MAAMU,GAAgBzT,EAAAA,OAA2B,MAAS,EACpD0T,GAAe1T,EAAAA,OAA4B,MAAS,EAC1DK,EAAAA,UAAU,IAAM,CACd,GAAIoT,GAAc,UAAY,QAAaC,GAAa,UAAY,OAAW,CAC7ED,GAAc,QAAU9T,EAAM,OAC9B+T,GAAa,QAAU/T,EAAM,MAC7B,MACF,EACI8T,GAAc,UAAY9T,EAAM,QAAU+T,GAAa,UAAY/T,EAAM,SAC3EuT,IAAA,MAAAA,GAAiBvT,EAAM,OAAQA,EAAM,QAEvC8T,GAAc,QAAU9T,EAAM,OAC9B+T,GAAa,QAAU/T,EAAM,KAC/B,EAAG,CAACA,EAAM,OAAQA,EAAM,MAAOuT,EAAc,CAAC,EAE9C,MAAMS,GAAsB3T,EAAAA,OAA2B,MAAS,EAChEK,EAAAA,UAAU,IAAM,CACd,GAAIsT,GAAoB,UAAY,OAAW,CAC7CA,GAAoB,QAAUhU,EAAM,aACpC,MACF,CACIgU,GAAoB,UAAYhU,EAAM,eACxCwT,IAAA,MAAAA,GAAuBxT,EAAM,eAE/BgU,GAAoB,QAAUhU,EAAM,YACtC,EAAG,CAACA,EAAM,aAAcwT,EAAoB,CAAC,EAE7C,MAAMS,EAAOC,EAAAA,YAAY,IAAM,CAC7BnU,EAAS,CAAE,KAAM,OAAQ,CAC3B,EAAG,CAAA,CAAE,EAECoU,EAAQD,EAAAA,YAAY,IAAM,OAC9BnU,EAAS,CAAE,KAAM,QAAS,GAC1BI,EAAAL,EAAS,UAAT,MAAAK,EAAkB,OACpB,EAAG,CAAA,CAAE,EAECiU,GAAkBF,EAAAA,YAAY,IAAM,CACpClU,EAAM,SAAUiU,EAAA,EACfE,EAAA,CACP,EAAG,CAACA,EAAOF,EAAMjU,EAAM,QAAQ,CAAC,EAE1BsK,EAAO4J,EAAAA,YACVG,GAAwB,CACvB,MAAMhV,EAAKS,EAAS,QACfT,GACA,OAAO,SAASgV,CAAW,IAChChV,EAAG,YAAc,KAAK,IAAI,EAAGgV,CAAW,EACxCZ,GAAA,MAAAA,EAAS,KAAK,IAAI,EAAGY,CAAW,GAClC,EACA,CAACZ,CAAM,CAAA,EAGHa,GAAYJ,cAAahF,GAAmB,CAChDnP,EAAS,CAAE,KAAM,aAAc,QAASmO,EAAYgB,CAAM,EAAG,CAC/D,EAAG,CAAA,CAAE,EAECqF,GAAWL,cAAa3N,GAAmB,CAC/CxG,EAAS,CAAE,KAAM,YAAa,QAASwG,EAAO,CAChD,EAAG,CAAA,CAAE,EAECC,GAAa0N,EAAAA,YAAY,IAAM,CACnCnU,EAAS,CAAE,KAAM,cAAe,CAClC,EAAG,CAAA,CAAE,EAEC8G,GAAkBqN,cAAa3S,GAAiB,CACpDxB,EAAS,CAAE,KAAM,oBAAqB,QAASqO,GAAkB7M,CAAI,EAAG,CAC1E,EAAG,CAAA,CAAE,EAECR,EAAOmT,EAAAA,YAAY,IAAM,CAC7BnU,EAAS,CAAE,KAAM,OAAQ,CAC3B,EAAG,CAAA,CAAE,EAECiB,EAAOkT,EAAAA,YAAY,IAAM,CAC7B,MAAM7U,EAAKS,EAAS,QACd0U,EAAYtB,IAA+B,EAC7C7T,GAAMmV,EAAY,GAAKnV,EAAG,YAAcmV,GAC1CnV,EAAG,YAAc,EACjBoU,GAAA,MAAAA,EAAS,IAET1T,EAAS,CAAE,KAAM,OAAQ,CAE7B,EAAG,CAACmT,GAA6BO,CAAM,CAAC,EAElCgB,GAAgBP,cAAa7P,GAAqB,CACtDtE,EAAS,CAAE,KAAM,aAAc,QAASsE,EAAM,CAChD,EAAG,CAAA,CAAE,EAECmB,GAAc0O,EAAAA,YAAY,IAAM,CACpCnU,EAAS,CAAE,KAAM,eAAgB,CACnC,EAAG,CAAA,CAAE,EAEC+F,GAAgBoO,EAAAA,YAAY,IAAM,CACtCnU,EAAS,CAAE,KAAM,iBAAkB,CACrC,EAAG,CAAA,CAAE,EAEC2U,GAAWR,EAAAA,YAAY,CAAC1K,EAAiBC,IAA0B,CACvE1J,EAAS,CAAE,KAAM,YAAa,QAAS,CAAE,OAAAyJ,EAAQ,aAAAC,CAAA,EAAgB,CACnE,EAAG,CAAA,CAAE,EAEC4F,GAAgB6E,EAAAA,YAAY,CAAC7I,EAAclB,EAAgBwK,IAAuB,CACtF5U,EAAS,CAAE,KAAM,eAAgB,QAAS,CAAE,MAAAsL,EAAO,MAAAlB,EAAO,SAAAwK,CAAA,EAAY,CACxE,EAAG,CAAA,CAAE,EAECrF,GAAgB4E,cAAa/J,GAAkB,CACnDpK,EAAS,CAAE,KAAM,eAAgB,QAAS,CAAE,MAAAoK,CAAA,EAAS,CACvD,EAAG,CAAA,CAAE,EAEC0F,GAAYqE,EAAAA,YAAY,CAACvE,EAAmBC,IAAoB,CACpE7P,EAAS,CAAE,KAAM,aAAc,QAAS,CAAE,UAAA4P,EAAW,QAAAC,CAAA,EAAW,CAClE,EAAG,CAAA,CAAE,EAECgF,GAAcV,cAAa7I,GAAiB,CAChDtL,EAAS,CAAE,KAAM,WAAY,QAAS,CAAE,MAAAsL,CAAA,EAAS,CACnD,EAAG,CAAA,CAAE,EAECmC,GAAc0G,cAAa/J,GAAkB,CACjDpK,EAAS,CAAE,KAAM,YAAa,QAAS,CAAE,MAAAoK,EAAO,SAAU,EAAA,EAAQ,CACpE,EAAG,CAAA,CAAE,EAECsD,GAAgByG,cAAa/J,GAAkB,CACnDpK,EAAS,CAAE,KAAM,YAAa,QAAS,CAAE,MAAAoK,EAAO,SAAU,EAAA,EAAS,CACrE,EAAG,CAAA,CAAE,EAEC0K,GAAkBX,cAAaY,GAA8B,CACjE/U,EAAS,CAAE,KAAM,oBAAqB,QAAS+U,EAAM,CACvD,EAAG,CAAA,CAAE,EAECC,GAAkBb,cAAa7P,GAAuB,CAC1DtE,EAAS,CAAE,KAAM,oBAAqB,QAASsE,EAAM,CACvD,EAAG,CAAA,CAAE,EAEC2Q,GAAOd,cAAae,GAA+B,CACvDlV,EAAS,CAAE,KAAM,OAAQ,QAAAkV,CAAA,CAAS,CACpC,EAAG,CAAA,CAAE,EAELvU,EAAAA,UAAU,IAAM,CACd,GAAI,GAACmS,GAAe,CAACC,GACrB,GAAI,CACF,MAAM5D,EAAS2D,EAAY,IAAI,eAAe,EACxCtM,EAAQsM,EAAY,IAAI,cAAc,EACtCjM,EAAeiM,EAAY,IAAI,qBAAqB,EACpDtN,EAAasN,EAAY,IAAI,mBAAmB,EAChDpJ,GAAeoJ,EAAY,IAAI,qBAAqB,EACpDqC,EAAIvB,GAAc,QACxB5T,EAAS,CACP,KAAM,OACN,QAAS,CACP,OAAQmV,EAAE,OACV,aAAcA,EAAE,aAChB,SAAUA,EAAE,SACZ,WAAYA,EAAE,WACd,aAAcA,EAAE,aAChB,aAAc,OAAOzL,IAAiB,SAAWA,GAAeyL,EAAE,aAClE,WACE3P,IAAe,OAASA,IAAe,OAASA,IAAe,MAC3DA,EACA2P,EAAE,WACR,OAAQ,OAAOhG,GAAW,SAAWA,EAASgG,EAAE,OAChD,MAAO,OAAO3O,GAAU,UAAYA,EAAQ2O,EAAE,MAC9C,aAAc,OAAOtO,GAAiB,SAAWA,EAAesO,EAAE,YAAA,CACpE,CACD,CACH,OAAS9T,EAAG,CACN,QAAQ,IAAI,WAAa,cAC3B,QAAQ,KAAK,mEAAoEA,CAAC,CAEtF,CACF,EAAG,CAAC0R,EAAgBD,CAAW,CAAC,EAEhCnS,EAAAA,UAAU,IAAM,CACd,GAAKmS,EACL,GAAI,CACFA,EAAY,IAAI,gBAAiB7S,EAAM,MAAM,EAC7C6S,EAAY,IAAI,eAAgB7S,EAAM,KAAK,EAC3C6S,EAAY,IAAI,sBAAuB7S,EAAM,YAAY,EACzD6S,EAAY,IAAI,oBAAqB7S,EAAM,UAAU,EACrD6S,EAAY,IAAI,sBAAuB7S,EAAM,YAAY,CAC3D,OAASoB,EAAG,CACN,QAAQ,IAAI,WAAa,cAC3B,QAAQ,KAAK,kDAAmDA,CAAC,CAErE,CACF,EAAG,CACDyR,EACA7S,EAAM,OACNA,EAAM,MACNA,EAAM,aACNA,EAAM,WACNA,EAAM,YAAA,CACP,EAEDU,EAAAA,UAAU,IAAM,CACd,GAAI,CAACmS,GAAe,CAACE,EAAqB,OAC1C,MAAM1H,EAAQrL,EAAM,OAAOA,EAAM,YAAY,EAC7C,GAAI,CAACqL,EAAO,OACZ,MAAM8J,EAAM,iBAAiBzH,EAAAA,cAAcrC,CAAK,CAAC,GACjD,GAAI,CACF,MAAM+J,EAAQvC,EAAY,IAAIsC,CAAG,EAC7B,OAAOC,GAAU,UAAY,OAAO,SAASA,CAAK,GACpD9K,EAAK8K,CAAK,CAEd,OAAShU,EAAG,CACN,QAAQ,IAAI,WAAa,cAC3B,QAAQ,KAAK,gEAAiEA,CAAC,CAEnF,CACF,EAAG,CAACyR,EAAaE,EAAqB/S,EAAM,aAAcA,EAAM,OAAQsK,CAAI,CAAC,EAE7E5J,EAAAA,UAAU,IAAM,CACd,GAAI,CAACmS,GAAe,CAACE,EAAqB,OAC1C,MAAM1H,EAAQrL,EAAM,OAAOA,EAAM,YAAY,EAC7C,GAAI,CAACqL,GAAS,EAAErL,EAAM,aAAe,GAAI,OACzC,MAAMmV,EAAM,iBAAiBzH,EAAAA,cAAcrC,CAAK,CAAC,GAC3CgK,EAAK,WAAW,IAAM,CAC1B,GAAI,CACFxC,EAAY,IAAIsC,EAAKnV,EAAM,WAAW,CACxC,OAASoB,EAAG,CACN,QAAQ,IAAI,WAAa,cAC3B,QAAQ,KAAK,qEAAsEA,CAAC,CAExF,CACF,EAAG,GAAG,EACN,MAAO,IAAM,aAAaiU,CAAE,CAC9B,EAAG,CAACxC,EAAaE,EAAqB/S,EAAM,aAAcA,EAAM,OAAQA,EAAM,WAAW,CAAC,EAE1F,MAAMsV,IAAanV,GAAAH,EAAM,OAAOA,EAAM,YAAY,IAA/B,YAAAG,GAAkC,QAErDO,EAAAA,UAAU,IAAM,CACd,MAAMrB,EAAKS,EAAS,QACpB,GAAI,CAACT,EAAI,OACT,GAAIW,EAAM,SAAU,CAClBX,EAAG,MAAA,EACH,MACF,CAEA,GAAIA,EAAG,OAASkW,EAAAA,uBAAuBvE,GAAS,OAAO,EAAE,OAAS,OAAQ,CACxEjR,EAAS,CAAE,KAAM,QAAS,EAC1B,MACF,CACA,IAAIyV,EAAY,GAChB,OAAM,SAAY,CAChB,GAAI7C,EAAY,CACd,IAAI8C,EAAU,GACd,GAAI,CACFA,EAAU,MAAM9C,EAAA,CAClB,OAAS+C,EAAO,CACd,MAAMC,GAAUD,aAAiB,MAAQA,EAAM,QAAU,sBACzD3V,EAAS,CAAE,KAAM,cAAe,QAAS,CAAE,QAAA4V,EAAA,EAAW,EACtD,MACF,CACA,GAAI,CAACF,EAAS,CACPD,IACHzV,EAAS,CAAE,KAAM,QAAS,EAC1B6S,GAAA,MAAAA,KAEF,MACF,CACF,CACI4C,GACCnW,EAAG,KAAA,EAAO,MAAO+B,GAAe,CACnC,MAAMwU,EACJxU,aAAa,MACTA,EAAE,QACF,OAAOA,GAAM,SACXA,EACA,gEACRrB,EAAS,CAAE,KAAM,cAAe,QAAS,CAAE,QAAS6V,CAAA,EAAO,CAC7D,CAAC,CACH,GAAA,EACO,IAAM,CACXJ,EAAY,EACd,CACF,EAAG,CAAC7C,EAAY2C,GAAY1C,EAAe5S,EAAM,QAAQ,CAAC,EAE1D,MAAMC,GAAciU,EAAAA,YAAY,IAAM,OACpC,MAAM2B,EAAaN,EAAAA,uBAAuBvE,GAAS,OAAO,EAC1D,GAAI6E,EAAW,OAAS,cAAe,CACrC,MAAMxW,EAAKS,EAAS,QAChBT,IACFA,EAAG,YAAc,GAEnBU,EAAS,CAAE,KAAM,OAAQ,EACzB,MACF,CACA,GAAI8V,EAAW,OAAS,OAAQ,EAC9B1V,EAAAL,EAAS,UAAT,MAAAK,EAAkB,QAClBJ,EAAS,CAAE,KAAM,QAAS,EAC1BuT,IAAA,MAAAA,KACA,MACF,CACA,MAAM/C,EAAYsF,EAAW,UAC7B9V,EAAS,CAAE,KAAM,YAAa,QAAS,CAAE,MAAOwQ,EAAW,SAAU,EAAA,EAAQ,CAC/E,EAAG,CAAC+C,EAAU,CAAC,EAETwC,GAAsBtT,EAAAA,QAC1B,KAAO,CAAE,KAAAyR,EAAM,MAAAE,EAAO,KAAApT,EAAM,KAAAC,EAAM,KAAAsJ,CAAA,GAClC,CAAC2J,EAAME,EAAOpT,EAAMC,EAAMsJ,CAAI,CAAA,EAE1ByL,GAAsB,OAAOrD,GAAiB,SAAW,GAAO,EAAQA,EACxEsD,GAA4BxT,EAAAA,QAChC,IAAO,OAAOkQ,GAAiB,SAAWA,EAAe,CAAA,EACzD,CAACA,CAAY,CAAA,EAEf7B,GAAsBkF,GAAqB/V,EAAO8V,GAAqBE,EAAyB,EAEhG,MAAMC,GACJhD,KAAYrR,GAAA,MAAAA,EAAQ,MAAQ,kBAAkB,KAAKA,EAAO,IAAI,EAAI,MAAQ,OAEtEE,GAAQU,EAAAA,QACZ,KAAO,CACL,MAAAxC,EACA,SAAAD,EACA,SAAAD,EACA,YAAAG,GACA,KAAA+U,GACA,KAAAf,EACA,MAAAE,EACA,gBAAAC,GACA,KAAA9J,EACA,UAAAgK,GACA,SAAAC,GACA,WAAA/N,GACA,gBAAAK,GACA,KAAA9F,EACA,KAAAC,EACA,cAAAyT,GACA,YAAAjP,GACA,cAAAM,GACA,SAAA4O,GACA,cAAArF,GACA,cAAAC,GACA,UAAAO,GACA,YAAA+E,GACA,YAAApH,GACA,cAAAC,GACA,gBAAAoH,GACA,gBAAAE,EAAA,GAEF,CACEvP,GACAzF,EACAiV,GACAjU,EACAd,GACAkU,EACAF,EACAzG,GACA6B,GACAC,GACAO,GACA+E,GACAnH,GACAzM,EACAsJ,EACAiK,GACA1N,GACA6N,GACAD,GACAI,GACAE,GACAT,GACAtU,EACAwG,GACA4N,GACAtO,EAAA,CACF,EAGIoQ,GAAgB1T,EAAAA,QACpB,KAAO,CACL,OAAQxC,EAAM,OACd,aAAcA,EAAM,aACpB,SAAUA,EAAM,SAChB,WAAYA,EAAM,WAClB,WAAYA,EAAM,WAClB,eAAgBA,EAAM,eACtB,aAAcA,EAAM,aACpB,KAAAgV,GACA,KAAAf,EACA,MAAAE,EACA,gBAAAC,GACA,KAAArT,EACA,KAAAC,EACA,cAAAyT,GACA,YAAAjP,GACA,cAAAM,GACA,aAAc9F,EAAM,aACpB,SAAA0U,GACA,cAAArF,GACA,cAAAC,GACA,UAAAO,GACA,YAAA+E,GACA,YAAApH,GACA,cAAAC,GACA,gBAAAoH,GACA,gBAAAE,GACA,SAAAhV,CAAA,GAEF,CACEC,EAAM,OACNA,EAAM,aACNA,EAAM,SACNA,EAAM,WACNA,EAAM,WACNA,EAAM,aACNA,EAAM,eACNA,EAAM,aACNgV,GACAf,EACAE,EACAC,GACArT,EACAC,EACAyT,GACAjP,GACAM,GACA4O,GACArF,GACAC,GACAO,GACA+E,GACApH,GACAC,GACAoH,GACAE,GACAhV,CAAA,CACF,EAGIoW,GAAa3T,EAAAA,QACjB,KAAO,CACL,YAAaxC,EAAM,YACnB,SAAUA,EAAM,SAChB,iBAAkBA,EAAM,iBACxB,YAAaA,EAAM,YACnB,aAAcA,EAAM,aACpB,OAAQA,EAAM,OACd,MAAOA,EAAM,MACb,aAAcA,EAAM,aACpB,KAAAsK,EACA,UAAAgK,GACA,SAAAC,GACA,WAAA/N,GACA,gBAAAK,GACA,SAAA/G,EACA,YAAAG,GACA,SAAAF,CAAA,GAEF,CACEC,EAAM,YACNA,EAAM,SACNA,EAAM,iBACNA,EAAM,YACNA,EAAM,aACNA,EAAM,OACNA,EAAM,MACNA,EAAM,aACNsK,EACAgK,GACAC,GACA/N,GACAK,GACA/G,EACAG,GACAF,CAAA,CACF,EAGIqW,GAAarJ,EAAAA,sBAAsB/M,CAAK,EAExCkG,GAAc1D,EAAAA,QAClB,IAAOyD,EAAWvG,GAAQ,CAAE,GAAGmS,GAAsB,GAAGnS,EAAA,EACxD,CAACA,GAAOuG,CAAQ,CAAA,EAGZoQ,EAAa7T,EAAAA,QACjB,KAAO,CACL,UAAA/C,EACA,MAAOyG,GACP,uBAAwBkQ,GACxB,IAAKH,EAAA,GAEP,CAACxW,EAAWyG,GAAakQ,GAAYH,EAAW,CAAA,EAG5CK,GAAQ9T,EAAAA,QAAQ,IAAM,CAC1B,GAAI,CAACwQ,EACH,OACE7R,EAAAA,IAAC,MAAA,CACC,UAAWkV,EAAW,UACtB,MAAOA,EAAW,MAClB,uBAAsBA,EAAW,sBAAsB,EACvD,IAAKA,EAAW,IAEf,SAAAxU,CAAA,CAAA,EAIP,MAAM0U,EAAOC,EAAAA,SAAS,KAAK3U,CAAQ,EACnC,GAAI,CAAC4U,EAAAA,eAAeF,CAAI,EACtB,MAAM,IAAI,MAAM,+DAA+D,EAEjF,MAAMG,EAAQH,EACRI,EAAaD,EAAM,MAAM,MAC/B,OAAOE,EAAAA,aAAaF,EAAgD,CAClE,UAAWG,GAAgBH,EAAM,MAAM,UAAWL,EAAW,SAAS,EACtE,MACEM,GAAc,OAAOA,GAAe,SAChC,CAAE,GAAGA,EAAY,GAAGN,EAAW,KAAA,EAC/BA,EAAW,MACjB,uBAAwBA,EAAW,sBAAsB,EACzD,IAAKA,EAAW,GAAA,CACjB,CACH,EAAG,CAACrD,EAASnR,EAAUwU,CAAU,CAAC,EAElC,OACElV,EAAAA,IAACQ,IAAqB,OAAAC,EACpB,SAAAT,EAAAA,IAAC2V,wBAAsB,SAAtB,CAA+B,MAAOZ,GACrC,SAAA/U,EAAAA,IAAC4V,EAAAA,mBAAmB,SAAnB,CAA4B,MAAOZ,GAClC,SAAAhV,EAAAA,IAACpC,GAAc,SAAd,CAAuB,MAAA+C,GAAe,SAAAwU,EAAA,CAAM,CAAA,CAC/C,CAAA,CACF,CAAA,CACF,CAEJ,CAEA,SAASO,GAAgB/P,EAAY1B,EAAgC,CACnE,MAAM4R,EAAS,CAAClQ,EAAG1B,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAC9C,OAAO4R,IAAW,GAAK,OAAYA,CACrC,CCpsBO,MAAMC,GAAS,CACpB,SAAUnF,GACV,OAAQtS,GACR,QAAS,CACP,MAAO0X,GACP,OAAQC,GACR,MAAOC,GACP,YAAaC,GACb,UAAWC,GACX,MAAOC,GACP,MAAOC,GACP,KAAMC,GACN,YAAaC,GACb,KAAMC,GACN,OAAQC,GACR,aAAcC,GACd,SAAUC,GACV,QAASC,GACT,QAASC,GACT,WAAYC,GACZ,YAAaC,GACb,cAAeC,GACf,QAASC,GACT,SAAUC,GACV,UAAWC,GACX,SAAUC,GACV,SAAUC,GACV,WAAYC,GACZ,cAAeC,GACf,aAAcC,EAAQ,EAExB,MAAO,CACL,MAAOC,GACP,SAAUC,GACV,YAAaC,GACb,UAAWC,GACX,QAASC,EAAM,EAEjB,QAAS,CACP,UAAWC,GACX,OAAQC,GACR,KAAMC,GACN,SAAUC,GACV,QAASC,GACT,QAASC,GACT,OAAQC,GACR,KAAMC,GACN,aAAcC,EAAQ,EAExB,KAAM,CACJ,KAAMC,GACN,MAAOC,GACP,YAAaC,GACb,SAAUC,GACV,QAASC,GACT,QAASC,GACT,QAASC,GACT,YAAaC,GACb,QAASC,CAAK,EAEhB,SAAUnM,EACZ"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const t=require("react"),H=require("./useGinger-4uvPoChz.cjs"),N=require("./liveAudioGraph-0cpHD_Ic.cjs"),w=require("./GingerSplitContexts-C7puo0M7.cjs"),z=require("./selectors-CEGlYoFu.cjs"),X=require("./transitions-Dx08t68T.cjs"),D=require("./ginger-Dv3iO_xQ.cjs"),q=new Uint8Array(0),C=new Uint8Array(0);function O(s={}){const{enabled:e=!0,fftSize:r=2048,smoothingTimeConstant:n=.8,minDecibels:u=-100,maxDecibels:c=-30}=s,{audioRef:a,state:o}=H.useGinger(),d=t.useMemo(()=>({fftSize:r,smoothingTimeConstant:n,minDecibels:u,maxDecibels:c}),[r,n,u,c]),[l,m]=t.useState(0),[f,i]=t.useState(null),[h,R]=t.useState(!1),[S,p]=t.useState({frequencyBinCount:0,sampleRate:0}),g=t.useRef(q),v=t.useRef(C),E=t.useCallback(async()=>{const x=y.current;x&&x.state==="suspended"&&await x.resume()},[]),y=t.useRef(null),I=t.useRef(null);return t.useLayoutEffect(()=>{if(!e||typeof window>"u")return;let x=!1,b=null,A=null,T=0;const F=()=>{const k=y.current;k&&R(k.state==="suspended")},V=()=>{if(x)return;const k=I.current,P=g.current,M=v.current;k&&P.length>0&&M.length>0&&(k.getByteFrequencyData(P),k.getByteTimeDomainData(M),m(G=>G+1)),T=requestAnimationFrame(V)},B=()=>{const k=a.current;if(!k||x)return"no-element";try{const{id:P,context:M,analyser:G}=N.attachLiveAnalyser(k,d);b=P,A=k,y.current=M,I.current=G,R(M.state==="suspended"),i(null),M.addEventListener("statechange",F);const L=G.frequencyBinCount,U=G.fftSize;return g.current=new Uint8Array(L),v.current=new Uint8Array(U),p({frequencyBinCount:L,sampleRate:M.sampleRate}),T=requestAnimationFrame(V),"ok"}catch(P){const M=P instanceof Error?P.message:"Failed to attach live analyser";return i(M),y.current=null,I.current=null,g.current=q,v.current=C,p({frequencyBinCount:0,sampleRate:0}),"error"}},K=B();if(K!=="ok"){let k=0;const P=120;let M=0;const G=()=>{if(x)return;const L=B();L==="ok"||L==="error"||(M+=1,!(M>=P)&&(k=requestAnimationFrame(G)))};return K==="no-element"&&(k=requestAnimationFrame(G)),()=>{var L;x=!0,cancelAnimationFrame(k),cancelAnimationFrame(T),b!=null&&A&&N.detachLiveAnalyser(A,b),(L=y.current)==null||L.removeEventListener("statechange",F),y.current=null,I.current=null,g.current=q,v.current=C}}return()=>{var k;x=!0,cancelAnimationFrame(T),b!=null&&A&&N.detachLiveAnalyser(A,b),(k=y.current)==null||k.removeEventListener("statechange",F),y.current=null,I.current=null,g.current=q,v.current=C,p({frequencyBinCount:0,sampleRate:0})}},[e,a,d,o.currentIndex]),{frequencyData:g.current,timeDomainData:v.current,frequencyBinCount:S.frequencyBinCount,sampleRate:S.sampleRate,isSuspended:h,error:f,resume:E,frame:l}}function Y(s=!0,e={}){const{togglePlayPause:r,next:n,prev:u}=w.useGingerPlayback(),{toggleMute:c,seek:a,currentTime:o,duration:d}=w.useGingerMedia(),{mute:l,seekForward:m,seekBackward:f}=e;t.useEffect(()=>{if(!s||typeof window>"u")return;const i=(e.playPause??" ").toLowerCase(),h=(e.next??"ArrowRight").toLowerCase(),R=(e.previous??"ArrowLeft").toLowerCase(),S=l==null?void 0:l.toLowerCase(),p=m==null?void 0:m.toLowerCase(),g=f==null?void 0:f.toLowerCase(),v=e.seekSeconds??5,E=y=>{const I=y.target;if(I&&(["INPUT","TEXTAREA","SELECT"].includes(I.tagName)||I.isContentEditable))return;const x=y.key.toLowerCase();if(x===i)y.preventDefault(),r();else if(x===h)y.preventDefault(),n();else if(x===R)y.preventDefault(),u();else if(S&&x===S)y.preventDefault(),c();else if(p&&x===p){y.preventDefault();const b=d>0?d:Number.POSITIVE_INFINITY;a(Math.min(b,o+v))}else g&&x===g&&(y.preventDefault(),a(Math.max(0,o-v)))};return window.addEventListener("keydown",E),()=>window.removeEventListener("keydown",E)},[e.next,e.playPause,e.previous,e.seekSeconds,o,d,s,l,n,u,a,f,m,c,r])}function _(s){const{durationMs:e,stopAfterTracks:r,respectPause:n=!0,enabled:u=!0,onFire:c}=s,{currentIndex:a,pause:o,isPaused:d}=w.useGingerPlayback(),l=t.useRef(r??0),m=t.useRef(a),f=t.useRef(e??0),i=t.useRef(null);t.useEffect(()=>{l.current=r??0},[r]);const h=t.useRef(e);t.useEffect(()=>{h.current!==e&&(f.current=e??0,h.current=e)},[e]),t.useEffect(()=>{if(!u||!e||e<=0){f.current=e??0,i.current=null;return}if(n&&d){if(i.current!==null){const S=Date.now()-i.current;f.current=Math.max(0,f.current-S),i.current=null}return}i.current=Date.now();const R=setTimeout(()=>{f.current=0,i.current=null,o(),c==null||c()},f.current);return()=>{if(clearTimeout(R),i.current!==null){const S=Date.now()-i.current;f.current=Math.max(0,f.current-S),i.current=null}}},[e,u,d,c,o,n]),t.useEffect(()=>{if(!u||!r||r<=0)return;const R=m.current;m.current=a,a!==R&&(l.current-=1,l.current<=0&&(o(),c==null||c()))},[a,u,c,o,r])}function j(s=!1){const e=w.useGingerState(),r=t.useRef(e);t.useEffect(()=>{if(!s||typeof console>"u")return;const n=r.current;n!==e&&console.debug("[ginger]",{from:{currentIndex:n.currentIndex,isPaused:n.isPaused,currentTime:n.currentTime,repeatMode:n.repeatMode},to:{currentIndex:e.currentIndex,isPaused:e.isPaused,currentTime:e.currentTime,repeatMode:e.repeatMode}}),r.current=e},[s,e])}function J(s){return Math.max(0,Math.min(1,s))}function Q(s){const e=w.useGingerMedia(),r=w.useGingerPlayback(),{seek:n}=e,[u,c]=t.useState(0),[a,o]=t.useState(!1),d=z.progressFraction(w.gingerStateFromContextValues(r,e)),l=a?u:d,m=t.useCallback(f=>{if(!(s>0))return;const i=f.currentTarget,h=i.getBoundingClientRect(),R=g=>{const v=J((g-h.left)/h.width);c(v),n(v*s)};o(!0),i.setPointerCapture(f.pointerId),R(f.clientX);const S=g=>R(g.clientX),p=g=>{R(g.clientX),o(!1),i.releasePointerCapture(f.pointerId),i.removeEventListener("pointermove",S),i.removeEventListener("pointerup",p),i.removeEventListener("pointercancel",p)};i.addEventListener("pointermove",S),i.addEventListener("pointerup",p),i.addEventListener("pointercancel",p)},[s,n]);return{fraction:u,displayFraction:l,isDragging:a,onPointerDown:m}}function W(s={}){const{enabled:e=!0,crossOrigin:r}=s,{tracks:n,currentIndex:u,repeatMode:c,playbackMode:a}=w.useGingerPlayback();t.useEffect(()=>{var m;if(!e||typeof document>"u")return;const o=X.computeNextIndex({tracks:n,currentIndex:u,repeatMode:c,playbackMode:a});if(o===u)return;const d=((m=n[o])==null?void 0:m.fileUrl)??"";if(!d)return;const l=document.createElement("audio");return l.preload="auto",r&&(l.crossOrigin=r),l.src=d,l.load(),()=>{l.removeAttribute("src"),l.load()}},[e,r,n,u,c,a])}function Z(s={}){let e=D.createInitialState({tracks:s.tracks??[],currentIndex:s.currentIndex,playlistMeta:s.playlistMeta,isPaused:s.isPaused,isShuffled:s.isShuffled,repeatMode:s.repeatMode,playbackMode:s.playbackMode,volume:s.volume,muted:s.muted,playbackRate:s.playbackRate});const r=new Set,n=a=>{const o=D.gingerReducer(e,a);if(o!==e){e=o;for(const d of r)d(e)}};return{getState:()=>e,dispatch:n,subscribe:a=>(r.add(a),()=>r.delete(a)),init:a=>{n({type:"INIT",payload:a})},clampVolume:D.clampVolume,clampPlaybackRate:D.clampPlaybackRate}}function $(s={}){const{maxLength:e=50}=s,{tracks:r,currentIndex:n}=w.useGingerPlayback(),[u,c]=t.useState([]),a=t.useRef(null),o=t.useRef(r);o.current=r,t.useEffect(()=>{const l=r[n];if(!l||a.current===n)return;a.current=n;const m={track:l,index:n,playedAt:Date.now()};c(f=>{const i=[...f,m];return i.length>e?i.slice(i.length-e):i})},[n,r,e]);const d=t.useCallback(()=>c([]),[]);return{history:u,clearHistory:d}}function ee(){const{setVolume:s,volume:e}=w.useGingerMedia(),[r,n]=t.useState(!1),u=t.useRef(0),c=t.useRef(!1),a=t.useCallback(()=>{cancelAnimationFrame(u.current),c.current=!0,n(!1)},[]);return{fadeVolumeTo:t.useCallback(({targetVolume:d,durationMs:l,onComplete:m})=>{cancelAnimationFrame(u.current),c.current=!1;const f=p=>Math.min(1,Math.max(0,p)),i=f(d),h=performance.now();let R=e;n(!0);const S=p=>{if(c.current)return;const g=p-h,v=Math.min(1,g/Math.max(1,l)),E=R+(i-R)*v;s(f(E)),v<1?u.current=requestAnimationFrame(S):(n(!1),m==null||m())};u.current=requestAnimationFrame(p=>{R=e,S(p)})},[s,e]),cancelFade:a,isFading:r}}function te(){const{tracks:s,currentIndex:e}=w.useGingerPlayback(),{currentTime:r,duration:n}=w.useGingerMedia(),u=t.useMemo(()=>{var a;return[...((a=s[e])==null?void 0:a.chapters)??[]].filter(o=>o&&Number.isFinite(o.startSeconds)&&o.startSeconds>=0).sort((o,d)=>o.startSeconds-d.startSeconds)},[s,e]);return t.useMemo(()=>{if(u.length===0)return{progress:0,elapsed:0,remaining:0};let c=-1;for(let h=u.length-1;h>=0;h--)if(r>=u[h].startSeconds){c=h;break}if(c===-1)return{progress:0,elapsed:0,remaining:0};const a=u[c],o=u[c+1],d=(o==null?void 0:o.startSeconds)??(n>0?n:r),l=Math.max(0,d-a.startSeconds),m=Math.max(0,r-a.startSeconds),f=Math.max(0,d-r);return{progress:l>0?Math.min(1,m/l):0,elapsed:m,remaining:f}},[u,r,n])}exports.createGingerStore=Z;exports.useGingerChapterProgress=te;exports.useGingerDebugLog=j;exports.useGingerKeyboardShortcuts=Y;exports.useGingerLiveAnalyzer=O;exports.useGingerPlaybackHistory=$;exports.useGingerSleepTimer=_;exports.useGingerVolumeFade=ee;exports.useNextTrackPrefetch=W;exports.useSeekDrag=Q;
|
|
2
|
-
//# sourceMappingURL=useGingerChapterProgress-D2pdmyjg.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useGingerChapterProgress-D2pdmyjg.cjs","sources":["../src/analyzer/useGingerLiveAnalyzer.ts","../src/hooks/useGingerKeyboardShortcuts.ts","../src/hooks/useGingerSleepTimer.ts","../src/hooks/useGingerDebugLog.ts","../src/hooks/useSeekDrag.ts","../src/hooks/useNextTrackPrefetch.ts","../src/store.ts","../src/hooks/useGingerPlaybackHistory.ts","../src/hooks/useGingerVolumeFade.ts","../src/hooks/useGingerChapterProgress.ts"],"sourcesContent":["import { useCallback, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useGinger } from \"../hooks/useGinger\";\nimport { type LiveAnalyserOptions, attachLiveAnalyser, detachLiveAnalyser } from \"./liveAudioGraph\";\n\nexport type UseGingerLiveAnalyzerOptions = {\n /** When false, the analyser is detached and no frames are read. Default true. */\n enabled?: boolean;\n fftSize?: number;\n smoothingTimeConstant?: number;\n minDecibels?: number;\n maxDecibels?: number;\n};\n\nexport type UseGingerLiveAnalyzerResult = {\n /** Byte frequency data (0–255); length equals `frequencyBinCount`. Updated each animation frame while enabled. */\n frequencyData: Uint8Array;\n /** Byte time-domain data (0–255); length equals `fftSize`. */\n timeDomainData: Uint8Array;\n frequencyBinCount: number;\n sampleRate: number;\n isSuspended: boolean;\n error: string | null;\n resume: () => Promise<void>;\n /**\n * Monotonically increasing counter incremented each animation frame.\n * Use as a `useMemo` / `useEffect` dependency to respond to new audio data, since\n * `frequencyData` and `timeDomainData` are mutated in-place (their reference never changes).\n */\n frame: number;\n};\n\nconst emptyFreq = new Uint8Array(0);\nconst emptyTime = new Uint8Array(0);\n\nexport function useGingerLiveAnalyzer(\n options: UseGingerLiveAnalyzerOptions = {},\n): UseGingerLiveAnalyzerResult {\n const {\n enabled = true,\n fftSize = 2048,\n smoothingTimeConstant = 0.8,\n minDecibels = -100,\n maxDecibels = -30,\n } = options;\n\n const { audioRef, state } = useGinger();\n const opts = useMemo<LiveAnalyserOptions>(\n () => ({\n fftSize,\n smoothingTimeConstant,\n minDecibels,\n maxDecibels,\n }),\n [fftSize, smoothingTimeConstant, minDecibels, maxDecibels],\n );\n\n const [frame, setFrame] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [isSuspended, setIsSuspended] = useState(false);\n const [meta, setMeta] = useState({ frequencyBinCount: 0, sampleRate: 0 });\n\n const freqRef = useRef<Uint8Array>(emptyFreq);\n const timeRef = useRef<Uint8Array>(emptyTime);\n\n const resume = useCallback(async () => {\n const ctx = contextHolderRef.current;\n if (ctx && ctx.state === \"suspended\") {\n await ctx.resume();\n }\n }, []);\n\n const contextHolderRef = useRef<AudioContext | null>(null);\n const analyserHolderRef = useRef<AnalyserNode | null>(null);\n\n useLayoutEffect(() => {\n if (!enabled || typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n let consumerId: number | null = null;\n let element: HTMLAudioElement | null = null;\n let rafId = 0;\n\n const onStateChange = () => {\n const ctx = contextHolderRef.current;\n if (ctx) setIsSuspended(ctx.state === \"suspended\");\n };\n\n const runLoop = () => {\n if (cancelled) return;\n const a = analyserHolderRef.current;\n const fq = freqRef.current;\n const td = timeRef.current;\n if (a && fq.length > 0 && td.length > 0) {\n a.getByteFrequencyData(fq as Uint8Array<ArrayBuffer>);\n a.getByteTimeDomainData(td as Uint8Array<ArrayBuffer>);\n setFrame((n) => n + 1);\n }\n rafId = requestAnimationFrame(runLoop);\n };\n\n type AttachOutcome = \"ok\" | \"no-element\" | \"error\";\n\n const attach = (): AttachOutcome => {\n const el = audioRef.current;\n if (!el || cancelled) return \"no-element\";\n try {\n const { id, context, analyser } = attachLiveAnalyser(el, opts);\n consumerId = id;\n element = el;\n contextHolderRef.current = context;\n analyserHolderRef.current = analyser;\n setIsSuspended(context.state === \"suspended\");\n setError(null);\n\n context.addEventListener(\"statechange\", onStateChange);\n\n const n = analyser.frequencyBinCount;\n const fft = analyser.fftSize;\n freqRef.current = new Uint8Array(n);\n timeRef.current = new Uint8Array(fft);\n setMeta({ frequencyBinCount: n, sampleRate: context.sampleRate });\n\n rafId = requestAnimationFrame(runLoop);\n return \"ok\";\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to attach live analyser\";\n setError(msg);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n return \"error\";\n }\n };\n\n const first = attach();\n if (first !== \"ok\") {\n let retryRaf = 0;\n const maxAttempts = 120;\n let attempts = 0;\n\n const retryLoop = () => {\n if (cancelled) return;\n const out = attach();\n if (out === \"ok\" || out === \"error\") return;\n attempts += 1;\n if (attempts >= maxAttempts) return;\n retryRaf = requestAnimationFrame(retryLoop);\n };\n\n if (first === \"no-element\") {\n retryRaf = requestAnimationFrame(retryLoop);\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(retryRaf);\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n };\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n };\n }, [enabled, audioRef, opts, state.currentIndex]);\n\n return {\n frequencyData: freqRef.current,\n timeDomainData: timeRef.current,\n frequencyBinCount: meta.frequencyBinCount,\n sampleRate: meta.sampleRate,\n isSuspended,\n error,\n resume,\n frame,\n };\n}\n","import { useEffect } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerKeyboardShortcutBindings = {\n playPause?: string;\n next?: string;\n previous?: string;\n mute?: string;\n /** Key to seek forward by `seekSeconds`. Default: undefined (disabled). */\n seekForward?: string;\n /** Key to seek backward by `seekSeconds`. Default: undefined (disabled). */\n seekBackward?: string;\n /** Seconds to seek per `seekForward` / `seekBackward` keypress. Default: 5. */\n seekSeconds?: number;\n};\n\nexport function useGingerKeyboardShortcuts(\n enabled = true,\n bindings: GingerKeyboardShortcutBindings = {},\n): void {\n const { togglePlayPause, next, prev } = useGingerPlayback();\n const { toggleMute, seek, currentTime, duration } = useGingerMedia();\n\n const {\n mute: muteBinding,\n seekForward: seekForwardBinding,\n seekBackward: seekBackwardBinding,\n } = bindings;\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\") return;\n const playPause = (bindings.playPause ?? \" \").toLowerCase();\n const nextKey = (bindings.next ?? \"ArrowRight\").toLowerCase();\n const prevKey = (bindings.previous ?? \"ArrowLeft\").toLowerCase();\n const muteKey = muteBinding?.toLowerCase();\n const seekFwdKey = seekForwardBinding?.toLowerCase();\n const seekBwdKey = seekBackwardBinding?.toLowerCase();\n const seekSecs = bindings.seekSeconds ?? 5;\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (\n target &&\n ([\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName) || target.isContentEditable)\n )\n return;\n const key = event.key.toLowerCase();\n if (key === playPause) {\n event.preventDefault();\n togglePlayPause();\n } else if (key === nextKey) {\n event.preventDefault();\n next();\n } else if (key === prevKey) {\n event.preventDefault();\n prev();\n } else if (muteKey && key === muteKey) {\n event.preventDefault();\n toggleMute();\n } else if (seekFwdKey && key === seekFwdKey) {\n event.preventDefault();\n const dur = duration > 0 ? duration : Number.POSITIVE_INFINITY;\n seek(Math.min(dur, currentTime + seekSecs));\n } else if (seekBwdKey && key === seekBwdKey) {\n event.preventDefault();\n seek(Math.max(0, currentTime - seekSecs));\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [\n bindings.next,\n bindings.playPause,\n bindings.previous,\n bindings.seekSeconds,\n currentTime,\n duration,\n enabled,\n muteBinding,\n next,\n prev,\n seek,\n seekBackwardBinding,\n seekForwardBinding,\n toggleMute,\n togglePlayPause,\n ]);\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerSleepTimerOptions = {\n durationMs?: number;\n stopAfterTracks?: number;\n respectPause?: boolean;\n enabled?: boolean;\n onFire?: () => void;\n};\n\nexport function useGingerSleepTimer(options: GingerSleepTimerOptions): void {\n const { durationMs, stopAfterTracks, respectPause = true, enabled = true, onFire } = options;\n const { currentIndex, pause, isPaused } = useGingerPlayback();\n const remainingTracksRef = useRef(stopAfterTracks ?? 0);\n const prevIndexRef = useRef(currentIndex);\n\n // Remaining milliseconds for the duration-based timer; carried across pause/resume cycles.\n const remainingMsRef = useRef(durationMs ?? 0);\n // Timestamp when the current timer segment started (set when playback resumes).\n const segmentStartRef = useRef<number | null>(null);\n\n useEffect(() => {\n remainingTracksRef.current = stopAfterTracks ?? 0;\n }, [stopAfterTracks]);\n\n // Keep remainingMsRef in sync when durationMs changes while the timer is inactive.\n const prevDurationMsRef = useRef(durationMs);\n useEffect(() => {\n if (prevDurationMsRef.current !== durationMs) {\n remainingMsRef.current = durationMs ?? 0;\n prevDurationMsRef.current = durationMs;\n }\n }, [durationMs]);\n\n useEffect(() => {\n if (!enabled || !durationMs || durationMs <= 0) {\n // Reset remaining when disabled or no duration\n remainingMsRef.current = durationMs ?? 0;\n segmentStartRef.current = null;\n return;\n }\n\n if (respectPause && isPaused) {\n // Snapshot how much time is left before pausing\n if (segmentStartRef.current !== null) {\n const elapsed = Date.now() - segmentStartRef.current;\n remainingMsRef.current = Math.max(0, remainingMsRef.current - elapsed);\n segmentStartRef.current = null;\n }\n return;\n }\n\n // Playing: start (or continue) the countdown from remainingMsRef\n segmentStartRef.current = Date.now();\n const id = setTimeout(() => {\n remainingMsRef.current = 0;\n segmentStartRef.current = null;\n pause();\n onFire?.();\n }, remainingMsRef.current);\n\n return () => {\n clearTimeout(id);\n // Snapshot remaining when effect cleans up (e.g. isPaused or deps changed)\n if (segmentStartRef.current !== null) {\n const elapsed = Date.now() - segmentStartRef.current;\n remainingMsRef.current = Math.max(0, remainingMsRef.current - elapsed);\n segmentStartRef.current = null;\n }\n };\n }, [durationMs, enabled, isPaused, onFire, pause, respectPause]);\n\n useEffect(() => {\n if (!enabled || !stopAfterTracks || stopAfterTracks <= 0) return;\n const prev = prevIndexRef.current;\n prevIndexRef.current = currentIndex;\n if (currentIndex === prev) return;\n remainingTracksRef.current -= 1;\n if (remainingTracksRef.current <= 0) {\n pause();\n onFire?.();\n }\n }, [currentIndex, enabled, onFire, pause, stopAfterTracks]);\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerState } from \"../context/GingerSplitContexts\";\n\nexport function useGingerDebugLog(enabled = false): void {\n const state = useGingerState();\n const prevRef = useRef(state);\n\n useEffect(() => {\n if (!enabled || typeof console === \"undefined\") return;\n const prev = prevRef.current;\n if (prev !== state) {\n console.debug(\"[ginger]\", {\n from: {\n currentIndex: prev.currentIndex,\n isPaused: prev.isPaused,\n currentTime: prev.currentTime,\n repeatMode: prev.repeatMode,\n },\n to: {\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n currentTime: state.currentTime,\n repeatMode: state.repeatMode,\n },\n });\n }\n prevRef.current = state;\n }, [enabled, state]);\n}\n","import { useCallback, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport {\n gingerStateFromContextValues,\n useGingerMedia,\n useGingerPlayback,\n} from \"../context/GingerSplitContexts\";\nimport { progressFraction } from \"../internal/selectors\";\n\nexport type SeekDragState = {\n /** Raw drag fraction — only updated during an active drag gesture. */\n fraction: number;\n /** Blended fraction: follows live playback when idle, drag position when dragging. */\n displayFraction: number;\n isDragging: boolean;\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useSeekDrag(duration: number): SeekDragState {\n const media = useGingerMedia();\n const playback = useGingerPlayback();\n const { seek } = media;\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n const liveFraction = progressFraction(gingerStateFromContextValues(playback, media));\n const displayFraction = isDragging ? fraction : liveFraction;\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (!(duration > 0)) return;\n const target = event.currentTarget;\n const rect = target.getBoundingClientRect();\n const update = (clientX: number) => {\n const ratio = clamp01((clientX - rect.left) / rect.width);\n setFraction(ratio);\n seek(ratio * duration);\n };\n setIsDragging(true);\n target.setPointerCapture(event.pointerId);\n update(event.clientX);\n const onMove = (moveEvent: PointerEvent) => update(moveEvent.clientX);\n const onUp = (upEvent: PointerEvent) => {\n update(upEvent.clientX);\n setIsDragging(false);\n target.releasePointerCapture(event.pointerId);\n target.removeEventListener(\"pointermove\", onMove);\n target.removeEventListener(\"pointerup\", onUp);\n target.removeEventListener(\"pointercancel\", onUp);\n };\n target.addEventListener(\"pointermove\", onMove);\n target.addEventListener(\"pointerup\", onUp);\n target.addEventListener(\"pointercancel\", onUp);\n },\n [duration, seek],\n );\n\n return { fraction, displayFraction, isDragging, onPointerDown };\n}\n","import { useEffect } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { computeNextIndex } from \"../core/transitions\";\n\nexport type UseNextTrackPrefetchOptions = {\n /** When false, no prefetch runs. Default true. */\n enabled?: boolean;\n /**\n * Match `crossOrigin` on `Ginger.Player` when `fileUrl` is cross-origin so the browser\n * can reuse cached media consistently.\n */\n crossOrigin?: \"\" | \"anonymous\" | \"use-credentials\" | undefined;\n};\n\n/**\n * Warms the browser cache for the **logical** next track (same rules as the Next control:\n * `computeNextIndex` from queue, repeat, and playback mode) using a detached `HTMLAudioElement`\n * with `preload=\"auto\"`. Safe to call alongside `Ginger.Player`; it does not replace main playback.\n *\n * The effect depends on the `tracks` array reference from context. If the parent recreates `tracks`\n * every render, prefetch will restart repeatedly; keep a stable queue reference (e.g. memoize) when possible.\n */\nexport function useNextTrackPrefetch(options: UseNextTrackPrefetchOptions = {}): void {\n const { enabled = true, crossOrigin } = options;\n const { tracks, currentIndex, repeatMode, playbackMode } = useGingerPlayback();\n\n useEffect(() => {\n if (!enabled || typeof document === \"undefined\") return;\n const nextIndex = computeNextIndex({ tracks, currentIndex, repeatMode, playbackMode });\n if (nextIndex === currentIndex) return;\n const nextUrl = tracks[nextIndex]?.fileUrl ?? \"\";\n if (!nextUrl) return;\n\n const audio = document.createElement(\"audio\");\n audio.preload = \"auto\";\n if (crossOrigin) audio.crossOrigin = crossOrigin;\n audio.src = nextUrl;\n audio.load();\n\n return () => {\n audio.removeAttribute(\"src\");\n audio.load();\n };\n }, [enabled, crossOrigin, tracks, currentIndex, repeatMode, playbackMode]);\n}\n","import {\n clampPlaybackRate,\n clampVolume,\n createInitialState,\n gingerReducer,\n} from \"./core/playbackReducer\";\nimport type {\n GingerAction,\n GingerInitPayload,\n GingerState,\n PlaylistMeta,\n RepeatMode,\n Track,\n} from \"./types\";\n\nexport type GingerStoreOptions = {\n tracks?: Track[];\n currentIndex?: number;\n playlistMeta?: PlaylistMeta | null;\n isPaused?: boolean;\n isShuffled?: boolean;\n repeatMode?: RepeatMode;\n playbackMode?: GingerState[\"playbackMode\"];\n volume?: number;\n muted?: boolean;\n playbackRate?: number;\n};\n\nexport type GingerStore = {\n /** Returns the current state snapshot. */\n getState: () => GingerState;\n /** Dispatch an action to update state. Synchronously updates state and notifies listeners. */\n dispatch: (action: GingerAction) => void;\n /**\n * Subscribe to state changes. The listener is called after every `dispatch` that produces\n * a new state object. Returns an unsubscribe function.\n */\n subscribe: (listener: (state: GingerState) => void) => () => void;\n /** Convenience: re-initialise with a new set of init options (equivalent to `dispatch({ type: \"INIT\", ... })`). */\n init: (payload: GingerInitPayload) => void;\n /** Clamp helpers re-exported for convenience. */\n clampVolume: typeof clampVolume;\n clampPlaybackRate: typeof clampPlaybackRate;\n};\n\n/**\n * Framework-agnostic store wrapping `gingerReducer`.\n * Usable outside React — e.g. in Svelte, Vue, Node.js testing, or server-side rendering contexts.\n *\n * @example\n * ```ts\n * import { createGingerStore } from \"@lucaismyname/ginger\";\n *\n * const store = createGingerStore({ tracks: myTracks });\n * const unsub = store.subscribe((state) => console.log(state.currentIndex));\n * store.dispatch({ type: \"NEXT\" });\n * unsub();\n * ```\n */\nexport function createGingerStore(options: GingerStoreOptions = {}): GingerStore {\n let state = createInitialState({\n tracks: options.tracks ?? [],\n currentIndex: options.currentIndex,\n playlistMeta: options.playlistMeta,\n isPaused: options.isPaused,\n isShuffled: options.isShuffled,\n repeatMode: options.repeatMode,\n playbackMode: options.playbackMode,\n volume: options.volume,\n muted: options.muted,\n playbackRate: options.playbackRate,\n });\n\n const listeners = new Set<(state: GingerState) => void>();\n\n const dispatch = (action: GingerAction): void => {\n const next = gingerReducer(state, action);\n if (next !== state) {\n state = next;\n for (const listener of listeners) {\n listener(state);\n }\n }\n };\n\n const subscribe = (listener: (state: GingerState) => void): (() => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n\n const init = (payload: GingerInitPayload): void => {\n dispatch({ type: \"INIT\", payload });\n };\n\n return {\n getState: () => state,\n dispatch,\n subscribe,\n init,\n clampVolume,\n clampPlaybackRate,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport type { Track } from \"../types\";\n\nexport type GingerPlaybackHistoryEntry = {\n track: Track;\n /** The track's index in the queue at the time it was played. */\n index: number;\n /** Unix timestamp (ms) when the track started playing. */\n playedAt: number;\n};\n\nexport type UseGingerPlaybackHistoryOptions = {\n /** Maximum number of entries to keep. Oldest entries are dropped first. Default: 50. */\n maxLength?: number;\n};\n\nexport type UseGingerPlaybackHistoryResult = {\n /** Chronological list of played tracks; most recent entry is last. */\n history: GingerPlaybackHistoryEntry[];\n clearHistory: () => void;\n};\n\n/**\n * Records a history of played tracks in chronological order.\n * Useful for \"what was playing before\" in shuffle mode or for analytics.\n *\n * The history is stored in component state and does not survive remounts.\n * In shuffle mode, `index` reflects the position in the current shuffled queue.\n */\nexport function useGingerPlaybackHistory(\n options: UseGingerPlaybackHistoryOptions = {},\n): UseGingerPlaybackHistoryResult {\n const { maxLength = 50 } = options;\n const { tracks, currentIndex } = useGingerPlayback();\n\n const [history, setHistory] = useState<GingerPlaybackHistoryEntry[]>([]);\n const prevIndexRef = useRef<number | null>(null);\n const prevTracksRef = useRef(tracks);\n prevTracksRef.current = tracks;\n\n useEffect(() => {\n const track = tracks[currentIndex];\n if (!track) return;\n\n if (prevIndexRef.current === currentIndex) return;\n prevIndexRef.current = currentIndex;\n\n const entry: GingerPlaybackHistoryEntry = {\n track,\n index: currentIndex,\n playedAt: Date.now(),\n };\n\n setHistory((prev) => {\n const next = [...prev, entry];\n return next.length > maxLength ? next.slice(next.length - maxLength) : next;\n });\n }, [currentIndex, tracks, maxLength]);\n\n const clearHistory = useCallback(() => setHistory([]), []);\n\n return { history, clearHistory };\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport { useGingerMedia } from \"../context/GingerSplitContexts\";\n\nexport type UseGingerVolumeFadeOptions = {\n /** Target volume to fade to (0–1). */\n targetVolume: number;\n /** Duration of the fade in milliseconds. */\n durationMs: number;\n /** Called when the fade completes normally (not when cancelled). */\n onComplete?: () => void;\n};\n\nexport type UseGingerVolumeFadeResult = {\n /** Start a volume fade. Cancels any in-progress fade. */\n fadeVolumeTo: (options: UseGingerVolumeFadeOptions) => void;\n /** Cancel the current fade and hold at the current volume. */\n cancelFade: () => void;\n /** True while a fade is in progress. */\n isFading: boolean;\n};\n\n/**\n * Smoothly interpolates volume over a given duration using `requestAnimationFrame`.\n * Useful for fade-in on track start, fade-out before sleep timer fires, or crossfade prep.\n */\nexport function useGingerVolumeFade(): UseGingerVolumeFadeResult {\n const { setVolume, volume } = useGingerMedia();\n const [isFading, setIsFading] = useState(false);\n\n const rafRef = useRef<number>(0);\n const cancelledRef = useRef(false);\n\n const cancelFade = useCallback(() => {\n cancelAnimationFrame(rafRef.current);\n cancelledRef.current = true;\n setIsFading(false);\n }, []);\n\n const fadeVolumeTo = useCallback(\n ({ targetVolume, durationMs, onComplete }: UseGingerVolumeFadeOptions) => {\n cancelAnimationFrame(rafRef.current);\n cancelledRef.current = false;\n\n const clamp = (v: number) => Math.min(1, Math.max(0, v));\n const target = clamp(targetVolume);\n const startTime = performance.now();\n\n // Capture start volume at the moment the fade begins\n let startVolume = volume;\n\n setIsFading(true);\n\n const tick = (now: number) => {\n if (cancelledRef.current) return;\n const elapsed = now - startTime;\n const progress = Math.min(1, elapsed / Math.max(1, durationMs));\n const current = startVolume + (target - startVolume) * progress;\n setVolume(clamp(current));\n\n if (progress < 1) {\n rafRef.current = requestAnimationFrame(tick);\n } else {\n setIsFading(false);\n onComplete?.();\n }\n };\n\n // Use a small delay so `volume` from closure is the current value\n rafRef.current = requestAnimationFrame((now) => {\n startVolume = volume;\n tick(now);\n });\n },\n [setVolume, volume],\n );\n\n return { fadeVolumeTo, cancelFade, isFading };\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerChapterProgress = {\n /** Fraction (0–1) of the way through the active chapter. 0 when no chapter is active. */\n progress: number;\n /** Seconds elapsed since the start of the active chapter. */\n elapsed: number;\n /** Seconds remaining until the end of the active chapter (or until end of track if last chapter). */\n remaining: number;\n};\n\n/**\n * Returns detailed progress information for the currently active chapter.\n * Complements `useGingerChapters` with per-chapter playback fractions.\n */\nexport function useGingerChapterProgress(): GingerChapterProgress {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime, duration } = useGingerMedia();\n\n const chapters = useMemo(() => {\n const raw = tracks[currentIndex]?.chapters ?? [];\n return [...raw]\n .filter((c) => c && Number.isFinite(c.startSeconds) && c.startSeconds >= 0)\n .sort((a, b) => a.startSeconds - b.startSeconds);\n }, [tracks, currentIndex]);\n\n return useMemo<GingerChapterProgress>(() => {\n if (chapters.length === 0) return { progress: 0, elapsed: 0, remaining: 0 };\n\n // Find active chapter (last one whose start is <= currentTime)\n let activeIdx = -1;\n for (let i = chapters.length - 1; i >= 0; i--) {\n if (currentTime >= chapters[i]!.startSeconds) {\n activeIdx = i;\n break;\n }\n }\n\n if (activeIdx === -1) return { progress: 0, elapsed: 0, remaining: 0 };\n\n const chapter = chapters[activeIdx]!;\n const nextChapter = chapters[activeIdx + 1];\n const chapterEnd = nextChapter?.startSeconds ?? (duration > 0 ? duration : currentTime);\n const chapterDuration = Math.max(0, chapterEnd - chapter.startSeconds);\n const elapsed = Math.max(0, currentTime - chapter.startSeconds);\n const remaining = Math.max(0, chapterEnd - currentTime);\n const progress = chapterDuration > 0 ? Math.min(1, elapsed / chapterDuration) : 0;\n\n return { progress, elapsed, remaining };\n }, [chapters, currentTime, duration]);\n}\n"],"names":["emptyFreq","emptyTime","useGingerLiveAnalyzer","options","enabled","fftSize","smoothingTimeConstant","minDecibels","maxDecibels","audioRef","state","useGinger","opts","useMemo","frame","setFrame","useState","error","setError","isSuspended","setIsSuspended","meta","setMeta","freqRef","useRef","timeRef","resume","useCallback","ctx","contextHolderRef","analyserHolderRef","useLayoutEffect","cancelled","consumerId","element","rafId","onStateChange","runLoop","a","fq","td","n","attach","el","id","context","analyser","attachLiveAnalyser","fft","e","msg","first","retryRaf","maxAttempts","attempts","retryLoop","out","detachLiveAnalyser","_a","useGingerKeyboardShortcuts","bindings","togglePlayPause","next","prev","useGingerPlayback","toggleMute","seek","currentTime","duration","useGingerMedia","muteBinding","seekForwardBinding","seekBackwardBinding","useEffect","playPause","nextKey","prevKey","muteKey","seekFwdKey","seekBwdKey","seekSecs","onKeyDown","event","target","key","dur","useGingerSleepTimer","durationMs","stopAfterTracks","respectPause","onFire","currentIndex","pause","isPaused","remainingTracksRef","prevIndexRef","remainingMsRef","segmentStartRef","prevDurationMsRef","elapsed","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","media","playback","fraction","setFraction","isDragging","setIsDragging","liveFraction","progressFraction","gingerStateFromContextValues","displayFraction","onPointerDown","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent","useNextTrackPrefetch","crossOrigin","tracks","repeatMode","playbackMode","nextIndex","computeNextIndex","nextUrl","audio","createGingerStore","createInitialState","listeners","dispatch","action","gingerReducer","listener","payload","clampVolume","clampPlaybackRate","useGingerPlaybackHistory","maxLength","history","setHistory","prevTracksRef","track","entry","clearHistory","useGingerVolumeFade","setVolume","volume","isFading","setIsFading","rafRef","cancelledRef","cancelFade","targetVolume","onComplete","clamp","v","startTime","startVolume","tick","now","progress","current","useGingerChapterProgress","chapters","c","b","activeIdx","i","chapter","nextChapter","chapterEnd","chapterDuration","remaining"],"mappings":"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"}
|