Files
MathApp_frontend/src/diagram/index.tsx

60 lines
2.7 KiB
TypeScript

import { Component, memo, type ReactNode } from 'react';
import type { DiagramSpec } from './types';
import { Plane } from './plane';
import { NumberLine } from './numberline';
import { Solid } from './solid';
import { Chart } from './charts';
import { Mapping, Tree, Venn } from './sets';
import { Clock, Fraction, Grid, Groups, Pattern, Table } from './misc';
import { PAPER } from './svg';
import { MathText } from '@/lib/MathText';
export type { DiagramSpec } from './types';
/**
* شکلِ جوابِ دستیار. توصیف از بک‌اند می‌آید (rag/services/diagram.py، اعتبارسنجی‌شده)
* و اینجا فقط به عنصرِ React/SVG تبدیل می‌شود؛ هیچ HTMLی از مدل وارد صفحه نمی‌شود.
*
* هر خطایی در رسم (شکلی که کد پیش‌بینی نکرده) فقط همین شکل را پنهان می‌کند؛
* متنِ جواب سرِ جایش می‌ماند.
*/
function Body({ spec }: { spec: DiagramSpec }): ReactNode {
switch (spec.kind) {
case 'plane': return <Plane spec={spec} />;
case 'numberline': return <NumberLine spec={spec} />;
case 'solid': return <Solid spec={spec} />;
case 'bar': case 'linechart': case 'pie': return <Chart spec={spec} />;
case 'venn': return <Venn spec={spec} />;
case 'mapping': return <Mapping spec={spec} />;
case 'tree': return <Tree spec={spec} />;
case 'fraction': return <Fraction spec={spec} />;
case 'grid': return <Grid spec={spec} />;
case 'groups': return <Groups spec={spec} />;
case 'clock': return <Clock spec={spec} />;
case 'table': return <Table spec={spec} />;
case 'pattern': return <Pattern spec={spec} />;
default: return null;
}
}
class Guard extends Component<{ children: ReactNode }, { broken: boolean }> {
state = { broken: false };
static getDerivedStateFromError() { return { broken: true }; }
render() { return this.state.broken ? null : this.props.children; }
}
function DiagramBase({ spec }: { spec: DiagramSpec }) {
return (
<Guard>
{/* dir=ltr: محور و مختصات چپ‌به‌راست‌اند؛ در زمینه‌ی rtl «−۱» به «۱−» برمی‌گشت.
برچسب‌های فارسی با unicode-bidi: plaintext جهتِ خودشان را می‌گیرند. */}
<figure dir="ltr" className="mt-2 overflow-hidden rounded-2xl border border-line p-2" style={{ backgroundColor: PAPER }}>
<Body spec={spec} />
{spec.title && <figcaption dir="rtl" className="mt-1 text-center text-[11px] font-bold text-muted"><MathText text={spec.title} /></figcaption>}
</figure>
</Guard>
);
}
export const Diagram = memo(DiagramBase);