import { Component } from 'react'; import type { ErrorInfo, ReactNode } from 'react'; import { AlertTriangle, RotateCcw } from 'lucide-react'; import { Button } from '@/components/ui/button'; const REPO_URL = 'https://git.karti.ai/PIG/PIG-Demo'; export interface DemoErrorBoundaryProps { children: ReactNode; /** Named in the fallback copy, so the visitor knows what broke. */ demoTitle?: string; /** Link to the exact source, if the caller knows it. Falls back to the repo. */ sourceHref?: string; /** Called when the visitor asks to try again; use it to reset shell state. */ onReset?: () => void; } interface DemoErrorBoundaryState { error: Error | null; } /** * One broken demo must never take the site down. * * This is a class because there is still no hook for `componentDidCatch`; that * is the entire reason for the exception to the function-component rule here. * * The fallback is deliberately calm and specific. A site whose pitch is * "here are the receipts" cannot answer a crash with a shrug: it names the * demo, links the source, and lets the visitor retry without a full reload. */ export class DemoErrorBoundary extends Component { override state: DemoErrorBoundaryState = { error: null }; static getDerivedStateFromError(error: Error): DemoErrorBoundaryState { return { error }; } override componentDidCatch(error: Error, info: ErrorInfo) { // No telemetry endpoint on a static site, and none is wanted. The console // is the only place a maintainer can see this, so keep the component stack. console.error('[pig-demo] a demo surface threw', error, info.componentStack); } private handleReset = () => { this.setState({ error: null }); this.props.onReset?.(); }; override render() { const { error } = this.state; if (!error) return this.props.children; const { demoTitle, sourceHref } = this.props; return (

Something in this demo threw while drawing. The rest of the site is unaffected — every other demo is a separate module. The environment and the recorded runs behind this page are in the repository either way, and you can run them yourself.

          {error.message || 'Unknown error'}
        
); } }