Docs Registry reference View as Markdown

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

ComponentParamsWhat 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

ComponentParamsWhat 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

ComponentParamsWhat 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 }`

3D

ComponentParamsWhat it is
Scene3D`{ grid: { [key: string]: number }, palette: { color: string, top?: string, opacity?: number, texture?: string, shape?: string }[], size?: { x: number, y: number, z: number }, entities?: { id: string, kind: string, pos: { x: number, y: number, z: number }, color?: string, sprite?: string, label?: string, scale?: number }[], camera?: { mode?: “orbit""follow"

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).

ComponentParamsWhat 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

ComponentParamsWhat 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.json is 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

CallReturnsNotes
func.currentTime()numberMilliseconds since Unix epoch.
func.randomInt({min, max})numberRandom int in [min, max]. Bounds swap if reversed; non-integer bounds are floored.
func.randomFloat({min, max})numberRandom 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)anyOne random element. Returns undefined for an empty list.
func.pickUnused({total, used})numberRandom 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

CallReturnsNotes
func.floor(n)numberEquivalent to Math.floor.
func.ceil(n)numberEquivalent to Math.ceil.
func.round(n)numberHalf-up. Equivalent to Math.round.
func.abs(n)numberAbsolute value.
func.clamp({value, min, max})numberConstrain to [min, max]. Bounds swap if reversed.
func.sum(arr)numberEmpty → 0.
func.avg(arr)numberEmpty → 0 (not NaN, so it renders cleanly).
func.minOf(arr)numberEmpty → 0.
func.maxOf(arr)numberEmpty → 0.
func.toInt(value)numberCoerces to int; -1 on failure.

Strings

CallReturnsNotes
func.isAlpha(s)booleanTrue for non-empty ASCII letter strings (A–Z, a–z). Empty / mixed → false.
func.isNumeric(s)booleanTrue for non-empty ASCII digit strings (0–9). No signs, decimals, or whitespace. Pair with func.toInt for the value.

Collections

CallReturnsNotes
func.size(obj)numberSugar over Object.keys(obj).length.
func.isEmpty(any)booleanTrue for null, undefined, "", [], {}.
func.hasKey({obj, key})booleanTrue if obj has its own property key.
func.first(arr)anyFirst element or undefined.
func.last(arr)anyLast element or undefined.
func.unique(arr)any[]First-occurrence dedup, === equality (no deep dedup).
func.setHas({items, value})booleanSet-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})booleanDeep structural equality.
func.merge({a, b})objectShallow {...a, ...b}. Non-mutating.
func.removeKey({obj, key})objectCopy of obj without key. Non-mutating. The cleanest way to drop an entry from a record.
func.mapValues({obj, key})objectProject a property out of every value: {[k]: obj[k][key]}.
func.groupBy({items, key})objectGroup 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.
func.sortBy({list, key?, desc?})any[]Stable non-mutating sort. With key, orders by that property (leaderboards: func.sortBy({list: Object.values(var.allPlayers), key: "coins", desc: true})); without, compares elements directly. Numbers numeric, strings lexicographic; incomparable values last.

3D grids (for cpnt.Scene3D)

CallReturnsNotes
func.voxKey({x, y, z})stringBuild a grid cell key: {x:1,y:0,z:2}"1,0,2". Coordinates truncate to integers.
func.voxParse(key){ x, y, z }Inverse of voxKey. Malformed components parse to 0.
func.voxFill({from, to, value, merge?}){ [key]: number }Grid map filling the inclusive cuboid between from and to (either corner order) with palette index value — platforms, walls, floors without nested .map loops. merge entries overlay the fill (they win), so layers compose while keeping the map type. Fill regions over 100k cells contribute nothing.
func.gridStep({grid, from, dir, climb?, gravity?}){ x, y, z }Collision-checked single-cell step (Y-up; north is −z, east is +x). Blocked destination → returns from unchanged. climb: true steps up 1-block ledges; gravity: true then drops onto the nearest support (or y=0). Wire directly to Scene3D’s onMove.
func.enclosure({grid, from, walls, min, max, y?}){ x, z }[]Flood-fill enclosure test on the x/z plane: walks 4-directionally from from, blocked by cells whose grid value at layer y (default 0) is in walls. Returns every open cell of the region when it’s fully walled in; [] when the start is a wall/out of bounds or the region leaks past min..max. Non-empty ⇒ enclosed; .length is the pen’s area. Fenced pens, sealed rooms, territory claims.

Game control & UX

CallReturnsNotes
func.kickPlayer(sessionId)actionDisconnects the player and removes them from var.players. Statement-callable from action bodies.
func.notify({to, message, type?})voidPop a toast. to ∈ `“host"
func.log({message, level?})voidWrite 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.json is 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.
CallArgument
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:

CallReturnsNotes
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)objectInverse of Object.entries.

These are the only Object.* calls Banto recognizes. Anything else (Object.assign, Object.freeze, etc.) is a compile error.