<web/dom>
Builders for virtual DOM trees. Apps return them from render, and server entries return them as pages.
let inherit (import <web/dom>) html svg element text; in html.div { class = "card"; } [ (html.h1 "Title") "Some text" ]
Elements#
html has a builder for each HTML element, and svg for each SVG element. element builds any other tag, like a custom element:
html.p "Hello" svg.circle { cx = 5; cy = 5; r = 5; } element "my-widget" { name = "Ada"; }
Builders take attributes, then children. Both are optional. Attributes come first, at most once, and children append each time they're applied:
html.button html.button { type = "button"; } "Save" html.button { type = "button"; } "Save" [ "!" ]
svg is separate from html because some tags are in both, like a and title. Its elements are in the SVG namespace.
Attributes#
string: set as is.number: set as its decimal string.true: set to an empty string, likedisabled.false: omitted.null: omitted.
Other types throw. On input, textarea, select, and option, value, checked, and selected set the element's properties, so they reflect what it shows.
Classes#
class takes strings, styles from <web/style>, null, or lists of those, nested to any depth.
html.div { class = [ card "p-4" (if active then "ring" else null) ]; }
Keys#
key identifies an element among its siblings, so it's patched in place rather than recreated when siblings come, go, or reorder. Keys are strings or integers, and 1 is the same key as "1". It isn't rendered.
html.ul (map (item: html.li { key = item.id; } item.text) items)
Event handlers#
on maps event names to handlers. A handler takes the event and returns an effect from <web/io>, or null to ignore it.
html.input { on.input = event: io.dispatch "typed" event.target.value; on.keydown = event: if event.key == "Escape" then io.dispatch "cancel" null else null; }
The event is a snapshot:
type, key, shiftKey, ...: the event's string, number, and boolean fields.target: the target'svalueandchecked, where it has them.preventDefault: an effect that callsevent.preventDefault().
To run preventDefault with other effects, combine them:
html.form { on.submit = event: io.all [ event.preventDefault (io.dispatch "save" null) ]; }
Children#
element: rendered.string: rendered as text, escaped.number: rendered as its decimal string.null, true, false: rendered as nothing, for conditional rendering.list: flattened, however deeply nested.function: a component, called with{ }. Writefooterforfooter { }.
Other types throw. text builds a text node from a string.