# OMD Documentation

# Visualization Components

This document covers OMD's SVG visualization components. Each component is instantiated and loaded via `loadFromJSON`, then passed to `omdDisplay` or `omdCanvas` for rendering.

    import { omdNumberLine, omdDisplay } from '@teachinglab/omd';

    const display = new omdDisplay(document.getElementById('container'));
    const line = new omdNumberLine();
    line.loadFromJSON({ min: 0, max: 10, increment: 1, dotValues: [3, 7] });
    display.load(line);

## numberLine

Renders a horizontal number line with optional dots, labels, and arrows.

Example JSON

    { "omdType": "numberLine", "min": 0, "max": 20, "increment": 2, "dotValues": [6, 14], "title": "Miles walked" }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`min` | number | Yes | — | Left bound of the number line
`max` | number | Yes | — | Right bound of the number line
`increment` | number | Yes | — | Spacing between tick marks
`dotValues` | number[] | No | `[]` | Values at which to place dots
`title` | string | No | `""` | Title text rendered above the line
`label` | string | No | `""` | Label rendered beside the line
`units` | string | No | `""` | Unit label appended to tick numbers
`showLeftArrow` | boolean | No | `false` | Show an arrow on the left end
`showRightArrow` | boolean | No | `false` | Show an arrow on the right end
`hideDefaultNumbers` | boolean | No | `false` | Hide the default tick number labels
`specialNumbers` | object[] | No | `[]` | Custom labels at specific positions: `{value, label}`
`totalWidth` | number | No | auto | Total SVG width in px

### Example

    const line = new omdNumberLine();
    line.loadFromJSON({
      min: 0,
      max: 20,
      increment: 2,
      dotValues: [6, 14],
      showRightArrow: true,
      title: 'Temperature (°C)',
      specialNumbers: [{ value: 6, label: 'low' }, { value: 14, label: 'high' }]
    });
    display.load(line);

## doubleNumberLine

Renders two aligned number lines stacked vertically, useful for ratio and rate comparisons.

Example JSON

    { "omdType": "doubleNumberLine", "topNumberLine": { "min": 0, "max": 5, "increment": 1, "title": "Hours" }, "bottomNumberLine": { "min": 0, "max": 60, "increment": 12, "title": "Minutes" } }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`topNumberLine` | object | Yes | — | Config for the top number line (same fields as `numberLine`)
`bottomNumberLine` | object | Yes | — | Config for the bottom number line
`spacing` | number | No | auto | Vertical gap in px between the two lines

### Example

    const dbl = new omdDoubleNumberLine();
    dbl.loadFromJSON({
      topNumberLine: { min: 0, max: 5, increment: 1, title: 'Hours' },
      bottomNumberLine: { min: 0, max: 60, increment: 12, title: 'Minutes' },
      spacing: 20
    });
    display.load(dbl);

## balanceHanger

Renders a balance scale hanger. Variables (e.g. `'x'`) are drawn as pill shapes; numbers as rectangles.

Example JSON

    { "omdType": "balanceHanger", "leftValues": ["x", "x", "x"], "rightValues": ["1", "1", "1", "1", "1", "1"], "tilt": "none" }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`leftValues` | string[] | Yes | — | Tokens on the left side, e.g. `['x', 'x', '3']`
`rightValues` | string[] | Yes | — | Tokens on the right side
`tilt` | `'none'`|`'left'`|`'right'` | No | `'none'` | Direction the beam tilts
`fontFamily` | string | No | system | Font for tile labels
`fontSize` | number | No | auto | Font size in px
`backgroundColor` | string | No | `""` | Background fill color
`backgroundCornerRadius` | number | No | `0` | Corner radius of the background rect
`backgroundOpacity` | number | No | `1` | Opacity of the background rect
`showBackground` | boolean | No | `false` | Whether to render a background rect

### Example

    const hanger = new omdBalanceHanger();
    hanger.loadFromJSON({
      leftValues: ['x', 'x', 'x'],
      rightValues: ['1', '1', '1', '1', '1', '1'],
      tilt: 'none'
    });
    display.load(hanger);

## tapeDiagram

Renders a horizontal segmented tape diagram. Each segment can be a plain value or a full object controlling color, label, and weight.

Example JSON

    { "omdType": "tapeDiagram", "title": "Parts of 24", "values": [{ "value": 8, "color": "#4A90D9", "label": "A" }, { "value": 8, "color": "#7ED321", "label": "B" }, { "value": 8, "color": "#F5A623", "label": "C" }], "labelSet": { "braces": [{ "startIndex": 0, "endIndex": 2, "label": "24", "showBelow": true }] } }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`values` | array | Yes | — | Segments. Each entry is a string/number or `{value, weight, showLabel, color, textColor, label}`
`totalWidth` | number | No | auto | Total width of the tape in px
`title` | string | No | `""` | Title above the tape
`titleFontSize` | number | No | auto | Font size for the title
`titleColor` | string | No | `""` | Color for the title text
`segmentHeight` | number | No | auto | Height of each segment in px
`segmentCornerRadius` | number | No | `0` | Corner radius of segments
`segmentStrokeColor` | string | No | `""` | Stroke color for segment borders
`segmentStrokeWidth` | number | No | `1` | Stroke width for segment borders
`labelFontSize` | number | No | auto | Font size for segment labels
`segmentTextColor` | string | No | `""` | Default text color for segment labels
`braceLabelFontSize` | number | No | auto | Font size for brace labels
`braceColor` | string | No | `""` | Color for brace strokes
`labelSet` | object | No | `{}` | Brace annotations: `{ braces: [{startIndex, endIndex, label, showBelow, color, fontSize, strokeWidth}] }`

### Example

    const tape = new omdTapeDiagram();
    tape.loadFromJSON({
      title: 'Parts of 24',
      values: [
        { value: 8, color: '#4A90D9', label: 'A' },
        { value: 8, color: '#7ED321', label: 'B' },
        { value: 8, color: '#F5A623', label: 'C' }
      ],
      labelSet: {
        braces: [{ startIndex: 0, endIndex: 2, label: '24', showBelow: true }]
      }
    });
    display.load(tape);

## doubleTapeDiagram

Renders two tape diagrams stacked vertically, useful for part-to-part or part-to-whole comparisons.

Example JSON

    { "omdType": "doubleTapeDiagram", "topTapeDiagram": { "values": [{ "value": 3, "color": "#4A90D9" }, { "value": 3, "color": "#4A90D9" }, { "value": 3, "color": "#4A90D9" }], "title": "Miles" }, "bottomTapeDiagram": { "values": [{ "value": 15, "color": "#F5A623" }], "title": "Total" } }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`topTapeDiagram` | object | Yes | — | Config for the top tape (same fields as `tapeDiagram`)
`bottomTapeDiagram` | object | Yes | — | Config for the bottom tape
`spacing` | number | No | auto | Vertical gap in px between the two tapes

### Example

    const dbl = new omdDoubleTapeDiagram();
    dbl.loadFromJSON({
      topTapeDiagram: {
        values: [{ value: 3, color: '#4A90D9' }, { value: 3, color: '#4A90D9' }, { value: 3, color: '#4A90D9' }],
        title: 'Miles'
      },
      bottomTapeDiagram: {
        values: [{ value: 15, color: '#F5A623' }],
        title: 'Total'
      },
      spacing: 16
    });
    display.load(dbl);

## coordinatePlane

Renders a Cartesian coordinate plane. Supports graphing equations, line segments, points, and interactive sliders.

Example JSON

    { "omdType": "coordinatePlane", "xMin": -5, "xMax": 5, "yMin": -5, "yMax": 5, "graphEquations": [{ "equation": "y = 2x + 1", "color": "#E74C3C", "strokeWidth": 2 }], "dotValues": [[0, 1, "#E74C3C"]] }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`xMin` | number | Yes | — | Left bound of the x-axis
`xMax` | number | Yes | — | Right bound of the x-axis
`yMin` | number | Yes | — | Bottom bound of the y-axis
`yMax` | number | Yes | — | Top bound of the y-axis
`xLabel` | string | No | `"x"` | Label for the x-axis
`yLabel` | string | No | `"y"` | Label for the y-axis
`tickInterval` | number | No | `1` | Spacing between tick marks
`showTickLabels` | boolean | No | `true` | Show numeric tick labels
`showBackground` | boolean | No | `false` | Render a background rect
`interactive` | boolean | No | `false` | Render variable sliders when `true`
`size` | `'small'`|`'medium'`|`'large'` | No | `'medium'` | Preset size of the plane
`graphEquations` | object[] | No | `[]` | Equations to plot: `{equation, color, strokeWidth}`
`lineSegments` | object[] | No | `[]` | Segments to draw: `{point1: [x,y], point2: [x,y], color}`
`dotValues` | array[] | No | `[]` | Points to mark: each entry is `[x, y, 'color']`
`variables` | object[] | No | `[]` | Interactive slider definitions: `{name, value, min, max, step}`
`shapeSet` | object | No | `{}` | Additional shapes to overlay
`graphPadding` | number | No | auto | Internal padding around the graphing area
`backgroundColor` | string | No | `""` | Background fill color
`backgroundCornerRadius` | number | No | `0` | Corner radius of the background rect
`backgroundOpacity` | number | No | `1` | Opacity of the background rect

### Example

    const plane = new omdCoordinatePlane();
    plane.loadFromJSON({
      xMin: -5, xMax: 5,
      yMin: -5, yMax: 5,
      graphEquations: [
        { equation: 'y = 2x + 1', color: '#E74C3C', strokeWidth: 2 }
      ],
      dotValues: [[0, 1, '#E74C3C'], [2, 5, '#3498DB']],
      size: 'medium'
    });
    display.load(plane);

Interactive example (with sliders):

    plane.loadFromJSON({
      xMin: -10, xMax: 10,
      yMin: -10, yMax: 10,
      interactive: true,
      variables: [{ name: 'm', value: 1, min: -5, max: 5, step: 0.5 }],
      graphEquations: [{ equation: 'y = m*x', color: '#2ECC71' }]
    });

## tileEquation

Renders an algebra tile equation. Token values: `'x'`, `'-x'`, `'y'`, `'-y'`, `'1'`, `'-1'`.

Example JSON

    { "omdType": "tileEquation", "left": ["x", "x", "1", "1", "1"], "right": ["1", "1", "1", "1", "1", "1", "1"], "tileSize": 40 }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`equation` | string | No | `""` | Equation string parsed into tiles (e.g. `'x + 1 = -x + 3'`)
`left` | string[] | No | `[]` | Explicit left-side token array
`right` | string[] | No | `[]` | Explicit right-side token array
`tileSize` | number | No | auto | Size of each tile in px
`tileGap` | number | No | auto | Gap between tiles in px
`equalGap` | number | No | auto | Gap around the equals sign
`tileRadius` | number | No | auto | Corner radius of tiles
`showLabels` | boolean | No | `true` | Show variable/number labels on tiles
`fontFamily` | string | No | system | Font for tile labels
`fontSize` | number | No | auto | Font size for tile labels
`plusColor` | string | No | `""` | Color for positive tiles
`equalsColor` | string | No | `""` | Color for the equals sign
`xPillColor` | string | No | `""` | Color for variable pill tiles

### Example

    const tiles = new omdTileEquation();
    tiles.loadFromJSON({
      left: ['x', 'x', '1', '1', '1'],
      right: ['1', '1', '1', '1', '1', '1', '1'],
      tileSize: 40
    });
    display.load(tiles);

## table

Renders a value table. Can auto-generate rows from an equation or use manually provided data.

Example JSON

    { "omdType": "table", "equation": "y=3x+2", "xMin": 0, "xMax": 5, "stepSize": 1, "headers": ["x", "y"], "alternatingRowColors": true }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`equation` | string | No* | `""` | Equation to generate rows (e.g. `'y=2x'`). Required unless `data` is provided.
`data` | array[][] | No* | `[]` | Manual rows as `[[x, y], ...]`. Used when `equation` is not set.
`headers` | string[] | No | auto | Column header labels
`xMin` | number | No | `0` | First x value (when using `equation`)
`xMax` | number | No | `5` | Last x value (when using `equation`)
`stepSize` | number | No | `1` | Step between x values
`title` | string | No | `""` | Title above the table
`alternatingRowColors` | boolean | No | `false` | Shade alternating rows
`fontSize` | number | No | auto | Font size for cell text
`headerFontSize` | number | No | auto | Font size for header text
`fontFamily` | string | No | system | Font for cell text
`headerFontFamily` | string | No | system | Font for header text
`cellHeight` | number | No | auto | Height of data rows in px
`headerHeight` | number | No | auto | Height of the header row in px
`minCellWidth` | number | No | auto | Minimum column width in px
`maxCellWidth` | number | No | auto | Maximum column width in px
`padding` | number | No | auto | Cell padding in px
`backgroundColor` | string | No | `""` | Background fill color
`backgroundCornerRadius` | number | No | `0` | Corner radius of the background rect
`backgroundOpacity` | number | No | `1` | Opacity of the background rect
`showBackground` | boolean | No | `false` | Whether to render a background rect

* Either `equation` or `data` must be provided.

### Example

    const table = new omdTable();
    table.loadFromJSON({
      equation: 'y=3x+2',
      xMin: 0,
      xMax: 5,
      stepSize: 1,
      headers: ['x', 'y'],
      alternatingRowColors: true
    });
    display.load(table);

## ratioChart

Renders a ratio or fraction visualization in one of several styles.

Example JSON

    { "omdType": "ratioChart", "valueA": 3, "valueB": 5, "renderType": "tile", "size": "medium" }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`valueA` | number | Yes* | — | First value (or use `numerator`)
`valueB` | number | Yes* | — | Second value (or use `denominator`)
`numerator` | number | No* | — | Alias for `valueA`
`denominator` | number | No* | — | Alias for `valueB`
`renderType` | `'pie'`|`'dots'`|`'dot'`|`'tile'`|`'bar'` | No | `'pie'` | Visual style for the chart
`size` | `'small'`|`'medium'`|`'large'` | No | `'medium'` | Preset size of the visualization

* Either `valueA`/`valueB` or `numerator`/`denominator` must be provided.

### Example

    const chart = new omdRatioChart();
    chart.loadFromJSON({
      valueA: 3,
      valueB: 5,
      renderType: 'tile',
      size: 'medium'
    });
    display.load(chart);

## spinner

Renders a circular spinner divided into equal sections with an arrow.

Example JSON

    { "omdType": "spinner", "divisions": 6, "arrowPosition": 90, "size": "large" }

### Fields

Name | Type | Required | Default | Description
--- | --- | --- | --- | ---
`divisions` | number | Yes | — | Number of equal sections on the spinner
`arrowPosition` | number | No | `0` | Arrow angle in degrees (0 = top)
`size` | `'small'`|`'medium'`|`'large'` | No | `'medium'` | Preset size of the spinner

### Example

    const spinner = new omdSpinner();
    spinner.loadFromJSON({
      divisions: 6,
      arrowPosition: 90,
      size: 'large'
    });
    display.load(spinner);

↑ Top