import React from "react"; import type NodeCG from "@nodecg/types"; import type { AssetFile, BreakSlide } from "../types"; import { useReplicantValue } from "./lib"; const breakSlideReplicant = nodecg.Replicant( "breakSlide", ) as unknown as NodeCG.ServerReplicant; // Optional background image (dashboard Assets → "Pauza — pozadinska slika"); // when present it replaces the drifting blobs. const backgroundReplicant = nodecg.Replicant( "assets:break-bg", ) as unknown as NodeCG.ServerReplicant; // Optional band logo (dashboard Assets → "Pauza — logo benda"), shown between // the heading and the act name. const logoReplicant = nodecg.Replicant( "assets:break-logo", ) as unknown as NodeCG.ServerReplicant; interface Blob { size: number; left: string; top: string; color: string; animation: string; } // Huge blurred radial blobs on slow drift loops — GPU-cheap ambient motion. // Colors come from the THEME LAB block in index.css. const BLOBS: Blob[] = [ { size: 900, left: "-10%", top: "-20%", color: "var(--color-break-blob-1)", animation: "drift-a 90s ease-in-out infinite alternate", }, { size: 800, left: "55%", top: "40%", color: "var(--color-break-blob-2)", animation: "drift-b 110s ease-in-out infinite alternate", }, { size: 700, left: "25%", top: "55%", color: "var(--color-break-blob-3)", animation: "drift-c 70s ease-in-out infinite alternate", }, ]; export function Break() { const slide = useReplicantValue(breakSlideReplicant); const backgroundUrl = useReplicantValue(backgroundReplicant)?.[0]?.url ?? null; // The slide names which uploaded file to use; fall back to the first one if // nothing is picked or the picked file was deleted. const logoFiles = useReplicantValue(logoReplicant); const logoUrl = (logoFiles?.find((f) => f.base === slide?.logoName) ?? logoFiles?.[0]) ?.url ?? null; return (
{backgroundUrl ? ( <> {/* scrim keeps the announcement text readable — tune to taste */}
) : ( BLOBS.map((blob, i) => (
)) )} {/* Text stays well inside the edges: this same source is shown shrunk to 70% in the BREAK_AD_* scenes, so extremes would crowd the ad cutout. */}
{slide?.heading}
{(slide?.logoVisible ?? true) && logoUrl && ( )}
{slide?.nextActName}
{slide?.nextActFrom}
); }