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:
localStorage["notatio:debug"] = "plot3d"; // or "plot*", or "*"The components
<notatio-animator>— Wolfram'sAnimator: 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 asundefined. */ 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 asundefined. */ 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'sCheckbox. The binding_onisTrueorFalse;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 alabelof 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 emitsnotatio-code-changewith{ value }. Syntax highlighting is a planned enhancement --#renderis the single seam where a highlighter would turn the value into markup.5 attributes<notatio-collection-table>— As authored:Descents, orMax(_) - 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'sColumn.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'sComplexPlot3D: |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 tomax-heightwith 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 asundefined. */ 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 asundefined. */ 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'sDynamic. It typesets whatever itsvalueevaluates 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]or3,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 asundefined. */ 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 ofcolumns, Wolfram'sGrid.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'sInputField. The text is notatio, parsed when you press Enter or leave the field, and the binding_xis 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, andsizeis the width in characters.4 attributes<notatio-interval-slider>— a track with two thumbs, Wolfram'sIntervalSlider. The binding_ris theList[lo, hi]; the thumbs cannot cross. Each thumb takes the arrows in a knob's gears;readoutshows 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'sLabeled.positionputs the labelafter(default),before,aboveorbelow. Inside a choice list an entryLabeled(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'sListPicker. Click toggles an entry; arrows move, Space toggles. The binding_sis theListof selected values in list order.singleallows one selection only (Wolfram'sMultiselection -> False), and then binds the value itself.rowsis how many entries show before scrolling.5 attributes<notatio-list-plot-3d>— Parse a JSON attribute defensively -- an empty/invalid value reads asundefined. */ 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'sLocator. It sits over the plot area in the plot's own coordinates, so the binding_pis theList[x, y]where the dot is (or the complexx + y i, withcomplex), and a template that reads_pgets 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-styleManipulate: 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 controlaand 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'sresolveHead. */ export interface HeadInfo { /** Where the head is documented. */ href?: string; /** Its defining expression, over_-prefixed wildcards, if it has areferenceone. */ definition?: MathJsonExpression; /** The wildcards, in parameter order. Defaults to first appearance indefinition. */ 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'sPanel.0 attributes<notatio-plot>— a 2-D line plot of a univariate expression.valueis notatio (the restricted-Epsil subset) by default, and accepts LaTeX inside a$…$island. Samples the expression acrossdomainby substitutingvar(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.valueis notatio; LaTeX is accepted inside a$…$island. Samples ann×ngrid 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 asundefined. */ 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'sPopupMenu. Arrows step it without opening. Entries are|-separated and may bevalue -> label. The binding is the entry's value.3 attributes<notatio-radio-button-bar>— Wolfram'sRadioButtonBar: 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'sRow. Nothing of its own: put controls, readouts and pictures inside and they sit in a line, which is how an expressionRow([Slider(k, (0, 5)), Dynamic(k^2)])draws.0 attributes<notatio-setter-bar>— a row of buttons of which one is down, Wolfram'sSetterBar. Click one to set it; arrows move the selection along the bar. Entries are|-separated and may bevalue -> label; a value that looks like mathematics is typeset. Inside a scope the binding_kis 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'sSlider. 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.readoutshows the value beside the track;axis="y"stands it up (Wolfram'sVerticalSlider, 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'sTogglerand Tangle's toggle in one.8 attributes<notatio-toggler-bar>— a row of buttons of which any number are down, Wolfram'sTogglerBar. Click one to toggle it; the binding_sis theListof the selected entries' values, in bar order, soLength(_s)andSum(_s)mean what they say. Entries are|-separated and may bevalue -> label;valuenames 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 afieldattribute 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'sVerticalSlider: 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