<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; }
/** How a compute-engine type is written on the page. Everything else falls back to an upright name, which is still readable if less conventional. / const TYPE_LATEX: Record<string, string> = { integer: "\\mathbb{Z}", finite_integer: "\\mathbb{Z}", rational: "\\mathbb{Q}", finite_rational: "\\mathbb{Q}", real: "\\mathbb{R}", finite_real: "\\mathbb{R}", complex: "\\mathbb{C}", finite_complex: "\\mathbb{C}", number: "\\mathbb{C}", boolean: "\\mathbb{B}", };
const typeLatex = (type: string): string => TYPE_LATEX[type] ?? \\mathrm{${type.replace(/_/g, "\\_")}};
/** The assignment operators a bound cell may be written with. */ const ASSIGN = /\\coloneqq?|:=/;
/** Everything after the assignment operator -- the part a pinned input lets you edit. */ function valuePart(latex: string): string { const m = ASSIGN.exec(latex); return (m ? latex.slice(m.index + m[0].length) : latex).trim(); }
/** The id of the one editable hole in a pinned field. */ const PROMPT = "value";
/** <notatio-in> -- a LaTeX math field wrapping MathLive's <math-field>. Emits notatio-change with { latex } on each edit. When readonly, it renders static markup via mathlive/ssr and never loads the (heavy) editor. MathLive is lazy-loaded the first time an editable input mounts.
A control on the field writes a *wrapper head* around what the reader typed -- N(x) for a number, FullForm(x) for the AST, TraditionalForm(x) for the rendering (see WRAPPER_HEADS). The head lands in the emitted value, not in the editor: the field keeps showing the expression as written, so the wrapper is a reversible request rather than an edit. A value handed back wrapped is unwrapped again into expression plus head, which is also how a saved one is restored.
With bind (and optionally type) the field is *pinned*: it shows a declaration like p \in \mathbb{Z} \coloneq 3 where only the value is editable. The declaration is not text the reader could delete -- it is a read-only field with one \placeholder[value]{} hole, so the caret cannot leave the value at all.
The asserted type is shown, not parsed: p \in \mathbb{Z} \coloneq 3 reads as a declaration but parses as Element(p, Assign(Integers, 3)), binding the assignment to the domain instead of to p. So value stays the plain p \coloneq 3 that everything downstream already understands, and the type travels beside it as structure. Enforcing it is a separate job, done by whoever declares the symbol.
A pinned field holding a number can play: play adds a button that sweeps the value through min..max by step (inferred from the value when not given, the way a knob's are), emitting each step as if it had been typed. loop says what the ends do -- cycle, reflect or none (the default: a range has ends) -- interval and rate set the pace, and holding the button opens the speed-and-loop panel. Typing into the field stops it.
Attributes
| Attribute | Type | Default | Notes |
|---|---|---|---|
value | string | "" | The LaTeX in the editor; changes emit notatio-change. |
readonly | boolean | false | Typeset the value without allowing edits.reflects |
input-form property inputForm | string | "" | Read-only: value as InputForm, kept in sync and reflected so a copy can read it off a cloned selection fragment. Set value, not this.reflects |
head | string | "" | The wrapper head asked for -- N, FullForm, TraditionalForm, ... (see WRAPPER_HEADS), or "" for none. The emitted value is wrapped in it while the editor keeps showing the expression as written.reflects |
bind | string | "" | Pin this field to a binding: the symbol name and its \coloneq become fixed chrome, and only the value can be edited. |
domain | string | "" | The domain asserted for bind, spelled as a compute-engine type (integer, real, complex, ...). Shown as a membership beside the name. Not type: that attribute already means "which symbol this component is" elsewhere. |
play | boolean | false | Show a play button that sweeps a pinned numeric value through its range.reflects |
loop | Loop | "" | "" | What a sweep does at the ends: cycle, reflect or none (default).reflects |
rate | number | 1 | Playback speed as a multiplier on interval.reflects |
interval | number | Number.NaN | Milliseconds per step; defaults to a whole sweep in a few seconds. |
min | number | Number.NaN | The sweep's range and step; inferred from the value when not given. |
max | number | Number.NaN | |
step | number | Number.NaN |