Generate a fresh random UUID in canonical hyphenated form.
Browse the reference
Pick an area to focus it, press / to search everything, or use Show all for one long page.
Guide
App author's guide — concepts, getting started, lifecycle.
Root
Top-level datumhue.* functions and fields.
12 sections2D Drawing
Retained vector primitives and paths.
4 sectionsImages, Sprites & Tiles
Raster images, drawing pictures, sprites, and tile maps.
8 sections3D & Scenes
Scene graph, meshes, materials, voxels, and shaders.
23 sectionsData & Charts
Tabular data, chart scales and marks, shared documents.
22 sectionsWindows & UI
Window manager, display control, UI elements.
9 sectionsInput & Events
Keyboard, mouse, and gamepad input, timers, system events.
9 sectionsPhysics & Grids
2D physics bodies, joints, and grid algorithms.
8 sectionsMath, Color & Noise
Vectors, quaternions, colors, noise fields, and seeded random streams.
15 sectionsAudio, Files & Storage
Audio playback, filesystem access, and local storage.
13 sectionsDocuments
Interactive documents: load, mount, and navigate books.
3 sectionsApp, Networking & Identity
App lifecycle, packages, HTTP mounts, identity, and commerce.
12 sectionsSerialization
Byte payloads and their decoders — text, data, images, scenes, and themes.
2 sectionsAssets & Resources
Loadable images, audio, scenes, cubemaps, fonts, and themes.
6 sectionsInternationalization
Localized text via Fluent catalogs and the active locale.
3 sectionsSQL
The query engine's functions and the DatumHue SQL dialect.
Documents (DHML)
The document page format's element reference.
Theme format
Color & metric tokens, shader materials — the theme-file format.
Package testing
The globals datumhue pkg test installs in a package's tests/ modules.
CLI reference
The datumhue commands this build exposes.
DatumHue — App Author's Guide
What is DatumHue
DatumHue is a creative workstation. You write apps in Lua that run inside the DatumHue client. Apps draw 2D and 3D graphics, play audio, handle input, load and visualize data, and collaborate in real time. Many apps run at once, arranged by a window manager — itself just another Lua app.
Apps can download content, exchange messages, and share live documents with other clients.
Who this guide is for
This guide is for people writing apps in DatumHue. It teaches the models
and conventions behind the datumhue.* API — what an app is, how it draws,
how it loads data, how it talks to other apps. It does not list every function
signature — those live in the API reference alongside this guide,
generated from the client you have installed so they always match your version.
You should be comfortable with Lua. No prior DatumHue knowledge is assumed.
Contents
- Specifications
- Quick start
- Core concepts
- Packages
- Working with the API
- The Lua environment
- Tooling
- Gotchas
- Glossary
- The API reference
Specifications
| Display | Any resolution, 2D and 3D |
| Audio | Waveform synthesis (sine, square, triangle, saw, noise) + sample playback |
| Input | Keyboard, mouse, gamepad (up to 8 pads) |
| Language | Lua (sandboxed, Lua 5.3/5.4 compatible subset) |
| Networking | Topic-based messaging, shared live documents |
| Storage | Per-app persistent key-value store |
| Grid | A* pathfinding, Dijkstra distance maps, field of view, Voronoi |
| Physics | 2D and 3D rigid bodies, collision detection, sensors |
| 3D | PBR materials, HDR, bloom, fog, atmosphere, voxels, particles, glTF models |
| Data | CSV/Parquet loading, SQL queries, streaming plotting |
Quick start
An app is a Lua script. The script body runs once when the app spawns; to
animate, register an update handler with datumhue.on_update(fn). Run any of
the examples below with datumhue run <file>.lua.
While iterating, add --watch: every save reloads the running app. A code
change relaunches it from the fresh source — a save that does not compile
keeps the current version running and reports the error — and a change to an
asset the app has loaded (an image, a sound, a scene) is applied in place,
without a relaunch and without losing the app's state. datumhue repl
accepts the same flag, and the console re-attaches across reloads.
Hello world
local color = datumhue.color
local bg = datumhue.ui.root:panel({
width = 400, height = 300, color = color("#1a1a2e"),
})
bg:label({
left = 120, top = 130,
text = "Hello, DatumHue!",
font_size = 24, color = color("#e0e0e0"),
})
A bouncing ball
A canvas is an offscreen surface; mount it with canvas:mount() so the drawing
shows up on screen. Primitives persist across frames — create them once, then
update their properties.
local color = datumhue.color
local vec2 = datumhue.math.vec2
local W, H, R = 320, 240, 12
local canvas = datumhue.draw.new({width = W, height = H, background = color("#1a1a2e")})
canvas:mount({width = W, height = H})
local pos = vec2(0, 0)
local vel = vec2(120, 80)
local bounds = vec2(W / 2 - R, H / 2 - R)
local ball = canvas:circle({pos = pos:extend(1), radius = R, color = color("#e94560")})
datumhue.on_update(function(dt)
pos = pos + vel * dt
if math.abs(pos.x) > bounds.x then vel = vel:with_x(-vel.x) end
if math.abs(pos.y) > bounds.y then vel = vel:with_y(-vel.y) end
ball:update({pos = pos:extend(1)})
end)
Pixel art
For retro framebuffer drawing, use the image API. You record drawing into a
picture and replay it onto an image with image:apply — the whole frame
lands at once, with nothing half-drawn ever visible. Build the picture once and
reuse it; picture:reset() clears it for the next frame.
local color = datumhue.color
local W, H = 128, 128
local c = datumhue.image.new({width = W, height = H})
c:mount({width = W * 4, height = H * 4}) -- 4x upscale
local pic = datumhue.image.picture()
datumhue.on_update(function()
local t = datumhue.time.now()
pic:reset()
pic:clear()
local x = 64 + math.cos(t * 2) * 40
local y = 64 + math.sin(t * 3) * 30
pic:circfill(x, y, 8, color("#ff004d"))
pic:print("hello", 48, 58, color("#fff1e8"))
c:apply(pic)
end)
For animated sprites and tile maps, slice an image into a grid with
image:atlas, then draw cells onto a draw canvas with
canvas:sprite(atlas:sprite(index), {pos = …}) (set prim.cell to animate),
or fill a canvas:tilemap(atlas, {columns = …, rows = …}) with tilemap:set(x, y, cell).
Because they are real draw primitives, sprites compose with physics, shaders,
and picking. Draw a whole image (or another canvas/scene) with canvas:image.
local color = datumhue.color
local vec2 = datumhue.math.vec2
local vec3 = datumhue.math.vec3
-- Paint a 4-frame strip of 16x16 cells: a dot orbiting each cell's center.
local sheet = datumhue.image.new({width = 64, height = 16})
local pic = datumhue.image.picture()
local steps = {vec2(4, 0), vec2(0, 4), vec2(-4, 0), vec2(0, -4)}
for i = 0, 3 do
local s = steps[i + 1]
pic:circfill(8 + i * 16 + s.x, 8 + s.y, 3, color("#ffcc00"))
end
sheet:apply(pic)
local atlas = sheet:atlas({tile_size = vec2(16, 16), columns = 4, rows = 1})
-- Draw cell 0 as a sprite, then cycle the cell to animate.
local canvas = datumhue.draw.new({width = 128, height = 128})
canvas:mount({width = 128, height = 128})
local prim = canvas:sprite(atlas:sprite(0, {size = vec2(48, 48)}), {pos = vec3(0, 0, 1)})
datumhue.on_update(function()
prim.cell = math.floor(datumhue.time.now() * 8) % 4
end)
A 3D scene
Scenes are retained-mode — primitives persist until removed.
local color = datumhue.color
local vec3 = datumhue.math.vec3
local W, H = 800, 600
local scene = datumhue.scene.new({width = W, height = H, hdr = true})
scene:mount({width = W, height = H})
scene:cube({pos = vec3(0, 0, 0), color = color("#4488ff")})
scene:directional_light({direction = vec3(-0.5, -1, -0.2), intensity = 12000, shadows = true})
scene.camera.pos = vec3(3, 3, 3)
scene.camera:look_at(vec3(0, 0, 0))
scene.bloom = {intensity = 0.2}
Physics
local color = datumhue.color
local vec3 = datumhue.math.vec3
local W, H = 400, 400
local canvas = datumhue.draw.new({width = W, height = H, background = color("#111111")})
canvas:mount({width = W, height = H})
local box = canvas:rect({pos = vec3(-10, 100, 1), width = 20, height = 20, color = color("#ff6b6b")})
box:add_body({type = "dynamic", shape = "rect"})
local floor = canvas:rect({pos = vec3(-150, -180, 1), width = 300, height = 20, color = color("#4ecdc4")})
floor:add_body({type = "static", shape = "rect"})
All 2D physics bodies that should collide must share the same z (the z
component of pos); see Gotchas.
Core concepts
Apps, the process tree, and the window manager
Apps form a parent-child process tree rooted at the bootstrap app. An app
creates a child with datumhue.app.spawn(). The window manager (WM) is
itself an ordinary app — usually the bootstrap — that spawns and arranges the
others.
Authority follows the tree. WM mutations (terminate_app, set_app_bounds,
and so on) require the caller to be an ancestor of the target; attempting
to manage a non-descendant raises an error. The bootstrap can manage
everything. WM functions take an App handle (from datumhue.app.self(),
app.spawn, or an event payload) — never a numeric id.
When startup produces errors, the runtime routes the launch to a package named
fallback instead of the configured bootstrap. The fallback runs as the root
app, reads the errors via datumhue.app.errors(), and otherwise inherits the
bootstrap's root-app privileges.
The app window
Each app gets an auto-created root container on spawn:
Root Container (WM-managed bounds, overflow clipped, z-indexed)
└── Content Area (fills root)
├── your panels, images, labels, buttons...
└── everything without an explicit parent lands here
The root container is the target for WM operations and an app cannot render
outside it. The content area is where your UI lives: datumhue.ui.root:panel(),
source:mount(), and the like auto-parent here when you build at the UI root.
datumhue.screen is scope-dependent. The bootstrap/WM app drives the
system window; a regular app drives its own root container — same code, different
scope:
| API | Bootstrap / WM app | Regular app |
|---|---|---|
fullscreen() | System window fullscreen | Maximize the root container |
request_resolution() | System window size | Resize the root container |
screen.width / screen.height | System window size | Root container size |
The request_* calls are proposals, not setters: a regular app's request goes
to the window manager, which answers it. The screen.width / screen.height
properties report the size actually in effect.
Apps are stacked most-recently-focused first. Focusing an app brings it to the
front; datumhue.app.is_focused() reports focus, and app_focused /
app_unfocused events fire on changes. A newly spawned app auto-receives focus
when its spawner can manage the currently focused app. Cursor state (visible,
locked, icon) is stored per app and swapped on focus change.
Coordinate systems
Two conventions coexist. State them once and keep them straight:
| API | Origin | Y direction | (0,0) is |
|---|---|---|---|
draw (retained 2D) | Center | Up | canvas center |
scene (3D) | Center | Up | scene center |
image (raster buffer) | Top-left | Down | top-left pixel |
physics | Matches the host handle's API | — | no conversion |
Draw primitives place depth in pos.z — pos = vec3(x, y, z), larger z in
front. When converting a coordinate between a Y-up API and the Y-down image
API, flip Y.
Capabilities and permissions
DatumHue gates sensitive operations two ways, and the distinction matters:
- Permissions are boolean grants drawn from a fixed set:
identity,screenshot,network,commerce,packages. They gate whole surfaces (e.g.identitygates the user-data accessors,networkgates network-scoped messaging/documents,commercegates the purchase API,packagesgates install management — installing, uninstalling, and reading the installed-package library, while plain catalog browsing stays open). The catalog itself spans every connected registry: each creator publishes under their own namespace, andpackages.list/packages.searchaggregate all of them unless narrowed to one. - Capability handles are unforgeable userdata that grant access to one
specific resource — a directory, file, data mount, or HTTP mount. Possession
of the handle is the grant, and the handle arrives through
datumhue.argsor a parent'sapp.spawnoptions.
A package's manifest declares the permissions it requires under
capabilities. Before the entry script runs, the runtime requests each from
the parent WM; if any is denied, the app refuses to start. So inside a running
app, datumhue.app.has_permission(name) is always true for every declared
permission. The manifest sets the required floor; an app may also
datumhue.app.request_permission(name) for optional grants at runtime.
Both permissions and capability handles flow down the tree and only
narrow. A child receives a permission only when the spawning parent passes it
in permissions = { … } on app.spawn and the parent itself holds it;
likewise a child receives a dirs / files / data_mounts / http_mounts
grant only from the parent's own grants. A call from an app that lacks a
required permission raises.
Physics needs no grant at all: each app simulates in its own worlds, and bodies, joints, queries, and gravity never interact across apps.
The app lifecycle
The script body is the app's init phase — it runs once on spawn. Read
spawn-time arguments from datumhue.args.argv. Calls that wait on I/O (loading
assets, installing packages) are fine in the body; execution resumes step by
step as each completes (see Suspending calls).
Register a per-frame handler with datumhue.on_update(fn). fn(dt) receives
seconds since the previous call (typically ~0.016; scheduler pressure can
stretch it). At most one update handler is active per app — calling again
replaces it; pass nil to clear it. Timer callbacks fire before on_update in
the same frame.
What keeps an app alive depends on its kind. A UI app stays alive until
something explicitly terminates it: it calls datumhue.app.terminate(), a
managing app calls datumhue.wm.terminate_app(child), the parent cascades, or
it crashes (see When a callback errors). The body
returning or having no callbacks does not reap it. A
service app (no UI) is kept alive only while some callback is still
registered; print("hi") runs and exits. Everything that counts as
"registered" is one of these:
- the
on_updatehandler; - a timer that hasn't fired for the last time or been cancelled;
- a subscription of any kind — events, messages, channels, document watchers and the collection / counter feeds built on them, package-catalog changes, text / key input capture;
- a callback attached to something the app owns — element handlers, collision callbacks, streamed-chunk callbacks, animation callbacks, data error handlers, route and dialogue hooks;
- a suspending call that is still waiting: an app is never reaped in the middle of a paused call, however long the wait.
When the last of these is gone — every timer done, every subscription unsubscribed, no update handler, nothing in flight — a service app ends.
Discarding a subscription's handle does not unsubscribe. The value a
subscribe call (or a timer) returns is a control handle, not the registration
itself: letting it go out of scope leaves the callback registered — still
firing, and still keeping a service app alive — with no way left to stop it
short of terminating the app. Keep the handle and call :unsubscribe() when
you are done with it.
A spawn that fails still ends in app_terminated. app.spawn returns the
child's handle immediately; a child spawned from the catalog starts running
only once its package arrives. If the package can't be delivered or can't run,
the child never starts: its handle reports not alive and app_terminated
fires for it — the same terminal signal as for a running app's exit, so one
handler covers both.
When an app terminates, all its descendants terminate too (cascade) and
everything it owns is cleaned up. If the terminated app had focus, the engine
auto-focuses the surviving app with the highest z-index. To flush state on the
way out, register a handler with datumhue.on_terminate(fn): it runs once,
inside a short bounded time budget, before the cleanup — but not on a crash —
and it cannot cancel the termination. Registering it does not keep a service
app alive.
When a callback errors
One rule covers every callback shape: an error that escapes a callback
crashes the app. The entry script, the on_update handler, timer callbacks,
UI handlers such as on_click, events.on and messaging subscription
callbacks, document watchers, and collision callbacks all behave identically —
the error is reported in the client's log output with the app's name, and the
app terminates with the usual cleanup: descendants cascade, everything the
app owns is removed, and none of its callbacks fires again. Nothing is
selectively unregistered; there is no middle ground where a timer stops but
the app lives on. Other apps are untouched, and a managing app observes the
same app_terminated event as for any other exit. When the crashed app is
the root of a datumhue run invocation, the process exits with a failure
code.
To survive an error, catch it where it can happen: wrap the failure-prone
call in pcall inside the callback and handle the result — a caught error
crashes nothing. A callback that one of your own calls invokes on the spot
(a router page builder, a book template function) raises at that call site
instead, so a pcall around the outer call catches those too.
Suspending calls
Some datumhue.* calls are suspending: they pause the calling code — and,
while paused, the app's per-frame work — until their result is ready, then
continue. They do not block the OS thread: the renderer keeps drawing this
app's last state and other apps keep running. For local or fast operations this
is sub-frame and unnoticeable; waiting on a slow network, a heavy query, or a
user dialog can be visibly long.
Suspending calls return their result the ordinary way — local t = b:text(),
no callback to wait on. The API reference flags each suspending call. Treat a
flagged call as one that can pause; don't put it in a tight loop assuming it
is free.
Most waits are handles, not pauses. Request/response operations — HTTP
requests, file writes and metadata reads, storage and document reads and
writes — start their work the moment you call them and return a handle
immediately, before the result exists. Reading a result field off an
unmaterialized handle raises; await it with the chainable :ready() (which
suspends, returns the same handle, and raises if the operation failed), or
probe its state field, which never raises or suspends. Asset handles work
the same way: they come back at once and load in the background. Because the
work starts at the call, several operations run concurrently — start them
all, then wait once with the datumhue.ready barrier, which resolves when
every handle in the batch is ready and raises on the first failure:
local store = datumhue.storage.open()
store:set("alpha", datumhue.bytes("first")):ready()
store:set("beta", datumhue.bytes("second")):ready()
local a = store:get("alpha")
local b = store:get("beta")
datumhue.ready({ a, b })
print(a.value:text(), b.value:text())
For straight-line code, chain the barrier onto the call — file:write(bytes):ready()
writes and confirms in one expression. Dropping a handle without awaiting it
is allowed: the operation still runs; you have chosen not to observe its
outcome. Chart state that settles as part of rendering a frame — a scale's
domain, data-space conversions — is nil while unresolved; read it again on a
later frame rather than waiting on it.
Suspending inside callbacks. Every callback shape can suspend — the entry
script, on_update, timers, UI handlers (the Navigation
example pushes a route from inside on_click), event and messaging
subscriptions, document watchers. An app's callbacks never interleave: they
run one at a time, in order, and each runs to completion before the next
starts, so a flow of several suspending calls in one callback executes
start-to-finish with nothing else of yours running in between. That
no-interleaving guarantee is the recommended shape for a long flow: write it
as straight-line code in a single callback. The cost is that while one
callback is paused, everything else the app has to run waits in line behind
it — a second click queues a second invocation that runs after the first
completes, and a repeating timer keeps firing on schedule, queueing one
invocation per fire, delivered back-to-back once the paused callback
finishes. Guard a flow that must not run twice with a flag. The per-frame
handler is the one thing that never piles up: at most one on_update
invocation is in flight or waiting at a time; beyond that, frames skip it and
the elapsed time accrues, so the next invocation receives the full time since
the previous one as its dt. Your own coroutines don't change any of this: a
suspending call inside a coroutine you resume still pauses the whole app's
Lua, not just that coroutine.
There is no timeout. A suspending call stays paused until its result
arrives, however long that takes — datumhue.ready on an asset that never
arrives waits indefinitely, and request_permission waits for as long as the
parent takes to answer (a parent prompting the user may take arbitrarily
long). This is deliberate: the runtime cannot know which waits are
legitimately long, and there is no timeout to configure. pcall does not
shorten a wait either — waiting is not an error, so there is nothing to
catch. A suspended app is still an ordinary app: the renderer keeps showing
its last state, it can be terminated normally, and it never stalls other apps
or the client.
Sessions
A session is an identifier attached to every launch, so concurrent launches
can be told apart. Apps read the resolved value via datumhue.app.session().
Each launch is independent by default — there is no implicit carry-over. A
launch can name a session explicitly, or resume the most recently used one. On
the desktop a launch is one process invocation; in a browser a launch is one
tab, with the session sticky across reloads of that tab and cleared when it
closes. The exact launch syntax is in datumhue --help.
Packages
A package is a directory with a package.kdl manifest plus a strict layout
of code and content. The client loads a package as a single unit — the entry
script, every require-able module under lib/, and every asset under
assets/ come from the same tree.
Layout
my-package/
├── package.kdl # manifest — name, version, kind, requires
├── init.lua # entry — app's main / library's exported table
├── lib/ # module tree, .lua only, any depth
│ ├── util.lua # → require("util")
│ ├── sub.lua # → require("sub")
│ └── sub/
│ └── leaf.lua # → require("sub.leaf")
└── assets/ # content, any file type, any depth
├── player.png # datumhue.package:dir():read("assets/player.png"):image()
├── audio/boop.ogg # datumhue.package:dir():read("assets/audio/boop.ogg"):audio()
└── data/grid.csv # datumhue.package:dir():read("assets/data/grid.csv"):csv()
The loader picks up only package.kdl (required), init.lua (the entry — the
app's main, or what require("<libname>") returns), lib/**/*.lua (the module
tree; non-.lua files under lib/ have no runtime meaning), and
assets/**/* (everything else). Anything else at the top level — README.md,
docs/, dotfiles — is silently skipped. deps/ at the root is reserved and
populated by the resolver under deps/@scope/name/; you never author it.
An optional .dhignore at the root layers gitignore-style glob exclusions over
the layout. It is itself a dotfile, so it never ships in the bundle.
The manifest
name "@alice/my-app"
version "0.1.0"
api_version "*"
kind "app"
author "Alice"
description "A tiny example."
icon "assets/icon.png"
license "MIT-0"
tags "demo" "example"
capabilities "network" "identity"
sealed #false
service #false
name is the package's identity in the catalog, written @scope/name. The
scope binds the package to the entity that owns it — an individual or a team —
and is enforced at publish against the publisher's verified sign-in. Both
segments are lowercase letters, digits, _, or -, starting with a letter or
digit; _ folds to -, so @a/foo_bar and @a/foo-bar are one identity.
version is a SemVer version;
api_version is a SemVer constraint on the client API the package was built
against. kind is one of:
app— launchable, hasinit.lua.library—require-able, has alib/tree.asset_pack— data only (themes, books, datasets, fonts, shaders, media). An open-listcontent_typetag (e.g."theme","dataset") refines it for discovery and validation. It is valid on anasset_packand on anappwhose substance is content (an interactive"book"); only alibraryrejects it.
The optional catalog fields round out the manifest. author and description
are display strings; icon, readme, and screenshots are package-relative
paths to images and a README; tags is a list of discovery keywords. license
is the package's license as an SPDX id. A free package must declare one the
platform may redistribute it under; the accepted ids, and which of them
qualify, are the Package licenses chapter. monetization is "free" (the
default) or "paid" — a flag, not a price: the listing price is store state,
set and changed at any time with datumhue pkg price, without republishing.
A paid package that has not been priced yet is gated but not purchasable.
A paid app must be sealed. A paid library or asset pack is the
opposite by design — never sealed: its sale delivers the source into the
buyer's project as a perpetual embed license, to use and adapt under the
seller's terms and ship inside the buyer's own packages.
Two manifest flags change how an app runs:
service #true— the app runs without a UI surface. No root container is created, and the UI-producing sides of thedatumhuetable (ui,draw,image,scene,screen,theme,input,wm,physics, …) are not registered — calling them errors.datumhue.app.is_service()reports the live value. Valid only onkind "app".sealed #true— the app opts out of external introspection. A consumer that loads a sealed package sees its manifest metadata butpkg:dir()returnsnil; the running app still reaches its own files. Sealing is a trust signal, not encryption — anyone with the bytes can unpack them offline. Only anappmay seal; libraries and asset packs are delivered as source.
capabilities declares required permissions; see
Capabilities and permissions.
A networked creation names its meeting point — the service its players'
copies contact to find each other — with meeting-point "https://play.example.com" ca-cert="assets/ca-cert.pem". The networked
runtime connects only there, reading no address from its environment, and
the CA file (omit it for a publicly-trusted certificate) ships inside the
package so the binding signature covers it. Valid only on kind "app";
every other client ignores it.
Archives
The same layout can travel as a single file: a .dhpkg archive is a plain zip
whose entries are the package-relative paths. A packed archive's content hash
matches the source tree's hash, so packing and unpacking are byte-identical
round trips.
require and modules
Each app has a sandboxed require that reads module source only from its own
package (plus resolved deps). Names are absolute from the package root and
dotted — lib/ is implicit and never spelled. There is no relative form, no
./sibling, no package.path.
require("foo") -- lib/foo.lua
require("foo.bar.baz") -- lib/foo/bar/baz.lua
One name, one file: a module named sub is lib/sub.lua, sitting
beside whatever lib/sub/ holds. A directory on its own is not a
module.
A leading @ switches lookup into the dependency namespace: a dependency is
addressed by its @scope/name identity in slash form, optionally followed by a
module path under the dep's lib/ tree.
require("@alice/greeter-lib") -- the dep's entry (its own init.lua return)
require("@alice/greeter-lib/messages/welcome") -- a module inside the dep's lib/ tree
A dependency may declare an exports list in its package.kdl
(exports "util" "messages.welcome"): when present, only the listed
modules answer deep requires like the second form — the rest of its
lib/ is its own business. The entry is always reachable, and a
package's own requires are never gated.
Each module runs once per app; repeat calls hand back the same value. A module
that returns nothing yields true. Circular requires surface as a runtime
error rather than deadlocking. A typo or missing module fails with an error naming the exact path it
looked for — require: module 'x' not found in package (looked for lib/x.lua) — and a module a dependency keeps private fails with
is not exported by @scope/name and the list that is.
For loading an exact path rather than a dotted name, a Dir or File
handle exposes dir:require(rel) / file:require(), which compile the literal
path's bytes as Lua — no lib/ prefixing, no .lua fallback. Handle-scoped
requires are separate from the global dotted require.
Dependencies
Declare each dependency in the manifest by its @scope/name identity. Only
library and asset_pack content is eligible — apps have their own lifecycle
and are launched, not required. A dependency resolves from one of two sources:
requires {
package "@alice/greeter-lib" version="^1.0" // from the registry (default)
package "@studio/art-pack" version="~0.3" namespace="brand" // registry, other namespace
package "@me/in-progress-lib" workspace=#true // from a local workspace member
}
A registry dependency carries a SemVer constraint and resolves to a
published version; an optional namespace looks it up in a different namespace.
A workspace dependency (workspace=#true) carries no version — it resolves
to the matching member of the enclosing workspace.kdl (below), letting you
iterate on a library and the app that uses it together before either is
published. At publish the workspace marker is stripped: the dependency is by
then published, so the on-wire manifest only ever carries registry references
pinned to the member's version.
Resolved dependencies graft into the consumer under deps/@scope/name/. Reach
into a dep from Lua with its @scope/name identity; read its assets through the
standard Dir methods, e.g.
datumhue.package:dir():read("deps/@studio/art-pack/assets/player.png"):image().
datumhue pkg update resolves the registry dependencies and writes
package.lock.kdl, pinning each to the exact published content it resolves to
(yanked versions are skipped) and recording each workspace dependency as a
marker. datumhue pkg push then publishes against that lock without
re-resolving — it fails if a pinned dependency has since been yanked or removed,
pointing you back at pkg update. To move onto newer or un-yanked dependency
versions, run pkg update, review the lockfile diff, and push.
datumhue pkg outdated lists dependencies with a newer or yanked pin.
A paid dependency works differently: buy it once (the store's Creator
shelf), and pkg update delivers its source into your project at
deps/@scope/name/ — yours to read, adapt under the seller's terms, and keep;
your own backups cover it from then on. The delivered tree is the dependency:
it ships inside your published package, your users never fetch it separately,
and the lock records it as vendored provenance rather than a pin. Delete the
tree and run pkg update to re-deliver a fresh copy.
Conflicts are errors: if two transitive requirements cannot be satisfied by one version of a dep, resolution refuses to proceed. Missing deps, version mismatches, and using an app as a dependency all fail with a clear message before the first line of Lua runs.
Workspaces
A workspace.kdl at the root of a tree of related packages declares which
directories are its members — the packages you develop together and publish as
a unit. It is the sole source of workspace membership; without one, every
dependency resolves from the registry.
workspace {
namespace "acme" // default publish namespace for members
member "chart-lib" // a member directory, relative to this file
member "apps/*" // a glob matching every immediate subdirectory
member "theme" namespace="brand" // a per-member namespace override
}
A workspace=#true dependency resolves to the member with that @scope/name.
datumhue pkg update --workspace refreshes every member's lockfile in one pass,
and datumhue pkg push --workspace publishes the members in dependency order — a
library before the app that depends on it — so each published package pins its
dependencies' real published content. It is idempotent: members already
published at their version are skipped, so re-running after a failure resumes.
--dry-run prints the order without publishing anything.
Maintaining a published release
Published versions are immutable — you never overwrite one. To retire a release
that should no longer be installed, datumhue pkg yank marks a specific version
yanked: it drops out of fresh resolutions, pkg update moves dependents off it,
and pkg outdated flags anyone still pinned to it — while installs already
pinned to that version keep launching. Yanking is reversible. Before you yank,
datumhue pkg dependents lists the published packages that depend on the one
you're about to pull, so you can gauge the blast radius first.
Package handles
A Package handle is the runtime representation of a package — the running app's
own bundle (datumhue.package) or another loaded via dir:load_package /
file:load_package:
print(datumhue.package:name(), datumhue.package:version())
local addon = datumhue.args.files.addon:load_package()
print(addon:name(), addon:version(), addon:kind())
if not addon:is_sealed() then
print("entry source:", addon:dir():read("init.lua"):text())
end
A handle exposes manifest metadata (name, version, kind) and a read-only
dir() over the bundle's files; dir() returns nil for a sealed package
loaded from outside. Content access goes through that directory using the
standard Dir methods and the Bytes decoders.
Handle equality is identity-based — loading the same path twice yields two
unequal handles; compare .name / :version() / :kind() instead.
Working with the API
The sections below cover the models behind each part of the API. For exact signatures, see the API reference alongside this guide.
A few conventions run through all of it:
- Colors are
Colorvalues fromdatumhue.color(...). The callable table accepts a hex string ("#RRGGBB"/"#RRGGBBAA"), RGB/RGBA floats, or named constructors (color.rgb,color.rgba,color.hex,color.hsl). Scripts usually bindlocal color = datumhue.color. - Typed handles are returned by every creation function (
Image,Atlas,Sprite,DrawCanvas,DrawPrimitive,TileMap,Scene,SceneNode,UiElement,Material,Shader, …). Each carries the methods for its API and supports==andtostring()— nothing else. They are opaque; don't treat them as numbers. - Texture creation vs display.
image.new,draw.new, andscene.newonly allocate a render target. Callsource:mount(opts)to display it — the same texture can be shown multiple times. - Parameter style. Retained-mode APIs (
draw,scene,ui) take option tables ({x = 10, y = 20}). Picture drawing takes positional arguments. - Angles are radians everywhere. Errors are raised, not returned — wrap
fallible calls in
pcall.
Drawing and 3D
Three rendering surfaces, all displayed via source:mount():
datumhue.draw— retained 2D vector drawing, center-origin and Y-up. Primitives (canvas:rect,canvas:circle, …) persist across frames; update their properties withprim:update(opts)rather than redrawing.datumhue.image— a rasterImage, top-left origin and Y-down. One type covers both a framebuffer you draw into and loaded/encodable pixel data: draw by recording apicture()and replaying it withimage:apply(the update is atomic; reuse one picture withpicture:reset()thenpicture:clear()), read pixels withimage:get, and persist withimage:encode_png. Slice an image into a cell grid withimage:atlasto feed sprites (canvas:sprite), tile maps (canvas:tilemap), and bitmap fonts (picture:set_font).datumhue.scene— retained 3D with PBR materials, HDR, bloom, fog, atmosphere, voxels, and glTF models. The camera mirrors a standard transform (arotationfield plus alook_atmethod).
The two 2D systems split by idiom. draw is retained vector: objects you
create, keep, and mutate, in Y-up center-origin space. image plus Picture
is recorded raster: record commands into a picture, replay them onto the image
with image:apply, in Y-down top-left pixel space. If you are used to
clearing and redrawing each frame, that idiom is a Picture plus reset();
if you think in persistent objects that move, that is draw.
They also split on blending. Draw primitives composite with standard alpha
blending — there is no per-primitive blend mode. For other compositing
(additive glow, multiply, screen), either work in pixels — picture:blit
takes a blend mode — or give the primitive a shader material and compute
the effect in its fragment program, feeding the layers to blend through its
channel textures.
Physics attaches to draw and scene primitives via prim:add_body(opts). The
engine owns a body's position each frame, so drive bodies through the
prim.pos and prim.velocity properties, whose assignment updates the
visual and the physics state together, not via prim:update({pos = …}).
Audio (datumhue.audio) covers waveform synthesis and sample playback; the
generated reference carries its surface. Mixing is three factors multiplied
together — the master volume, an optional named bus (audio.bus), and each
instance's own gain — so one bus knob ducks everything routed through it
without touching the instances, and a bed switch cannot desync the duck. A
one-shot given a position (at, heard from listener) arrives panned toward
its side and quieter with distance; omit at and it plays centered and
unattenuated, from everywhere.
Shaders
datumhue.shader.new() returns a Shader you apply anywhere a surface
accepts a material option — UI panels, 2D draw primitives, 3D meshes, and
scene post-processing all take the same handle:
datumhue.ui.root:panel({..., material = glow})
canvas:rect({..., material = gradient})
scene:cube({material = noise})
scene:mount({..., material = scanline}) -- post-processing
Beyond the presets, bytes:shader compiles your own fragment program
(WGSL, or WESL extended syntax) into the same kind of handle. The source
defines dh_fragment(uv) and reads auto-fed globals — dh.time, and a
per-primitive dh.resolution / dh.mouse (each shaded primitive sees its
own size and its own cursor position) — plus the uniforms you declare at
creation (written later with shader:set) and up to four dh_channel
textures fed from images, draw canvases, or scenes (shader:set_channel).
Compile errors raise immediately with the failing source line, and
shader:reload recompiles live, keeping the previous program when the new
source is broken — an edit-save-reload loop. A dh_fragment that never
returns can stall rendering and may trigger a GPU driver reset — keep it
free of unbounded loops.
User interface
datumhue.ui builds flex-laid-out widgets — panel, button, label,
image. Each widget is a method on its parent UiElement (parent:button{...},
some_panel:label{...}); build at the top level with datumhue.ui.root
(datumhue.ui.root:panel{...}). Every constructor and elem:update share one
set of layout and style options.
Every dimensional option (positions, sizes, gaps, padding, margins, borders) accepts a number or a string:
| Form | Meaning |
|---|---|
100 | 100 pixels (numbers default to pixels) |
"100px" | 100 pixels |
"50%" | 50% of the parent dimension |
"10vw" / "10vh" | 10% of viewport width / height |
"5vmin" / "5vmax" | 5% of the smaller / larger viewport dimension |
"auto" | computed automatically |
padding, margin, and border accept a single value (all four sides), a
named table ({left = 10, top = 4, …}), or the CSS array shorthand
({a}, {a,b}, {a,b,c}, {a,b,c,d}). border_radius takes the same shapes
per corner. Anchoring an element (left / right / top / bottom) switches
it to absolute positioning; otherwise it participates in its parent's flex
layout. panel and button default to themed padding and rounding — pass
padding = 0 / border_radius = 0 to opt out.
Navigation
panel:router() turns a region into a navigation stack. You declare routes from
builder functions and move between them; the router keeps backgrounded pages
alive (hidden), so going back restores their scroll position and widget state
instead of rebuilding from scratch.
local content = datumhue.ui.root:panel({ left = 20, top = 20, right = 20, bottom = 20 })
local router = content:router()
local list = router:route(function(page)
page:button({ text = "Open item 1", on_click = function() router:push(detail, { id = 1 }) end })
end, { title = "Items" })
detail = router:route(function(page, params)
page:label({ text = "Item " .. params.id })
page:button({ text = "Back", on_click = function() router:pop() end })
end, { title = "Detail" })
router:show(list)
route(builder, opts) returns a Route handle; navigate with push (drill in),
pop (back), replace (swap the top), to_root (back to the start), and go
(jump to a route — popping to it if it's already on the stack, else pushing). A
page builder receives its page element and the params passed to the navigator
(small identifiers, not data — fetch the data from your own store). router.depth,
router.active, router.params, and router.can_go_back describe the current
state; compare router.active to a route handle to highlight the current tab.
Tabs are just several root routes switched with show — each keeps its own
retained sub-stack, so switching tabs and coming back restores where you were.
Routers are independent and nest: a route's page can create its own router.
A route may declare on_enter (called once the page is built — start per-page
work here) and on_leave (called before the page is destroyed; return false to
veto and keep it, e.g. to confirm discarding unsaved edits). Navigating moves
keyboard focus into the new page (a screen reader announces its title) and
restores focus when you go back.
Theming
datumhue.theme drives appearance through a token map: widgets and chart
primitives reference named color and metric tokens (panel_background,
chart_axis, padding_medium, …) rather than hard-coded values. The full
token list lives in the generated reference.
datumhue.theme.pin(datumhue.theme.default_dark()) -- built-in theme
datumhue.theme.pin(datumhue.theme.default_light(), child) -- a managed child
local custom = datumhue.args.files.mytheme:read():theme() -- a custom theme file
datumhue.theme.pin(custom)
Partial overrides are valid — a theme only defines the tokens it changes; the
rest fall back to the built-in default. Child apps that haven't set their own
theme inherit from the nearest ancestor that has, and update reactively when
that ancestor changes. Themes can also bind default shader materials to widget
types via widget_shaders; on creation, a widget resolves its surface in
priority order: per-widget material > theme widget_shaders slot > solid
background color.
Custom themes are KDL documents decoded via file:read():theme() /
dir:read(rel):theme(), returning a Theme for theme.pin:
colors {
panel_background 0x1a1a2e
text_primary 0xeaeaea
accent_primary 0xe94560
}
metrics {
padding_medium 12
border_radius 6
}
Colors are 0xRRGGBB hex. A theme can also define GPU materials in a shaders
block and bind them to widget slots; the block shapes and every token live in
the generated reference.
Display and input
datumhue.screen is scope-dependent (see The app window).
Four sizing knobs compose, from OS-level outward:
| Knob | Requested by | Affects |
|---|---|---|
request_resolution | author, app start | physical window size |
request_design_resolution | author, app start | the canvas your UI was authored against |
request_stretch_mode | author, app start | how the design canvas fits the window |
request_zoom | end user, runtime | a comfort multiplier on top of everything above |
Each knob is a request, not a setter: the proposal goes to the window manager,
which answers it. Read what is actually in effect from the screen state
properties. The OS display scale (DPI, Retina, fractional scaling) is always
honored on top; the reported screen.width / screen.height are already in
logical units.
datumhue.input reads keyboard, mouse, and gamepad state. Input is
focus-gated by the same can_manage rule as lifecycle events: only the
focused app and its ancestors receive real input state. Any other caller sees
inert values (booleans false, positions nil, vectors {x=0, y=0},
triggers 0.0) so background apps cannot observe keystrokes. Key names are
physical keys (layout-independent), written in lowercase snake case:
"a" is the QWERTY-A position regardless of layout. "shift" / "control" /
"alt" are side-agnostic aliases; use "shift_left" / "shift_right" (etc.)
to distinguish sides. Cursor mutations are per app and apply only while focused;
state is saved and restored on focus change.
Filesystem and data capabilities
Apps never see host paths. They navigate opaque Dir and File
handles through a small set of methods — there is no ambient open(path).
Handles arrive three ways:
- From the launcher, under
datumhue.args— directories, files, and remote mounts the launch granted. The exact launch syntax is indatumhue --help(desktop) or the browser launcher's URL params. - From a file widget —
ui.root:open_button{mode=…, on_pick=…}opens a file / directory dialog when the user clicks it and delivers the chosenFile/File[]/Dirtoon_pick;save_button{source=…, on_save=…}writes bytes to a chosen file and hands back a read-onlyFile. Returned handles are indistinguishable from launcher-supplied ones. - From child-spawn inheritance — a parent hands handles to a child it spawns.
Every handle exposes the same methods regardless of origin: dir:list,
dir:read(rel), dir:write(rel, bytes), file:read(), file:write(bytes),
and the full set of Bytes decoders. Remote mounts
connect lazily on first use; failures surface to the specific Lua call, not at
startup. Data mounts (a SQL surface, under datumhue.args.data_mounts)
open and authenticate lazily on the first mount:query(...).
Bytes and encoding
datumhue.bytes is the one handle for opaque byte payloads. Every API that
produces bytes (file reads, HTTP responses, encoder output)
returns a Bytes; every API that consumes bytes (request bodies, file writes)
accepts one. All decoding lives on the Bytes userdata — :text, :json,
:image, :csv, :parquet, :kdl, :theme, :audio, … — there is no
separate decoder namespace.
Construct a Bytes from a Lua string via the namespace's call form, or from a
structured value via an encoder constructor (datumhue.bytes.json(v) /
.kdl(v) / .msgpack(v)). KDL maps to and from Lua tables like this (applies
to bytes:kdl() and datumhue.bytes.kdl(value)):
| KDL shape | Lua representation |
|---|---|
name "foo" | name = "foo" |
port 8080 | port = 8080 |
enabled true | enabled = true |
tags "a" "b" "c" | tags = {"a", "b", "c"} |
flag (no args, no children) | flag = true |
server { host "x"; port 8080 } | server = { host = "x", port = 8080 } |
node prop="v" | node = { prop = "v" } |
entry "a"; entry "b" (repeated siblings) | entry = {"a", "b"} |
The mapping preserves structural meaning, not textual layout — type
annotations, comments, ordering, and spacing are not round-tripped. To omit a
key, set it to nil; an empty Lua table encodes as a bare node.
Tabular data
Tabular data sits behind opaque DataHandle userdata from bytes:csv() and
bytes:parquet() — typically file:read():csv() or
dir:read(rel):parquet(), or datumhue.bytes(literal):csv() for an inline
CSV. Methods that read data are suspending: if the source is still loading, the
call pauses and resumes once it is ready.
local sales = datumhue.bytes([[
month,region,revenue
1,North,45000
1,South,38000
2,North,52000
]]):csv()
local top = sales:query(
"SELECT region, SUM(revenue) AS total FROM data GROUP BY region")
Queries are lazy: nothing executes until a consumer reads them, via rows(),
batches(), count(), or binding to a mark. Results stream rather than
materializing full columns into Lua tables.
Charts
datumhue.chart composes charts from shared scales (data → pixels) and a
plot area carved out of a DrawCanvas. Marks render inside the plot area
using its scales, so hand-drawn primitives and chart primitives coexist on one
canvas.
Scales exist independently and own only the data domain: multiple marks —
and multiple plot areas — can share one scale to stay aligned under
pan/zoom, while each plot area assigns the scale its own pixel range from
its geometry. Two differently sized plots sharing an x scale therefore pan
together without sharing pixels, and everything reflows when an area
resizes. Marks bound to DataHandle instances stream with pixel-aware
downsampling — full columns are never materialized.
local color = datumhue.color
local vec3 = datumhue.math.vec3
local canvas = datumhue.draw.new({ width = 800, height = 400 })
local xs = datumhue.chart.scale.linear({ domain = "auto", nice = true })
local ys = datumhue.chart.scale.linear({ domain = "auto", nice = true })
local plot = canvas:chart({
pos = vec3(0, 0, 0), width = 800, height = 400,
margin = { left = 60, right = 20, top = 20, bottom = 40 },
x_scale = xs, y_scale = ys,
})
local h = datumhue.bytes("x,y\n1,10\n2,20\n3,15\n"):csv()
plot:line({ data = h, x_column = "x", y_column = "y", color = color("#4488ff") })
Chart primitives render in fixed depth layers, back to front: background →
grid → area → line → bars → points → reference rules → text overlays
→ axis spine/ticks/labels → legend. Ties within a layer resolve by insertion
order. There is no z option — choose the primitive type to land in the right
layer, and construct primitives in the order you want them stacked.
Aggregating marks — histograms, 2D-density and categorical heatmaps, box
plots, and multi-series bars — compute their bins, group-bys, and summaries
engine-side against the source, and re-aggregate over the visible domain
when a scale zooms. Interaction is opt-in per area: pan/zoom, crosshair
readouts, and a brush gesture that delivers the selected data-space range
to a callback — re-query other charts' sources from it to crossfilter.
canvas:charts lays out a grid of plot areas for faceting (cells passed
the same scale handle stay linked under pan/zoom), and scale:animate
eases a domain change for animated transitions.
Storage
datumhue.storage.open(label?) returns a Storage handle for persistent
key→bytes storage that survives across sessions. Your package is the
identity — the same package reaches the same store across runs, instances,
and upgrades, and no other app can address it. Optional labels open
independent sub-stores of the same identity. How the package arrived
qualifies the identity: a registry-installed package, a license-bound
creation, and a locally run directory or script each get their own store,
even under the same package name — so local development never sees (or
risks) an installed package's data, and a locally run package claiming an
installed package's name gets an empty store, not that package's data.
Locally run code is only as private as your machine: any local app that
claims the same name shares the same local-tier store.
open_scoped(label?) opens a store shared by every package under your
publisher scope — cooperating apps from one publisher coordinate through it
without any exchange. open_shared(uuid) is the explicit cross-scope
mechanism: every app passing the same UUID reaches the same store, so a
UUID hard-coded in published source is public, and a UUID kept out of the
source is a secret capability (datumhue.uuid() mints one). Values are
opaque Bytes; the handle methods are suspending.
Identity
datumhue.identity reports who the current user is, if anyone has signed in.
sign_in, sign_out, and is_signed_in are available to every app — but when
a regular app calls sign_in / sign_out, the shell receives an
app_identity_sign_in_request / app_identity_sign_out_request event and
decides whether to honor it. Outcomes surface through datumhue.events.
The accessors that expose user data — sub, issuer, email, name, and
claims — require identity permission. The user's credential stays
server-side: when an HTTP mount forwards it, the provider attaches it itself
(see HTTP).
Messaging, events, and documents
Three ways apps coordinate:
datumhue.messaging — topic-based pub/sub with two scopes. scope = "local"
(default) is a shared in-process bus across apps on this client; topic names are
not namespaced, so pick a hard-to-guess name for a private channel.
scope = "network" also reaches other clients, is opt-in, and requires
network permission. In both scopes, a publisher that subscribes to the same
topic does not receive its own messages.
datumhue.events — events.on(name, callback) subscribes to a system event;
the callback gets the payload table. Delivery is scoped: app-lifecycle events
(app_spawned, app_focused, app_bounds_changed, screen requests, …) reach
an app only for apps it can manage — its descendants and itself — and each
payload carries app and parent. Identity events reach every app. A child's
permission request is delivered to the parent WM as the request handle on the
app_permission_request payload; the WM answers it with request:grant() /
request:deny(), or stashes it to answer later (e.g. behind an approval modal) —
dropping it unanswered denies the request. connectivity reports whether a
deployment connection is up: it fires once on subscribe with the current state
and again on every transition, so a creation can start offline and light up its
shared layer when its meeting point is reached; a build without a network layer
reports offline once and never flips. The full event-name catalog and payload
fields are in the generated reference.
datumhue.documents — shared key-value state with change subscriptions.
scope = "local" (default) is an in-process store shared by apps on this client
for the process lifetime; scope = "network" replicates with other clients,
converging concurrent writes last-write-wins, and requires network
permission. Constructors return a Document handle whose methods (set, get,
subscribe, …) route by scope. Network keys are /-separated paths: writing
a key supersedes everything under it, and delete_prefix removes a whole
subtree. Sharing access goes through grants: doc:grant{...} mints a
DocumentGrant — bound to a recipient's identity, or bearer when no
recipient is named — whose :encode() string travels over any channel and
opens with datumhue.documents.open(...). Grants attenuate: a holder can
delegate a narrower one (read-only, a key subtree, a shorter validity)
but never a wider one. Every user also has a communal document derived
from their durable identity (documents.identity, gated on the identity
permission): your own section is always writable, others' sections need a
grant from them.
HTTP
An app makes HTTP requests through a granted HttpMount capability —
datumhue.args.http_mounts.<name>, or one a parent forwarded. Possession of
the handle is the grant, and the handle arrives only from those two sources.
An operator pins each mount to one origin, so the app supplies a mount-relative
path and reaches exactly the configured destination. mount:get(path) / post /
put / patch / delete / head are suspending — they pause the calling
coroutine until the response arrives, blocking no frame. The methods share one
option-table shape; the body, when present, is a Bytes
handle. A response's .body is itself a Bytes, so decode it inline:
mount:get("/items").body:json(). Credentials are attached provider-side per
the mount's configuration; the app never handles them.
The package catalog
datumhue.packages browses the packages the client knows about. Reads are
synchronous and return whatever the client has at the moment of the call; the
catalog stays current automatically, and on_change subscribes to live
changes. Read functions return opaque PackageRef userdata — also the value
app.spawn({package_ref = …}) accepts.
Books and documents
A book is content first: pages written as .dhml (markdown prose whose
kdl code fences hold declarative elements) or as .kdl (one element tree
under a page node), listed by a book.kdl at the book's root. Load one
through the filesystem capability you already hold — file:book() for a
single page, dir:book() for a directory — and book:mount{} renders the
current chapter into a scrollable page view. Multi-chapter books mount with
a chapter sidebar and a navigation row; pass toc = false / nav = false
for a bare page view.
Documents stay data until they need behavior. Give an element an id and
the hosting app binds it live: book:element(id) hands back the same typed
handle the constructor would have returned, so a button takes on_click,
a chart's plot takes new marks, and a slot element is an empty container
to mount anything into. Markdown headings register their slugs in the same
id namespace; book:go(target) jumps to an anchor or switches chapters.
Prose and properties may carry {{ expression }} templates — Lua evaluated
against the app's globals on each render — and the if / for nodes render
conditionally and per-item. book:refresh(id?) re-renders a subtree or the
whole page against current state. A page can also carry its own code: a
lua fence (or a script node) runs once when the book loads, in the
app's environment, and a kdl fence mounts as live elements. Add a
source mode to either fence to show the code as an inert listing
instead, or echo to show the listing and keep it live — so a book can
teach the very syntax it is built from.
Scripts make a book an app: a package whose pages carry them is
kind "app" with content_type "book", while a script-free book is a
plain asset_pack that any app — such as the bundled reader — opens with
dir:book(). To ship a book that opens on its own, make it a kind "app"
package that bundles its pages and mount it from init.lua:
pkg:dir():book():mount({ toc = true, nav = true })
pkg:dir() is the running app's own bundle, so this reads the bundled
book.kdl and chapters and renders them without a separate reader — the
same on a connected workstation or a fully offline one. datumhue pkg check validates a book package end-to-end — manifest, pages, includes,
and referenced files. The full element reference lives in the Documents
(DHML) area of this documentation.
The Lua environment
DatumHue runs a safe, sandboxed Lua interpreter. Most of Lua 5.3/5.4 works as expected, with these notes:
- Available standard library:
math,string,table,coroutine, and the base functions (print,type,error,assert,pcall,tonumber,tostring,pairs,ipairs,select,next,setmetatable,getmetatable).string.format,string.find,string.match,string.gmatch,string.gsub,string.sub, and the rest of the string library are present; bothstring.sub(s, 1, 3)ands:sub(1, 3)work. - Not available:
os,io,loadstring,dofile. There is no filesystem or system access except through capability handles. loadholds the standard Lua 5.4 contract (the compiled closure, ornil, errmsg) for string chunks, but is text-only: binary chunks are rejected whatever mode is requested, and reader-function chunks are not accepted.requireis available in sandboxed form, scoped to the package — see require and modules. Apps cannot import modules across package boundaries.- Random:
math.random()gives a float in [0, 1);math.random(n)an integer in [1, n];math.random(m, n)an integer in [m, n].math.randomseed(n)seeds for deterministic sequences. Each app has an independent RNG state. - Coroutines are fully supported.
- No weak tables, no
__gcmetamethods.
Tooling
The command-line tools (datumhue run, repl, pkg …, login, debug)
document themselves — run datumhue --help or datumhue <command> --help for
flags, arguments, and exit codes. The pieces of tooling worth knowing as an
author are editor integration, testing, and debugging.
Editor integration
DatumHue ships no first-party language server or formatter; it leans on mature
external tooling. datumhue pkg new and datumhue pkg refresh drop three
files into your package root:
datumhue.d.lua— LuaLS type annotations for thedatumhue.*API, rendered from the exact surface your client version ships. Regenerate withdatumhue pkg refreshafter a client upgrade..luarc.json— LuaLS workspace config wiring indatumhue.d.lua,lib/, and resolveddeps/, and declaringdatumhuea known global..stylua.toml— formatter config matching the scaffolded style.
A package with a tests/ suite also gets tests/test.d.lua — annotations
for the globals available inside test modules, documented in the Package
testing area of this reference.
Install LuaLS and
stylua once. Any LuaLS-aware editor
auto-picks up .luarc.json from the package root, giving completion and
type-checking against your client's real API.
Document pages (.dhml) are markdown with embedded kdl code fences, so any
editor's markdown mode highlights them. In Helix, associate the extension in
languages.toml:
[[language]]
name = "markdown"
file-types = [{ glob = "*.dhml" }, "md", "markdown"]
Testing
A package's automated tests live in its tests/ directory — module files named
*_test.lua plus optional support modules under tests/lib/. datumhue pkg new scaffolds a passing example. The directory never ships: packing,
publishing, and running all ignore it.
datumhue pkg test <dir> runs the suite inside the real engine. Test modules
declare suites and tests with describe and it; a test body can drive the
app across frames (wait_frames, wait_until), inject keyboard and pointer
input, and read the package's own modules with require, asserting through
expect matchers or plain assert. Results stream in TAP form and the exit
code carries the verdict; name filters, --skip, and --list select what
runs, and every run prints a seed that reproduces its random rolls via
--seed. Suites for windowed apps open a window — wrap the invocation in a
headless compositor (such as gamescope --backend headless --) to run them
unattended, and judge wrapped runs by the printed summary. `datumhue pkg test
datumhue pkg cov <dir> runs the same suite with line coverage of the
package's Lua and prints a per-file table afterwards; modules the suite never
loaded count as uncovered. --lcov writes a standard tracefile for coverage
tooling and --fail-under turns a minimum into a gate.
Both commands take --report <file>, which also writes the run as a styled
HTML page — the verdict, every test with its failure diagnostics, and for
coverage runs each source file annotated line by line. --open writes the
page (to --report's path, or a temporary file without it) and opens it in
your browser. The page is written even when the run fails, and exit codes
are unchanged.
Debugging
The client speaks the Debug Adapter Protocol, so any DAP-capable editor can set
breakpoints, step through Lua, and inspect the call stack and locals. Start the
client in debug mode (datumhue debug, see --help), then point your editor's
generic DAP client at the printed TCP port and issue a launch request with
the program path — a .lua file, a package directory, or a .dhpkg.
Breakpoints match Lua files by absolute filesystem path. Every DAP breakpoint
type, setVariable during a pause, REPL evaluate, and multi-coroutine
debugging (each coroutine surfaces as its own DAP thread) are supported.
Profiling
When an app stutters, the first question is where the frame's script budget went. The performance counters answer at a glance, from inside the app: an app can query its own share of the per-frame script budget and its current script memory and render them however suits — a corner label, a log line. The values are raw per-frame readings; smooth them over a few frames if you want a calm display.
For per-function attribution, record a profile. datumhue run <dir> --profile <file> plays the app normally and writes a sampling profile (speedscope
format, one profile per app) when it exits — reproduce the slow moment, quit,
and open the file in a compatible viewer to explore each app's time-ordered
flame graph. Adding --profile-summary <file> also writes a plain JSON table
of per-function call counts and self/total times plus frame-budget
statistics, made for scripted comparison. The same flags on datumhue pkg test <dir> profile a suite run instead — a repeatable workload for tracking
a package's performance over time.
A profiled run can also render its numbers as a styled HTML page: on
datumhue run, --report <file> (or --open) writes a report with each
app's frame-budget statistics and a hottest-first function table; on
datumhue pkg test, the profile joins the suite's report page as its own
section instead.
Gotchas
Traps that bite once if you don't know them:
- Texture ≠ display.
image.new(),draw.new(), andscene.new()only create a render target. Nothing is visible until you callsource:mount(). - Depth lives in
pos.z. Draw primitives created without an explicit z — a vec2pos, or none — stack in creation order, later on top. Pass a vec3 to pin the depth yourself: an explicit z is authoritative, and largerzrenders in front. - 2D physics needs a shared
z. All 2D bodies that should collide must share the samez; the engine overwrites the z component each frame, so usezonly for visual layering of non-physics elements. - Physics owns position. Don't
prim:update({pos = …})a body — the engine overwrites it each frame. Assign theprim.pos/prim.velocityproperties instead; they update the physics body along with the visual.colorandscaleonprim:update()are safe. - Screenshots are suspending.
screen.screenshot()pauses the caller until the capture lands; the returnedImageis then ready to draw, encode, or save.
Glossary
- App — a running Lua program inside the client. Every app is a node in the process tree.
- Bootstrap — the root app of a launch; usually the window manager.
- Capability — an opaque handle granting access to a resource (a directory, file, or mount). Distinct from a permission.
- Package — a
package.kdlmanifest plus a strictlib/+assets/layout; the unit the client loads. - Permission — a named grant (
identity,network, …) gating a sensitive API, flowing down the process tree and only narrowing. - Service app — an app with no UI surface, kept alive only while a callback is registered.
- Session — an identifier attached to every launch, so concurrent launches can be told apart.
- Suspending call — a call that pauses the app's Lua (not the OS thread) until its result is ready.
- WM (window manager) — the app that spawns and arranges other apps; itself an ordinary app.
The API reference
Everything above is the conceptual guide. The per-function contract — every namespace, function, handle method, field, operator, and option table this build exposes — lives in the API reference that accompanies it: a searchable, cross-linked list grouped by area. It is generated from the client's own registry, so it always matches the version you are running.
The datumhue docs command renders that same surface on demand, in whichever
form you need:
datumhue docs # Markdown to stdout
datumhue docs -o api.md # Markdown to a file
datumhue docs --format json # structured JSON catalog
datumhue docs --format html -o doc.html # this searchable HTML page
datumhue docs --open # build the HTML page and open it
datumhue pkg new and datumhue pkg refresh drop the same definitions into a
package as LuaLS annotations (datumhue.d.lua), so an editor with the Lua
language server offers completion and type-checking against the exact surface
your client version ships.
Package licenses
Every package declares, in its manifest, the license it is provided
under — the license field, holding one id from a closed set. The id is
shown wherever the package is offered: in the store, in the package
manager, in pkg info, and in the package's generated documentation.
Which ids a package may use depends on how it is offered:
- Free packages are redistributed openly, peer to peer, so they must
carry a license that permits exactly that:
0BSDorMIT-0for any package,CC0-1.0for data-only asset packs, orLicenseRef-DatumHue-Freewarefor a package that is free of charge while reserving all other rights. - Paid packages are access-gated, so the field is optional: absent, the package is provided under its creator's own terms.
A package that wants its code unreadable in the shipped artifact pairs
its license with sealed #true: packing then compiles every Lua source
to a chunk and refuses raw source in the archive. Sealing is required
for paid packages and available to any package.
The ids, in one line each:
0BSD— use for any purpose, no obligations.MIT-0— use for any purpose, no obligations.CC0-1.0— public-domain dedication; asset packs only.LicenseRef-DatumHue-Freeware— free to play through any DatumHue client; the artifact may travel DatumHue's content distribution as-is; everything else stays reserved.LicenseRef-Proprietary— all rights reserved; for packages whose terms arrive with the package.
pkg license prints this list; pkg license <id> prints an id's full
text. The full texts also follow below.
Full texts
0BSD — open license (0BSD): use for any purpose, no obligations
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
MIT-0 — open license (MIT-0): use for any purpose, no obligations
MIT No Attribution
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
CC0-1.0 — public domain (CC0 1.0): all rights waived; asset packs only
CC0 1.0 Universal is a public-domain dedication: the creator waives all
copyright and related rights in the work, worldwide, to the extent allowed
by law. It carries no patent grant, which is why DatumHue allows it only on
data-only asset packs. The canonical legal code is published by Creative
Commons as "CC0 1.0 Universal" at
https://creativecommons.org/publicdomain/zero/1.0/legalcode
LicenseRef-DatumHue-Freeware — freeware: free to play, all other rights reserved
# DatumHue Freeware Package License
**SPDX id: `LicenseRef-DatumHue-Freeware` — Version 1.2 — 2026-08-29**
This license covers a **package** distributed for DatumHue under the
SPDX identifier `LicenseRef-DatumHue-Freeware`. It applies to the
published package artifact — its code (compiled where the package is
sealed) and its assets — not to any DatumHue binary, which is covered
by its own license. It applies regardless of which DatumHue edition
runs the package: the platform client, the Personal or Indie edition,
or any other licensed DatumHue client.
---
## 1. Grant
The rights holder — the author named in the package manifest — grants
you, free of charge, a non-exclusive, non-transferable right to:
- **download and run** the package with any licensed DatumHue client,
and
- **redistribute the published artifact as-is** to other DatumHue users
as part of DatumHue's content distribution (including its
peer-to-peer distribution), unmodified and in whole.
## 2. Reservations
All rights not expressly granted are reserved by the rights holder. You
may not:
- decompile, disassemble, or otherwise reverse engineer the package's
code, or attempt to reconstruct the source of a sealed package;
- modify the package or create derivative works from it;
- extract its code or assets for use outside the package;
- redistribute it outside DatumHue's content distribution, or sell,
rent, or sublicense it.
## 3. No warranty
The package is provided "as is", without warranty of any kind. To the
maximum extent permitted by law, the rights holder disclaims all
liability arising from its use.
## 4. Termination
This license ends automatically if you breach it. On termination you
must delete your copies of the package.
## 5. Governing law
This license is governed by and construed in accordance with the laws
of Sweden, without regard to its conflict-of-laws principles. Any
dispute arising out of or in connection with this license — including
questions about its existence, validity, interpretation, or
termination — is subject to the exclusive jurisdiction of the Swedish
courts, with Gothenburg District Court (Göteborgs tingsrätt) as the
court of first instance. The rights holder may nevertheless seek
injunctive or other interim relief to protect its intellectual
property rights in any court of competent jurisdiction.
Nothing in this section deprives a consumer of the protection of
mandatory consumer-protection law of the country where they reside,
including the right to bring proceedings in, and to be sued only in,
the courts for the place where they reside.
LicenseRef-Proprietary — proprietary: all rights reserved
All rights reserved. There is no public license text for this id: the terms
are whatever the rights holder grants you when the package is provided to
you. Absent such terms, you have no rights beyond running the package
through the channel it was provided by.
API Reference
Root functions
Query a performance counter by key. A counter that has not produced a sample yet reports 0. An unknown key raises.
Register the per-frame update handler. callback is called as callback(dt) where dt is seconds since the previous invocation. At most one handler is active per app — calling again replaces the previous one. Pass nil to clear it.
Register the termination handler. It runs once, when the app is being terminated — its own terminate, a manager's terminate_app, an ancestor's termination cascading down, or the automatic reap of an idle service app — but not when the app crashes or the workstation itself exits. The handler gets a short, bounded time budget to flush state; suspending calls are allowed and the budget keeps counting while they wait, and when it runs out teardown proceeds regardless. It cannot cancel the termination. When a termination cascades through a subtree, the order in which the tree's handlers run is unspecified. Registering a handler does not keep an idle service app alive. At most one handler is active per app — calling again replaces the previous one. Pass nil to clear it.
Wait until every handle in the array is ready — a barrier across a mixed batch of loadable assets (Image, AudioAsset, SceneAsset, CubemapAsset, Font, Shader, DataHandle), Bytes (registration starts materializing file-backed bytes), and request/response handles (Response, Op, Stat, ListFetch, BoolFetch, BytesFetch, DocEntry, DocQuery). Returns nothing; chain a single handle with its own :ready() instead. Raises on the first failure. A never-arriving remote target waits indefinitely.
Construct a 2D vector: vec2() is (0,0), vec2(s) splats, vec2(x, y) is component-wise.
Construct a 3D vector: vec3() is (0,0,0), vec3(s) splats, vec3(x, y) sets z=0, vec3(x, y, z) is component-wise.
Construct a ray from an origin and a direction (normalized on construction; raises if the direction is zero).
Root fields
#namespacedatumhue.time — Timers
Monotonic time measurement and scheduled callbacks.
Monotonic seconds elapsed since the app started.
Wall-clock microseconds since the Unix epoch.
Break a Unix-microseconds timestamp (as from time.unix_micros) into its UTC calendar fields. Pair with the fields and time.unix_micros to build relative or formatted time in the app's own locale. Raises if the timestamp is out of the representable range.
Build a Unix-microseconds timestamp (UTC) from calendar fields — the inverse of time.calendar. Only year is required; month/day default to 1 and hour/minute/second to 0. Raises on an invalid date or time (e.g. month 13, Feb 30, hour 24).
Whole days since 1970-01-01 UTC for a unix-microseconds instant (as returned by unix_micros). Floor division: a day boundary is midnight UTC, and instants before the epoch give negative indices.
Schedule a one-shot callback to fire after secs seconds. The callback receives the frame delta (seconds) as its argument — timers fire on frame ticks, so it is the same dt an update callback sees, ready to integrate motion. 0 fires on the next frame tick — the way to defer work out of the current callback. Returns a timer; call :unsubscribe() to cancel it before it fires, or pause/resume and query it.
Schedule a repeating callback to fire every secs seconds. The callback receives the frame delta (seconds) as its argument — timers fire on frame ticks, so it is the same dt an update callback sees, ready to integrate motion. An interval of 0 fires once every frame — the frame hook for a library, leaving the app's single datumhue.on_update slot free. Returns a timer; call :unsubscribe() to stop it, or pause/resume and query it.
Animate a value from from to to over duration seconds, delivering the eased in-between value to on_update once per frame (frame ticks, like a timer); the final delivery is exactly to, then on_finish runs. from and to must be the same type. Returns a timer: :unsubscribe() cancels it (no further deliveries, on_finish never runs), and pause/resume/elapsed/remaining work as on any timer. Colors blend perceptually (Oklab, like Color:lerp).
Pause the calling code for secs seconds of engine time — the same per-frame clock that drives timers — then continue. The wait resolves on frame ticks, so the actual pause rounds up to the frame. 0 returns at once.
Pause the calling code for frames frame ticks, then continue. 1 resumes on the next frame; 0 returns at once.
#namespacedatumhue.noise — Scalar Noise Fields
Perlin / simplex / cellular / fractal noise samplers.
Create a Perlin-noise sampler. Options: seed (integer), frequency (number).
Create a simplex-noise sampler. Options: seed (integer), frequency (number).
Create a smooth simplex-noise sampler. Options: seed (integer), frequency (number).
Create a value-noise sampler. Options: seed (integer), frequency (number).
Create a cubic value-noise sampler. Options: seed (integer), frequency (number).
Create a cellular (Worley) noise sampler. Options: seed, frequency, distance, return_type, jitter.
Create a fractal (fBm / ridged / ping-pong) sampler.
NoiseSampler handle: at#namespacedatumhue.audio — Audio
Procedural synthesis, SFX, music, sample playback, and named buses.
.master_volume: number read/write — Global linear playback volume (1.0 = unchanged). Applies live to playing instances; the audible volume is master x bus x instance.
Synthesize and play a tone.
Play a sequence of synthesized notes (array of note tables).
Play a pattern-sequenced track.
Play a loaded audio asset.
Get or create the app's named bus — the same name always returns the same bus. Route playing audio into it with the constructors' bus option field.
#namespacedatumhue.font — Fonts
The bundled brand face, the app's default face, and per-script glyph fallback. Load custom faces with bytes:font().
.default: Font read/write — The app's default font face: every text surface that doesn't pin its ownfontuses it. Assigning re-applies to the app's text; reading returns the resolved face (the brand font when unset).
A handle to the bundled brand font face. Use it to reference or reset the app default: datumhue.font.default = datumhue.font.builtin().
Register font as a covering face for an ISO-15924 script, so text in that script renders through it instead of missing-glyph boxes when the active face lacks those glyphs. The engine shapes and falls back per run automatically — you never split text by script. Raises if font is not a loaded font face.
#namespacedatumhue.i18n — Internationalization
Localized text via Mozilla Fluent (.ftl) catalogs. t(key, vars) builds a reactive message usable anywhere a text string is; the active catalog is the locale property (an Ftl from bytes:ftl()).
.locale: Ftl read/write — The app's active localization catalog. Assign anFtl(frombytes:ftl()) to switch locale — reactive, theme-style inherit/pin: child apps follow unless they set their own. Reading returns the active catalog (the built-in until set).
Build a reactive localized message for catalog key, interpolating vars (string or number values; a number also drives plural selection). Pass it as the text of a label, button, or link (or to label:update) and it re-renders on a locale change. A key missing in both the active catalog and the built-in default renders verbatim.
The embedded built-in catalog (the engine's default English chrome). Reading datumhue.i18n.locale returns this until the app sets its own.
#namespacedatumhue.input — Input
Focus-scoped keyboard, mouse, touch, gamepad readers and cursor control. Touch is a separate device from the mouse: a screen touch never moves the cursor or presses a mouse button, so the touch readers and the mouse readers can be polled side by side without double-counting a gesture.
Subscribe callback to text-producing keystrokes on the focused app; it receives the layout-resolved text (Shift / keyboard layout applied, OS auto-repeat included). Returns a subscription; call :unsubscribe() to stop. Special keys (backspace, enter, arrows) come through is_key_pressed/on_key.
Subscribe callback to key press and release on the focused app; it receives the physical key name (an input.Key) and whether the key is now pressed. Returns a subscription; call :unsubscribe() to stop.
Bind a named action to keys / mouse buttons / gamepad buttons / any screen touch; replaces any existing binding. Query it with is_action_down / is_action_pressed / is_action_released. Lets controls be remapped without rewriting input checks.
Remove a named action binding (idempotent).
Whether any input bound to the named action is currently held.
Whether any input bound to the named action was pressed since the app's previous update tick. Edges are latched per app and delivered exactly once, so a press is never dropped when a tick spans several frames.
Whether any input bound to the named action was released since the app's previous update tick. Edges are latched per app and delivered exactly once, so a release is never dropped when a tick spans several frames.
Compose a 2D movement vector and return its x and y components: each of the four named actions contributes one unit on its axis while held, the first connected gamepad adds its left stick (past a 0.25 deadzone) and d-pad, and the result is clamped to length 1. Screen convention — y grows downward, so positive_y is toward the bottom of the screen and stick/d-pad up pulls toward negative_y. Unbound action names contribute nothing.
Which device spoke last. Lets prompts and control glyphs follow the device the player is actually using, without polling every button.
Whether a key was pressed since the app's previous update tick. Edges are latched per app and delivered exactly once, so a press is never dropped when a tick spans several frames.
Whether a key was released since the app's previous update tick. Edges are latched per app and delivered exactly once, so a release is never dropped when a tick spans several frames.
Cursor position relative to the app's root container, or nil.
Whether a mouse button is held.
Whether a mouse button was pressed since the app's previous update tick. Edges are latched per app and delivered exactly once, so a press is never dropped when a tick spans several frames.
Whether a mouse button was released since the app's previous update tick. Edges are latched per app and delivered exactly once, so a release is never dropped when a tick spans several frames.
Array of the screen touches currently pressed, ordered by id. Empty when nothing touches the screen.
Whether the touch with this id is currently pressed.
Whether the touch with this id started since the app's previous update tick. Edges are latched per app and delivered exactly once, so a press is never dropped when a tick spans several frames.
Whether the touch with this id ended since the app's previous update tick (a touch the system cancels counts as ended). Edges are latched per app and delivered exactly once, so a release is never dropped when a tick spans several frames.
Position of the touch with this id relative to the app's root container, or nil when the touch isn't pressed.
Array of connected gamepad ids. An id is the pad's 1-based position in the connected list, not a stable hardware identifier — ids shift when a pad connects or disconnects, so re-enumerate rather than caching them.
Whether a gamepad button is held.
Whether a gamepad button was pressed since the app's previous update tick. Edges are latched per app and delivered exactly once, so a press is never dropped when a tick spans several frames.
Whether a gamepad button was released since the app's previous update tick. Edges are latched per app and delivered exactly once, so a release is never dropped when a tick spans several frames.
Gamepad stick vector.
Gamepad trigger value 0..1.
Rumble a gamepad's motors. A pad index with no pad connected does nothing.
Stop all rumble on a gamepad. A pad index with no pad connected does nothing.
Show or hide the cursor (applies while focused).
Lock or release the cursor (applies while focused).
Set the cursor icon by name (applies while focused).
Subscription handle: unsubscribeVec2 handle: length, length_squared, to_angle, min_element, max_element, normalize, normalize_or, try_normalize, distance_squared, signum, fract, recip, element_sum, element_product, to_array, perp, abs, floor, ceil, round, dot, distance, perp_dot, angle_to, rotate, midpoint, reflect, min, max, project_onto, reject_from, lerp, move_towards, clamp, clamp_length, is_normalized, extend, with_x, with_y, unpack#namespacedatumhue.theme — Theming
Read, apply, and reset an app's theme, and build theme-tracking colors.
The theme currently applied to the app — its own pinned theme, or the one it inherits.
Apply a theme to the app, pinning it so it no longer follows the inherited theme.
Drop the app's pinned theme so it follows the inherited theme again (its nearest themed ancestor, else the default).
A theme color token. Pass it as a UI element color to make that slot follow the active theme and repaint automatically on theme change.
The app's current value for a theme metric token — typography sizes and weights, plus spacing. Use a size token as a font_size value or a weight token as a font_weight value to drive text from the theme.
#namespacedatumhue.events — System Events
Subscribe to system / app-lifecycle events. callback receives the event's payload table — see the accepted forms for each event's shape.
Subscribe callback to a named system event. Returns a subscription; call :unsubscribe() to stop receiving the event.
- datumhue.events.on(name: "window_resized", callback: fun(e: events.WindowResized))
- datumhue.events.on(name: "window_focused", callback: fun())
- datumhue.events.on(name: "window_unfocused", callback: fun())
- datumhue.events.on(name: "scale_factor_changed", callback: fun(e: events.ScaleFactorChanged))
- datumhue.events.on(name: "zoom_changed", callback: fun(e: events.ZoomChanged))
- datumhue.events.on(name: "app_focused", callback: fun(e: events.AppEvent))
- datumhue.events.on(name: "app_unfocused", callback: fun(e: events.AppEvent))
- datumhue.events.on(name: "app_spawned", callback: fun(e: events.AppSpawned))
- datumhue.events.on(name: "app_terminated", callback: fun(e: events.AppTerminated))
- datumhue.events.on(name: "app_state_changed", callback: fun(e: events.AppStateChanged))
- datumhue.events.on(name: "app_bounds_changed", callback: fun(e: events.AppBoundsChanged))
- datumhue.events.on(name: "app_fullscreen_request", callback: fun(e: events.AppFullscreenRequest))
- datumhue.events.on(name: "app_stretch_mode_request", callback: fun(e: events.AppStretchModeRequest))
- datumhue.events.on(name: "app_design_resolution_request", callback: fun(e: events.AppDesignResolutionRequest))
- datumhue.events.on(name: "app_resize_request", callback: fun(e: events.AppResizeRequest))
- datumhue.events.on(name: "app_zoom_request", callback: fun(e: events.AppZoomRequest))
- datumhue.events.on(name: "app_frame_pressed", callback: fun(e: events.AppFramePressed))
- datumhue.events.on(name: "app_permission_request", callback: fun(e: events.AppPermissionRequest))
- datumhue.events.on(name: "connectivity", callback: fun(e: events.Connectivity))
- datumhue.events.on(name: "identity_signed_in", callback: fun(e: events.IdentitySignedIn))
- datumhue.events.on(name: "identity_refreshed", callback: fun(e: events.IdentityRefreshed))
- datumhue.events.on(name: "identity_signed_out", callback: fun())
- datumhue.events.on(name: "identity_sign_in_failed", callback: fun(e: events.IdentitySignInFailed))
- datumhue.events.on(name: "app_identity_sign_in_request", callback: fun(e: events.AppIdentitySignInRequest))
- datumhue.events.on(name: "app_identity_sign_out_request", callback: fun(e: events.AppEvent))
Subscription handle: unsubscribe#namespacedatumhue.storage — Local Storage
Local persistent key→bytes storage, scoped by app identity — private durable bytes no other app observes. For values shared with other apps or clients, with change subscriptions, see documents.
Open this app's private store. The store follows the package: the same package reaches the same data across runs, instances, and versions, and no other app can address it. Distinct labels are independent stores; omitting the label opens the default store. Raises on an empty label.
Open the store shared by every package under this app's scope (the publisher's @scope). Label semantics match open.
#namespacedatumhue.messaging — Inter-App Communication
Topic-based publish/subscribe between apps on this client (local scope) and across clients (network scope).
Publish a message. Options: topic, scope ("local"/"network"), payload. scope defaults to "local"; requires the network capability when scope is "network".
Subscribe to a topic. Options: topic, scope ("local"/"network"), callback. Returns a subscription; call :unsubscribe() to stop it. Requires the network capability when scope is "network".
network capabilityJoin a presence group on a topic. Everyone holding a handle on the same topic sees everyone else's beacons; a peer disappears from peers() when its beacons stop for ttl seconds. Beacons carry a per-handle id, not an identity — they prove liveness only.
Subscription handle: unsubscribe#namespacedatumhue.screen — Display Control
Window dimensions, fullscreen, resolution, stretch/zoom, and monitor information. Scope follows the caller: bootstrap controls the workstation window, while a regular app controls its own root panel. The request_* functions are proposals — bootstrap's apply at the end of the frame, and an app's are sent to its window manager to answer (see the app_*_request events and the wm namespace).
.keep_awake: boolean read/write — Whether this app asks the host to keep the display awake. While any running app holdstrue, the host inhibits the machine's screensaver and display sleep; the request is released when the app clears it or exits. Best-effort: where no platform inhibitor is available the value still reads back as set and nothing else changes..zoom: number read-only — Current end-user comfort zoom multiplier..width: number read-only — Drawable surface width in logical pixels — the app's own panel (the whole window for bootstrap)..height: number read-only — Drawable surface height in logical pixels — the app's own panel (the whole window for bootstrap)..stretch_mode: screen.StretchMode read-only — Current stretch mode..resolution: screen.Resolution read-only — Drawable surface resolution — the app's own panel (the whole window for bootstrap)..design_resolution: screen.DesignResolution read-only — Current design resolution.
Whether the window is in any fullscreen mode.
Enter a fullscreen mode, or pass false to exit; optional monitor index.
Request a window/container resolution.
List of connected monitors.
The monitor the window is currently on, or nil.
screenshot capabilityCapture the whole workstation window.
Request how the design canvas fits the window when their sizes differ.
Request the logical design resolution (0, 0 to clear).
Request a change to the end-user comfort zoom multiplier.
#namespacedatumhue.wm — Window Manager
Manage descendant apps: terminate, focus, bounds, weight, minimize, cursor override, frame wrapping, and permission grants.
Terminate a managed descendant app (silent no-op if already gone).
Set the caller's cursor override (effective only while it manages the focused app); nil clears.
Minimize or restore a managed app.
Set the position/size of a managed app. Omitted fields are left unchanged.
Set a managed app's layout weight.
Wrap a managed app in a decoration frame; returns the frame's root UiElement.
Change the frame insets of an already-wrapped managed app.
UiElement handle: remove, router, option, item, on_click, on_pick, on_save, on_save_source, on_copy_source, row, on_hover, on_hover_exit, on_press, on_release, on_double_click, on_focus, on_blur, on_cancel, focus, set_text_color, set_material, set_source, update, mouse_position, to_texture_coords, panel, button, open_button, save_button, copy_button, link, date_picker, time_picker, datetime_picker, color_picker, checkbox, slider, number_input, radio_group, list, table, text_input, popover, menu, label#namespacedatumhue.physics — Physics
Unified 2D/3D physics. Auto-detects 2D vs 3D mode from the host handle. Each app simulates in its own worlds: bodies, joints, queries, and gravity never interact with other apps.
.gravity: Vec3 read/write — This app's gravity vector (Y-up; default{0, -9.81, 0}). 2D bodies feel its X/Y components. Assign a vec2/vec3.
Create an additional isolated physics world. Bodies join it via add_body{world = ...}; it has its own gravity and query methods. Bodies in different worlds never interact.
Register this app's physics step handler, called once per completed simulation step with dt the fixed timestep in seconds -- the constant interval every step advances by, independent of frame rate. Steps finish before the frame's Lua callbacks run, so the handler reads post-step state; within a frame it runs after the same steps' collision callbacks and before on_update, and a frame that ran several catch-up steps calls it once per step. At most one handler is active per app -- calling again replaces the previous one. Pass nil to clear it.
Create a physics joint (fixed / revolute / prismatic) between two bodies.
Cast a ray and return the nearest body hit, or nil.
Cast a ray and return every body along it, nearest first.
Return every body whose collider overlaps the given world-space point.
Sweep a 3D collider shape along the ray and return the nearest body hit, or nil.
Vec3 handle: length, length_squared, min_element, max_element, normalize, normalize_or, try_normalize, distance_squared, signum, fract, recip, element_sum, element_product, to_array, abs, floor, ceil, round, any_orthogonal, dot, distance, angle_between, cross, midpoint, reflect, min, max, project_onto, reject_from, lerp, slerp, move_towards, clamp, clamp_length, is_normalized, truncate, with_x, with_y, with_z, unpackDrawPrimitive handle: update, remove, animate, contains, bounds, add_body, character_controller, apply_impulse, apply_angular_impulse, apply_force, apply_torque, lock_rotation, set_collision_layers, set_locked_axes, on_collision_start, on_collision_end, remove_bodySceneNode handle: update, remove, animate, play_animation, stop_animation, blend, bounds, mesh, deform, add_body, character_controller, apply_impulse, apply_angular_impulse, apply_force, apply_torque, lock_rotation, set_collision_layers, set_locked_axes, on_collision_start, on_collision_end, remove_body#namespacedatumhue.grid — Grid Algorithms
2D integer grids with pathfinding, FOV, flood-fill, cellular automata, and procedural fills.
Create a zeroed width x height grid (each dimension 1..=4096).
Create a zeroed width x height light field (each dimension 1..=4096).
Generate Voronoi hives.
The rasterized cells of a straight line from (x1,y1) to (x2,y2).
Distance between two cells.
Grid handle: get, set, fill, fill_rect, find_path, agent, slide, dijkstra, field_of_view, flood_fill, count_neighbors, automata_step, fill_noise#namespacedatumhue.random — Random Streams
Deterministic seeded random streams, for content that must replay identically from a shared seed.
Create an independent random stream from a seed. Equal seeds give equal sequences, on every platform, in every session. A stream name selects a named substream of the seed: the same seed under different names yields unrelated sequences, and the name-to-stream mapping is itself a stable contract -- one seed can feed a family of parallel streams without any hand-rolled hashing.
#namespacedatumhue.dialogue — Dialogue
A sequenced conversation queue with a typewriter reveal and choice prompts. The engine owns the queue, the reveal clock, the wrapping, and the selection; the app reads current() each frame, draws the entry in its own style, and drives the machine with advance() and select() from its own input handling — or hands a frame's input to drive().
.active: boolean read-only — Whether a line or ask is on display or queued. Apps typically suppress their movement input while true.
Queue a plain line.
Queue a line whose on_done fires when the player advances past it.
Queue a choice prompt. on_choice receives the picked choice's value when the player confirms with advance().
Drop the queue and whatever is on display; no callbacks fire.
The entry on display (promoting the next queued one when none is), or nil when the queue is idle. Custom renderers draw from this.
Move an ask entry's selection by delta, wrapping. No effect until the text is revealed, or on plain lines.
The one advance gesture: an unrevealed entry reveals fully; a revealed plain line dismisses (firing on_done); a revealed ask confirms the selection (firing on_choice with the picked value).
Attach reveal marks to the most recently queued entry, or the one on display when the queue is empty (raises when there is neither). The typewriter clock dwells at each mark's doorstep and reports each crossing; a mark the on-display reveal has already passed keeps only its crossing. clear() drops marks with their entries.
Drive the machine from input, once per frame: arrow keys and W/S (plus a pad's d-pad, hat, or left stick, one step per flick) steer an ask's cursor, and the confirm action advances — a press during the reveal lands the whole text first, never swallowing the input. Returns what happened so the app can play its own cues, or nil.
#namespacedatumhue.scene — 3D Scenes
3D scene graph: meshes, lights, cameras, raycasting.
Create a 3D scene viewport.
Scene handle: cube, sphere, plane, cylinder, capsule, torus, cone, set_skybox, set_environment, point_light, directional_light, spot_light, model, clear, remove, group, sprite, camera_relative_yaw, camera_yaw_bucket, raycast, screen_to_ray, mount#namespacedatumhue.material — Materials
PBR and unlit materials for 3D meshes.
Create a physically-based material. Lit by the scene; supports PBR texture maps, transparency, and clearcoat. Apply it via a mesh's material option or node:update.
Create an unlit material that ignores scene lighting and shows its color (and texture) at full brightness.
#namespacedatumhue.voxel — Voxels
Editable voxel volumes: palette materials, transform properties, scene-space raycasting, and bulk fills driven by the noise, grid, and image APIs.
Create a voxel volume inside scene. Cells hold 0-based palette indices, 0 = air.
Create a chunk-streamed voxel world inside scene. Chunks load nearest-first around center under the per-frame budget and unload least-recently-needed beyond unload_radius. Each chunk is a full voxel volume sharing the world's palette, lighting, and physics configuration.
Voxel handle: set, get, raycast, fill, palette, atlas, clear, count, set_material, capture, play, stop, drop_frames, remove, fill_noise, heightmap, stamp_grid, stamp_image#namespacedatumhue.particles — Particles
Particle effects: emitters spawn short-lived camera-facing quads with velocity, gravity, and size/color over life.
Create a particle emitter inside scene: camera-facing quads simulated on the CPU and drawn in one batch per emitter. Emission starts immediately.
#namespacedatumhue.shader — Shaders
Shader materials for UI panels, 2D draw primitives, and 3D meshes. Create once and apply anywhere; the correct backend is auto-detected.
Create a shader of the given type (the required field that selects the shader kind). color1/color2 are Colors; color2 is optional only for "solid" and required for every other type.
#namespacedatumhue.app — Application Management
Spawn, terminate, and introspect apps in the process tree.
.offline: boolean read-only — True while no deployment connection is up.
Spawn a child app from inline code, a loaded package, or a resolved package_ref. Returns the child's App handle immediately.
Terminate this app. Cascades to all descendants.
The root app's App handle. Returns this app's own handle when called from the root.
Whether this app currently has focus. Always false for service apps.
Whether this app was spawned as a service. Fixed at spawn time and immutable.
Whether this app currently holds the named capability. An unknown name raises.
Request a capability from the parent window manager. Returns true immediately if already held, otherwise the parent's verdict — the parent may prompt the user before answering. An unknown name raises.
The launcher-resolved session identifier. Available to every app in the tree.
Startup errors collected by the launcher, as a 1-based string array (empty if none). Only the root app sees the real list; child apps get an empty table.
#namespacedatumhue.documents — Shared Key-Value State
Shared key-value documents with change subscriptions. scope = "local" (default) shares an in-process store among every app on this client; scope = "network" replicates with other clients and requires the network capability. Access sharing goes through grants minted by doc:grant — attenuable capabilities whose encoded form travels over any channel. For private durable bytes no other app can observe, see storage.
.identity: string read-only — This user's durable document identity key — what others pass astoin grants and what appears asmeta.authoron this user's writes. Stable across restarts.
Create a new document. opts.scope defaults to "local". The returned handle is writable; share access with doc:grant. Requires the network capability when scope = "network".
Open (creating if needed) a document keyed by name. Two callers passing the same name and scope share the document. The returned handle is always writable.
Open the document a grant authorizes. The scope is decided by the grant; requires the network capability when the grant is network-scoped. opts narrows the synced window — reads and subscriptions outside it see nothing.
Open the communal document derived from an identity. Every user holds intrinsic write authority over their own section; reading another user's section requires a grant from them. Requires the identity and network capabilities.
Parse and verify an encoded grant. Raises when the string is not a grant or its authorization does not verify.
Document handle: collection, counter, set, delete, get, query_prefix, delete_prefix, subscribe, grant, close#namespacedatumhue.bytes — Opaque Bytes
Unified opaque byte payloads. Every API that produces bytes returns a Bytes; every API that consumes bytes accepts one. The call form lifts a string; the json / kdl / msgpack constructors encode a value. All decoding lives on the returned handle.
KDL-encode value (must be a table) and return the resulting bytes.
MessagePack-encode value and return the resulting bytes.
#namespacedatumhue.math — Math
Scalar math helpers, plus the vec2 and vec3 constructors.
Linear interpolation from a to b by t (clamped 0..1).
Clamp v to the range [lo, hi].
Remap v from [in_lo, in_hi] to [out_lo, out_hi]. A zero-width input range maps to out_lo.
Smooth Hermite interpolation: 0 at or below edge0, 1 at or above edge1, with a smooth 3t^2 - 2t^3 ramp between (zero slope at both edges). A zero-width edge range degenerates to a hard step at edge0.
#namespacedatumhue.math.vec2 — Vec2 Constructors
Construct 2D vectors.
Unit vector pointing at radians from the +X axis.
Vec2 from a {x, y} array (the inverse of vec2:to_array).
Vec2 handle: length, length_squared, to_angle, min_element, max_element, normalize, normalize_or, try_normalize, distance_squared, signum, fract, recip, element_sum, element_product, to_array, perp, abs, floor, ceil, round, dot, distance, perp_dot, angle_to, rotate, midpoint, reflect, min, max, project_onto, reject_from, lerp, move_towards, clamp, clamp_length, is_normalized, extend, with_x, with_y, unpack#namespacedatumhue.math.vec3 — Vec3 Constructors
Construct 3D vectors.
.ZERO: Vec3 read-only — The zero vector(0, 0, 0)..ONE: Vec3 read-only —(1, 1, 1)..X: Vec3 read-only — The +X axis(1, 0, 0)..Y: Vec3 read-only — The +Y axis(0, 1, 0)..Z: Vec3 read-only — The +Z axis(0, 0, 1)..NEG_X: Vec3 read-only — The -X axis(-1, 0, 0)..NEG_Y: Vec3 read-only — The -Y axis(0, -1, 0)..NEG_Z: Vec3 read-only — The -Z axis(0, 0, -1).
Vec3 from an {x, y, z} array (the inverse of vec3:to_array).
Vec3 handle: length, length_squared, min_element, max_element, normalize, normalize_or, try_normalize, distance_squared, signum, fract, recip, element_sum, element_product, to_array, abs, floor, ceil, round, any_orthogonal, dot, distance, angle_between, cross, midpoint, reflect, min, max, project_onto, reject_from, lerp, slerp, move_towards, clamp, clamp_length, is_normalized, truncate, with_x, with_y, with_z, unpack#namespacedatumhue.math.quat — Quaternions
Construct rotation quaternions (angles in radians).
Rotation from XYZ Euler angles (radians).
Rotation of angle radians around axis (normalized). Raises if axis is zero-length / non-finite.
Rotation of angle radians around the X axis.
Rotation of angle radians around the Y axis.
Rotation of angle radians around the Z axis.
Minimal rotation taking unit vector from to unit to. Raises if either is zero-length / non-finite.
Rotation about v's direction by |v| radians (the scaled-axis form). Zero v yields the identity rotation.
Quat from a raw {x, y, z, w} array (not re-normalized; the inverse of quat:to_array).
Quat handle: normalize, normalize_or, try_normalize, inverse, conjugate, dot, length, angle_between, slerp, lerp, is_normalized, to_euler, to_scaled_axis, to_array, to_axis_angle, unpack#namespacedatumhue.color — Colors
Construct sRGB colors. Call datumhue.color(...) with a hex string or r,g,b[,a] numbers, or use the named constructors.
Color from sRGB r, g, b, a (0..1).
Color from hue (degrees — the CSS convention; hue is the API's one angle not in radians), saturation, lightness.
Color from Oklab lightness, a, b (perceptual space).
Color from Oklch lightness, chroma, hue (degrees — the CSS convention, as in color.hsl; perceptual space).
Color from an {r, g, b[, a]} array (sRGB, 0..1; the inverse of color:to_array).
#namespacedatumhue.image — Images
Raster images and drawable framebuffers (top-left origin, Y-down). Create a blank image with new, then draw by recording a picture() and replaying it with image:apply — each replay rewrites pixels. For vector shapes that persist as live handles across frames (center-origin, Y-up), use draw.
Create a blank drawable image. Options: {width, height}. Display via image:mount().
Create an empty, reusable drawing command list. Record draw operations into it, then replay it onto an image with image:apply(picture). Build it once and apply every frame; call picture:reset() to rebuild dynamic content.
The built-in bitmap font as an Atlas (8x13 cells, 16x6 grid; cell index = ASCII code - 32). Hand it to picture:set_font(atlas), or draw individual glyphs as sprites with atlas:sprite(code - 32).
Image handle: get, apply, cursor, remove, mount, atlas, sprite, ready, encode_png, update, to_cubemap#namespacedatumhue.draw — Retained 2D Drawing
Retained-mode 2D vector graphics. Primitives persist across frames; center-origin, Y-up. Positions take a vec3 (z controls depth, -1000..1000) or a vec2 — without an explicit z, primitives auto-stack in creation order (later on top), and an explicit z is authoritative. Colors use Color values. For raster pixels — recorded pictures replayed onto an image's buffer (top-left origin, Y-down) — use image.
Create a draw canvas (render target). Options: width, height, background (Color that fills before each frame; omit for transparent), pixel_perfect (default false).
Create a detached text span. Attach via the spans array in canvas:text() or prim:update(). Options: text, color (Color), font_size.
Measure the rendered size of text in the draw font, using the same text shaping — and the same size, weight, and face defaults — the renderer uses.
DrawCanvas handle: rect, circle, ellipse, line, polygon, rrect, arc, text, sprite, image, tilemap, clear, remove, resize, set_camera, enable_pan_zoom, disable_pan_zoom, screen_to_world, world_to_screen, group, body, path, point_query, point_query_all, mount, chart, chartsDrawPrimitive handle: update, remove, animate, contains, bounds, add_body, character_controller, apply_impulse, apply_angular_impulse, apply_force, apply_torque, lock_rotation, set_collision_layers, set_locked_axes, on_collision_start, on_collision_end, remove_body#namespacedatumhue.chart.scale — Chart Scales
Construct shared scales (data → pixels / data → color) for chart marks. A scale exists independently of any plot area; multiple marks share one scale so they stay aligned under pan / zoom.
Construct a linear numeric scale.
Construct a log scale (same numeric-scale fields as linear).
Construct a categorical (band) scale.
Construct a time scale. Domain values are f64 epoch-milliseconds.
Construct a numeric → color ramp.
Construct a discrete category → color map.
#namespacedatumhue.ui — User Interface
The root content area — the entry point for building UI. Element constructors are methods on the UiElement handle it returns; layout and styling follow the shared NodeStyle option fields.
.root: UiElement read-only — The app's root content area — the parent for top-level UI. Build on it with the constructor methods, e.g.ui.root:panel{...}.
UiElement handle: remove, router, option, item, on_click, on_pick, on_save, on_save_source, on_copy_source, row, on_hover, on_hover_exit, on_press, on_release, on_double_click, on_focus, on_blur, on_cancel, focus, set_text_color, set_material, set_source, update, mouse_position, to_texture_coords, panel, button, open_button, save_button, copy_button, link, date_picker, time_picker, datetime_picker, color_picker, checkbox, slider, number_input, radio_group, list, table, text_input, popover, menu, label#namespacedatumhue.debug.input — Debug Input
Synthetic keyboard, pointer, and touch input for development: injected keys, buttons, and touches enter the same input state and event streams real ones do, so focus routing and every input read behave identically -- except click-gated file-access widgets and links, which ignore synthetic clicks. Available when running from local source; a packed archive run needs the run command's opt-in flag, and other launch modes never allow it.
Set a key's state as if pressed or released. The key stays held until released.
Press a key now and release it next frame: one clean press-release to every consumer.
Move the pointer to a window position in logical pixels (the frame input.mouse_position reads back).
Press a mouse button at the current pointer position and release it next frame. Defaults to the left button. File-access widgets and links ignore synthetic clicks.
Set a touch point's state at a window position in logical pixels: down = true starts the touch with this id, or moves it when already down; down = false ends it (a no-op when not down). The event flows through the same touch pipeline real contacts do, so the input readers see it from the next frame on.
#namespacedatumhue.identity — Identity
OIDC sign-in: start sign-in/sign-out and read the signed-in identity's claims.
Start OIDC sign-in. Required issuer; optional prompt, login_hint. The scopes requested are the issuer's configured ones; a caller cannot widen them. Outcomes arrive via datumhue.events.
Sign out the current identity. Outcome arrives via datumhue.events.
Whether an identity is currently signed in.
identity capabilitySigned-in subject id, or nil.
identity capabilityIssuer of the current identity, or nil.
identity capabilityEmail claim of the current identity, or nil.
identity capabilityName claim of the current identity, or nil.
identity capabilityEvery claim of the current identity's ID token as a table, custom claims such as groups included; arrays become sequences and nested objects tables. Nil when signed out; a session restored at start-up carries only sub and iss until identity_refreshed fires.
#namespacedatumhue.packages — Package Catalog
Browse the packages the client knows about. Reads return whatever the client has at the moment of the call and the catalog stays current automatically.
Array of PackageRef userdata for every visible catalog entry.
Array of PackageRef userdata matching a text / tag filter.
Look up a single entry by exact @scope/name; raises when no entry matches.
Every published version of a @scope/name, newest first; empty when the name is unknown to the catalog.
packages capabilityArray of PackageRef userdata for every installed package, sorted by namespace then name. Each ref reflects the version actually installed, which may be older than the catalog's latest. Reads local state, so it works offline.
One row per connected package registry, sorted by namespace. Empty while no registry has been reached (e.g. offline).
Register a callback fired whenever a catalog entry is added or updated. The callback receives a change table with kind, namespace, and package. Returns a subscription; call :unsubscribe() to stop receiving changes.
packages capabilityRegister a callback fired whenever the installed-package library changes. Returns a subscription; call :unsubscribe() to stop receiving changes.
Register a callback fired whenever a connected registry's reachability flips (see registries). Returns a subscription; call :unsubscribe() to stop receiving changes.
PackageRef handle: scope, publisher, namespace, version, kind, content_type, description, author, icon, size, is_sealed, is_service, requires, capabilities, monetization, license, tags, screenshots, readme, load, installed_version, install, uninstallSubscription handle: unsubscribe#namespacedatumhue.commerce — Commerce
Buyer-only paid-package ownership. Requires the commerce capability. Ownership is per-name and perpetual; entitlements verify offline.
commerce capabilityWhether the signed-in user owns package. Verifies a cached entitlement offline; on a cache miss does a best-effort online refresh first. Returns false when signed out. Raises when the check itself cannot complete.
commerce capabilityEvery paid package the signed-in user owns on this device, as Entitlement handles. Empty when signed out or nothing is owned. Raises when the listing cannot complete.
commerce capabilityBuy package for the signed-in user, returning the granted Entitlement. Shows a runtime confirmation, opens the hosted checkout page in a browser, then resolves once payment completes and the entitlement is granted. The charge is non-refundable. Raises if declined, signed out, already pending, or payment does not complete in time.
#handleNoiseSampler
A configured noise sampler returned by the datumhue.noise.* constructors.
Sample the noise field. Accepts a vec2, a vec3, or numeric coordinates (x, y) / (x, y, z).
#handleAudio
A playing audio instance returned by the datumhue.audio.* constructors.
.position: number | nil read-only — Current playback position in seconds, ornilif not playing..playing: boolean read-only —truewhile the instance is actively producing sound;falseonce paused, finished, or stopped..volume: number read/write — The instance's own linear gain (1.0= unchanged); the audible volume is master x bus x instance..pitch: number | nil read/write — Playback rate multiplier, clamped to 0.25..4 — resampling, so rate and pitch move together (2.0 plays an octave up at double speed). Applies live to the playing instance;nilonce the instance is gone.
Stop playback and release the instance.
Pause playback (resume with :resume()).
Resume a paused instance.
Fade the playback rate linearly to pitch (clamped to 0.25..4) over seconds; a non-positive seconds applies it at once, and assigning pitch cancels an active fade.
#handleAudioBus
A named per-app gain stage returned by datumhue.audio.bus; every instance routed to it via the bus option field rides its volume live.
.volume: number read/write — Bus gain, clamped to 0..1 (starts at 1.0). Applies live to every routed instance; the audible volume is master x bus x instance.
Fade the bus gain linearly to volume (clamped to 0..1) over seconds; a non-positive seconds applies it at once, and assigning volume cancels an active fade.
#handleStorage
A local key→bytes store opened by the datumhue.storage constructors. Handles comparing equal address the same physical store. A handle names the store rather than holding it open — it pins no file, connection, or other scarce resource, so drop handles freely and open as many as needed.
Write value (a Bytes handle) under key. The write starts immediately; :ready() observes completion or failure.
Look up key. The result's value materializes as the stored bytes, or nil when the key is absent.
#handleGrid
A 2D integer grid with pathfinding, FOV, flood-fill, cellular automata, and procedural fills. Cells are 0-based, addressed as (x, y) = (column, row) with a top-left origin and Y increasing downward — the vertical mirror of TileMap's bottom-left Y-up frame, so copying cells into a tilemap flips the row: ty = rows - 1 - gy.
.width: integer read-only — Grid width in cells..height: integer read-only — Grid height in cells.
Cell value at (x, y), or nil when out of bounds.
Set cell (x, y) to value; no-op when out of bounds.
Set every cell to value.
Fill a rectangle with value; no-op when w or h is non-positive.
A* path from (x1,y1) to (x2,y2), or nil if unreachable.
Create a PathAgent starting at the given position: a mover that owns the walk-the-waypoints bookkeeping against this grid (or any grid passed to its methods later).
Move a w x h axis-aligned box centered at (x, y) by (dx, dy), sliding against cells whose value is in solid: the x move applies and clamps first, then the y move — the classic tile character controller. Units are cells (1.0 = one cell); a clamped box stops flush on the cell face. Cells outside the grid are open, and a box already overlapping a solid cell collides only with cells it newly enters. Returns the final center.
A new Grid of distance scores from weighted sources (-1 unreachable).
Visible cells from (x,y).
8-connected flood fill from (x,y).
Count of the 8 neighbours whose value is in match.
Advance one cellular-automata generation in place.
Bucket a noise sampler into integer cell values.
#handleLightField
A 2D scalar field of poured lights over grid cells: each pour writes a radial linear falloff and cells keep the maximum of everything poured onto them, so overlapping lights never sum past the brightest source. Cells are 0-based, addressed as (x, y) = (column, row) with a top-left origin and Y increasing downward, the same frame as Grid.
.width: integer read-only — Field width in cells..height: integer read-only — Field height in cells.
Pour a light centered at (x, y), which may be fractional: every cell within range takes the larger of its value and strength falling off linearly to zero at range.
The brightest pour reaching cell (x, y); 0 where nothing reaches or out of bounds.
Zero every cell.
#handlePathAgent
A grid mover that owns the walk-the-waypoints bookkeeping: pathing to a target, waypoint acceptance including the final waypoint, motion carry-over, and repath cadence. Positions are continuous cell coordinates (a cell center is x + 0.5). Methods that path take the Grid explicitly, so a mutated grid is read live and one agent can move across grid swaps.
.x: number read-only — Position in cells (a cell center is x + 0.5)..y: number read-only — Position in cells (a cell center is y + 0.5)..speed: number read/write — Movement speed in cells per second; writable, so per-frame speed changes (sprint, slow, status effects) need no new agent.
Path toward cell (x, y) on the grid, repathing immediately (and afterward on the agent's repath cadence, when one was configured).
Move along the current path for dt seconds and return the position and status. With no target, the agent stays put.
The per-frame driving loop as one call: retarget to cell (tx, ty) only when it differs from the current goal, advance for dt seconds, and return the step. When the position moved more than 1/16 of a cell since the previous drive — another hand teleported the agent — the goal is dropped first so the walk rebuilds from the new position.
Drop the target and path; the agent stays where it is.
Place the agent at (x, y) and drop the path; the target, when set, repaths on the next advance.
The cell the agent is currently walking toward, or nil when it has no path.
#handleDocCollection
An append-only view over one key prefix of a document: subscribed before it backfills and deduplicated by key. Up to max distinct entries reach on_add exactly once each -- backfill, live window, and your own adds included. Entries past max still sync and are counted by count(); they just fire no callback.
Append a value under a fresh key and return the new entry's id — the same id on_add's meta carries and ack takes. Your own on_add sees the entry exactly once, like everyone else's.
Anonymously acknowledge an entry, by the id on_add's meta carried. The entry's author learns through its on_ack that the entry has a reader — nothing identifies which reader, and the receipt carries no proof. Fire-and-forget: delivery is best-effort, like messaging.
Distinct entries observed so far -- including entries past the collection's max, which count here without reaching on_add.
Stop listening and drop the collection's bookkeeping. Idempotent.
#handleDocCounter
A grow-only distributed counter over one key prefix of a document: each writer overwrites one slot entry holding its own count, reconciled across backfill and the live window, so the value converges without double counting and the document carries one entry per writer rather than one per increment.
.value: integer read-only — The reconciled count.
Add one, visible to every holder of the same prefix. Counts are kept per writer: two sessions writing as the same identity share a slot, so their simultaneous increments can collapse into one.
Set, replace, or clear (pass nil) the change callback; fired with the new value on every counted increment, yours included.
Stop listening and drop the counter's bookkeeping. Idempotent.
#handlePresence
Membership in one presence group: publish beacons, read the roster of peers seen within the ttl. Peers on the same client and across the network fold into the same roster.
Broadcast a beacon carrying payload (a small value; its encoded form is bounded to 256 bytes). Publish again within the ttl to stay listed; the latest payload replaces the previous one.
The peers seen within the ttl, ordered by id. The caller's own handle is never listed.
Leave the group and drop the roster. Idempotent; publish and peers on a stopped handle raise.
#handleRng
An independent seeded random stream. The same seed produces the same sequence on every platform, and separate handles never disturb each other -- the property shared-seed content generation needs and math.random cannot give.
The next number in the stream, in [0, 1).
The next integer in the stream, in [lo, hi] inclusive. Raises when lo > hi.
True with probability p (one draw). p at or below 0 is never true; at or above 1, always.
One element of the list (one draw). Raises when the list is empty.
One element of the list, chosen with probability proportional to its weight (one draw). weights parallels the list one to one; zero-weight entries are never chosen. Raises when the list is empty, the lengths differ, a weight is negative or not finite, or every weight is zero.
Shuffle the list in place (Fisher-Yates, one draw per element past the first) and return the same table.
A new independent stream seeded from this one (three draws). Forking lets one shared seed split into shared and local streams that never disturb each other.
A shuffled copy of the list; the list itself is untouched. Same draw count as shuffle (one per element past the first), so swapping a call between the two never moves a shared stream. The safe choice for shared vocabulary tables, where an in-place shuffle would silently reorder every later draw.
n distinct elements drawn without replacement (exactly n draws); the list itself is untouched. Raises when n is negative or exceeds the list length.
#handleBag
A shuffle-bag over positions 1 to n: every position is dealt exactly once per lap, and the bag reshuffles between laps -- draws without repeats until the pool is spent, then a fresh lap. A lap's last deal may equal the next lap's first.
The next position of the current lap, starting a fresh shuffled lap when the last one is spent.
How many positions the current lap still holds; 0 means the next draw starts a fresh lap.
#handlePermissionRequest
A capability a descendant app asked for, delivered as the request field on the app_permission_request event payload. Answer it now with :grant() / :deny(), or stash it and answer on a later frame (e.g. when the user picks Allow or Deny). Dropping every reference to it without answering denies the request — promptly when the handler returns without keeping it, but only eventually when a kept reference is released later, so a deferring handler should answer explicitly. A request kept unanswered leaves the requester suspended; it is denied when the keeping app terminates.
.app: App read-only — The app that made the request..permission: app.Permission read-only — The requested capability..reason: string | nil read-only — The justification the requester supplied, or nil when none was given.
Approve the request. The grant is narrowed against the answering app's own holdings — a manager cannot grant a capability it does not itself hold. Raises when the answering app cannot manage the requester, or when the request was already answered.
Refuse the request. Raises when the answering app cannot manage the requester, or when the request was already answered.
#handleScene
A 3D scene viewport returned by datumhue.scene.new.
.camera: SceneCamera read/write — The scene's camera sub-handle. Assign a table of{pos, rotation, fov}to configure it in one step; it cannot be removed..ambient: SceneAmbient read/write — The scene's ambient-light sub-handle. Assign a table of{color, brightness}to configure it in one step; it cannot be removed..bloom: SceneBloom | nil read/write — The scene's bloom sub-handle, or nil when bloom is off. Assign a table of{intensity, threshold}to enable/configure it, or nil to disable..fog: SceneFog | nil read/write — The scene's distance-fog sub-handle, or nil when fog is off. Assign a table of{color, near, far}to enable/configure it, or nil to disable..vignette: SceneVignette | nil read/write — The scene's vignette sub-handle, or nil when off. Assign a table of{intensity, radius, smoothness, roundness, edge_compensation, center, color}to enable/configure it, or nil to disable..lens_distortion: SceneLensDistortion | nil read/write — The scene's lens-distortion sub-handle, or nil when off. Assign a table of{intensity, scale, multiplier, center, edge_curvature}to enable/configure it, or nil to disable..chromatic_aberration: SceneChromaticAberration | nil read/write — The scene's chromatic-aberration sub-handle, or nil when off. Assign a table of{intensity, max_samples, color_lut}to enable/configure it, or nil to disable..grid: SceneGrid | nil read/write — The scene's reference grid, or nil when off. Assign a table of{x_axis_color, z_axis_color, minor_line_color, major_line_color, fadeout_distance, dot_fadeout_strength, scale}to enable/configure it, or nil to disable..tonemapping: scene.Tonemapping read/write — Tonemapping operator name (e.g. "aces", "agx", "tony_mcmapface")..exposure: number | nil read/write — Camera exposure (EV100)..atmosphere: boolean read/write — Whether the procedural atmosphere is enabled..background: Color | nil read/write — Solid background (clear) color, or nil for a transparent background. Assign a color or nil.
Spawn a cube mesh. Options: pos, rotation, scale, color, material.
Spawn a sphere mesh. Options: pos, rotation, scale, color, material.
Spawn a plane mesh. Options: pos, rotation, scale, color, material, subdivisions.
Spawn a cylinder mesh. Options: pos, rotation, scale, color, material.
Spawn a capsule mesh. Options: pos, rotation, scale, color, material.
Spawn a torus mesh. Options: pos, rotation, scale, color, material.
Spawn a cone mesh. Options: pos, rotation, scale, color, material.
Set the scene's skybox to a cubemap (from bytes:cubemap() or image_asset:to_cubemap()), or nil to remove it.
Set image-based environment lighting from prefiltered cubemaps, or nil to remove it. Requires diffuse and specular cubemaps; raises if either is missing.
Spawn a point light. Options: pos, color, intensity, range, shadows.
Spawn a directional light. Options: direction, color, intensity, shadows.
Spawn a spot light. Options: pos, direction, color, intensity, range, shadows, inner_angle, outer_angle.
Add an external glTF / GLB scene.
Despawn every node in the scene — meshes, models, lights, voxels, and groups (a parented child goes with its parent). The camera and its settings (background, ambient, fog, bloom, tonemapping, exposure) are kept.
Despawn the scene wholesale — every node, the camera and its settings, and any UI element mounting it — freeing its render target. Methods on the handle raise afterwards; other handles still holding the texture (a shader channel, a material) keep the last rendered frame.
Group existing nodes under a new empty frame node and return it; moving or reparenting the frame moves the whole group (a shared transform frame).
Spawn a billboarded sprite: a textured quad the engine reorients to face the scene camera every frame. Pass either source (a Sprite from image:sprite/atlas:sprite) or image (a whole Image). The returned SceneNode carries the sprite-only properties billboard, size_mode, size, pivot, alpha, cutoff, color, flip_x, flip_y, shaded, and cell, alongside the usual node pos/visible/parent. While billboard is not none the engine owns the node's rotation. Animate the atlas cell by binding a sprite animator, or by setting cell each frame.
The horizontal angle (radians, -pi..pi) from node to the scene camera, in world space. Combine with the character's own facing to choose a directional sprite row.
The horizontal camera angle from node quantized to one of n evenly-spaced buckets (0..n-1, bucket 0 centered on the camera being straight ahead in +Z). Map the bucket to a directional sprite row, e.g. an 8-way character.
Cast a ray into the scene. Returns the nearest hit, or nil if the ray missed.
Convert viewport pixel coordinates to a world-space ray, or nil if off-screen. x/y are pixels in the scene's rendered image — origin top-left, Y-down, spanning the scene's own pixel resolution. No display-fit adjustment is applied: when the mounted element scales or letterboxes the scene, convert the cursor into image pixels first.
Mount this render target as a UI image element. Returns the new UiElement, or nil if the app has no UI.
#handleSceneNode
A node (mesh / light / model) within a 3D scene.
.velocity: Vec3 | nil read/write — Linear velocity (assign a vec2/vec3), or nil if the handle has no physics body..angular_velocity: Vec3 | nil read/write — Angular velocity per axis (radians/sec), or nil if the handle has no physics body. Assign a vec3..pos: Vec3 | nil read/write — Transform position (assign a vec2/vec3), updating visual + physics state. nil if the entity is gone..rotation: Quat | nil read/write — Rotation quaternion, or nil if the entity is gone. Assign a quat; updates visual + physics state..restitution: number | nil read/write — Bounciness, 0..1; nil if the handle has no physics body. Assign a number to change it at runtime..friction: number | nil read/write — Surface friction coefficient; nil if the handle has no physics body. Assign a number to change it at runtime..ccd: boolean read/write — Whether this body, when moving fast, also sweeps moving (kinematic and dynamic) bodies so it never tunnels through them; fast bodies always sweep static geometry. Assign a boolean to toggle..visible: boolean read/write — Whether the node is shown. Setting false hides it and every node parented under it; true defers to the parent's visibility..parent: SceneNode | nil read/write — The node this node is parented to (its transform composes with the parent's), or nil if it sits at the scene root. Assign a node to reparent (the local transform is kept), or nil to detach; reparenting across scenes raises..billboard: scene.BillboardMode read/write — Camera-facing mode. While notnone, the engine owns the node's rotation..size_mode: scene.SpriteSizeMode read/write — Whethersizeis world units or constant on-screen pixels..size: Vec2 read/write — Quad extent (units persize_mode)..pivot: Vec2 read/write — Normalized anchor in 0..1; the node position sits at this point..alpha: scene.SpriteAlphaMode read/write — Transparency handling..cutoff: number read/write — Alpha-test threshold for thecutoutmode (0..1)..color: Color read/write — Base color. On sprites, a tint multiplied with the texture; on mesh primitives, the material's base color (a shared material is cloned to this node on first write, so siblings keep theirs)..flip_x: boolean read/write — Mirror horizontally..flip_y: boolean read/write — Mirror vertically..shaded: boolean read/write — Lit by scene lights when true; full-bright (unlit) when false..cell: integer read/write — Current atlas cell index (0-based, row-major). Raises if the sprite draws a whole image.
Update node transform / material / light properties.
Despawn this node.
Tween the node's transform (position, rotation, scale), color, and opacity over duration seconds with the given easing curve.
Play one of the model's animation clips, crossfading from whatever is currently playing. Clips are loaded on first use; only meaningful on nodes created with scene:model.
Stop all animation playback on the node, freezing it at the current pose.
Play several of the model's clips at once at the given weights (a blend tree), replacing whatever was playing. Each clip loops. Only meaningful on nodes created with scene:model.
The mesh's local-space bounding box (intrinsic dimensions, before the node's transform). nil for nodes without a direct mesh (loaded models, lights, groups).
This node's mutable mesh. Only primitive mesh nodes (cube, sphere, plane, ...) qualify; raises for voxel volumes, glTF models, lights, cameras, and groups.
Attach an engine-ticked deformer to this node's mesh — displacement runs every frame without Lua involvement. One deformer per node: a second call replaces the parameters but keeps the original base geometry. mesh:update with new positions re-bases an attached deformer. Raycast picking follows the displaced mesh; physics colliders do not.
Attach a physics body. 2D vs 3D is inferred from the host handle. See physics.BodyOptions for the shape + material fields; omitted size fields default from the host's visual geometry.
Attach a kinematic character controller to this body and return its CharacterController handle. The body must be kinematic. The controller solves walking/sliding/stair-stepping geometry only — gravity, jump, input, and camera stay in your code. Raises if the body is missing, not kinematic, or already has a controller (remove() to rebind).
Apply an instantaneous, mass-correct velocity change (Δv = impulse / mass). Accepts vec2 or vec3.
Apply an instantaneous, inertia-correct spin change. A number for 2D bodies (about Z), a vec3 for 3D.
Set the continuous force applied every step until changed. Pass a zero vector to stop. Accepts vec2 or vec3.
Set the continuous torque applied every step until changed. Pass zero to stop. A number for 2D bodies (about Z), a vec3 for 3D.
Lock or unlock rotation.
Replace this body's collision filtering at runtime (e.g. switching teams).
Lock or unlock individual translation/rotation axes at runtime. The 2D in-plane constraints are always preserved.
Set, replace, or clear (pass nil) the handler fired when this body starts colliding.
Set, replace, or clear (pass nil) the handler fired when this body stops colliding.
Remove all physics from this handle.
#handleSceneCamera
The scene's camera. Read/write .pos, .rotation, .fov (radians); aim it with :look_at; tween it with :animate.
Aim the camera at a world-space point. up defaults to world Y.
Tween the camera's position, orientation, and field of view over duration seconds with the given easing curve.
Switch the camera to an orthographic projection. height is the world-space vertical extent visible; the horizontal extent follows the scene's aspect ratio.
Switch the camera to a perspective projection with the given vertical field of view (radians).
#handleSceneAmbient
The scene's ambient lighting. Read/write .color and .brightness.
.color: Color read/write — Ambient light color..brightness: number read/write — Ambient light brightness.
#handleSceneBloom
The scene's bloom post-processing. Read/write .intensity and .threshold.
.intensity: number read/write — Bloom intensity..threshold: number read/write — Luminance threshold below which pixels do not bloom.
#handleSceneFog
The scene's distance fog. Read/write .color, .near, .far.
.color: Color read/write — Fog color..near: number read/write — Distance at which fog begins..far: number read/write — Distance at which fog is fully opaque.
#handleSceneVignette
The scene's vignette post-processing. Read/write its fields, or set scene.vignette = nil to disable.
.intensity: number read/write — Strength of the corner darkening (0 = none, 1 = black corners)..radius: number read/write — Size of the clear center region; larger values shrink the vignette..smoothness: number read/write — Softness of the edge between the clear and dark areas..roundness: number read/write — Shape of the vignette; 1 is a circle, lower is more rectangular..edge_compensation: number read/write — Compensates the darkening toward the screen edges..center: Vec2 read/write — Vignette center in UV space (0..1; screen center is (0.5, 0.5))..color: Color read/write — Color the corners fade toward.
#handleSceneLensDistortion
The scene's lens-distortion post-processing. Read/write its fields, or set scene.lens_distortion = nil to disable.
.intensity: number read/write — Distortion strength; positive bulges (barrel), negative pinches (pincushion)..scale: number read/write — Zoom applied to the distorted image; raise to crop edge artifacts..multiplier: Vec2 read/write — Per-axis distortion scale; (1, 1) is uniform, a 0 axis disables that axis..center: Vec2 read/write — Distortion center in UV space (0..1; screen center is (0.5, 0.5))..edge_curvature: number read/write — Additional curvature applied toward the screen edges.
#handleSceneChromaticAberration
The scene's chromatic-aberration post-processing. Read/write its fields, or set scene.chromatic_aberration = nil to disable.
.intensity: number read/write — Streak size at object edges, as a fraction of the window size..max_samples: integer read/write — Cap on texture samples; higher is smoother but slower..color_lut: Image | nil read/write — Color-gradient lookup image; nil uses the default red/green/blue split.
#handleSceneGrid
The scene's reference grid. Read/write its colors and spacing, or set scene.grid = nil to remove it.
.x_axis_color: Color read/write — Color of the line along the world X axis..z_axis_color: Color read/write — Color of the line along the world Z axis..minor_line_color: Color read/write — Color of the minor grid lines..major_line_color: Color read/write — Color of the major grid lines (every 10th line)..fadeout_distance: number read/write — Distance from the camera at which the grid fades out..dot_fadeout_strength: number read/write — How quickly the grid fades with distance..scale: number read/write — Spacing between grid lines; a smaller value spaces them farther apart.
#handleMaterial
A material handle returned by datumhue.material.*. Materials are 3D-only: 2D and UI surfaces take a Shader instead.
.metallic: number read/write — Metallic factor (0..1)..roughness: number read/write — Perceptual roughness (0..1)..color: Color read/write — Base color..emissive: Color read/write — Emissive color..reflectance: number read/write — Specular reflectance at normal incidence (0..1)..ior: number read/write — Index of refraction..clearcoat: number read/write — Clearcoat layer strength (0..1)..clearcoat_roughness: number read/write — Clearcoat layer perceptual roughness (0..1)..double_sided: boolean read/write — Render both faces (disables back-face culling)..alpha_mode: material.AlphaMode read/write — Transparency mode. Themaskmode uses a 0.5 cutoff; set a custom cutoff viamaterial:update.
Set or clear the base-color texture from a source (pixel / draw canvas / scene).
Batch-update the material's fields; omitted options are left unchanged.
#handleVoxel
An editable voxel volume returned by datumhue.voxel.new. Cells are 0-based (x, y, z) integer coordinates; each cell holds a 0-based palette index, where 0 is air (empty).
.pos: Vec3 read/write — World-space position of the volume's minimum corner..rotation: Quat read/write — Rotation quaternion about the minimum corner..scale: Vec3 read/write — Per-axis scale on top of the cell size..width: integer read-only — Cells along x..height: integer read-only — Cells along y..depth: integer read-only — Cells along z..cell_size: number read-only — World units per cell..physics: boolean read/write — Whether the volume carries a static physics body whose collider matches its cells, following every edit. Assign a boolean to toggle.
Set the material index at a cell.
Read the material index at a cell.
Raycast through the volume with a scene-space ray (the volume's position, rotation, and cell size are accounted for). Returns the hit cell, or nil.
Fill an axis-aligned box of cells.
Define a palette material: color, render class, and — with an atlas bound — static per-face or animated block textures.
Bind a tile atlas to the volume; palette entries then pick tiles with texture / frames. The atlas image must carry readable pixel data. Binding replaces any previous atlas; an opaque-section material override takes precedence over block textures.
Reset every cell to air.
Count cells holding material, or every non-air cell when omitted.
Set the material for the volume's solid surfaces (a standard Material or a Shader). Transparent and emissive faces keep their built-in rendering.
Snapshot the current cells as an animation frame; returns the frame's 1-based index for play.
Play captured frames as a flip-book, swapping the volume's cells on the fps clock; the first frame applies immediately. Cell edits made while playing are overwritten at the next swap.
Stop playback, leaving the currently shown frame's cells in place.
Discard every captured frame (and stop any playback), freeing their memory; the current cells stay.
Despawn the volume and its meshes.
Set material wherever 3D noise meets the threshold over the region — one engine-side pass, no per-cell calls. Cells below the threshold are untouched.
Fill each (x, z) column with material up to the height the source yields — terrain from noise, a grid, or a heightmap image in one engine-side pass.
Write a 2D grid into one slice of the volume — dungeon layouts, automata output, or path maps become geometry in one pass.
Write image pixels into one slice by nearest-palette-color match; pixels with alpha below 0.5 write air. The image reads upright on wall planes.
#handleVoxelWorld
A chunk-streamed voxel world returned by datumhue.voxel.world. Move center to stream chunks in and out; chunk content arrives through the on_chunk_load callback.
.center: Vec3 read/write — Streaming focus in the world's local space; assign to move it (e.g. follow the camera) and stream chunks in and out..chunk_size: integer read-only — Cells per chunk axis..cell_size: number read-only — World units per cell..loaded: integer read-only — Number of chunks loaded right now.
Define a palette material shared by every chunk: updates the world palette and every loaded chunk; chunks loading later inherit it.
The loaded chunk at integer grid coordinates coords, or nil while it isn't loaded.
Despawn the world and every loaded chunk.
#handleVoxelChunk
A loaded chunk of a streamed voxel world. chunk.voxel is the chunk's volume — edit it with the full Voxel surface; read/write snapshot and restore the cells for persistence.
#handleEmitter
A particle emitter returned by datumhue.particles.emitter. Configuration scalars are read-write properties; pause/resume gate continuous emission.
.rate: number read/write — Particles spawned per second while emitting. Assign to retune..lifetime: number read/write — Seconds each newly spawned particle lives. Assign to retune..gravity: Vec3 read/write — Constant acceleration applied to every particle. Assign a vec3..pos: Vec3 read/write — Emitter position in the scene. Assign a vec3 to move it..count: integer read-only — Number of live particles right now.
Resume continuous emission.
Pause continuous emission; live particles finish their lives.
Spawn n particles at once (bounded by max_particles).
Despawn the emitter and its particles.
#handleSpriteClips
A reusable sprite-animation clip-set built by Atlas:clips. Immutable: bind it to any number of sprites with clips:bind(sprite), each getting an independent Animator playhead.
Attach an animator to a sprite (a 2D draw sprite or a 3D scene:sprite) and return its Animator. Adopts this clip-set's atlas onto the sprite; raises if the target is not a sprite. Bind again (here or with another clip-set) to replace it. Call animator:play(name) to start — binding does not auto-play.
The clip names in this set.
#handleAnimator
A sprite-animation playhead bound to one sprite by SpriteClips:bind. Drives the sprite's atlas cell over time; play/queue/stop/pause/resume/seek control it, on_finish/on_marker observe it, and clip/frame/playing/speed/looping read or set its state.
.clip: string | nil read-only — The currently playing clip name, or nil before the firstplay..frame: integer read-only — Current 1-based frame position within the active clip (position 1 = its first frame), or 0 before the firstplay..playing: boolean read-only — Whether the playhead is advancing..speed: number read/write — Playback rate multiplier; negative plays in reverse, 0 holds..looping: boolean read/write — Whether the current clip loops (per-instance override).
Hard-cut to clip name from its first frame, clearing the queue. Options: {speed?, looping?}. Raises if the clip is unknown.
Append clip name to play once the current non-looping clip (and any already queued) finishes. Raises if the clip is unknown, or if the chain already ends in a forever-looping clip.
Stop playback and clear the queue, leaving the current frame shown.
Freeze the playhead; resume continues from here.
Resume a paused animator without resetting the playhead.
Jump to a 1-based frame position within the current clip (clamped). Position 1 is the clip's first frame — a position in the clip's frames list, not an atlas-cell value.
Set, replace, or clear (pass nil) the callback fired once when a non-looping clip reaches its terminal end. Receives the animator and the finished clip name.
#handleMesh
A primitive node's mutable mesh, returned by node:mesh(). Reads are snapshot copies as flat arrays; update writes one validated, atomic batch. Raycast picking follows edits; physics colliders are inferred from the primitive kind at body creation and do not.
.vertex_count: integer read-only — Number of vertices in the mesh..index_count: integer read-only — Number of triangle indices; 0 for a non-indexed mesh.
Vertex positions as flat x,y,z triplets in node-local space.
Vertex normals as flat x,y,z triplets; empty when the mesh has none.
Texture coordinates as flat u,v pairs; empty when the mesh has none.
Vertex colors as flat r,g,b,a quads; empty when the mesh has none.
1-based triangle indices; empty for a non-indexed mesh.
Apply one batch of attribute writes atomically: the whole batch is validated against the post-update state (one agreed vertex count, indices in range, budget respected) and nothing is written on any violation. Triggers a single GPU re-upload.
#handleDeformer
An active mesh deformer returned by node:deform. Parameters are read-write properties; remove detaches it and restores the base geometry.
.kind: scene.DeformKind read-only — The deformation shape..amplitude: number read/write — Peak displacement in local units. Culling bounds follow on write..frequency: number read/write — Spatial frequency in cycles per local unit..speed: number read/write — Animation speed in radians per second..direction: Vec2 read/write — Travel / bend direction in the local XZ plane..origin: Vec2 read/write — Ripple center in the local XZ plane..seed: integer read/write — Noise seed; same seed, same field.
Detach the deformer and restore the mesh's base geometry and bounds.
#handleShader
A compiled shader returned by datumhue.shader.new or bytes:shader, applicable to draw canvases, UI panels, or scene materials.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Update a preset shader's parameters. Changes propagate to every primitive using this shader. Custom shaders raise — their state changes through set / set_channel.
Update or clear the shader's texture source. source is a pixel canvas, draw canvas, or scene handle, or nil to clear.
Write a declared uniform on a custom shader; every primitive using it updates. Raises on an undeclared name or a value not matching the declared type.
Bind or clear a custom shader's channel texture. index is 1-based and maps down by one to the 0-based uniform: set_channel(1) writes dh_channel0, set_channel(2) writes dh_channel1, up to set_channel(4) for dh_channel3. source is a pixel canvas, draw canvas, or scene handle, or nil to restore white.
Recompile a custom shader from new source, keeping its declared uniforms, current values, and channels. On a compile error the previous program keeps rendering and the error raises with the failing source line.
Remove the shader. A custom shader's slot under the per-app limit is freed; anything the shader is applied to keeps its current look. Methods on the handle raise afterwards.
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
#handleThemedColor
A theme color token from datumhue.theme.token(...). Pass it as a UI element color to make that slot follow the active theme; it repaints automatically when the theme changes.
#handleTheme
A theme — a built-in (datumhue.theme.default_dark() / default_light()), one loaded from a file (file:read():theme()), or the app's current theme (datumhue.theme.current()). Pass it to datumhue.theme.pin(...). Compare two themes with ==; .name is a display label, not an identity.
.name: string read-only — Display label for the theme (e.g."Everforest Dark"). For comparison, use==on the handle, not this string.
#handleApp
An opaque app identity. Comparable with ==, usable as a table key, and stable across the app's lifetime. spawn returns the child's handle immediately; a package_ref child starts running only once its package is delivered. If the delivery or the spawn fails, the child never runs: the handle reports not alive and app_terminated fires for it, the same terminal signal as for a running app's exit.
.name: string | nil read-only — The name the app was spawned with. Nil once the app is no longer running.
True if the handle refers to the current app (works even on dead handles).
True if the app referenced by the handle is still running.
True if the handle is the direct parent of the current app.
True if the handle is any proper ancestor of the current app.
True if the current app may manage the referenced app (ancestry or self).
#handlePackage
The runtime representation of a loaded package — the running app's own bundle (datumhue.package) or another package loaded via dir:load_package / file:load_package.
.name: string read-only — The manifest name.
The manifest version.
The manifest kind.
The refinement tag on asset packs, or nil on apps and libraries.
Mirrors the manifest sealed flag.
#handleDocument
A shared key-value document; operations route automatically to the matching backend. Network keys are /-separated paths: writing a key supersedes everything under it, so a parent write replaces the subtree.
.scope: documents.Scope read-only — Which backend stores the document..can_write: boolean read-only — Whether this handle may write, or is read-only.
An append-only view over the prefix: subscribed before it backfills and deduplicated by key, so each distinct entry reaches on_add exactly once until max entries have been delivered. Without a schema, values pass through unvalidated and treating them as untrusted stays the caller's job.
A grow-only distributed counter over the prefix, reconciled across backfill and the live window so nothing double-counts.
Write a key-value pair. Errors when doc.can_write is false. The write starts immediately; :ready() observes completion or failure.
Remove a key. Errors when doc.can_write is false. After delete, get returns nil and query_prefix omits the key; subscribers are notified with a nil value.
Read a key. The result's value and meta are both nil when the key isn't present (or was deleted).
Query every key under the prefix, newest per key; the result's entries is {[key] = {value, meta}}.
Remove the whole key subtree. On network documents this physically reclaims the entries everywhere; subscribers are notified with nil values. Errors when doc.can_write is false.
Watch for changes. callback(key, value, meta); value is nil when the key was deleted. Pass "" to match every write.
Mint a grant from this handle's authority. With to, the grant is bound to that identity; without it, anyone holding the encoded string holds its authority. A write grant always carries read alongside. Raises on any attempted widening.
Close this handle. Other handles and subscriptions on the same document keep working.
#handleDocumentGrant
Authorization over a document. Holding the handle (or its encoded string) is the access.
.scope: documents.Scope read-only — Which backend the grant authorizes over..mode: documents.GrantMode read-only — The access level the grant confers..prefix: string read-only — The key subtree the grant is narrowed to; empty for the whole document..expires_at: integer | nil read-only — Expiry as a UNIX-microseconds timestamp; nil when the grant never expires..bearer: boolean read-only — Whether holding the encoded string alone confers the authority.
An attenuated grant chained from this one, without opening the document. Only this grant's receiver can delegate (bearer grants: anyone holding them). Raises on any attempted widening.
The transport form, for any channel (messaging, a file, a QR code). Opaque; decode with documents.decode_grant.
#handleSubscription
A live subscription returned by doc:subscribe, events.on, messaging.subscribe, packages.on_change, input.on_text/on_key, or scale:on_change. Call :unsubscribe() to stop it. Recurring streams return a subscription; per-entity handlers are set, replaced, or cleared (pass nil) via their on_* method.
Stop the subscription. Idempotent.
#handleTimer
A scheduled timer from time.after / time.every, or a running time.tween. Unsubscribe it, pause/resume it, or query its elapsed / remaining time.
Stop the timer and release it. Idempotent.
Pause the timer; it stops advancing until resumed. No-op if it already fired.
Resume a paused timer. No-op if it already fired.
Seconds elapsed in the current cycle (resets each fire for a repeating timer); 0 once fired/unsubscribed.
Seconds until the next fire; 0 once fired/unsubscribed.
#handleCalendar
The UTC calendar breakdown of an instant, from datumhue.time.calendar. Read-only fields; tostring yields ISO-8601 UTC.
.year: integer read-only — Full year (e.g. 2026)..month: integer read-only — Month, 1-12..day: integer read-only — Day of the month, 1-31..hour: integer read-only — Hour, 0-23..minute: integer read-only — Minute, 0-59..second: integer read-only — Second, 0-59..weekday: integer read-only — Day of the week, 1=Monday..7=Sunday (ISO 8601)..yearday: integer read-only — Day of the year, 1-366.
#handleBytes
An opaque byte payload. Every byte-producing API returns one; every byte-consuming API accepts one. Decoders raise on failure. Decoders producing a plain value suspend until the bytes are materialised, while decoders producing an asset handle return at once and are awaited with :ready() — except theme() and ftl(), which suspend and return their handle, because the theme must be registered and the catalog parsed before the returned handle is usable.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Materialize file-backed bytes now, then return the same handle for chaining. In-memory bytes return at once; decoders on a materialized handle skip the filesystem round-trip. Raises if the read fails.
Materialise the bytes as a Lua string. UTF-8 is not validated; bytes are returned verbatim.
Parse the bytes as JSON. Raises on parse failure.
Parse the bytes as KDL. Raises on parse failure or non-UTF-8 input.
Parse the bytes as MessagePack. Raises on parse failure.
Decode the bytes as CSV into a DataHandle. Raises on parse failure.
Decode the bytes as Parquet into a DataHandle. Raises on parse failure.
Compile the bytes as a fragment shader (WGSL, or WESL extended syntax) defining fn dh_fragment(uv: vec2<f32>) -> vec4<f32>. The source may read dh.time, dh.resolution, and dh.mouse (auto-fed per shaded primitive), the declared u.<name> uniforms, and the dh_channel0..3 textures. Raises with the failing source line on a compile error. The returned shader applies anywhere a preset does. Limits per shader: 64 KiB source, 16 uniforms, 4 channels; up to 32 live custom shaders per app.
Parse the bytes as a one-chapter book: markdown prose with kdl element islands, or a KDL page (chosen by content). A byte payload has no backing directory, so scripts never run and images render as their alt text; include raises. Raises on parse or validation errors.
Decode the bytes as an image (PNG, JPEG, WebP, etc.); format auto-detected. Raises if the format is unsupported or the bytes cannot be decoded.
Decode the bytes as a KTX2 cubemap (6 faces) for use as a skybox or environment map. Raises if the bytes are not a KTX2 cubemap; to build one from a vertically-stacked 2D image use image_asset:to_cubemap() instead.
Decode the bytes as audio (OGG, MP3, WAV, FLAC). Format is detected at play time, so invalid bytes surface as a play-time error.
Decode the bytes as a font face (TrueType or OpenType). Set it as a text surface's font, as datumhue.font.default, or a fallback via datumhue.font.fallback. Raises at decode if the bytes are not a TrueType/OpenType font (WOFF/WOFF2 are not supported); the returned face is ready at once.
Decode the bytes as a 3D scene (glTF). The loader resolves dependent buffers and textures against a source path, so the bytes must come from a file or directory grant — decode via file:read():scene() or dir:read(rel):scene(). Bytes lifted from a string raise.
Decode the bytes as a theme and register it. Returns a Theme handle for the registered theme.
#handleDataHandle
Opaque tabular-data handle produced by bytes:csv() and bytes:parquet(). Methods read the data lazily or return a derived handle; re-reading never re-runs cached work.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Row count, computed from the source — see len() on in-memory batches.
Create a lazy SQL query rooted on this handle (bound as the table data). params is an array bound to ? placeholders; a Dir or File handle binds the next ? to a location inside its grant; another DataHandle binds the next ? as a table to select from or join. The query runs and caches on first read.
Streaming row iterator (for _, row in h:rows() do). One row table per step; each step suspends until the data is available. A full pass over the source with a table allocated per row — for rendering, bind the handle to a chart mark instead of iterating.
Streaming batch iterator yielding DataBatch values that expose columns directly via DataColumn — no per-row Lua table allocation. Each step suspends until the data is available.
Describe the columns, their types, nullability, and metadata.
Create a viewport-aware, downsampled projection of this handle.
Serialize the handle's contents as CSV, returning a Bytes userdata.
Serialize the handle's contents as Parquet, returning a Bytes userdata.
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
#handleDataBatch
A batch of rows produced by h:batches(). Exposes columns directly via DataColumn — no per-row Lua table allocation.
Row count in this batch.
Array of column names (respects projection).
Column accessor; errors if the name isn't in the batch (or in the projected subset).
#handleDataColumn
A typed column inside a DataBatch. Direct cell access without materializing the column as a Lua array.
.name: string read-only — Column name.
Cell value at 1-indexed row i. binary / fixed_binary columns return a Bytes handle. One call per cell — spot reads are fine; for rendering, bind the data to a chart mark instead of walking cells.
Row count for this column.
The column's data type name.
#handleSchema
Returned by DataHandle:schema(). Lookup by name is O(1); fields and metadata resolve lazily.
Column count.
Iterator: for i, f in s:fields() do yields (integer, Field) pairs.
Schema-level metadata as a string->string table.
A single schema-level metadata entry.
#handleField
Returned by Schema:field(...) and yielded by Schema:fields().
.name: string read-only — Column name.
Canonical data type name — the same vocabulary as DataColumn:dtype.
Whether the column may contain null values.
1-based position in the parent schema.
Per-field metadata as a string->string table.
A single per-field metadata entry.
#handleDataView
Viewport-aware downsampled projection of a DataHandle. Created by h:view(options).
.pixel_width: integer read/write — X-axis downsampling pixel budget. Assigning re-downsamples..pixel_height: integer read/write — Y-axis downsampling pixel budget. Assigning re-downsamples.
Update the viewport range; omitted keys are left unchanged.
Effective viewport range {x_min, x_max, y_min, y_max} with resolved auto values. Raises if the view was removed.
Remove the DataView and free its resources.
#handleVec2
A 2D vector (Y-up, center-origin). Construct with datumhue.math.vec2(x, y). #v is v:length(), not a component count.
.x: number read-only — X component..y: number read-only — Y component.
Magnitude.
Squared magnitude (no sqrt).
Angle in radians from the +X axis.
Smallest component.
Largest component.
Unit vector. Raises if v is zero-length / non-finite; use normalize_or or try_normalize for a fallback.
Unit vector, or fallback if v is zero-length / non-finite.
Sum of the components.
Product of the components.
Components as a {x, y} array.
Linear interpolation toward o by t; t outside 0..1 extrapolates past the endpoints (not clamped).
Whether the vector is unit length.
Return the x and y components as two values.
#handleVec3
A 3D vector (Y-up). Construct with datumhue.math.vec3(x, y, z). #v is v:length(), not a component count.
.x: number read-only — X component..y: number read-only — Y component..z: number read-only — Z component.
Magnitude.
Squared magnitude (no sqrt).
Smallest component.
Largest component.
Unit vector. Raises if v is zero-length / non-finite; use normalize_or or try_normalize for a fallback.
Unit vector, or fallback if v is zero-length / non-finite.
Sum of the components.
Product of the components.
Components as a {x, y, z} array.
Linear interpolation toward o by t; t outside 0..1 extrapolates past the endpoints (not clamped).
Whether the vector is unit length.
Return the x, y and z components as three values.
#handleQuat
A rotation quaternion (radians). Construct with datumhue.math.quat.from_euler(...) etc.
.x: number read-only — X component..y: number read-only — Y component..z: number read-only — Z component..w: number read-only — W (scalar) component.
Unit-length quaternion. Raises if q is zero-length / non-finite; use normalize_or or try_normalize for a fallback.
Unit-length quaternion, or fallback if q is zero-length / non-finite.
Unit-length quaternion, or nil if q is zero-length / non-finite.
Magnitude.
Normalized linear interpolation toward o by t, along the shorter arc. t outside 0..1 extrapolates, and the result is renormalized so it stays a unit rotation.
Whether the quaternion is unit length.
Scaled-axis form (axis * angle) — the inverse of quat.from_scaled_axis.
Components as an {x, y, z, w} array.
Return the rotation axis (unit vec3) and angle (radians) as two values.
Return the x, y, z and w components as four values.
#handleRay
A 3D ray: an origin and a normalized direction. Construct with datumhue.math.ray(origin, direction); returned by scene:screen_to_ray and accepted by the raycast APIs.
The point distance units along the ray from its origin.
#handleColor
An sRGB color. Construct with datumhue.color(...); read components via .r/.g/.b/.a.
.r: number read-only — Red channel (0..1)..g: number read-only — Green channel (0..1)..b: number read-only — Blue channel (0..1)..a: number read-only — Alpha channel (0..1).
Perceptual interpolation toward o by t (clamped 0..1), blended in Oklab so midtones stay vivid. Use mix for a different space.
Interpolate toward o by t (clamped 0..1) in the given color space.
Perceptually darken by amount (subtracted from Oklab lightness, 0..1); alpha unchanged.
Perceptually lighten by amount (added to Oklab lightness, 0..1); alpha unchanged.
Rotate the hue by degrees — hue is the API's one angle in degrees (the CSS convention), matching color.hsl; every other angle is radians.
Components as an {r, g, b, a} array (sRGB, 0..1).
Hue (degrees), saturation and lightness as three values.
Oklch lightness, chroma and hue (degrees) as three values.
Return the r, g, b and a components as four values.
#handleImage
A raster image (pixel data + a renderable texture). Created blank by datumhue.image.new, or produced by bytes:image(), file:read():image(), dir:read(rel):image(), datumhue.screen.screenshot(), and pkg:icon(). Mount via image:mount(opts), read pixels with image:get, persist with image:encode_png. Draw by recording a datumhue.image.picture() and replaying it with image:apply(picture).
.filter: image.Filter read/write — Texture sampling mode wherever the image is drawn. Setnearestto keep pixel art crisp; the default smooths..width: integer read-only — Width in pixels. Raises if the image isn't loaded yet — await it withimage:ready()ordatumhue.ready{...}first..height: integer read-only — Height in pixels. Raises if the image isn't loaded yet — await it withimage:ready()ordatumhue.ready{...}first..state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Read a pixel. Returns a color (.r/.g/.b/.a, 0-1), or nil when out of bounds. Raises if the image isn't loaded yet — await it with image:ready() or datumhue.ready{...} first.
Replay one or more pictures onto this image in a single atomic pass: extract the pixels once, replay every recorded op in order, write back once. Accepts a single picture or an array of them (drawn in order, sharing draw state). The image is never seen partially updated. Raises if this image, or any image a picture blits from, isn't loaded yet — await it with image:ready() or datumhue.ready{...} first; nothing is drawn when it raises.
Cursor position in this image's own pixel coordinates (Y-down from the top-left), accounting for how the image is displayed — correct even when it is letterboxed or scaled inside a larger element. Nil when the cursor isn't over a mounted, unoccluded instance. The fit-aware companion to elem:mouse_position(); mount the image first.
Despawn the image and any UI element mounting it, freeing its texture. Methods on the handle raise afterwards; copies already made from it (a sprite, a material texture, a shader channel) keep rendering.
Mount this render target as a UI image element. Returns the new UiElement, or nil if the app has no UI.
Build a uniform grid Atlas over this image. Options: {tile_size, columns, rows, padding?, offset?}. Index cells from 0, row-major, with atlas:sprite(index).
Build a reusable Sprite appearance from this whole image. Options: {color?, flip_x?, flip_y?, size?}. Draw it with canvas:sprite(sprite, {pos = ...}).
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
Re-encode the pixel buffer as PNG bytes ready for file:write or a save_button's on_save_source.
Decode bytes (PNG, JPEG, WebP, etc.) into the existing pixel buffer in place; the texture refreshes on the next frame. The decoded image must match the image's existing dimensions and pixel format — mismatches raise. Returns the same handle for chaining.
Build a cubemap for a skybox or environment map from this image, which must be six square faces stacked vertically (height == 6 * width, in +X, -X, +Y, -Y, +Z, -Z order). The original image is unchanged. For prefiltered image-based-lighting maps, load a KTX2 cubemap via bytes:cubemap() instead.
#handleAudioAsset
An audio source asset produced by bytes:audio() or file:read():audio() and played via datumhue.audio.play. An in-memory decode is ready at once; a file or remote read loads in the background — :ready() waits for the bytes to land.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
#handleSceneAsset
A glTF/GLB scene asset produced by bytes:scene() or file:read():scene() and placed via scene:model. :ready() waits until the scene and all its buffers and textures have loaded.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
#handleCubemapAsset
A cubemap texture asset produced by bytes:cubemap() or image:to_cubemap() and consumed by scene:set_skybox / scene:set_environment. :ready() waits until the texture loads.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
#handleFont
A font face produced by bytes:font() or datumhue.font.builtin(). Set it as a text surface's font, as datumhue.font.default, or a fallback via datumhue.font.fallback. The decode validates the bytes before returning, so the face is ready at once.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
Wait until this asset is fully loaded, then return it for chaining. An in-memory asset returns at once; one still loading (a file read or remote fetch) yields the coroutine until it lands. A load failure raises; format errors on playable assets still surface at use time.
Vertical metrics of this face at size — a number (px) or a unit string like "1.5rem"/"50vw" — from the same text shaping the renderer uses. Use them to align text baselines with other drawing, or to size rows before laying text out.
#handleFtl
A parsed Fluent (.ftl) localization catalog for one locale, produced by bytes:ftl() and held like a font asset. Set it as datumhue.i18n.locale to activate; :locale() is its BCP-47 code.
The BCP-47 locale code the catalog declares via its -datumhue-locale term.
#handleMessage
A reactive localized message from datumhue.i18n.t(...). Set it as a label, button, or link text (or via label:update) to follow the active locale; :get() resolves it to a plain string now.
Resolve the message against the app's active catalog right now (a snapshot). A missing key returns the key verbatim.
#handlePicture
A reusable, canvas-agnostic command list created by datumhue.image.picture. Record drawing with the methods below, then replay it onto an Image with canvas:apply(picture) — the whole picture lands in one atomic pass. Record once and apply every frame; rebuild dynamic content with reset.
Set a pixel. No-op if out of bounds when applied.
Clear to transparent black (all zeros). Also resets the clip rectangle.
Draw a line.
Draw a filled circle.
Draw an oval outline (bounding box).
Draw a filled oval (bounding box).
Draw a rectangle outline.
Draw a filled rectangle between two corners (inclusive, in either order). Clips to bounds.
Draw a rounded-rectangle outline.
Draw a filled rounded rectangle.
Draw a triangle outline.
Draw a filled triangle.
Draw a polygon outline from a flat point array {x1,y1, x2,y2, ...}.
Draw a filled polygon from a flat point array {x1,y1, x2,y2, ...}.
Draw an arc outline. Angles in radians.
Draw a filled arc (pie slice). Angles in radians.
Replace all connected same-color pixels from (x,y). Bypasses camera and clip.
Box blur over a rectangular region.
Draw text. Returns the x position after the last character (sized by the current font). Supports newlines and the active font, clip, and camera.
Size of the text for the picture's current font. Bitmap fonts have a fixed line height (the cell height), so height depends only on the number of lines.
Word-wrap the text to fit max_width pixels for the picture's current font, breaking at spaces (a word longer than the width hard-splits) and honoring embedded newlines. Print the returned lines one per row; every line's measured width fits within max_width. The same breaking rule the dialogue box uses.
Restore the camera offset and clip rectangle. No-op if the stack is empty.
Shift the drawing origin by (dx, dy). Additive with the current camera offset.
Set the camera offset absolutely. Call with no arguments to reset to (0, 0).
Set the clipping rectangle in screen space. Call with no arguments to reset.
Set a 4x4 fill-pattern bitmask (16-bit). Call with no arguments to reset to solid.
Set a custom bitmap font from an Atlas (cell index = ASCII code - 32). char_w overrides the per-glyph advance, defaulting to the atlas cell width. Pass nil for the atlas to reset to the built-in font.
Copy pixels from another Image (or the target itself) onto the canvas at apply time. blend_mode defaults to copy.
#handleDrawCanvas
A vector-drawing surface returned by datumhue.draw.new. Hand it to canvas:mount(opts) to mount as a UI element, or call the primitive constructors to add drawables.
.filter: image.Filter read/write — Texture sampling mode for this canvas wherever it is drawn (a UI mount,canvas:image, a shader channel). Setnearestto keep pixel art crisp when the canvas is scaled up; the default smooths.
Draw a rectangle. Options: pos (vec3 bottom-left), width, height, color (Color), filled (default true), stroke_width (default 2), material.
Draw a circle. Options: pos (vec3 center), radius, color, filled, stroke_width, material.
Draw an ellipse. Options: pos (vec3 center), rx, ry, color, filled, stroke_width, material.
Draw a line. Options: from, to (vec3), color, width (default 1).
Draw a polygon. Options: points (array of vec2, min 3), color, z (number), filled, stroke_width, material. Supports convex and simple concave polygons.
Draw a rounded rectangle. Options: pos (vec3 bottom-left), width, height, radius (default 10), color, filled, stroke_width, material.
Draw an arc (pie slice when filled, curve when stroked). Options: pos (vec3 center), radius, start_angle, end_angle (radians, 0 = +x axis, counterclockwise), color, filled, stroke_width, material.
Draw text. Options: pos (vec3), text, font_size (default 16), color, max_width (enables wrapping), align (left/center/right/justified), linebreak (word/character/word_or_character/none), spans (rich-text array).
Draw a Sprite (from image:sprite / atlas:sprite) onto this canvas as a textured quad (composes with physics, shaders, and picking). Options: {pos?, rotation?, scale?, size?, material?}. size overrides the sprite's own. The returned primitive's cell property repoints the atlas cell to animate. To draw a whole image or another render target, use canvas:image.
Draw a whole Image, or another DrawCanvas / Scene render target, onto this canvas as a textured quad (picture-in-picture). Options: {pos?, rotation?, scale?, size?, material?}. size sets the rendered extent; it defaults to the source's own size (a render target uses its logical size).
Create a tilemap that draws onto this canvas from an Atlas. Options: {columns, rows} (grid dimensions in cells). Returns a TileMap; set cells with tilemap:set(x, y, index) (atlas cell index) and read them with tilemap:get(x, y).
Remove all primitives on the canvas (hand-drawn shapes, text, images, and chart marks/axes/legends). Plot areas survive but their rendered content is gone.
Despawn the canvas and everything it hosts — primitives, chart content, plot areas, and any UI element mounting it — freeing its render target. Methods on the handle raise afterwards; other handles still holding the texture (a shader channel, a material) keep the last rendered frame.
Resize the canvas render texture. Existing primitives survive (world-space coordinates); any UI element displaying the canvas picks up the new size.
Set the 2D camera. Options (all optional): pos (vec2 center), zoom (>1 in, <1 out).
Drive this canvas's camera from the mouse: drag to pan, scroll to zoom (around the cursor). Replaces any prior pan/zoom config on the canvas; call disable_pan_zoom to stop.
Stop driving this canvas's camera from the mouse.
Convert element-relative cursor pixels (Y-down) to draw coordinates (Y-up), accounting for camera pan/zoom and the canvas's on-screen placement (letterbox / scale). Returns nil if the canvas is invalid.
Convert draw coordinates to element-relative screen pixels, accounting for camera pan/zoom and the canvas's on-screen placement (letterbox / scale).
Group primitives so they move, hide, and fade as a unit. Nested groups supported. group:remove() removes the group and every primitive in it.
Spawn an invisible physics-only body on the canvas. Returns a handle with all physics methods but no visual representation. Options: all add_body() options plus pos (vec3) for initial position.
Create a path builder for arbitrary shapes with bezier curves. The returned builder accepts chainable :move_to / :line_to / :quad_to / :cubic_to / :close calls and is committed with :fill(...) or :stroke(...).
Return the topmost primitive whose drawn shape covers point (canvas-local world space — pipe a cursor through canvas:screen_to_world first), or nil if none. Tests the rendered geometry: a filled shape is hit on its interior, a stroked shape on its outline. Hidden primitives, text, and groups are not hit; for a primitive inside a group, walk .parent to reach the group.
Every primitive whose drawn shape covers point (canvas-local world space), topmost first; empty when nothing is hit. Same geometry rules as point_query.
Mount this render target as a UI image element. Returns the new UiElement, or nil if the app has no UI.
Carve a PlotArea out of this canvas for charting, positioned by pos / width / height with optional margin, x_scale / y_scale, and background.
Carve a rows x cols grid of PlotAreas out of this canvas for faceting / subplots, returned row-major from the top-left. Pass a shared x_scale / y_scale handle to link the cells' axes; omitted scales are created independently per cell.
#handleDrawPrimitive
A single drawable on a DrawCanvas, returned by the primitive constructors and canvas:body. Methods update geometry, color, rotation/scale, visibility, or attach physics.
.visible: boolean read/write — Whether the primitive is shown (propagates to children)..opacity: number read/write — Alpha 0.0-1.0 (propagates to children)..velocity: Vec3 | nil read/write — Linear velocity (assign a vec2/vec3), or nil if the handle has no physics body..angular_velocity: number | nil read/write — Angular velocity in radians/sec about Z, or nil if the handle has no physics body. Assign a number..pos: Vec3 | nil read/write — Transform position (assign a vec2/vec3), updating visual + physics state. nil if the entity is gone..rotation: number | nil read/write — Rotation in radians about Z, or nil if the entity is gone. Assign a number; updates visual + physics state..restitution: number | nil read/write — Bounciness, 0..1; nil if the handle has no physics body. Assign a number to change it at runtime..friction: number | nil read/write — Surface friction coefficient; nil if the handle has no physics body. Assign a number to change it at runtime..ccd: boolean read/write — Whether this body, when moving fast, also sweeps moving (kinematic and dynamic) bodies so it never tunnels through them; fast bodies always sweep static geometry. Assign a boolean to toggle..parent: DrawPrimitive | nil read/write — The group this primitive belongs to (its transform composes with the group's), or nil if it is ungrouped. Assign a primitive to reparent (the local transform is kept), or nil to detach; reparenting across canvases raises..cell: integer | nil read/write — The atlas cell index (0-based) for a sprite drawn from anAtlas; assign to animate. Nil for primitives that are not atlas sprites; assigning to those is ignored.
Update a primitive's properties in-place. All optional: pos (a vec2 keeps the current depth; for groups an offset), color, material (Shader), rotation (radians CCW), scale_x, scale_y, text, font_size, max_width, align, spans.
Remove a primitive from its canvas.
Tween the primitive's position, rotation, scale, color, and opacity over duration seconds with the given easing curve.
Whether this primitive's drawn shape covers point (canvas-local world space). Geometry only — a named primitive is tested regardless of its visibility. Always false for text and groups (no single mesh).
The primitive's axis-aligned bounding box in canvas-local world space, or nil for primitives without a single mesh (text, groups).
Attach a physics body. 2D vs 3D is inferred from the host handle. See physics.BodyOptions for the shape + material fields; omitted size fields default from the host's visual geometry.
Attach a kinematic character controller to this body and return its CharacterController handle. The body must be kinematic. The controller solves walking/sliding/stair-stepping geometry only — gravity, jump, input, and camera stay in your code. Raises if the body is missing, not kinematic, or already has a controller (remove() to rebind).
Apply an instantaneous, mass-correct velocity change (Δv = impulse / mass). Accepts vec2 or vec3.
Apply an instantaneous, inertia-correct spin change. A number for 2D bodies (about Z), a vec3 for 3D.
Set the continuous force applied every step until changed. Pass a zero vector to stop. Accepts vec2 or vec3.
Set the continuous torque applied every step until changed. Pass zero to stop. A number for 2D bodies (about Z), a vec3 for 3D.
Lock or unlock rotation.
Replace this body's collision filtering at runtime (e.g. switching teams).
Lock or unlock individual translation/rotation axes at runtime. The 2D in-plane constraints are always preserved.
Set, replace, or clear (pass nil) the handler fired when this body starts colliding.
Set, replace, or clear (pass nil) the handler fired when this body stops colliding.
Remove all physics from this handle.
#handleAtlas
An image plus a uniform grid of cells, built by Image:atlas. Cells are indexed from 0 in row-major order. Use atlas:sprite(index) to make a drawable appearance.
Build a Sprite appearance for cell index (0-based, row-major). Options: {color?, flip_x?, flip_y?, size?}.
Build a reusable SpriteClips clip-set from this atlas. defs maps each clip name to a {frames, fps?, looping?, direction?, durations?, markers?} table; frames are 0-based atlas cell indices. Bind it to a sprite with clips:bind(sprite) — one clip-set drives many sprites, each with its own playhead.
#handleSprite
A reusable sprite appearance (image or atlas cell, tint, flip, size), built by Image:sprite / Atlas:sprite. Draw it onto a canvas with canvas:sprite.
Return a copy of this appearance with the given overrides applied. Options: {color?, flip_x?, flip_y?, size?}; omitted fields are kept.
#handleTileMap
A tilemap created by canvas:tilemap(atlas, opts). Cells index into the atlas; set(x, y, index) places a tile (0-based, bottom-left origin) and get(x, y) returns its index or nil for an empty/out-of-bounds cell. Rows count upward from the bottom — the vertical mirror of Grid's top-left Y-down frame — so copying Grid cells into a tilemap flips the row: ty = rows - 1 - gy.
Set cell (x, y) to atlas index. Raises if the cell is out of bounds (unlike Grid:set, which is a no-op there).
Read the atlas index at cell (x, y), or nil for an empty or out-of-bounds cell.
#handleBook
A loaded document or multi-chapter book, returned by file:book() and dir:book(). Mount it to render the current chapter; address elements by their document id.
.title: string read-only — The book title..page: integer read-only — Current chapter (1-based). Navigate withgo..pages: integer read-only — Chapter count.
Render the current chapter into a scrollable page view and return its root element. Unmount via root:remove(); a book mounts once at a time.
Navigate: an integer selects a chapter (1-based) and re-renders the mount; a string scrolls the mounted page to the element with that id. Raises on an unknown chapter or id.
Re-render against the app's current state: templates and control nodes re-evaluate. With an id, only that element's subtree re-renders in place; without one, the whole mounted page does. Raises when the id names anything but a declared element, or the book is not mounted.
#handleResponse
The in-flight result of an HTTP request. The request runs while the handle is unmaterialized; payload fields raise until it materializes — await :ready() or datumhue.ready, or probe state. An HTTP error status is data (status), not a failure; only transport-level errors fail the handle. Dropping an unawaited handle discards its outcome (the request still runs).
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..status: integer read-only — HTTP status code..headers: table<string, string> read-only — Response headers (keys lowercased)..body: Bytes read-only — Response body as opaqueBytes.
#handleOp
The in-flight acknowledgement of an effectful operation (a write, delete, or create). Await :ready() to observe completion or failure — file:write(bytes):ready() is the check-now idiom. Dropping an unawaited handle discards the outcome; the operation itself still runs.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready().
#handleStat
In-flight file or directory metadata from file:stat / dir:stat. Payload fields raise until it materializes — await :ready() or datumhue.ready, or probe state.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..kind: Dir.EntryKind read-only — Whether the entry is a file or a directory..size: integer read-only — Size in bytes..mtime: integer | nil read-only — Modification time in Unix seconds; nil when the backend doesn't report one.
#handleListFetch
An in-flight name listing (dir:list, storage:list). value raises until it materializes — await :ready() or datumhue.ready, or probe state.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..value: string[] read-only — The names, in ascending order.
#handleBoolFetch
An in-flight boolean answer (dir:exists). value raises until it materializes — await :ready() or datumhue.ready, or probe state.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..value: boolean read-only — The answer.
#handleBytesFetch
An in-flight bytes lookup (storage:get). value raises until it materializes — await :ready() or datumhue.ready, or probe state. An absent key is a successful lookup: state reads as completed and value is nil — it never fails a datumhue.ready barrier.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..value: Bytes | nil read-only — The stored bytes, or nil when the key is absent.
Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.
#handleDocEntry
An in-flight single-key document read. Payload fields raise until it materializes — await :ready() or datumhue.ready, or probe state. value and meta are both nil when the key is absent (or deleted) — an absent key never fails a barrier.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..value: nil | boolean | integer | number | string | table read-only — The stored value, or nil when the key is absent..meta: documents.Meta | nil read-only — Write metadata, or nil when the key is absent.
#handleDocQuery
An in-flight document prefix query. entries raises until it materializes — await :ready() or datumhue.ready, or probe state.
.state: ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at:ready()..entries: table<string, documents.Entry> read-only — Every key under the prefix mapped to its{value, meta}entry, newest per key.
#handleDir
A directory capability. Obtained from datumhue.args.dirs[name], datumhue.package:dir(), an open_button pick, or dir:subdir(rel). Relative paths must stay inside the directory — .., absolute paths, and symlinks that escape the root are all rejected.
.name: string read-only — The user-facing alias for this directory, never a host path.
Return a file-backed Bytes handle for rel under the directory. Construction is synchronous; the bytes resolve when a decoder method on the handle runs.
Whether rel exists. Only unexpected failures fail the operation.
Create an empty file at rel. Requires rw mode. An already-existing file fails the operation.
Overwrite rel with bytes. Requires rw mode. bytes must be a Bytes handle — strings are not auto-lifted. The write starts immediately; :ready() observes completion or failure.
The directory's access mode.
Mint a new file capability rooted at rel within this directory. Returns immediately; the handle inherits the parent dir's mode.
Mint a narrowed directory capability rooted at rel inside this dir. The returned handle sees only files under its own root.
Load the Lua module at exactly rel under the directory and run it once; repeat calls with the same rel hand back the same value. Returns the module's first return value, or true if it returned nothing.
Load a package rooted at rel under this directory. Auto-detects the shape: a regular file is read as an archive; a directory is walked under the strict layout.
#handleFile
A capability for one file inside a granted directory. Read, write, stat, or load it as a Lua module / package.
.name: string read-only — The file's name.
The file's access mode.
Return a file-backed Bytes handle for this file. Construction is synchronous; the bytes resolve through the filesystem when a decoder method runs. Decode via file:read():text(), file:read():image(), file:read():parquet(), etc.
Overwrite the file with bytes. Requires rw mode. bytes must be a Bytes handle — strings are not auto-lifted; wrap via datumhue.bytes("..."). The write starts immediately; file:write(b):ready() observes completion or failure.
Load this file as a Lua module and run it once; repeat calls on the same handle hand back the same value. Each file handle's require is independent.
Load this .kdl page as a one-chapter book. Raises with file:line:col diagnostics on parse or validation errors.
#handleDataMount
An opaque capability for SQL queries against a named remote mount. The mount and its provider are never visible to Lua — handles come only from datumhue.args.data_mounts or child-spawn inheritance.
Build a lazy DataHandle that runs sql against the mount when consumed. No network I/O happens until the handle is materialised. Errors raise at the consumption site; wrap consumption in pcall to catch them. params is an integer-indexed table of bound values substituted into ? placeholders in order, or omitted for no parameters. Each value must be nil, boolean, integer, number, or string.
#handleScale
The data-domain side of a chart mapping (linear, log, band, or time). Created by chart scale constructors; drives dependent marks and axes. Each plot area using the scale assigns its own pixel range, so sharing one handle across areas links their domains while every area keeps its own geometry.
.domain: table | "auto" | nil read/write — Resolved domain{min = N, max = N}, ornilwhile pending. Assign{min = N, max = N}or"auto"; dependent marks and axes re-render. Band scales read and assign the ordered category array instead (same list ascategories)..categories: string[] | nil read-only — Ordered category names of a band scale — the construction domain plus any categories marks discovered from their data by the time of the read.nilon linear / log / time scales, which map a numeric continuum and keep no category list.
Data value → pixel position, resolved through the plot area using this scale. nil while pending (no domain, or no area has laid the scale out). Raises when areas with different pixel ranges share the scale — convert through area:data_to_world then.
Pixel position → data value, resolved through the plot area using this scale. Band scales return the name of the category whose slot contains the pixel. nil while pending or outside every slot. Raises when areas with different pixel ranges share the scale — convert through area:world_to_data then.
Scan a column for min/max and set the domain. Returns self. Linear / log / time only. By default only writes if the domain is still pending, so a user pan / zoom during a long-running fit isn't overwritten when the query lands. Pass force = true to always apply.
Clear the domain and then refit from column. Equivalent to assigning domain = "auto" immediately followed by fit(data, column, true), but as one call. Returns self.
Width of one band, minus padding, resolved through the plot area using this scale. Band only; nil for numeric scales or while no area has laid the scale out. Raises when areas with different pixel ranges share the scale.
1-based category position for name, or nil if absent (band scales only). This is an ordinal for display/iteration; to position a mark, pass the category *name* to scale:map, not this number.
Ease the domain toward a target over a duration; dependent marks and axes re-render every frame. Pins the domain like a direct assignment. A scale whose domain is still pending snaps to the target immediately; a new call replaces an in-flight animation from the current domain. Errors on band scales.
Subscribe to changes of the scale's resolved domain — assignment, pan / zoom, fit / reset, animation frames, and band-category updates all count. Fires at most once per frame while the domain is changing (a continuous pan delivers one call per frame). Subscribing does not fire for the domain the scale already has. Multiple subscriptions can be active on one scale.
Destroy the scale.
#handleMark
A rendered mark (line / points / area / bars / rule / text) inside a plot area. Returned by the area:* mark constructors.
.visible: boolean read/write — True while the mark is drawn. Assign to show or hide — a hidden mark stops drawing until shown again and re-renders on the next frame when shown; a rule's value label follows the toggle.
Change the mark's appearance or data. Hidden marks stop drawing until shown again; showing one re-renders it on the next frame. Errors when called on a handle that isn't a mark.
Row nearest to the data-space query point. Line / points / area marks answer with the nearest source row; histograms with the bin containing the query x (row is the bin index, y the bin height); heatmaps with the nearest cell (row is the cell index); box marks with the category nearest along the band axis (value is the median); bars marks with the category whose band slot is nearest along the band axis (value sums the category's series values). Rule / text / band marks carry no data rows and answer nil.
Append a single data-space point to a line / points / area mark whose source is inline points. When the mark was constructed with max_points = N, the oldest point is evicted once len ≥ N (ring buffer). Errors on data-bound marks — those reshape via mark:replace_data, not push.
Swap the underlying data source on a data-bound mark of any kind. Line / points / area marks keep their x_column / y_column and re-render against the new source; aggregating marks (bars, histogram, histogram2d, heatmap, box) keep their column / bin / aggregate bindings, drop the aggregation cache, and re-aggregate. Scale domains reset and refit once the new data loads, and a line / area mark with series_column re-partitions its series. Errors on marks built from inline values (recreate those), on inline-points marks (reshape via mark:update({points=...})), and on borrowed-view marks (update through the view API).
Remove the mark. Data-owned marks also release their streaming view.
#handlePlotArea
A plot area inside a canvas, created by canvas:chart(opts). Hosts marks, axes, legends, scales, and interaction behaviors.
.x_scale: Scale | nil read-only — The area's x-axis Scale handle — the one passed at construction, or the default linear scale auto-created when the caller omitted it. Read-only; swap scales viaarea:update({x_scale = ...})..y_scale: Scale | nil read-only — The area's y-axis Scale handle. Mirror ofx_scale; swap viaarea:update({y_scale = ...}).
Add a line mark. Exactly one of points, data, or view is required. Rows with null values are skipped; a null in the x or y column breaks the line at that row.
Add a scatter (dots) mark. Exactly one of points, data, or view is required; data-bound points render every row in the visible range. Rows with null values are skipped.
Add a filled-area mark — closed polygon between a data line and a numeric baseline. Exactly one of points, data, or view required. Rows with null values are skipped; a null in the x or y column breaks the area at that row.
Add a horizontal or vertical reference line at a data-space value.
Add a text annotation at a data-space position.
Add a filled highlighted region spanning a [from, to] range on one axis and the full inner rect on the orthogonal axis.
Add a bar mark — one rectangle per category, from inline entries/series or an engine-side group-by over a data source. Requires a band scale on the categorical axis; discovered categories append to it.
Add a histogram — contiguous bins over a numeric column or inline values, aggregated engine-side. Pending scales fit to the bin extent and peak; a zoomed x scale re-bins over the visible domain. Rows with null values are skipped.
Add a categorical heatmap — one colored cell per (x, y) category pair, from inline cells, a matrix, or an engine-side group-by over a data source. Both axes need band scales; discovered categories append to them.
Add a box-and-whisker mark — one five-number summary per category, from pre-computed entries or an engine-side group-by over a data source. Requires a band scale on the categorical axis; discovered categories append to it.
Add a 2D density heatmap — numeric (x, y) pairs binned engine-side into a colored grid. Zoomed scales re-bin over the visible window.
Add an axis bound to a scale.
Add a legend.
Update the area geometry, scales, or background in place. Pass background = color(...) to pin a concrete fill, or background = false to opt back into the theme default.
Canvas coord → data coord using current scales. Exact for time scales (full-precision epoch-ms).
Data coord → canvas coord. An {x, y} table keeps a time-scale x exact (a vec2 rounds epoch-ms to f32 first).
Clear both scale domains and refit against only currently-visible marks. Scales the user has pinned with pan / zoom / box-zoom are left alone. Pass {force = true} to always refit, matching the double-click-reset gesture.
Pin a title to the plot area. When color is omitted the title follows the theme's chart-label color and restyles on theme switch. One title per area — re-calling replaces any prior title. Auto-repositions on area resize.
Remove the plot area's title (if any).
Draw a hover crosshair: guide lines at the cursor, a readout text with the cursor's data-space x/y, and dots + labels at every line / area mark's y(cursor.x). Overlays redraw each frame; nothing persists when the cursor leaves the plot area. One crosshair per area — raises while one is active; update or remove it instead.
Enable built-in pan / zoom / box-zoom / double-click-reset interaction on the plot area. Works on linear, log, and time scales; band scales are skipped. Data-bound marks re-downsample at every zoom so detail stays pixel-faithful at any zoom level. One per area — raises while one is active; update or remove it instead.
Enable a brush selection gesture on the plot area. Dragging sweeps a tinted selection region; releasing delivers the selection's data-space bounds to on_brush, and a plain click clears the selection and delivers nil. The selection region persists until cleared, replaced, or the brush is removed. One brush per area — raises while one is active; update or remove it instead.
Register a callback fired every frame the cursor is inside the plot area's inner rect, with the cursor in data space (exact for time scales). Pass nil to clear.
Fire a callback on mouse-button release inside the area's inner rect, with the cursor in data space (exact for time scales). Pass nil to clear.
Y-value at data-space x for each line / area mark on this area. Rows match the mark's readout setting. Empty if no mark has a value at x.
Current cursor in data-space, composing window → canvas → plot area → scales. Exact for time scales (full-precision epoch-ms). nil when the cursor is outside the plot area's inner rect, or when any stage is unresolved.
Composite cursor accessor. Returns nil when no cursor resolves. Unlike mouse_data_position, returns a value even when the cursor is outside the area.
Remove every mark attached to this area — line / points / bars / area / rule / text / band / axis / legend. The PlotArea itself survives, as does the canvas.
Bundle a set of mark handles for synchronized visibility toggles and lifecycle. Not a hierarchy — marks render where they were created.
Destroy the plot area and every mark on it. The canvas survives (shared state).
#handleCrosshair
Returned by area:crosshair(...). The active hover crosshair on one plot area — reconfigure it in place or remove it.
Reconfigure the crosshair in place; omitted options keep their current values. Raises after remove.
Remove the crosshair and sweep any lingering overlay primitives. The area can then construct a new one. Safe to call more than once.
#handlePanZoom
Returned by area:pan_zoom(...). The active pan / zoom interaction on one plot area — reconfigure it in place or remove it.
Reconfigure the interaction in place; omitted options keep their current values and an in-flight gesture is left undisturbed. Raises after remove.
Remove the interaction — the area stops reacting to mouse / scroll. The area can then construct a new one. Safe to call more than once.
#handleBrush
Returned by area:brush(...). The active brush gesture on one plot area — read the committed selection off selection, reconfigure it in place, clear it, or remove it.
.selection: chart.BrushSelection | nil read-only — Data-space bounds of the committed brush selection;nilwhen nothing is selected or the brush was removed.
Reconfigure the brush in place; omitted options keep their current values and passing on_brush replaces the callback. Changing axis clears any committed selection (without firing on_brush). Raises after remove.
Clear the committed selection and its region without firing on_brush.
Remove the brush, its selection region, and its on_brush callback. The area can then construct a new one. Safe to call more than once.
#handleColorScale
A numeric → color ramp created by datumhue.chart.scale.color(options). Drives per-row color on data-bound marks via the color_column option.
.domain: table | "auto" | nil read/write — Domain{min = N, max = N}, ornilwhile pending. Assign{min = N, max = N}or"auto".
Ramp scales: interpolated color at a numeric value, or nil while pending. Category scales: the category's color (a string registers first-seen; a number is a 0-based index).
Destroy the color scale.
#handleAxis
A tick axis bound to a scale, created by area:axis(options).
Change the axis ticks, label, format, grid, or colors.
Remove the axis.
#handleLegend
A legend panel attached to a plot area, created by area:legend(options).
Change the legend items, position, anchor, orientation, or colors.
Remove the legend.
#handleChartGroup
Returned by area:group(marks). Bundles a set of mark handles for synchronized visibility toggles and lifecycle. Not a hierarchy — marks render where they were created.
.visible: boolean read/write — True while every member is visible. Assign to show or hide every member at once; members toggled individually afterwards read back here.
Removes every member and the group.
#handleUiElement
A node in the UI tree, returned by the constructor methods on a parent element (ui.root:panel{...}, panel:button{...}, ...) and by source:mount(opts) on a render target. Methods adjust layout, content, hit-testing, and appearance.
.visible: boolean read/write — Whether the element and its children are shown..display: ui.Display read/write — Layout display mode. Assigningnoneremoves the element from layout while keeping its subtree (and scroll position) alive; other values restore it..pos: Vec2 | nil read/write — Left/top anchor in pixels as a vec2;nilwhen unset. Assign a vec2..size: Vec2 | nil read/write — Width/height in pixels as a vec2;nilwhen unset. Assign a vec2..color: Color | ThemedColor read/write — Background color. Assign adatumhue.theme.token(...)to follow the theme, or aColorto pin it; reading gives the resolvedColor..text: string | nil read/write — Text content of a label or a text input (nilon other elements). Assigning to a text input replaces its value silently (noon_change)..marquee: boolean read/write — Whether an overflowing label loops its text horizontally, pausing briefly at each wrap. Text that fits stays still. Writable on labels; false elsewhere, and raises on assignment to a non-label..scroll: Vec2 | nil read/write — Scroll offset in logical px (scroll containers only;nilotherwise). Assign a vec2; clamped to the scrollable bounds. Raises on a non-scroll element..scroll_max: Vec2 | nil read-only — Maximum scroll offset (content minus viewport, logical px; zero until first layout).nilfor non-scroll elements..enabled: boolean read/write — Whether an interactive widget (a button, checkbox) accepts input. Settingfalsegrays it out and suppresses its click / keyboard activation;truerestores it. Readstrueon non-interactive elements..checked: boolean read/write — Whether a checkbox is checked. Assigning updates it silently (theon_changecallback fires only on user toggles, not programmatic writes). Readsfalseon non-checkbox elements; assigning to one raises..value: number | Color | nil read/write — A value-bearing widget's current value: a number for a slider or number input, an integer instant (Unix microseconds) for a date/time picker, or aColorfor a color picker. Assigning updates it silently (noon_change).nilon elements that hold no value; assigning to one raises..min: number | nil read/write — A slider's range minimum. Assigning re-clampsvalueinto the new range.nilon non-slider elements; assigning to one raises..max: number | nil read/write — A slider's range maximum. Assigning re-clampsvalueinto the new range.nilon non-slider elements; assigning to one raises..step: number | nil read/write — A slider's keyboard / track-click step increment.nilon non-slider elements; assigning to one raises..selected: integer | integer[] | nil read/write — Current selection as a 1-based index. A radio group or single-select list or table reads an integer (ornil); a multi-select list or table reads an index array. A data table's indices are display positions, and its selection follows the rows across a sort. Assigning selects silently (noon_change): an integer (ornilto clear) for radio/single, an array for multi.nilon elements that aren't a radio group, list, or table; an out-of-range index, or an array on a radio group, raises..pressed: boolean read-only — Whether the element is currently held down by the pointer. Read-only;falseon non-interactive elements..hovered: boolean read-only — Whether the cursor is currently over the element. Read-only;falseon non-interactive elements..strikethrough: boolean read/write — Whether a line is drawn through a text label. Assigning toggles it. Readsfalseon non-text elements; assigning to one raises..underline: boolean read/write — Whether a line is drawn under a text label. Assigning toggles it. Readsfalseon non-text elements; assigning to one raises.
Remove the element and its children. Raises on ui.root (the engine-owned app content area) — remove its children or individual elements instead.
Create an in-app navigation region under this element and return its Router. The region fills this element; declare routes with router:route and navigate with show/push/pop/go. Pages are retained (hidden) when backgrounded, so going back restores their scroll and state.
Returns the i-th radio option (1-based) of a radio group as a UiElement. Raises on a non-group element or an out-of-range index.
Returns the i-th row (1-based) of a list as a UiElement. Raises on a non-list element or an out-of-range index.
Set, replace, or clear (pass nil) the click handler at runtime. Fires only on an interactive element (a button).
Set, replace, or clear (pass nil) an open_button's pick handler at runtime — the path to bind a <open_button> declared in DHML from the hosting app. Called with the picked File / File[] / Dir on success (never on cancel); with none bound, a click opens no dialog.
Set, replace, or clear (pass nil) a save_button's save handler at runtime. Called with the read-only File handle after the bytes are committed (never on cancel).
Set the bytes a save_button writes at its next click, captured now. Pass nil to clear (a click then does nothing). The way to keep a save button's payload current — call it whenever the app's data changes. Raises on a non-widget element.
Set the text a copy_button places on the clipboard at its next click, captured now — a string or UTF-8 Bytes (non-UTF-8 raises). Pass nil to clear (a click then does nothing). The way to keep a copy button's payload current — call it whenever the app's data changes. Raises on a non-widget element.
The i-th row (1-based, display order — the sorted order while sorted) of a data table as a {column = value} table over its configured columns; a cell missing from the data reads nil. The one sanctioned per-row materialization — it reads the source data directly. Raises on a non-table element or an out-of-range index.
Set, replace, or clear (pass nil) the hover-enter handler at runtime. Fires when the cursor enters this element or any of its descendants.
Set, replace, or clear (pass nil) the hover-exit handler at runtime. Fires when the cursor leaves this element and all of its descendants.
Set, replace, or clear (pass nil) the press handler (fires while held) at runtime. Fires only on an interactive element.
Set, replace, or clear (pass nil) the release handler at runtime. Fires only on an interactive element.
Set, replace, or clear (pass nil) the double-click handler at runtime. Fires on a second press within the double-click window. Fires only on an interactive element (a panel or button).
Set, replace, or clear (pass nil) the focus-gained handler at runtime. Fires only on a focusable element (e.g. a text input) when it gains keyboard focus.
Set, replace, or clear (pass nil) the focus-lost handler at runtime. Fires only on a focusable element (e.g. a text input) when it loses keyboard focus.
Set, replace, or clear (pass nil) the cancel handler at runtime. Fires when Escape is pressed while a text input is focused.
Move keyboard focus to this element. Takes effect on focusable widgets (a text input, button, checkbox, slider, radio group, or list); a no-op on elements that cannot hold focus.
Set a text element's fill color. Pass a datumhue.theme.token(...) to follow the theme; omit / pass nil to re-follow the default text color.
Apply a shader material. Omit / pass nil to remove it.
Swap the image texture to a render-target source. Omit / pass nil to clear it.
Batch-update layout / style plus source, color, text, visible, or material.
Cursor position relative to the element's top-left corner (logical px), or nil.
Scale element-relative logical px to the source texture's native pixel space, or nil.
Create a child UI panel.
Create a child interactive button.
Create a child button that opens a file / directory picker when clicked. The click is the user gesture — there is no programmatic open — so an app can neither open a dialog on its own nor spam them. On a successful pick on_pick fires with the chosen handle; cancel fires nothing. With no on_pick bound the click opens no dialog.
Create a child button that opens a save dialog when clicked and atomically writes source to the chosen file. The click is the user gesture. On success on_save fires with the read-only File handle; cancel fires nothing. With no source set the click does nothing.
Create a child button that places its source text on the system clipboard when clicked. The click is the user gesture — there is no programmatic copy, so an app can neither read nor spam the clipboard on its own. On success on_copy fires; a failed write logs. With no source set the click does nothing.
Create a child link styled as link text. Clicking it opens url in a new browser tab; opening only ever happens from this user click, so an app cannot open URLs on its own. url must be http, https, or mailto (any other scheme raises). Hovering shows the destination host.
Create a date picker: a field that opens a calendar popover. Selecting a day fires on_change with the selected instant (Unix microseconds); read/write it via value (nil until picked). Build / decode the value with time.from_calendar / time.calendar.
Create a time picker: a field that opens a popover with 24-hour HH:MM steppers. Editing the time fires on_change with the selected instant (Unix microseconds).
Create a combined date+time picker: a calendar popover with 24-hour HH:MM steppers. Picking a day or editing the time fires on_change with the selected instant (Unix microseconds).
Create a color picker: a field (a swatch + the hex string) that opens a popover with a saturation/value square, a hue strip, a live preview, a hex field, and optional preset swatches. Dragging, committing the hex, or clicking a preset fires on_change with the picked color (sRGB). Read or write the current color via the value property; a programmatic write is silent.
Create a child checkbox. State is the checked property; on_change fires on user toggles.
Create a child horizontal slider. State is the value property; on_change fires continuously while dragging.
Create a child numeric input: a number field with -/+ steppers. State is the value property; on_change fires on field edits and steps.
Create a child radio group. State is the selected property (1-based); on_change fires on user selection.
Create a child selectable list. State is the selected property (a 1-based index, or an index array when multi); on_change fires on user selection.
Create a child data table bound to a DataHandle: a header row over a scrolling, engine-virtualized body that reads only the rows in view — rows are never materialized into Lua. State is the selected property (a 1-based display index, or an index array when multi); on_change fires on user selection. tbl:row(i) reads one row on demand.
Create a child text input. Its content is the text property; on_change fires on each user edit and on_submit on Enter (single-line).
Create an overlay popover anchored to this element, positioned on side/align with gap, auto-flipped to stay on-screen. Fill it with child widgets; show/hide via the visible property.
Create a child text label.
#handleRouter
In-app navigation for one region: a retained page stack with named routes and switchable roots (tabs). From panel:router(). Pages are kept (hidden) when backgrounded, so going back restores their scroll and state.
.depth: integer read-only — Number of pages on the active stack..active: Route | nil read-only — The active page's Route, or nil for an inline-pushed page..params: table | nil read-only — The active page's params (as passed to the navigator), or nil..can_go_back: boolean read-only — Whether the active stack has more than one page.
Declare a route from a builder(page, params) that fills the given page element. Returns a Route handle to navigate to.
Switch the active root to route (tabs); the previous root and its whole sub-stack are retained. Builds the route on first show.
Push a page onto the active stack (a Route or an inline builder(page, params)); the page below is hidden, retained.
Replace the top page in place (no depth change). Runs the old page's on_leave (which may veto).
Navigate to route: if it is already on the active stack, pop back to it (retained); otherwise push it.
Go back one page: discard the top and reveal the one below with its retained state. Runs the top's on_leave (may veto). No-op at the root.
Pop every page above the active root and reveal the root with its retained state.
#handleRoute
A declared navigation destination from router:route(...). Pass it to router:show/push/go. Equality identifies the route (e.g. to highlight the active tab).
.title: string | nil read-only — The route's title string (resolved from its options), or nil.
#handleJoint
A physics joint created by datumhue.physics.add_joint.
Remove this joint, releasing its constraint between the two bodies.
#handlePhysicsWorld
An isolated physics world created by datumhue.physics.world(). Bodies join it via add_body{world = ...}; queries and gravity are scoped to it.
.gravity: Vec3 read/write — This world's gravity vector (Y-up; default{0, -9.81, 0}). 2D bodies feel its X/Y components. Assign a vec2/vec3.
Cast a ray and return the nearest body hit, or nil.
Cast a ray and return every body along it, nearest first.
Return every body whose collider overlaps the given world-space point.
Sweep a 3D collider shape along the ray and return the nearest body hit, or nil.
Drop this world and every body and joint simulating in it.
#handleCharacterController
A kinematic character controller bound to a body, created by body:character_controller{…}. It solves collide-and-slide geometry (walls, slopes, stairs, ground-snap); gravity, jump, input, and camera stay in your code. The solver knobs are read/write properties; move is a pure query you apply yourself.
.up: Vec3 read/write — Floor-defining up direction (unit vector). Selects which contacts count as ground and is the slope-angle reference. Assign a vec2/vec3; 2D uses the XY components..offset: number | physics.RelativeLength read/write — Small gap kept between the character and surroundings for numerical stability; must be > 0..slide: boolean read/write — Slide along blocking walls instead of stopping dead..max_slope_climb_angle: number read/write — Steepest slope, in radians, the character climbs; steeper surfaces act as walls..min_slope_slide_angle: number read/write — Slope angle, in radians, at/above which the character auto-slides down..snap_to_ground: number | physics.RelativeLength | boolean read/write — Distance to snap down onto ground after a move;falsewhen disabled..autostep: physics.AutostepConfig | boolean read/write — Step-climbing config, orfalsewhen disabled. Assign a config table to enable. Needs a flat-bottomed body (cube or cylinder): the step lands the body on the ledge by only the frame's leftover motion, and a capsule's rounded bottom slides back off. The body also needs head room of its own height plusmax_heightabove where it stands, so a low ceiling stops it stepping..normal_nudge_factor: number read/write — Tiny anti-stick push along contact normals while sliding..grounded: boolean read-only — Result of the lastmove: standing on ground afterward. False while that move commanded upward motion (e.g. a jump), so a launching jump is never reported grounded, and false before the first move..sliding_down_slope: boolean read-only — Result of the lastmove: the character was let slide down a too-steep slope. False before the first move.
Sweep the character by displacement and return the movement actually allowed plus the grounded/slope results and the surfaces hit. Does NOT move the body — apply it yourself (body.pos = body.pos + result.translation). displacement is the full movement you want this frame and must already include your own gravity·dt and jump velocity; the controller adds no gravity. For correct stair-climbing under gravity, you may move horizontal and vertical displacement in separate calls. dt (seconds, > 0) is the solver timestep used only for moving-platform carry; it defaults to the fixed timestep and does NOT scale displacement (you already scaled that by your frame time).
Push the dynamic bodies the character pressed against during the most recent move, using mass (kg) as the character's effective mass for the reduced-mass impulse. Call it after move in the same frame; raises if no move has run since the last push.
Detach the controller from its body (the body and its collider remain). Idempotent.
#handlePathBuilder
A chainable path builder returned by canvas:path. Record segments with move_to / line_to / quad_to / cubic_to / close, then commit with fill or stroke.
Start a new subpath at (x, y). Returns self for chaining.
Add a straight segment to (x, y). Returns self for chaining.
Add a quadratic bezier through control point (cx, cy) to (x, y). Returns self.
Add a cubic bezier through control points (c1x, c1y) / (c2x, c2y) to (x, y). Returns self.
Close the current subpath back to its start. Returns self.
Tessellate and fill the recorded path. Options: color, z, material. Returns the new DrawPrimitive, or nil if the canvas is invalid.
Tessellate and stroke the recorded path. Options: color, width, z, material. Returns the new DrawPrimitive, or nil if the canvas is invalid.
#handlePackageRef
An opaque, resolved reference to a catalog entry. Read-only; accepted by app.spawn({package_ref = …}).
.name: string read-only — Scoped@scope/nameidentity.
Owning scope segment (the scope in @scope/name), without the leading @.
Stable identifier of the entity that published this version, as verified at publish from the publisher's sign-in.
Namespace this entry belongs to.
SemVer string from the manifest.
Manifest kind: "app", "library", or "asset_pack".
The refinement tag on asset packs, or nil when unset.
One-line summary, or nil when unset.
Display name, or nil when unset.
Catalog icon, returned synchronously and populated in the background; nil when the manifest declares no icon. Decoded at up to 256 px on the longest edge.
Total size of the package's files in bytes.
The sealed flag from the manifest.
The service flag from the manifest.
Map of dependency @scope/name to its SemVer constraint.
Array of capability grants the manifest declares as required to run, in declaration order; empty when none.
Pricing for a paid package as { paid, price, currency }, or nil when the package is free. price/currency are the creator's current listing — live state, not a property of the version — and are absent while the package is not listed for sale yet. Pass the ref to datumhue.commerce.purchase to buy it.
SPDX license id the package declares (e.g. "0BSD"), or nil when unset. Free packages always carry one; paid packages may omit it.
Discovery tags from the manifest, in declaration order; empty when none.
Screenshot images in manifest order, each populated in the background like icon() and decoded at up to 1024 px on the longest edge. Every call starts one load per screenshot, so call it for the package being viewed rather than across a whole list.
The package's readme text (raw Markdown or plain text), fetched on demand; nil when the package ships none. Raises when the readme exceeds 1 MiB or is not valid UTF-8.
Download and materialise the package as a Package handle. Raises if the request fails.
packages capabilityVersion of this package currently installed from this ref's registry — keyed by name, so a catalog-latest ref answers for the installed copy. nil when not installed; a value differing from version() means an update is available. Reads local state, so it works offline.
packages capabilityDownload this exact version, with its dependencies, into the local library. Returns immediately when this version is already installed; installing over a different installed version replaces it. A paid package must be purchased first. Succeeds offline when the content is already cached.
packages capabilityRemove this package from the local library — keyed by name, whatever version is installed. Raises when it is not installed or an app is currently running from it. Local content shared with other installed packages is kept; returns the bytes reclaimed (0 when space reclamation was skipped).
#handleEntitlement
Proof the signed-in user owns a paid package. Returned by datumhue.commerce.owned and purchase. Verified offline against the creator's license-derived namespace.
.package: string read-only — Canonical@scope/nameof the owned package..name: string read-only — The package's bare name (no scope)..namespace: string read-only — The creator registry namespace the package lives in..purchased_at: number read-only — Unix seconds when the entitlement was recorded on this device.
#handleHttpMount
An opaque capability for HTTP to one operator-pinned origin. The origin, access control, and any forwarded credential are configured provider-side and never visible to Lua — handles come only from datumhue.args.http_mounts or child-spawn inheritance. Each method takes a mount-relative path (resolved against the origin) and an options table, starts the request immediately, and returns an unmaterialized Response — await it with :ready() or datumhue.ready, or probe its state.
Options: headers, query, timeout_ms.
Options: headers, query, body (Bytes), timeout_ms.
Options: headers, query, body (Bytes), timeout_ms.
Options: headers, query, body (Bytes), timeout_ms.
Options: headers, query, body (Bytes), timeout_ms.
Options: headers, query, timeout_ms.
#handleIngressMount
An opaque capability for subscribing to one operator-named ingress channel. The channel, its access control, and its decryption keys are configured provider-side and never visible to Lua — handles come only from datumhue.args.ingress_mounts or child-spawn inheritance. subscribe joins the channel's encrypted fan-out and delivers each authenticated record to a callback.
Subscribe to the channel behind this handle. The callback fires with each authenticated record as {channel, payload, headers}. Returns a subscription; call :unsubscribe() to stop it. Records whose author is not a verified provider for the channel, or that fail decryption, are dropped silently. Delivery starts once the subscription has joined the channel's gossip mesh, usually within a second; a record pushed before that arrives only if a peer still holds it.
Option tables265
dirs: table<string, Dir> — Granted directory capabilities, keyed by mount name.files: table<string, File> — Granted file capabilities, keyed by mount name.data_mounts: table<string, DataMount> — Granted data-mount capabilities, keyed by mount name.http_mounts: table<string, HttpMount> — Granted HTTP mount capabilities, keyed by mount name.ingress_mounts: table<string, IngressMount> — Granted ingress mount capabilities, keyed by mount name.argv: string[] — Positional launch arguments passed to this app.
headers: table<string, string> optional — Request headers. Credentials are injected provider-side per the mount's configuration; the mount may override theAuthorizationheader.query: table<string, string> optional — Query-string parameters appended to the path.body: Bytes optional — Request body as opaqueBytes(ignored by GET / HEAD).timeout_ms: integer optional — Request timeout in milliseconds.
channel: string — The channel the record arrived on.payload: Bytes — The record's application payload as opaqueBytes.headers: table<string, string> — Application headers the source set and the provider forwarded.
channel: string optional — Sub-channel selector, when the provider multiplexes several streams on one mount. Omit for the mount's default channel.callback: fun(event: IngressEvent) — Invoked with each authenticated record. Duplicates (by the source's idempotency key) are collapsed before delivery.
handle: Dir — The handle to inherit.mode: app.PreopenMode optional — Mode narrowing the inherited access; defaults to the parent's.
handle: File — The handle to inherit.mode: app.PreopenMode optional — Mode narrowing the inherited access; defaults to the parent's.
reason: string optional — Justification shown to the user when the window manager prompts for approval.
name: string optional — App name; required forcode, defaults to the manifest name for a package.code: string optional — Inline Lua source. Mutually exclusive withpackage/package_ref.package: Package optional — A loaded package bundle to run. Mutually exclusive withcode/package_ref.package_ref: PackageRef optional — A catalog reference; the child arrives once resolved + downloaded. Mutually exclusive withcode/package.weight: number optional — Scheduler weight for the child (default 10).x: number optional — Initial bounds x; set x/y/width/height together.y: number optional — Initial bounds y; set x/y/width/height together.width: number optional — Initial bounds width; set x/y/width/height together.height: number optional — Initial bounds height; set x/y/width/height together.args: string[] optional — Launch arguments passed to the child.title: string optional — Window title for the child app.dirs: table<string, Dir | app.PreopenEntry> optional — Directories to grant, keyed by child-facing name; each value is a Dir handle or a{handle, mode}entry.files: table<string, File | app.PreopenFileEntry> optional — Files to grant, keyed by child-facing name; each value is a File handle or a{handle, mode}entry.data_mounts: table<string, DataMount> optional — Data mounts to grant, keyed by child-facing name.http_mounts: table<string, HttpMount> optional — HTTP mounts to grant, keyed by child-facing name. A child can only receive mounts the parent holds.ingress_mounts: table<string, IngressMount> optional — Ingress mounts to grant, keyed by child-facing name. A child can only receive mounts the parent holds.permissions: app.SpawnPermissions optional — Capabilities to grant the child; narrowed against the parent's grants.service: boolean optional — Spawn headless; valid only with inlinecode.parent: App optional — An ancestor (or self) to reparent the spawn under; defaults to the caller.
identity: boolean optional — Request the identity capability.screenshot: boolean optional — Request the screenshot capability.network: boolean optional — Request the raw-network capability.commerce: boolean optional — Request the commerce capability (purchase paid packages).packages: boolean optional — Request the packages capability (manage the installed-package library).
patterns: audio.SfxNote[][] — Ordered patterns; each is an array of note tables.sequence: integer[] — 1-based pattern indices played in order.looping: boolean optional — Loop the assembled track (defaults to false).volume: number optional — Linear playback volume (defaults to 1.0) — the instance gain the handle'svolumereads and writes.bus: string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
Inherits all fields of audio.PositionalOptions.
volume: number optional — Linear volume (defaults to 1.0) — the instance gain the handle'svolumereads and writes.looping: boolean optional — Loop playback when true (defaults to false).speed: number optional — Playback speed multiplier (defaults to 1.0); the instance's startingpitch.bus: string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
at: Vec2 optional — Where the sound stands, in any 2D unit kept consistent withlistener. Pan comes from the horizontal offset (viapan_scale/pan_limit), loudness from the distance curve (falloff_*,max_distance); both are rendered into the sound when playback starts. Omit to play centered and unattenuated — every other positional field requires it.listener: Vec2 optional — Where the ear stands, same units asat; defaults to the origin.max_distance: number optional — Distance past which the sound is silent; unlimited when omitted.pan_scale: number optional — Horizontal offset at which the pan fold would reach a full ear (default 128; must be > 0).pan_limit: number optional — Clamp on the folded pan's magnitude, 0..1 (default 0.8), so a distant source never sits in one ear alone.falloff_cap: number optional — Ceiling on the arriving gain (default 1.0).falloff_gain: number optional — Numerator k of the distance curvemin(falloff_cap, k / (1 + d / falloff_scale))(default 1.0).falloff_scale: number optional — Distance at which the curve has halved a unitfalloff_gain(default 128; must be > 0).
waveform: audio.Waveform — Oscillator waveform for this note.frequency: number optional — Tone frequency in Hz (defaults to 440).duration: number optional — Note duration in seconds (defaults to 0.1).volume: number optional — Linear volume for this note (defaults to 1.0).slide: number optional — Target frequency in Hz to glide toward over the note.vibrato: audio.Vibrato optional — Pitch vibrato parameters.arpeggio: number[] optional — Semitone offsets cycled per 1/60s tick.
Inherits all fields of audio.PositionalOptions.
pan: number optional — Stereo pan, -1 (left) .. 1 (right), constant-power; 0 or absent plays center as mono. Mutually exclusive withat.space: number optional — Room size for the reverb tail, 0 (dry, the default) .. 1 (a gymnasium). Rendered into the sound deterministically.muffle: number optional — Low-pass amount, 0 (open, the default) .. 1 (through a shut door). Applied before the reverb tail.volume: number optional — Linear gain for this play as a whole (defaults to 1.0), on top of each note's own volume; adjust it live via the handle'svolume.bus: string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
waveform: audio.Waveform — Oscillator waveform.frequency: number optional — Tone frequency in Hz (defaults to 440).duration: number optional — Tone duration in seconds (defaults to 0.5). A looping tone whose duration holds a whole number of cycles loops seamlessly.volume: number optional — Linear volume (defaults to 1.0) — the instance gain the handle'svolumereads and writes.looping: boolean optional — Loop playback when true (defaults to false); adjust a running loop by assigninghandle.volume.bus: string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
depth: number optional — Frequency deviation in Hz (defaults to 5.0).speed: number optional — Vibrato LFO rate in Hz (defaults to 4.0).
Inherits all fields of ui.NodeStyle.
parent: UiElement optional — Parent element; defaults to the app's content area.toc: boolean optional — Chapter sidebar; defaults to on for multi-chapter books.nav: boolean optional — Prev/next navigation row; defaults to on for multi-chapter books.
header: boolean optional — Treat the first row as a header (default true).delimiter: string optional — Single-byte field delimiter (default,).quote: string optional — Single-byte quote character (default").comment: string optional — Single-byte comment marker; matching lines are skipped.
domain: table — Target domain{min, max}(epoch-ms on time scales).duration: number optional — Animation length in seconds (default 0.4).easing: Easing optional — Easing curve (default cubic_in_out).
Inherits all fields of chart.DataMarkBase.
baseline: number optional — Numeric baseline the area fills to.series_column: string optional — Category column splitting rows into one series per distinct value (data sources only). Each series renders its own polyline with per-series downsampling and null-gap handling, takes a color fromcolor_scaleor the category palette in first-seen order, and contributes its own legend item.color_scale: ColorScale optional — Category color scale assigning per-series colors; requiresseries_column.readout: chart.ReadoutMode optional — Crosshair readout interpolation mode.
scale: Scale — Scale the axis is bound to.side: chart.AxisSide — Edge of the plot area the axis sits on.ticks: integer optional — Target tick count (default 6).tick_values: number[] optional — Explicit tick positions.label: string optional — Axis label.format: string optional — Tick-label format string; the scale's kind selects how it is read. On a time scale it is a UTC date pattern of literal text plus%Y%m%d%H%M%S(%%for a percent sign), and an unknown specifier raises. On every other scale it is a numeric dialect with three forms:{:.N}for N fixed decimals,{}for plain stringification, or literal text with each{value}substituted.grid: boolean optional — Draw grid lines.color: Color optional — Axis / tick color.grid_color: Color optional — Grid-line color.
ticks: integer optional — Target tick count.tick_values: number[] optional — Explicit tick positions.label: string optional — Axis label.format: string optional — Tick-label format string; the scale's kind selects how it is read. On a time scale it is a UTC date pattern of literal text plus%Y%m%d%H%M%S(%%for a percent sign), and an unknown specifier raises. On every other scale it is a numeric dialect with three forms:{:.N}for N fixed decimals,{}for plain stringification, or literal text with each{value}substituted.grid: boolean optional — Draw grid lines.color: Color optional — Axis / tick color.grid_color: Color optional — Grid-line color.
axis: chart.BandAxis — Axis the[from, to]range spans.from: number — Range start (data space).to: number — Range end (data space).color: Color optional — Fill color.
domain: string[] — Non-empty array of category strings.padding: number optional — Gap between bands, 0..1 (default 0.1).
entries: table optional — Array of{category, value}entries. Exactly one ofentries,series, ordata.series: table optional — Array of{name?, color?, entries}series for stacked/grouped layouts; colors default from the category palette. Requiresmode.data: DataHandle optional — Tabular source; requirescategory_column. Bars aggregate engine-side per category — rows are never materialized. Rows with a null category or value are skipped.category_column: string optional — Category column to group by (data sources).value_column: string optional — Numeric column to aggregate; required for every aggregate except count.series_column: string optional — Category column splitting rows into one series per distinct value (data sources). Requiresmode; series take palette colors in first-seen order.aggregate: chart.BarsAggregate optional — Per-category aggregation for data sources. Default sum with avalue_column, count without one.mode: chart.BarsMode optional — Multi-series layout. Stacked accumulates per category from the baseline (negatives stack downward); grouped subdivides each band per series.group_padding: number optional — Gap between grouped sub-bars as a 0..1 fraction (default 0.1).orientation: chart.Orientation optional — Bar orientation (default vertical).color: Color optional — Bar color.baseline: number optional — Numeric baseline the bars grow from.name: string optional — Legend name.x_scale: Scale optional — X scale; defaults to the area's.y_scale: Scale optional — Y scale; defaults to the area's.
category: string — Category the summary belongs to.low: number — Lower whisker end.q1: number — First quartile.median: number — Median.q3: number — Third quartile.high: number — Upper whisker end.outliers: number[] optional — Points beyond the whiskers.
entries: chart.BoxEntry[] optional — Array of{category, low, q1, median, q3, high, outliers?}pre-computed summaries (low/high are the whisker ends). Exactly one ofentriesordata.data: DataHandle optional — Tabular source; requirescategory_columnandvalue_column. Summaries compute engine-side: quartiles by linear interpolation, whiskers at the farthest values inside the 1.5 IQR fences, the rest as outliers.category_column: string optional — Category column to group by (data sources).value_column: string optional — Numeric column to summarize (data sources).box_width: number optional — Box width as a 0..1 fraction of the band slot (default 0.6).orientation: chart.Orientation optional — Box orientation (default vertical). The category axis is x when vertical, y when horizontal.color: Color optional — Box and whisker color.median_color: Color optional — Median line color (defaults to black).outlier_color: Color optional — Outlier point color (defaults to the box color).name: string optional — Legend name.x_scale: Scale optional — X scale; defaults to the area's. Discovered categories append to the band scale on the category axis.y_scale: Scale optional — Y scale; defaults to the area's.
axis: chart.BrushAxis optional — Which axes the brush selects on (default x). Single-axis brushes span the full plot on the other axis.button: input.MouseButton optional — Mouse button that drags the brush (default left).color: Color optional — Selection region fill (defaults to a translucent tint).on_brush: fun(selection: chart.BrushSelection | nil) optional — Fires when a selection commits (bounds table) or a click clears it (nil).
x_min: number optional — Selection lower x bound in data space (epoch-ms on time scales). Absent when the brush axis isy.x_max: number optional — Selection upper x bound in data space. Absent when the brush axis isy.y_min: number optional — Selection lower y bound in data space. Absent when the brush axis isx.y_max: number optional — Selection upper y bound in data space. Absent when the brush axis isx.
pos: Vec3 optional — Bottom-left corner of the plot area within the canvas (Y-up, center origin); defaults to the origin.width: number optional — Plot area width in canvas units.height: number optional — Plot area height in canvas units.margin: chart.Margin optional — Inner margins reserved for axes / labels.x_scale: Scale optional — Scale handle mapping data values to the X axis.y_scale: Scale optional — Scale handle mapping data values to the Y axis.background: Color optional — Background fill color for the plot area.
rows: integer — Grid rows.columns: integer — Grid columns.pos: Vec3 optional — Bottom-left corner of the whole grid within the canvas (Y-up, center origin); defaults to the origin.width: number — Total grid width in canvas units; cells divide it evenly aftergap.height: number — Total grid height in canvas units; cells divide it evenly aftergap.gap: number optional — Spacing between cells (default 16).margin: chart.Margin optional — Inner margins reserved for axes / labels, per cell.x_scale: Scale optional — One X scale shared by every cell — pan / zoom on any cell moves all of them. Omit for an independent scale per cell.y_scale: Scale optional — One Y scale shared by every cell. Omit for an independent scale per cell.background: Color optional — Background fill color, per cell.
categories: string[] optional — Category names in color order. Unlisted categories register first-seen on lookup.colors: Color[] optional — One color per category, cycled past the end. Defaults to the built-in qualitative palette.
colors: Color[] optional — Array of at least two color stops. Exactly one ofcolorsorpalette.palette: chart.Palette optional — Built-in ramp preset. Exactly one ofcolorsorpalette.domain: table | string optional —{min, max}numeric bounds, or"auto"to fit the data.clamp: boolean optional — Clamp out-of-domain inputs to the end stops (default true).
lines: boolean optional — Draw the crosshair lines (default true).line_color: Color optional — Crosshair line color.readout: boolean optional — Show the value readout (default true).readout_color: Color optional — Readout text color.mark_values: boolean optional — Highlight nearest mark values (default true).
data: chart.DataPos — Cursor in data space. Exact for time scales (full-precision epoch-ms).world: Vec3 — Cursor in canvas space.in_area: boolean — Whether the cursor is inside the plot area's inner rect.
points: table optional — Inline{x, y}points array.data: DataHandle optional — Bind to a tabular data source.view: DataView optional — Bind to a streaming data view.x_column: string optional — X column name (data / view marks).y_column: string optional — Y column name (data / view marks).x_scale: Scale optional — X scale; defaults to the area's.y_scale: Scale optional — Y scale; defaults to the area's.color: Color optional — Mark color.name: string optional — Legend name.max_points: integer optional — Ring-buffer cap for inline-points marks.on_error: function optional — Called when the data source fails to load.
x: number — Data-space x. Exact for time scales (full-precision epoch-ms).y: number — Data-space y.
cells: table optional — Array of{x, y, value}cells (x/y are category strings). Exactly one ofcells,matrix, ordata.matrix: table optional — Row-major{{number, ...}, ...}values; requiresx_categoriesandy_categories(row index followsy_categories).x_categories: string[] optional — Column categories formatrix.y_categories: string[] optional — Row categories formatrix.data: DataHandle optional — Tabular source; requiresx_columnandy_column. Cells aggregate engine-side per category pair.x_column: string optional — Category column for cell columns (data sources).y_column: string optional — Category column for cell rows (data sources).value_column: string optional — Value column to aggregate; required for sum/mean.aggregate: chart.HeatAggregate optional — Cell aggregation for data sources. Default mean with avalue_column, count without one.color_scale: ColorScale — Maps cell values to colors. A pending domain fits the cell extent and keeps tracking it.gap: number optional — Pixel gap between cells (default 0).name: string optional — Legend name.x_scale: Scale optional — Band scale for columns; defaults to the area's. Discovered categories are appended in first-seen order.y_scale: Scale optional — Band scale for rows; defaults to the area's. Discovered categories are appended in first-seen order.
points: table optional — Inline{{x, y}, ...}pairs to bin. Exactly one ofpointsordata.data: DataHandle optional — Tabular source; requiresx_columnandy_column.x_column: string optional — Numeric column for x (data sources).y_column: string optional — Numeric column for y (data sources).x_bins: number | string optional — Bin count for x, or"auto"(default).y_bins: number | string optional — Bin count for y, or"auto"(default).normalize: chart.Histogram2dNormalize optional — Cell values (default count).color_scale: ColorScale — Maps cell values to colors. A pending domain fits the cell extent and keeps tracking it across zoom re-bins.gap: number optional — Pixel gap between cells (default 0).name: string optional — Legend name.x_scale: Scale optional — Numeric x scale; defaults to the area's.y_scale: Scale optional — Numeric y scale; defaults to the area's.
values: number[] optional — Inline values to bin. Exactly one ofvaluesordata.data: DataHandle optional — Tabular source; requirescolumn. Binning runs engine-side over the column — rows are never materialized.column: string optional — Column to bin (data sources).bins: number | string optional — Bin count, or"auto"(default) for width-by-spread with a count floor. Mutually exclusive withbin_width.bin_width: number optional — Explicit bin width in data units. Mutually exclusive withbins.normalize: chart.HistogramNormalize optional — Bar heights (default count).range: table optional —{min, max}bin extent. Defaults to the data extent; a zoomed x scale re-bins over the visible domain.color: Color optional — Bar color.name: string optional — Legend name.x_scale: Scale optional — X scale; defaults to the area's.y_scale: Scale optional — Y scale; defaults to the area's.
label: string — The item's label text.color: Color optional — The item's swatch color; white when omitted.
kind: chart.LegendKind optional — Legend form. Defaults to discrete swatch items; a gradient legend renderscolor_scale's ramp with its domain bounds as labels.color_scale: ColorScale optional — Color scale rendered as the gradient ramp; required for gradient legends, rejected otherwise. A pending domain renders once its fit lands.items: chart.LegendItem[] | string optional — Legend entries array, or"auto"; derived from named marks when omitted. Only applies to the default legend form.pos: Vec2 optional — Panel position.anchor: chart.LegendAnchor optional — Corner / edge the legend anchors to.orientation: chart.Orientation optional — Stack direction of legend items.background: Color optional — Panel background color.border: Color optional — Panel border color.color: Color optional — Item label color.
items: table optional — Legend entries array.pos: table optional —{x, y}panel position.anchor: chart.LegendAnchor optional — Corner / edge the legend anchors to.orientation: chart.Orientation optional — Stack direction of legend items.background: Color optional — Panel background color.border: Color optional — Panel border color.color: Color optional — Item label color.
Inherits all fields of chart.DataMarkBase.
width: number optional — Stroke width.series_column: string optional — Category column splitting rows into one series per distinct value (data sources only). Each series renders its own polyline with per-series downsampling and null-gap handling, takes a color fromcolor_scaleor the category palette in first-seen order, and contributes its own legend item.color_scale: ColorScale optional — Category color scale assigning per-series colors; requiresseries_column.readout: chart.ReadoutMode optional — Crosshair readout interpolation mode.
Inherits all fields of chart.ScaleBase.
follow: number optional — Rolling-window size for streaming marks.
Inherits all fields of chart.ScaleBase.
base: number optional — Log base (default 10; must be positive and not 1).follow: number optional — Rolling-window size for streaming marks.
top: number optional — Top inset.right: number optional — Right inset.bottom: number optional — Bottom inset.left: number optional — Left inset.
color: Color optional — New mark color.width: number optional — Line / rule stroke width.name: string optional — Legend name.points: table optional — Replacement points array (inline-points marks only).visible: boolean optional — Show or hide the mark.text: string optional — Text-mark string.font_size: number | string optional — Text-mark font size — a number (px) or a unit string like "1.5rem"/"50vw".font_weight: number | FontWeight optional — Text-mark weight on the brand font's variable axis.font_style: FontStyle optional — Text-mark face.
row: integer — Source-data row index of the nearest point.x: number — Data-space x of the nearest point. Exact for time scales (full-precision epoch-ms read from the source rows).y: number — Data-space y of the nearest point.distance: number — Distance to the query point, in pixel space.value: number optional — Cell value (heatmap marks), category median (box marks), or category total (bars marks).x_category: string optional — Cell x-axis category, for categorical heatmap marks.y_category: string optional — Cell y-axis category, for categorical heatmap marks.
x: boolean optional — Pan / zoom the x axis.y: boolean optional — Pan / zoom the y axis.pan_button: input.MouseButton | boolean optional — Drag button for panning, orfalseto disable.zoom: boolean optional — Enable scroll-wheel zoom.zoom_step: number optional — Zoom step per scroll tick.box_zoom_button: input.MouseButton | boolean optional — Drag button for box-zoom, orfalseto disable.double_click_reset: boolean optional — Reset view on double-click.double_click_ms: number optional — Double-click window in milliseconds.
pos: Vec2 optional — Area position within the canvas.width: number optional — Area width.height: number optional — Area height.margin: number | table optional — Inner margin: a scalar or{top, bottom, left, right}.x_scale: Scale optional — Replacement x scale.y_scale: Scale optional — Replacement y scale.background: Color | boolean optional — Fill color to pin, orfalseto opt back into the theme default.
Inherits all fields of chart.DataMarkBase.
size: number optional — Dot size.size_column: string optional — Column driving per-dot size.size_scale: Scale optional — Scale whose domain normalizessize_columnvalues. Required withsize_column.size_range: table optional —{min, max}output dot sizes in pixels forsize_columnvalues. Required withsize_column.color_column: string optional — Column driving per-dot color.color_scale: ColorScale optional — Color scale forcolor_column.
force: boolean optional — Always refit, even over scales the user has pinned with pan / zoom.
orientation: chart.Orientation — Reference-line direction.value: number | string — Data-space position of the line. A category name resolves to the band scale's slot center when the mark is created; raises when the axis scale isn't a band scale or the category is unknown.color: Color optional — Line color.width: number optional — Line width.value_label: string optional — Optional label drawn at the line.
domain: table | string optional —{min, max}numeric bounds, or"auto"to fit the data.nice: boolean optional — Extend the domain to round numbers.clamp: boolean optional — Clamp out-of-domain inputs into the range.
pos: Vec2 | chart.TextPos — Data-space anchor position. In the table form a category name resolves to the band scale's slot center when the mark is created; raises when that axis's scale isn't a band scale or the category is unknown.text: string — Annotation text.color: Color optional — Text color.font_size: number | string optional — Font size — a number (px) or a unit string like "1.5rem"/"50vw".font_weight: number | FontWeight optional — Text weight on the brand font's variable axis (default the theme's body weight).font_style: FontStyle optional — Text face (default upright).align: chart.TextAnchor optional — Anchor point of the text box relative topos.offset: Vec2 optional — Pixel offset frompos.
x: number | string — Anchor x — a data value, or a category name on a band x scale.y: number | string — Anchor y — a data value, or a category name on a band y scale.
text: string optional — Title text.font_size: number | string optional — Font size — a number (px) or a unit string like "1.5rem"/"50vw" (default 16).font_weight: number | FontWeight optional — Title weight on the brand font's variable axis (default the theme's heading weight).font_style: FontStyle optional — Title face (default upright).color: Color optional — Title color.side: chart.TitleSide optional — Edge the title sits on (default top).align: chart.TitleAlign optional — Horizontal alignment (default left).inset: number optional — Inset from the edge (default 10).
Inherits all fields of data.ColumnSelectBase.
size: integer optional — Rows per batch; each source batch is sliced into chunks of at most this many rows.
columns: string[] optional — Column names to include; all columns if omitted.
x_min: number | string optional — Lower x bound: a number, or"auto"to fit the data.x_max: number | string optional — Upper x bound: a number, or"auto".y_min: number | string optional — Lower y bound: a number, or"auto".y_max: number | string optional — Upper y bound: a number, or"auto".
Inherits all fields of data.RangeBounds.
x_column: string — Column name for the x axis.y_column: string — Column name for the y axis.strategy: data.DownsampleStrategy optional — Downsampling strategy (defaultlttb_pixel).pixel_width: number optional — X-axis downsampling pixel budget (defaults from the canvas or 400).pixel_height: number optional — Y-axis downsampling pixel budget (defaults from the canvas or 300).canvas: DrawCanvas optional — Draw canvas to size the pixel budget from.
label: string — The choice as shown.value: any optional — Delivered to on_choice when picked; nil is allowed and delivered as nil.
text: string — The entry's full text.speaker: string optional — Speaker attribution, when the entry carries one.lines: string[] — The text word-wrapped at a fixed 46 characters; unbreakable tokens are hard-split so no line overflows.shown: integer — Characters revealed so far by the typewriter clock (a fixed 55 per second; reveal marks may dwell it).revealed: boolean — The whole text is on display.choices: string[] optional — Choice labels, present on ask entries.selected: integer optional — 1-based selected choice, present on ask entries.
confirm: string optional — Action name for the advance gesture; defaults tointeract.
text: string — The line's text.speaker: string optional — Speaker attribution.on_done: fun() optional — Fired when the player advances past this line.
at: integer — 1-based character offset into the entry's text; whitespace runs count as one space.hold: number optional — Seconds the reveal clock dwells one character short of the mark.on_cross: fun() optional — Fired as the reveal passes the mark; a forced reveal fires it immediately.
id: string — The entry's id within the collection — whatacktakes andon_ackcarries.timestamp: integer — Write time, UNIX microseconds.author: string optional — The verified writer identity. Absent on local scope, which has no author concept.
on_add: fun(value: any, meta: documents.CollectionMeta) — Fired once per distinct entry, backfill included, up tomaxentries.max: integer optional — Bound on on_add fires. Entries past it still sync and are counted bycount(); they just no longer reach on_add. Default 1024.max_per_author: integer optional — Bound on on_add fires per verified author. Past it that author's further entries no longer reach on_add — they still sync, still count towardcount(), and still consume the globalmax, which applies on top of this. Requires a network-scope document.since: integer optional — Observe only entries written at or after this UNIX-microseconds timestamp. Entries older than it are excluded from the backfill query and the live window, and never reach on_add orcount().authors: string[] optional — Observe only these writers' entries (identity keys, asmeta.author). Requires a network-scope document. Entries still sync; the filter runs on this client before delivery, narrowing the backfill query only when a single author is listed.schema: table<string, documents.SchemaField> optional — Declarative per-entry validation, keyed by field name. An entry that fails — wrong type, out of bounds, a missing required field, or any undeclared field — is dropped whole before dedupe: it never reaches on_add and never counts. The schema declaration itself is validated here and raises on unknown keys or malformed specs.on_ack: fun(id: string) optional — Fired at most once per entry this handle added (or, on network scope, authored), when a reader acknowledges it viaack. The receipt carries the entry id only — no reader identity, and no proof: it is an anonymous, unauthenticated courtesy signal.
identity: string optional — Whose communal namespace to open. Defaults to your own (documents.identity).prefix: string optional — Sync, read, and observe only this key subtree.since: integer optional — Sync only entries written at or after this UNIX-microseconds timestamp.authors: string[] optional — Sync only these writers' entries (identity keys, asmeta.author/documents.identity).
value: any — The stored value.meta: documents.Meta — Write metadata.
author: string optional — Read this writer's entry at the key instead of newest-wins across writers.
to: string optional — Receiver identity key the grant is bound to. Omitted mints a bearer grant — anyone holding the encoded string holds its authority.mode: documents.GrantMode optional — Never wider than the granting handle's own mode. Defaults to"read".prefix: string optional — Narrow the grant to this key subtree.valid_days: integer optional — Bound the grant's validity window from now. Defaults to the granting handle's own window.
timestamp: integer — Write time, UNIX microseconds.author: string optional — The writer's identity key. Absent on local-scope writes, which have no author concept.
Inherits all fields of documents.ScopedOptions.
name: string — Stable document name; the same name and scope share one document. The name locates the document; the lease and minted capabilities authorize.prefix: string optional — Sync, read, and observe only this key subtree.since: integer optional — Sync only entries written at or after this UNIX-microseconds timestamp.authors: string[] optional — Sync only these writers' entries (identity keys, asmeta.author/documents.identity).
prefix: string optional — Sync, read, and observe only this key subtree.since: integer optional — Sync only entries written at or after this UNIX-microseconds timestamp.authors: string[] optional — Sync only these writers' entries (identity keys, asmeta.author/documents.identity).
author: string optional — Keep only this writer's entries.since: integer optional — Keep only entries written at or after this UNIX-microseconds timestamp.before: integer optional — Keep only entries written before this UNIX-microseconds timestamp (half-open).
type: documents.SchemaFieldType — The field's declared type.max_len: integer optional — Maximum byte length; string fields only.min: number optional — Inclusive lower bound; integer and number fields only.max: number optional — Inclusive upper bound; integer and number fields only.values: string[] optional — The admitted strings; enum fields only, at least one.optional: boolean optional — An absent field passes; a present one still validates.
scope: documents.Scope optional — Backend:"network"replicates with other clients and requires thenetworkcapability. Defaults to"local".
pos: Vec2 optional — Target position; the primitive's current z (layer) is kept.rotation: number optional — Target rotation in radians (about Z).scale: Vec2 optional — Target scale (x, y).color: Color optional — Target color, blended perceptually (Oklab, likeColor:lerp). Writes the same color slotupdate{color=}writes.opacity: number optional — Target alpha 0.0-1.0 — theopacityproperty's value, so it propagates to children.duration: number optional — Tween duration in seconds (default 1).easing: Easing optional — Easing curve (default linear).looping: boolean optional — Ping-pong loop the tween (default false).
Inherits all fields of draw.DrawShapeOptions.
pos: Vec2 | Vec3 optional — Center position (default origin); without an explicit z the shape auto-stacks in creation order.radius: number optional — Arc radius in pixels (default 50).start_angle: number optional — Start angle in radians (0 = +x axis, increasing counterclockwise; default 0).end_angle: number optional — End angle in radians (default pi/2).
Inherits all fields of physics.BodyOptions.
pos: Vec3 — Initial world position of the body (vec3; vec2 accepted, z = 0).
pos: Vec3 optional — Center position in draw space (default origin).rotation: number optional — Rotation in radians, counter-clockwise (default 0).scale: Vec2 optional — Per-axis scale (default{1, 1}).size: Vec2 optional — Rendered size in draw units ({w, h}), overriding the sprite's or source's own size (a render target defaults to its logical size).material: Shader optional — Shader material to render with instead of the plain textured quad. 2D surfaces take aShader;Materialhandles are 3D-only.
Inherits all fields of draw.DrawShapeOptions.
Inherits all fields of draw.DrawShapeOptions.
from: Vec2 | Vec3 optional — Start point (default origin).to: Vec2 | Vec3 optional — End point (default (100, 100)). The line renders at one depth: the first explicit z among the endpoints, else it auto-stacks in creation order.color: Color optional — Line color.width: number optional — Line width in pixels (default 1).
font_size: number | string optional — Font size — a number (px) or a unit string like "1.5rem"/"50vw" (default 16).font_weight: number | FontWeight optional — Weight to measure at — a number on the variable weight axis, or a weight name (boldis the heaviest); defaults to the brand body weight, the same default the renderer uses.font_style: FontStyle optional — Face to measure with: upright, the calligraphic cursive, or a mechanical slant; defaults to upright, the same default the renderer uses.max_width: number optional — Wrap width in draw units; unconstrained (single line) when omitted.
width: number optional — Canvas width in pixels (default 400).height: number optional — Canvas height in pixels (default 300).background: Color optional — Fill color applied before each frame; omit for transparent.pixel_perfect: boolean optional — Snap rendering to the pixel grid (default false).
pan_button: input.MouseButton optional — Mouse button that pans while dragged (default left).zoom: boolean optional — Enable scroll-wheel zoom (default true).zoom_step: number optional — Multiplicative zoom change per scroll notch, > 1 (default 1.1).min_zoom: number optional — Smallest zoom factor, where 1 is the canvas's default framing (default 0.1).max_zoom: number optional — Largest zoom factor (default 10).
color: Color optional — Fill / stroke color (default white).z: number optional — Depth layer within the canvas; auto-stacks in creation order when omitted.material: Shader optional — Shader material to apply. 2D surfaces take aShader;Materialhandles are 3D-only.width: number optional — Stroke width in canvas units (default 2).
Inherits all fields of draw.DrawShapeOptions.
points: Vec2[] — Vertices (array of vec2, min 3).z: number optional — Depth ordering; auto-stacks in creation order when omitted.
Inherits all fields of draw.DrawShapeOptions.
Inherits all fields of draw.DrawShapeOptions.
pos: Vec2 | Vec3 optional — Top-left position (default origin); without an explicit z the shape auto-stacks in creation order.width: number optional — Rectangle width in pixels (default 100).height: number optional — Rectangle height in pixels (default 50).radius: number optional — Corner radius in pixels (default 10).
pos: Vec2 optional — Camera center in draw coordinates.zoom: number optional — Zoom factor (>1 in, <1 out).
pos: Vec2 | Vec3 optional — Position (default origin); without an explicit z the text auto-stacks in creation order.text: string — Text content.font_size: number | string optional — Font size: a number (pixels) or a unit string like"1.5rem"/"50vw"/"4vmin"(default 16).color: Color optional — Text color (default white).max_width: number optional — Maximum line width in pixels; enables wrapping when set.align: draw.TextAlign optional — Horizontal alignment (defaultleft).linebreak: draw.LineBreak optional — Line-break mode (defaultword).font_weight: number | FontWeight optional — Font weight: a number on the variable weight axis, or a weight name (boldis the heaviest). Defaults to the brand body weight.font_style: FontStyle optional — Font face: upright, the calligraphic cursive, or a mechanical slant. Defaults to upright.spans: (draw.TextSpan | DrawPrimitive)[] optional — Rich-text spans: each entry is a{ text, color, font_size }table or a detached span handle.
width: number — Rendered width in draw units.height: number — Rendered height in draw units.
text: string — Span text.color: Color optional — Span color; inherits the parent when omitted.font_size: number | string optional — Span font size — a number (px) or a unit string like "1.5rem"/"50vw"; inherits the parent when omitted.font_weight: number | FontWeight optional — Span weight — a number on the variable weight axis, or a weight name (boldis the heaviest); inherits the parent when omitted.font_style: FontStyle optional — Span face: upright, the calligraphic cursive, or a mechanical slant; inherits the parent when omitted.
text: string — Span text.color: Color optional — Text color.font_size: number | string optional — Span font size: a number (pixels) or a unit string like"1.5rem"/"50vw"/"4vmin"(inherits the parent when omitted).font_weight: number | FontWeight optional — Span weight: a number on the variable weight axis, or a weight name (boldis the heaviest). Inherits when omitted.font_style: FontStyle optional — Span face: upright, the calligraphic cursive, or a mechanical slant. Inherits when omitted.
columns: number — Number of columns in the grid.rows: number — Number of rows in the grid.
pos: Vec2 | Vec3 optional — New position (an offset for groups); a vec2 keeps the current depth. Unchanged when omitted.color: Color optional — New color. Unchanged when omitted.material: Shader optional — Shader handle to apply. Unchanged when omitted.rotation: number optional — Rotation in radians CCW. Unchanged when omitted.scale_x: number optional — Horizontal scale factor. Unchanged when omitted.scale_y: number optional — Vertical scale factor. Unchanged when omitted.text: string optional — New text content. Unchanged when omitted.font_size: number | string optional — New font size: a number (pixels) or a unit string like"1.5rem"/"50vw"/"4vmin". Unchanged when omitted.max_width: number optional — Maximum line width in pixels; enables wrapping. Unchanged when omitted.align: draw.TextAlign optional — Horizontal alignment. Unchanged when omitted.font_weight: number | FontWeight optional — New font weight: a number on the variable weight axis, or a weight name (boldis the heaviest). Unchanged when omitted.font_style: FontStyle optional — New font face: upright, the calligraphic cursive, or a mechanical slant. Unchanged when omitted.spans: (draw.TextSpan | DrawPrimitive)[] optional — Rich-text spans to set: each entry is a{ text, color, font_size }table or a detached span handle.
Inherits all fields of events.AppEvent.
x: number — New window x.y: number — New window y.width: number — New window width.height: number — New window height.
Inherits all fields of events.AppEvent.
width: number — Requested design-canvas width.height: number — Requested design-canvas height.
Inherits all fields of events.AppEvent.
x: number — Press x within the frame.y: number — Press y within the frame.
Inherits all fields of events.AppEvent.
mode: screen.FullscreenMode — Requested fullscreen mode.
Inherits all fields of events.AppEvent.
issuer: string — Issuer the child wants to sign in against.prompt: string optional — OIDC prompt hint, if set.login_hint: string optional — OIDC login_hint, if set.
Inherits all fields of events.AppEvent.
permission: app.Permission — The capability the descendant is requesting.reason: string optional — The justification the requester supplied; absent when none was given.request: PermissionRequest — The pending request — answer it now, or stash it to answer on a later frame.
Inherits all fields of events.AppEvent.
width: number — Requested window width.height: number — Requested window height.
Inherits all fields of events.AppEvent.
app_name: string — The spawned app's name.title: string optional — Window title, if the app set one.has_bounds: boolean — Whether the spawn specified window bounds.x: number — Window x (meaningful when has_bounds).y: number — Window y (meaningful when has_bounds).width: number — Window width (meaningful when has_bounds).height: number — Window height (meaningful when has_bounds).has_ui: boolean — Whether the spawned app has a UI.
Inherits all fields of events.AppEvent.
app_name: string — The app's name.minimized: boolean — Whether the app is now minimized.
Inherits all fields of events.AppEvent.
mode: screen.StretchMode — Requested content stretch mode.
Inherits all fields of events.AppEvent.
app_name: string — The terminated app's name.
Inherits all fields of events.AppEvent.
zoom: number — Requested zoom multiplier.
online: boolean — True while a deployment connection is up; a build without a network layer reports false. The callback fires once right after subscribing, with the current state, then again on every connectivity transition.
sub: string — OIDC subject identifier.issuer: string — OIDC issuer URL.email: string optional — User email, if the provider returned one.name: string optional — Display name, if the provider returned one.claims: table<string, any> — The verified ID-token claims.
error_kind: string — Diagnostic failure category.error_message: string — Human-readable failure detail.skew_secs: number optional — Clock-skew seconds, for time-related failures.
sub: string — OIDC subject identifier.issuer: string — OIDC issuer URL.email: string optional — User email, if the provider returned one.name: string optional — Display name, if the provider returned one.claims: table<string, any> — The verified ID-token claims.
scale_factor: number — New OS display scale factor.
width: number — New window width, logical pixels.height: number — New window height, logical pixels.
zoom: number — New end-user zoom multiplier.
ascent: number — Baseline to the top of the em box, in pixels.descent: number — Baseline to the bottom of the em box, in pixels (a positive distance downward).line_height: number — Vertical advance between consecutive baselines, in pixels.
x: number — Starting position, in cells.y: number — Starting position, in cells.speed: number — Movement speed, in cells per second.blocked: integer[] optional — Cell values the agent will not path through.repath: number optional — Repath cadence in seconds while a target is set. Absent, the agent paths once per set_target (and when it has no path yet).arrive_radius: number optional — Stop this many cells short of the target center instead of standing on it -- for follow-at-distance movers. Default 0 (arrive on the cell).stop_before: integer[] optional — Cell values the agent paths through but will not walk into: the walk halts flush before such a cell and the advance result carries it asstopped. Handle the cell (open the door, clear the line) and the walk resumes on its own once the cell's value changes.
x: number — position after the step, in cellsy: number — position after the step, in cellsarrived: boolean — the target cell has been reachedblocked: boolean — a target is set but no path to it existsstopped: grid.AgentStop optional — when the walk halted before a stop_before cell: the cell and its value
x: integer — the halting celly: integer — the halting cellvalue: integer — the cell's value at the halt
x: integer — waypoint celly: integer — waypoint cell
alive: integer[] — Cell values considered alive this generation.birth: integer[] — Live-neighbour counts that turn a dead cell alive.survival: integer[] — Live-neighbour counts that keep a live cell alive.alive_value: integer optional — Value written to cells alive next generation (default 1).dead_value: integer optional — Value written to cells dead next generation (default 0).
x: integer — Cell column.y: integer — Cell row.
match: integer[] — Cell values counted as matching neighbours.
sources: grid.DijkstraSource[] — Weighted source cells the distance field flows out from.blocked: integer[] — Cell values treated as impassable walls.
x: integer — Source cell x coordinate.y: integer — Source cell y coordinate.score: number optional — Starting distance score (default 0).
type: grid.DistanceType optional — Metric used to measure the distance (default euclidean).
range: integer — Maximum sight radius in cells.opaque: integer[] — Cell values that block line of sight.
thresholds: number[] optional — Ascending noise cutoffs partitioning samples into buckets.values: integer[] optional — Cell value per bucket; length must equal len(thresholds)+1.offset_x: number optional — Horizontal offset added to each cell's sample coordinate (default 0).offset_y: number optional — Vertical offset added to each cell's sample coordinate (default 0).
blocked: integer[] — Cell values treated as impassable walls.
match: integer[] — Cell values the fill is allowed to spread into.
solid: integer[] — Cell values the box collides with.
distance: grid.DistanceType optional — Metric used to assign cells to the nearest hive (default euclidean).seed: integer optional — Seed for deterministic hive placement. Omitting bothseedandrngdraws from an engine-internal source thatrandom.newstreams do not affect.rng: Rng optional — Draw hive placement from this stream (advancing it). Mutually exclusive withseed.
issuer: string — OIDC issuer name to sign in against.prompt: string optional — OIDCpromptparameter (e.g.login,consent).login_hint: string optional — Pre-filled login hint passed to the authorization endpoint.
tile_size: Vec2 — Cell size in pixels ({w, h}).columns: number — Number of columns in the grid.rows: number — Number of rows in the grid.padding: Vec2 optional — Gap in pixels between cells (default none).offset: Vec2 optional — Pixel offset of the grid's top-left from the image origin (default none).
width: number — Image width in pixels. Must be positive.height: number — Image height in pixels. Must be positive.
color: Color optional — Tint multiplied with the texture (default white = unchanged).flip_x: boolean optional — Mirror horizontally (default false).flip_y: boolean optional — Mirror vertically (default false).size: Vec2 optional — Rendered size in draw units ({w, h}); defaults to the cell/image pixel size.
width: integer — The widest line's advance, in pixels.height: integer — Line count times the font's cell height, in pixels.
keys: input.Key[] optional — Keys that trigger the action.mouse_buttons: input.MouseButton[] optional — Mouse buttons that trigger the action.gamepad_buttons: input.GamepadButton[] optional — Gamepad buttons (on any connected pad) that trigger the action.touch: boolean optional — When true, any screen touch triggers the action (defaults to false).
strong: number optional — Strong (low-frequency) motor intensity, 0..1 (defaults to 0).weak: number optional — Weak (high-frequency) motor intensity, 0..1 (defaults to 0).duration: number optional — Rumble duration in seconds (defaults to 0.1).
id: integer — Identifier for the touch, stable from press to release. The system may reuse an id after the touch ends.pos: Vec2 — Current position in window pixels (same frame asmouse_position).start_pos: Vec2 — Position where the touch started, in window pixels.force: number optional — Pressure of the touch, normalized toward 1; absent when the hardware doesn't report pressure.
Inherits all fields of material.PbrMaterialOptions.
texture: Image optional — Base-color texture from an image asset.texture_source: Image | DrawCanvas | Scene optional — Base-color texture from a source handle (pixel / draw canvas / scene).normal_map: Image optional — Tangent-space normal map.occlusion: Image optional — Ambient-occlusion map (grayscale; darkens crevices).metallic_roughness: Image optional — Combined metallic (blue channel) + roughness (green channel) map.emissive_texture: Image optional — Emissive map, modulated by the emissive color.alpha_mode: material.AlphaMode optional — Transparency handling (default opaque).alpha_cutoff: number optional — Threshold for themaskalpha mode, 0..1 (default 0.5); ignored by other modes.double_sided: boolean optional — Render both faces, disabling back-face culling (default false).reflectance: number optional — Specular reflectance at normal incidence, 0..1 (default 0.5).ior: number optional — Index of refraction (default 1.5).clearcoat: number optional — Clearcoat layer strength, 0..1 (default 0, no clearcoat).clearcoat_roughness: number optional — Clearcoat layer perceptual roughness, 0..1 (default 0).
color: Color optional — Base color (default white).
color: Color optional — New base color.metallic: number optional — Metallic factor (0..1).roughness: number optional — Perceptual roughness (0..1).emissive: Color optional — Emissive color.source: Image | DrawCanvas | Scene optional — Base-color texture source (pixel / draw canvas / scene); omit to leave unchanged.normal_map: Image optional — Tangent-space normal map.occlusion: Image optional — Ambient-occlusion map (grayscale).metallic_roughness: Image optional — Combined metallic + roughness map.emissive_texture: Image optional — Emissive map, modulated by the emissive color.alpha_mode: material.AlphaMode optional — Transparency handling.alpha_cutoff: number optional — Threshold for themaskalpha mode, 0..1.double_sided: boolean optional — Render both faces (disables back-face culling).reflectance: number optional — Specular reflectance at normal incidence, 0..1.ior: number optional — Index of refraction.clearcoat: number optional — Clearcoat layer strength, 0..1.clearcoat_roughness: number optional — Clearcoat layer perceptual roughness, 0..1.
topic: string — Topic to publish or subscribe on.scope: messaging.Scope optional — Message scope (defaults to in-process); the networked scope requires thenetworkcapability.
id: string — The peer's presence id — stable for one handle's lifetime, minted fresh per handle.payload: any — The peer's latest published payload.age: number — Seconds since the peer's latest beacon.
ttl: number optional — Seconds a peer stays listed after its last beacon. Default 10.max: integer optional — Peer cap; past it the least recently seen peer is evicted. Default 64, at most 1024.
Inherits all fields of messaging.MessageOptions.
payload: any — Message payload, serialized as-is.
Inherits all fields of messaging.MessageOptions.
callback: function — Function invoked with each received message payload.
seed: integer optional — Random seed for the noise field.frequency: number optional — Spatial frequency of the noise.
Inherits all fields of noise.BaseOptions.
distance: noise.CellularDistance optional — Distance metric.return_type: noise.CellularReturn optional — Return mode.jitter: number optional — Cell-point jitter amount.
source: noise.NoiseSource optional — Base noise kind the fractal layers.type: noise.FractalType optional — Fractal combination mode.seed: integer optional — Random seed for the noise field.frequency: number optional — Spatial frequency of the base noise.octaves: integer optional — Number of fractal layers summed.lacunarity: number optional — Frequency multiplier between successive octaves.gain: number optional — Amplitude multiplier between successive octaves.weighted_strength: number optional — How much each octave's amplitude is weighted by the previous octave's value.ping_pong_strength: number optional — Folding strength used by the ping-pong fractal mode.
kind: string — What changed:"added"for a newly listed entry,"updated"for a re-observed one.namespace: string — The catalog namespace it lives in.package: PackageRef — A reference to the changed package.
kind: packages.Kind optional — Restrict results to one package kind; all kinds if omitted.namespace: string optional — Restrict to one registry namespace; every connected registry if omitted.
namespace: string optional — Catalog namespace to look up in; defaults to the bootstrap namespace.
kind: packages.InstallChangeKind — What happened to the library entry.namespace: string — The registry namespace the entry belongs to.package: PackageRef — The affected library entry. For"uninstalled"it is built from the removed record, so it stays complete even when the version is no longer in any catalog.
paid: boolean — Always true — a free package returns nil instead.price: integer optional — Amount in the currency's minor unit (e.g. cents); absent while the package is not listed for sale yet.currency: string optional — ISO 4217 currency code, lowercase; absent while the package is not listed for sale yet.
namespace: string — The registry's namespace.available: boolean — Whether the registry currently has a reachable provider. Refreshed periodically; a registry never yet observed reportstrue. An unavailable registry keeps its catalog entries visible, but installs of uncached content from it fail.
Inherits all fields of packages.FilterBase.
query: string optional — Glob pattern (* / ?) matched against entry name and description.tags: string[] optional — Tags an entry must all carry to match; absent means no tag filter.
rate: number optional — Particles spawned per second while emitting (default 10).seed: integer optional — Spawn-stream seed; the same configuration and seed reproduce the same pattern, and distinct seeds keep identically configured emitters from animating in lockstep (default 0).max_particles: integer optional — Live-particle cap 1..100000 (default 1000); emission pauses at the cap.lifetime: number optional — Seconds each particle lives (default 2).shape: particles.Shape optional — Where particles spawn relative to the emitter.velocity: particles.VelocityRange optional — Initial velocity, sampled per axis between min and max.gravity: Vec3 optional — Constant acceleration applied every second (default zero).size: particles.SizeOverLife optional — Particle size over its life.color: particles.ColorOverLife optional — Particle color over its life.texture: Image optional — Image drawn on each quad; untextured quads are flat color.blend: particles.Blend optional — Alpha blending or additive glow (default alpha).space: particles.Space optional — Reference frame for spawned particles (defaultworld).pos: Vec3 optional — Emitter position in the scene (default origin).
kind: particles.ShapeKind — Spawn distribution (default point).radius: number optional — Sphere radius, or the cone's base disc radius (default 0).size: Vec3 optional — Box edge lengths, centered on the emitter.angle: number optional — Cone half-angle in radians: the sampled velocity keeps its magnitude but is redirected within this angle of +Y.
start: number optional — Quad edge length at spawn (default 0.1).stop: number optional — Quad edge length at end of life (defaultstart).
max_height: number | physics.RelativeLength optional — Max step height the character climbs (default{relative=0.25}).min_width: number | physics.RelativeLength optional — Minimum free width that must remain on the step (default{relative=0.5}).include_dynamic_bodies: boolean optional — Whether dynamic bodies can act as steps (default true).
type: physics.BodyType optional — Body dynamics (defaults todynamic).shape: physics.Shape optional — Collider shape; defaults to a dimension-appropriate box.width: number optional — Box width in metres (default 1).height: number optional — Box height / capsule length in metres (default 1).depth: number optional — Box depth in metres, 3D only (default 1).radius: number optional — Sphere / capsule / cylinder / cone radius in metres (default 0.5).restitution: number optional — Bounciness, 0..1 (default 0.3).friction: number optional — Surface friction (default 0.5).mass: number optional — Mass override; unset lets the engine derive it from the collider.sensor: boolean optional — Make the body a non-colliding trigger volume (default false).points: Vec3[] optional — Vertices forconvex_hull/polyline/trimesh(vec3; vec2 accepted, z = 0).indices: integer[][] optional — Triangle index triples for thetrimeshshape.layers: integer[] optional — Collision membership: layer bit indices 0..=31 the body belongs to. Omitted = all layers.collides_with: integer[] optional — Collision filter: layer bit indices 0..=31 the body collides with. Omitted = all; an empty list = collides with nothing.lock_translation: physics.Axis[] optional — Axes to lock translation on, additive to the 2D in-plane constraints.lock_rotation: physics.Axis[] optional — Axes to lock rotation on, additive to the 2D in-plane constraints.ccd: boolean optional — Sweep this body against moving (kinematic and dynamic) bodies too when it moves fast; fast bodies always sweep static geometry so they never tunnel through it (default false).world: PhysicsWorld optional — Simulate in this minted physics world instead of the app's default one.
body: DrawPrimitive | SceneNode — The body that was hit.point: Vec3 — World-space witness point of the hit.normal: Vec3 — World-space surface normal at the hit (use it for wall-jump or facing).distance: number — Distance along the attempted movement when the hit occurred.
up: Vec2 | Vec3 optional — Floor-defining up direction; selects which contacts count as ground (default{0,1,0}). 2D uses the XY components.offset: number | physics.RelativeLength optional — Small gap kept between the character and surroundings for stability; must be > 0 (default{relative=0.01}).slide: boolean optional — Slide along blocking walls instead of stopping dead (default true).max_slope_climb_angle: number optional — Steepest slope, in radians, the character will climb; steeper surfaces act as walls (default pi/4).min_slope_slide_angle: number optional — Slope angle, in radians, at/above which the character auto-slides down (default pi/4).snap_to_ground: number | physics.RelativeLength | boolean optional — Distance to snap down onto ground after a move, keeping the character glued over dips;falsedisables (default{relative=0.2}).autostep: physics.AutostepConfig | boolean optional — Step-climbing config, orfalse/absent to disable (disabled by default — it is expensive). Needs a flat-bottomed body (cube or cylinder): the step lands the body on the ledge by only the frame's leftover motion, and a capsule's rounded bottom slides back off. The body also needs head room of its own height plusmax_heightabove where it stands, so a low ceiling stops it stepping.normal_nudge_factor: number optional — Tiny anti-stick push along contact normals while sliding (default 1.0e-4).
translation: Vec3 — The movement to apply this frame — the body is not moved; setbody.pos = body.pos + translation.grounded: boolean — Standing on ground after applyingtranslation. False while the move commanded upward motion (a jump in progress), so a launching jump is never reported grounded.sliding_down_slope: boolean — The character was let slide down a too-steep slope this frame.collisions: physics.CharacterCollision[] — Surfaces hit during the slide, in application order; empty if unobstructed.
layers: integer[] optional — Membership layer bit indices 0..=31; omitted = all layers.collides_with: integer[] optional — Filter layer bit indices 0..=31; omitted = all, an empty list = none.
type: physics.JointType optional — Joint kind; defaults tofixed.anchor1: Vec3 optional — Attachment point on the first body (local frame); defaults to the origin.anchor2: Vec3 optional — Attachment point on the second body (local frame); defaults to the origin.axis: Vec3 optional — Rotation axis (revolute) or slide axis (prismatic).angle_limits: number[] optional — Revolute-only{min, max}angle range in radians.limits: number[] optional — Prismatic-only{min, max}displacement range in metres.distance_limits: number[] optional — Distance-only{min, max}separation range in metres (equal min/max for a rigid rod).swing_limits: number[] optional — Spherical-only{min, max}swing-cone angle range in radians.twist_limits: number[] optional — Spherical-only{min, max}twist angle range in radians.motor_speed: number optional — Target motor velocity (rad/s revolute, m/s prismatic).motor_force: number optional — Maximum motor torque (revolute) or force (prismatic).motor_target: number optional — Motor target position (rad revolute, m prismatic).motor_stiffness: number optional — Spring gain towardmotor_target(default 1000 when a target is set).motor_damping: number optional — Damper gain towardmotor_speed(default 100 for velocity motors, 30 for position motors).
lock_translation: physics.Axis[] optional — Axes to lock translation on; omitted/empty = unlocked (the 2D in-plane locks always remain).lock_rotation: physics.Axis[] optional — Axes to lock rotation on; omitted/empty = unlocked (the 2D in-plane locks always remain).
layers: integer[] optional — Only include bodies in these layer bit indices 0..=31 (default all).exclude: DrawPrimitive | SceneNode optional — A body to ignore.
body: DrawPrimitive | SceneNode — The body that was hit.point: Vec3 — World-space contact point.normal: Vec3 — World-space surface normal at the hit.distance: number — Distance from the origin to the hit.
max_distance: number optional — Maximum ray length in metres (default very large).layers: integer[] optional — Only hit bodies in these layer bit indices 0..=31 (default all).exclude: DrawPrimitive | SceneNode optional — A body to ignore.solid: boolean optional — Count a ray starting inside a collider as a hit at distance 0 (default true).max_hits: integer optional — Maximum hits to return (default 64).
max_distance: number optional — Maximum ray length in metres (default very large).layers: integer[] optional — Only hit bodies in these layer bit indices 0..=31 (default all).exclude: DrawPrimitive | SceneNode optional — A body to ignore.solid: boolean optional — Count a ray starting inside a collider as a hit at distance 0 (default true).
relative: number — Fraction of the character shape's relevant extent.
shape: physics.Shape optional — 3D collider shape to cast (default cube).width: number optional — Box width (default 1).height: number optional — Box height / capsule length (default 1).depth: number optional — Box depth (default 1).radius: number optional — Sphere / capsule / cylinder / cone radius (default 0.5).rotation: Quat optional — Shape orientation (default identity).max_distance: number optional — Maximum cast length in metres (default very large).layers: integer[] optional — Only hit bodies in these layer bit indices 0..=31 (default all).exclude: DrawPrimitive | SceneNode optional — A body to ignore.
Inherits all fields of scene.Transform3dOptions.
color: Color optional — Target color, blended perceptually (Oklab, likeColor:lerp). The node gets its own copy of its material, so other nodes sharing it are unaffected; a light tweens its light color instead.opacity: number optional — Target alpha 0.0-1.0 for the material's base color. The node's material copy switches to alpha blending if it was opaque.duration: number optional — Tween duration in seconds (default 1).easing: Easing optional — Easing curve (default linear).looping: boolean optional — Loop the tween (default false).
clip: string — Animation clip label, e.g.Animation0.weight: number — Relative blend weight (normalized across the set).
pos: Vec3 optional — Target world-space position.rotation: Quat optional — Target orientation. Mutually exclusive withlook_at.look_at: Vec3 optional — World-space point to end up facing. Resolved to a target rotation once, when the tween starts — againstposwhen both are given, so the end pose faces the point; the camera does not track the point afterwards. Mutually exclusive withrotation.fov: number optional — Target vertical field of view in radians. Ignored on a non-perspective camera, like.fovassignment.duration: number optional — Tween duration in seconds (default 1).easing: Easing optional — Easing curve (default linear).
frames: integer[] — 0-based atlas cell indices in play order.fps: number optional — Frames per second (default 8). Ignored whendurationsis given.looping: boolean optional — Whether the clip repeats (default true).direction: scene.ClipDirection optional — Traversal order (default "forward").durations: number[] optional — Per-frame seconds (same length asframes); overridesfps.markers: table<integer, string> optional — 1-based frame position within this clip'sframeslist → marker name; fireson_markerwhen the playhead crosses that frame.
kind: scene.DeformKind — The deformation shape.amplitude: number optional — Peak displacement in local units (default 0.1).frequency: number optional — Spatial frequency in cycles per local unit (default 1).speed: number optional — Animation speed in radians per second (default 1).direction: Vec2 optional — Travel / bend direction in the local XZ plane (default{1, 0}).origin: Vec2 optional — Ripple center in the local XZ plane (default origin).seed: integer optional — Noise seed; same seed, same field (default 0).
Inherits all fields of scene.LightOptions.
direction: Vec3 optional — Light direction (default down).
diffuse: CubemapAsset optional — Prefiltered diffuse irradiance cubemap.specular: CubemapAsset optional — Prefiltered specular radiance cubemap.intensity: number optional — Light intensity in cd/m^2 (default 1000).
color: Color optional — Light color (default white).intensity: number optional — Luminous intensity (default 1000).shadows: boolean optional — Cast shadows (default false).
Inherits all fields of scene.Transform3dOptions.
positions: number[] optional — Flat x,y,z triplets in node-local space; sets the vertex count.normals: number[] optional — Flat x,y,z triplets; one per vertex.uvs: number[] optional — Flat u,v pairs; one per vertex.colors: number[] optional — Flat r,g,b,a quads (0..1); one per vertex.indices: integer[] optional — 1-based triangle indices, length divisible by 3. An empty array makes the mesh non-indexed (vertex-order triangles).recompute_normals: boolean optional — Recompute vertex normals after the other fields apply (smooth when indexed, flat otherwise). Mutually exclusive withnormals.
asset: SceneAsset — External glTF / GLB scene asset (fromfile:read():scene()/dir:read(rel):scene()).pos: Vec3 optional — World-space position (default origin).rotation: Quat optional — Rotation quaternion (default identity). Build withdatumhue.math.quat.from_euleretc.scale: Vec3 optional — Per-axis scale (default(1, 1, 1)).
Inherits all fields of scene.Transform3dOptions.
color: Color optional — Base color; unchanged when omitted.material: Material | Shader optional — Material handle to apply (a standard Material or a Shader); unchanged when omitted.intensity: number optional — Light intensity; unchanged when omitted.range: number optional — Light falloff range; unchanged when omitted.shadows: boolean optional — Cast shadows; unchanged when omitted.direction: Vec3 optional — Light direction; unchanged when omitted.inner_angle: number optional — Spot inner cone half-angle in radians; unchanged when omitted.outer_angle: number optional — Spot outer cone half-angle in radians; unchanged when omitted.
Inherits all fields of scene.Transform3dOptions.
color: Color optional — Base color (default unset; uses the material's color).material: Material | Shader optional — Material handle to apply (a standard Material or a Shader).subdivisions: integer optional — Grid subdivisions per side (default 0, max 254). A subdivided plane givesmesh:updateandnode:deformvertices to move.
clip: string optional — Animation clip label, e.g.Animation0,Animation1(defaultAnimation0).speed: number optional — Playback speed multiplier (default 1).looping: boolean optional — Loop the clip (default true).fade: number optional — Seconds to crossfade from the currently-playing clip (default 0, an instant cut).
speed: number optional — Playback rate multiplier; negative plays the clip in reverse. Default keeps the animator's current speed.looping: boolean optional — Override the clip's loop policy for this play. Default uses the clip's ownlooping.
Inherits all fields of scene.LightOptions.
pos: Vec3 optional — World-space position (default origin).range: number optional — Falloff range (default 20).
width: number optional — Viewport width in pixels (default 512).height: number optional — Viewport height in pixels (default 512).hdr: boolean optional — Enable HDR rendering (default false).
Inherits all fields of scene.LightOptions.
pos: Vec3 optional — World-space position (default origin).direction: Vec3 optional — Light direction (default down).range: number optional — Falloff range (default 20).inner_angle: number optional — Inner cone half-angle in radians (default 0).outer_angle: number optional — Outer cone half-angle in radians (defaultpi/4).
source: Sprite optional — The appearance to draw, fromimage:sprite()oratlas:sprite(i). Provide this orimage, not both.image: Image optional — A wholeImageto draw, as an alternative tosource. Provide this orsource, not both.pos: Vec3 optional — World-space position (default origin).billboard: scene.BillboardMode optional — How the sprite turns to face the camera; defaulty_locked(stays upright, turning horizontally toward the camera — the 2.5D character look).size_mode: scene.SpriteSizeMode optional — Whethersizeis measured in scene units or in constant on-screen pixels; defaultworld.size: Vec2 optional — Quad extent, in the unit chosen bysize_mode. Defaults to the cell aspect ratio at 1 scene-unit tall.pivot: Vec2 optional — Normalized anchor{x, y}in 0..1 (x rightward, y upward); the node position sits at this point. Default{0.5, 0}(bottom-center, feet on the floor).alpha: scene.SpriteAlphaMode optional — How transparency is handled; defaultcutout(crisp alpha-tested edges that depth-sort correctly without draw-order dependence).cutoff: number optional — Alpha-test threshold for thecutoutmode (0..1). Default 0.5.color: Color optional — Tint multiplied with the texture. Default white (unchanged).flip_x: boolean optional — Mirror horizontally. Default false.flip_y: boolean optional — Mirror vertically. Default false.shaded: boolean optional — Lit by the scene's lights when true; full-bright (unlit) when false. Default false.
width: number — Design width in points.height: number — Design height in points.
index: integer — 1-based monitor index.name: string optional — Monitor name, when the OS reports one.width: integer — Width in pixels.height: integer — Height in pixels.scale_factor: number — Device pixel ratio.refresh_rate_hz: number optional — Refresh rate in Hz, when known.is_primary: boolean — Whether this is the primary monitor.is_current: boolean — Whether the window is currently on this monitor.
width: number — Logical width in points.height: number — Logical height in points.scale_factor: number — Device pixel ratio (physical / logical).physical_width: integer — Physical width in pixels.physical_height: integer — Physical height in pixels.zoom: number — Current zoom factor.
uniforms: table optional — Table ofname = initialdeclarations the source reads asu.<name>. A number declares anf32, a vec2/vec3 its vector type, a color avec4<f32>. Capacity 16.channels: table optional — Array of up to 4 texture sources (pixel canvas, draw canvas, or scene) bound asdh_channel0..3; unset channels sample white.
type: shader.ShaderType — Shader kind.color1: Color — Primary color.color2: Color optional — Secondary color; required for every type except"solid".param1: number optional — First shader parameter (default 0).param2: number optional — Second shader parameter (default 0).animated: boolean optional — Animate the shader (default false).source: Image | DrawCanvas | Scene optional — Texture source handle (pixel / draw canvas / scene).
color1: Color optional — New primary color.color2: Color optional — New secondary color.param1: number optional — First shader parameter.param2: number optional — Second shader parameter.animated: boolean optional — Animate the shader.source: Image | DrawCanvas | Scene optional — Texture source handle; omit to leave unchanged.
year: integer — Full year (e.g. 2026).month: integer optional — Month, 1-12 (default 1).day: integer optional — Day of the month, 1-31 (default 1).hour: integer optional — Hour, 0-23 (default 0).minute: integer optional — Minute, 0-59 (default 0).second: integer optional — Second, 0-59 (default 0).
from: number | Vec2 | Vec3 | Color — Start value. Same type asto.to: number | Vec2 | Vec3 | Color — End value. Same type asfrom.duration: number — Tween duration in seconds.easing: Easing optional — Easing curve (default linear).on_update: fun(value: number | Vec2 | Vec3 | Color) — Receives the in-between value once per frame while the tween runs; the final delivery is exactlyto.on_finish: fun() optional — Runs once, after the finalon_updatedelivery. Skipped when the tween is unsubscribed before it finishes.
Inherits all fields of ui.NodeStyle.
text: string | Message — Button label (required) — a plain string, or adatumhue.i18n.t(...)message that follows the active locale.enabled: boolean optional — Whether the button starts enabled (defaulttrue). A disabled button is grayed out and ignores clicks and keyboard activation untilelem.enabled = true.on_click: function optional — Click callback.on_hover: function optional — Called when the cursor enters the button or any of its descendants.on_hover_exit: function optional — Called when the cursor leaves the button and all of its descendants.on_press: function optional — Called when a mouse button is pressed on the button.on_release: function optional — Called when a mouse button is released over the button.on_double_click: function optional — Called on a double-click: two presses on the button within the double-click window.
Inherits all fields of ui.NodeStyle.
label: string optional — Label shown beside the box; omit for a bare checkbox.checked: boolean optional — Whether it starts checked (defaultfalse).enabled: boolean optional — Whether it starts enabled (defaulttrue). A disabled checkbox ignores clicks and keyboard toggling untilelem.enabled = true.on_change: function optional — Called with the new checked state (boolean) each time the user toggles it. A programmaticelem.checked = ...write does not fire it.
Inherits all fields of ui.NodeStyle.
initial: Color | ThemedColor optional — Initial color (aColoror a theme token); default opaque white.alpha: boolean optional — Add an alpha strip and widen the hex field to#RRGGBBAA(defaultfalse, fully opaque).swatches: (Color | ThemedColor)[] optional — Preset swatches shown as a clickable row (colors or theme tokens); omit for none. Clicking one sets the color and keeps the popover open.enabled: boolean optional — Whether it starts enabled (defaulttrue).open: boolean optional — Start with the popover open (defaultfalse).on_change: function optional — Called with the pickedColorwhen the user drags the square/strips, commits the hex field, or clicks a preset. A programmaticvaluewrite does not fire it.
Inherits all fields of ui.NodeStyle.
label: string | Message — Button label (required) — a plain string, or adatumhue.i18n.t(...)message that follows the active locale.source: string | Bytes optional — The text a click places on the clipboard, captured now. A string or UTF-8Bytes(non-UTF-8 raises — the clipboard is text). Omit and bind later withelem:on_copy_sourceto keep the payload current; with none set a click does nothing.on_copy: function optional — Called after a click places the text on the clipboard. In the browser the write is asynchronous — it fires when the write is handed to the clipboard, and a rejected write logs instead.
Inherits all fields of ui.NodeStyle.
initial: integer optional — Initially-selected instant (Unix microseconds, UTC). Omit for no initial selection.min: integer optional — Earliest selectable instant (Unix microseconds); earlier days are disabled.max: integer optional — Latest selectable instant (Unix microseconds); later days are disabled.enabled: boolean optional — Whether it starts enabled (defaulttrue).open: boolean optional — Start with the popover open (defaultfalse).on_change: function optional — Called with the selected instant (Unix microseconds) when the user picks a day or edits the time. A programmaticvaluewrite does not fire it.
Inherits all fields of ui.NodeStyle.
source: Image | DrawCanvas | Scene optional — Texture source handle (Pixel / DrawCanvas / Scene); swaps the image.color: Color | ThemedColor optional — Background color. Pass adatumhue.theme.token(...)to follow the theme.text: string | Message optional — New text — a plain string (stops following any locale), or adatumhue.i18n.t(...)message (follows the active locale). Unchanged when omitted.font_size: number | string optional — New label font size: a number (pixels) or a unit string. Pins the size (stops following the theme). Unchanged when omitted.font_weight: number | FontWeight optional — New label weight: a number on the variable weight axis, or a weight name (boldis the heaviest). Pins the weight. Unchanged when omitted.font_style: FontStyle optional — New label face: upright, the calligraphic cursive, or a mechanical slant. Unchanged when omitted.font: Font optional — New font (abytes:font()/datumhue.font.builtin()handle); pins the face. Unchanged when omitted.visible: boolean optional — Show or hide the element.material: Shader optional — Shader material.
Inherits all fields of ui.NodeStyle.
parent: UiElement optional — Parent element; defaults to the content area.material: Shader optional — Shader material for post-processing.fit: ui.ImageFit optional — How the texture maps into the element box (defaultfill); aspect-preserving modes center in the box.auto_size: boolean optional — Render-target sources (draw canvas or scene): re-resolve the backing texture to the host element's size on resize, so content stays crisp instead of being scaled. Raises on a plain image (fixed resolution — usefit).accessible_label: string optional — Accessible name for assistive technology. Images carry no text, so without this their accessible name is empty (unlike text-bearing widgets, which derive one from their text). Set it on images that convey meaning.
Inherits all fields of ui.NodeStyle.
text: string | Message optional — Text content — a plain string, or adatumhue.i18n.t(...)message that follows the active locale and re-renders when it changes.font_size: number | string optional — Font size: a number (pixels) or a unit string like"1.5rem"/"50vw"/"4vmin"(defaults to the theme's normal text size).color: Color | ThemedColor optional — Text color; defaults to the theme text color. Pass adatumhue.theme.token(...)to follow the theme and repaint on change.strikethrough: boolean optional — Draw a line through the text (defaultfalse). Also a read/write property.underline: boolean optional — Draw a line under the text (defaultfalse). Also a read/write property.font_weight: number | FontWeight optional — Font weight: a number on the variable weight axis, or a weight name (boldis the heaviest). Defaults to the theme body weight.font_style: FontStyle optional — Font face: upright, the calligraphic cursive, or a mechanical slant. Defaults to upright.font: Font optional — Font (abytes:font()/datumhue.font.builtin()handle); pins this label's face, overridingdatumhue.font.default. Defaults to the app default face.
Inherits all fields of ui.NodeStyle.
text: string | Message — Link text (required) — a plain string, or adatumhue.i18n.t(...)message that follows the active locale.url: string — Destination URL (required). Must behttp,https, ormailto; any other scheme raises. Clicking opens it in a new browser tab — there is no programmatic open, so a user gesture is always required.
Inherits all fields of ui.NodeStyle.
items: string[] — Row labels (required); one selectable row per entry, in order.selected: integer[] optional — Initially-selected 1-based indices (default: none). A single-element array selects one row; several pre-select multiple (multi-select only).multi: boolean optional — Allow selecting multiple rows at once (defaultfalse).enabled: boolean optional — Whether it starts enabled (defaulttrue). A disabled list ignores clicks and keyboard navigation untilelem.enabled = true.on_change: function optional — Called on user selection with the newselectedvalue — a 1-based integer for a single-select list, a 1-based index array for multi. A programmaticelem.selected = ...write does not fire it.
Inherits all fields of ui.NodeStyle.
label: string — The menu button's label.enabled: boolean optional — Whether it starts enabled (defaulttrue).
left: number | string optional — Left anchor (px or "%").right: number | string optional — Right anchor (px or "%").top: number | string optional — Top anchor (px or "%").bottom: number | string optional — Bottom anchor (px or "%").width: number | string optional — Width (px or "%").height: number | string optional — Height (px or "%").min_width: number | string optional — Minimum width.max_width: number | string optional — Maximum width.min_height: number | string optional — Minimum height.max_height: number | string optional — Maximum height.aspect_ratio: number optional — Aspect ratio (width / height).margin: number | string | table optional — Outer margin: scalar, string, or {top,bottom,left,right}.padding: number | string | table optional — Inner padding: scalar, string, or {top,bottom,left,right}.border: number | string | table optional — Border widths: scalar, string, or {top,bottom,left,right}.flex_grow: number optional — Flex grow factor.flex_shrink: number optional — Flex shrink factor.flex_basis: number | string optional — Flex basis (px or "%").align_self: ui.AlignSelf optional — Per-item cross-axis alignment.flex_direction: ui.FlexDirection optional — Main-axis direction.flex_wrap: ui.FlexWrap optional — Wrapping behavior.justify_content: ui.JustifyContent optional — Main-axis distribution.align_items: ui.AlignItems optional — Cross-axis alignment of items.align_content: ui.AlignContent optional — Cross-axis distribution of wrapped lines.gap: number | string optional — Shorthand for row_gap + column_gap.row_gap: number | string optional — Row gap (overrides gap).column_gap: number | string optional — Column gap (overrides gap).overflow: ui.Overflow optional — Overflow handling. The scroll variants make the element a wheel-scrollable container; see thescroll/scroll_maxelement properties.display: ui.Display optional — Display mode.gridauto-places children one per row — a single-column grid, as no track or placement options exist; for multi-column layouts composeflexcontainers.border_color: Color | ThemedColor optional — Border color; defaults to the theme panel border. Pass adatumhue.theme.token(...)to follow the theme and repaint on change.border_radius: number | string | table optional — Corner rounding: scalar, string, or per-corner table.z_index: integer optional — Stacking order.outline: ui.Outline optional — Focus outline.box_shadow: ui.Shadow | ui.Shadow[] optional — Drop shadow: one shadow, or an array drawn back-to-front.
Inherits all fields of ui.NodeStyle.
value: number optional — Initial value, clamped to the range (defaultmin, or0).min: number optional — Minimum value (default: unbounded below).max: number optional — Maximum value (default: unbounded above).step: number optional — Amount the-/+steppers add or subtract (default1).precision: integer optional — Decimal places the value is displayed and snapped to (default0).enabled: boolean optional — Whether it starts enabled (defaulttrue). A disabled number input ignores typing and the steppers untilelem.enabled = true.on_change: function optional — Called with the new value (number) when the user edits the field or uses a stepper. A programmaticelem.value = ...write does not fire it.
Inherits all fields of ui.NodeStyle.
text: string | Message — Button label (required) — a plain string, or adatumhue.i18n.t(...)message that follows the active locale.mode: ui.PickMode — What the click picks; selects theon_pickpayload.filters: table[] optional — File-type filters, an array of{label, {ext, ...}}pairs. Valid only for file modes; raises with a directory mode.start_dir: Dir optional — Seeds the dialog's starting location. Best-effort: native dialogs open there; browser pickers ignore it.title: string optional — Dialog title.on_pick: function optional — Called on a successful pick with the picked handle (never on cancel). Optional; bind later withelem:on_pick(e.g. from a hosting app viabook:element). With no handler bound a click opens no dialog.enabled: boolean optional — Whether the button starts enabled (defaulttrue). Settingfalsegrays it out and ignores clicks.
width: number | string optional — Outline thickness (px or "%"); defaults to 0.offset: number | string optional — Gap between the element edge and the outline; defaults to 0.color: Color optional — Outline color; defaults to fully transparent.
Inherits all fields of ui.NodeStyle.
color: Color | ThemedColor optional — Background color; defaults to the theme panel background. Pass adatumhue.theme.token(...)to follow the theme and repaint on change.material: Shader optional — Shader material applied to the panel.on_hover: function optional — Called when the cursor enters the panel or any of its descendants.on_hover_exit: function optional — Called when the cursor leaves the panel and all of its descendants.on_press: function optional — Called when a mouse button is pressed on the panel.on_release: function optional — Called when a mouse button is released over the panel.on_double_click: function optional — Called on a double-click: two presses on the panel within the double-click window.
Inherits all fields of ui.NodeStyle.
side: ui.PopoverSide optional — Which side of the anchor to place it (default"bottom"). Auto-flips to the opposite side if it would clip the window.align: ui.PopoverAlign optional — Alignment along the axis perpendicular toside(default"start").gap: number optional — Gap in logical px between the anchor and the popover (default4).visible: boolean optional — Whether it starts shown (defaultfalse); toggle later via thevisibleproperty.light_dismiss: boolean optional — Close the popover on a pointer press outside it (defaultfalse). Off: fully app-controlled via thevisibleproperty. On: light-dismisses like a menu (pressing the anchor still toggles it).
Inherits all fields of ui.NodeStyle.
options: string[] — Option labels (required); one radio button per entry, in order.selected: integer optional — 1-based index of the initially-selected option (default: none selected).enabled: boolean optional — Whether it starts enabled (defaulttrue). A disabled group ignores clicks and keyboard navigation untilelem.enabled = true.on_change: function optional — Called with the selected 1-based index (integer) when the user picks an option. A programmaticelem.selected = ...write does not fire it.
title: string | Message optional — Accessible title (a plain string or adatumhue.i18n.t(...)message), announced to a screen reader on navigation and readable asroute.title.on_enter: function optional — Called with the page element once it is built — start per-page work here.on_leave: function optional — Called when the page is about to be destroyed (pop/replace/to_root/go). Returnfalseto veto and keep it (confirm-before-leave).
Inherits all fields of ui.NodeStyle.
text: string | Message — Button label (required) — a plain string, or adatumhue.i18n.t(...)message that follows the active locale.source: string | Bytes optional — The bytes to write, captured now. The write is atomic, on the one click. Omit and bind later withelem:on_save_sourceto keep the payload current; with none set a click does nothing.suggested_name: string optional — Default filename pre-filled in the save dialog.filters: table[] optional — File-type filters, an array of{label, {ext, ...}}pairs.start_dir: Dir optional — Seeds the dialog's starting location. Best-effort: native dialogs open there; browser pickers ignore it.title: string optional — Dialog title.on_save: function optional — Called after the bytes are committed to the chosen file, with the read-onlyFilehandle (never on cancel). Optional; bind later withelem:on_save.enabled: boolean optional — Whether the button starts enabled (defaulttrue).
color: Color optional — Shadow color; defaults to black.x_offset: number | string optional — Horizontal offset (px or "%"); defaults to 0.y_offset: number | string optional — Vertical offset (px or "%"); defaults to 0.spread_radius: number | string optional — Amount the shadow grows beyond the element box; defaults to 0.blur_radius: number | string optional — Blur radius; defaults to 0.
Inherits all fields of ui.NodeStyle.
value: number optional — Initial value, clamped to[min, max](default the range midpoint).min: number optional — Range minimum (default0).max: number optional — Range maximum (default1).step: number optional — Keyboard / track-click step increment (default0.1).enabled: boolean optional — Whether it starts enabled (defaulttrue). A disabled slider ignores drag and keyboard input untilelem.enabled = true.on_change: function optional — Called with the new value (number) continuously as the user drags or steps it. A programmaticelem.value = ...write does not fire it.
column: string — Source column name.label: string optional — Header text; defaults to the column name.format: string optional — Cell format for numeric columns, e.g."{:.2}"or"{value} ms"(the chart tick-format dialect). Non-numeric columns ignore it.
Inherits all fields of ui.NodeStyle.
data: DataHandle — The tabular data to display (required). Rows render engine-side for the visible scroll window only and are never materialized into Lua;tbl:row(i)reads a single row on demand.columns: ui.TableColumn[] — Column specs (required, in display order). Raises when a named column is missing from already-loaded data.sortable: boolean optional — Make the headers clickable: a click sorts by that column (stable), a second click on the same header reverses. The selection follows the rows across a sort. Defaultfalse.multi: boolean optional — Allow selecting multiple rows at once (defaultfalse).on_change: function optional — Called on user row selection with the newselectedvalue — a 1-based display index for a single-select table, an index array whenmulti. A programmaticelem.selected = ...write does not fire it.
Inherits all fields of ui.NodeStyle.
value: string optional — Initial text content (default empty). Read/write later via thetextproperty.placeholder: string optional — Placeholder shown while the field is empty.max_length: integer optional — Maximum number of characters the field accepts.multiline: boolean optional — Allow multiple lines: Enter inserts a newline instead of submitting (defaultfalse).filter: string optional — A Lua character-class pattern (e.g."%d","[%d.-]") restricting which characters can be typed or pasted, matched per character. It masks the character *set*, not structure: validate the whole value inon_changeoron_submit(and prefernumber_inputfor numbers). ASCII-oriented like Lua's own%-classes; raises if the pattern is malformed.select_all_on_focus: boolean optional — Select all the text when the field gains keyboard focus (defaultfalse).enabled: boolean optional — Whether it starts enabled (defaulttrue). A disabled input ignores keyboard and pointer input untilelem.enabled = true.on_change: function optional — Called with the new text (string) on each user edit. A programmaticelem.text = ...write does not fire it.on_submit: function optional — Called with the text (string) when Enter is pressed in a single-line input.autofocus: boolean optional — Take keyboard focus as soon as the input is created (defaultfalse). If several inputs request it in one frame, the last one created wins.on_focus: function optional — Called when the input gains keyboard focus.on_blur: function optional — Called when the input loses keyboard focus (clicking away, Tab, or the app losing focus).on_cancel: function optional — Called when Escape is pressed while the input is focused.
sampler: NoiseSampler — 3D-sampled noise source.material: integer — Palette index written where the sample meets the threshold.threshold: number optional — Minimum sample value (noise output is -1..1; default 0).region: voxel.Region optional — Cell region to fill; defaults to the whole volume.scale: number optional — Cell → noise-space coordinate scale (default 1).offset: Vec3 optional — Noise-space offset, for scrolling or layering.
source: NoiseSampler | Grid | Image — Height source: 2D-sampled noise (remapped 0..1), a grid (cell value = height in cells), or an image (luminance, stretched over the region).material: integer — Palette index columns fill with.max_height: integer optional — Height in cells a full-strength source value reaches, above the region floor; defaults to the region's full height.region: voxel.Region optional — Cell region; defaults to the whole volume.scale: number optional — Cell → noise-space scale for noise sources (default 1).offset: Vec2 optional — Noise-space offset for noise sources.
width: integer — Cells along x.height: integer — Cells along y.depth: integer — Cells along z.pos: Vec3 optional — World-space position of the volume's minimum corner (default origin).rotation: Quat optional — Rotation quaternion (default identity).cell_size: number optional — World units per cell (default 1).material: Material | Shader optional — Material for the volume's solid surfaces (a standard Material or a Shader); the default lights vertex colors through a plain white surface.sunlight: boolean optional — Sky light fills open-air columns from above and spreads into overhangs (default false). With it off, baked lighting still activates when any palette entry emits light.ambient: number optional — Baked-light floor 0..1: how bright a fully dark face renders (default 0.15). Only meaningful when lighting is active.physics: boolean optional — Attach a static physics body whose collider matches the volume's cells, following every edit (default false).layers: integer[] optional — Collision membership: layer bit indices 0..=31 the body belongs to. Omitted = all layers. Requiresphysics.collides_with: integer[] optional — Collision filter: only collide with bodies in these layer bit indices 0..=31. Omitted = all. Requiresphysics.
color: Color optional — Base color (default white); tints the tile when textured.emissive: Color optional — Emissive color: entries with one render unlit at this color (channel values above 1 feed bloom).transparent: boolean optional — Transparent entries render alpha-blended and don't occlude neighboring faces (default false).light: integer optional — Block-light emission level 0..15 (default 0): cells of this entry glow and light their surroundings, falling off one level per cell.texture: integer | voxel.TextureFaces optional — Atlas tile for every face, or{top, bottom, side}per-face tiles. Needs an atlas bound viavoxel:atlas. At most one oftexture/frames.frames: integer[] optional — Animated tile sequence shown on every face, advancing atfps.fps: number optional — Animation frames per second (default 4).
frames: integer[] optional — Captured frame indices to play, in order (default every captured frame in capture order).fps: number optional — Frame swaps per second (default 8).looping: boolean optional — Wrap back to the first frame after the last (default true); with it off, playback stops on the last frame.
x: integer — Voxel x coordinate of the hit cell.y: integer — Voxel y coordinate of the hit cell.z: integer — Voxel z coordinate of the hit cell.material: integer — Palette material index of the hit cell.distance: number — Distance from the ray origin to the hit, in scene units.normal: Vec3 — Face normal at the hit cell, in cell axes.
grid: Grid — 2D source; its (x, y) maps onto the plane's axes.plane: voxel.StampPlane — Slice orientation: xz is a floor plan at heightat, xy a wall at depthat, zy a wall at columnat.at: integer — The fixed coordinate of the slice.materials: table optional — Map of grid value → palette index; unmapped values leave cells untouched. Omitted: positive values write directly as indices.
image: Image — Pixel source; must carry readable pixel data.plane: voxel.StampPlane — Slice orientation (seestamp_grid).at: integer — The fixed coordinate of the slice.
top: integer — Atlas tile index for the top face.bottom: integer — Atlas tile index for the bottom face.side: integer — Atlas tile index for the four side faces.
chunk_size: integer — Cells per chunk axis, 1..128 (chunks are cubes).cell_size: number optional — World units per cell (default 1).load_radius: integer optional — Chunks within this radius (in chunks) of the center load (default 2).unload_radius: integer optional — Chunks beyond this radius unload; must be >= load_radius (default load_radius + 1). The gap is hysteresis.budget: integer optional — Maximum chunk loads (and unloads) per frame (default 4).pos: Vec3 optional — World-space position of the world's origin chunk corner (default origin).center: Vec3 optional — Initial streaming focus, relative to the world origin (default origin).physics: boolean optional — Every chunk carries a static collider matching its cells (default false).sunlight: boolean optional — Sky light fills open-air columns in every chunk (default false).ambient: number optional — Baked-light floor 0..1 for every chunk (default 0.15).on_chunk_load: fun(chunk: VoxelChunk) optional — Invoked after a chunk loads; fillchunk.voxelwith content or restore a snapshot viachunk:write.on_chunk_unload: fun(coords: Vec3, data: Bytes) optional — Invoked after a chunk unloads, with its grid coordinates and cell snapshot — the chunk entity is already gone. Persistdataand hand it back tochunk:writeon the next load.
top: number optional — Top edge inset in pixels (default 0).bottom: number optional — Bottom edge inset in pixels (default 0).left: number optional — Left edge inset in pixels (default 0).right: number optional — Right edge inset in pixels (default 0).
app: App — The managed app to reposition or resize.x: number optional — New x position in pixels; unchanged when omitted.y: number optional — New y position in pixels; unchanged when omitted.width: number optional — New width in pixels; unchanged when omitted.height: number optional — New height in pixels; unchanged when omitted.
app: App — The managed app to minimize or restore.minimized: boolean —trueto minimize,falseto restore.
String enums84
One of "file", "dir"
One of "linear", "quadratic_in", "quadratic_out", "quadratic_in_out", "cubic_in", "cubic_out", "cubic_in_out", "quartic_in", "quartic_out", "quartic_in_out", "quintic_in", "quintic_out", "quintic_in_out", "sine_in", "sine_out", "sine_in_out", "circular_in", "circular_out", "circular_in_out", "exponential_in", "exponential_out", "exponential_in_out", "elastic_in", "elastic_out", "elastic_in_out", "back_in", "back_out", "back_in_out", "bounce_in", "bounce_out", "bounce_in_out", "smooth_step_in", "smooth_step_out", "smooth_step", "smoother_step_in", "smoother_step_out", "smoother_step"
One of "Arab", "Hebr", "Cyrl", "Deva", "Beng", "Thai", "Hani"
One of "normal", "italic", "oblique"
One of "thin", "extralight", "light", "regular", "normal", "medium", "semibold", "bold"
One of "pending", "ready", "failed"
One of "fps", "frame_time", "frame_count", "entity_count", "app_count", "cpu", "memory"
"fps"— Smoothed frames per second."frame_time"— Smoothed frame time in seconds."frame_count"— Frames rendered since launch."entity_count"— Live entities in the world."app_count"— Running apps in the process tree."cpu"— Fraction of the per-frame script budget this app consumed during the previous frame. Raw per-frame value, no smoothing."memory"— Script memory currently allocated by this app, in bytes.
One of "identity", "screenshot", "network", "commerce", "packages"
"identity"— Unlocks the signed-in identity's claims (`datumhue.identity`)."screenshot"— Unlocks screen capture (`screen.screenshot`)."network"— Unlocks network-scoped messaging and documents (`scope = "network"`)."commerce"— Unlocks paid-package purchasing and entitlements (`datumhue.commerce`), part of the networked surface."packages"— Unlocks install management: installing, uninstalling, and reading the installed-package library.
One of "r", "rw"
One of "sine", "square", "triangle", "sawtooth", "noise"
One of "bottom", "left", "top", "right"
One of "x", "y"
One of "sum", "mean", "min", "max", "count"
One of "stacked", "grouped"
One of "x", "y", "both"
One of "count", "sum", "mean"
One of "count", "fraction"
One of "count", "fraction", "density"
One of "top_left", "top_right", "bottom_left", "bottom_right", "top_center", "bottom_center"
One of "items", "gradient"
One of "vertical", "horizontal"
One of "viridis", "plasma", "inferno", "magma", "turbo", "diverging"
One of "interpolate", "nearest"
One of "center", "top_left", "top_center", "top_right", "center_left", "center_right", "bottom_left", "bottom_center", "bottom_right"
One of "left", "center", "right"
One of "top", "bottom"
One of "oklab", "oklch", "linear", "srgb", "hsl"
One of "none", "lttb_pixel", "stride", "bin_2d"
One of "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "utf8", "binary", "fixed_binary", "date", "timestamp", "unknown"
"unknown"— Any column type outside this vocabulary.
One of "reveal", "select", "advance", "confirm"
"reveal"— A press landed the whole text early."select"— The choice cursor moved."advance"— A revealed plain line was dismissed."confirm"— A revealed ask committed its selection.
One of "read", "write"
One of "string", "integer", "number", "boolean", "enum"
"string"— UTF-8 text; bound its byte length with `max_len`."number"— Any finite numeric value; NaN and infinities always fail."enum"— A string drawn from `values`.
One of "local", "network"
One of "word", "character", "word_or_character", "none"
One of "left", "center", "right", "justified"
One of "window_resized", "window_focused", "window_unfocused", "scale_factor_changed", "zoom_changed", "app_focused", "app_unfocused", "app_spawned", "app_terminated", "app_state_changed", "app_bounds_changed", "app_fullscreen_request", "app_stretch_mode_request", "app_design_resolution_request", "app_resize_request", "app_zoom_request", "app_frame_pressed", "app_permission_request", "identity_signed_in", "identity_signed_out", "identity_refreshed", "identity_sign_in_failed", "app_identity_sign_in_request", "app_identity_sign_out_request", "connectivity"
One of "euclidean", "manhattan", "chebyshev"
One of "copy", "alpha", "add", "multiply", "screen"
"copy"— Destination = source (straight copy)."alpha"— Standard alpha compositing (source-over)."add"— Additive; clamps at white."multiply"— Multiplies channels; darkens."screen"— Inverse multiply; lightens.
One of "nearest", "linear"
One of "default", "pointer", "crosshair", "text", "move", "grab", "grabbing", "not_allowed", "help", "wait", "progress", "cell", "copy", "alias", "context_menu", "vertical_text", "col_resize", "row_resize", "n_resize", "s_resize", "e_resize", "w_resize", "ne_resize", "nw_resize", "se_resize", "sw_resize", "nesw_resize", "nwse_resize", "ew_resize", "ns_resize", "zoom_in", "zoom_out"
One of "south", "east", "north", "west", "c", "z", "left_trigger", "left_trigger2", "right_trigger", "right_trigger2", "select", "start", "mode", "left_thumb", "right_thumb", "dpad_up", "dpad_down", "dpad_left", "dpad_right"
One of "keyboard", "mouse", "gamepad"
"keyboard"— Flipped by any key press. The initial value before any input arrives."mouse"— Flipped by a mouse button, cursor motion, or scrolling."gamepad"— Flipped by a gamepad button, or a stick pushed past a 0.25 deadzone.
One of "shift", "control", "alt", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "space", "enter", "escape", "backspace", "tab", "shift_left", "shift_right", "control_left", "control_right", "alt_left", "alt_right", "arrow_up", "arrow_down", "arrow_left", "arrow_right", "minus", "equal", "bracket_left", "bracket_right", "semicolon", "quote", "backquote", "backslash", "comma", "period", "slash", "delete", "insert", "home", "end", "page_up", "page_down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12"
One of "left", "right", "middle", "back", "forward"
One of "left", "right"
One of "opaque", "mask", "blend", "premultiplied", "add", "multiply"
One of "local", "network"
One of "euclidean", "euclidean_sq", "manhattan", "hybrid"
One of "cell_value", "distance", "distance2", "distance2_add", "distance2_sub", "distance2_mul", "distance2_div"
One of "fbm", "ridged", "ping_pong"
One of "perlin", "simplex", "simplex_smooth", "value", "value_cubic"
One of "installed", "updated", "uninstalled"
"installed"— The package was added to the library."updated"— An installed package was replaced by a different version."uninstalled"— The package was removed from the library.
One of "app", "library", "asset_pack"
One of "alpha", "add"
One of "point", "sphere", "box", "cone"
One of "world", "local"
"world"— Spawned particles stay put when the emitter moves."local"— Spawned particles follow the emitter.
One of "x", "y", "z"
One of "dynamic", "static", "kinematic"
One of "fixed", "revolute", "prismatic", "distance", "spherical"
One of "rect", "circle", "capsule", "convex_hull", "polyline", "cube", "sphere", "cylinder", "cone", "trimesh"
One of "y_locked", "full", "none"
One of "forward", "reverse", "ping_pong"
One of "wave", "ripple", "sway", "noise"
"wave"— Directional sine across local XZ, displacing local Y."ripple"— Radial sine out from `origin` in local XZ, displacing local Y."sway"— Lateral bend along `direction`, weighted by height so the base stays anchored."noise"— Smooth animated noise over local XZ, displacing local Y.
One of "cutout", "blend", "opaque", "hash"
One of "world", "screen"
One of "none", "reinhard", "reinhard_luminance", "aces", "agx", "somewhat_boring", "blender_filmic", "tony_mcmapface", "khronos_pbr_neutral"
One of "windowed", "borderless", "exclusive"
"windowed"— Normal decorated window. Also selected by passing `false`."borderless"— Borderless window filling the current monitor at its desktop resolution."exclusive"— Exclusive fullscreen at the monitor's current video mode.
One of "fill", "letterbox", "pixel_perfect"
One of "solid", "gradient", "radial_gradient", "animated_glow", "glassmorphism", "scanline", "noise", "border", "checkerboard", "stripe", "dissolve", "outline", "wave", "color_ramp"
One of "panel_background", "panel_border", "surface_sunken", "surface_raised", "surface_overlay", "selection_background", "focus_ring", "button_normal", "button_hover", "button_pressed", "button_text", "button_disabled", "button_text_disabled", "checkbox_background", "checkbox_background_checked", "checkbox_border", "checkbox_mark", "slider_track", "slider_fill", "slider_thumb", "radio_border", "radio_mark", "scrollbar_track", "scrollbar_thumb", "list_row_selected", "list_row_active", "input_background", "input_border", "input_text", "input_placeholder", "input_cursor", "popover_background", "popover_border", "menu_background", "menu_border", "text_primary", "text_secondary", "text_disabled", "accent_primary", "accent_secondary", "accent_data", "accent_tertiary", "success", "warning", "error", "info", "success_background", "warning_background", "error_background", "info_background", "accent_tertiary_background", "statusline_primary", "statusline_secondary", "statusline_tertiary", "chart_axis", "chart_grid", "chart_axis_label", "chart_background", "chart_legend_background", "chart_legend_border", "chart_legend_text"
One of "padding_small", "padding_medium", "padding_large", "input_padding_vertical", "gap_small", "gap_medium", "gap_large", "border_width", "border_radius", "font_size_small", "font_size_normal", "font_size_large", "font_size_heading", "font_size_title", "font_size_display", "font_weight_normal", "font_weight_heading", "button_min_width", "button_min_height"
One of "default", "start", "end", "flex_start", "flex_end", "center", "stretch", "space_between", "space_around", "space_evenly"
One of "default", "start", "end", "flex_start", "flex_end", "center", "baseline", "stretch"
One of "auto", "start", "end", "flex_start", "flex_end", "center", "baseline", "stretch"
One of "flex", "grid", "block", "none"
One of "row", "row_reverse", "column", "column_reverse"
One of "nowrap", "wrap", "wrap_reverse"
One of "fill", "contain", "cover", "scale_down"
"fill"— Stretch to the element box, ignoring the source's aspect ratio."contain"— Largest aspect-preserving size that fits inside the box; the rest letterboxes."cover"— Smallest aspect-preserving size that covers the box; the overflow is clipped."scale_down"— Like contain, but never enlarges past the source's natural size.
One of "default", "start", "end", "flex_start", "flex_end", "center", "stretch", "space_between", "space_around", "space_evenly"
One of "visible", "clip", "clip_x", "clip_y", "hidden", "scroll", "scroll_x", "scroll_y"
One of "file", "files", "dir"
"file"— One file; `on_pick` receives a `File`."files"— One or more files; `on_pick` receives a `File` array."dir"— A directory; `on_pick` receives a `Dir`.
One of "start", "center", "end"
"start"— Align to the anchor's leading edge."center"— Center on the anchor."end"— Align to the anchor's trailing edge.
One of "top", "bottom", "left", "right"
"top"— Above the anchor."bottom"— Below the anchor."left"— Left of the anchor."right"— Right of the anchor.
One of "xz", "xy", "zy"
SQL
A DatumHue app runs SQL through DataHandle:query. The query is lazy — it plans and runs on first read, then caches.
Querying
The query is rooted on the handle it's called on, bound as the table data:
local top = sales:query("SELECT region, SUM(amount) AS total FROM data GROUP BY region")
Pass values for ? placeholders as a second array argument; each ? binds left to right:
local big = sales:query("SELECT * FROM data WHERE amount > ?", { 1000 })
A Dir or File handle in the params binds the next ? to a location inside its grant, so a query can read a granted file directly. Only granted locations are reachable — there is no path to the wider filesystem:
local rows = data_handle:query("SELECT * FROM ? WHERE ok", { my_file })
Write results into a granted location with COPY ... TO ?:
data_handle:query("COPY data TO ? STORED AS PARQUET", { out_dir })
Queries never modify your source data. The only writes are into a location you've granted for writing — COPY ... TO ?, or a table you create over a granted directory. They run under a memory budget (2 GiB on desktop, 1 GiB in the browser) and spill to disk where one is available.
Functions
The functions the embedded query engine exposes, grouped as the engine groups them. Each row is the call syntax and what it does.
Analytical Functions
| Function | Description |
|---|---|
first_value(expression) | Returns value evaluated at the row that is the first row of the window frame. |
lag(expression, offset, default) | Returns value evaluated at the row that is offset rows before the current row within the partition; if there is no such row, instead return default (which must be of the same type as value). |
last_value(expression) | Returns value evaluated at the row that is the last row of the window frame. |
lead(expression, offset, default) | Returns value evaluated at the row that is offset rows after the current row within the partition; if there is no such row, instead return default (which must be of the same type as value). |
nth_value(expression, n) | Returns the value evaluated at the nth row of the window frame (counting from 1). Returns NULL if no such row exists. |
Approximate Functions
| Function | Description |
|---|---|
approx_distinct(expression) | Returns the approximate number of distinct input values calculated using the HyperLogLog algorithm. |
approx_median(expression) | Returns the approximate median (50th percentile) of input values. It is an alias of approx_percentile_cont(0.5) WITHIN GROUP (ORDER BY x). |
approx_percentile_cont(percentile [, centroids]) WITHIN GROUP (ORDER BY expression) | Returns the approximate percentile of input values using the t-digest algorithm. |
approx_percentile_cont_with_weight(weight, percentile [, centroids]) WITHIN GROUP (ORDER BY expression) | Returns the weighted approximate percentile of input values using the t-digest algorithm. |
Array Functions
| Function | Description |
|---|---|
array_any_value(array) (aliases: list_any_value) | Returns the first non-null element in the array. |
array_append(array, element) (aliases: list_append, array_push_back, list_push_back) | Appends an element to the end of an array. |
array_concat(array[, ..., array_n]) (aliases: array_cat, list_concat, list_cat) | Concatenates arrays. |
array_dims(array) (aliases: list_dims) | Returns an array of the array's dimensions. |
array_distance(array1, array2) (aliases: list_distance) | Returns the Euclidean distance between two input arrays of equal length. |
array_distinct(array) (aliases: list_distinct) | Returns distinct values from the array after removing duplicates. |
array_element(array, index) (aliases: array_extract, list_element, list_extract) | Extracts the element with the index n from the array. |
array_except(array1, array2) (aliases: list_except) | Returns an array of the elements that appear in the first array but not in the second. |
array_has(array, element) (aliases: list_has, array_contains, list_contains) | Returns true if the array contains the element. |
array_has_all(array, sub-array) (aliases: list_has_all) | Returns true if all elements of sub-array exist in array. |
array_has_any(array1, array2) (aliases: list_has_any, arrays_overlap) | Returns true if the arrays have any elements in common. |
array_intersect(array1, array2) (aliases: list_intersect) | Returns an array of elements in the intersection of array1 and array2. |
array_length(array, dimension) (aliases: list_length) | Returns the length of the array dimension. |
array_max(array) (aliases: list_max) | Returns the maximum value in the array. |
array_min(array) | Returns the minimum value in the array. |
array_ndims(array, element) (aliases: list_ndims) | Returns the number of dimensions of the array. |
array_pop_back(array) (aliases: list_pop_back) | Returns the array without the last element. |
array_pop_front(array) (aliases: list_pop_front) | Returns the array without the first element. |
array_position(array, element), array_position(array, element, index) (aliases: list_position, array_indexof, list_indexof) | Returns the position of the first occurrence of the specified element in the array, or NULL if not found. Comparisons are done using IS DISTINCT FROM semantics, so NULL is considered to match NULL. |
array_positions(array, element) (aliases: list_positions) | Searches for an element in the array, returns all occurrences. |
array_prepend(element, array) (aliases: list_prepend, array_push_front, list_push_front) | Prepends an element to the beginning of an array. |
array_remove(array, element) (aliases: list_remove) | Removes the first element from the array equal to the given value. |
array_remove_all(array, element) (aliases: list_remove_all) | Removes all elements from the array equal to the given value. |
array_remove_n(array, element, max)) (aliases: list_remove_n) | Removes the first max elements from the array equal to the given value. |
array_repeat(element, count) (aliases: list_repeat) | Returns an array containing element count times. |
array_replace(array, from, to) (aliases: list_replace) | Replaces the first occurrence of the specified element with another specified element. |
array_replace_all(array, from, to) (aliases: list_replace_all) | Replaces all occurrences of the specified element with another specified element. |
array_replace_n(array, from, to, max) (aliases: list_replace_n) | Replaces the first max occurrences of the specified element with another specified element. |
array_resize(array, size, value) (aliases: list_resize) | Resizes the list to contain size elements. Initializes new elements with value or empty if value is not set. |
array_reverse(array) (aliases: list_reverse) | Returns the array with the order of the elements reversed. |
array_slice(array, begin, end) (aliases: list_slice) | Returns a slice of the array based on 1-indexed start and end positions. |
array_sort(array, desc, nulls_first) (aliases: list_sort) | Sort array. |
array_to_string(array, delimiter[, null_string]) (aliases: list_to_string, array_join, list_join) | Converts each element to its text representation. |
array_union(array1, array2) (aliases: list_union) | Returns an array of elements that are present in both arrays (all elements from both arrays) without duplicates. |
arrays_zip(array1, array2[, ..., array_n]) (aliases: list_zip) | Returns an array of structs created by combining the elements of each input array at the same index. If the arrays have different lengths, shorter arrays are padded with NULLs. |
cardinality(array) | Returns the total number of elements in the array. |
empty(array) (aliases: array_empty, list_empty) | Returns 1 for an empty array or 0 for a non-empty array. |
flatten(array) | Converts an array of arrays to a flat array. - Applies to any depth of nested arrays - Does not change arrays that are already flat The flattened array contains all the elements from all source arrays. |
generate_series(stop), generate_series(start, stop[, step]) | Similar to the range function, but it includes the upper bound. |
make_array(expression1[, ..., expression_n]) (aliases: make_list) | Returns an array using the specified input expressions. |
range(stop), range(start, stop[, step]) | Returns an array between start and stop with step. The range start..end contains all values with start <= x < end. It is empty if start >= end. Step cannot be 0. |
string_to_array(str, delimiter[, null_str]) (aliases: string_to_list) | Splits a string into an array of substrings based on a delimiter. Any substrings matching the optional null_str argument are replaced with NULL. |
Binary String Functions
| Function | Description |
|---|---|
decode(expression, format) | Decode binary data from textual representation in string. |
encode(expression, format) | Encode binary data into a textual representation. |
Conditional Functions
| Function | Description |
|---|---|
coalesce(expression1[, ..., expression_n]) | Returns the first of its arguments that is not null. Returns null if all arguments are null. This function is often used to substitute a default value for null values. |
greatest(expression1[, ..., expression_n]) | Returns the greatest value in a list of expressions. Returns null if all expressions are null. |
least(expression1[, ..., expression_n]) | Returns the smallest value in a list of expressions. Returns null if all expressions are null. |
nullif(expression1, expression2) | Returns null if expression1 equals expression2; otherwise it returns expression1. This can be used to perform the inverse operation of coalesce. |
nvl(expression1, expression2) (aliases: ifnull) | Returns expression2 if expression1 is NULL otherwise it returns expression1 and expression2 is not evaluated. This function can be used to substitute a default value for NULL values. |
nvl2(expression1, expression2, expression3) | Returns expression2 if expression1 is not NULL; otherwise it returns expression3. |
General Functions
| Function | Description |
|---|---|
array_agg(expression [ORDER BY expression]) | Returns an array created from the expression elements. If ordering is required, elements are inserted in the specified order. This aggregation function can only mix DISTINCT and ORDER BY if the ordering expression is exactly the same as the argument expression. |
avg(expression) (aliases: mean) | Returns the average of numeric values in the specified column. |
bit_and(expression) | Computes the bitwise AND of all non-null input values. |
bit_or(expression) | Computes the bitwise OR of all non-null input values. |
bit_xor(expression) | Computes the bitwise exclusive OR of all non-null input values. |
bool_and(expression) | Returns true if all non-null input values are true, otherwise false. |
bool_or | Returns true if all non-null input values are true, otherwise false. |
count(expression) | Returns the number of non-null values in the specified column. To include null values in the total count, use count(*). |
first_value(expression [ORDER BY expression]) | Returns the first element in an aggregation group according to the requested ordering. If no ordering is given, returns an arbitrary element from the group. |
grouping(expression) | Returns 1 if the data is aggregated across the specified column, or 0 if it is not aggregated in the result set. |
last_value(expression [ORDER BY expression]) | Returns the last element in an aggregation group according to the requested ordering. If no ordering is given, returns an arbitrary element from the group. |
max(expression) | Returns the maximum value in the specified column. |
median(expression) | Returns the median value in the specified column. |
min(expression) | Returns the minimum value in the specified column. |
percentile_cont(percentile) WITHIN GROUP (ORDER BY expression) (aliases: quantile_cont) | Returns the exact percentile of input values, interpolating between values if needed. |
string_agg([DISTINCT] expression, delimiter [ORDER BY expression]) | Concatenates the values of string expressions and places separator values between them. If ordering is required, strings are concatenated in the specified order. This aggregation function can only mix DISTINCT and ORDER BY if the ordering expression is exactly the same as the first argument expression. |
sum(expression) | Returns the sum of all values in the specified column. |
var(expression) (aliases: var_sample, var_samp) | Returns the statistical sample variance of a set of numbers. |
var_pop(expression) (aliases: var_population) | Returns the statistical population variance of a set of numbers. |
Hashing Functions
| Function | Description |
|---|---|
digest(expression, algorithm) | Computes the binary hash of an expression using the specified algorithm. |
md5(expression) | Computes an MD5 128-bit checksum for a string expression. |
sha224(expression) | Computes the SHA-224 hash of a binary string. |
sha256(expression) | Computes the SHA-256 hash of a binary string. |
sha384(expression) | Computes the SHA-384 hash of a binary string. |
sha512(expression) | Computes the SHA-512 hash of a binary string. |
Map Functions
| Function | Description |
|---|---|
map(key, value), map(key: value) | Returns an Arrow map with the specified key-value pairs. The make_map function creates a map from two lists: one for keys and one for values. Each key must be unique and non-null. |
map_entries(map) | Returns a list of all entries in the map. |
map_extract(map, key) (aliases: element_at) | Returns a list containing the value for the given key or an empty list if the key is not present in the map. |
map_keys(map) | Returns a list of all keys in the map. |
map_values(map) | Returns a list of all values in the map. |
Math Functions
| Function | Description |
|---|---|
abs(numeric_expression) | Returns the absolute value of a number. |
acos(numeric_expression) | Returns the arc cosine or inverse cosine of a number. |
acosh(numeric_expression) | Returns the area hyperbolic cosine or inverse hyperbolic cosine of a number. |
asin(numeric_expression) | Returns the arc sine or inverse sine of a number. |
asinh(numeric_expression) | Returns the area hyperbolic sine or inverse hyperbolic sine of a number. |
atan(numeric_expression) | Returns the arc tangent or inverse tangent of a number. |
atan2(expression_y, expression_x) | Returns the arc tangent or inverse tangent of expression_y / expression_x. |
atanh(numeric_expression) | Returns the area hyperbolic tangent or inverse hyperbolic tangent of a number. |
cbrt(numeric_expression) | Returns the cube root of a number. |
ceil(numeric_expression) | Returns the nearest integer greater than or equal to a number. |
cos(numeric_expression) | Returns the cosine of a number. |
cosh(numeric_expression) | Returns the hyperbolic cosine of a number. |
cot(numeric_expression) | Returns the cotangent of a number. |
degrees(numeric_expression) | Converts radians to degrees. |
exp(numeric_expression) | Returns the base-e exponential of a number. |
factorial(numeric_expression) | Factorial. Returns 1 if value is less than 2. |
floor(numeric_expression) | Returns the nearest integer less than or equal to a number. |
gcd(expression_x, expression_y) | Returns the greatest common divisor of expression_x and expression_y. Returns 0 if both inputs are zero. |
isnan(numeric_expression) | Returns true if a given number is +NaN or -NaN otherwise returns false. |
iszero(numeric_expression) | Returns true if a given number is +0.0 or -0.0 otherwise returns false. |
lcm(expression_x, expression_y) | Returns the least common multiple of expression_x and expression_y. Returns 0 if either input is zero. |
ln(numeric_expression) | Returns the natural logarithm of a number. |
log(base, numeric_expression), log(numeric_expression) | Returns the base-x logarithm of a number. Can either provide a specified base, or if omitted then takes the base-10 of a number. |
log10(numeric_expression) | Returns the base-10 logarithm of a number. |
log2(numeric_expression) | Returns the base-2 logarithm of a number. |
nanvl(expression_x, expression_y) | Returns the first argument if it's not NaN. Returns the second argument otherwise. |
pi() | Returns an approximate value of π. |
power(base, exponent) (aliases: pow) | Returns a base expression raised to the power of an exponent. |
radians(numeric_expression) | Converts degrees to radians. |
random() | Returns a random float value in the range [0, 1). The random seed is unique to each row. |
round(numeric_expression[, decimal_places]) | Rounds a number to the nearest integer. |
signum(numeric_expression) | Returns the sign of a number. Negative numbers return -1. Zero and positive numbers return 1. |
sin(numeric_expression) | Returns the sine of a number. |
sinh(numeric_expression) | Returns the hyperbolic sine of a number. |
sqrt(numeric_expression) | Returns the square root of a number. |
tan(numeric_expression) | Returns the tangent of a number. |
tanh(numeric_expression) | Returns the hyperbolic tangent of a number. |
trunc(numeric_expression[, decimal_places]) | Truncates a number to a whole number or truncated to the specified decimal places. |
Other Functions
| Function | Description |
|---|---|
arrow_cast(expression, datatype) | Casts a value to a specific data type. |
arrow_metadata(expression[, key]) | Returns the metadata of the input expression. If a key is provided, returns the value for that key. If no key is provided, returns a Map of all metadata. |
arrow_typeof(expression) | Returns the name of the underlying data type of the expression. |
get_field(expression, field_name[, field_name2, ...]) | Returns a field within a map or a struct with the given key. Supports nested field access by providing multiple field names. Note: most users invoke get_field indirectly via field access syntax such as my_struct_col['field_name'] which results in a call to get_field(my_struct_col, 'field_name'). Nested access like my_struct['a']['b'] is optimized to a single call: get_field(my_struct, 'a', 'b'). |
version() | Returns the version of the query engine. |
Ranking Functions
| Function | Description |
|---|---|
cume_dist() | Relative rank of the current row: (number of rows preceding or peer with the current row) / (total rows). |
dense_rank() | Returns the rank of the current row without gaps. This function ranks rows in a dense manner, meaning consecutive ranks are assigned even for identical values. |
ntile(expression) | Integer ranging from 1 to the argument value, dividing the partition as equally as possible |
percent_rank() | Returns the percentage rank of the current row within its partition. The value ranges from 0 to 1 and is computed as (rank - 1) / (total_rows - 1). |
rank() | Returns the rank of the current row within its partition, allowing gaps between ranks. This function provides a ranking similar to row_number, but skips ranks for identical values. |
row_number() | Number of the current row within its partition, counting from 1. |
Regular Expression Functions
| Function | Description |
|---|---|
regexp_count(str, regexp[, start, flags]) | Returns the number of matches that a regular expression has in a string. |
regexp_instr(str, regexp[, start[, N[, flags[, subexpr]]]]) | Returns the position in a string where the specified occurrence of a POSIX regular expression is located. |
regexp_like(str, regexp[, flags]) | Returns true if a regular expression has at least one match in a string, false otherwise. |
regexp_match(str, regexp[, flags]) | Returns the first regular expression matches in a string. |
regexp_replace(str, regexp, replacement[, flags]) | Replaces substrings in a string that match a regular expression. |
Statistical Functions
| Function | Description |
|---|---|
corr(expression1, expression2) | Returns the coefficient of correlation between two numeric values. |
covar_pop | Returns the population covariance of a set of number pairs. |
covar_samp(expression1, expression2) (aliases: covar) | Returns the sample covariance of a set of number pairs. |
nth_value(expression, n ORDER BY expression) | Returns the nth value in a group of values. |
regr_avgx(expression_y, expression_x) | Computes the average of the independent variable (input) expression_x for the non-null paired data points. |
regr_avgy(expression_y, expression_x) | Computes the average of the dependent variable (output) expression_y for the non-null paired data points. |
regr_count(expression_y, expression_x) | Counts the number of non-null paired data points. |
regr_intercept(expression_y, expression_x) | Computes the y-intercept of the linear regression line. For the equation (y = kx + b), this function returns b. |
regr_r2(expression_y, expression_x) | Computes the square of the correlation coefficient between the independent and dependent variables. |
regr_slope(expression_y, expression_x) | Returns the slope of the linear regression line for non-null pairs in aggregate columns. Given input column Y and X: regr_slope(Y, X) returns the slope (k in Y = k*X + b) using minimal RSS fitting. |
regr_sxx(expression_y, expression_x) | Computes the sum of squares of the independent variable. |
regr_sxy(expression_y, expression_x) | Computes the sum of products of paired data points. |
regr_syy(expression_y, expression_x) | Computes the sum of squares of the dependent variable. |
stddev(expression) (aliases: stddev_samp) | Returns the standard deviation of a set of numbers. |
stddev_pop(expression) | Returns the population standard deviation of a set of numbers. |
String Functions
| Function | Description |
|---|---|
ascii(str) | Returns the first Unicode scalar value of a string. |
bit_length(str) | Returns the bit length of a string. |
btrim(str[, trim_str]) (aliases: trim) | Trims the specified trim string from the start and end of a string. If no trim string is provided, all spaces are removed from the start and end of the input string. |
character_length(str) (aliases: length, char_length) | Returns the number of characters in a string. |
chr(expression) | Returns a string containing the character with the specified Unicode scalar value. |
concat(str[, ..., str_n]) | Concatenates multiple strings together. |
concat_ws(separator, str[, ..., str_n]) | Concatenates multiple strings together with a specified separator. |
contains(str, search_str) | Return true if search_str is found within string (case-sensitive). |
ends_with(str, substr) | Tests if a string ends with a substring. |
find_in_set(str, strlist) | Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. |
initcap(str) | Capitalizes the first character in each word in the input string. Words are delimited by non-alphanumeric characters. |
left(str, n) | Returns a specified number of characters from the left side of a string. |
levenshtein(str1, str2) | Returns the Levenshtein distance between the two given strings. |
lower(str) | Converts a string to lower-case. |
lpad(str, n[, padding_str]) | Pads the left side of a string with another string to a specified string length. |
ltrim(str[, trim_str]) | Trims the specified trim string from the beginning of a string. If no trim string is provided, spaces are removed from the start of the input string. |
octet_length(str) | Returns the length of a string in bytes. |
overlay(str PLACING substr FROM pos [FOR count]) | Returns the string which is replaced by another string from the specified position and specified count length. |
repeat(str, n) | Returns a string with an input string repeated a specified number. |
replace(str, substr, replacement) | Replaces all occurrences of a specified substring in a string with a new substring. |
reverse(str) | Reverses the character order of a string. |
right(str, n) | Returns a specified number of characters from the right side of a string. |
rpad(str, n[, padding_str]) | Pads the right side of a string with another string to a specified string length. |
rtrim(str[, trim_str]) | Trims the specified trim string from the end of a string. If no trim string is provided, all spaces are removed from the end of the input string. |
split_part(str, delimiter, pos) | Splits a string based on a specified delimiter and returns the substring in the specified position. |
starts_with(str, substr) | Tests if a string starts with a substring. |
strpos(str, substr) (aliases: instr, position) | Returns the starting position of a specified substring in a string. Positions begin at 1. If the substring does not exist in the string, the function returns 0. |
substr(str, start_pos[, length]) (aliases: substring) | Extracts a substring of a specified number of characters from a specific starting position in a string. |
substr_index(str, delim, count) (aliases: substring_index) | Returns the substring from str before count occurrences of the delimiter delim. If count is positive, everything to the left of the final delimiter (counting from the left) is returned. If count is negative, everything to the right of the final delimiter (counting from the right) is returned. |
to_hex(int) | Converts an integer to a hexadecimal string. |
translate(str, from, to) | Performs character-wise substitution based on a mapping. |
upper(str) | Converts a string to upper-case. |
uuid() | Returns UUID v4 string value which is unique per row. |
Struct Functions
| Function | Description |
|---|---|
named_struct(expression1_name, expression1_input[, ..., expression_n_name, expression_n_input]) | Returns an struct using the specified name and input expressions pairs. |
struct(expression1[, ..., expression_n]) (aliases: row) | Returns an struct using the specified input expressions optionally named. Fields in the returned struct use the optional name or the cN naming convention. For example: c0, c1, c2, etc. |
Time and Date Functions
| Function | Description |
|---|---|
current_date() (aliases: today) | Returns the current date in the session time zone. The current_date() return value is determined at query time and will return the same date, no matter when in the query plan the function executes. |
current_time() | Returns the current time in the session time zone. The current_time() return value is determined at query time and will return the same time, no matter when in the query plan the function executes. The time zone can be a value like +00:00, 'Europe/London' etc. |
date_bin(interval, expression, origin-timestamp) | Calculates time intervals and returns the start of the interval nearest to the specified timestamp. Use date_bin to downsample time series data by grouping rows into time-based "bins" or "windows" and applying an aggregate or selector function to each window. For example, if you "bin" or "window" data into 15 minute intervals, an input timestamp of 2023-01-01T18:18:18Z will be updated to the start time of the 15 minute bin it is in: 2023-01-01T18:15:00Z. |
date_part(part, expression) (aliases: datepart) | Returns the specified part of the date as an integer. |
date_trunc(precision, expression) (aliases: datetrunc) | Truncates a timestamp or time value to a specified precision. |
from_unixtime(expression[, timezone]) | Converts an integer to RFC3339 timestamp format (YYYY-MM-DDT00:00:00.000000000Z). Integers and unsigned integers are interpreted as seconds since the unix epoch (1970-01-01T00:00:00Z) return the corresponding timestamp. |
make_date(year, month, day) | Make a date from year/month/day component parts. |
make_time(hour, minute, second) | Make a time from hour/minute/second component parts. |
now() (aliases: current_timestamp) | Returns the current timestamp in the system configured timezone (None by default). The now() return value is determined at query time and will return the same timestamp, no matter when in the query plan the function executes. |
to_char(expression, format) (aliases: date_format) | Returns a string representation of a date, time, timestamp or duration based on a strftime format. Unlike the PostgreSQL equivalent of this function numerical formatting is not supported. |
to_date('2017-05-31', '%Y-%m-%d') | Converts a value to a date (YYYY-MM-DD). Supports strings, numeric and timestamp types as input. Strings are parsed as YYYY-MM-DD (e.g. '2023-07-20') if no strftime formats are provided. Integers and doubles are interpreted as days since the unix epoch (1970-01-01T00:00:00Z). Returns the corresponding date. Note: to_date returns Date32, which represents its values as the number of days since unix epoch(1970-01-01) stored as signed 32 bit value. The largest supported date value is 9999-12-31. |
to_local_time(expression) | Converts a timestamp with a timezone to a timestamp without a timezone (with no offset or timezone information). This function handles daylight saving time changes. |
to_time('12:30:45', '%H:%M:%S') | Converts a value to a time (HH:MM:SS.nnnnnnnnn). Supports strings and timestamps as input. Strings are parsed as HH:MM:SS, HH:MM:SS.nnnnnnnnn, or HH:MM if no strftime formats are provided. Timestamps will have the time portion extracted. Returns the corresponding time. Note: to_time returns Time64(Nanosecond), which represents the time of day in nanoseconds since midnight. |
to_timestamp(expression[, ..., format_n]) | Converts a value to a timestamp (YYYY-MM-DDT00:00:00.000000<TZ>) in the session time zone. Supports strings, integer, unsigned integer, and double types as input. Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00') if no strftime formats are provided. Strings that parse without a time zone are treated as if they are in the session time zone, or UTC if no session time zone is set. Integers, unsigned integers, and doubles are interpreted as seconds since the unix epoch (1970-01-01T00:00:00Z). Note: to_timestamp returns Timestamp(ns, TimeZone) where the time zone is the session time zone. The supported range for integer input is between-9223372037 and 9223372036. Supported range for string input is between 1677-09-21T00:12:44.0 and 2262-04-11T23:47:16.0. Please use to_timestamp_seconds for the input outside of supported bounds. The session time zone can be set using the statement SET TIMEZONE = 'desired time zone'. The time zone can be a value like +00:00, 'Europe/London' etc. |
to_timestamp_micros(expression[, ..., format_n]) | Converts a value to a timestamp (YYYY-MM-DDT00:00:00.000000<TZ>) in the session time zone. Supports strings, integer, unsigned integer, and double types as input. Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00') if no strftime formats are provided. Strings that parse without a time zone are treated as if they are in the session time zone, or UTC if no session time zone is set. Integers, unsigned integers, and doubles are interpreted as microseconds since the unix epoch (1970-01-01T00:00:00Z). The session time zone can be set using the statement SET TIMEZONE = 'desired time zone'. The time zone can be a value like +00:00, 'Europe/London' etc. |
to_timestamp_millis(expression[, ..., format_n]) | Converts a value to a timestamp (YYYY-MM-DDT00:00:00.000<TZ>) in the session time zone. Supports strings, integer, unsigned integer, and double types as input. Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00') if no strftime formats are provided. Strings that parse without a time zone are treated as if they are in the session time zone, or UTC if no session time zone is set. Integers, unsigned integers, and doubles are interpreted as milliseconds since the unix epoch (1970-01-01T00:00:00Z). The session time zone can be set using the statement SET TIMEZONE = 'desired time zone'. The time zone can be a value like +00:00, 'Europe/London' etc. |
to_timestamp_nanos(expression[, ..., format_n]) | Converts a value to a timestamp (YYYY-MM-DDT00:00:00.000000000<TZ>) in the session time zone. Supports strings, integer, unsigned integer, and double types as input. Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00') if no strftime formats are provided. Strings that parse without a time zone are treated as if they are in the session time zone. Integers, unsigned integers, and doubles are interpreted as nanoseconds since the unix epoch (1970-01-01T00:00:00Z). The session time zone can be set using the statement SET TIMEZONE = 'desired time zone'. The time zone can be a value like +00:00, 'Europe/London' etc. |
to_timestamp_seconds(expression[, ..., format_n]) | Converts a value to a timestamp (YYYY-MM-DDT00:00:00<TZ>) in the session time zone. Supports strings, integer, unsigned integer, and double types as input. Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00') if no strftime formats are provided. Strings that parse without a time zone are treated as if they are in the session time zone, or UTC if no session time zone is set. Integers, unsigned integers, and doubles are interpreted as seconds since the unix epoch (1970-01-01T00:00:00Z). The session time zone can be set using the statement SET TIMEZONE = 'desired time zone'. The time zone can be a value like +00:00, 'Europe/London' etc. |
to_unixtime(expression[, ..., format_n]) | Converts a value to seconds since the unix epoch (1970-01-01T00:00:00). Supports strings, dates, timestamps, integer, unsigned integer, and float types as input. Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00') if no strftime formats are provided. Integers, unsigned integers, and floats are interpreted as seconds since the unix epoch (1970-01-01T00:00:00). |
Union Functions
| Function | Description |
|---|---|
union_extract(union, field_name) | Returns the value of the given field in the union when selected, or NULL otherwise. |
union_tag(union_expression) | Returns the name of the currently selected field in the union |
Documents (DHML)
Document pages come in two forms producing the same result: .dhml pages are markdown prose whose ```kdl fences hold element islands, and .kdl pages are one declarative element tree under a top-level page node. file:book() loads a single page and dir:book() loads a directory whose book.kdl lists the title and chapters. A script-free book ships as a content_type "book" asset pack any app can open; a book that opens itself is a kind "app" package whose init.lua mounts its own bundle with pkg:dir():book():mount{}. Give an element an id (every element accepts one) and the hosting app reaches its live handle via book:element; markdown headings are addressable the same way through their slug.
page title="Solar output" {
column gap=8 {
label "Daily production" font_size=24
chart id="solar" height=300 {
line color="#e67e80" width=2 {
point x=0 y=12.5
point x=1 y=14.1
}
}
button id="refresh" "Refresh"
}
}
The same page written as markdown:
# Solar output
Daily production, with the *peak* day **highlighted**.

```kdl
chart id="solar" height=300 {
line color="#e67e80" width=2 {
point x=0 y=12.5
point x=1 y=14.1
}
}
```
The same chart as a listing, shown but not run:
```kdl source
chart id="solar" height=300 { }
```
A button you can read and click:
```kdl echo
button id="refresh" "Refresh"
```
Those two forms can be the chapters of a book. A book.kdl at the book's root names the title and lists the chapters in reading order; each file is a page (.dhml or .kdl) relative to the book directory:
title "Solar output"
chapter "Markdown" file="chapters/markdown.dhml"
chapter "KDL page" file="chapters/kdl.kdl"
Prose and string/number properties may carry {{ expression }} templates: Lua expressions evaluated against the hosting app's globals on every render (mount, go, refresh). A property that is exactly one template keeps the value's own type, so height="{{ h }}" can stand in for a number; an unclosed {{ is left as literal text. A lua fence — or a script node, which may load an external script file="..." — runs once at load, and a kdl fence is an element island; an optional mode word makes either fence a listing instead — source shows the code without running it, and echo shows the listing and keeps the block live. Inline code and every other fenced language stay verbatim. The if / for nodes render conditionally and per-item; include splices another page in at load, and a markdown image () embeds an asset resolved against the book directory, so it needs a directory-loaded book.
For example, this page sets up its data in a load-time lua fence, then renders it: greeting the current user, doubling a running total, repeating a row per series item, and gating a detail chart on a flag:
# Live readings
```lua
user = { name = "Ada" }
total = 21
base = 10
series = { { name = "edge", value = 3 }, { name = "core", value = 7 } }
show_detail = true
refresh = function() end
```
```kdl
column gap=8 {
label "Hello, {{ user.name }}"
label "Total: {{ total * 2 }} kWh" font_size="{{ base + 6 }}"
button "Refresh" on_click="{{ refresh }}"
for var="s" in="series" {
label "{{ s.name }}: {{ s.value }}"
}
if cond="show_detail" {
chart id="detail" height=160 {
line color="#7fbbb3" width=3 {
point x=0 y=3
point x=1 y=7
point x=2 y=5
}
}
}
}
```
Layout and style properties are the ui.NodeStyle fields, restricted to the shapes a KDL scalar can carry; color-valued properties take hex literals.
button
A button; the positional argument is the label. Give it an id and bind on_click from the hosting app via book:element.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | string | message | Button label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale. |
enabled | boolean | Whether the button starts enabled (default true). A disabled button is grayed out and ignores clicks and keyboard activation until elem.enabled = true. |
on_click | {{ }} template (handle / table) | Click callback. |
on_hover | {{ }} template (handle / table) | Called when the cursor enters the button or any of its descendants. |
on_hover_exit | {{ }} template (handle / table) | Called when the cursor leaves the button and all of its descendants. |
on_press | {{ }} template (handle / table) | Called when a mouse button is pressed on the button. |
on_release | {{ }} template (handle / table) | Called when a mouse button is released over the button. |
on_double_click | {{ }} template (handle / table) | Called on a double-click: two presses on the button within the double-click window. |
Plus the shared layout/style properties.
chart
A chart plot hosted on an auto-sized canvas; the mark children draw on it.
Children: line / points / area / rule / band / bars / histogram / heatmap / box / histogram2d / text only.
Plus the shared layout/style properties.
area
A filled-area mark on the enclosing chart; point children are its data.
Children: point only.
| Property | Type | Description |
|---|---|---|
baseline | number | Numeric baseline the area fills to. |
series_column | string | Category column splitting rows into one series per distinct value (data sources only). Each series renders its own polyline with per-series downsampling and null-gap handling, takes a color from color_scale or the category palette in first-seen order, and contributes its own legend item. |
color_scale | {{ }} template (handle / table) | Category color scale assigning per-series colors; requires series_column. |
readout | "interpolate" | "nearest" | Crosshair readout interpolation mode. |
points | {{ }} template (handle / table) | Inline {x, y} points array. |
data | {{ }} template (handle / table) | Bind to a tabular data source. |
view | {{ }} template (handle / table) | Bind to a streaming data view. |
x_column | string | X column name (data / view marks). |
y_column | string | Y column name (data / view marks). |
x_scale | {{ }} template (handle / table) | X scale; defaults to the area's. |
y_scale | {{ }} template (handle / table) | Y scale; defaults to the area's. |
color | color ("#rrggbb") | Mark color. |
name | string | Legend name. |
max_points | number | Ring-buffer cap for inline-points marks. |
on_error | {{ }} template (handle / table) | Called when the data source fails to load. |
band
A filled region on the enclosing chart spanning [from, to] on one axis.
Takes no children.
| Property | Type | Description |
|---|---|---|
axis (required) | "x" | "y" | Axis the [from, to] range spans. |
from (required) | number | Range start (data space). |
to (required) | number | Range end (data space). |
color | color ("#rrggbb") | Fill color. |
bar
One category of the enclosing bars mark.
Takes no children.
| Property | Type | Description |
|---|---|---|
category (required) | string | Category label. |
value (required) | number | Bar height (data space). |
bars
A bar mark on the enclosing chart; nest bar children for one series, or series children (each holding bar children) to group them.
Children: bar / series only.
| Property | Type | Description |
|---|---|---|
entries | {{ }} template (handle / table) | Array of {category, value} entries. Exactly one of entries, series, or data. |
series | {{ }} template (handle / table) | Array of {name?, color?, entries} series for stacked/grouped layouts; colors default from the category palette. Requires mode. |
data | {{ }} template (handle / table) | Tabular source; requires category_column. Bars aggregate engine-side per category — rows are never materialized. Rows with a null category or value are skipped. |
category_column | string | Category column to group by (data sources). |
value_column | string | Numeric column to aggregate; required for every aggregate except count. |
series_column | string | Category column splitting rows into one series per distinct value (data sources). Requires mode; series take palette colors in first-seen order. |
aggregate | "sum" | "mean" | "min" | "max" | "count" | Per-category aggregation for data sources. Default sum with a value_column, count without one. |
mode | "stacked" | "grouped" | Multi-series layout. Stacked accumulates per category from the baseline (negatives stack downward); grouped subdivides each band per series. |
group_padding | number | Gap between grouped sub-bars as a 0..1 fraction (default 0.1). |
orientation | "vertical" | "horizontal" | Bar orientation (default vertical). |
color | color ("#rrggbb") | Bar color. |
baseline | number | Numeric baseline the bars grow from. |
name | string | Legend name. |
x_scale | {{ }} template (handle / table) | X scale; defaults to the area's. |
y_scale | {{ }} template (handle / table) | Y scale; defaults to the area's. |
box
A box-and-whisker mark on the enclosing chart; box-entry children are its per-category five-number summaries.
Children: box-entry only.
| Property | Type | Description |
|---|---|---|
entries | {{ }} template (handle / table) | Array of {category, low, q1, median, q3, high, outliers?} pre-computed summaries (low/high are the whisker ends). Exactly one of entries or data. |
data | {{ }} template (handle / table) | Tabular source; requires category_column and value_column. Summaries compute engine-side: quartiles by linear interpolation, whiskers at the farthest values inside the 1.5 IQR fences, the rest as outliers. |
category_column | string | Category column to group by (data sources). |
value_column | string | Numeric column to summarize (data sources). |
box_width | number | Box width as a 0..1 fraction of the band slot (default 0.6). |
orientation | "vertical" | "horizontal" | Box orientation (default vertical). The category axis is x when vertical, y when horizontal. |
color | color ("#rrggbb") | Box and whisker color. |
median_color | color ("#rrggbb") | Median line color (defaults to black). |
outlier_color | color ("#rrggbb") | Outlier point color (defaults to the box color). |
name | string | Legend name. |
x_scale | {{ }} template (handle / table) | X scale; defaults to the area's. Discovered categories append to the band scale on the category axis. |
y_scale | {{ }} template (handle / table) | Y scale; defaults to the area's. |
box-entry
One per-category five-number summary of the enclosing box mark (low <= q1 <= median <= q3 <= high).
Children: outlier only.
| Property | Type | Description |
|---|---|---|
category (required) | string | Category label. |
low (required) | number | Lower whisker. |
q1 (required) | number | First quartile. |
median (required) | number | Median. |
q3 (required) | number | Third quartile. |
high (required) | number | Upper whisker. |
cell
One categorical cell of the enclosing heatmap.
Takes no children.
| Property | Type | Description |
|---|---|---|
x (required) | string | X-axis category. |
y (required) | string | Y-axis category. |
value (required) | number | Cell magnitude. |
heatmap
A categorical heatmap on the enclosing chart; cell children are its data.
Children: cell only.
| Property | Type | Description |
|---|---|---|
cells | {{ }} template (handle / table) | Array of {x, y, value} cells (x/y are category strings). Exactly one of cells, matrix, or data. |
matrix | {{ }} template (handle / table) | Row-major {{number, ...}, ...} values; requires x_categories and y_categories (row index follows y_categories). |
x_categories | {{ }} template (handle / table) | Column categories for matrix. |
y_categories | {{ }} template (handle / table) | Row categories for matrix. |
data | {{ }} template (handle / table) | Tabular source; requires x_column and y_column. Cells aggregate engine-side per category pair. |
x_column | string | Category column for cell columns (data sources). |
y_column | string | Category column for cell rows (data sources). |
value_column | string | Value column to aggregate; required for sum/mean. |
aggregate | "count" | "sum" | "mean" | Cell aggregation for data sources. Default mean with a value_column, count without one. |
color_scale (required) | {{ }} template (handle / table) | Maps cell values to colors. A pending domain fits the cell extent and keeps tracking it. |
name | string | Legend name. |
x_scale | {{ }} template (handle / table) | Band scale for columns; defaults to the area's. Discovered categories are appended in first-seen order. |
y_scale | {{ }} template (handle / table) | Band scale for rows; defaults to the area's. Discovered categories are appended in first-seen order. |
Plus the shared layout/style properties.
histogram
A histogram on the enclosing chart; value children are the samples to bin.
Children: value only.
| Property | Type | Description |
|---|---|---|
values | {{ }} template (handle / table) | Inline values to bin. Exactly one of values or data. |
data | {{ }} template (handle / table) | Tabular source; requires column. Binning runs engine-side over the column — rows are never materialized. |
column | string | Column to bin (data sources). |
bins | number | string | Bin count, or "auto" (default) for width-by-spread with a count floor. Mutually exclusive with bin_width. |
bin_width | number | Explicit bin width in data units. Mutually exclusive with bins. |
normalize | "count" | "fraction" | "density" | Bar heights (default count). |
range | {{ }} template (handle / table) | {min, max} bin extent. Defaults to the data extent; a zoomed x scale re-bins over the visible domain. |
color | color ("#rrggbb") | Bar color. |
name | string | Legend name. |
x_scale | {{ }} template (handle / table) | X scale; defaults to the area's. |
y_scale | {{ }} template (handle / table) | Y scale; defaults to the area's. |
histogram2d
A 2D density heatmap on the enclosing chart; point children are the (x, y) samples to bin.
Children: point only.
| Property | Type | Description |
|---|---|---|
points | {{ }} template (handle / table) | Inline {{x, y}, ...} pairs to bin. Exactly one of points or data. |
data | {{ }} template (handle / table) | Tabular source; requires x_column and y_column. |
x_column | string | Numeric column for x (data sources). |
y_column | string | Numeric column for y (data sources). |
x_bins | number | string | Bin count for x, or "auto" (default). |
y_bins | number | string | Bin count for y, or "auto" (default). |
normalize | "count" | "fraction" | Cell values (default count). |
color_scale (required) | {{ }} template (handle / table) | Maps cell values to colors. A pending domain fits the cell extent and keeps tracking it across zoom re-bins. |
name | string | Legend name. |
x_scale | {{ }} template (handle / table) | Numeric x scale; defaults to the area's. |
y_scale | {{ }} template (handle / table) | Numeric y scale; defaults to the area's. |
Plus the shared layout/style properties.
line
A line mark on the enclosing chart; point children are its data.
Children: point only.
| Property | Type | Description |
|---|---|---|
series_column | string | Category column splitting rows into one series per distinct value (data sources only). Each series renders its own polyline with per-series downsampling and null-gap handling, takes a color from color_scale or the category palette in first-seen order, and contributes its own legend item. |
color_scale | {{ }} template (handle / table) | Category color scale assigning per-series colors; requires series_column. |
readout | "interpolate" | "nearest" | Crosshair readout interpolation mode. |
points | {{ }} template (handle / table) | Inline {x, y} points array. |
data | {{ }} template (handle / table) | Bind to a tabular data source. |
view | {{ }} template (handle / table) | Bind to a streaming data view. |
x_column | string | X column name (data / view marks). |
y_column | string | Y column name (data / view marks). |
x_scale | {{ }} template (handle / table) | X scale; defaults to the area's. |
y_scale | {{ }} template (handle / table) | Y scale; defaults to the area's. |
color | color ("#rrggbb") | Mark color. |
name | string | Legend name. |
max_points | number | Ring-buffer cap for inline-points marks. |
on_error | {{ }} template (handle / table) | Called when the data source fails to load. |
Plus the shared layout/style properties.
outlier
One outlier sample of the enclosing box entry.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | number | The outlier value (data space). |
point
One data point of the enclosing mark.
Takes no children.
| Property | Type | Description |
|---|---|---|
x (required) | number | X value (data space). |
y (required) | number | Y value (data space). |
points
A scatter (dots) mark on the enclosing chart; point children are its data.
Children: point only.
| Property | Type | Description |
|---|---|---|
size | number | Dot size. |
size_column | string | Column driving per-dot size. |
size_scale | {{ }} template (handle / table) | Scale whose domain normalizes size_column values. Required with size_column. |
size_range | {{ }} template (handle / table) | {min, max} output dot sizes in pixels for size_column values. Required with size_column. |
color_column | string | Column driving per-dot color. |
color_scale | {{ }} template (handle / table) | Color scale for color_column. |
points | {{ }} template (handle / table) | Inline {x, y} points array. |
data | {{ }} template (handle / table) | Bind to a tabular data source. |
view | {{ }} template (handle / table) | Bind to a streaming data view. |
x_column | string | X column name (data / view marks). |
y_column | string | Y column name (data / view marks). |
x_scale | {{ }} template (handle / table) | X scale; defaults to the area's. |
y_scale | {{ }} template (handle / table) | Y scale; defaults to the area's. |
color | color ("#rrggbb") | Mark color. |
name | string | Legend name. |
max_points | number | Ring-buffer cap for inline-points marks. |
on_error | {{ }} template (handle / table) | Called when the data source fails to load. |
rule
A reference line on the enclosing chart at a data-space value.
Takes no children.
| Property | Type | Description |
|---|---|---|
orientation (required) | "vertical" | "horizontal" | Reference-line direction. |
value (required) | number | string | Data-space position of the line. A category name resolves to the band scale's slot center when the mark is created; raises when the axis scale isn't a band scale or the category is unknown. |
color | color ("#rrggbb") | Line color. |
value_label | string | Optional label drawn at the line. |
Plus the shared layout/style properties.
series
One named series of the enclosing bars mark; its bar children are its categories.
Children: bar only.
| Property | Type | Description |
|---|---|---|
name | string | Legend name. |
color | color ("#rrggbb") | Series color. |
text
A text annotation on the enclosing chart at a data-space (x, y). x / y / offset_x / offset_y are read as literal numbers (a templated value falls back to 0), like the other inline-data props.
Takes no children.
| Property | Type | Description |
|---|---|---|
x (required) | number | X position (data space). |
y (required) | number | Y position (data space). |
text (required) | string | Annotation text. |
color | color ("#rrggbb") | Text color. |
font_size | number | string | Font size — a number (px) or a unit string. |
align | "center" | "top_left" | "top_center" | "top_right" | "center_left" | "center_right" | "bottom_left" | "bottom_center" | "bottom_right" | Anchor of the text box relative to (x, y). |
offset_x | number | Pixel offset X from (x, y). |
offset_y | number | Pixel offset Y from (x, y). |
value
One sample value to bin in the enclosing histogram.
Takes no children.
| Property | Type | Description |
|---|---|---|
n (required) | number | The sample value (data space). |
checkbox
A checkbox; the positional argument is the label. Bind on_change from the hosting app via book:element.
Takes no children.
| Property | Type | Description |
|---|---|---|
value | string | Label shown beside the box; omit for a bare checkbox. |
checked | boolean | Whether it starts checked (default false). |
enabled | boolean | Whether it starts enabled (default true). A disabled checkbox ignores clicks and keyboard toggling until elem.enabled = true. |
on_change | {{ }} template (handle / table) | Called with the new checked state (boolean) each time the user toggles it. A programmatic elem.checked = ... write does not fire it. |
Plus the shared layout/style properties.
column
A panel with column flex direction.
Children: any element.
| Property | Type | Description |
|---|---|---|
color | color ("#rrggbb") | Background color; defaults to the theme panel background. Pass a datumhue.theme.token(...) to follow the theme and repaint on change. |
material | {{ }} template (handle / table) | Shader material applied to the panel. |
on_hover | {{ }} template (handle / table) | Called when the cursor enters the panel or any of its descendants. |
on_hover_exit | {{ }} template (handle / table) | Called when the cursor leaves the panel and all of its descendants. |
on_press | {{ }} template (handle / table) | Called when a mouse button is pressed on the panel. |
on_release | {{ }} template (handle / table) | Called when a mouse button is released over the panel. |
on_double_click | {{ }} template (handle / table) | Called on a double-click: two presses on the panel within the double-click window. |
Plus the shared layout/style properties.
for
Renders its children once per item of in, binding var.
Children: any element.
| Property | Type | Description |
|---|---|---|
var (required) | string | Loop variable name. |
in (required) | string | A Lua expression evaluating to an array table. |
if
Renders its children when cond evaluates truthy.
Children: any element.
| Property | Type | Description |
|---|---|---|
cond (required) | string | A Lua expression; false / nil drop the children. |
include
Splices another page's blocks in place; the path is relative to the book directory.
Takes no children.
| Property | Type | Description |
|---|---|---|
file (required) | string | Page path inside the book. |
label
A text label; the positional argument is the content.
Takes no children.
| Property | Type | Description |
|---|---|---|
value | string | message | Text content — a plain string, or a datumhue.i18n.t(...) message that follows the active locale and re-renders when it changes. |
font_size | number | string | Font size: a number (pixels) or a unit string like "1.5rem"/ "50vw"/"4vmin" (defaults to the theme's normal text size). |
color | color ("#rrggbb") | Text color; defaults to the theme text color. Pass a datumhue.theme.token(...) to follow the theme and repaint on change. |
strikethrough | boolean | Draw a line through the text (default false). Also a read/write property. |
underline | boolean | Draw a line under the text (default false). Also a read/write property. |
font_weight | number | Font weight: a number on the variable weight axis, or a weight name (bold is the heaviest). Defaults to the theme body weight. |
font_style | "normal" | "italic" | "oblique" | Font face: upright, the calligraphic cursive, or a mechanical slant. Defaults to upright. |
font | {{ }} template (handle / table) | Font (a bytes:font() / datumhue.font.builtin() handle); pins this label's face, overriding datumhue.font.default. Defaults to the app default face. |
Plus the shared layout/style properties.
link
A link; the positional argument is the text and url is the destination. Clicking opens it in a new browser tab.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | string | message | Link text (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale. |
url (required) | string | Destination URL (required). Must be http, https, or mailto; any other scheme raises. Clicking opens it in a new browser tab — there is no programmatic open, so a user gesture is always required. |
Plus the shared layout/style properties.
list
A selectable list. Provide its rows either by binding items to a Lua array via {{ }}, or by listing inline item children whose labels become the rows (children take priority).
Children: item only.
| Property | Type | Description |
|---|---|---|
items | {{ }} template (handle / table) | Row labels as a Lua array (alternative to inline item children). |
selected | number | 1-based index of the initially-selected row. |
multi | boolean | Allow selecting multiple rows at once (default false). |
enabled | boolean | Whether the list accepts input (default true). |
on_change | {{ }} template (handle / table) | fun(selected) called on user selection (an index, or an index array when multi). |
Plus the shared layout/style properties.
item
One row of the enclosing list; the positional argument is its label.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | string | The row label. |
menu
A dropdown menu; label names the trigger button and child elements become the menu items.
Children: any element.
| Property | Type | Description |
|---|---|---|
label (required) | string | The menu button's label. |
enabled | boolean | Whether it starts enabled (default true). |
Plus the shared layout/style properties.
number_input
A numeric input with -/+ steppers. Bind on_change from the hosting app via book:element.
Takes no children.
| Property | Type | Description |
|---|---|---|
value | number | Initial value, clamped to the range (default min, or 0). |
min | number | Minimum value (default: unbounded below). |
max | number | Maximum value (default: unbounded above). |
step | number | Amount the -/+ steppers add or subtract (default 1). |
precision | number | Decimal places the value is displayed and snapped to (default 0). |
enabled | boolean | Whether it starts enabled (default true). A disabled number input ignores typing and the steppers until elem.enabled = true. |
on_change | {{ }} template (handle / table) | Called with the new value (number) when the user edits the field or uses a stepper. A programmatic elem.value = ... write does not fire it. |
Plus the shared layout/style properties.
open_button
A button that opens a file/directory picker on click; the positional argument is the label. Give it an id and bind on_pick from the hosting app via book:element.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | string | message | Button label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale. |
mode (required) | "file" | "files" | "dir" | What the click picks; selects the on_pick payload. |
filters | {{ }} template (handle / table) | File-type filters, an array of {label, {ext, ...}} pairs. Valid only for file modes; raises with a directory mode. |
start_dir | {{ }} template (handle / table) | Seeds the dialog's starting location. Best-effort: native dialogs open there; browser pickers ignore it. |
title | string | Dialog title. |
on_pick | {{ }} template (handle / table) | Called on a successful pick with the picked handle (never on cancel). Optional; bind later with elem:on_pick (e.g. from a hosting app via book:element). With no handler bound a click opens no dialog. |
enabled | boolean | Whether the button starts enabled (default true). Setting false grays it out and ignores clicks. |
Plus the shared layout/style properties.
panel
A container panel; children lay out by the flex style props.
Children: any element.
| Property | Type | Description |
|---|---|---|
color | color ("#rrggbb") | Background color; defaults to the theme panel background. Pass a datumhue.theme.token(...) to follow the theme and repaint on change. |
material | {{ }} template (handle / table) | Shader material applied to the panel. |
on_hover | {{ }} template (handle / table) | Called when the cursor enters the panel or any of its descendants. |
on_hover_exit | {{ }} template (handle / table) | Called when the cursor leaves the panel and all of its descendants. |
on_press | {{ }} template (handle / table) | Called when a mouse button is pressed on the panel. |
on_release | {{ }} template (handle / table) | Called when a mouse button is released over the panel. |
on_double_click | {{ }} template (handle / table) | Called on a double-click: two presses on the panel within the double-click window. |
Plus the shared layout/style properties.
popover
A floating popover anchored to its parent element; fill it with child elements and show it via visible.
Children: any element.
| Property | Type | Description |
|---|---|---|
side | "top" | "bottom" | "left" | "right" | Which side of the anchor to place it (default "bottom"). Auto-flips to the opposite side if it would clip the window. |
align | "start" | "center" | "end" | Alignment along the axis perpendicular to side (default "start"). |
visible | boolean | Whether it starts shown (default false); toggle later via the visible property. |
light_dismiss | boolean | Close the popover on a pointer press outside it (default false). Off: fully app-controlled via the visible property. On: light-dismisses like a menu (pressing the anchor still toggles it). |
Plus the shared layout/style properties.
radio_group
A radio group. Provide its options either by binding options to a Lua array via {{ }}, or by listing inline radio children whose labels become the options (children take priority).
Children: radio only.
| Property | Type | Description |
|---|---|---|
options | {{ }} template (handle / table) | Option labels as a Lua array (alternative to inline radio children). |
selected | number | 1-based index of the initially-selected option. |
enabled | boolean | Whether the group accepts input (default true). |
on_change | {{ }} template (handle / table) | fun(index) called with the 1-based selected index on user selection. |
Plus the shared layout/style properties.
radio
One option of the enclosing radio group; the positional argument is its label.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | string | The option label. |
row
A panel with row flex direction.
Children: any element.
| Property | Type | Description |
|---|---|---|
color | color ("#rrggbb") | Background color; defaults to the theme panel background. Pass a datumhue.theme.token(...) to follow the theme and repaint on change. |
material | {{ }} template (handle / table) | Shader material applied to the panel. |
on_hover | {{ }} template (handle / table) | Called when the cursor enters the panel or any of its descendants. |
on_hover_exit | {{ }} template (handle / table) | Called when the cursor leaves the panel and all of its descendants. |
on_press | {{ }} template (handle / table) | Called when a mouse button is pressed on the panel. |
on_release | {{ }} template (handle / table) | Called when a mouse button is released over the panel. |
on_double_click | {{ }} template (handle / table) | Called on a double-click: two presses on the panel within the double-click window. |
Plus the shared layout/style properties.
save_button
A button that opens a save dialog on click; the positional argument is the label. Give it an id and bind on_save / on_save_source from the hosting app via book:element.
Takes no children.
| Property | Type | Description |
|---|---|---|
value (required) | string | message | Button label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale. |
source | string | The bytes to write, captured now. The write is atomic, on the one click. Omit and bind later with elem:on_save_source to keep the payload current; with none set a click does nothing. |
suggested_name | string | Default filename pre-filled in the save dialog. |
filters | {{ }} template (handle / table) | File-type filters, an array of {label, {ext, ...}} pairs. |
start_dir | {{ }} template (handle / table) | Seeds the dialog's starting location. Best-effort: native dialogs open there; browser pickers ignore it. |
title | string | Dialog title. |
on_save | {{ }} template (handle / table) | Called after the bytes are committed to the chosen file, with the read-only File handle (never on cancel). Optional; bind later with elem:on_save. |
enabled | boolean | Whether the button starts enabled (default true). |
Plus the shared layout/style properties.
slider
A horizontal slider. Bind on_change from the hosting app via book:element.
Takes no children.
| Property | Type | Description |
|---|---|---|
value | number | Initial value, clamped to [min, max] (default the range midpoint). |
min | number | Range minimum (default 0). |
max | number | Range maximum (default 1). |
step | number | Keyboard / track-click step increment (default 0.1). |
enabled | boolean | Whether it starts enabled (default true). A disabled slider ignores drag and keyboard input until elem.enabled = true. |
on_change | {{ }} template (handle / table) | Called with the new value (number) continuously as the user drags or steps it. A programmatic elem.value = ... write does not fire it. |
Plus the shared layout/style properties.
slot
A named empty container the hosting app fills via book:element — mount canvases, scenes, or any UI into it.
Takes no children.
| Property | Type | Description |
|---|---|---|
color | color ("#rrggbb") | Background color; defaults to the theme panel background. Pass a datumhue.theme.token(...) to follow the theme and repaint on change. |
material | {{ }} template (handle / table) | Shader material applied to the panel. |
on_hover | {{ }} template (handle / table) | Called when the cursor enters the panel or any of its descendants. |
on_hover_exit | {{ }} template (handle / table) | Called when the cursor leaves the panel and all of its descendants. |
on_press | {{ }} template (handle / table) | Called when a mouse button is pressed on the panel. |
on_release | {{ }} template (handle / table) | Called when a mouse button is released over the panel. |
on_double_click | {{ }} template (handle / table) | Called on a double-click: two presses on the panel within the double-click window. |
Plus the shared layout/style properties.
text_input
A text input field; value seeds it and placeholder shows while empty.
Takes no children.
| Property | Type | Description |
|---|---|---|
value | string | Initial text content (default empty). Read/write later via the text property. |
placeholder | string | Placeholder shown while the field is empty. |
max_length | number | Maximum number of characters the field accepts. |
multiline | boolean | Allow multiple lines: Enter inserts a newline instead of submitting (default false). |
filter | string | A Lua character-class pattern (e.g. "%d", "[%d.-]") restricting which characters can be typed or pasted, matched per character. It masks the character set, not structure: validate the whole value in on_change or on_submit (and prefer number_input for numbers). ASCII-oriented like Lua's own %-classes; raises if the pattern is malformed. |
select_all_on_focus | boolean | Select all the text when the field gains keyboard focus (default false). |
enabled | boolean | Whether it starts enabled (default true). A disabled input ignores keyboard and pointer input until elem.enabled = true. |
on_change | {{ }} template (handle / table) | Called with the new text (string) on each user edit. A programmatic elem.text = ... write does not fire it. |
on_submit | {{ }} template (handle / table) | Called with the text (string) when Enter is pressed in a single-line input. |
autofocus | boolean | Take keyboard focus as soon as the input is created (default false). If several inputs request it in one frame, the last one created wins. |
on_focus | {{ }} template (handle / table) | Called when the input gains keyboard focus. |
on_blur | {{ }} template (handle / table) | Called when the input loses keyboard focus (clicking away, Tab, or the app losing focus). |
on_cancel | {{ }} template (handle / table) | Called when Escape is pressed while the input is focused. |
Plus the shared layout/style properties.
Layout & style properties
Shared by every visual element; the same names and values as the ui.NodeStyle option fields.
| Property | Type | Description |
|---|---|---|
left | number | string | Left anchor (px or "%"). |
right | number | string | Right anchor (px or "%"). |
top | number | string | Top anchor (px or "%"). |
bottom | number | string | Bottom anchor (px or "%"). |
width | number | string | Width (px or "%"). |
height | number | string | Height (px or "%"). |
min_width | number | string | Minimum width. |
max_width | number | string | Maximum width. |
min_height | number | string | Minimum height. |
max_height | number | string | Maximum height. |
aspect_ratio | number | Aspect ratio (width / height). |
margin | number | string | Outer margin: scalar, string, or {top,bottom,left,right}. |
padding | number | string | Inner padding: scalar, string, or {top,bottom,left,right}. |
border | number | string | Border widths: scalar, string, or {top,bottom,left,right}. |
flex_grow | number | Flex grow factor. |
flex_shrink | number | Flex shrink factor. |
flex_basis | number | string | Flex basis (px or "%"). |
align_self | "auto" | "start" | "end" | "flex_start" | "flex_end" | "center" | "baseline" | "stretch" | Per-item cross-axis alignment. |
flex_direction | "row" | "row_reverse" | "column" | "column_reverse" | Main-axis direction. |
flex_wrap | "nowrap" | "wrap" | "wrap_reverse" | Wrapping behavior. |
justify_content | "default" | "start" | "end" | "flex_start" | "flex_end" | "center" | "stretch" | "space_between" | "space_around" | "space_evenly" | Main-axis distribution. |
align_items | "default" | "start" | "end" | "flex_start" | "flex_end" | "center" | "baseline" | "stretch" | Cross-axis alignment of items. |
align_content | "default" | "start" | "end" | "flex_start" | "flex_end" | "center" | "stretch" | "space_between" | "space_around" | "space_evenly" | Cross-axis distribution of wrapped lines. |
gap | number | string | Shorthand for row_gap + column_gap. |
row_gap | number | string | Row gap (overrides gap). |
column_gap | number | string | Column gap (overrides gap). |
overflow | "visible" | "clip" | "clip_x" | "clip_y" | "hidden" | "scroll" | "scroll_x" | "scroll_y" | Overflow handling. The scroll variants make the element a wheel-scrollable container; see the scroll / scroll_max element properties. |
display | "flex" | "grid" | "block" | "none" | Display mode. grid auto-places children one per row — a single-column grid, as no track or placement options exist; for multi-column layouts compose flex containers. |
border_color | color ("#rrggbb") | Border color; defaults to the theme panel border. Pass a datumhue.theme.token(...) to follow the theme and repaint on change. |
border_radius | number | string | Corner rounding: scalar, string, or per-corner table. |
z_index | number | Stacking order. |
outline | {{ }} template (handle / table) | Focus outline. |
box_shadow | {{ }} template (handle / table) | Drop shadow: one shadow, or an array drawn back-to-front. |
Authoring & tooling
Theme format
A theme is a small text document with up to four blocks: colors, metrics, shaders, and widget_shaders. Every block is optional and any block may set only some of its keys — unset keys keep the active theme's value, so a theme can be a tiny override or a full repaint. Unknown keys are ignored.
Colors are hex literals: 0xRRGGBB for an opaque color, 0xRRGGBBAA where a shader wants alpha.
Load a theme file and apply it:
local theme = my_dir:read("sunset.theme"):theme()
datumhue.theme.pin(theme)
colors
Each line is a token name followed by an 0xRRGGBB hex color:
colors {
panel_background 0x343f44
accent_primary 0xa7c080
}
The Dark / Light columns are the built-in Everforest values each token resolves to when a theme leaves it unset.
| Token | Group | Dark | Light | Description |
|---|---|---|---|---|
panel_background | Surfaces | 0x343f44 | 0xf4f0d9 | Panel / card fill. |
panel_border | Surfaces | 0x475258 | 0xe6e2cc | Panel / card border. |
surface_sunken | Surfaces | 0x2d353b | 0xfdf6e3 | Recessed surface: wells, insets, trays. |
surface_raised | Surfaces | 0x4f585e | 0xe0dcc7 | Raised surface: cards, headers. |
surface_overlay | Surfaces | 0x56635f | 0xbdc3af | Floating overlay: menus, tooltips. |
selection_background | Surfaces | 0x543a48 | 0xeaedc8 | Selection / row-highlight background. |
focus_ring | Surfaces | 0xa7c080 | 0x8da101 | Keyboard-focus ring outline. |
button_normal | Buttons | 0x3d484d | 0xefebd4 | Button rest fill. |
button_hover | Buttons | 0x475258 | 0xe6e2cc | Button hover fill. |
button_pressed | Buttons | 0x343f44 | 0xf4f0d9 | Button pressed fill. |
button_text | Buttons | 0xd3c6aa | 0x5c6a72 | Button label text. |
button_disabled | Buttons | 0x2d353b | 0xfdf6e3 | Disabled button fill. |
button_text_disabled | Buttons | 0x7a8478 | 0xa6b0a0 | Disabled button label text. |
checkbox_background | Checkbox | 0x2d353b | 0xfdf6e3 | Checkbox box fill when unchecked. |
checkbox_background_checked | Checkbox | 0xa7c080 | 0x8da101 | Checkbox box fill when checked. |
checkbox_border | Checkbox | 0x4f585e | 0xe0dcc7 | Checkbox box border. |
checkbox_mark | Checkbox | 0x2d353b | 0xfdf6e3 | Checkbox mark drawn inside when checked. |
slider_track | Slider | 0x2d353b | 0xfdf6e3 | Slider track groove. |
slider_fill | Slider | 0xa7c080 | 0x8da101 | Slider filled portion left of the thumb. |
slider_thumb | Slider | 0x4f585e | 0xe0dcc7 | Slider draggable thumb. |
radio_border | Radio | 0x859289 | 0x939f91 | Radio option circle border (unselected). |
radio_mark | Radio | 0xa7c080 | 0x8da101 | Radio inner dot + selected circle border. |
scrollbar_track | Scrollbar | 0x2d353b | 0xfdf6e3 | Scrollbar track gutter. |
scrollbar_thumb | Scrollbar | 0x4f585e | 0xe0dcc7 | Scrollbar draggable thumb. |
list_row_selected | List | 0x425047 | 0xf0f1d2 | Selected list row background. |
list_row_active | List | 0xa7c080 | 0x8da101 | Active (focused) list row outline. |
input_background | Text Input | 0x2d353b | 0xfdf6e3 | Text input field background. |
input_border | Text Input | 0x4f585e | 0xe0dcc7 | Text input field border. |
input_text | Text Input | 0xd3c6aa | 0x5c6a72 | Entered text. |
input_placeholder | Text Input | 0x859289 | 0x939f91 | Placeholder text shown when empty. |
input_cursor | Text Input | 0xa7c080 | 0x8da101 | Text input caret. |
popover_background | Overlay | 0x3d484d | 0xefebd4 | Popover panel background. |
popover_border | Overlay | 0x56635f | 0xbdc3af | Popover panel border. |
menu_background | Overlay | 0x3d484d | 0xefebd4 | Dropdown menu popup background. |
menu_border | Overlay | 0x56635f | 0xbdc3af | Dropdown menu popup border. |
text_primary | Text | 0xd3c6aa | 0x5c6a72 | Primary text. |
text_secondary | Text | 0x859289 | 0x939f91 | Secondary / muted text. |
text_disabled | Text | 0x7a8478 | 0xa6b0a0 | Disabled / faint text. |
accent_primary | Accents | 0xa7c080 | 0x8da101 | Primary accent (brand green). |
accent_secondary | Accents | 0x83c092 | 0x35a77c | Secondary accent. |
accent_data | Accents | 0xe69875 | 0xf57d26 | Data-point accent (brand orange). |
accent_tertiary | Accents | 0xd699b6 | 0xdf69ba | Tertiary accent. |
success | Status | 0xa7c080 | 0x8da101 | Success foreground. |
warning | Status | 0xdbbc7f | 0xdfa000 | Warning foreground. |
error | Status | 0xe67e80 | 0xf85552 | Error foreground. |
info | Status | 0x7fbbb3 | 0x3a94c5 | Info foreground. |
success_background | Status surfaces | 0x425047 | 0xf0f1d2 | Muted success banner surface. |
warning_background | Status surfaces | 0x4d4c43 | 0xfaedcd | Muted warning banner surface. |
error_background | Status surfaces | 0x514045 | 0xfde3da | Muted error banner surface. |
info_background | Status surfaces | 0x3a515d | 0xe9f0e9 | Muted info banner surface. |
accent_tertiary_background | Status surfaces | 0x4a444e | 0xfae8e2 | Muted tertiary-accent surface. |
statusline_primary | Status bar | 0xa7c080 | 0x93b259 | Status bar, primary state. |
statusline_secondary | Status bar | 0xd3c6aa | 0x708089 | Status bar, secondary state. |
statusline_tertiary | Status bar | 0xe67e80 | 0xe66868 | Status bar, tertiary state. |
chart_axis | Chart | 0x859289 | 0x939f91 | Axis / tick lines. |
chart_grid | Chart | 0x475258 | 0xe6e2cc | Gridlines. |
chart_axis_label | Chart | 0x9da9a0 | 0x829181 | Tick labels. |
chart_background | Chart | 0x232a2e | 0xefebd4 | Plot-area background. |
chart_legend_background | Chart | 0x2d353b | 0xfdf6e3 | Legend backing (translucent). |
chart_legend_border | Chart | 0x475258 | 0xe6e2cc | Legend border. |
chart_legend_text | Chart | 0xd3c6aa | 0x5c6a72 | Legend text. |
metrics
Each line is a token name followed by one number, in pixels:
metrics {
padding_medium 10
border_radius 6
}
| Token | Group | Default | Description |
|---|---|---|---|
padding_small | Spacing | 4 px | Small inner padding. |
padding_medium | Spacing | 8 px | Medium inner padding. |
padding_large | Spacing | 16 px | Large inner padding. |
input_padding_vertical | Spacing | 6 px | Vertical padding inside a text input field. |
gap_small | Spacing | 4 px | Small gap between items. |
gap_medium | Spacing | 8 px | Medium gap between items. |
gap_large | Spacing | 16 px | Large gap between items. |
border_width | Borders | 1 px | Default border width. |
border_radius | Borders | 4 px | Default corner radius. |
font_size_small | Typography | 12 px | Small font size. |
font_size_normal | Typography | 14 px | Normal font size. |
font_size_large | Typography | 16 px | Large font size. |
font_size_heading | Typography | 20 px | Heading / section-title font size. |
font_size_title | Typography | 24 px | Dialog and modal title font size. |
font_size_display | Typography | 28 px | Largest display font size (top-level document headings, hero text). |
font_weight_normal | Typography | 500 wght | Body text weight on the variable axis. |
font_weight_heading | Typography | 600 wght | Heading and title weight on the variable axis. |
button_min_width | Buttons | 80 px | Minimum button width. |
button_min_height | Buttons | 32 px | Minimum button height. |
shaders
Each child of shaders is a named GPU material. type picks one of the shader kinds below; color1 / color2 are 0xRRGGBBAA hex (some kinds read the alpha), param1 / param2 are numbers whose meaning depends on the type, and animated (a #true / #false flag) freezes or runs the time-driven kinds. An optional fallback (0xRRGGBB) is the solid color shown if the material can't render; it defaults to color1.
shaders {
frosted {
type "glassmorphism"
color1 0xffffff40
color2 0xa7c080ff
param1 0.5
param2 0.2
}
}
The parameter columns name what each slot means for that type; a blank cell means the type ignores that slot. The Anim column marks the time-driven kinds.
| Type | Anim | color1 | color2 | param1 | param2 | Description |
|---|---|---|---|---|---|---|
solid | Fill color | Flat fill. | ||||
gradient | Start color | End color | Angle in radians (0 = left-to-right) | Linear gradient between two colors. | ||
radial_gradient | Inner / center color | Outer / edge color | Center offset X (UV; 0 = centered) | Center offset Y (UV; 0 = centered) | Radial gradient from a center point. | |
animated_glow | yes | Base color | Glow color | Glow intensity | Pulse speed | Base color under a pulsing glow. |
glassmorphism | Glass tint (alpha = transparency) | Border highlight | Border width (0-1) | Noise intensity | Frosted-glass panel with a highlighted border. | |
scanline | yes | Base color (alpha = scanline darkness) | Beam tint | Scanline density | Beam sweep speed | CRT scanlines with a moving phosphor beam. |
noise | Base color | Noise tint | Noise intensity | Noise scale (higher = finer grain) | Static value noise over a base color. | |
border | Border color | Fill color | Border width (UV) | Corner radius (UV) | Rounded border over a fill. | |
checkerboard | First color | Second color | Tile count across | Two-color checkerboard. | ||
stripe | Stripe color | Gap color | Stripe count | Angle in radians (0 = horizontal) | Parallel stripes. | |
dissolve | Visible color | Edge glow color | Threshold (0 = visible, 1 = dissolved) | Edge width | Threshold burn / dissolve with a glowing edge. | |
outline | Fill color | Outline color | Outline width (0-1) | Glow falloff | Filled shape with a glowing outline. | |
wave | yes | Base color | Blend color | Wave amplitude | Wave frequency | Time-distorted wave blend between two colors. |
color_ramp | Start color | End color | 0 = linear, 1 = stepped | Step count (when stepped) | Color ramp, linear or stepped. |
widget_shaders
Each line binds a widget slot to a material defined in the shaders block, so widgets of that kind paint with the material unless they set their own. Slots left unset use a solid fill:
widget_shaders {
button "frosted"
panel "frosted"
}
| Slot | Description |
|---|---|
button | Default shader material for buttons. |
panel | Default shader material for panels. |
Overridable engine messages
An app or deployment .ftl set as datumhue.i18n.locale may redefine any of these keys to translate or rebrand built-in widget chrome; unredefined keys fall back to the embedded en-001 defaults below.
| Key | Vars | Default (en-001) | Description |
|---|---|---|---|
datumhue-calendar-month | $n | { $n -> [1] January [2] February [3] March [4] April [5] May [6] June [7] July [8] August [9] September [10] October [11] November [12] December *[other] {$n} } | Full month name shown in the date picker's header; selects on the 1–12 month number ($n). |
datumhue-calendar-weekday-narrow | $n | { $n -> [1] M [2] T [3] W [4] T [5] F [6] S *[7] S } | Narrow (single-letter) weekday label for the date picker's column header; selects on 1=Monday..7=Sunday ($n). |
datumhue-calendar-weekday-long | $n | { $n -> [1] Monday [2] Tuesday [3] Wednesday [4] Thursday [5] Friday [6] Saturday *[7] Sunday } | Full weekday name used as the date picker column header's accessible name (a screen reader reads it instead of the narrow letter); selects on 1=Monday..7=Sunday ($n). |
datumhue-calendar-week-start | — | 1 | First day of the week for the date picker (1=Monday..7=Sunday). Defaults to Monday; a locale catalog may override it (e.g. set 7 for a Sunday-first region). |
Package testing
The globals datumhue pkg test installs in a package's tests/*_test.lua modules before requiring them. They exist only during a test run — never while the package runs normally. The same declarations render the tests/test.d.lua annotation file datumhue pkg new / pkg refresh write, so editors check test modules against exactly this surface.
Test globals
describe(name, opts)
describe(name: string, opts?: dhtest.DescribeOpts)
Opens a suite; the it calls that follow belong to it until the next describe. Suites and their tests run serially in declaration order.
it(name, opts_or_body, body)
it(name: string, opts_or_body: dhtest.ItOpts|fun(), body?: fun())
Registers a test. The body runs as a coroutine pumped once per engine tick, so it can suspend with wait_frames / wait_until. Before the body, math.randomseed is set from the test's full name mixed with the run seed, so RNG is reproducible and insertion-stable.
wait_frames(n)
wait_frames(n: integer)
Suspends the current test for n engine ticks (at least one).
wait_until(pred, timeout_frames)
wait_until(pred: fun(): boolean, timeout_frames?: integer)
Suspends until pred() returns a truthy value, checking once per engine tick. Fails the test when the budget runs out (default 600 ticks).
expect(value)
expect(value: any) -> dhtest.Expectation
Builds a matcher for value; every matcher raises on mismatch.
fail(msg)
fail(msg?: string)
Fails the current test.
skip(reason)
skip(reason?: string)
Marks the current test skipped and stops its body.
Expectation matchers
expect(value) returns a matcher table; every matcher raises on mismatch, failing the test with the mismatch in its diagnostic.
| Matcher | Description |
|---|---|
.to_be(expected) | Same value (==). |
.to_equal(expected) | Deep table equality. |
.to_be_truthy() | |
.to_be_falsy() | |
.to_be_nil() | |
.to_be_close(expected, tolerance?) | Numeric closeness (default tolerance 1e-6). |
.to_contain(needle) | Substring of a string, or == member of an array. |
Option tables
dhtest.DescribeOpts
| Field | Type | Description |
|---|---|---|
before_each? | fun() | Runs inside each test's coroutine before the body; may wait. |
after_each? | fun() | Runs after each test in its own coroutine, even when the body failed or timed out; may wait. |
dhtest.ItOpts
| Field | Type | Description |
|---|---|---|
timeout_frames? | integer | Per-test budget in engine ticks (default 3600). |
CLI reference
The datumhue commands this build exposes. Each command's options and defaults mirror its --help.
datumhue
DatumHue Creative Workstation
Arguments:
[<SCRIPT_ARGS>]— Tokens forwarded to the launched script viadatumhue.args.argv
Options:
[--bootstrap <NAME>]— Bootstrap package to launch. Falls back toDATUMHUE_BOOTSTRAP_PACKAGE[--namespace <NAME>]— Catalog namespace to bootstrap from. The bootstrap package anddatumhue.packagesqueries resolve against this namespace. Falls back toDATUMHUE_BOOTSTRAP_NAMESPACE, thendatumhue[--session <NAME>]— Explicit session id. Wins over--continue[--continue]— Resume the most recently used session id (if any)[--headless]— Run without a window; nothing is drawn. The launched package must be a service app; UI apps are rejected. Lua execution, networking, asset loading, and local-scope messaging behave the same as in a windowed launch[--accept-license]— Accept the embedded end-user license agreement for this run. The acceptance is recorded so subsequent launches skip both the dialog and this flag. Required once for--headless; GUI launches can accept via the dialog instead[--debug-input]— Allowdatumhue.debug.inputfor this launch even though the package arrives from the deployment. Local scripts and package directories allow it without this flag[--dir <NAME:PATH>]— Grant a read-only directory capability (NAME:PATH)[--dir-rw <NAME:PATH>]— Grant a read-write directory capability (NAME:PATH)[--file <NAME:PATH>]— Grant a read-only file capability (NAME:PATH)[--file-rw <NAME:PATH>]— Grant a read-write file capability (NAME:PATH)[--remote-dir <NAME:MOUNT>]— Grant a read-only directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT). The script reaches the directory asdatumhue.args.dirs.<name>[--remote-dir-rw <NAME:MOUNT>]— Grant a read-write directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT)[--data-mount <NAME:MOUNT>]— Grant a read-only data mount capability (NAME:MOUNT). The script reaches the mount asdatumhue.args.data_mounts.<name>and runs SQL queries viamount:query(sql)[--data-mount-rw <NAME:MOUNT>]— Grant a read-write data mount capability (NAME:MOUNT)[--http-mount <NAME:MOUNT>]— Grant an HTTP mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.http_mounts.<name>and makes requests viamount:get(path)/mount:post(path, opts)etc[--ingress-mount <NAME:MOUNT>]— Grant an ingress mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.ingress_mounts.<name>and subscribes to its channel viamount:subscribe({callback = ...})
datumhue run
Run a local Lua script or package directly. Accepts a .lua file, a directory containing a package.kdl manifest, or a .dhpkg archive. Defaults to the current directory when no path is given
Arguments:
[<SCRIPT>]— Path to the.luascript, package directory, or.dhpkgarchive to run. Defaults to the current directory (default:.)[<SCRIPT_ARGS>]— Everything after--reaches the script viadatumhue.args.argv
Options:
[--dir <NAME:PATH>]— Grant a read-only directory capability (NAME:PATH)[--dir-rw <NAME:PATH>]— Grant a read-write directory capability (NAME:PATH)[--file <NAME:PATH>]— Grant a read-only file capability (NAME:PATH)[--file-rw <NAME:PATH>]— Grant a read-write file capability (NAME:PATH)[--remote-dir <NAME:MOUNT>]— Grant a read-only directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT). The script reaches the directory asdatumhue.args.dirs.<name>[--remote-dir-rw <NAME:MOUNT>]— Grant a read-write directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT)[--data-mount <NAME:MOUNT>]— Grant a read-only data mount capability (NAME:MOUNT). The script reaches the mount asdatumhue.args.data_mounts.<name>and runs SQL queries viamount:query(sql)[--data-mount-rw <NAME:MOUNT>]— Grant a read-write data mount capability (NAME:MOUNT)[--http-mount <NAME:MOUNT>]— Grant an HTTP mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.http_mounts.<name>and makes requests viamount:get(path)/mount:post(path, opts)etc[--ingress-mount <NAME:MOUNT>]— Grant an ingress mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.ingress_mounts.<name>and subscribes to its channel viamount:subscribe({callback = ...})[--service]— Run the script as a service app — no UI, and the UI subtables ofdatumhueare unavailable. Only applies to a.luafile; for a package directory or.dhpkgarchive the manifest's ownservicefield is authoritative and passing this flag errors[--debug-input]— Allowdatumhue.debug.inputfor this run even though the target is a packed archive. Local scripts and package directories allow it without this flag[--watch]— Watch the source and reload the running app when files change. A change that fails to load or compile keeps the current version running and prints the error[--profile <PATH>]— Record a sampling profile of the run's script execution and write it to PATH on exit, in speedscope JSON format with one profile per app[--profile-summary <PATH>]— Also write a profiling summary as JSON to PATH: per-function call counts with self and total times, plus per-app frame-budget statistics[--report <PATH>]— Also write an HTML report of the profile to PATH[--open]— Write the HTML report (to --report PATH or a temporary file) and open it in the system browser after the run
datumhue debug
Bind a DAP (Debug Adapter Protocol) TCP listener and wait for an editor (Helix, VS Code, nvim-dap, Zed) to connect and send a launch request with the program path. Filesystem capabilities (--dir / --file) go on this command because the DAP protocol doesn't carry them; the program path comes from the editor. The listener accepts any connection without authentication and a connected client can run arbitrary code — keep it on the loopback default and treat the port as trusted
Options:
[--dap-listen <HOST:PORT>]— Listener address. The default matches the fixed port most editors dial; use127.0.0.1:0to let the OS pick a free port instead — the bound port is printed to stdout so wrapper scripts can read it (default:127.0.0.1:4711)[--dir <NAME:PATH>]— Grant a read-only directory capability (NAME:PATH)[--dir-rw <NAME:PATH>]— Grant a read-write directory capability (NAME:PATH)[--file <NAME:PATH>]— Grant a read-only file capability (NAME:PATH)[--file-rw <NAME:PATH>]— Grant a read-write file capability (NAME:PATH)[--remote-dir <NAME:MOUNT>]— Grant a read-only directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT). The script reaches the directory asdatumhue.args.dirs.<name>[--remote-dir-rw <NAME:MOUNT>]— Grant a read-write directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT)[--data-mount <NAME:MOUNT>]— Grant a read-only data mount capability (NAME:MOUNT). The script reaches the mount asdatumhue.args.data_mounts.<name>and runs SQL queries viamount:query(sql)[--data-mount-rw <NAME:MOUNT>]— Grant a read-write data mount capability (NAME:MOUNT)[--http-mount <NAME:MOUNT>]— Grant an HTTP mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.http_mounts.<name>and makes requests viamount:get(path)/mount:post(path, opts)etc[--ingress-mount <NAME:MOUNT>]— Grant an ingress mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.ingress_mounts.<name>and subscribes to its channel viamount:subscribe({callback = ...})
datumhue pkg
Build and inspect package directories and .dhpkg archives
datumhue pkg pack
Bundle a package directory into a .dhpkg archive. The source directory must contain a package.kdl manifest at its root. Output defaults to <scope>-<name>-<version>.dhpkg next to the source; override with --out. Source defaults to the current directory
Arguments:
[<SOURCE>]— Package directory to archive. Must containpackage.kdl. Defaults to the current directory (default:.)
Options:
[--out <PATH>]— Destination.dhpkgpath. If omitted, the archive is written next tosourceas<scope>-<name>-<version>.dhpkg[--bind-license <FILE>]— Bind the archive to the indie license in FILE for redistribution with the runtime. Requires a sealed package. Signs the archive content with the license's package key, stampslicensed-tointo the packed manifest, and writes the redistributable<scope>-<name>.dhruntimebinding next to the archive. Ship the archive and the binding with your creation; bound archives load only on your own workstation or on the runtime[--allow-plugin <NAME:PATH>]— Pin a host plugin build into the packed manifest. GiveNAME:PATH, where NAME matches arequires_pluginentry in package.kdl and PATH is the plugin library to hash. Its blake3 content hash is recorded on that entry's allowlist and covered by the package binding signature. Repeat once per platform binary; a redistributable runtime loads a plugin only when its content hash matches one of the pins
datumhue pkg info
Print a one-line summary of a package: name, version, kind, file count, and content hash. Accepts a .dhpkg archive or a source directory
Arguments:
[<TARGET>]— Path to a.dhpkgfile or a package source directory. Defaults to the current directory (default:.)
datumhue pkg ls
List the files inside a package — either a .dhpkg archive or a source directory. Paths are package-relative, sorted, one per line. Add --long to include per-file size and content hash columns
Arguments:
[<TARGET>]— Path to a.dhpkgfile or a package source directory. Defaults to the current directory (default:.)
Options:
[--long]— Emit size + content hash columns alongside each path
datumhue pkg cat
Print the raw bytes of a single file inside a package to stdout. Binary-safe — no encoding or framing. Errors if the requested path isn't in the bundle
Arguments:
<TARGET>— Path to a.dhpkgfile or a package source directory<REL>— Package-relative path to read
datumhue pkg hash
Print just the content hash of a package to stdout — nothing else, single line, shell-pipeable. Accepts a .dhpkg file or a source directory
Arguments:
[<TARGET>]— Path to a.dhpkgfile or a package source directory. Defaults to the current directory (default:.)
datumhue pkg unpack
Extract a .dhpkg archive back to a directory. Useful for inspecting, forking, or diffing a published package. Errors if the output directory already exists and is non-empty unless --force is supplied
Arguments:
<ARCHIVE>—.dhpkgarchive to extract
Options:
[--out <DIR>]— Output directory. Defaults to the archive's stem in the current working directory[--force]— Allow overwriting existing files in the output dir
datumhue pkg new
Scaffold a new package directory with package.kdl, init.lua, empty lib/ and assets/ directories, and a .dhignore with common editor-artifact patterns. kind defaults to "app". Errors if <dir> already exists and is non-empty
Arguments:
<DIR>— Directory to create and scaffold into
Options:
[--name <NAME>]— Scoped package identity@scope/name, e.g.@your-scope/my-package. Both segments are lowercase letters, digits,_, or-, starting with a letter or digit;_is folded to-[--kind <KIND>]— Manifestkind. The refinements (theme, book, dataset, ...) scaffold asasset_packpackages with the matchingcontent_type(default:app)[--service]— Scaffold a service app: setsservice #truein the manifest and uses aninit.luatemplate oriented around messaging instead of UI. Only valid with--kind app
datumhue pkg refresh
Rewrite the editor-integration files — datumhue.d.lua (LuaLS annotations), .luarc.json (LuaLS workspace), and .stylua.toml (formatter config) — in a package directory to match the current binary's templates. Run after a datumhue upgrade to pick up annotations for new APIs. Never modifies package.kdl, init.lua, lib/, or assets/
Arguments:
[<SOURCE>]— Package directory to refresh. Must containpackage.kdl. Defaults to the current directory (default:.)
datumhue pkg check
Validate a package directory without packing it. Parses the manifest, checks the layout, rejects reserved paths, applies .dhignore, applies the publish license policy (a free package must declare a license the platform may redistribute it under), and resolves requires against sibling packages. Exit 0 on success with an OK summary line; exit 1 on failure with per-problem diagnostics
Arguments:
[<SOURCE>]— Package directory to validate. Must containpackage.kdl. Defaults to the current directory (default:.)
datumhue pkg test
Run the package's test suite from its tests/ directory. Test modules (tests/*_test.lua) register suites with describe/it; results stream as TAP on stdout. Service packages run headless; windowed packages open a window, so wrap the invocation in a headless compositor (e.g. gamescope --backend headless --) when no display should appear. Exit 0 when every test passes, 1 on test failures, 2 on usage, assembly, or pre-flight errors
Arguments:
[<DIR>]— Package directory containing atests/suite. Defaults to the current directory (default:.)[<FILTER>]— Run only tests whose full name (suite > name) contains any FILTER substring. A filter that matches nothing fails the run[<ARGS>]— Everything after--reaches the suite viadatumhue.args.argv
Options:
[--list]— List test names without running anything[--skip <PAT>]— Skip tests whose full name contains PAT (repeatable). A pattern that matches nothing fails the run[--seed <SEED>]— Seed mixed into every test's RNG stream. Each run prints the seed it used; pass it back to reproduce the run[--timeout <SECS>]— Whole-run watchdog in seconds. Overrides the suite'stests/test.kdltimeout-seconds(default 300)[--report <PATH>]— Also write an HTML report of the run to PATH[--open]— Write the HTML report (to --report PATH or a temporary file) and open it in the system browser after the run[--dap]— Serve the assembled suite on a DAP listener instead of running it: connect an editor, set breakpoints on the real source paths (tests/ included), and sendlaunch[--dap-listen <HOST:PORT>]— Address for the--daplistener (default:127.0.0.1:4711)[--profile <PATH>]— Record a sampling profile of the suite's script execution and write it to PATH after the run, in speedscope JSON format with one profile per app[--profile-summary <PATH>]— Also write a profiling summary as JSON to PATH: per-function call counts with self and total times, plus per-app frame-budget statistics[--dir <NAME:PATH>]— Grant a read-only directory capability (NAME:PATH)[--dir-rw <NAME:PATH>]— Grant a read-write directory capability (NAME:PATH)[--file <NAME:PATH>]— Grant a read-only file capability (NAME:PATH)[--file-rw <NAME:PATH>]— Grant a read-write file capability (NAME:PATH)[--remote-dir <NAME:MOUNT>]— Grant a read-only directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT). The script reaches the directory asdatumhue.args.dirs.<name>[--remote-dir-rw <NAME:MOUNT>]— Grant a read-write directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT)[--data-mount <NAME:MOUNT>]— Grant a read-only data mount capability (NAME:MOUNT). The script reaches the mount asdatumhue.args.data_mounts.<name>and runs SQL queries viamount:query(sql)[--data-mount-rw <NAME:MOUNT>]— Grant a read-write data mount capability (NAME:MOUNT)[--http-mount <NAME:MOUNT>]— Grant an HTTP mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.http_mounts.<name>and makes requests viamount:get(path)/mount:post(path, opts)etc[--ingress-mount <NAME:MOUNT>]— Grant an ingress mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.ingress_mounts.<name>and subscribes to its channel viamount:subscribe({callback = ...})
datumhue pkg cov
Run the package's test suite with line and branch coverage of the package's Lua code. After the run, prints a per-file covered/total table; modules the suite never loaded count as uncovered. Exit 0 on a passing run (within any --fail-under / --fail-under-branch bound), 1 on test failures or a missed bound, 2 on usage, assembly, or pre-flight errors
Arguments:
[<DIR>]— Package directory containing atests/suite. Defaults to the current directory (default:.)[<FILTER>]— Run only tests whose full name (suite > name) contains any FILTER substring. A filter that matches nothing fails the run[<ARGS>]— Everything after--reaches the suite viadatumhue.args.argv
Options:
[--skip <PAT>]— Skip tests whose full name contains PAT (repeatable). A pattern that matches nothing fails the run[--seed <SEED>]— Seed mixed into every test's RNG stream. Each run prints the seed it used; pass it back to reproduce the run[--timeout <SECS>]— Whole-run watchdog in seconds. Overrides the suite'stests/test.kdltimeout-seconds(default 300)[--lcov <PATH>]— Also write an LCOV tracefile to PATH[--fail-under <PCT>]— Exit non-zero when total line coverage is below PCT[--fail-under-branch <PCT>]— Exit non-zero when total branch coverage is below PCT. Branches are condition-level: each conditional gets two outcomes, and ana and bcondition counts as two branches[--report <PATH>]— Also write an HTML report of the run — test results plus per-file line and branch coverage over the package's source — to PATH[--open]— Write the HTML report (to --report PATH or a temporary file) and open it in the system browser after the run[--dir <NAME:PATH>]— Grant a read-only directory capability (NAME:PATH)[--dir-rw <NAME:PATH>]— Grant a read-write directory capability (NAME:PATH)[--file <NAME:PATH>]— Grant a read-only file capability (NAME:PATH)[--file-rw <NAME:PATH>]— Grant a read-write file capability (NAME:PATH)[--remote-dir <NAME:MOUNT>]— Grant a read-only directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT). The script reaches the directory asdatumhue.args.dirs.<name>[--remote-dir-rw <NAME:MOUNT>]— Grant a read-write directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT)[--data-mount <NAME:MOUNT>]— Grant a read-only data mount capability (NAME:MOUNT). The script reaches the mount asdatumhue.args.data_mounts.<name>and runs SQL queries viamount:query(sql)[--data-mount-rw <NAME:MOUNT>]— Grant a read-write data mount capability (NAME:MOUNT)[--http-mount <NAME:MOUNT>]— Grant an HTTP mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.http_mounts.<name>and makes requests viamount:get(path)/mount:post(path, opts)etc[--ingress-mount <NAME:MOUNT>]— Grant an ingress mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.ingress_mounts.<name>and subscribes to its channel viamount:subscribe({callback = ...})
datumhue pkg update
Resolve a package's dependencies against the registry and write package.lock.kdl. Registry dependencies are pinned to the published content they currently resolve to; yanked versions are skipped. Workspace dependencies are recorded as markers, pinned when the workspace is published. A purchased paid dependency is delivered: its source lands in the project's deps/ directory (signed in, entitled), and the lock records it as vendored. Run this to move onto newer or un-yanked dependency versions; pkg push then publishes against the lock without re-resolving.
Exit codes: 0 = lockfile already up to date, 1 = local error, 3 = the lockfile changed (or would change, with --dry-run) — CI can gate on lock drift by treating exit 3 as failure, 9 = a dependency could not be resolved.
Arguments:
[<SOURCE>]— Package directory to update. Defaults to the current directory. With--workspace, a directory inside the workspace (default:.)
Options:
[--namespace <NAME>]— Registry namespace to resolve dependencies against (a dependency may override it per-entry) (default:datumhue) (env:DATUMHUE_BOOTSTRAP_NAMESPACE)[--workspace]— Update every member of the enclosingworkspace.kdlin one pass[--dry-run]— Resolve and print what would change without writing the lockfile
datumhue pkg license
Print the package licenses DatumHue accepts. Without an id, lists every accepted license with a one-line reading. With an id, prints that license's full text (or, for ids with no public text, what the id means and where its terms come from)
Arguments:
[<ID>]— License id to print, e.g. "0BSD", "MIT-0", "CC0-1.0", "LicenseRef-DatumHue-Freeware", "LicenseRef-Proprietary"
datumhue pkg docs
Generate documentation for a package directory — its modules and exports, the package README as a guide, and its dependencies. --format selects Markdown, JSON, or a self-contained searchable HTML page (the default); --open builds the HTML page and opens it in your browser. Prints to stdout by default; use --out to write a file. Resolves dependencies the same way pkg check does
Arguments:
[<SOURCE>]— Package directory to document. Defaults to the current directory (default:.)
Options:
[--format <FORMAT>]— Output format (default:html)[--out <PATH>]— Write the output to this path instead of stdout[--open]— Build the searchable HTML page and open it in the system browser. Writes to--outwhen given, otherwise a temp file[--deps <DEPS>]— How much of each dependency to include: a card (compact), the dependency's full surface inlined (full), or nothing (none) (default:compact)[--core <CORE>]— How much of each referenced DatumHue core type to include: a stub (compact), the full type inlined (full), or nothing (none). Core types stay recognized and styled either way (default:compact)[--namespace <NAME>]— Document a published package from this namespace's catalog instead of a local directory;<source>is then the package name. Connects to the deployment
datumhue pkg uuid
Print a fresh random UUID to stdout — one line, nothing else. Handy for picking the namespace argument to datumhue.storage.open_shared the same way on every platform
datumhue pkg push
Publish a package directory's lockfile contents to a registry, after verifying the committed package.lock.kdl still resolves (run pkg update first if a dependency was yanked or removed). With --workspace, publishes every member of the enclosing workspace.kdl in dependency order: a member's workspace dependency is published first, so the dependent pins its real published content. Members already published at their version are skipped, so a re-run resumes after a partial failure. Sign in first with datumhue login.
Exit codes: 0 = published, 1 = local error, 2 = registry rejected the sign-in, 3 = signed-in user is not allowed to publish, 4 = manifest invalid, 5 = registry error, 6 = not signed in, 7 = sign-in expired and could not be renewed, 8 = the deployment's sign-in configuration has changed since last login, 9 = the lockfile is stale or a dependency could not be resolved, 10 = the signed-in user does not own the package's scope, 11 = the version is already published with different content.
Arguments:
[<SOURCE>]— Package directory to publish. Must containpackage.kdl. With--workspace, a directory inside the workspace. Defaults to the current directory (default:.)
Options:
[--namespace <NAME>]— Target registry namespace. Defaults to the package's @scope, the namespace the platform issued it under. With --workspace, the default for members that don't set their own. (env:DATUMHUE_BOOTSTRAP_NAMESPACE)[--workspace]— Publish every member of the enclosingworkspace.kdl, in dependency order[--dry-run]— Verify and build locally (with--workspace, stage and order the whole workspace), then exit without sending anything to the registry
datumhue pkg namespaces
List the package namespaces a deployment serves. An operator can run several package providers on distinct namespaces; this enumerates them
datumhue pkg search
Search a namespace's package catalog. With no query, lists every package; a query matches names and descriptions. Narrow with --tags and --kind. Connects to the deployment
Arguments:
[<QUERY>]— Case-insensitive text matched against package name and description. Omit to list the whole namespace
Options:
[--namespace <NAME>]— Namespace to search (default:datumhue) (env:DATUMHUE_BOOTSTRAP_NAMESPACE)[--tags <TAG>]— Require this tag. Repeat to require several[--kind <KIND>]— Restrict to one package kind
datumhue pkg show
Show a catalog package's metadata — version, kind, description, tags, capabilities, and dependencies — without downloading it. Connects to the deployment
Arguments:
<NAME>— Package name to show
Options:
[--namespace <NAME>]— Namespace the package lives in (default:datumhue) (env:DATUMHUE_BOOTSTRAP_NAMESPACE)
datumhue pkg yank
Yank a published version: it drops out of version-range resolution and catalog listings, so new installs skip it. The bytes are never deleted — an exact =X.Y.Z request and already-pinned consumers keep resolving it. Use --undo to re-list. Requires ownership of the package's scope; sign in first with datumhue login.
Exit codes: 0 = done, 1 = local error, 2 = registry rejected the sign-in, 3 = signed-in user is not allowed to yank, 5 = registry error, 6 = not signed in, 7 = sign-in expired and could not be renewed, 8 = the deployment's sign-in configuration has changed since last login, 10 = the signed-in user does not own the package's scope, 11 = the version is not published.
Arguments:
<NAME>— Scoped package name@scope/name<VERSION>— Exact version to yank
Options:
[--namespace <NAME>]— Registry namespace to address. Defaults to the package's @scope, the namespace the platform issued it under. (env:DATUMHUE_BOOTSTRAP_NAMESPACE)[--reason <TEXT>]— Reason recorded with the yank, surfaced when resolution skips the version and inpkg show[--undo]— Reverse a previous yank — re-list the version for resolution
datumhue pkg price
Show or set a paid package's listing price. With an amount, lists (or relists) the package for sale — the platform creates the price on your payout account and the storefront picks it up; without one, shows the current listing. Requires ownership of the package's scope; sign in first with datumhue login.
Exit codes: 0 = done, 1 = local error, 2 = registry rejected the sign-in, 3 = signed-in user is not allowed to set prices, 4 = the package is free or the amount or currency is invalid, 5 = registry error or the platform could not be reached, 6 = not signed in, 7 = sign-in expired and could not be renewed, 8 = the deployment's sign-in configuration has changed since last login, 11 = the package is not published.
Arguments:
<NAME>— Scoped package name@scope/name[<AMOUNT>]— Amount in the currency's minor unit (e.g. cents). Omit to show the current listing
Options:
[--currency <CURRENCY>]— ISO 4217 currency code, lowercase (default:usd)[--namespace <NAME>]— Registry namespace to address. Defaults to the package's @scope, the namespace the platform issued it under. (env:DATUMHUE_BOOTSTRAP_NAMESPACE)
datumhue pkg dependents
List the published packages that depend on a package — the reverse dependency view, for gauging the blast radius before yanking it. Connects to the deployment
Arguments:
<NAME>— Scoped package name@scope/nameto find dependents of
Options:
[--namespace <NAME>]— Namespace the package lives in (default:datumhue) (env:DATUMHUE_BOOTSTRAP_NAMESPACE)
datumhue pkg outdated
Report a local package's registry dependencies that have a newer published version than its constraints currently resolve to, and flag any whose pinned version has since been yanked. Reads package.kdl and connects to the deployment
Arguments:
[<SOURCE>]— Package directory to check. Defaults to the current directory (default:.)
Options:
[--namespace <NAME>]— Namespace to resolve registry dependencies against (a dependency may override it per-entry) (default:datumhue) (env:DATUMHUE_BOOTSTRAP_NAMESPACE)
datumhue license
Inspect or install a license file
datumhue license inspect
Inspect a license file
Arguments:
<PATH>— Path to the.dhlicensefile
datumhue license apply
Verify a license file and install it so DatumHue runs under it
Arguments:
<PATH>— Path to the.dhlicensefile
datumhue login
Sign in to a DatumHue deployment. Sign-in is shared with the GUI client; running this once activates both surfaces.
Exit codes: 0 = signed in, 1 = local error, 2 = the deployment's sign-in service is unreachable, 3 = no matching issuer, 4 = sign-in rejected.
Options:
[--issuer <NAME>]— Issuer name to sign in against: the short name your operator registered with the deployment's identity provider (default:datumhue)[--no-browser]— Print the sign-in URL to stdout instead of opening a browser. Useful for SSH workflows
datumhue data-mount
Document a data mount's SQL surface — its tables, the functions its engine accepts, and a given table's columns — or list the mounts you can reach. Connects to a provider over the deployment's network; sign in with datumhue login first for mounts that require it. The output reflects what your identity is allowed to see
datumhue data-mount list
List the data mounts announced in the deployment
datumhue data-mount describe
Render a mount's manual — its tables and the SQL functions its engine accepts. Give a table or path to describe just that table's columns
Arguments:
<MOUNT>— Mount name (as listed bydata-mount list)[<PATH>]— View name or mount-relative path to describe instead of the whole mount
Options:
[--format <FORMAT>]— Output format (default:markdown)[--out <PATH>]— Write the output to this path instead of stdout[--open]— Build the HTML manual and open it in the system browser. Writes to--outwhen given, otherwise a temp file
datumhue http-mount
Discover and document HTTP mounts
datumhue http-mount list
List the HTTP mounts announced in the deployment
datumhue http-mount describe
Describe a mount — its pinned origin, credential mode, and any attached OpenAPI document. The mount's access control decides what the caller sees, so the description is identity-scoped
Arguments:
<MOUNT>— Mount name (as listed byhttp-mount list)
Options:
[--format <FORMAT>]— Output format (default:text)[--out <PATH>]— Write the output to this path instead of stdout[--open]— Build the HTML description and open it in the system browser. Writes to--outwhen given, otherwise a temp file
datumhue ingress
Discover and document ingress channels
datumhue ingress list
List the ingress channels announced in the deployment
datumhue ingress describe
Describe a channel — its key-rotation period, how it dedups records, and any attached AsyncAPI document. The channel's access control decides what the caller sees, so the description is identity-scoped
Arguments:
<CHANNEL>— Channel name (as listed byingress list)
Options:
[--format <FORMAT>]— Output format (default:text)[--out <PATH>]— Write the output to this path instead of stdout[--open]— Build the HTML description and open it in the system browser. Writes to--outwhen given, otherwise a temp file
datumhue fs-mount
List the remote filesystem mounts a deployment offers. Connects to the deployment's network; sign in with datumhue login first for mounts that require it
datumhue fs-mount list
List the filesystem mounts announced in the deployment
datumhue identity
Discover the sign-in issuers a deployment offers and inspect one's OIDC configuration
datumhue identity list
List the sign-in issuers announced in the deployment
datumhue identity describe
Print an issuer's OIDC configuration — the URL, client id, and scopes a datumhue login would authenticate against
Arguments:
<ISSUER>— Issuer name (as listed byidentity list)
datumhue repl
Interactive Lua REPL. Reads lines from stdin, evaluates each against the running app's globals, and prints results. Optional path (a .lua file, package directory, or .dhpkg archive) is loaded the same way datumhue run would; omit it for an empty service app. Meta-commands start with : (:quit, :help). A terminal gets line editing and history; --no-tty reads stdin line-by-line for piped input
Arguments:
[<PATH>]— Path to a.luascript, package directory, or.dhpkgarchive to load before the prompt. Omit for an empty service app[<SCRIPT_ARGS>]— Tokens forwarded to the loaded script viadatumhue.args.argv
Options:
[--dir <NAME:PATH>]— Grant a read-only directory capability (NAME:PATH)[--dir-rw <NAME:PATH>]— Grant a read-write directory capability (NAME:PATH)[--file <NAME:PATH>]— Grant a read-only file capability (NAME:PATH)[--file-rw <NAME:PATH>]— Grant a read-write file capability (NAME:PATH)[--remote-dir <NAME:MOUNT>]— Grant a read-only directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT). The script reaches the directory asdatumhue.args.dirs.<name>[--remote-dir-rw <NAME:MOUNT>]— Grant a read-write directory capability backed by a remote mount on a deployment-side filesystem provider (NAME:MOUNT)[--data-mount <NAME:MOUNT>]— Grant a read-only data mount capability (NAME:MOUNT). The script reaches the mount asdatumhue.args.data_mounts.<name>and runs SQL queries viamount:query(sql)[--data-mount-rw <NAME:MOUNT>]— Grant a read-write data mount capability (NAME:MOUNT)[--http-mount <NAME:MOUNT>]— Grant an HTTP mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.http_mounts.<name>and makes requests viamount:get(path)/mount:post(path, opts)etc[--ingress-mount <NAME:MOUNT>]— Grant an ingress mount capability (NAME:MOUNT). The script reaches it asdatumhue.args.ingress_mounts.<name>and subscribes to its channel viamount:subscribe({callback = ...})[--service]— Run the loaded.luascript as a service app. Same meaning asdatumhue run --service[--no-tty]— Read stdin line-by-line instead of using the interactive line editor. Chosen automatically when stdin is not a terminal (piped from another process or a file)[--watch]— Watch the loaded source and reload the app when files change; the prompt re-attaches to the reloaded app. Requires a path
datumhue docs
Generate the documentation this build exposes — the author's guide, the full datumhue.* reference (every function, handle method, field, and operator), the theme-file format, and the CLI reference. --format selects the output; --open builds the searchable HTML page and opens it in your browser. Prints to stdout by default; use --out to write a file. The output reflects the running build, so a client without networking omits the networked surface
Options:
[--format <FORMAT>]— Output format (default:markdown)[--out <PATH>]— Write the output to this path instead of stdout[--open]— Build the searchable HTML page and open it in the system browser. Writes to--outwhen given, otherwise a temp file
Environment
Environment (variables without a flag):
DATUMHUE_CERT_PATH
Extra CA certificates (PEM) trusted when contacting the deployment, alongside the embedded roots.
DATUMHUE_BOOTSTRAP_PACKAGE
Bootstrap package to launch when --bootstrap is not passed.