forked from Tadrisino/MathApp_frontend
draw every kind of textbook figure, lock math text left-to-right, student-first family screen
- src/diagram: plane (constructed points, graphs with computed roots, vertex, extrema, tangent, asymptotes, piecewise limits, regions, rotations and reflections, line from ax + by = c), number line with intervals and stacked fractions, solids with hidden edges, bar/line/pie charts, sign tables, Venn, arrow mappings, probability trees, fraction bars and mixed numbers, grids, groups, clock. Pure-math text is bidi-overridden: Persian digits used to turn 3 × 4 = 12 into 12 = 4 × 3 even with dir=ltr. - MathText locks math runs inside Persian sentences in chat bubbles and figure captions, so -1 no longer shows as 1-. - Family screen: a student sees only the invite-code form; the parent form is behind a link. - Dev-only diagram gallery at ?gallery (not in the production build). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
58
src/diagram/index.tsx
Normal file
58
src/diagram/index.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
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, 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} />;
|
||||
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);
|
||||
Reference in New Issue
Block a user