@bsol-oss/mathdiagram
v0.1.0
Published
React SVG renderer for declarative exam-style math and geometry diagrams.
Keywords
Readme
MathDiagram
MathDiagram is a React SVG diagram renderer for student-friendly math and geometry diagrams. It is built for plain Vite/React projects and uses local SVG rendering only: no hosted embeds, no Three.js, no Babylon.js, and no commercial diagram platform.
The core idea is simple: pass a JSON-friendly spec object to <MathDiagram />, and the renderer draws the matching 2D or 3D exam-style diagram.
Quick Start
Install and run this repo:
npm install
npm run devOpen the demo app and go to #/mathdiagram/3d-solids to see the live editable MathDiagram examples.
Use In React
Install the package:
npm install @bsol-oss/mathdiagramImport the component and stylesheet in any React/Vite app:
import { MathDiagram } from '@bsol-oss/mathdiagram';
import '@bsol-oss/mathdiagram/style.css';
export function Example() {
return <MathDiagram spec={{
kind: 'volume',
shape: 'rectangular_prism',
color: 'green',
arrowColor: 'auto',
canvas: {
width: 420,
height: 270,
fit: 'contain',
padding: 32
},
dimensions: {
length: 4,
width: 3,
height: 2,
unit: 'cm'
},
view: {
azimuth: 45,
elevation: 30
},
header: {
text: 'V = l x w x h',
position: 'left-upper'
}
}} />;
}The current repo also keeps the library source in src/diagrams for local development. If you do not want to use npm yet, copy that folder into another React project and import ./diagrams/MathDiagram.jsx directly.
You can also render from JSON:
const spec = JSON.parse(jsonText);
<MathDiagram spec={spec} />Component API
MathDiagram currently accepts one prop:
| Prop | Type | Description |
| --- | --- | --- |
| spec | object | Declarative diagram configuration. Must include shape. |
If the spec is invalid, the component renders a visible validation error instead of throwing.
Spec Model
Common top-level keys:
| Key | Type | Description |
| --- | --- | --- |
| shape | string | Diagram renderer to use, such as rectangle, cube, or triangular_prism. |
| kind | string | Optional teaching context, usually volume. Net diagrams are not supported. |
| dimensions | object | Numeric dimensions and unit. These drive labels and proportional geometry. |
| layoutDimensions | object | Numeric fallback dimensions for unknown values like height: '?'. |
| unknowns | string[] | Dimension keys to display as unknowns. |
| measurements | array | Optional list of dimension arrows/labels to show. |
| canvas | object | SVG output size and scaling behavior. |
| view | object/string | 3D viewing angle for supported 3D shapes. |
| color | string | Per-shape color name. |
| arrowColor | string | auto or a supported color name for dimension arrows. |
| header | object | Annotation badge with text and named position. |
| remarks | object | Secondary annotation badge with text and named position. |
| labels | array | Extra annotation badges. |
| alt | string | Accessible label for the SVG. |
Canvas Sizing
Use canvas.width and canvas.height to specify the rendered SVG size. The default fit: 'contain' scales the internal diagram coordinate system into that canvas.
canvas: {
width: 420,
height: 270,
fit: 'contain',
padding: 32
}Use viewBoxWidth and viewBoxHeight only when you need a custom SVG coordinate space:
canvas: {
width: 520,
height: 300,
viewBoxWidth: 520,
viewBoxHeight: 300,
padding: 36
}Supported Shapes
2D shapes:
rectanglesquaretriangleright_trianglecircletrapezoidparallelogramregular_polygoncomposite_2d
3D solids:
rectangular_prismcubecylinderconesquare_pyramidrectangular_pyramidtriangular_prismspherehemispherecapsuletriangular_pyramidfrustum_conefrustum_pyramidcomposite_3d
Legacy shape: 'composite' is still routed to the 3D composite renderer, but new specs should use composite_3d.
Dimension Names
Preferred public dimension keys:
| Shape | Dimensions |
| --- | --- |
| rectangle | length, width, unit |
| square | side, unit |
| triangle | base, height, topOffset, unit |
| right_triangle | base, height, hypotenuse, unit |
| circle | radius, unit |
| trapezoid | bottomBase, topBase, height, unit |
| parallelogram | base, height, side, unit |
| regular_polygon | sides, side, unit |
| rectangular_prism | length, width, height, unit |
| cube | side, unit |
| cylinder | radius, height, unit |
| cone | radius, height, slantHeight, unit |
| square_pyramid | baseSide, height, unit |
| rectangular_pyramid | length, width, height, unit |
| triangular_prism | base, triangleHeight, length, unit |
| triangular_pyramid | base, baseHeight, height, unit |
| frustum_cone | topRadius, bottomRadius, height, unit |
| frustum_pyramid | topLength, topWidth, bottomLength, bottomWidth, height, unit |
topOffset means the horizontal distance from the left base endpoint to the vertical foot of the triangle's top vertex. If omitted, the triangle defaults to an isosceles layout with topOffset = base / 2.
Older aliases such as apexX, legA, legB, baseA, baseB, and sideLength are kept internally for compatibility, but new JSON should use the clearer names above.
Measurements And Unknowns
By default, renderers show their standard measurements. You can restrict or relabel them with measurements:
measurements: [
{ target: 'base' },
{ target: 'height', label: 'h = ?' }
]For exam questions with unknown values, put the visible value in dimensions, provide a numeric fallback in layoutDimensions, and list the unknown key in unknowns:
{
shape: 'triangle',
dimensions: { base: 8, height: '?', topOffset: 3, unit: 'cm' },
layoutDimensions: { height: 5 },
unknowns: ['height'],
measurements: [
{ target: 'base' },
{ target: 'height', label: 'h = ?' }
]
}Annotations
Use header, remarks, and labels for diagram text. They use named positions instead of exact coordinates.
header: { text: 'A = 1/2 bh', position: 'left-upper' },
remarks: { text: 'Find h', position: 'right-lower' },
labels: [{ text: 'radius shown', position: 'right-lower' }]Supported positions:
left-uppercenter-upperright-upperleft-middlecenter-middleright-middleleft-lowercenter-lowerright-lower
Colors
Use one color per shape. Composite diagrams can set color per part.
Supported color names:
blueskycyangreenlimeyelloworangeredpinkpurpleslateneutral
Use arrowColor: 'auto' for contrast-friendly dimension arrows, or override it with one of the supported color names.
3D Viewing Angle
Supported 3D renderers accept either a preset string or an angle object:
view: { azimuth: 45, elevation: 30 }Presets:
isometrictextbookfrontrighttopleftright_downleft_down
Composite Examples
2D additive composite:
{
shape: 'composite_2d',
operation: 'add',
parts: [
{ shape: 'rectangle', color: 'blue', dimensions: { length: 8, width: 4, unit: 'cm' }, position: { x: 0, y: 0 } },
{ shape: 'rectangle', color: 'orange', dimensions: { length: 3, width: 5, unit: 'cm' }, position: { x: 0, y: 4 } }
]
}3D additive composite:
{
shape: 'composite_3d',
operation: 'add',
view: { azimuth: 45, elevation: 30 },
canvas: { width: 520, height: 300 },
parts: [
{ id: 'A', shape: 'rectangular_prism', color: 'blue', dimensions: { length: 8, width: 4, height: 2, unit: 'cm' }, position: { x: 0, y: 0, z: 0 } },
{ id: 'B', shape: 'rectangular_prism', color: 'orange', dimensions: { length: 3, width: 4, height: 5, unit: 'cm' }, position: { x: 5, y: 0, z: 2 } }
]
}Validation
Run a production build:
npm run buildThe current app also includes live JSON editors on the MathDiagram page so you can test each supported shape interactively.
