Registry reference
A quick catalog of the components and functions Banto ships with.
This doc is hand-curated (categories + tightened descriptions) but
drift-checked against the canonical registries in
packages/core/src/registries/ by npm run docs:check — every item in
those JSON files must appear here and vice versa. When in doubt, the JSON
files are the source of truth.
Contents
Components: cpnt.X
Used inside host/plyr/cpnt blocks anywhere a child (or
nested element) is expected. Pass an object whose fields match the
component’s params. Optional fields are marked ? and may be
omitted.
Layout & screens
| Component | Params | What it is |
|---|---|---|
HostLobby | { onStart: action, roomCode: string, playerButtons: { name: string, sessionId: string, onClick: action(string) }[] } | The default host lobby. Purple background, room code, player list with kick buttons. |
PlayerScreen | { name: string, score: number, roomCode: string, child: element } | Wrapper for player views — shows the player’s name, score, and room code along with the inner child. |
HostScreen | { roomCode: string, onSkip: action, sideBar: { label: string, child: element }[], child: element } | Wrapper for host views — main area + side bar. Default white background. |
container | { child?: element, class: style } | A styleable wrapper. The Banto equivalent of <div>. Omit child for a purely decorative element. |
Icon | { id: string, class?: style } | A lucide icon rendered by name. id accepts a kebab-case id (alarm-clock) or PascalCase name (AlarmClock); an unknown name renders nothing. Style the SVG via class (size with w-8 h-8, color with text-*). |
conditional | { when: boolean, child: element }[] | Renders the first entry whose when is true. Useful for picking a child based on data. |
portal | { child: element } | Renders child into a React portal on document.body, so it escapes parent layout / overflow / stacking context. Use for overlays (toasts, modals, floating menus). |
modal | { isOpen: boolean, onClose: action, child: element } | A full-screen dimmed overlay centering child while isOpen is true. Clicking the backdrop (outside child) fires onClose. The child owns its styling; the modal only supplies the centered, dimmed overlay. |
cursorLayer | { cursors: { id: string, x: number, y: number, color: string }[], onMove: action({ x: number, y: number }) } | A full-bleed overlay rendering one colored cursor per cursors entry and reporting this client’s pointer movement via onMove. Positions are percentages (0–100) of the layer’s box, so cursors stay aligned across differently-sized viewports. Drive shared-cursor experiences by writing each onMove into var.* keyed by session id. |
Buttons & inputs
| Component | Params | What it is |
|---|---|---|
button | { child: element, onClick: action, class: style, keyboardNav?: boolean } | A clickable element. keyboardNav defaults to true; set to false to opt out of keyboard focus (renders tabIndex={-1} and suppresses focus-on-mousedown). |
textInput | { value: string, onChange?: action(string), onSubmit?: action(string), hint?: string, maxLength?: number, class?: style } | Single-line text input. Bind value to a cstate.<name> so typing stays local. |
numberInput | { value: number, onChange?: action(number), onSubmit?: action(number), hint?: string, min?: number, max?: number, step?: number, class?: style } | Single-line numeric input. Empty input delivers 0. |
textArea | { value: string, onChange?: action(string), onSubmit?: action(string), hint?: string, maxLength?: number, rows?: number, class?: style } | Multi-line text input. onSubmit fires on Ctrl/Cmd+Enter; Enter alone inserts a newline. |
select | { value: string, options: { label: string, value: string }[], onChange?: action(string), placeholder?: string, class?: style } | Dropdown. |
checkbox | { checked: boolean, label?: string, onChange?: action(boolean), class?: style } | Single boolean checkbox. |
checkboxGroup | { values: string[], options: { label: string, value: string }[], onChange?: action(string[]), class?: style } | Multi-select checkboxes. onChange receives the full new selection list. |
radioGroup | { value: string, options: { label: string, value: string }[], onChange?: action(string), class?: style } | Single-select radios. |
slider | { value: number, min: number, max: number, step?: number, onChange?: action(number), onSubmit?: action(number), class?: style } | Range slider. onChange ticks during drag; onSubmit fires on release. |
keyboard | { value: string, onChange?: action(string), onSubmit?: action(string), maxLength?: number, showNumbers?: boolean, showSpace?: boolean } | Bottom-pinned QWERTY keyboard. A–Z plus ENTER (bottom-left) and backspace (bottom-right); optional 0–9 row when showNumbers is true; optional spacebar row when showSpace is true (also enables physical space key). Doesn’t render the value itself — bind value to a cstate.<name>. onChange fires on every key with the new full string; onSubmit fires on ENTER. Caps at ~30% viewport width on desktop, full width on mobile. |
Drawing
| Component | Params | What it is |
|---|---|---|
Canvas | `{ mode: “draw" | "view”, value: { lines: { points: number[], color: string, width: number }[], bg: string, w: number, h: number }, onChange?: action({ lines: { points: number[], color: string, width: number }[], bg: string, w: number, h: number }), colors?: string[], class?: style }` |
Media (custom assets)
Render your own uploaded images and audio. src takes an asst.<name>
reference (build-validated to the right kind) or a raw asset id / URL string.
See Custom image & audio assets
for the upload flow (banto assets push).
| Component | Params | What it is |
|---|---|---|
image | `{ src: image, alt?: string, fit?: “cover" | "contain”, class?: style }` |
audio | { src: audio, autoplay?: boolean, loop?: boolean, controls?: boolean, class?: style } | Plays a custom audio asset. Set controls to show a native player; omit it for background/ambient audio driven by autoplay/loop. For a one-shot sound cue fired from an action, use client.playSound(asst.<name>) instead. |
Animation
| Component | Params | What it is |
|---|---|---|
AnimatedComponent | `{ child: element, class: style, onStart?: action, onComplete?: action, delay: number, transition: { type?: “spring" | "tween”, stiffness?: number, damping?: number, duration?: number }, animate: { scale?: number, rotate?: number, opacity?: number, x?: number, y?: number }, initial: { scale?: number, rotate?: number, opacity?: number, x?: number, y?: number } }` |
Heads up. Components, params, and slot types evolve. The registry JSON in
packages/core/src/registries/components.jsonis the authoritative list. If something here looks stale, that file wins.
Server functions: func.X
Run on the server. Use as expressions everywhere except where noted
(returns: action functions can also be statements in an action
body; returns: void functions are statement-only).
Time & RNG
| Call | Returns | Notes |
|---|---|---|
func.currentTime() | number | Milliseconds since Unix epoch. |
func.randomInt({min, max}) | number | Random int in [min, max]. Bounds swap if reversed; non-integer bounds are floored. |
func.randomFloat({min, max}) | number | Random float in [min, max). |
func.shuffle(arr) | any[] | Non-mutating; returns the array in random order. Works on any element type. |
func.shuffleStrings(arr) | string[] | Deprecated — prefer func.shuffle. |
func.pickRandom(arr) | any | One random element. Returns undefined for an empty list. |
func.pickUnused({total, used}) | number | Random int in [0, total) not in used. Returns -1 if all used. |
func.range({start, end, step?}) | number[] | Inclusive of start, exclusive of end. step defaults to 1; negative counts down. |
Math
| Call | Returns | Notes |
|---|---|---|
func.floor(n) | number | Equivalent to Math.floor. |
func.ceil(n) | number | Equivalent to Math.ceil. |
func.round(n) | number | Half-up. Equivalent to Math.round. |
func.abs(n) | number | Absolute value. |
func.clamp({value, min, max}) | number | Constrain to [min, max]. Bounds swap if reversed. |
func.sum(arr) | number | Empty → 0. |
func.avg(arr) | number | Empty → 0 (not NaN, so it renders cleanly). |
func.minOf(arr) | number | Empty → 0. |
func.maxOf(arr) | number | Empty → 0. |
func.toInt(value) | number | Coerces to int; -1 on failure. |
Strings
| Call | Returns | Notes |
|---|---|---|
func.isAlpha(s) | boolean | True for non-empty ASCII letter strings (A–Z, a–z). Empty / mixed → false. |
func.isNumeric(s) | boolean | True for non-empty ASCII digit strings (0–9). No signs, decimals, or whitespace. Pair with func.toInt for the value. |
Collections
| Call | Returns | Notes |
|---|---|---|
func.size(obj) | number | Sugar over Object.keys(obj).length. |
func.isEmpty(any) | boolean | True for null, undefined, "", [], {}. |
func.hasKey({obj, key}) | boolean | True if obj has its own property key. |
func.first(arr) | any | First element or undefined. |
func.last(arr) | any | Last element or undefined. |
func.unique(arr) | any[] | First-occurrence dedup, === equality (no deep dedup). |
func.setHas({items, value}) | boolean | Set-backed membership check. Builds a Set from items then checks value; O(1) lookup, cheaper than items.includes(value) for large lists. === equality. |
func.equals({a, b}) | boolean | Deep structural equality. |
func.merge({a, b}) | object | Shallow {...a, ...b}. Non-mutating. |
func.removeKey({obj, key}) | object | Copy of obj without key. Non-mutating. The cleanest way to drop an entry from a record. |
func.mapValues({obj, key}) | object | Project a property out of every value: {[k]: obj[k][key]}. |
func.groupBy({items, key}) | object | Group items into a record keyed by item[key]. Missing keys grouped under "". |
func.fill({value, n}) | any[] | Length-n array where every entry is value. n ≤ 0 or non-integer → []. Pad a list to a fixed length: pd.guesses.concat(func.fill({value: emptyRow, n: 6})).slice(0, 6). The same reference is repeated — mutating one entry mutates all. |
Game control & UX
| Call | Returns | Notes |
|---|---|---|
func.kickPlayer(sessionId) | action | Disconnects the player and removes them from var.players. Statement-callable from action bodies. |
func.notify({to, message, type?}) | void | Pop a toast. to ∈ `“host" |
func.log({message, level?}) | void | Write to the server log. level defaults to "info". Handy for debugging your game’s server logic. |
About the canonical list.
packages/core/src/registries/functions.jsonis the single source of truth. New functions are added there.
Client functions: client.X
Run on the player’s browser. Restrictions:
- May only appear inside an action arrow body (an
onClick,onChange,onSubmit, etc.). - May not appear inside an iterator body (
.map,.forEach, …). - Always returns
void; can’t be used as an expression.
| Call | Argument |
|---|---|
client.playSound(sound) | A built-in cue name — "tick", "ding", "whoosh", "chching", "applause", "countdown", "anticipation", "waiting" — or an audio asset (asst.<name>) to play a custom clip. |
The compiler optimizes statically-known calls (e.g., a literal cue name
or a single asst.<name>) so they fire instantly on click without a
server round-trip. Calls with non-literal arguments still work — they
just dispatch via the server.
Object built-ins
Object.X(...) works the way you expect from JavaScript:
| Call | Returns | Notes |
|---|---|---|
Object.keys(obj) | string[] | The object’s own keys. |
Object.values(obj) | T[] | The object’s own values. |
Object.entries(obj) | [string, T][] | Tuples. The standard input to .map(([key, value]) => ...). |
Object.fromEntries(arr) | object | Inverse of Object.entries. |
These are the only Object.* calls Banto recognizes. Anything else
(Object.assign, Object.freeze, etc.) is a compile error.