import type { DesignState, LineSegment, LineStitchBounds } from '../App.tsx'; import type { HoopConfig } from '../data.ts'; import type { MachinePreset } from '../data.ts'; import type { WarningLocation } from '../lib/engine.ts'; import type { PathParamDef, PointParamDef } from '../lib/editor/parameters.ts'; import StageCanvas from './StageCanvas.tsx'; import PlaybackBar from './PlaybackBar.tsx'; import StatsChips from './StatsChips.tsx'; import styles from './StagePane.module.css'; import { cn } from '@/utils.ts'; import { colorDist } from '../lib/core/colormath.ts'; import type { CSSProperties } from 'react'; interface Props { design: DesignState; hoop: HoopConfig; scrubPos: number; onScrubChange: (v: number) => void; activeLine: number | null; lineSegments: LineSegment[]; warningLoc: WarningLocation | null; hoveredLineBounds: LineStitchBounds | null; showDensity: boolean; onToggleDensity: () => void; chalkControl: { visible: boolean; toggle: () => void }; hideJumps: boolean; onToggleHideJumps: () => void; hoveredDataVar?: string | null; pinnedDataVars?: Set; // ── XY handle props ─────────────────────────────────────────────────────── pointParams?: PointParamDef[]; pathParams?: PathParamDef[]; showHandles?: boolean; onToggleHandles?: () => void; highlightedHandle?: string | null; lockedHandles?: Set; onHandleDrag?: ( name: string, line: number, x: number, y: number, options?: { breakPair: boolean }, ) => void; onHandleCommit?: ( name: string, line: number, x: number, y: number, options?: { breakPair: boolean }, ) => void; onPathInsert?: (name: string, segment: number, t: number) => void; onPathDelete?: (name: string, anchor: number) => void; onCurveToggleSmooth?: (name: string, anchor: number) => void; onPathTranslate?: (name: string, dx: number, dy: number, commit: boolean) => void; onMachineContextMenu?: (x: number, y: number) => void; machine?: MachinePreset | null; } // ── Small pill switch sized for the canvas toolbar ──────────────────────────── function CanvasSwitch({ checked, onCheckedChange, label, title, }: { checked: boolean; onCheckedChange: (checked: boolean) => void; label: string; title?: string; }) { return (
{label} {/* Track */}
); } export default function StagePane({ design, hoop, scrubPos, onScrubChange, activeLine, lineSegments, warningLoc, hoveredLineBounds, showDensity, onToggleDensity, chalkControl, hideJumps, onToggleHideJumps, hoveredDataVar, pinnedDataVars, pointParams, pathParams, showHandles = true, onToggleHandles, highlightedHandle, lockedHandles, onHandleDrag, onHandleCommit, onPathInsert, onPathDelete, onCurveToggleSmooth, onPathTranslate, onMachineContextMenu, machine, }: Props) { // Only show the handles toggle when there are point params to show const hasHandles = (pointParams?.length ?? 0) > 0; const darkGround = colorDist(design.background, '#000000') < 0.5; return (
onToggleHideJumps()} label="jumps" title="Hide jump threads for a cleaner preview" /> {(design.chalk.length > 0 || design.dataVars.length > 0) && ( )} {hasHandles && ( onToggleHandles?.()} label="handles" title="Toggle draggable point handles" /> )}
); }