'use client' import { useMemo } from 'react' import katex from 'katex' import { AnimPlayerShell } from '@/components/simulators/anim-player-shell' import type { StepsBlock } from '@/lib/interactive-page' import { cn } from '@/lib/utils' function renderTex(tex: string, displayMode: boolean): string { try { return katex.renderToString(tex, { displayMode, throwOnError: false }) } catch { return tex } } /** * Step-by-step derivation (Symbolab/Khan style): equation states revealed * line by line, current line highlighted, transformation rule in the margin. * No boxes, no LLM drawing — pure KaTeX + deterministic chrome. */ export function StepsBlockView({ block, lang, }: { block: StepsBlock lang: string }) { const fr = lang.startsWith('fr') const steps = block.steps const beats = useMemo( () => steps.map((s, i) => ({ id: `st${i + 1}`, speak: { fr: s.speak || s.rule || (fr ? `Étape ${i + 1}` : `Step ${i + 1}`), en: s.speak || s.rule || `Step ${i + 1}`, }, })), [steps, fr] ) const rendered = useMemo(() => steps.map((s) => renderTex(s.tex, true)), [steps]) return (
{block.title ? (

{block.title}

{fr ? 'Dérivation pas à pas' : 'Step-by-step derivation'}
) : null} {(stepIndex) => (
{steps.slice(0, stepIndex + 1).map((s, i) => { const current = i === stepIndex return (
{String(i + 1).padStart(2, '0')}
{s.rule ? ( {s.rule} ) : null}
) })}
)} {block.caption ? (
{block.caption}
) : null} {/* Without JS: full derivation visible + rules listed */}
) }