Skip to content

Components

Every <notatio-*> custom element, with its attributes, types and defaults read straight out of the source at build time — so these tables cannot drift from the code.

The components are plain custom elements built on Lit. They need no framework: import @enumeratio/notatio for the side effect and use the tags in any HTML. The playground shows each one working; this reference is for reading the dials.

Expression attributes take notatio

An attribute that holds an expression — value, expr, u/v — is written in notatio, the restricted-Epsil subset: Sin(x) * Cos(y), with products spelled out (x y is a parse error, though 3x is not). LaTeX is read only inside a $…$ island: value="$x\sin(x)$".

That includes the editable components: a <notatio-cell>'s value and a <notatio-notebook>'s or <notatio-worksheet>'s seed are notatio, converted to LaTeX only for the MathLive field that edits them; in-form="latex" hands the field LaTeX as written. A seed may bind with := — a cell is notatio plus one binding.

Two components keep LaTeX as their own form. <notatio-in> is the math field, so its value is the field's LaTeX. <notatio-out> renders an encoding it is handed rather than input someone authored, so it keeps a format attribute naming the encoding — latex (the default), mathjson or notatio. The formats reference covers those.

A value that fails to parse renders nothing at all, silently. To find out why, name the component's namespace and reload:

js
localStorage["notatio:debug"] = "plot3d"; // or "plot*", or "*"

The components

  • <notatio-animator>Wolfram's Animator: a <notatio-slider> that plays. The play button and the readout are on by default and the sweep cycles unless told otherwise -- an animator's job is to run, not to stop at the end. Hold the button for the speed and loop.12 attributes
  • <notatio-bar-chart-3d>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }10 attributes
  • <notatio-cell>a notebook-style In/Out pair: an editable input over a live read-only <notatio-out> of the result. Renders in light DOM so the nested output inherits the page's MathLive styles.5 attributes
  • <notatio-chart>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }5 attributes
  • <notatio-checkbox>a box that is ticked or not, Wolfram's Checkbox. The binding _on is True or False; value="True" starts it ticked. Put the words beside it in the prose -- the box is the control, the sentence is the label -- or give it a label of its own.3 attributes
  • <notatio-clock>play, pause and scrub the page's shared clock.5 attributes
  • <notatio-code>a small code box for source in a named language (wolfram, python, javascript, latex, json, glsl, …). Read-only by default (a <pre>), or an editable <textarea> that emits notatio-code-change with { value }. Syntax highlighting is a planned enhancement -- #render is the single seam where a highlighter would turn the value into markup.5 attributes
  • <notatio-collection-table>As authored: Descents, or Max(_) - Min(_). */ readonly source: string; readonly label: string; /** The expression over _, or undefined when it did not parse. */ readonly json: MathJsonExpression | undefined; readonly error: string; }13 attributes
  • <notatio-color-slider>#rrggbb -> [r, g, b] in 0..1. */ export function rgbOf(hex: string): [number, number, number] | undefined { const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim()); if (!m) return undefined; const n = Number.parseInt(m[1], 16); return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255]; }2 attributes
  • <notatio-column>its children one under another, Wolfram's Column.0 attributes
  • <notatio-complex-plot>domain-colouring of a complex-valued expression over the complex plane, one GPU invocation per pixel: hue is the argument, brightness a compressed log-magnitude, poles white and zeros black.7 attributes
  • <notatio-complex-plot-3d>Wolfram's ComplexPlot3D: |f(z)| as a surface over the complex plane, each face coloured by arg f(z) on the same hue wheel <notatio-complex-plot> paints. A pole is a spike that rises to max-height with every hue winding round it; a zero is a dimple the hues wind round the other way.11 attributes
  • <notatio-contour-plot>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }13 attributes
  • <notatio-curve-3d>a curve in space, from an expression that evaluates to a list of points.10 attributes
  • <notatio-density-plot>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }13 attributes
  • <notatio-dynamic>a derived readout in running prose, after Wolfram's Dynamic. It typesets whatever its value evaluates to and nothing else: no editor, no assertion, no In/Out row.3 attributes
  • <notatio-figure>Parse a MathJSON-ish integer list from an attribute: [3,1,2] or 3,1,2. */ function parseList(value: string): number[] { const text = value.trim(); if (!text) return []; try { const parsed = JSON.parse(text.startsWith("[") ? text : [${text}]); if (Array.isArray(parsed)) return parsed.map(Number).filter((x) => Number.isFinite(x)); } catch { // fall through to an empty glyph rather than throwing in render } return []; }4 attributes
  • <notatio-graph-plot>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }4 attributes
  • <notatio-grid>its children in rows of columns, Wolfram's Grid. Grid([[a, b], [c, d]]) draws as one of these with the cells in reading order.1 attributes
  • <notatio-in>The subset of MathLive's <math-field> this element drives. */ interface MathField extends HTMLElement { value: string; readOnly: boolean; /** MathLive's current selection, and a reader for the LaTeX inside it. */ selection?: unknown; getValue?: (range?: unknown, format?: string) => string; /** MathLive's fill-in-the-blank API: the content of a \placeholder[id]{}. */ getPromptValue?: (id: string, format?: string) => string; }13 attributes
  • <notatio-input-field>a field you type a value into, Wolfram's InputField. The text is notatio, parsed when you press Enter or leave the field, and the binding _x is the expression it parses to: a number, a symbol, Sin(t), whatever was typed. Text that does not parse leaves the binding where it was and marks the field. type="number" accepts only a number, and size is the width in characters.4 attributes
  • <notatio-interval-slider>a track with two thumbs, Wolfram's IntervalSlider. The binding _r is the List [lo, hi]; the thumbs cannot cross. Each thumb takes the arrows in a knob's gears; readout shows the interval beside the track.6 attributes
  • <notatio-knob>Two taps this close together mean "let me type it". */ const DOUBLE_TAP_MS = 400;14 attributes
  • <notatio-labeled>its children with a label beside them, Wolfram's Labeled. position puts the label after (default), before, above or below. Inside a choice list an entry Labeled(2, "two") shows the label and binds the value.2 attributes
  • <notatio-list-picker>a list in view, with any number of entries selected: Wolfram's ListPicker. Click toggles an entry; arrows move, Space toggles. The binding _s is the List of selected values in list order. single allows one selection only (Wolfram's Multiselection -> False), and then binds the value itself. rows is how many entries show before scrolling.5 attributes
  • <notatio-list-plot-3d>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }12 attributes
  • <notatio-locator><notatio-locator name="p" value="1,0.5"> inside a <notatio-plot> -- a point ON the picture that you drag about it, Wolfram's Locator. It sits over the plot area in the plot's own coordinates, so the binding _p is the List [x, y] where the dot is (or the complex x + y i, with complex), and a template that reads _p gets a point on the curve's axes. The arrows nudge it by a hundredth of the window, Shift ten times that, Alt a tenth.3 attributes
  • <notatio-manipulate>a generic Wolfram-style Manipulate: it renders a slider (or setter) per parameter and re-binds those parameters into its slotted content live. Any descendant attribute that is a notatio expression containing a named wildcard (_a) is treated as a template: the wildcard is compute-engine's slot notation, filled from the control a and re-evaluated on every change. So the same wrapper drives a plot, a glyph, several elements at once, or plain markup:5 attributes
  • <notatio-notebook>a notebook that sits on top of <notatio-in> and owns the session: it evaluates every cell in its own compute-engine *scope* (a child of the shared engine's root, so bindings never leak to other notebooks or the reference pages), tracks dependencies between cells, and re-evaluates live.2 attributes
  • <notatio-out>What TreeForm can know about a head, from the page's resolveHead. */ export interface HeadInfo { /** Where the head is documented. */ href?: string; /** Its defining expression, over _-prefixed wildcards, if it has a reference one. */ definition?: MathJsonExpression; /** The wildcards, in parameter order. Defaults to first appearance in definition. */ params?: readonly string[]; /** Why it does not reduce further, when it sits on the primitive frontier. */ primitive?: string; }12 attributes
  • <notatio-panel>its children in a framed box, Wolfram's Panel.0 attributes
  • <notatio-plot>a 2-D line plot of a univariate expression. value is notatio (the restricted-Epsil subset) by default, and accepts LaTeX inside a $…$ island. Samples the expression across domain by substituting var (defaults to the sole free variable) and taking the numeric value. compute-engine is loaded on demand.22 attributes
  • <notatio-plot-3d>a surface plot of a bivariate expression, projected to SVG. value is notatio; LaTeX is accepted inside a $…$ island. Samples an n×n grid by substituting the two free variables (defaulting to the first two unknowns) and drawing the height field. compute-engine loads on demand. The view is interactive: drag rotates (azimuth / elevation), and ctrl/⌘ + wheel (or a pinch) zooms. Sampling happens once per expression; a view change only re-projects the cached grid.19 attributes
  • <notatio-polar-plot>Parse a JSON attribute defensively -- an empty/invalid value reads as undefined. */ function parseJson(value: string): unknown { const text = value.trim(); if (!text) return undefined; try { return JSON.parse(text); } catch { return undefined; } }11 attributes
  • <notatio-polytope>a polytope's face poset, drawn, draggable and clickable.13 attributes
  • <notatio-popup-menu>the selected entry, and a menu of the rest when clicked: Wolfram's PopupMenu. Arrows step it without opening. Entries are |-separated and may be value -> label. The binding is the entry's value.3 attributes
  • <notatio-radio-button-bar>Wolfram's RadioButtonBar: a <notatio-setter-bar> whose entries are radio buttons, one of which is on. The entries, the arrows and the binding are the setter bar's.3 attributes
  • <notatio-row>its children side by side, Wolfram's Row. Nothing of its own: put controls, readouts and pictures inside and they sit in a line, which is how an expression Row([Slider(k, (0, 5)), Dynamic(k^2)]) draws.0 attributes
  • <notatio-setter-bar>a row of buttons of which one is down, Wolfram's SetterBar. Click one to set it; arrows move the selection along the bar. Entries are |-separated and may be value -> label; a value that looks like mathematics is typeset. Inside a scope the binding _k is the entry's value (a number, a named value) or its index for a bare word.3 attributes
  • <notatio-slider>a track with a thumb, Wolfram's Slider. Drag the thumb or click the track to set it; the arrows step it, accelerating when held, Shift or PageUp/PageDown step coarse and Alt fine (the same gears as a <notatio-knob>), Home/End go to the ends. readout shows the value beside the track; axis="y" stands it up (Wolfram's VerticalSlider, which is also <notatio-vertical-slider>).12 attributes
  • <notatio-slider-2d>a,b -> [a, b]; a single number -> [n, n]; nothing -> undefined. */ function pair(raw: string | number | undefined): [number, number] | undefined { if (raw === undefined) return undefined; const parts = String(raw) .split(",") .map((s) => Number(s.trim().replace(/_/g, ""))); if (parts.length === 1 && Number.isFinite(parts[0])) return [parts[0], parts[0]]; if (parts.length === 2 && parts.every(Number.isFinite)) return [parts[0], parts[1]]; return undefined; }8 attributes
  • <notatio-tangle>a reactive document, after Bret Victor's [Tangle](http://worrydream.com/Tangle/): prose whose numbers you can grab, and whose other numbers follow.1 attributes
  • <notatio-terminal>The behaviour that differs between the REPL and command-line modes. */ interface Engine { banner(): string; prompt(): string; run(input: string): { text: string; graphic?: Graphic; clear?: boolean; exit?: boolean }; groups(): Group[]; }3 attributes
  • <notatio-toggler>a word in the prose that cycles when you click it, Wolfram's Toggler and Tangle's toggle in one.8 attributes
  • <notatio-toggler-bar>a row of buttons of which any number are down, Wolfram's TogglerBar. Click one to toggle it; the binding _s is the List of the selected entries' values, in bar order, so Length(_s) and Sum(_s) mean what they say. Entries are |-separated and may be value -> label; value names the entries down at first, |-separated.3 attributes
  • <notatio-torus-square>the torus as a square with its opposite edges glued, and the torus knot T(p, q) on it as a straight line of slope q/p.6 attributes
  • <notatio-vector-plot>Split a field attribute into its two components. Handles an optional \{...\}, {...} or (...) wrapper and only splits on a comma at brace / paren depth zero, so \{\frac{y}{2}, -x\} survives intact. / export function splitField(raw: string): [string, string] | undefined { let s = raw.trim(); const unwrap: [string, string][] = [ ["\\{", "\\}"], ["\\left(", "\\right)"], ["{", "}"], ["(", ")"], ["[", "]"], ]; for (const [open, close] of unwrap) { if (s.startsWith(open) && s.endsWith(close)) { s = s.slice(open.length, s.length - close.length).trim(); break; } } let depth = 0; for (let i = 0; i < s.length; i++) { const c = s[i]; if (c === "{" || c === "(" || c === "[") depth++; else if (c === "}" || c === ")" || c === "]") depth--; else if (c === "," && depth === 0) { const u = s.slice(0, i).trim(); const v = s.slice(i + 1).trim(); if (u && v) return [u, v]; return undefined; } } return undefined; }14 attributes
  • <notatio-vertical-slider>Wolfram's VerticalSlider: a <notatio-slider> standing up, with up/down as its arrows. Everything else -- range, gears, readout, play, loop -- is the slider's.12 attributes
  • <notatio-when>a run of prose that appears only while its condition holds, Tangle's conditional sentence.2 attributes
  • <notatio-worksheet>a set of named expressions and a shared view of what they draw.6 attributes