TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1"use client";2import * as React from "react";34/**5 * Fake streaming engine for the marketing mocks — purely client-side, nothing is sent anywhere.6 * Drives one or more scripted texts character by character with a per-stream delay and speed,7 * and records wall-clock timings so the mock metadata (tok/s, TTFT) is internally consistent.8 */9export interface FakeStream {10 text: string;11 /** characters per tick (~35 ms) */12 speed: number;13 /** ms before the first token */14 delay: number;15}1617export interface FakeStreamState {18 /** Characters revealed per stream. */19 progress: number[];20 /** ms since the first token of stream i (frozen when it completes). */21 elapsedFor: (i: number) => number;22 /** Time to first token per stream (its scripted delay). */23 ttftFor: (i: number) => number;24 done: (i: number) => boolean;25 allDone: boolean;26}2728export function useFakeStreams(streams: FakeStream[], active: boolean, replayKey: number, instant: boolean): FakeStreamState {29 const [progress, setProgress] = React.useState<number[]>(() => streams.map(() => 0));30 const [elapsed, setElapsed] = React.useState(0);31 const [finishedAt, setFinishedAt] = React.useState<(number | null)[]>(() => streams.map(() => null));3233 React.useEffect(() => {34 if (!active) return;35 if (instant) {36 // Reduced motion: show the finished state right away.37 const t = setTimeout(() => {38 setProgress(streams.map((s) => s.text.length));39 setFinishedAt(streams.map((s) => s.delay + 2400));40 setElapsed(2400);41 }, 0);42 return () => clearTimeout(t);43 }44 const started = performance.now();45 let cancelled = false;46 let raf = 0;47 let last = started;48 const finished: (number | null)[] = streams.map(() => null);49 const tick = (now: number) => {50 if (cancelled) return;51 const sinceStart = now - started;52 if (now - last >= 35) {53 last = now;54 setElapsed(sinceStart);55 setProgress((prev) => {56 let done = true;57 const next = prev.map((p, i) => {58 const s = streams[i];59 if (sinceStart < s.delay) {60 done = false;61 return 0;62 }63 if (p >= s.text.length) return p;64 const jitter = Math.random() < 0.15 ? 0 : s.speed;65 const n = Math.min(s.text.length, p + jitter);66 if (n < s.text.length) done = false;67 else if (finished[i] === null) finished[i] = sinceStart;68 return n;69 });70 if (done) cancelled = true;71 return next;72 });73 setFinishedAt([...finished]);74 }75 if (!cancelled) raf = requestAnimationFrame(tick);76 };77 const start = setTimeout(() => {78 setProgress(streams.map(() => 0));79 setFinishedAt(streams.map(() => null));80 setElapsed(0);81 raf = requestAnimationFrame(tick);82 }, 250);83 return () => {84 cancelled = true;85 clearTimeout(start);86 cancelAnimationFrame(raf);87 };88 // replayKey intentionally restarts the effect; `streams` are module constants.89 // eslint-disable-next-line react-hooks/exhaustive-deps90 }, [active, instant, replayKey]);9192 const elapsedFor = (i: number) => Math.max(0, (finishedAt[i] ?? elapsed) - streams[i].delay);93 const ttftFor = (i: number) => streams[i].delay;94 const done = (i: number) => progress[i] >= streams[i].text.length;95 const allDone = streams.every((s, i) => progress[i] >= s.text.length);96 return { progress, elapsedFor, ttftFor, done, allDone };97}9899export function approxTokens(chars: number) {100 return Math.round(chars / 4);101}102103/** Which stream finishes first given the scripted delays and speeds (35 ms per tick). */104export function fastestIndex(streams: FakeStream[]): number {105 return streams.map((s, i) => [s.delay + (s.text.length / s.speed) * 35, i] as const).sort((a, b) => a[0] - b[0])[0][1];106}107