import clsx from "clsx"; import type { ReactNode } from "react"; import { Activity, Download, FastForward, Info, Keyboard, Maximize, MoreHorizontal, Pause, Play, Pin, Rewind, RotateCcw, Settings, SkipBack, SkipForward, Subtitles, Volume2, X, } from "lucide-react"; import { Btn } from "./batchA"; import { C1 } from "./batchCActions"; import { Reference, Sample } from "./labKit"; import { FADE_ABOVE_PANEL, FADE_BELOW_PANEL, LAYER } from "./labTokens"; import { SURFACE } from "../components/ui/surfaces"; import { iconButtonClass } from "../components/ui/buttonStyles"; import { fieldClass } from "../components/ui/fieldStyles"; // The ui/ primitives' own classes on static spans: the lab draws what the app ships, not a copy. const ICON = iconButtonClass({ variant: "ghost", size: "sm" }); // E28 S2 · Batch C — behaviour on touch and on a narrow window, DECIDED (owner, 2026-09-24): C1–C4 as // proposed; C5 is the owner's reworked Plex control set (found by the live player pass, E28 S2d: the // old row ran off-screen below 1024) with the two refinements they accepted. References only. const ico = "w-4 h-4"; function Screen({ label, children }: { label: string; children: ReactNode }) { return (
{children}
); } function Content() { return (
{Array.from({ length: 9 }, (_, i) => (
Video {i + 1}
))}
); } function FilterPanel() { return (
Filters
{["Unwatched", "Shorts hidden", "Last 30 days", "Tech", "Science"].map((f) => ( {f} ))}
); } // ── C2 · side panels on touch and on a narrow window ───────────────────────────────────────────── function C2() { return (
); } // ── C3 · the players on touch ──────────────────────────────────────────────────────────────────── function C3() { const btn = "grid h-11 w-11 place-items-center rounded-full"; return (
{/* The visible track stays thin; the dashed box is the 44-tall hit area around it. */}
{[Pause, SkipForward, Volume2, Subtitles].map((I, i) => ( ))} 12:04 / 31:40
); } // ── C4 · dialog conventions ────────────────────────────────────────────────────────────────────── function Field({ label, value, focused }: { label: string; value: string; focused?: boolean }) { return ( ); } function C4() { return (
Edit details
Cancel Save
); } export function BatchC() { return (
); } // ── C5 · the Plex player's controls (the owner's model, 2026-09-24) ────────────────────────────── // What is left after Stop, Restart and ±10 s leave the row fits a portrait tablet in one row, with a // fixed "⋯" for the rare tools; restarting moves onto the card. const ROW: { icon: typeof Pause; label: string }[] = [ { icon: Pause, label: "Play / pause" }, { icon: SkipBack, label: "Back: restart, then the previous episode" }, { icon: SkipForward, label: "Next episode (only when there is one)" }, { icon: Volume2, label: "Mute" }, ]; const MORE: { icon: typeof Pause; label: string }[] = [ { icon: Settings, label: "Player settings" }, { icon: Info, label: "Media info" }, { icon: Activity, label: "Stats for nerds" }, { icon: Keyboard, label: "Keyboard shortcuts" }, { icon: Download, label: "Download original file" }, ]; const ctl = "grid h-11 w-11 shrink-0 place-items-center rounded-full"; function PlayerRow() { return (
{/* Double-tap zones: the left and right thirds of the picture skip ∓10 s on touch. */}
double-tap −10 s double-tap +10 s
{ROW.map((c) => ( ))} 12:04 / 42:21
{MORE.map((c) => ( {c.label} ))}
); } function MediaCard({ state }: { state: "new" | "started" | "touch" }) { const pill = "inline-flex h-8 items-center gap-1.5 rounded-full px-3 text-xs font-medium"; return (
{state !== "new" && ( )} {state === "new" && ( )} {state === "started" && ( Continue Restart )}
Darkman III
{state === "new" ? "1996 · not started" : "1996 · 14 min in"}
{state === "touch" && ( )}
); } function Cards() { return (
); } function C5() { return (
); }