"use client"; import { useState } from "react"; import { Button } from "../ui/primitives"; import { PreviewTap } from "./preview-tap"; import { tileTally } from "./tally"; import type { Production, Source } from "./types"; export type GridTier = "2x1" | "2x2" | "3x3" | "4x4" | "custom"; export function liveTapIds(sources: Source[], tier: GridTier, focused: string | null, upgrades: string[], mobile: boolean): string[] { const ids = sources.map(source => source.id); const valid = (id: string): boolean => id === "program" || ids.includes(id); const candidates = mobile ? [focused ?? "program"] : tier === "2x1" || tier === "2x2" ? ["program", ...(focused ? [focused] : []), ...ids] : ["program", ...(focused ? [focused] : []), ...upgrades]; return [...new Set(candidates)].filter(valid).slice(0, mobile ? 1 : Math.min(4, tier === "2x1" ? 2 : 4)); } export function MultiviewGrid({ production, observed, channelId, fixture, mobile, liveIds, focused, onFocus, tier, onTier, upgrades, onUpgrade }: { production: Production; observed: Production | null; channelId: string; fixture: boolean; mobile: boolean; liveIds: string[]; focused: string | null; onFocus: (id: string) => void; tier: GridTier; onTier: (tier: GridTier) => void; upgrades: string[]; onUpgrade: (id: string) => void }): React.ReactElement { const [columns, setColumns] = useState(3); const capacity = tier === "2x1" ? 2 : tier === "2x2" ? 4 : tier === "3x3" ? 9 : 16; const tiles = [{ id: "program", label: "PGM · encoder output", kind: "hls" as const }, ...production.sources].slice(0, capacity); const selectedSourceIds = production.scenes.find(scene => scene.id === production.buses.preview)?.slots.map(slot => slot.sourceId) ?? []; return
{tier === "custom" && } {liveIds.length}/{mobile ? 1 : 4} live slots · tap to focus
{tiles.map(source => { const tally = source.id === "program" ? observed?.buses.program ? "program" : "none" : tileTally(observed, source.id); return

{fixture ? "SAMPLE" : "Health not reported"}

{!mobile && (tier === "3x3" || tier === "4x4" || tier === "custom") && source.id !== "program" && source.id !== focused && }
; })}

Extra live tiles can strain the device. Red/green tally uses the worker’s realized version. Unknown versions have no tally.

; }