View API (vanilla)
The vanilla API for building custom collaborative elements. For usage with side-by-side examples, see Custom elements; for the React equivalent, see the React API.
import { playhtml, html, svg, repeat, classMap, styleMap, nothing } from "playhtml";
playhtml.register(elementId, init)
Section titled “playhtml.register(elementId, init)”Binds an initializer to one element by id and returns a handle. Callable before or after playhtml.init() and before or after the element exists in the DOM — binding happens once both are present (like customElements.define).
const handle = playhtml.register("my-counter", init);
- The element needs a stable, unique
id(it is theelementId). Thecan-playattribute is optional —registerimplies it. - Re-registering the same id replaces its initializer.
playhtml.define(capabilityName, init)
Section titled “playhtml.define(capabilityName, init)”Registers a reusable capability under an attribute name. Every element carrying [capabilityName] binds — including ones added later, or rendered by a view. The imperative counterpart of init({ extraCapabilities }).
playhtml.define("can-note", init);
Defining a name that collides with a built-in capability throws. Each bound element still needs a unique id.
playhtml.getHandle(elementId, capability?)
Section titled “playhtml.getHandle(elementId, capability?)”Returns a handle for any bound element. Because data is keyed by capability and id, pass the capability name when one element carries more than one.
const handle = playhtml.getHandle("card-1", "can-move");
The init object
Section titled “The init object”The full annotated property list is on Element API. The view argument is ctx — see Callback context.
defaultData must be an object (or a function that returns one), not a bare value like 0 or "". Use { count: 0 }, not 0.
A valid initializer provides exactly one update path — view or updateElement.
The view context
Section titled “The view context”view receives ctx (Callback context). Drive ctx.setData from @click handlers, not during render.
onMount gets getters (getData(), getElement(), …) instead of live values. See Element API → onMount for the playhtml.ready pattern.
PlayElementHandle
Section titled “PlayElementHandle”Returned by register and getHandle. Reads and writes resolve the live handler lazily — a handle obtained before binding works once the element exists.
{
id,
getElement(), // null until bound
getData(), // undefined until bound
setData(next),
setLocalData(next),
setMyAwareness(next),
requestUpdate(), // no-op without a view
unregister(), // detach + run onMount cleanup; shared data is kept
}
A write through a handle whose element hasn’t bound yet is dropped (with a dev-mode warning); reads return undefined.
Re-exported lit-html helpers
Section titled “Re-exported lit-html helpers”playhtml re-exports the lit-html pieces a view needs. unsafeHTML is intentionally not exported, so interpolated values stay auto-escaped.
| Export | Use |
|---|---|
html | the tagged template for view output |
svg | SVG fragments (e.g. <path> inside <svg>) |
repeat(items, keyFn, template) | keyed lists — key by a stable unique id |
classMap(obj) | conditional classes |
styleMap(obj) | conditional inline styles (safer than a style string) |
nothing | render nothing (or just return null / undefined) |
See the lit-html templating guide for the full template syntax.