62 lines
2.7 KiB
TypeScript
62 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 { Space } from './space';
|
|
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 'space': return <Space 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);
|