Skip to content

In ​

<In> -- a LaTeX math field wrapping MathLive's <math-field>. Emits notatio-change with { latex } on each edit, live as the reader types, and notatio-commit with the same shape when MathLive itself considers the edit committed -- its native change event, which it fires on Enter and on blur (only if the value actually changed since focus). A consumer that only cares about finished edits -- a cell inside a transcript, where Wolfram evaluates on Shift+Enter, not on every keystroke -- listens for notatio-commit instead. It shows the value typeset (KaTeX, selectable) until clicked, and only then loads MathLive's (heavy) editor; when readonly, it never does.

A reader can type a *wrapper head* around an expression -- 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 strips it from the display and 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} \coloneqq 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} \coloneqq 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 \coloneqq 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.

Demos·packages/components/src/notatio-in.ts

Props

PropTypeDefaultNotes
valuestring""The LaTeX in the editor; changes emit notatio-change.
readonlybooleanfalseTypeset the value without allowing edits.reflects
inputForm
attribute input-form
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
headstring""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
bindstring""Pin this field to a binding: the symbol name and its \coloneqq become fixed chrome, and only the value can be edited.
domainstring""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.
playbooleanfalseShow a play button that sweeps a pinned numeric value through its range.reflects
loopLoop | """"What a sweep does at the ends: cycle, reflect or none (default).reflects
ratenumber1Playback speed as a multiplier on interval.reflects
intervalnumberNumber.NaNMilliseconds per step; defaults to a whole sweep in a few seconds.
minnumberNumber.NaNThe sweep's range and step; inferred from the value when not given.
maxnumberNumber.NaN
stepnumberNumber.NaN

As a web component

Plain custom elements, no framework required: import @enumeratio/frontend for the side effect and write <notatio-in> in any HTML. Attributes are kebab-case and always strings; the props table above names each one's attribute where it differs from its prop.