Refactor App into TS modules; add tsc typecheck
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import { Check, ChevronLeft, ChevronRight, Link } from "lucide-react";
|
||||
import type { KeyboardEventHandler, MouseEventHandler } from "react";
|
||||
import type { BookMetadata } from "../types";
|
||||
import { styles } from "../styles";
|
||||
import { PauseSolid, PlaySolid } from "./Icons";
|
||||
|
||||
type Props = {
|
||||
isPlaying: boolean;
|
||||
onTogglePlay: () => void;
|
||||
onBack10: () => void;
|
||||
onForward10: () => void;
|
||||
|
||||
onProgressClick: MouseEventHandler<HTMLDivElement>;
|
||||
onProgressKeyDown: KeyboardEventHandler<HTMLDivElement>;
|
||||
progressPercent: number;
|
||||
currentIndex: number;
|
||||
wordsLength: number;
|
||||
|
||||
linkCopied: boolean;
|
||||
onCopyLink: () => void;
|
||||
|
||||
bookMetadata: BookMetadata | null;
|
||||
bookStatsText: string | null;
|
||||
};
|
||||
|
||||
export function BottomControls({
|
||||
isPlaying,
|
||||
onTogglePlay,
|
||||
onBack10,
|
||||
onForward10,
|
||||
onProgressClick,
|
||||
onProgressKeyDown,
|
||||
progressPercent,
|
||||
currentIndex,
|
||||
wordsLength,
|
||||
linkCopied,
|
||||
onCopyLink,
|
||||
bookMetadata,
|
||||
bookStatsText,
|
||||
}: Props) {
|
||||
return (
|
||||
<div style={styles.bottomArea} className="bottom-area">
|
||||
<div style={styles.controlsRow}>
|
||||
<button onClick={onBack10} style={styles.skipBtn} title="Back 10 words">
|
||||
<ChevronLeft size={24} />
|
||||
<ChevronLeft size={24} style={{ marginLeft: -14 }} />
|
||||
</button>
|
||||
<button
|
||||
onClick={onTogglePlay}
|
||||
style={styles.playBtn}
|
||||
className="play-btn"
|
||||
>
|
||||
{isPlaying ? <PauseSolid size={32} /> : <PlaySolid size={32} />}
|
||||
</button>
|
||||
<button
|
||||
onClick={onForward10}
|
||||
style={styles.skipBtn}
|
||||
title="Forward 10 words"
|
||||
>
|
||||
<ChevronRight size={24} />
|
||||
<ChevronRight size={24} style={{ marginLeft: -14 }} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={styles.progressContainer}
|
||||
onClick={onProgressClick}
|
||||
onKeyDown={onProgressKeyDown}
|
||||
role="slider"
|
||||
tabIndex={0}
|
||||
aria-label="Reading progress"
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
aria-valuenow={Math.round(progressPercent)}
|
||||
aria-valuetext={`${Math.round(progressPercent)}% complete, word ${currentIndex + 1} of ${wordsLength}`}
|
||||
>
|
||||
<div style={{ ...styles.progressBar, width: `${progressPercent}%` }} />
|
||||
</div>
|
||||
<div style={styles.progressRow}>
|
||||
<div style={styles.progressText}>
|
||||
{currentIndex + 1} / {wordsLength} ({Math.round(progressPercent)}%)
|
||||
</div>
|
||||
<button
|
||||
onClick={onCopyLink}
|
||||
style={styles.linkBtn}
|
||||
className="icon-btn"
|
||||
title="Copy link to current position"
|
||||
>
|
||||
{linkCopied ? <Check size={14} /> : <Link size={14} />}
|
||||
<span style={styles.linkBtnText}>
|
||||
{linkCopied ? "Copied" : "Copy link"}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style={styles.hint} className="hint">
|
||||
<kbd style={styles.kbd}>Space</kbd> play<kbd style={styles.kbd}>←</kbd>
|
||||
<kbd style={styles.kbd}>→</kbd> word<kbd style={styles.kbd}>↑</kbd>
|
||||
<kbd style={styles.kbd}>↓</kbd> speed<kbd style={styles.kbd}>R</kbd>{" "}
|
||||
reset
|
||||
</div>
|
||||
|
||||
{bookMetadata && (bookMetadata.title || bookMetadata.cover) && (
|
||||
<aside
|
||||
style={styles.bookMetadata}
|
||||
aria-label="Current book"
|
||||
className="book-metadata"
|
||||
>
|
||||
{bookMetadata.cover && (
|
||||
<img
|
||||
src={bookMetadata.cover}
|
||||
alt={`Cover of ${bookMetadata.title || "current book"}`}
|
||||
style={styles.bookCover}
|
||||
className="book-cover"
|
||||
/>
|
||||
)}
|
||||
<div style={styles.bookInfo}>
|
||||
{bookMetadata.title && (
|
||||
<h3 style={styles.bookTitle} className="book-title">
|
||||
{bookMetadata.title}
|
||||
</h3>
|
||||
)}
|
||||
{bookMetadata.author && (
|
||||
<p style={styles.bookAuthor} className="book-author">
|
||||
{bookMetadata.author}
|
||||
</p>
|
||||
)}
|
||||
{bookStatsText && (
|
||||
<p style={styles.bookStats} className="book-stats">
|
||||
{bookStatsText}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</aside>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user