fix lint: make bun tsc --noEmit actually pass (was a TS crash + latent errors)

tsconfig used jsx:"preserve"+jsxImportSource, which trips a TS 5.9
internal crash ("Expected sourceFile.imports[0] to be the synthesized JSX
runtime import") so tsc could never run clean. Switch to jsx:"react-jsx"
with the package's real jsx-runtime types, and fix the real errors that
surfaced:
- delete dead src/components/Navigation.tsx (imported ./Tab that doesn't
  exist; the component has no importers)
- PlaybackControls: fix relative path to @/utils/audio-player
- SourceBadge: drop dead module-level typeColor (bare 'theme')
- command palette: bind to the real 'command' keybind (:) instead of the
  never-defined 'command_list' action (palette was unreachable)
- yazi-pane-row test: destroy() must return Promise<void> as typed

Also fold in the package.json lint fix (bun tsc --noEmit) and doc polish.
This commit is contained in:
2026-08-07 18:18:25 -04:00
parent 1d3abd53d4
commit 0cc15c8d90
8 changed files with 403 additions and 410 deletions

View File

@@ -1,64 +1,86 @@
import type { BackendName } from "../utils/audio-player"
import { useTheme } from "@/context/ThemeContext"
import type { BackendName } from "@/utils/audio-player";
import { useTheme } from "@/context/ThemeContext";
type PlaybackControlsProps = {
isPlaying: boolean
volume: number
speed: number
backendName?: BackendName
hasAudioUrl?: boolean
onToggle: () => void
onPrev: () => void
onNext: () => void
onVolumeChange: (value: number) => void
onSpeedChange: (value: number) => void
}
isPlaying: boolean;
volume: number;
speed: number;
backendName?: BackendName;
hasAudioUrl?: boolean;
onToggle: () => void;
onPrev: () => void;
onNext: () => void;
onVolumeChange: (value: number) => void;
onSpeedChange: (value: number) => void;
};
const BACKEND_LABELS: Record<BackendName, string> = {
mpv: "mpv",
ffplay: "ffplay",
afplay: "afplay",
system: "system",
none: "none",
}
mpv: "mpv",
ffplay: "ffplay",
afplay: "afplay",
system: "system",
none: "none",
};
export function PlaybackControls(props: PlaybackControlsProps) {
const { theme } = useTheme();
return (
<box flexDirection="row" gap={1} alignItems="center" border padding={1} borderColor={theme.border}>
<box border padding={0} onMouseDown={props.onPrev} borderColor={theme.border}>
<text fg={theme.primary}>[Prev]</text>
</box>
<box border padding={0} onMouseDown={props.onToggle} borderColor={theme.border}>
<text fg={theme.primary}>{props.isPlaying ? "[Pause]" : "[Play]"}</text>
</box>
<box border padding={0} onMouseDown={props.onNext} borderColor={theme.border}>
<text fg={theme.primary}>[Next]</text>
</box>
<box flexDirection="row" gap={1} marginLeft={2}>
<text fg={theme.textMuted}>Vol</text>
<text fg={theme.text}>{Math.round(props.volume * 100)}%</text>
</box>
<box flexDirection="row" gap={1} marginLeft={2}>
<text fg={theme.textMuted}>Speed</text>
<text fg={theme.text}>{props.speed}x</text>
</box>
{props.backendName && props.backendName !== "none" && (
<box flexDirection="row" gap={1} marginLeft={2}>
<text fg={theme.textMuted}>via</text>
<text fg={theme.primary}>{BACKEND_LABELS[props.backendName]}</text>
</box>
)}
{props.backendName === "none" && (
<box marginLeft={2}>
<text fg={theme.warning}>No audio player found</text>
</box>
)}
{props.hasAudioUrl === false && (
<box marginLeft={2}>
<text fg={theme.warning}>No audio URL</text>
</box>
)}
</box>
)
const { theme } = useTheme();
return (
<box
flexDirection="row"
gap={1}
alignItems="center"
border
padding={1}
borderColor={theme.border}
>
<box
border
padding={0}
onMouseDown={props.onPrev}
borderColor={theme.border}
>
<text fg={theme.primary}>[Prev]</text>
</box>
<box
border
padding={0}
onMouseDown={props.onToggle}
borderColor={theme.border}
>
<text fg={theme.primary}>{props.isPlaying ? "[Pause]" : "[Play]"}</text>
</box>
<box
border
padding={0}
onMouseDown={props.onNext}
borderColor={theme.border}
>
<text fg={theme.primary}>[Next]</text>
</box>
<box flexDirection="row" gap={1} marginLeft={2}>
<text fg={theme.textMuted}>Vol</text>
<text fg={theme.text}>{Math.round(props.volume * 100)}%</text>
</box>
<box flexDirection="row" gap={1} marginLeft={2}>
<text fg={theme.textMuted}>Speed</text>
<text fg={theme.text}>{props.speed}x</text>
</box>
{props.backendName && props.backendName !== "none" && (
<box flexDirection="row" gap={1} marginLeft={2}>
<text fg={theme.textMuted}>via</text>
<text fg={theme.primary}>{BACKEND_LABELS[props.backendName]}</text>
</box>
)}
{props.backendName === "none" && (
<box marginLeft={2}>
<text fg={theme.warning}>No audio player found</text>
</box>
)}
{props.hasAudioUrl === false && (
<box marginLeft={2}>
<text fg={theme.warning}>No audio URL</text>
</box>
)}
</box>
);
}