DatumHue documentation

Platformv0.0.19

App author's guide, the Lua API reference, the theme-file format, and the CLI reference. Press / to search.

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 sections

2D Drawing

Retained vector primitives and paths.

4 sections

Images, Sprites & Tiles

Raster images, drawing pictures, sprites, and tile maps.

8 sections

3D & Scenes

Scene graph, meshes, materials, voxels, and shaders.

23 sections

Data & Charts

Tabular data, chart scales and marks, shared documents.

22 sections

Windows & UI

Window manager, display control, UI elements.

9 sections

Input & Events

Keyboard, mouse, and gamepad input, timers, system events.

9 sections

Physics & Grids

2D physics bodies, joints, and grid algorithms.

8 sections

Math, Color & Noise

Vectors, quaternions, colors, noise fields, and seeded random streams.

15 sections

Audio, Files & Storage

Audio playback, filesystem access, and local storage.

13 sections

Documents

Interactive documents: load, mount, and navigate books.

3 sections

App, Networking & Identity

App lifecycle, packages, HTTP mounts, identity, and commerce.

12 sections

Serialization

Byte payloads and their decoders — text, data, images, scenes, and themes.

2 sections

Assets & Resources

Loadable images, audio, scenes, cubemaps, fonts, and themes.

6 sections

Internationalization

Localized text via Fluent catalogs and the active locale.

3 sections

SQL

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

DisplayAny resolution, 2D and 3D
AudioWaveform synthesis (sine, square, triangle, saw, noise) + sample playback
InputKeyboard, mouse, gamepad (up to 8 pads)
LanguageLua (sandboxed, Lua 5.3/5.4 compatible subset)
NetworkingTopic-based messaging, shared live documents
StoragePer-app persistent key-value store
GridA* pathfinding, Dijkstra distance maps, field of view, Voronoi
Physics2D and 3D rigid bodies, collision detection, sensors
3DPBR materials, HDR, bloom, fog, atmosphere, voxels, particles, glTF models
DataCSV/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:

APIBootstrap / WM appRegular app
fullscreen()System window fullscreenMaximize the root container
request_resolution()System window sizeResize the root container
screen.width / screen.heightSystem window sizeRoot 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:

APIOriginY direction(0,0) is
draw (retained 2D)CenterUpcanvas center
scene (3D)CenterUpscene center
image (raster buffer)Top-leftDowntop-left pixel
physicsMatches the host handle's APIno conversion

Draw primitives place depth in pos.zpos = 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. identity gates the user-data accessors, network gates network-scoped messaging/documents, commerce gates the purchase API, packages gates 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, and packages.list / packages.search aggregate 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.args or a parent's app.spawn options.

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_update handler;
  • 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, has init.lua.
  • libraryrequire-able, has a lib/ tree.
  • asset_pack — data only (themes, books, datasets, fonts, shaders, media). An open-list content_type tag (e.g. "theme", "dataset") refines it for discovery and validation. It is valid on an asset_pack and on an app whose substance is content (an interactive "book"); only a library rejects 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 the datumhue table (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 on kind "app".
  • sealed #true — the app opts out of external introspection. A consumer that loads a sealed package sees its manifest metadata but pkg:dir() returns nil; the running app still reaches its own files. Sealing is a trust signal, not encryption — anyone with the bytes can unpack them offline. Only an app may 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 Color values from datumhue.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 bind local 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 == and tostring() — nothing else. They are opaque; don't treat them as numbers.
  • Texture creation vs display. image.new, draw.new, and scene.new only allocate a render target. Call source: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 with prim:update(opts) rather than redrawing.
  • datumhue.image — a raster Image, top-left origin and Y-down. One type covers both a framebuffer you draw into and loaded/encodable pixel data: draw by recording a picture() and replaying it with image:apply (the update is atomic; reuse one picture with picture:reset() then picture:clear()), read pixels with image:get, and persist with image:encode_png. Slice an image into a cell grid with image:atlas to 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 (a rotation field plus a look_at method).

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:

FormMeaning
100100 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:

KnobRequested byAffects
request_resolutionauthor, app startphysical window size
request_design_resolutionauthor, app startthe canvas your UI was authored against
request_stretch_modeauthor, app starthow the design canvas fits the window
request_zoomend user, runtimea 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 in datumhue --help (desktop) or the browser launcher's URL params.
  • From a file widgetui.root:open_button{mode=…, on_pick=…} opens a file / directory dialog when the user clicks it and delivers the chosen File / File[] / Dir to on_pick; save_button{source=…, on_save=…} writes bytes to a chosen file and hands back a read-only File. 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 shapeLua representation
name "foo"name = "foo"
port 8080port = 8080
enabled trueenabled = 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: backgroundgridarealinebarspoints → 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.eventsevents.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; both string.sub(s, 1, 3) and s:sub(1, 3) work.
  • Not available: os, io, loadstring, dofile. There is no filesystem or system access except through capability handles.
  • load holds the standard Lua 5.4 contract (the compiled closure, or nil, errmsg) for string chunks, but is text-only: binary chunks are rejected whatever mode is requested, and reader-function chunks are not accepted.
  • require is 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 __gc metamethods.

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 the datumhue.* API, rendered from the exact surface your client version ships. Regenerate with datumhue pkg refresh after a client upgrade.
  • .luarc.json — LuaLS workspace config wiring in datumhue.d.lua, lib/, and resolved deps/, and declaring datumhue a 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

--dap` serves the suite to a debugger instead of running it, with breakpoints on your real source files.

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(), and scene.new() only create a render target. Nothing is visible until you call source:mount().
  • Depth lives in pos.z. Draw primitives created without an explicit z — a vec2 pos, or none — stack in creation order, later on top. Pass a vec3 to pin the depth yourself: an explicit z is authoritative, and larger z renders in front.
  • 2D physics needs a shared z. All 2D bodies that should collide must share the same z; the engine overwrites the z component each frame, so use z only for visual layering of non-physics elements.
  • Physics owns position. Don't prim:update({pos = …}) a body — the engine overwrites it each frame. Assign the prim.pos / prim.velocity properties instead; they update the physics body along with the visual. color and scale on prim:update() are safe.
  • Screenshots are suspending. screen.screenshot() pauses the caller until the capture lands; the returned Image is 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.kdl manifest plus a strict lib/ + 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: 0BSD or MIT-0 for any package, CC0-1.0 for data-only asset packs, or LicenseRef-DatumHue-Freeware for 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

#fndatumhue.uuid() → string

Generate a fresh random UUID in canonical hyphenated form.

#fndatumhue.stat(key: StatKey) → number | integer

Query a performance counter by key. A counter that has not produced a sample yet reports 0. An unknown key raises.

#fndatumhue.on_update(callback: fun(dt: number) | nil)

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.

#fndatumhue.on_terminate(callback: fun() | nil)

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.

#fndatumhue.ready(handles: any[])
Suspends until the result arrives

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.

#fndatumhue.bytes(s: string) → Bytes

Lift a Lua string to opaque Bytes.

#fndatumhue.math.vec2(x: number, y: number) → Vec2

Construct a 2D vector: vec2() is (0,0), vec2(s) splats, vec2(x, y) is component-wise.

Accepted forms
  • datumhue.math.vec2() → Vec2
  • datumhue.math.vec2(scalar: number) → Vec2
#fndatumhue.math.vec3(x: number, y: number, z: number) → Vec3

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.

Accepted forms
  • datumhue.math.vec3() → Vec3
  • datumhue.math.vec3(scalar: number) → Vec3
  • datumhue.math.vec3(x: number, y: number) → Vec3
#fndatumhue.math.ray(origin: Vec3, direction: Vec3) → Ray

Construct a ray from an origin and a direction (normalized on construction; raises if the direction is zero).

#fndatumhue.color(r: number, g: number, b: number, [a]: number) → Color

Construct a color from a hex string (#RRGGBB/#RRGGBBAA) or r, g, b[, a] numbers (0..1).

Accepted forms
  • datumhue.color(hex: string) → Color

Root fields

#fielddatumhue.argsAppArgs

Filesystem and launch capabilities granted to this app at spawn.

#fielddatumhue.packagePackage | nil

The running app's own loaded package bundle — its manifest metadata (.name, :version(), :kind()) and a read-only :dir() over its files. nil when the app was launched from inline code rather than a package.

#namespacedatumhue.time — Timers

Monotonic time measurement and scheduled callbacks.

#fndatumhue.time.now() → number

Monotonic seconds elapsed since the app started.

#fndatumhue.time.unix_micros() → integer

Wall-clock microseconds since the Unix epoch.

#fndatumhue.time.calendar(at_micros: integer) → Calendar

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.

#fndatumhue.time.from_calendar(opts: time.FromCalendarOptions) → integer

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

#fndatumhue.time.day_index(micros: integer) → integer

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.

#fndatumhue.time.after(secs: number, callback: fun(dt: number)) → Timer

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.

#fndatumhue.time.every(secs: number, callback: fun(dt: number)) → Timer

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.

#fndatumhue.time.tween(opts: time.TweenOptions) → Timer

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

#fndatumhue.time.sleep(secs: number)
Suspends until the result arrives

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.

#fndatumhue.time.wait_frames(frames: integer)
Suspends until the result arrives

Pause the calling code for frames frame ticks, then continue. 1 resumes on the next frame; 0 returns at once.

Methods on the returned Timer handle: unsubscribe, pause, resume, elapsed, remaining

#namespacedatumhue.noise — Scalar Noise Fields

Perlin / simplex / cellular / fractal noise samplers.

#fndatumhue.noise.perlin([opts]: noise.BaseOptions) → NoiseSampler

Create a Perlin-noise sampler. Options: seed (integer), frequency (number).

#fndatumhue.noise.simplex([opts]: noise.BaseOptions) → NoiseSampler

Create a simplex-noise sampler. Options: seed (integer), frequency (number).

#fndatumhue.noise.simplex_smooth([opts]: noise.BaseOptions) → NoiseSampler

Create a smooth simplex-noise sampler. Options: seed (integer), frequency (number).

#fndatumhue.noise.value([opts]: noise.BaseOptions) → NoiseSampler

Create a value-noise sampler. Options: seed (integer), frequency (number).

#fndatumhue.noise.value_cubic([opts]: noise.BaseOptions) → NoiseSampler

Create a cubic value-noise sampler. Options: seed (integer), frequency (number).

#fndatumhue.noise.cellular([opts]: noise.CellularOptions) → NoiseSampler

Create a cellular (Worley) noise sampler. Options: seed, frequency, distance, return_type, jitter.

#fndatumhue.noise.fbm([opts]: noise.FbmOptions) → NoiseSampler

Create a fractal (fBm / ridged / ping-pong) sampler.

Methods on the returned NoiseSampler handle: at

#namespacedatumhue.audio — Audio

Procedural synthesis, SFX, music, sample playback, and named buses.

UI apps only — nil for service apps
Properties
  • .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.
#fndatumhue.audio.synth(opts: audio.SynthOptions) → Audio

Synthesize and play a tone.

#fndatumhue.audio.sfx(notes: audio.SfxNote[], [opts]: audio.SfxPlayOptions) → Audio

Play a sequence of synthesized notes (array of note tables).

#fndatumhue.audio.music(opts: audio.MusicOptions) → Audio

Play a pattern-sequenced track.

#fndatumhue.audio.play(asset: AudioAsset, [opts]: audio.PlayOptions) → Audio

Play a loaded audio asset.

#fndatumhue.audio.bus(name: string) → AudioBus

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.

Methods on the returned Audio handle: stop, pause, resume, pitch_to
Methods on the returned AudioBus handle: volume_to

#namespacedatumhue.font — Fonts

The bundled brand face, the app's default face, and per-script glyph fallback. Load custom faces with bytes:font().

UI apps only — nil for service apps
Properties
  • .default : Font read/write — The app's default font face: every text surface that doesn't pin its own font uses it. Assigning re-applies to the app's text; reading returns the resolved face (the brand font when unset).
#fndatumhue.font.builtin() → Font

A handle to the bundled brand font face. Use it to reference or reset the app default: datumhue.font.default = datumhue.font.builtin().

#fndatumhue.font.fallback(script: FontScript, font: Font)

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.

Methods on the returned Font handle: ready, metrics

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

Properties
  • .locale : Ftl read/write — The app's active localization catalog. Assign an Ftl (from bytes: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).
#fndatumhue.i18n.t(key: string, [vars]: table) → Message

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.

#fndatumhue.i18n.builtin() → Ftl

The embedded built-in catalog (the engine's default English chrome). Reading datumhue.i18n.locale returns this until the app sets its own.

Methods on the returned Ftl handle: locale
Methods on the returned Message handle: get

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

UI apps only — nil for service apps
#fndatumhue.input.on_text(callback: function) → Subscription

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.

#fndatumhue.input.on_key(callback: function) → Subscription

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.

#fndatumhue.input.bind_action(name: string, options: input.ActionBindOptions)

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.

#fndatumhue.input.unbind_action(name: string)

Remove a named action binding (idempotent).

#fndatumhue.input.is_action_down(name: string) → boolean

Whether any input bound to the named action is currently held.

#fndatumhue.input.is_action_pressed(name: string) → boolean

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.

#fndatumhue.input.is_action_released(name: string) → boolean

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.

#fndatumhue.input.action_vector(negative_x: string, positive_x: string, negative_y: string, positive_y: string) → (number, number)

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.

#fndatumhue.input.last_source() → input.InputSource

Which device spoke last. Lets prompts and control glyphs follow the device the player is actually using, without polling every button.

#fndatumhue.input.is_key_down(key: input.Key) → boolean

Whether a key is currently held.

#fndatumhue.input.is_key_pressed(key: input.Key) → boolean

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.

#fndatumhue.input.is_key_released(key: input.Key) → boolean

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.

#fndatumhue.input.mouse_position() → Vec2 | nil

Cursor position in window pixels, or nil.

#fndatumhue.input.app_mouse_position() → Vec2 | nil

Cursor position relative to the app's root container, or nil.

#fndatumhue.input.mouse_delta() → Vec2

Mouse movement since last frame.

#fndatumhue.input.is_mouse_down(button: input.MouseButton) → boolean

Whether a mouse button is held.

#fndatumhue.input.is_mouse_pressed(button: input.MouseButton) → boolean

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.

#fndatumhue.input.is_mouse_released(button: input.MouseButton) → boolean

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.

#fndatumhue.input.scroll_delta() → Vec2

Scroll-wheel movement since last frame.

#fndatumhue.input.touches() → input.Touch[]

Array of the screen touches currently pressed, ordered by id. Empty when nothing touches the screen.

#fndatumhue.input.is_touch_down(id: integer) → boolean

Whether the touch with this id is currently pressed.

#fndatumhue.input.is_touch_pressed(id: integer) → boolean

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.

#fndatumhue.input.is_touch_released(id: integer) → boolean

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.

#fndatumhue.input.app_touch_position(id: integer) → Vec2 | nil

Position of the touch with this id relative to the app's root container, or nil when the touch isn't pressed.

#fndatumhue.input.gamepads() → integer[]

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.

#fndatumhue.input.is_button_down(pad_id: integer, button: input.GamepadButton) → boolean

Whether a gamepad button is held.

#fndatumhue.input.is_button_pressed(pad_id: integer, button: input.GamepadButton) → boolean

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.

#fndatumhue.input.is_button_released(pad_id: integer, button: input.GamepadButton) → boolean

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.

#fndatumhue.input.stick(pad_id: integer, side: input.StickSide) → Vec2

Gamepad stick vector.

#fndatumhue.input.dpad(pad_id: integer) → Vec2

Gamepad d-pad vector.

#fndatumhue.input.trigger(pad_id: integer, side: input.StickSide) → number

Gamepad trigger value 0..1.

#fndatumhue.input.rumble(pad_id: integer, opts: input.RumbleOptions)

Rumble a gamepad's motors. A pad index with no pad connected does nothing.

#fndatumhue.input.stop_rumble(pad_id: integer)

Stop all rumble on a gamepad. A pad index with no pad connected does nothing.

#fndatumhue.input.set_cursor_visible(visible: boolean)

Show or hide the cursor (applies while focused).

#fndatumhue.input.set_cursor_locked(locked: boolean)

Lock or release the cursor (applies while focused).

#fndatumhue.input.set_cursor_icon(icon: input.CursorIcon)

Set the cursor icon by name (applies while focused).

Methods on the returned Subscription handle: unsubscribe

#namespacedatumhue.theme — Theming

Read, apply, and reset an app's theme, and build theme-tracking colors.

UI apps only — nil for service apps
#fndatumhue.theme.default_dark() → Theme

The built-in dark theme.

#fndatumhue.theme.default_light() → Theme

The built-in light theme.

#fndatumhue.theme.current([target]: App) → Theme

The theme currently applied to the app — its own pinned theme, or the one it inherits.

#fndatumhue.theme.pin(theme: Theme, [target]: App)

Apply a theme to the app, pinning it so it no longer follows the inherited theme.

#fndatumhue.theme.unpin([target]: App)

Drop the app's pinned theme so it follows the inherited theme again (its nearest themed ancestor, else the default).

#fndatumhue.theme.token(token: theme.ColorToken) → ThemedColor

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.

#fndatumhue.theme.metric(token: theme.MetricToken) → number

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.

#fndatumhue.events.on(event_name: events.EventName, callback: function) → Subscription

Subscribe callback to a named system event. Returns a subscription; call :unsubscribe() to stop receiving the event.

Accepted forms
Methods on the returned 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.

#fndatumhue.storage.open([label]: string) → Storage

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.

#fndatumhue.storage.open_scoped([label]: string) → Storage

Open the store shared by every package under this app's scope (the publisher's @scope). Label semantics match open.

#fndatumhue.storage.open_shared(uuid: string) → Storage

Open the store named by uuid — any standard spelling, case-insensitive. Sharing is by knowledge: every app passing the same UUID reaches the same store, so treat an unpublished UUID as a secret. Raises when uuid is not a valid UUID.

Methods on the returned Storage handle: set, get, delete, list

#namespacedatumhue.messaging — Inter-App Communication

Topic-based publish/subscribe between apps on this client (local scope) and across clients (network scope).

#fndatumhue.messaging.publish(opts: messaging.PublishOptions)

Publish a message. Options: topic, scope ("local"/"network"), payload. scope defaults to "local"; requires the network capability when scope is "network".

#fndatumhue.messaging.subscribe(opts: messaging.SubscribeOptions) → Subscription

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

#fndatumhue.messaging.presence(topic: string, [opts]: messaging.PresenceOptions) → Presence
Requires the network capability

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

Methods on the returned Subscription handle: unsubscribe
Methods on the returned Presence handle: publish, peers, stop

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

UI apps only — nil for service apps
Properties
  • .keep_awake : boolean read/write — Whether this app asks the host to keep the display awake. While any running app holds true, 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.
#fndatumhue.screen.is_fullscreen() → boolean

Whether the window is in any fullscreen mode.

#fndatumhue.screen.fullscreen(mode: screen.FullscreenMode | boolean, [monitor_index]: integer)

Enter a fullscreen mode, or pass false to exit; optional monitor index.

#fndatumhue.screen.request_resolution(width: number, height: number)

Request a window/container resolution.

#fndatumhue.screen.monitors() → screen.Monitor[]

List of connected monitors.

#fndatumhue.screen.current_monitor() → screen.Monitor | nil

The monitor the window is currently on, or nil.

#fndatumhue.screen.screenshot() → Image
Suspends until the result arrives
Requires the screenshot capability

Capture the whole workstation window.

#fndatumhue.screen.request_stretch_mode(mode: screen.StretchMode)

Request how the design canvas fits the window when their sizes differ.

#fndatumhue.screen.request_design_resolution(width: number, height: number)

Request the logical design resolution (0, 0 to clear).

#fndatumhue.screen.request_zoom(factor: number)

Request a change to the end-user comfort zoom multiplier.

Methods on the returned Image handle: get, apply, cursor, remove, mount, atlas, sprite, ready, encode_png, update, to_cubemap

#namespacedatumhue.wm — Window Manager

Manage descendant apps: terminate, focus, bounds, weight, minimize, cursor override, frame wrapping, and permission grants.

UI apps only — nil for service apps
#fndatumhue.wm.terminate_app(app: App)

Terminate a managed descendant app (silent no-op if already gone).

#fndatumhue.wm.override_cursor_icon([icon]: input.CursorIcon)

Set the caller's cursor override (effective only while it manages the focused app); nil clears.

#fndatumhue.wm.set_app_minimized(options: wm.SetAppMinimizedOptions)

Minimize or restore a managed app.

#fndatumhue.wm.set_app_bounds(options: wm.SetAppBoundsOptions)

Set the position/size of a managed app. Omitted fields are left unchanged.

#fndatumhue.wm.set_app_focused(app: App)

Give input focus to a managed app.

#fndatumhue.wm.set_app_weight(options: wm.SetAppWeightOptions)

Set a managed app's layout weight.

#fndatumhue.wm.wrap_app(app: App, [options]: wm.FrameInsets) → UiElement

Wrap a managed app in a decoration frame; returns the frame's root UiElement.

#fndatumhue.wm.set_frame_insets(app: App, [options]: wm.FrameInsets)

Change the frame insets of an already-wrapped managed app.

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

UI apps only — nil for service apps
Properties
  • .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.
#fndatumhue.physics.world() → PhysicsWorld

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.

#fndatumhue.physics.on_step(callback: fun(dt: number) | nil)

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.

#fndatumhue.physics.add_joint(body1: DrawPrimitive | SceneNode, body2: DrawPrimitive | SceneNode, options: physics.JointOptions) → Joint

Create a physics joint (fixed / revolute / prismatic) between two bodies.

#fndatumhue.physics.raycast(ray: Ray, [options]: physics.RaycastOptions) → physics.RayHit | nil

Cast a ray and return the nearest body hit, or nil.

#fndatumhue.physics.raycast_all(ray: Ray, [options]: physics.RaycastAllOptions) → physics.RayHit[]

Cast a ray and return every body along it, nearest first.

#fndatumhue.physics.point_query(point: Vec2 | Vec3, [options]: physics.PointQueryOptions) → (DrawPrimitive | SceneNode)[]

Return every body whose collider overlaps the given world-space point.

#fndatumhue.physics.shapecast(ray: Ray, options: physics.ShapecastOptions) → physics.RayHit | nil

Sweep a 3D collider shape along the ray and return the nearest body hit, or nil.

Methods on the returned PhysicsWorld handle: raycast, raycast_all, point_query, shapecast, remove
Methods on the returned Joint handle: remove

#namespacedatumhue.grid — Grid Algorithms

2D integer grids with pathfinding, FOV, flood-fill, cellular automata, and procedural fills.

#fndatumhue.grid.new(width: integer, height: integer) → Grid

Create a zeroed width x height grid (each dimension 1..=4096).

#fndatumhue.grid.light_field(width: integer, height: integer) → LightField

Create a zeroed width x height light field (each dimension 1..=4096).

#fndatumhue.grid.voronoi(width: integer, height: integer, num_cells: integer, [opts]: grid.VoronoiOptions) → grid.VoronoiCell[]

Generate Voronoi hives.

#fndatumhue.grid.line(x1: integer, y1: integer, x2: integer, y2: integer) → grid.Cell[]

The rasterized cells of a straight line from (x1,y1) to (x2,y2).

#fndatumhue.grid.distance(x1: integer, y1: integer, x2: integer, y2: integer, [opts]: grid.DistanceOptions) → number

Distance between two cells.

Methods on the returned LightField handle: pour, get, clear

#namespacedatumhue.random — Random Streams

Deterministic seeded random streams, for content that must replay identically from a shared seed.

#fndatumhue.random.new(seed: integer, [stream]: string) → Rng

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.

Methods on the returned Rng handle: next, int, chance, pick, pick_weighted, shuffle, fork, shuffled, sample, bag

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

UI apps only — nil for service apps
Properties
  • .active : boolean read-only — Whether a line or ask is on display or queued. Apps typically suppress their movement input while true.
#fndatumhue.dialogue.say(text: string, [speaker]: string)

Queue a plain line.

#fndatumhue.dialogue.push(entry: dialogue.Entry)

Queue a line whose on_done fires when the player advances past it.

#fndatumhue.dialogue.ask(text: string, choices: dialogue.Choice[], on_choice: fun(value: any), [speaker]: string)

Queue a choice prompt. on_choice receives the picked choice's value when the player confirms with advance().

#fndatumhue.dialogue.clear()

Drop the queue and whatever is on display; no callbacks fire.

#fndatumhue.dialogue.current() → dialogue.Current | nil

The entry on display (promoting the next queued one when none is), or nil when the queue is idle. Custom renderers draw from this.

#fndatumhue.dialogue.select(delta: integer)

Move an ask entry's selection by delta, wrapping. No effect until the text is revealed, or on plain lines.

#fndatumhue.dialogue.advance()

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

#fndatumhue.dialogue.mark(marks: dialogue.Mark[])

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.

#fndatumhue.dialogue.drive([opts]: dialogue.DriveOptions) → dialogue.DriveEvent | nil

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.

UI apps only — nil for service apps
#fndatumhue.scene.new(opts: scene.SceneNewOptions) → Scene

Create a 3D scene viewport.

#namespacedatumhue.material — Materials

PBR and unlit materials for 3D meshes.

UI apps only — nil for service apps
#fndatumhue.material.standard(opts: material.MaterialStandardOptions) → Material

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.

#fndatumhue.material.unlit(opts: material.MaterialUnlitOptions) → Material

Create an unlit material that ignores scene lighting and shows its color (and texture) at full brightness.

Methods on the returned Material handle: set_source, update

#namespacedatumhue.voxel — Voxels

Editable voxel volumes: palette materials, transform properties, scene-space raycasting, and bulk fills driven by the noise, grid, and image APIs.

UI apps only — nil for service apps
#fndatumhue.voxel.new(scene: Scene, opts: voxel.NewOptions) → Voxel

Create a voxel volume inside scene. Cells hold 0-based palette indices, 0 = air.

#fndatumhue.voxel.world(scene: Scene, opts: voxel.WorldOptions) → VoxelWorld

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.

Methods on the returned VoxelWorld handle: palette, chunk, remove

#namespacedatumhue.particles — Particles

Particle effects: emitters spawn short-lived camera-facing quads with velocity, gravity, and size/color over life.

UI apps only — nil for service apps
#fndatumhue.particles.emitter(scene: Scene, options: particles.EmitterOptions) → Emitter

Create a particle emitter inside scene: camera-facing quads simulated on the CPU and drawn in one batch per emitter. Emission starts immediately.

Methods on the returned Emitter handle: resume, pause, burst, remove

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

UI apps only — nil for service apps
#fndatumhue.shader.new(opts: shader.CreateOptions) → Shader

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.

Methods on the returned Shader handle: update, set_source, set, set_channel, reload, remove, ready

#namespacedatumhue.app — Application Management

Spawn, terminate, and introspect apps in the process tree.

Properties
  • .offline : boolean read-only — True while no deployment connection is up.
#fndatumhue.app.spawn(options: app.SpawnAppOptions) → App

Spawn a child app from inline code, a loaded package, or a resolved package_ref. Returns the child's App handle immediately.

#fndatumhue.app.terminate()

Terminate this app. Cascades to all descendants.

#fndatumhue.app.self() → App

This app's own opaque App handle.

#fndatumhue.app.parent() → App | nil

This app's parent App handle, or nil for the root app.

#fndatumhue.app.bootstrap() → App | nil

The root app's App handle. Returns this app's own handle when called from the root.

#fndatumhue.app.is_focused() → boolean

Whether this app currently has focus. Always false for service apps.

#fndatumhue.app.is_service() → boolean

Whether this app was spawned as a service. Fixed at spawn time and immutable.

#fndatumhue.app.has_permission(name: app.Permission) → boolean

Whether this app currently holds the named capability. An unknown name raises.

#fndatumhue.app.request_permission(name: app.Permission, [opts]: app.RequestPermissionOptions) → boolean
Suspends until the result arrives

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.

#fndatumhue.app.session() → string

The launcher-resolved session identifier. Available to every app in the tree.

#fndatumhue.app.errors() → string[]

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.

Methods on the returned App handle: is_self, is_alive, is_parent, is_ancestor, can_manage

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

Properties
  • .identity : string read-only — This user's durable document identity key — what others pass as to in grants and what appears as meta.author on this user's writes. Stable across restarts.
#fndatumhue.documents.create([opts]: documents.CreateOptions) → Document
Suspends until the result arrives

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

#fndatumhue.documents.open_named(opts: documents.OpenNamedOptions) → Document
Suspends until the result arrives

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.

#fndatumhue.documents.open(grant: DocumentGrant | string, [opts]: documents.OpenOptions) → Document
Suspends until the result arrives

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.

#fndatumhue.documents.communal([opts]: documents.CommunalOptions) → Document
Suspends until the result arrives

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.

#fndatumhue.documents.decode_grant(encoded: string) → DocumentGrant

Parse and verify an encoded grant. Raises when the string is not a grant or its authorization does not verify.

Methods on the returned DocumentGrant handle: delegate, encode

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

#fndatumhue.bytes.json(value: any) → Bytes

JSON-encode value and return the resulting bytes.

#fndatumhue.bytes.kdl(value: any) → Bytes

KDL-encode value (must be a table) and return the resulting bytes.

#fndatumhue.bytes.msgpack(value: any) → Bytes

MessagePack-encode value and return the resulting bytes.

Methods on the returned Bytes handle: ready, size, text, json, kdl, msgpack, csv, parquet, shader, book, image, cubemap, audio, font, scene, theme, ftl

#namespacedatumhue.math — Math

Scalar math helpers, plus the vec2 and vec3 constructors.

#fndatumhue.math.lerp(a: number, b: number, t: number) → number

Linear interpolation from a to b by t (clamped 0..1).

#fndatumhue.math.clamp(v: number, lo: number, hi: number) → number

Clamp v to the range [lo, hi].

#fndatumhue.math.remap(v: number, in_lo: number, in_hi: number, out_lo: number, out_hi: number) → number

Remap v from [in_lo, in_hi] to [out_lo, out_hi]. A zero-width input range maps to out_lo.

#fndatumhue.math.smoothstep(edge0: number, edge1: number, x: number) → number

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.

Properties
  • .ZERO : Vec2 read-only — The zero vector (0, 0).
  • .ONE : Vec2 read-only(1, 1).
  • .X : Vec2 read-only — The +X axis (1, 0).
  • .Y : Vec2 read-only — The +Y axis (0, 1).
  • .NEG_X : Vec2 read-only — The -X axis (-1, 0).
  • .NEG_Y : Vec2 read-only — The -Y axis (0, -1).
#fndatumhue.math.vec2.from_angle(radians: number) → Vec2

Unit vector pointing at radians from the +X axis.

#fndatumhue.math.vec2.from_array(a: number[]) → Vec2

Vec2 from a {x, y} array (the inverse of vec2:to_array).

#namespacedatumhue.math.vec3 — Vec3 Constructors

Construct 3D vectors.

Properties
  • .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).
#fndatumhue.math.vec3.from_array(a: number[]) → Vec3

Vec3 from an {x, y, z} array (the inverse of vec3:to_array).

#namespacedatumhue.math.quat — Quaternions

Construct rotation quaternions (angles in radians).

#fndatumhue.math.quat.identity() → Quat

The identity rotation (no rotation).

#fndatumhue.math.quat.from_euler(x: number, y: number, z: number) → Quat

Rotation from XYZ Euler angles (radians).

#fndatumhue.math.quat.from_axis_angle(axis: Vec3, angle: number) → Quat

Rotation of angle radians around axis (normalized). Raises if axis is zero-length / non-finite.

#fndatumhue.math.quat.from_rotation_x(angle: number) → Quat

Rotation of angle radians around the X axis.

#fndatumhue.math.quat.from_rotation_y(angle: number) → Quat

Rotation of angle radians around the Y axis.

#fndatumhue.math.quat.from_rotation_z(angle: number) → Quat

Rotation of angle radians around the Z axis.

#fndatumhue.math.quat.from_rotation_arc(from: Vec3, to: Vec3) → Quat

Minimal rotation taking unit vector from to unit to. Raises if either is zero-length / non-finite.

#fndatumhue.math.quat.from_scaled_axis(v: Vec3) → Quat

Rotation about v's direction by |v| radians (the scaled-axis form). Zero v yields the identity rotation.

#fndatumhue.math.quat.from_array(a: number[]) → Quat

Quat from a raw {x, y, z, w} array (not re-normalized; the inverse of quat:to_array).

#namespacedatumhue.color — Colors

Construct sRGB colors. Call datumhue.color(...) with a hex string or r,g,b[,a] numbers, or use the named constructors.

#fndatumhue.color.rgb(r: number, g: number, b: number) → Color

Color from sRGB r, g, b (0..1).

#fndatumhue.color.rgba(r: number, g: number, b: number, a: number) → Color

Color from sRGB r, g, b, a (0..1).

#fndatumhue.color.hex(s: string) → Color

Color from a hex string (#RRGGBB or #RRGGBBAA).

#fndatumhue.color.hsl(h: number, s: number, l: number) → Color

Color from hue (degrees — the CSS convention; hue is the API's one angle not in radians), saturation, lightness.

#fndatumhue.color.oklab(l: number, a: number, b: number) → Color

Color from Oklab lightness, a, b (perceptual space).

#fndatumhue.color.oklch(l: number, c: number, h: number) → Color

Color from Oklch lightness, chroma, hue (degrees — the CSS convention, as in color.hsl; perceptual space).

#fndatumhue.color.from_array(a: number[]) → Color

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.

UI apps only — nil for service apps
#fndatumhue.image.new(options: image.NewOptions) → Image

Create a blank drawable image. Options: {width, height}. Display via image:mount().

#fndatumhue.image.picture() → Picture

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.

#fndatumhue.image.font() → Atlas

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

Methods on the returned Image handle: get, apply, cursor, remove, mount, atlas, sprite, ready, encode_png, update, to_cubemap
Methods on the returned Atlas handle: sprite, clips

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

UI apps only — nil for service apps
#fndatumhue.draw.new(opts: draw.NewOptions) → DrawCanvas

Create a draw canvas (render target). Options: width, height, background (Color that fills before each frame; omit for transparent), pixel_perfect (default false).

#fndatumhue.draw.text_span(opts: draw.TextSpanOptions) → DrawPrimitive

Create a detached text span. Attach via the spans array in canvas:text() or prim:update(). Options: text, color (Color), font_size.

#fndatumhue.draw.measure_text(text: string, [options]: draw.MeasureTextOptions) → draw.TextSize

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.

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

#fndatumhue.chart.scale.linear(options: chart.LinearScaleOptions) → Scale

Construct a linear numeric scale.

#fndatumhue.chart.scale.log(options: chart.LogScaleOptions) → Scale

Construct a log scale (same numeric-scale fields as linear).

#fndatumhue.chart.scale.band(options: chart.BandScaleOptions) → Scale

Construct a categorical (band) scale.

#fndatumhue.chart.scale.time(options: chart.TimeScaleOptions) → Scale

Construct a time scale. Domain values are f64 epoch-milliseconds.

#fndatumhue.chart.scale.color(options: chart.ColorScaleOptions) → ColorScale

Construct a numeric → color ramp.

#fndatumhue.chart.scale.color_category(options: chart.ColorCategoryOptions) → ColorScale

Construct a discrete category → color map.

Methods on the returned Scale handle: map, invert, fit, reset, bandwidth, index_of, animate, on_change, remove
Methods on the returned ColorScale handle: map, remove

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

UI apps only — nil for service apps
Properties
  • .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{...}.

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

#fndatumhue.debug.input.key(key: input.Key, down: boolean)

Set a key's state as if pressed or released. The key stays held until released.

#fndatumhue.debug.input.tap(key: input.Key)

Press a key now and release it next frame: one clean press-release to every consumer.

#fndatumhue.debug.input.cursor(x: number, y: number)

Move the pointer to a window position in logical pixels (the frame input.mouse_position reads back).

#fndatumhue.debug.input.click([button]: input.MouseButton)

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.

#fndatumhue.debug.input.touch(id: integer, x: number, y: number, down: boolean)

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.

#fndatumhue.identity.sign_in(opts: identity.SignInOptions)

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.

#fndatumhue.identity.sign_out()

Sign out the current identity. Outcome arrives via datumhue.events.

#fndatumhue.identity.is_signed_in() → boolean

Whether an identity is currently signed in.

#fndatumhue.identity.sub() → string | nil
Requires the identity capability

Signed-in subject id, or nil.

#fndatumhue.identity.issuer() → string | nil
Requires the identity capability

Issuer of the current identity, or nil.

#fndatumhue.identity.email() → string | nil
Requires the identity capability

Email claim of the current identity, or nil.

#fndatumhue.identity.name() → string | nil
Requires the identity capability

Name claim of the current identity, or nil.

#fndatumhue.identity.claims() → table | nil
Requires the identity capability

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

#fndatumhue.packages.list([opts]: packages.ListOptions) → PackageRef[]

Array of PackageRef userdata for every visible catalog entry.

#fndatumhue.packages.search([opts]: packages.SearchOptions) → PackageRef[]

Array of PackageRef userdata matching a text / tag filter.

#fndatumhue.packages.info(name: string, [opts]: packages.InfoOptions) → PackageRef

Look up a single entry by exact @scope/name; raises when no entry matches.

#fndatumhue.packages.versions(name: string, [opts]: packages.InfoOptions) → string[]

Every published version of a @scope/name, newest first; empty when the name is unknown to the catalog.

#fndatumhue.packages.installed([opts]: packages.InstalledOptions) → PackageRef[]
Requires the packages capability

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

#fndatumhue.packages.registries() → packages.RegistryInfo[]

One row per connected package registry, sorted by namespace. Empty while no registry has been reached (e.g. offline).

#fndatumhue.packages.on_change(callback: fun(change: packages.ChangeEvent)) → Subscription

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.

#fndatumhue.packages.on_install_change(callback: fun(change: packages.InstallChangeEvent)) → Subscription
Requires the packages capability

Register a callback fired whenever the installed-package library changes. Returns a subscription; call :unsubscribe() to stop receiving changes.

#fndatumhue.packages.on_registry_change(callback: fun(change: packages.RegistryInfo)) → Subscription

Register a callback fired whenever a connected registry's reachability flips (see registries). Returns a subscription; call :unsubscribe() to stop receiving changes.

Methods on the returned Subscription handle: unsubscribe

#namespacedatumhue.commerce — Commerce

Buyer-only paid-package ownership. Requires the commerce capability. Ownership is per-name and perpetual; entitlements verify offline.

#fndatumhue.commerce.check_purchase(package: PackageRef) → boolean
Suspends until the result arrives
Requires the commerce capability

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

#fndatumhue.commerce.owned() → Entitlement[]
Suspends until the result arrives
Requires the commerce capability

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

#fndatumhue.commerce.purchase(package: PackageRef) → Entitlement
Suspends until the result arrives
Requires the commerce capability

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

#methodNoiseSampler:at(x: number, y: number, [z]: number) → number

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.

Fields
  • .position : number | nil read-only — Current playback position in seconds, or nil if not playing.
  • .playing : boolean read-onlytrue while the instance is actively producing sound; false once 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; nil once the instance is gone.
#methodAudio:stop()

Stop playback and release the instance.

#methodAudio:pause()

Pause playback (resume with :resume()).

#methodAudio:resume()

Resume a paused instance.

#methodAudio:pitch_to(pitch: number, seconds: number)

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.

Fields
  • .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.
#methodAudioBus:volume_to(volume: number, seconds: number)

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.

#methodStorage:set(key: string, value: Bytes) → Op

Write value (a Bytes handle) under key. The write starts immediately; :ready() observes completion or failure.

#methodStorage:get(key: string) → BytesFetch

Look up key. The result's value materializes as the stored bytes, or nil when the key is absent.

#methodStorage:delete(key: string) → Op

Delete the entry at key.

#methodStorage:list([prefix]: string) → ListFetch

Keys in ascending order, optionally filtered by prefix.

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

Fields
  • .width : integer read-only — Grid width in cells.
  • .height : integer read-only — Grid height in cells.
#methodGrid:get(x: integer, y: integer) → integer | nil

Cell value at (x, y), or nil when out of bounds.

#methodGrid:set(x: integer, y: integer, value: integer)

Set cell (x, y) to value; no-op when out of bounds.

#methodGrid:fill(value: integer)

Set every cell to value.

#methodGrid:fill_rect(x: integer, y: integer, w: integer, h: integer, value: integer)

Fill a rectangle with value; no-op when w or h is non-positive.

#methodGrid:find_path(x1: integer, y1: integer, x2: integer, y2: integer, opts: grid.FindPathOptions) → grid.Cell[] | nil

A* path from (x1,y1) to (x2,y2), or nil if unreachable.

#methodGrid:agent(opts: grid.AgentOptions) → PathAgent

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

#methodGrid:slide(x: number, y: number, dx: number, dy: number, w: number, h: number, opts: grid.SlideOptions) → (number, number)

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.

#methodGrid:dijkstra(opts: grid.DijkstraOptions) → Grid

A new Grid of distance scores from weighted sources (-1 unreachable).

#methodGrid:field_of_view(x: integer, y: integer, opts: grid.FieldOfViewOptions) → grid.Cell[]

Visible cells from (x,y).

#methodGrid:flood_fill(x: integer, y: integer, opts: grid.FloodFillOptions) → grid.Cell[]

8-connected flood fill from (x,y).

#methodGrid:count_neighbors(x: integer, y: integer, opts: grid.CountNeighborsOptions) → integer

Count of the 8 neighbours whose value is in match.

#methodGrid:automata_step(opts: grid.AutomataStepOptions)

Advance one cellular-automata generation in place.

#methodGrid:fill_noise(sampler: NoiseSampler, [opts]: grid.FillNoiseOptions)

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.

Fields
  • .width : integer read-only — Field width in cells.
  • .height : integer read-only — Field height in cells.
#methodLightField:pour(x: number, y: number, strength: number, range: number)

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.

#methodLightField:get(x: integer, y: integer) → number

The brightest pour reaching cell (x, y); 0 where nothing reaches or out of bounds.

#methodLightField:clear()

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.

Fields
  • .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.
#methodPathAgent:set_target(grid: Grid, x: integer, y: integer)

Path toward cell (x, y) on the grid, repathing immediately (and afterward on the agent's repath cadence, when one was configured).

#methodPathAgent:advance(grid: Grid, dt: number) → grid.AgentStep

Move along the current path for dt seconds and return the position and status. With no target, the agent stays put.

#methodPathAgent:drive(grid: Grid, tx: integer, ty: integer, dt: number) → grid.AgentStep

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.

#methodPathAgent:stop()

Drop the target and path; the agent stays where it is.

#methodPathAgent:teleport(x: number, y: number)

Place the agent at (x, y) and drop the path; the target, when set, repaths on the next advance.

#methodPathAgent:waypoint() → grid.AgentWaypoint | nil

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.

#methodDocCollection:add(value: any) → string
Suspends until the result arrives

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.

#methodDocCollection:ack(id: string)

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.

#methodDocCollection:count() → integer

Distinct entries observed so far -- including entries past the collection's max, which count here without reaching on_add.

#methodDocCollection:unsubscribe()

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.

Fields
  • .value : integer read-only — The reconciled count.
#methodDocCounter:increment()
Suspends until the result arrives

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.

#methodDocCounter:on_change([callback]: fun(value: integer))

Set, replace, or clear (pass nil) the change callback; fired with the new value on every counted increment, yours included.

#methodDocCounter:unsubscribe()

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.

#methodPresence:publish(payload: any)

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.

#methodPresence:peers() → messaging.Peer[]

The peers seen within the ttl, ordered by id. The caller's own handle is never listed.

#methodPresence:stop()

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.

#methodRng:next() → number

The next number in the stream, in [0, 1).

#methodRng:int(lo: integer, hi: integer) → integer

The next integer in the stream, in [lo, hi] inclusive. Raises when lo > hi.

#methodRng:chance(p: number) → boolean

True with probability p (one draw). p at or below 0 is never true; at or above 1, always.

#methodRng:pick(list: any[]) → any

One element of the list (one draw). Raises when the list is empty.

#methodRng:pick_weighted(list: any[], weights: number[]) → any

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.

#methodRng:shuffle(list: any[]) → any[]

Shuffle the list in place (Fisher-Yates, one draw per element past the first) and return the same table.

#methodRng:fork() → Rng

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.

#methodRng:shuffled(list: any[]) → any[]

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.

#methodRng:sample(list: any[], n: integer) → any[]

n distinct elements drawn without replacement (exactly n draws); the list itself is untouched. Raises when n is negative or exceeds the list length.

#methodRng:bag(n: integer) → Bag

A shuffle-bag over positions 1 to n: draw deals each position exactly once per lap and reshuffles between laps. The bag forks its own stream at creation (three draws), so its laps never move this one. Raises when n is below 1.

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

#methodBag:draw() → integer

The next position of the current lap, starting a fresh shuffled lap when the last one is spent.

#methodBag:left() → integer

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.

Fields
  • .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.
#methodPermissionRequest:grant()

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.

#methodPermissionRequest:deny()

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.

Fields
  • .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.
#methodScene:cube(opts: scene.MeshOptions) → SceneNode

Spawn a cube mesh. Options: pos, rotation, scale, color, material.

#methodScene:sphere(opts: scene.MeshOptions) → SceneNode

Spawn a sphere mesh. Options: pos, rotation, scale, color, material.

#methodScene:plane(opts: scene.PlaneOptions) → SceneNode

Spawn a plane mesh. Options: pos, rotation, scale, color, material, subdivisions.

#methodScene:cylinder(opts: scene.MeshOptions) → SceneNode

Spawn a cylinder mesh. Options: pos, rotation, scale, color, material.

#methodScene:capsule(opts: scene.MeshOptions) → SceneNode

Spawn a capsule mesh. Options: pos, rotation, scale, color, material.

#methodScene:torus(opts: scene.MeshOptions) → SceneNode

Spawn a torus mesh. Options: pos, rotation, scale, color, material.

#methodScene:cone(opts: scene.MeshOptions) → SceneNode

Spawn a cone mesh. Options: pos, rotation, scale, color, material.

#methodScene:set_skybox([cubemap]: CubemapAsset)

Set the scene's skybox to a cubemap (from bytes:cubemap() or image_asset:to_cubemap()), or nil to remove it.

#methodScene:set_environment([options]: scene.EnvironmentOptions)

Set image-based environment lighting from prefiltered cubemaps, or nil to remove it. Requires diffuse and specular cubemaps; raises if either is missing.

#methodScene:point_light(opts: scene.PointLightOptions) → SceneNode

Spawn a point light. Options: pos, color, intensity, range, shadows.

#methodScene:directional_light(opts: scene.DirectionalLightOptions) → SceneNode

Spawn a directional light. Options: direction, color, intensity, shadows.

#methodScene:spot_light(opts: scene.SpotLightOptions) → SceneNode

Spawn a spot light. Options: pos, direction, color, intensity, range, shadows, inner_angle, outer_angle.

#methodScene:model(opts: scene.ModelOptions) → SceneNode

Add an external glTF / GLB scene.

#methodScene:clear()

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.

#methodScene:remove()

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.

#methodScene:group(nodes: SceneNode[]) → SceneNode

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

#methodScene:sprite(opts: scene.SpriteOptions) → SceneNode

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.

#methodScene:camera_relative_yaw(node: SceneNode) → number

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.

#methodScene:camera_yaw_bucket(node: SceneNode, n: number) → integer

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.

#methodScene:raycast(ray: Ray) → scene.RaycastHit | nil

Cast a ray into the scene. Returns the nearest hit, or nil if the ray missed.

#methodScene:screen_to_ray(x: number, y: number) → Ray | nil

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.

#methodScene:mount([options]: ui.ImageOptions) → UiElement | nil

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.

Fields
  • .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 not none, the engine owns the node's rotation.
  • .size_mode : scene.SpriteSizeMode read/write — Whether size is world units or constant on-screen pixels.
  • .size : Vec2 read/write — Quad extent (units per size_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 the cutout mode (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.
#methodSceneNode:update(opts: scene.NodeUpdateOptions)

Update node transform / material / light properties.

#methodSceneNode:remove()

Despawn this node.

#methodSceneNode:animate(opts: scene.AnimateOptions)

Tween the node's transform (position, rotation, scale), color, and opacity over duration seconds with the given easing curve.

#methodSceneNode:play_animation(opts: scene.PlayAnimationOptions)

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.

#methodSceneNode:stop_animation()

Stop all animation playback on the node, freezing it at the current pose.

#methodSceneNode:blend(clips: scene.BlendClip[])

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.

#methodSceneNode:bounds() → scene.MeshBounds | nil

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

#methodSceneNode:mesh() → Mesh

This node's mutable mesh. Only primitive mesh nodes (cube, sphere, plane, ...) qualify; raises for voxel volumes, glTF models, lights, cameras, and groups.

#methodSceneNode:deform(opts: scene.DeformOptions) → Deformer

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.

#methodSceneNode:add_body([options]: physics.BodyOptions)

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.

#methodSceneNode:character_controller([options]: physics.CharacterControllerOptions) → CharacterController

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

#methodSceneNode:apply_impulse(vec: Vec2 | Vec3)

Apply an instantaneous, mass-correct velocity change (Δv = impulse / mass). Accepts vec2 or vec3.

#methodSceneNode:apply_angular_impulse(impulse: number | Vec3)

Apply an instantaneous, inertia-correct spin change. A number for 2D bodies (about Z), a vec3 for 3D.

#methodSceneNode:apply_force(vec: Vec2 | Vec3)

Set the continuous force applied every step until changed. Pass a zero vector to stop. Accepts vec2 or vec3.

#methodSceneNode:apply_torque(torque: number | 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.

#methodSceneNode:lock_rotation(locked: boolean)

Lock or unlock rotation.

#methodSceneNode:set_collision_layers(options: physics.CollisionLayerOptions)

Replace this body's collision filtering at runtime (e.g. switching teams).

#methodSceneNode:set_locked_axes(options: physics.LockedAxesOptions)

Lock or unlock individual translation/rotation axes at runtime. The 2D in-plane constraints are always preserved.

#methodSceneNode:on_collision_start([callback]: fun(other: DrawPrimitive | SceneNode, contact: physics.Contact))

Set, replace, or clear (pass nil) the handler fired when this body starts colliding.

#methodSceneNode:on_collision_end([callback]: fun(other: DrawPrimitive | SceneNode))

Set, replace, or clear (pass nil) the handler fired when this body stops colliding.

#methodSceneNode:remove_body()

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.

Fields
  • .pos : Vec3 read/write — Camera world-space position.
  • .rotation : Quat read/write — Camera orientation.
  • .fov : number read/write — Vertical field of view in radians.
#methodSceneCamera:look_at(target: Vec3, [up]: Vec3)

Aim the camera at a world-space point. up defaults to world Y.

#methodSceneCamera:animate(opts: scene.CameraAnimateOptions)

Tween the camera's position, orientation, and field of view over duration seconds with the given easing curve.

#methodSceneCamera:set_orthographic(height: number)

Switch the camera to an orthographic projection. height is the world-space vertical extent visible; the horizontal extent follows the scene's aspect ratio.

#methodSceneCamera:set_perspective(fov: number)

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.

Fields
  • .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.

Fields
  • .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.

Fields
  • .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.

Fields
  • .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.

Fields
  • .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.

Fields
  • .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.

Fields
  • .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.

Fields
  • .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. The mask mode uses a 0.5 cutoff; set a custom cutoff via material:update.
#methodMaterial:set_source([source]: Image | DrawCanvas | Scene)

Set or clear the base-color texture from a source (pixel / draw canvas / scene).

#methodMaterial:update(opts: material.UpdateOptions)

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

Fields
  • .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.
#methodVoxel:set(x: integer, y: integer, z: integer, material: integer)

Set the material index at a cell.

#methodVoxel:get(x: integer, y: integer, z: integer) → integer

Read the material index at a cell.

#methodVoxel:raycast(ray: Ray) → voxel.RaycastHit | nil

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.

#methodVoxel:fill(x0: integer, y0: integer, z0: integer, x1: integer, y1: integer, z1: integer, material: integer)

Fill an axis-aligned box of cells.

#methodVoxel:palette(index: integer, opts: voxel.PaletteOptions)

Define a palette material: color, render class, and — with an atlas bound — static per-face or animated block textures.

#methodVoxel:atlas(atlas: Atlas)

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.

#methodVoxel:clear()

Reset every cell to air.

#methodVoxel:count([material]: integer) → integer

Count cells holding material, or every non-air cell when omitted.

#methodVoxel:set_material(material: Material | Shader)

Set the material for the volume's solid surfaces (a standard Material or a Shader). Transparent and emissive faces keep their built-in rendering.

#methodVoxel:capture() → integer

Snapshot the current cells as an animation frame; returns the frame's 1-based index for play.

#methodVoxel:play(opts: voxel.PlayOptions)

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.

#methodVoxel:stop()

Stop playback, leaving the currently shown frame's cells in place.

#methodVoxel:drop_frames()

Discard every captured frame (and stop any playback), freeing their memory; the current cells stay.

#methodVoxel:remove()

Despawn the volume and its meshes.

#methodVoxel:fill_noise(opts: voxel.FillNoiseOptions)

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.

#methodVoxel:heightmap(opts: voxel.HeightmapOptions)

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.

#methodVoxel:stamp_grid(opts: voxel.StampGridOptions)

Write a 2D grid into one slice of the volume — dungeon layouts, automata output, or path maps become geometry in one pass.

#methodVoxel:stamp_image(opts: voxel.StampImageOptions)

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.

Fields
  • .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.
#methodVoxelWorld:palette(index: integer, opts: voxel.PaletteOptions)

Define a palette material shared by every chunk: updates the world palette and every loaded chunk; chunks loading later inherit it.

#methodVoxelWorld:chunk(coords: Vec3) → VoxelChunk | nil

The loaded chunk at integer grid coordinates coords, or nil while it isn't loaded.

#methodVoxelWorld:remove()

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.

Fields
  • .coords : Vec3 read-only — The chunk's integer grid coordinates in the world, or nil once unloaded.
  • .voxel : Voxel read-only — The chunk's voxel volume; edit it with the full Voxel surface.
#methodVoxelChunk:read() → Bytes

Snapshot the chunk's cells (run-length encoded).

#methodVoxelChunk:write(data: Bytes)

Restore cells from a read (or on_chunk_unload) snapshot taken at the same chunk size.

#handleEmitter

A particle emitter returned by datumhue.particles.emitter. Configuration scalars are read-write properties; pause/resume gate continuous emission.

Fields
  • .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.
#methodEmitter:resume()

Resume continuous emission.

#methodEmitter:pause()

Pause continuous emission; live particles finish their lives.

#methodEmitter:burst(n: integer)

Spawn n particles at once (bounded by max_particles).

#methodEmitter:remove()

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.

#methodSpriteClips:bind(target: DrawPrimitive | SceneNode) → Animator

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.

#methodSpriteClips:names() → string[]

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.

Fields
  • .clip : string | nil read-only — The currently playing clip name, or nil before the first play.
  • .frame : integer read-only — Current 1-based frame position within the active clip (position 1 = its first frame), or 0 before the first play.
  • .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).
#methodAnimator:play(name: string, [opts]: scene.PlayOpts)

Hard-cut to clip name from its first frame, clearing the queue. Options: {speed?, looping?}. Raises if the clip is unknown.

#methodAnimator:queue(name: string, [opts]: scene.PlayOpts)

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.

#methodAnimator:stop()

Stop playback and clear the queue, leaving the current frame shown.

#methodAnimator:pause()

Freeze the playhead; resume continues from here.

#methodAnimator:resume()

Resume a paused animator without resetting the playhead.

#methodAnimator:seek(frame: number)

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.

#methodAnimator:on_finish([callback]: fun(animator: Animator, clip: string))

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.

#methodAnimator:on_marker([callback]: fun(animator: Animator, marker: string))

Set, replace, or clear (pass nil) the callback fired each time the playhead crosses a named frame marker. Receives the animator and the marker 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.

Fields
  • .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.
#methodMesh:positions() → number[]

Vertex positions as flat x,y,z triplets in node-local space.

#methodMesh:normals() → number[]

Vertex normals as flat x,y,z triplets; empty when the mesh has none.

#methodMesh:uvs() → number[]

Texture coordinates as flat u,v pairs; empty when the mesh has none.

#methodMesh:colors() → number[]

Vertex colors as flat r,g,b,a quads; empty when the mesh has none.

#methodMesh:indices() → integer[]

1-based triangle indices; empty for a non-indexed mesh.

#methodMesh:update(opts: scene.MeshUpdateOptions)

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.

Fields
  • .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.
#methodDeformer:remove()

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.

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodShader:update(opts: shader.UpdateOptions)

Update a preset shader's parameters. Changes propagate to every primitive using this shader. Custom shaders raise — their state changes through set / set_channel.

#methodShader:set_source(source: Image | DrawCanvas | Scene | nil)

Update or clear the shader's texture source. source is a pixel canvas, draw canvas, or scene handle, or nil to clear.

#methodShader:set(name: string, value: number | Vec2 | Vec3 | Color)

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.

#methodShader:set_channel(index: integer, source: Image | DrawCanvas | Scene | nil)

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.

#methodShader:reload(source: Bytes)

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.

#methodShader:remove()

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.

#methodShader:ready() → Shader
Suspends until the result arrives

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.

Fields
  • .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.

Fields
  • .name : string | nil read-only — The name the app was spawned with. Nil once the app is no longer running.
#methodApp:is_self() → boolean

True if the handle refers to the current app (works even on dead handles).

#methodApp:is_alive() → boolean

True if the app referenced by the handle is still running.

#methodApp:is_parent() → boolean

True if the handle is the direct parent of the current app.

#methodApp:is_ancestor() → boolean

True if the handle is any proper ancestor of the current app.

#methodApp:can_manage() → boolean

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.

Fields
  • .name : string read-only — The manifest name.
#methodPackage:version() → string

The manifest version.

#methodPackage:kind() → packages.Kind

The manifest kind.

#methodPackage:content_type() → string | nil

The refinement tag on asset packs, or nil on apps and libraries.

#methodPackage:is_sealed() → boolean

Mirrors the manifest sealed flag.

#methodPackage:dir() → Dir | nil

A read-only directory rooted at the loaded bundle; the same handle across calls. Returns nil for sealed packages loaded from outside; the running app's own package always succeeds.

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

Fields
  • .scope : documents.Scope read-only — Which backend stores the document.
  • .can_write : boolean read-only — Whether this handle may write, or is read-only.
#methodDocument:collection(prefix: string, opts: documents.CollectionOptions) → DocCollection
Suspends until the result arrives

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.

#methodDocument:counter(prefix: string) → DocCounter
Suspends until the result arrives

A grow-only distributed counter over the prefix, reconciled across backfill and the live window so nothing double-counts.

#methodDocument:set(key: string, value: nil | boolean | integer | number | string | table) → Op

Write a key-value pair. Errors when doc.can_write is false. The write starts immediately; :ready() observes completion or failure.

#methodDocument:delete(key: string) → Op

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.

#methodDocument:get(key: string, [opts]: documents.GetOptions) → DocEntry

Read a key. The result's value and meta are both nil when the key isn't present (or was deleted).

#methodDocument:query_prefix(prefix: string, [opts]: documents.QueryOptions) → DocQuery

Query every key under the prefix, newest per key; the result's entries is {[key] = {value, meta}}.

#methodDocument:delete_prefix(prefix: string) → Op

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.

#methodDocument:subscribe(prefix: string, callback: fun(key: string, value: any, meta: documents.Meta)) → Subscription
Suspends until the result arrives

Watch for changes. callback(key, value, meta); value is nil when the key was deleted. Pass "" to match every write.

#methodDocument:grant([opts]: documents.GrantOptions) → DocumentGrant
Suspends until the result arrives

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.

#methodDocument:close()
Suspends until the result arrives

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.

Fields
  • .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.
#methodDocumentGrant:delegate(opts: documents.GrantOptions) → DocumentGrant

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.

#methodDocumentGrant:encode() → string

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.

#methodSubscription:unsubscribe()

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.

#methodTimer:unsubscribe()

Stop the timer and release it. Idempotent.

#methodTimer:pause()

Pause the timer; it stops advancing until resumed. No-op if it already fired.

#methodTimer:resume()

Resume a paused timer. No-op if it already fired.

#methodTimer:elapsed() → number

Seconds elapsed in the current cycle (resets each fire for a repeating timer); 0 once fired/unsubscribed.

#methodTimer:remaining() → number

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.

Fields
  • .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.

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodBytes:ready() → Bytes
Suspends until the result arrives

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.

#methodBytes:size() → integer
Suspends until the result arrives

Byte length.

#methodBytes:text() → string
Suspends until the result arrives

Materialise the bytes as a Lua string. UTF-8 is not validated; bytes are returned verbatim.

#methodBytes:json() → any
Suspends until the result arrives

Parse the bytes as JSON. Raises on parse failure.

#methodBytes:kdl() → any
Suspends until the result arrives

Parse the bytes as KDL. Raises on parse failure or non-UTF-8 input.

#methodBytes:msgpack() → any
Suspends until the result arrives

Parse the bytes as MessagePack. Raises on parse failure.

#methodBytes:csv([opts]: bytes.CsvOptions) → DataHandle
Suspends until the result arrives

Decode the bytes as CSV into a DataHandle. Raises on parse failure.

#methodBytes:parquet() → DataHandle
Suspends until the result arrives

Decode the bytes as Parquet into a DataHandle. Raises on parse failure.

#methodBytes:shader([options]: shader.CompileOptions) → Shader

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.

#methodBytes:book() → Book
Suspends until the result arrives

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.

#methodBytes:image() → Image

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.

#methodBytes:cubemap() → CubemapAsset

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.

#methodBytes:audio() → AudioAsset

Decode the bytes as audio (OGG, MP3, WAV, FLAC). Format is detected at play time, so invalid bytes surface as a play-time error.

#methodBytes:font() → Font
Suspends until the result arrives

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.

#methodBytes:scene() → SceneAsset

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.

#methodBytes:theme() → Theme
Suspends until the result arrives

Decode the bytes as a theme and register it. Returns a Theme handle for the registered theme.

#methodBytes:ftl() → Ftl
Suspends until the result arrives

Parse the bytes as a Fluent (.ftl) localization catalog for one locale (declared by its -datumhue-locale term). Returns an Ftl to set as datumhue.i18n.locale. Raises on a missing/invalid locale term or a Fluent syntax error.

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

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodDataHandle:count() → integer
Suspends until the result arrives

Row count, computed from the source — see len() on in-memory batches.

#methodDataHandle:query(sql: string, [params]: any[]) → DataHandle

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.

#methodDataHandle:rows([opts]: data.RowsOptions) → (function, table, integer)

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.

#methodDataHandle:batches([opts]: data.BatchesOptions) → (function, table, integer)

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.

#methodDataHandle:schema() → Schema
Suspends until the result arrives

Describe the columns, their types, nullability, and metadata.

#methodDataHandle:view(options: data.ViewOptions) → DataView
Suspends until the result arrives

Create a viewport-aware, downsampled projection of this handle.

#methodDataHandle:encode_csv() → Bytes
Suspends until the result arrives

Serialize the handle's contents as CSV, returning a Bytes userdata.

#methodDataHandle:encode_parquet() → Bytes
Suspends until the result arrives

Serialize the handle's contents as Parquet, returning a Bytes userdata.

#methodDataHandle:ready() → DataHandle
Suspends until the result arrives

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.

#methodDataBatch:len() → integer

Row count in this batch.

#methodDataBatch:columns() → string[]

Array of column names (respects projection).

#methodDataBatch:column(name: string) → DataColumn

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.

Fields
  • .name : string read-only — Column name.
#methodDataColumn:get(i: integer) → any

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.

#methodDataColumn:len() → integer

Row count for this column.

#methodDataColumn:dtype() → data.Dtype

The column's data type name.

#handleSchema

Returned by DataHandle:schema(). Lookup by name is O(1); fields and metadata resolve lazily.

#methodSchema:len() → integer

Column count.

#methodSchema:field(name: string) → Field | nil

Look up a field by column name.

#methodSchema:field_at(i: integer) → Field | nil

Look up a field by 1-based position.

#methodSchema:fields() → (function, any, nil)

Iterator: for i, f in s:fields() do yields (integer, Field) pairs.

#methodSchema:metadata() → table

Schema-level metadata as a string->string table.

#methodSchema:meta(key: string) → string | nil

A single schema-level metadata entry.

#handleField

Returned by Schema:field(...) and yielded by Schema:fields().

Fields
  • .name : string read-only — Column name.
#methodField:dtype() → data.Dtype

Canonical data type name — the same vocabulary as DataColumn:dtype.

#methodField:is_nullable() → boolean

Whether the column may contain null values.

#methodField:index() → integer

1-based position in the parent schema.

#methodField:metadata() → table

Per-field metadata as a string->string table.

#methodField:meta(key: string) → string | nil

A single per-field metadata entry.

#handleDataView

Viewport-aware downsampled projection of a DataHandle. Created by h:view(options).

Fields
  • .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.
#methodDataView:set_range(options: data.SetRangeOptions)

Update the viewport range; omitted keys are left unchanged.

#methodDataView:range() → table
Suspends until the result arrives

Effective viewport range {x_min, x_max, y_min, y_max} with resolved auto values. Raises if the view was removed.

#methodDataView:remove()

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.

Fields
  • .x : number read-only — X component.
  • .y : number read-only — Y component.
Operators
  • add Vec2Vec2 — Component-wise addition.
  • sub Vec2Vec2 — Component-wise subtraction.
  • mul Vec2 | number → Vec2 — Vector or scalar multiplication.
  • div Vec2 | number → Vec2 — Vector or scalar division.
  • unmVec2 — Negation.
  • len → number — Magnitude (the # operator).
#methodVec2:length() → number

Magnitude.

#methodVec2:length_squared() → number

Squared magnitude (no sqrt).

#methodVec2:to_angle() → number

Angle in radians from the +X axis.

#methodVec2:min_element() → number

Smallest component.

#methodVec2:max_element() → number

Largest component.

#methodVec2:normalize() → Vec2

Unit vector. Raises if v is zero-length / non-finite; use normalize_or or try_normalize for a fallback.

#methodVec2:normalize_or(fallback: Vec2) → Vec2

Unit vector, or fallback if v is zero-length / non-finite.

#methodVec2:try_normalize() → Vec2 | nil

Unit vector, or nil if v is zero-length / non-finite.

#methodVec2:distance_squared(o: Vec2) → number

Squared Euclidean distance to o (no sqrt).

#methodVec2:signum() → Vec2

Component-wise sign (-1, 0, or +1).

#methodVec2:fract() → Vec2

Component-wise fractional part (self - self.trunc()).

#methodVec2:recip() → Vec2

Component-wise reciprocal (1/x).

#methodVec2:element_sum() → number

Sum of the components.

#methodVec2:element_product() → number

Product of the components.

#methodVec2:to_array() → number[]

Components as a {x, y} array.

#methodVec2:perp() → Vec2

Perpendicular vector (90 deg CCW).

#methodVec2:abs() → Vec2

Component-wise absolute value.

#methodVec2:floor() → Vec2

Component-wise floor.

#methodVec2:ceil() → Vec2

Component-wise ceil.

#methodVec2:round() → Vec2

Component-wise round.

#methodVec2:dot(o: Vec2) → number

Dot product.

#methodVec2:distance(o: Vec2) → number

Euclidean distance to o.

#methodVec2:perp_dot(o: Vec2) → number

Perpendicular dot (2D cross).

#methodVec2:angle_to(o: Vec2) → number

Signed angle to o in radians.

#methodVec2:rotate(o: Vec2) → Vec2

Rotate v by the rotation o represents.

#methodVec2:midpoint(o: Vec2) → Vec2

Midpoint between v and o.

#methodVec2:reflect(o: Vec2) → Vec2

Reflect v about the normal o.

#methodVec2:min(o: Vec2) → Vec2

Component-wise minimum.

#methodVec2:max(o: Vec2) → Vec2

Component-wise maximum.

#methodVec2:project_onto(o: Vec2) → Vec2

Projection of v onto o. Errors if o is zero-length.

#methodVec2:reject_from(o: Vec2) → Vec2

Rejection of v from o. Errors if o is zero-length.

#methodVec2:lerp(o: Vec2, t: number) → Vec2

Linear interpolation toward o by t; t outside 0..1 extrapolates past the endpoints (not clamped).

#methodVec2:move_towards(o: Vec2, d: number) → Vec2

Move toward o by at most distance d.

#methodVec2:clamp(lo: Vec2, hi: Vec2) → Vec2

Component-wise clamp to [lo, hi].

#methodVec2:clamp_length(lo: number, hi: number) → Vec2

Clamp magnitude to [lo, hi].

#methodVec2:is_normalized() → boolean

Whether the vector is unit length.

#methodVec2:extend(z: number) → Vec3

Extend to a Vec3 with the given z.

#methodVec2:with_x(x: number) → Vec2

Copy with x replaced.

#methodVec2:with_y(y: number) → Vec2

Copy with y replaced.

#methodVec2:unpack() → (number, number)

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.

Fields
  • .x : number read-only — X component.
  • .y : number read-only — Y component.
  • .z : number read-only — Z component.
Operators
  • add Vec3Vec3 — Component-wise addition.
  • sub Vec3Vec3 — Component-wise subtraction.
  • mul Vec3 | number → Vec3 — Vector or scalar multiplication.
  • div Vec3 | number → Vec3 — Vector or scalar division.
  • unmVec3 — Negation.
  • len → number — Magnitude (the # operator).
#methodVec3:length() → number

Magnitude.

#methodVec3:length_squared() → number

Squared magnitude (no sqrt).

#methodVec3:min_element() → number

Smallest component.

#methodVec3:max_element() → number

Largest component.

#methodVec3:normalize() → Vec3

Unit vector. Raises if v is zero-length / non-finite; use normalize_or or try_normalize for a fallback.

#methodVec3:normalize_or(fallback: Vec3) → Vec3

Unit vector, or fallback if v is zero-length / non-finite.

#methodVec3:try_normalize() → Vec3 | nil

Unit vector, or nil if v is zero-length / non-finite.

#methodVec3:distance_squared(o: Vec3) → number

Squared Euclidean distance to o (no sqrt).

#methodVec3:signum() → Vec3

Component-wise sign (-1, 0, or +1).

#methodVec3:fract() → Vec3

Component-wise fractional part (self - self.trunc()).

#methodVec3:recip() → Vec3

Component-wise reciprocal (1/x).

#methodVec3:element_sum() → number

Sum of the components.

#methodVec3:element_product() → number

Product of the components.

#methodVec3:to_array() → number[]

Components as a {x, y, z} array.

#methodVec3:abs() → Vec3

Component-wise absolute value.

#methodVec3:floor() → Vec3

Component-wise floor.

#methodVec3:ceil() → Vec3

Component-wise ceil.

#methodVec3:round() → Vec3

Component-wise round.

#methodVec3:any_orthogonal() → Vec3

An arbitrary vector orthogonal to v.

#methodVec3:dot(o: Vec3) → number

Dot product.

#methodVec3:distance(o: Vec3) → number

Euclidean distance to o.

#methodVec3:angle_between(o: Vec3) → number

Unsigned angle to o in radians.

#methodVec3:cross(o: Vec3) → Vec3

Cross product.

#methodVec3:midpoint(o: Vec3) → Vec3

Midpoint between v and o.

#methodVec3:reflect(o: Vec3) → Vec3

Reflect v about the normal o.

#methodVec3:min(o: Vec3) → Vec3

Component-wise minimum.

#methodVec3:max(o: Vec3) → Vec3

Component-wise maximum.

#methodVec3:project_onto(o: Vec3) → Vec3

Projection of v onto o. Errors if o is zero-length.

#methodVec3:reject_from(o: Vec3) → Vec3

Rejection of v from o. Errors if o is zero-length.

#methodVec3:lerp(o: Vec3, t: number) → Vec3

Linear interpolation toward o by t; t outside 0..1 extrapolates past the endpoints (not clamped).

#methodVec3:slerp(o: Vec3, t: number) → Vec3

Spherical interpolation toward o by t.

#methodVec3:move_towards(o: Vec3, d: number) → Vec3

Move toward o by at most distance d.

#methodVec3:clamp(lo: Vec3, hi: Vec3) → Vec3

Component-wise clamp to [lo, hi].

#methodVec3:clamp_length(lo: number, hi: number) → Vec3

Clamp magnitude to [lo, hi].

#methodVec3:is_normalized() → boolean

Whether the vector is unit length.

#methodVec3:truncate() → Vec2

Drop the z component, returning a Vec2.

#methodVec3:with_x(x: number) → Vec3

Copy with x replaced.

#methodVec3:with_y(y: number) → Vec3

Copy with y replaced.

#methodVec3:with_z(z: number) → Vec3

Copy with z replaced.

#methodVec3:unpack() → (number, number, number)

Return the x, y and z components as three values.

#handleQuat

A rotation quaternion (radians). Construct with datumhue.math.quat.from_euler(...) etc.

Fields
  • .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.
Operators
  • mul Quat | Vec3Quat | Vec3 — Compose with another quaternion (q * q), or rotate a vector (q * vec3).
#methodQuat:normalize() → Quat

Unit-length quaternion. Raises if q is zero-length / non-finite; use normalize_or or try_normalize for a fallback.

#methodQuat:normalize_or(fallback: Quat) → Quat

Unit-length quaternion, or fallback if q is zero-length / non-finite.

#methodQuat:try_normalize() → Quat | nil

Unit-length quaternion, or nil if q is zero-length / non-finite.

#methodQuat:inverse() → Quat

Inverse rotation.

#methodQuat:conjugate() → Quat

Conjugate (-x, -y, -z, w).

#methodQuat:dot(o: Quat) → number

Dot product (cosine of the angle between the rotations).

#methodQuat:length() → number

Magnitude.

#methodQuat:angle_between(o: Quat) → number

Angle in radians between two rotations.

#methodQuat:slerp(o: Quat, t: number) → Quat

Spherical interpolation toward o by t.

#methodQuat:lerp(o: Quat, t: number) → Quat

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.

#methodQuat:is_normalized() → boolean

Whether the quaternion is unit length.

#methodQuat:to_euler() → Vec3

Euler angles (radians, XYZ order) as a vec3.

#methodQuat:to_scaled_axis() → Vec3

Scaled-axis form (axis * angle) — the inverse of quat.from_scaled_axis.

#methodQuat:to_array() → number[]

Components as an {x, y, z, w} array.

#methodQuat:to_axis_angle() → (Vec3, number)

Return the rotation axis (unit vec3) and angle (radians) as two values.

#methodQuat:unpack() → (number, number, number, number)

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.

Fields
  • .origin : Vec3 read-only — The ray's start point.
  • .direction : Vec3 read-only — The ray's normalized direction.
#methodRay:get_point(distance: number) → Vec3

The point distance units along the ray from its origin.

#methodRay:unpack() → (Vec3, Vec3)

Return the origin and (normalized) direction as two vec3 values.

#handleColor

An sRGB color. Construct with datumhue.color(...); read components via .r/.g/.b/.a.

Fields
  • .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).
#methodColor:lerp(o: Color, t: number) → Color

Perceptual interpolation toward o by t (clamped 0..1), blended in Oklab so midtones stay vivid. Use mix for a different space.

#methodColor:mix(o: Color, t: number, space: color.MixSpace) → Color

Interpolate toward o by t (clamped 0..1) in the given color space.

#methodColor:darken(amount: number) → Color

Perceptually darken by amount (subtracted from Oklab lightness, 0..1); alpha unchanged.

#methodColor:lighten(amount: number) → Color

Perceptually lighten by amount (added to Oklab lightness, 0..1); alpha unchanged.

#methodColor:with_a(alpha: number) → Color

Copy with the alpha channel replaced (clamped 0..1).

#methodColor:with_r(r: number) → Color

Copy with the sRGB red channel replaced (clamped 0..1).

#methodColor:with_g(g: number) → Color

Copy with the sRGB green channel replaced (clamped 0..1).

#methodColor:with_b(b: number) → Color

Copy with the sRGB blue channel replaced (clamped 0..1).

#methodColor:rotate_hue(degrees: number) → Color

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.

#methodColor:saturate(amount: number) → Color

Increase saturation by amount (clamped 0..1).

#methodColor:desaturate(amount: number) → Color

Decrease saturation by amount (clamped 0..1).

#methodColor:to_array() → number[]

Components as an {r, g, b, a} array (sRGB, 0..1).

#methodColor:to_hsl() → (number, number, number)

Hue (degrees), saturation and lightness as three values.

#methodColor:to_oklch() → (number, number, number)

Oklch lightness, chroma and hue (degrees) as three values.

#methodColor:unpack() → (number, number, number, number)

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

Fields
  • .filter : image.Filter read/write — Texture sampling mode wherever the image is drawn. Set nearest to keep pixel art crisp; the default smooths.
  • .width : integer read-only — Width in pixels. Raises if the image isn't loaded yet — await it with image:ready() or datumhue.ready{...} first.
  • .height : integer read-only — Height in pixels. Raises if the image isn't loaded yet — await it with image:ready() or datumhue.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().
#methodImage:get(x: number, y: number) → Color | nil

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.

#methodImage:apply(pictures: Picture | Picture[])

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.

#methodImage:cursor() → Vec2 | nil

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.

#methodImage:remove()

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.

#methodImage:mount([options]: ui.ImageOptions) → UiElement | nil

Mount this render target as a UI image element. Returns the new UiElement, or nil if the app has no UI.

#methodImage:atlas(opts: image.AtlasOptions) → Atlas

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

#methodImage:sprite([opts]: image.SpriteOptions) → Sprite

Build a reusable Sprite appearance from this whole image. Options: {color?, flip_x?, flip_y?, size?}. Draw it with canvas:sprite(sprite, {pos = ...}).

#methodImage:ready() → Image
Suspends until the result arrives

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.

#methodImage:encode_png() → Bytes

Re-encode the pixel buffer as PNG bytes ready for file:write or a save_button's on_save_source.

#methodImage:update(bytes: Bytes) → Image

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.

#methodImage:to_cubemap() → CubemapAsset

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.

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodAudioAsset:ready() → AudioAsset
Suspends until the result arrives

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.

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodSceneAsset:ready() → SceneAsset
Suspends until the result arrives

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.

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodCubemapAsset:ready() → CubemapAsset
Suspends until the result arrives

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.

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodFont:ready() → Font
Suspends until the result arrives

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.

#methodFont:metrics(size: number | string) → font.Metrics

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.

#methodFtl:locale() → string

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.

#methodMessage:get() → string

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.

#methodPicture:set(x: number, y: number, color: Color) → Picture

Set a pixel. No-op if out of bounds when applied.

#methodPicture:fill(color: Color) → Picture

Fill the entire buffer with a color.

#methodPicture:clear() → Picture

Clear to transparent black (all zeros). Also resets the clip rectangle.

#methodPicture:line(x0: number, y0: number, x1: number, y1: number, color: Color) → Picture

Draw a line.

#methodPicture:circ(x: number, y: number, r: number, color: Color) → Picture

Draw a circle outline.

#methodPicture:circfill(x: number, y: number, r: number, color: Color) → Picture

Draw a filled circle.

#methodPicture:oval(x0: number, y0: number, x1: number, y1: number, color: Color) → Picture

Draw an oval outline (bounding box).

#methodPicture:ovalfill(x0: number, y0: number, x1: number, y1: number, color: Color) → Picture

Draw a filled oval (bounding box).

#methodPicture:rect(x0: number, y0: number, x1: number, y1: number, color: Color) → Picture

Draw a rectangle outline.

#methodPicture:rectfill(x0: number, y0: number, x1: number, y1: number, color: Color) → Picture

Draw a filled rectangle between two corners (inclusive, in either order). Clips to bounds.

#methodPicture:rrect(x: number, y: number, w: number, h: number, r: number, color: Color) → Picture

Draw a rounded-rectangle outline.

#methodPicture:rrectfill(x: number, y: number, w: number, h: number, r: number, color: Color) → Picture

Draw a filled rounded rectangle.

#methodPicture:tri(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, color: Color) → Picture

Draw a triangle outline.

#methodPicture:trifill(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, color: Color) → Picture

Draw a filled triangle.

#methodPicture:polygon(points: number[], color: Color) → Picture

Draw a polygon outline from a flat point array {x1,y1, x2,y2, ...}.

#methodPicture:polygonfill(points: number[], color: Color) → Picture

Draw a filled polygon from a flat point array {x1,y1, x2,y2, ...}.

#methodPicture:arc(cx: number, cy: number, r: number, start_angle: number, end_angle: number, color: Color) → Picture

Draw an arc outline. Angles in radians.

#methodPicture:arcfill(cx: number, cy: number, r: number, start_angle: number, end_angle: number, color: Color) → Picture

Draw a filled arc (pie slice). Angles in radians.

#methodPicture:floodfill(x: number, y: number, color: Color) → Picture

Replace all connected same-color pixels from (x,y). Bypasses camera and clip.

#methodPicture:blur(x: number, y: number, w: number, h: number, radius: number) → Picture

Box blur over a rectangular region.

#methodPicture:print(text: string, x: number, y: number, color: Color) → integer

Draw text. Returns the x position after the last character (sized by the current font). Supports newlines and the active font, clip, and camera.

#methodPicture:measure_text(text: string) → image.TextSize

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.

#methodPicture:wrap(text: string, max_width: number) → string[]

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.

#methodPicture:push() → Picture

Save the current camera offset and clip rectangle.

#methodPicture:pop() → Picture

Restore the camera offset and clip rectangle. No-op if the stack is empty.

#methodPicture:translate(dx: number, dy: number) → Picture

Shift the drawing origin by (dx, dy). Additive with the current camera offset.

#methodPicture:camera([x]: number, [y]: number) → Picture

Set the camera offset absolutely. Call with no arguments to reset to (0, 0).

#methodPicture:clip([x]: number, [y]: number, [w]: number, [h]: number) → Picture

Set the clipping rectangle in screen space. Call with no arguments to reset.

#methodPicture:fillp([pattern]: number) → Picture

Set a 4x4 fill-pattern bitmask (16-bit). Call with no arguments to reset to solid.

#methodPicture:set_font([atlas]: Atlas, [char_w]: number) → Picture

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.

#methodPicture:blit(src: Image, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, [blend_mode]: image.BlendMode) → Picture

Copy pixels from another Image (or the target itself) onto the canvas at apply time. blend_mode defaults to copy.

#methodPicture:reset() → Picture

Empty the command list so the picture can be rebuilt. Does not change the current font.

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

Fields
  • .filter : image.Filter read/write — Texture sampling mode for this canvas wherever it is drawn (a UI mount, canvas:image, a shader channel). Set nearest to keep pixel art crisp when the canvas is scaled up; the default smooths.
#methodDrawCanvas:rect(opts: draw.RectOptions) → DrawPrimitive

Draw a rectangle. Options: pos (vec3 bottom-left), width, height, color (Color), filled (default true), stroke_width (default 2), material.

#methodDrawCanvas:circle(opts: draw.CircleOptions) → DrawPrimitive

Draw a circle. Options: pos (vec3 center), radius, color, filled, stroke_width, material.

#methodDrawCanvas:ellipse(opts: draw.EllipseOptions) → DrawPrimitive

Draw an ellipse. Options: pos (vec3 center), rx, ry, color, filled, stroke_width, material.

#methodDrawCanvas:line(opts: draw.LineOptions) → DrawPrimitive

Draw a line. Options: from, to (vec3), color, width (default 1).

#methodDrawCanvas:polygon(opts: draw.PolygonOptions) → DrawPrimitive

Draw a polygon. Options: points (array of vec2, min 3), color, z (number), filled, stroke_width, material. Supports convex and simple concave polygons.

#methodDrawCanvas:rrect(opts: draw.RrectOptions) → DrawPrimitive

Draw a rounded rectangle. Options: pos (vec3 bottom-left), width, height, radius (default 10), color, filled, stroke_width, material.

#methodDrawCanvas:arc(opts: draw.ArcOptions) → DrawPrimitive

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.

#methodDrawCanvas:text(opts: draw.TextOptions) → DrawPrimitive

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

#methodDrawCanvas:sprite(sprite: Sprite, [opts]: draw.CanvasSpriteOptions) → DrawPrimitive

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.

#methodDrawCanvas:image(source: Image | DrawCanvas | Scene, [opts]: draw.CanvasSpriteOptions) → DrawPrimitive

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

#methodDrawCanvas:tilemap(atlas: Atlas, opts: draw.TilemapOptions) → TileMap

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

#methodDrawCanvas:clear()

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.

#methodDrawCanvas:remove()

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.

#methodDrawCanvas:resize(width: number, height: number)

Resize the canvas render texture. Existing primitives survive (world-space coordinates); any UI element displaying the canvas picks up the new size.

#methodDrawCanvas:set_camera(opts: draw.SetCameraOptions)

Set the 2D camera. Options (all optional): pos (vec2 center), zoom (>1 in, <1 out).

#methodDrawCanvas:enable_pan_zoom(opts: draw.PanZoomOptions)

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.

#methodDrawCanvas:disable_pan_zoom()

Stop driving this canvas's camera from the mouse.

#methodDrawCanvas:screen_to_world(pos: Vec2) → Vec2 | nil

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.

#methodDrawCanvas:world_to_screen(pos: Vec2) → Vec2 | nil

Convert draw coordinates to element-relative screen pixels, accounting for camera pan/zoom and the canvas's on-screen placement (letterbox / scale).

#methodDrawCanvas:group(primitives: DrawPrimitive[]) → DrawPrimitive

Group primitives so they move, hide, and fade as a unit. Nested groups supported. group:remove() removes the group and every primitive in it.

#methodDrawCanvas:body(opts: draw.BodyOptions) → DrawPrimitive

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.

#methodDrawCanvas:path() → PathBuilder

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

#methodDrawCanvas:point_query(point: Vec2) → DrawPrimitive | nil

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.

#methodDrawCanvas:point_query_all(point: Vec2) → DrawPrimitive[]

Every primitive whose drawn shape covers point (canvas-local world space), topmost first; empty when nothing is hit. Same geometry rules as point_query.

#methodDrawCanvas:mount([options]: ui.ImageOptions) → UiElement | nil

Mount this render target as a UI image element. Returns the new UiElement, or nil if the app has no UI.

#methodDrawCanvas:chart(options: chart.CanvasChartOptions) → PlotArea

Carve a PlotArea out of this canvas for charting, positioned by pos / width / height with optional margin, x_scale / y_scale, and background.

#methodDrawCanvas:charts(options: chart.CanvasChartsOptions) → PlotArea[]

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.

Fields
  • .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 an Atlas; assign to animate. Nil for primitives that are not atlas sprites; assigning to those is ignored.
#methodDrawPrimitive:update(opts: draw.UpdateOptions)

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.

#methodDrawPrimitive:remove()

Remove a primitive from its canvas.

#methodDrawPrimitive:animate(opts: draw.AnimateOptions)

Tween the primitive's position, rotation, scale, color, and opacity over duration seconds with the given easing curve.

#methodDrawPrimitive:contains(point: Vec2) → boolean

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

#methodDrawPrimitive:bounds() → draw.Bounds | nil

The primitive's axis-aligned bounding box in canvas-local world space, or nil for primitives without a single mesh (text, groups).

#methodDrawPrimitive:add_body([options]: physics.BodyOptions)

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.

#methodDrawPrimitive:character_controller([options]: physics.CharacterControllerOptions) → CharacterController

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

#methodDrawPrimitive:apply_impulse(vec: Vec2 | Vec3)

Apply an instantaneous, mass-correct velocity change (Δv = impulse / mass). Accepts vec2 or vec3.

#methodDrawPrimitive:apply_angular_impulse(impulse: number | Vec3)

Apply an instantaneous, inertia-correct spin change. A number for 2D bodies (about Z), a vec3 for 3D.

#methodDrawPrimitive:apply_force(vec: Vec2 | Vec3)

Set the continuous force applied every step until changed. Pass a zero vector to stop. Accepts vec2 or vec3.

#methodDrawPrimitive:apply_torque(torque: number | 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.

#methodDrawPrimitive:lock_rotation(locked: boolean)

Lock or unlock rotation.

#methodDrawPrimitive:set_collision_layers(options: physics.CollisionLayerOptions)

Replace this body's collision filtering at runtime (e.g. switching teams).

#methodDrawPrimitive:set_locked_axes(options: physics.LockedAxesOptions)

Lock or unlock individual translation/rotation axes at runtime. The 2D in-plane constraints are always preserved.

#methodDrawPrimitive:on_collision_start([callback]: fun(other: DrawPrimitive | SceneNode, contact: physics.Contact))

Set, replace, or clear (pass nil) the handler fired when this body starts colliding.

#methodDrawPrimitive:on_collision_end([callback]: fun(other: DrawPrimitive | SceneNode))

Set, replace, or clear (pass nil) the handler fired when this body stops colliding.

#methodDrawPrimitive:remove_body()

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.

#methodAtlas:sprite(index: number, [opts]: image.SpriteOptions) → Sprite

Build a Sprite appearance for cell index (0-based, row-major). Options: {color?, flip_x?, flip_y?, size?}.

#methodAtlas:clips(defs: table<string, scene.ClipDef>) → SpriteClips

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.

#methodSprite:with([opts]: image.SpriteOptions) → 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.

#methodTileMap:set(x: number, y: number, index: number)

Set cell (x, y) to atlas index. Raises if the cell is out of bounds (unlike Grid:set, which is a no-op there).

#methodTileMap:get(x: number, y: number) → integer | nil

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.

Fields
  • .title : string read-only — The book title.
  • .page : integer read-only — Current chapter (1-based). Navigate with go.
  • .pages : integer read-only — Chapter count.
#methodBook:mount([options]: book.MountOptions) → UiElement
Suspends until the result arrives

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.

#methodBook:go(target: integer | string)
Suspends until the result arrives

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.

#methodBook:refresh([id]: string)
Suspends until the result arrives

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.

#methodBook:element(id: string) → UiElement | PlotArea | Mark

The handle behind the mounted element with this document id — a chart id yields its PlotArea, a line id its Mark, anything else its UiElement. Raises when the id is unknown 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).

Fields
  • .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 opaque Bytes.
#methodResponse:ready() → Response
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

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

Fields
  • .state : ReadyState read-only — Completion state of this operation. Reading it never raises or suspends; a failed operation's error surfaces at :ready().
#methodOp:ready() → Op
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

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

Fields
  • .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.
#methodStat:ready() → Stat
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

#handleListFetch

An in-flight name listing (dir:list, storage:list). value raises until it materializes — await :ready() or datumhue.ready, or probe state.

Fields
  • .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.
#methodListFetch:ready() → ListFetch
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

#handleBoolFetch

An in-flight boolean answer (dir:exists). value raises until it materializes — await :ready() or datumhue.ready, or probe state.

Fields
  • .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.
#methodBoolFetch:ready() → BoolFetch
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

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

Fields
  • .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.
#methodBytesFetch:ready() → BytesFetch
Suspends until the result arrives

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.

Fields
  • .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.
#methodDocEntry:ready() → DocEntry
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

#handleDocQuery

An in-flight document prefix query. entries raises until it materializes — await :ready() or datumhue.ready, or probe state.

Fields
  • .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.
#methodDocQuery:ready() → DocQuery
Suspends until the result arrives

Wait until this operation completes, then return the same handle for chaining. Raises if the operation failed. A completed handle returns at once.

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

Fields
  • .name : string read-only — The user-facing alias for this directory, never a host path.
#methodDir:list() → ListFetch

Direct-child names, sorted ascending.

#methodDir:read(rel: string) → Bytes

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.

#methodDir:stat(rel: string) → Stat

Metadata for rel; a missing rel fails the operation.

#methodDir:exists(rel: string) → BoolFetch

Whether rel exists. Only unexpected failures fail the operation.

#methodDir:create_file(rel: string) → Op

Create an empty file at rel. Requires rw mode. An already-existing file fails the operation.

#methodDir:mkdir(rel: string) → Op

Create a directory at rel. Requires rw mode.

#methodDir:remove(rel: string) → Op

Remove a file or empty directory at rel. Requires rw mode.

#methodDir:write(rel: string, bytes: Bytes) → Op

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.

#methodDir:mode() → app.PreopenMode

The directory's access mode.

#methodDir:open(rel: string) → File

Mint a new file capability rooted at rel within this directory. Returns immediately; the handle inherits the parent dir's mode.

#methodDir:subdir(rel: string) → Dir

Mint a narrowed directory capability rooted at rel inside this dir. The returned handle sees only files under its own root.

#methodDir:require(rel: string) → any
Suspends until the result arrives

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.

#methodDir:load_package(rel: string) → Package
Suspends until the result arrives

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.

#methodDir:book() → Book
Suspends until the result arrives

Load the book rooted at this directory: book.kdl names the title and chapters, each a page file inside the directory. Raises with file:line:col diagnostics on parse or validation errors.

#handleFile

A capability for one file inside a granted directory. Read, write, stat, or load it as a Lua module / package.

Fields
  • .name : string read-only — The file's name.
#methodFile:mode() → app.PreopenMode

The file's access mode.

#methodFile:read() → Bytes

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.

#methodFile:write(bytes: Bytes) → Op

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.

#methodFile:stat() → Stat

Metadata for this file — the same fields dir:stat materializes.

#methodFile:require() → any
Suspends until the result arrives

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.

#methodFile:book() → Book
Suspends until the result arrives

Load this .kdl page as a one-chapter book. Raises with file:line:col diagnostics on parse or validation errors.

#methodFile:load_package() → Package
Suspends until the result arrives

Read this file's bytes and parse them as a .dhpkg archive, returning a typed Package handle.

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

#methodDataMount:query(sql: string, [params]: table) → DataHandle

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.

Fields
  • .domain : table | "auto" | nil read/write — Resolved domain {min = N, max = N}, or nil while 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 as categories).
  • .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. nil on linear / log / time scales, which map a numeric continuum and keep no category list.
#methodScale:map(value: number | string) → number | nil

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.

#methodScale:invert(pixel: number) → number | string | nil

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.

#methodScale:fit(data: DataHandle, column: string, [force]: boolean) → Scale
Suspends until the result arrives

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.

#methodScale:reset(data: DataHandle, column: string) → Scale
Suspends until the result arrives

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.

#methodScale:bandwidth() → number | nil

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.

#methodScale:index_of(name: string) → integer | nil

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.

#methodScale:animate(options: chart.AnimateOptions)

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.

#methodScale:on_change(fn: fun(scale: Scale)) → Subscription

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.

#methodScale:remove()

Destroy the scale.

#handleMark

A rendered mark (line / points / area / bars / rule / text) inside a plot area. Returned by the area:* mark constructors.

Fields
  • .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.
#methodMark:update(options: chart.MarkUpdateOptions)

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.

#methodMark:nearest(data_pos: Vec2 | chart.DataPos) → chart.NearestRow | nil

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.

#methodMark:push_point(data_pos: Vec2 | chart.DataPos)

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.

#methodMark:replace_data(handle: DataHandle)

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

#methodMark:remove()

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.

Fields
  • .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 via area:update({x_scale = ...}).
  • .y_scale : Scale | nil read-only — The area's y-axis Scale handle. Mirror of x_scale; swap via area:update({y_scale = ...}).
#methodPlotArea:line(options: chart.LineMarkOptions) → Mark

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.

#methodPlotArea:points(options: chart.PointsMarkOptions) → Mark

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.

#methodPlotArea:area(options: chart.AreaMarkOptions) → Mark

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.

#methodPlotArea:rule(options: chart.RuleMarkOptions) → Mark

Add a horizontal or vertical reference line at a data-space value.

#methodPlotArea:text(options: chart.TextMarkOptions) → Mark

Add a text annotation at a data-space position.

#methodPlotArea:band(options: chart.BandMarkOptions) → Mark

Add a filled highlighted region spanning a [from, to] range on one axis and the full inner rect on the orthogonal axis.

#methodPlotArea:bars(options: chart.BarsMarkOptions) → Mark

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.

#methodPlotArea:histogram(options: chart.HistogramMarkOptions) → Mark

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.

#methodPlotArea:heatmap(options: chart.HeatmapMarkOptions) → Mark

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.

#methodPlotArea:box(options: chart.BoxMarkOptions) → Mark

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.

#methodPlotArea:histogram2d(options: chart.Histogram2dMarkOptions) → Mark

Add a 2D density heatmap — numeric (x, y) pairs binned engine-side into a colored grid. Zoomed scales re-bin over the visible window.

#methodPlotArea:axis(options: chart.AxisOptions) → Axis

Add an axis bound to a scale.

#methodPlotArea:legend(options: chart.LegendOptions) → Legend

Add a legend.

#methodPlotArea:update(options: chart.PlotAreaUpdateOptions)

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.

#methodPlotArea:world_to_data(pos: Vec2) → chart.DataPos | nil

Canvas coord → data coord using current scales. Exact for time scales (full-precision epoch-ms).

#methodPlotArea:data_to_world(pos: Vec2 | chart.DataPos) → Vec2 | nil

Data coord → canvas coord. An {x, y} table keeps a time-scale x exact (a vec2 rounds epoch-ms to f32 first).

#methodPlotArea:rescale([opts]: chart.RescaleOptions)

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.

#methodPlotArea:title(options: chart.TitleOptions)

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.

#methodPlotArea:remove_title()

Remove the plot area's title (if any).

#methodPlotArea:crosshair([options]: chart.CrosshairOptions) → Crosshair

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.

#methodPlotArea:pan_zoom([options]: chart.PanZoomOptions) → PanZoom

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.

#methodPlotArea:brush([options]: chart.BrushOptions) → Brush

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.

#methodPlotArea:on_hover(fn: fun(data_pos: chart.DataPos))

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.

#methodPlotArea:on_click(fn: fun(data_pos: chart.DataPos, button: input.MouseButton))

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.

#methodPlotArea:value_at(x: number) → chart.MarkValue[]

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.

#methodPlotArea:mouse_data_position() → chart.DataPos | nil

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.

#methodPlotArea:cursor() → chart.CursorInfo | nil

Composite cursor accessor. Returns nil when no cursor resolves. Unlike mouse_data_position, returns a value even when the cursor is outside the area.

#methodPlotArea:clear()

Remove every mark attached to this area — line / points / bars / area / rule / text / band / axis / legend. The PlotArea itself survives, as does the canvas.

#methodPlotArea:group(marks: table) → ChartGroup

Bundle a set of mark handles for synchronized visibility toggles and lifecycle. Not a hierarchy — marks render where they were created.

#methodPlotArea:remove()

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.

#methodCrosshair:update(options: chart.CrosshairOptions)

Reconfigure the crosshair in place; omitted options keep their current values. Raises after remove.

#methodCrosshair: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.

#methodPanZoom:update(options: chart.PanZoomOptions)

Reconfigure the interaction in place; omitted options keep their current values and an in-flight gesture is left undisturbed. Raises after remove.

#methodPanZoom: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.

Fields
  • .selection : chart.BrushSelection | nil read-only — Data-space bounds of the committed brush selection; nil when nothing is selected or the brush was removed.
#methodBrush:update(options: chart.BrushOptions)

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.

#methodBrush:clear()

Clear the committed selection and its region without firing on_brush.

#methodBrush:remove()

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.

Fields
  • .domain : table | "auto" | nil read/write — Domain {min = N, max = N}, or nil while pending. Assign {min = N, max = N} or "auto".
#methodColorScale:map(value: number | string) → Color | nil

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

#methodColorScale:remove()

Destroy the color scale.

#handleAxis

A tick axis bound to a scale, created by area:axis(options).

#methodAxis:update(options: chart.AxisUpdateOptions)

Change the axis ticks, label, format, grid, or colors.

#methodAxis:remove()

Remove the axis.

#handleLegend

A legend panel attached to a plot area, created by area:legend(options).

#methodLegend:update(options: chart.LegendUpdateOptions)

Change the legend items, position, anchor, orientation, or colors.

#methodLegend:remove()

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.

Fields
  • .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.
#methodChartGroup:remove()

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.

Fields
  • .visible : boolean read/write — Whether the element and its children are shown.
  • .display : ui.Display read/write — Layout display mode. Assigning none removes 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; nil when unset. Assign a vec2.
  • .size : Vec2 | nil read/write — Width/height in pixels as a vec2; nil when unset. Assign a vec2.
  • .color : Color | ThemedColor read/write — Background color. Assign a datumhue.theme.token(...) to follow the theme, or a Color to pin it; reading gives the resolved Color.
  • .text : string | nil read/write — Text content of a label or a text input (nil on other elements). Assigning to a text input replaces its value silently (no on_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; nil otherwise). 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). nil for non-scroll elements.
  • .enabled : boolean read/write — Whether an interactive widget (a button, checkbox) accepts input. Setting false grays it out and suppresses its click / keyboard activation; true restores it. Reads true on non-interactive elements.
  • .checked : boolean read/write — Whether a checkbox is checked. Assigning updates it silently (the on_change callback fires only on user toggles, not programmatic writes). Reads false on 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 a Color for a color picker. Assigning updates it silently (no on_change). nil on elements that hold no value; assigning to one raises.
  • .min : number | nil read/write — A slider's range minimum. Assigning re-clamps value into the new range. nil on non-slider elements; assigning to one raises.
  • .max : number | nil read/write — A slider's range maximum. Assigning re-clamps value into the new range. nil on non-slider elements; assigning to one raises.
  • .step : number | nil read/write — A slider's keyboard / track-click step increment. nil on 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 (or nil); 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 (no on_change): an integer (or nil to clear) for radio/single, an array for multi. nil on 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; false on non-interactive elements.
  • .hovered : boolean read-only — Whether the cursor is currently over the element. Read-only; false on non-interactive elements.
  • .strikethrough : boolean read/write — Whether a line is drawn through a text label. Assigning toggles it. Reads false on non-text elements; assigning to one raises.
  • .underline : boolean read/write — Whether a line is drawn under a text label. Assigning toggles it. Reads false on non-text elements; assigning to one raises.
#methodUiElement:remove()

Remove the element and its children. Raises on ui.root (the engine-owned app content area) — remove its children or individual elements instead.

#methodUiElement:router() → Router

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.

#methodUiElement:option(index: integer) → UiElement

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.

#methodUiElement:item(index: integer) → UiElement

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.

#methodUiElement:on_click([callback]: function)

Set, replace, or clear (pass nil) the click handler at runtime. Fires only on an interactive element (a button).

#methodUiElement:on_pick([callback]: function)

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.

#methodUiElement:on_save([callback]: function)

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

#methodUiElement:on_save_source([source]: string | Bytes)

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.

#methodUiElement:on_copy_source([source]: string | Bytes)

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.

#methodUiElement:row(index: integer) → table

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.

#methodUiElement:on_hover([callback]: function)

Set, replace, or clear (pass nil) the hover-enter handler at runtime. Fires when the cursor enters this element or any of its descendants.

#methodUiElement:on_hover_exit([callback]: function)

Set, replace, or clear (pass nil) the hover-exit handler at runtime. Fires when the cursor leaves this element and all of its descendants.

#methodUiElement:on_press([callback]: function)

Set, replace, or clear (pass nil) the press handler (fires while held) at runtime. Fires only on an interactive element.

#methodUiElement:on_release([callback]: function)

Set, replace, or clear (pass nil) the release handler at runtime. Fires only on an interactive element.

#methodUiElement:on_double_click([callback]: function)

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

#methodUiElement:on_focus([callback]: function)

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.

#methodUiElement:on_blur([callback]: function)

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.

#methodUiElement:on_cancel([callback]: function)

Set, replace, or clear (pass nil) the cancel handler at runtime. Fires when Escape is pressed while a text input is focused.

#methodUiElement:focus()

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.

#methodUiElement:set_text_color([color]: Color | ThemedColor)

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.

#methodUiElement:set_material([material]: Shader)

Apply a shader material. Omit / pass nil to remove it.

#methodUiElement:set_source([source]: Image | DrawCanvas | Scene)

Swap the image texture to a render-target source. Omit / pass nil to clear it.

#methodUiElement:update(opts: ui.ElemUpdateOptions)

Batch-update layout / style plus source, color, text, visible, or material.

#methodUiElement:mouse_position() → Vec2 | nil

Cursor position relative to the element's top-left corner (logical px), or nil.

#methodUiElement:to_texture_coords(pos: Vec2) → Vec2 | nil

Scale element-relative logical px to the source texture's native pixel space, or nil.

#methodUiElement:panel(opts: ui.PanelOptions) → UiElement

Create a child UI panel.

#methodUiElement:button(opts: ui.ButtonOptions) → UiElement

Create a child interactive button.

#methodUiElement:open_button(opts: ui.OpenButtonOptions) → UiElement

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.

#methodUiElement:save_button(opts: ui.SaveButtonOptions) → UiElement

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.

#methodUiElement:copy_button(opts: ui.CopyButtonOptions) → UiElement

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.

#methodUiElement:link(opts: ui.LinkOptions) → UiElement

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.

#methodUiElement:date_picker(opts: ui.DatePickerOptions) → UiElement

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.

#methodUiElement:time_picker(opts: ui.DatePickerOptions) → UiElement

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

#methodUiElement:datetime_picker(opts: ui.DatePickerOptions) → UiElement

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

#methodUiElement:color_picker(opts: ui.ColorPickerOptions) → UiElement

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.

#methodUiElement:checkbox(opts: ui.CheckboxOptions) → UiElement

Create a child checkbox. State is the checked property; on_change fires on user toggles.

#methodUiElement:slider(opts: ui.SliderOptions) → UiElement

Create a child horizontal slider. State is the value property; on_change fires continuously while dragging.

#methodUiElement:number_input(opts: ui.NumberInputOptions) → UiElement

Create a child numeric input: a number field with -/+ steppers. State is the value property; on_change fires on field edits and steps.

#methodUiElement:radio_group(opts: ui.RadioGroupOptions) → UiElement

Create a child radio group. State is the selected property (1-based); on_change fires on user selection.

#methodUiElement:list(opts: ui.ListOptions) → UiElement

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.

#methodUiElement:table(opts: ui.TableOptions) → UiElement

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.

#methodUiElement:text_input(opts: ui.TextInputOptions) → UiElement

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

#methodUiElement:popover(opts: ui.PopoverOptions) → UiElement

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.

#methodUiElement:menu(opts: ui.MenuOptions) → UiElement

Create a dropdown menu anchored to this element: a label trigger button and a popup you fill with child widgets (each item carries its own callback). Clicking the button toggles the popup; clicking outside or pressing Escape closes it; activating a button item runs it and closes the menu.

#methodUiElement:label(opts: ui.LabelOptions) → UiElement

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.

Fields
  • .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.
#methodRouter:route(builder: function, [options]: ui.RouteOptions) → Route

Declare a route from a builder(page, params) that fills the given page element. Returns a Route handle to navigate to.

#methodRouter:show(route: Route, [params]: table | nil)
Suspends until the result arrives

Switch the active root to route (tabs); the previous root and its whole sub-stack are retained. Builds the route on first show.

#methodRouter:push(target: Route | function, [params]: table | nil)
Suspends until the result arrives

Push a page onto the active stack (a Route or an inline builder(page, params)); the page below is hidden, retained.

#methodRouter:replace(target: Route | function, [params]: table | nil)
Suspends until the result arrives

Replace the top page in place (no depth change). Runs the old page's on_leave (which may veto).

#methodRouter:go(route: Route, [params]: table | nil)
Suspends until the result arrives

Navigate to route: if it is already on the active stack, pop back to it (retained); otherwise push it.

#methodRouter:pop()
Suspends until the result arrives

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.

#methodRouter:to_root()
Suspends until the result arrives

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

Fields
  • .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.

#methodJoint:remove()

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.

Fields
  • .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.
#methodPhysicsWorld:raycast(ray: Ray, [options]: physics.RaycastOptions) → physics.RayHit | nil

Cast a ray and return the nearest body hit, or nil.

#methodPhysicsWorld:raycast_all(ray: Ray, [options]: physics.RaycastAllOptions) → physics.RayHit[]

Cast a ray and return every body along it, nearest first.

#methodPhysicsWorld:point_query(point: Vec2 | Vec3, [options]: physics.PointQueryOptions) → (DrawPrimitive | SceneNode)[]

Return every body whose collider overlaps the given world-space point.

#methodPhysicsWorld:shapecast(ray: Ray, options: physics.ShapecastOptions) → physics.RayHit | nil

Sweep a 3D collider shape along the ray and return the nearest body hit, or nil.

#methodPhysicsWorld:remove()

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.

Fields
  • .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; false when disabled.
  • .autostep : physics.AutostepConfig | boolean read/write — Step-climbing config, or false when 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 plus max_height above 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 last move: 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 last move: the character was let slide down a too-steep slope. False before the first move.
#methodCharacterController:move(displacement: Vec2 | Vec3, [dt]: number) → physics.CharacterMove

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

#methodCharacterController:push_dynamics(mass: number)

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.

#methodCharacterController:remove()

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.

#methodPathBuilder:move_to(x: number, y: number) → PathBuilder

Start a new subpath at (x, y). Returns self for chaining.

#methodPathBuilder:line_to(x: number, y: number) → PathBuilder

Add a straight segment to (x, y). Returns self for chaining.

#methodPathBuilder:quad_to(cx: number, cy: number, x: number, y: number) → PathBuilder

Add a quadratic bezier through control point (cx, cy) to (x, y). Returns self.

#methodPathBuilder:cubic_to(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number) → PathBuilder

Add a cubic bezier through control points (c1x, c1y) / (c2x, c2y) to (x, y). Returns self.

#methodPathBuilder:close() → PathBuilder

Close the current subpath back to its start. Returns self.

#methodPathBuilder:fill([options]: draw.PathFillOptions) → DrawPrimitive | nil

Tessellate and fill the recorded path. Options: color, z, material. Returns the new DrawPrimitive, or nil if the canvas is invalid.

#methodPathBuilder:stroke([options]: draw.PathStrokeOptions) → DrawPrimitive | nil

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 = …}).

Fields
  • .name : string read-only — Scoped @scope/name identity.
#methodPackageRef:scope() → string

Owning scope segment (the scope in @scope/name), without the leading @.

#methodPackageRef:publisher() → string

Stable identifier of the entity that published this version, as verified at publish from the publisher's sign-in.

#methodPackageRef:namespace() → string

Namespace this entry belongs to.

#methodPackageRef:version() → string

SemVer string from the manifest.

#methodPackageRef:kind() → string

Manifest kind: "app", "library", or "asset_pack".

#methodPackageRef:content_type() → string | nil

The refinement tag on asset packs, or nil when unset.

#methodPackageRef:description() → string | nil

One-line summary, or nil when unset.

#methodPackageRef:author() → string | nil

Display name, or nil when unset.

#methodPackageRef:icon() → Image | nil

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.

#methodPackageRef:size() → integer

Total size of the package's files in bytes.

#methodPackageRef:is_sealed() → boolean

The sealed flag from the manifest.

#methodPackageRef:is_service() → boolean

The service flag from the manifest.

#methodPackageRef:requires() → table<string, string>

Map of dependency @scope/name to its SemVer constraint.

#methodPackageRef:capabilities() → string[]

Array of capability grants the manifest declares as required to run, in declaration order; empty when none.

#methodPackageRef:monetization() → packages.Monetization | nil

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.

#methodPackageRef:license() → string | nil

SPDX license id the package declares (e.g. "0BSD"), or nil when unset. Free packages always carry one; paid packages may omit it.

#methodPackageRef:tags() → string[]

Discovery tags from the manifest, in declaration order; empty when none.

#methodPackageRef:screenshots() → Image[]

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.

#methodPackageRef:readme() → string | nil
Suspends until the result arrives

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.

#methodPackageRef:load() → Package
Suspends until the result arrives

Download and materialise the package as a Package handle. Raises if the request fails.

#methodPackageRef:installed_version() → string | nil
Requires the packages capability

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

#methodPackageRef:install()
Suspends until the result arrives
Requires the packages capability

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

#methodPackageRef:uninstall() → integer
Suspends until the result arrives
Requires the packages capability

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

Fields
  • .package : string read-only — Canonical @scope/name of 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.

#methodHttpMount:get(path: string, [opts]: HttpMount.RequestOptions) → Response

Options: headers, query, timeout_ms.

#methodHttpMount:post(path: string, [opts]: HttpMount.RequestOptions) → Response

Options: headers, query, body (Bytes), timeout_ms.

#methodHttpMount:put(path: string, [opts]: HttpMount.RequestOptions) → Response

Options: headers, query, body (Bytes), timeout_ms.

#methodHttpMount:patch(path: string, [opts]: HttpMount.RequestOptions) → Response

Options: headers, query, body (Bytes), timeout_ms.

#methodHttpMount:delete(path: string, [opts]: HttpMount.RequestOptions) → Response

Options: headers, query, body (Bytes), timeout_ms.

#methodHttpMount:head(path: string, [opts]: HttpMount.RequestOptions) → Response

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.

#methodIngressMount:subscribe(opts: IngressMount.SubscribeOptions) → Subscription

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
#optdatumhue.AppArgs options table
  • 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.
#optdatumhue.HttpMount.RequestOptions options table
  • headers : table<string, string> optional — Request headers. Credentials are injected provider-side per the mount's configuration; the mount may override the Authorization header.
  • query : table<string, string> optional — Query-string parameters appended to the path.
  • body : Bytes optional — Request body as opaque Bytes (ignored by GET / HEAD).
  • timeout_ms : integer optional — Request timeout in milliseconds.
#optdatumhue.IngressEvent options table
  • channel : string — The channel the record arrived on.
  • payload : Bytes — The record's application payload as opaque Bytes.
  • headers : table<string, string> — Application headers the source set and the provider forwarded.
#optdatumhue.IngressMount.SubscribeOptions options table
  • 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.
#optdatumhue.app.PreopenEntry options table
  • handle : Dir — The handle to inherit.
  • mode : app.PreopenMode optional — Mode narrowing the inherited access; defaults to the parent's.
#optdatumhue.app.PreopenFileEntry options table
  • handle : File — The handle to inherit.
  • mode : app.PreopenMode optional — Mode narrowing the inherited access; defaults to the parent's.
#optdatumhue.app.RequestPermissionOptions options table
  • reason : string optional — Justification shown to the user when the window manager prompts for approval.
#optdatumhue.app.SpawnAppOptions options table
  • name : string optional — App name; required for code, defaults to the manifest name for a package.
  • code : string optional — Inline Lua source. Mutually exclusive with package / package_ref.
  • package : Package optional — A loaded package bundle to run. Mutually exclusive with code / package_ref.
  • package_ref : PackageRef optional — A catalog reference; the child arrives once resolved + downloaded. Mutually exclusive with code / 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 inline code.
  • parent : App optional — An ancestor (or self) to reparent the spawn under; defaults to the caller.
#optdatumhue.app.SpawnPermissions options table
  • 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).
#optdatumhue.audio.MusicOptions options table
  • 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's volume reads 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.
#optdatumhue.audio.PlayOptions options table

Inherits all fields of audio.PositionalOptions.

  • volume : number optional — Linear volume (defaults to 1.0) — the instance gain the handle's volume reads 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 starting pitch.
  • bus : string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
#optdatumhue.audio.PositionalOptions options table
  • at : Vec2 optional — Where the sound stands, in any 2D unit kept consistent with listener. Pan comes from the horizontal offset (via pan_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 as at; 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 curve min(falloff_cap, k / (1 + d / falloff_scale)) (default 1.0).
  • falloff_scale : number optional — Distance at which the curve has halved a unit falloff_gain (default 128; must be > 0).
#optdatumhue.audio.SfxNote options table
  • 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.
#optdatumhue.audio.SfxPlayOptions options table

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 with at.
  • 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's volume.
  • bus : string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
#optdatumhue.audio.SynthOptions options table
  • 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's volume reads and writes.
  • looping : boolean optional — Loop playback when true (defaults to false); adjust a running loop by assigning handle.volume.
  • bus : string optional — Route through the app's named bus (created on first use); the audible volume is master x bus x instance.
#optdatumhue.audio.Vibrato options table
  • depth : number optional — Frequency deviation in Hz (defaults to 5.0).
  • speed : number optional — Vibrato LFO rate in Hz (defaults to 4.0).
#optdatumhue.book.MountOptions options table

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.
#optdatumhue.bytes.CsvOptions options table
  • 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.
#optdatumhue.chart.AnimateOptions options table
  • 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).
#optdatumhue.chart.AreaMarkOptions options table

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 from color_scale or the category palette in first-seen order, and contributes its own legend item.
  • color_scale : ColorScale optional — Category color scale assigning per-series colors; requires series_column.
  • readout : chart.ReadoutMode optional — Crosshair readout interpolation mode.
#optdatumhue.chart.AxisOptions options table
  • 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.
#optdatumhue.chart.AxisUpdateOptions options table
  • 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.
#optdatumhue.chart.BandMarkOptions options table
  • 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.
#optdatumhue.chart.BandScaleOptions options table
  • domain : string[] — Non-empty array of category strings.
  • padding : number optional — Gap between bands, 0..1 (default 0.1).
#optdatumhue.chart.BarsMarkOptions options table
  • entries : table optional — Array of {category, value} entries. Exactly one of entries, series, or data.
  • series : table optional — Array of {name?, color?, entries} series for stacked/grouped layouts; colors default from the category palette. Requires mode.
  • data : DataHandle optional — 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 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). Requires mode; series take palette colors in first-seen order.
  • aggregate : chart.BarsAggregate optional — Per-category aggregation for data sources. Default sum with a value_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.
#optdatumhue.chart.BoxEntry options table
  • 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.
#optdatumhue.chart.BoxMarkOptions options table
  • entries : chart.BoxEntry[] optional — 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 : DataHandle optional — 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 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.
#optdatumhue.chart.BrushOptions options table
  • 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).
#optdatumhue.chart.BrushSelection options table
  • x_min : number optional — Selection lower x bound in data space (epoch-ms on time scales). Absent when the brush axis is y.
  • x_max : number optional — Selection upper x bound in data space. Absent when the brush axis is y.
  • y_min : number optional — Selection lower y bound in data space. Absent when the brush axis is x.
  • y_max : number optional — Selection upper y bound in data space. Absent when the brush axis is x.
#optdatumhue.chart.CanvasChartOptions options table
  • 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.
#optdatumhue.chart.CanvasChartsOptions options table
  • 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 after gap.
  • height : number — Total grid height in canvas units; cells divide it evenly after gap.
  • 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.
#optdatumhue.chart.ColorCategoryOptions options table
  • 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.
#optdatumhue.chart.ColorScaleOptions options table
  • colors : Color[] optional — Array of at least two color stops. Exactly one of colors or palette.
  • palette : chart.Palette optional — Built-in ramp preset. Exactly one of colors or palette.
  • 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).
#optdatumhue.chart.CrosshairOptions options table
  • 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).
#optdatumhue.chart.CursorInfo options table
  • 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.
#optdatumhue.chart.DataMarkBase options table
  • 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.
#optdatumhue.chart.DataPos options table
  • x : number — Data-space x. Exact for time scales (full-precision epoch-ms).
  • y : number — Data-space y.
#optdatumhue.chart.HeatmapMarkOptions options table
  • cells : table optional — Array of {x, y, value} cells (x/y are category strings). Exactly one of cells, matrix, or data.
  • matrix : table optional — Row-major {{number, ...}, ...} values; requires x_categories and y_categories (row index follows y_categories).
  • x_categories : string[] optional — Column categories for matrix.
  • y_categories : string[] optional — Row categories for matrix.
  • data : DataHandle optional — Tabular source; requires x_column and y_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 a value_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.
#optdatumhue.chart.Histogram2dMarkOptions options table
  • points : table optional — Inline {{x, y}, ...} pairs to bin. Exactly one of points or data.
  • data : DataHandle optional — Tabular source; requires x_column and y_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.
#optdatumhue.chart.HistogramMarkOptions options table
  • values : number[] optional — Inline values to bin. Exactly one of values or data.
  • data : DataHandle optional — Tabular source; requires column. 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 with bin_width.
  • bin_width : number optional — Explicit bin width in data units. Mutually exclusive with bins.
  • 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.
#optdatumhue.chart.LegendItem options table
  • label : string — The item's label text.
  • color : Color optional — The item's swatch color; white when omitted.
#optdatumhue.chart.LegendOptions options table
  • kind : chart.LegendKind optional — Legend form. Defaults to discrete swatch items; a gradient legend renders color_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.
#optdatumhue.chart.LegendUpdateOptions options table
  • 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.
#optdatumhue.chart.LineMarkOptions options table

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 from color_scale or the category palette in first-seen order, and contributes its own legend item.
  • color_scale : ColorScale optional — Category color scale assigning per-series colors; requires series_column.
  • readout : chart.ReadoutMode optional — Crosshair readout interpolation mode.
#optdatumhue.chart.LinearScaleOptions options table

Inherits all fields of chart.ScaleBase.

  • follow : number optional — Rolling-window size for streaming marks.
#optdatumhue.chart.LogScaleOptions options table

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.
#optdatumhue.chart.Margin options table
  • top : number optional — Top inset.
  • right : number optional — Right inset.
  • bottom : number optional — Bottom inset.
  • left : number optional — Left inset.
#optdatumhue.chart.MarkUpdateOptions options table
  • 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.
#optdatumhue.chart.MarkValue options table
  • mark : Mark — The mark this value belongs to.
  • x : number — Data-space x (the sample x for nearest readouts, the query x for interpolate).
  • value : number — The mark's y-value at x.
  • color : Color — The mark's color.
  • name : string optional — The mark's name, when set.
#optdatumhue.chart.NearestRow options table
  • 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.
#optdatumhue.chart.PanZoomOptions options table
  • 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, or false to 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, or false to disable.
  • double_click_reset : boolean optional — Reset view on double-click.
  • double_click_ms : number optional — Double-click window in milliseconds.
#optdatumhue.chart.PlotAreaUpdateOptions options table
  • 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, or false to opt back into the theme default.
#optdatumhue.chart.PointsMarkOptions options table

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 normalizes size_column values. Required with size_column.
  • size_range : table optional{min, max} output dot sizes in pixels for size_column values. Required with size_column.
  • color_column : string optional — Column driving per-dot color.
  • color_scale : ColorScale optional — Color scale for color_column.
#optdatumhue.chart.RescaleOptions options table
  • force : boolean optional — Always refit, even over scales the user has pinned with pan / zoom.
#optdatumhue.chart.RuleMarkOptions options table
  • 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.
#optdatumhue.chart.ScaleBase options table
  • 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.
#optdatumhue.chart.TextMarkOptions options table
  • 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 to pos.
  • offset : Vec2 optional — Pixel offset from pos.
#optdatumhue.chart.TextPos options table
  • 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.
#optdatumhue.chart.TimeScaleOptions options table

Inherits all fields of chart.ScaleBase.

    #optdatumhue.chart.TitleOptions options table
    • 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).
    #optdatumhue.data.BatchesOptions options table

    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.
    #optdatumhue.data.ColumnSelectBase options table
    • columns : string[] optional — Column names to include; all columns if omitted.
    #optdatumhue.data.RangeBounds options table
    • 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".
    #optdatumhue.data.RowsOptions options table

    Inherits all fields of data.ColumnSelectBase.

      #optdatumhue.data.SetRangeOptions options table

      Inherits all fields of data.RangeBounds.

        #optdatumhue.data.ViewOptions options table

        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 (default lttb_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.
        #optdatumhue.dialogue.Choice options table
        • label : string — The choice as shown.
        • value : any optional — Delivered to on_choice when picked; nil is allowed and delivered as nil.
        #optdatumhue.dialogue.Current options table
        • 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.
        #optdatumhue.dialogue.DriveOptions options table
        • confirm : string optional — Action name for the advance gesture; defaults to interact.
        #optdatumhue.dialogue.Entry options table
        • text : string — The line's text.
        • speaker : string optional — Speaker attribution.
        • on_done : fun() optional — Fired when the player advances past this line.
        #optdatumhue.dialogue.Mark options table
        • 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.
        #optdatumhue.documents.CollectionMeta options table
        • id : string — The entry's id within the collection — what ack takes and on_ack carries.
        • timestamp : integer — Write time, UNIX microseconds.
        • author : string optional — The verified writer identity. Absent on local scope, which has no author concept.
        #optdatumhue.documents.CollectionOptions options table
        • on_add : fun(value: any, meta: documents.CollectionMeta) — Fired once per distinct entry, backfill included, up to max entries.
        • max : integer optional — Bound on on_add fires. Entries past it still sync and are counted by count(); 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 toward count(), and still consume the global max, 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 or count().
        • authors : string[] optional — Observe only these writers' entries (identity keys, as meta.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 via ack. The receipt carries the entry id only — no reader identity, and no proof: it is an anonymous, unauthenticated courtesy signal.
        #optdatumhue.documents.CommunalOptions options table
        • 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, as meta.author / documents.identity).
        #optdatumhue.documents.CreateOptions options table

        Inherits all fields of documents.ScopedOptions.

          #optdatumhue.documents.Entry options table
          • value : any — The stored value.
          • meta : documents.Meta — Write metadata.
          #optdatumhue.documents.GetOptions options table
          • author : string optional — Read this writer's entry at the key instead of newest-wins across writers.
          #optdatumhue.documents.GrantOptions options table
          • 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.
          #optdatumhue.documents.Meta options table
          • timestamp : integer — Write time, UNIX microseconds.
          • author : string optional — The writer's identity key. Absent on local-scope writes, which have no author concept.
          #optdatumhue.documents.OpenNamedOptions options table

          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, as meta.author / documents.identity).
          #optdatumhue.documents.OpenOptions options table
          • 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, as meta.author / documents.identity).
          #optdatumhue.documents.QueryOptions options table
          • 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).
          #optdatumhue.documents.SchemaField options table
          • 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.
          #optdatumhue.documents.ScopedOptions options table
          • scope : documents.Scope optional — Backend: "network" replicates with other clients and requires the network capability. Defaults to "local".
          #optdatumhue.draw.AnimateOptions options table
          • 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, like Color:lerp). Writes the same color slot update{color=} writes.
          • opacity : number optional — Target alpha 0.0-1.0 — the opacity property'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).
          #optdatumhue.draw.ArcOptions options table

          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).
          #optdatumhue.draw.BodyOptions options table

          Inherits all fields of physics.BodyOptions.

          • pos : Vec3 — Initial world position of the body (vec3; vec2 accepted, z = 0).
          #optdatumhue.draw.Bounds options table
          • min : Vec2 — Minimum corner.
          • max : Vec2 — Maximum corner.
          • size : Vec2 — Extent along each axis (max - min).
          • center : Vec2 — Center of the box.
          #optdatumhue.draw.CanvasSpriteOptions options table
          • 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 a Shader; Material handles are 3D-only.
          #optdatumhue.draw.CircleOptions options table

          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 — Circle radius in pixels (default 25).
          #optdatumhue.draw.DrawShapeOptions options table
          • color : Color optional — Fill/stroke color (default white).
          • filled : boolean optional — Fill the shape rather than stroke it (default true).
          • stroke_width : number optional — Stroke width in pixels when not filled (default 2).
          • material : Shader optional — Shader handle to apply.
          #optdatumhue.draw.EllipseOptions options table

          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.
          • rx : number optional — Horizontal radius in pixels (default 50).
          • ry : number optional — Vertical radius in pixels (default 25).
          #optdatumhue.draw.LineOptions options table
          • 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).
          #optdatumhue.draw.MeasureTextOptions options table
          • 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 (bold is 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.
          #optdatumhue.draw.NewOptions options table
          • 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).
          #optdatumhue.draw.PanZoomOptions options table
          • 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).
          #optdatumhue.draw.PathFillOptions options table
          • 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 a Shader; Material handles are 3D-only.
          #optdatumhue.draw.PathStrokeOptions options table
          • 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 a Shader; Material handles are 3D-only.
          • width : number optional — Stroke width in canvas units (default 2).
          #optdatumhue.draw.PolygonOptions options table

          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.
          #optdatumhue.draw.RectOptions options table

          Inherits all fields of draw.DrawShapeOptions.

          • pos : Vec2 | Vec3 optional — Bottom-left position (default origin); without an explicit z the shape auto-stacks in creation order.
          • width : number optional — Rectangle width in pixels (default 50).
          • height : number optional — Rectangle height in pixels (default 50).
          #optdatumhue.draw.RrectOptions options table

          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).
          #optdatumhue.draw.SetCameraOptions options table
          • pos : Vec2 optional — Camera center in draw coordinates.
          • zoom : number optional — Zoom factor (>1 in, <1 out).
          #optdatumhue.draw.TextOptions options table
          • 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 (default left).
          • linebreak : draw.LineBreak optional — Line-break mode (default word).
          • font_weight : number | FontWeight optional — Font weight: a number on the variable weight axis, or a weight name (bold is 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.
          #optdatumhue.draw.TextSize options table
          • width : number — Rendered width in draw units.
          • height : number — Rendered height in draw units.
          #optdatumhue.draw.TextSpan options table
          • 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 (bold is 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.
          #optdatumhue.draw.TextSpanOptions options table
          • 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 (bold is the heaviest). Inherits when omitted.
          • font_style : FontStyle optional — Span face: upright, the calligraphic cursive, or a mechanical slant. Inherits when omitted.
          #optdatumhue.draw.TilemapOptions options table
          • columns : number — Number of columns in the grid.
          • rows : number — Number of rows in the grid.
          #optdatumhue.draw.UpdateOptions options table
          • 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 (bold is 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.
          #optdatumhue.events.AppBoundsChanged options table

          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.
          #optdatumhue.events.AppDesignResolutionRequest options table

          Inherits all fields of events.AppEvent.

          • width : number — Requested design-canvas width.
          • height : number — Requested design-canvas height.
          #optdatumhue.events.AppEvent options table
          • app : App — The app the event is about.
          • parent : App optional — The subject app's parent; nil for the bootstrap root.
          #optdatumhue.events.AppFramePressed options table

          Inherits all fields of events.AppEvent.

          • x : number — Press x within the frame.
          • y : number — Press y within the frame.
          #optdatumhue.events.AppFullscreenRequest options table

          Inherits all fields of events.AppEvent.

          #optdatumhue.events.AppIdentitySignInRequest options table

          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.
          #optdatumhue.events.AppPermissionRequest options table

          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.
          #optdatumhue.events.AppResizeRequest options table

          Inherits all fields of events.AppEvent.

          • width : number — Requested window width.
          • height : number — Requested window height.
          #optdatumhue.events.AppSpawned options table

          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.
          #optdatumhue.events.AppStateChanged options table

          Inherits all fields of events.AppEvent.

          • app_name : string — The app's name.
          • minimized : boolean — Whether the app is now minimized.
          #optdatumhue.events.AppStretchModeRequest options table

          Inherits all fields of events.AppEvent.

          #optdatumhue.events.AppTerminated options table

          Inherits all fields of events.AppEvent.

          • app_name : string — The terminated app's name.
          #optdatumhue.events.AppZoomRequest options table

          Inherits all fields of events.AppEvent.

          • zoom : number — Requested zoom multiplier.
          #optdatumhue.events.Connectivity options table
          • 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.
          #optdatumhue.events.IdentityRefreshed options table
          • 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.
          #optdatumhue.events.IdentitySignInFailed options table
          • error_kind : string — Diagnostic failure category.
          • error_message : string — Human-readable failure detail.
          • skew_secs : number optional — Clock-skew seconds, for time-related failures.
          #optdatumhue.events.IdentitySignedIn options table
          • 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.
          #optdatumhue.events.ScaleFactorChanged options table
          • scale_factor : number — New OS display scale factor.
          #optdatumhue.events.WindowResized options table
          • width : number — New window width, logical pixels.
          • height : number — New window height, logical pixels.
          #optdatumhue.events.ZoomChanged options table
          • zoom : number — New end-user zoom multiplier.
          #optdatumhue.font.Metrics options table
          • 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.
          #optdatumhue.grid.AgentOptions options table
          • 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 as stopped. Handle the cell (open the door, clear the line) and the walk resumes on its own once the cell's value changes.
          #optdatumhue.grid.AgentStep options table
          • x : number — position after the step, in cells
          • y : number — position after the step, in cells
          • arrived : boolean — the target cell has been reached
          • blocked : boolean — a target is set but no path to it exists
          • stopped : grid.AgentStop optional — when the walk halted before a stop_before cell: the cell and its value
          #optdatumhue.grid.AgentStop options table
          • x : integer — the halting cell
          • y : integer — the halting cell
          • value : integer — the cell's value at the halt
          #optdatumhue.grid.AgentWaypoint options table
          • x : integer — waypoint cell
          • y : integer — waypoint cell
          #optdatumhue.grid.AutomataStepOptions options table
          • 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).
          #optdatumhue.grid.Cell options table
          • x : integer — Cell column.
          • y : integer — Cell row.
          #optdatumhue.grid.CountNeighborsOptions options table
          • match : integer[] — Cell values counted as matching neighbours.
          #optdatumhue.grid.DijkstraOptions options table
          • sources : grid.DijkstraSource[] — Weighted source cells the distance field flows out from.
          • blocked : integer[] — Cell values treated as impassable walls.
          #optdatumhue.grid.DijkstraSource options table
          • x : integer — Source cell x coordinate.
          • y : integer — Source cell y coordinate.
          • score : number optional — Starting distance score (default 0).
          #optdatumhue.grid.DistanceOptions options table
          • type : grid.DistanceType optional — Metric used to measure the distance (default euclidean).
          #optdatumhue.grid.FieldOfViewOptions options table
          • range : integer — Maximum sight radius in cells.
          • opaque : integer[] — Cell values that block line of sight.
          #optdatumhue.grid.FillNoiseOptions options table
          • 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).
          #optdatumhue.grid.FindPathOptions options table
          • blocked : integer[] — Cell values treated as impassable walls.
          #optdatumhue.grid.FloodFillOptions options table
          • match : integer[] — Cell values the fill is allowed to spread into.
          #optdatumhue.grid.SlideOptions options table
          • solid : integer[] — Cell values the box collides with.
          #optdatumhue.grid.VoronoiCell options table
          • origin : grid.Cell — The hive's seed cell.
          • cells : grid.Cell[] — Cells belonging to this hive.
          #optdatumhue.grid.VoronoiOptions options table
          • distance : grid.DistanceType optional — Metric used to assign cells to the nearest hive (default euclidean).
          • seed : integer optional — Seed for deterministic hive placement. Omitting both seed and rng draws from an engine-internal source that random.new streams do not affect.
          • rng : Rng optional — Draw hive placement from this stream (advancing it). Mutually exclusive with seed.
          #optdatumhue.identity.SignInOptions options table
          • issuer : string — OIDC issuer name to sign in against.
          • prompt : string optional — OIDC prompt parameter (e.g. login, consent).
          • login_hint : string optional — Pre-filled login hint passed to the authorization endpoint.
          #optdatumhue.image.AtlasOptions options table
          • 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).
          #optdatumhue.image.NewOptions options table
          • width : number — Image width in pixels. Must be positive.
          • height : number — Image height in pixels. Must be positive.
          #optdatumhue.image.SpriteOptions options table
          • 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.
          #optdatumhue.image.TextSize options table
          • width : integer — The widest line's advance, in pixels.
          • height : integer — Line count times the font's cell height, in pixels.
          #optdatumhue.input.ActionBindOptions options table
          • 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).
          #optdatumhue.input.RumbleOptions options table
          • 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).
          #optdatumhue.input.Touch options table
          • 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 as mouse_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.
          #optdatumhue.material.MaterialStandardOptions options table

          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 the mask alpha 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).
          #optdatumhue.material.MaterialUnlitOptions options table
          • color : Color optional — Base color (default white).
          #optdatumhue.material.PbrMaterialOptions options table
          • color : Color optional — Base color (default white).
          • metallic : number optional — Metallic factor (default 0).
          • roughness : number optional — Perceptual roughness (default 0.5).
          • emissive : Color optional — Emissive color (default none).
          #optdatumhue.material.UpdateOptions options table
          • 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 the mask alpha 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.
          #optdatumhue.messaging.MessageOptions options table
          • topic : string — Topic to publish or subscribe on.
          • scope : messaging.Scope optional — Message scope (defaults to in-process); the networked scope requires the network capability.
          #optdatumhue.messaging.Peer options table
          • 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.
          #optdatumhue.messaging.PresenceOptions options table
          • 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.
          #optdatumhue.messaging.PublishOptions options table

          Inherits all fields of messaging.MessageOptions.

          • payload : any — Message payload, serialized as-is.
          #optdatumhue.messaging.SubscribeOptions options table

          Inherits all fields of messaging.MessageOptions.

          • callback : function — Function invoked with each received message payload.
          #optdatumhue.noise.BaseOptions options table
          • seed : integer optional — Random seed for the noise field.
          • frequency : number optional — Spatial frequency of the noise.
          #optdatumhue.noise.CellularOptions options table

          Inherits all fields of noise.BaseOptions.

          #optdatumhue.noise.FbmOptions options table
          • 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.
          #optdatumhue.packages.ChangeEvent options table
          • 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.
          #optdatumhue.packages.FilterBase options table
          • 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.
          #optdatumhue.packages.InfoOptions options table
          • namespace : string optional — Catalog namespace to look up in; defaults to the bootstrap namespace.
          #optdatumhue.packages.InstallChangeEvent options table
          • 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.
          #optdatumhue.packages.InstalledOptions options table

          Inherits all fields of packages.FilterBase.

            #optdatumhue.packages.ListOptions options table

            Inherits all fields of packages.FilterBase.

              #optdatumhue.packages.Monetization options table
              • 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.
              #optdatumhue.packages.RegistryInfo options table
              • namespace : string — The registry's namespace.
              • available : boolean — Whether the registry currently has a reachable provider. Refreshed periodically; a registry never yet observed reports true. An unavailable registry keeps its catalog entries visible, but installs of uncached content from it fail.
              #optdatumhue.packages.SearchOptions options table

              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.
              #optdatumhue.particles.ColorOverLife options table
              • start : Color optional — Color at spawn (default white).
              • stop : Color optional — Color at end of life (default start faded to transparent).
              #optdatumhue.particles.EmitterOptions options table
              • 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 (default world).
              • pos : Vec3 optional — Emitter position in the scene (default origin).
              #optdatumhue.particles.Shape options table
              • 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.
              #optdatumhue.particles.SizeOverLife options table
              • start : number optional — Quad edge length at spawn (default 0.1).
              • stop : number optional — Quad edge length at end of life (default start).
              #optdatumhue.particles.VelocityRange options table
              • min : Vec3 optional — Lower bound (default zero).
              • max : Vec3 optional — Upper bound (default min).
              #optdatumhue.physics.AutostepConfig options table
              • 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).
              #optdatumhue.physics.BodyOptions options table
              • type : physics.BodyType optional — Body dynamics (defaults to dynamic).
              • 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 for convex_hull / polyline / trimesh (vec3; vec2 accepted, z = 0).
              • indices : integer[][] optional — Triangle index triples for the trimesh shape.
              • 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.
              #optdatumhue.physics.CharacterCollision options table
              • 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.
              #optdatumhue.physics.CharacterControllerOptions options table
              • 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; false disables (default {relative=0.2}).
              • autostep : physics.AutostepConfig | boolean optional — Step-climbing config, or false/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 plus max_height above 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).
              #optdatumhue.physics.CharacterMove options table
              • translation : Vec3 — The movement to apply this frame — the body is not moved; set body.pos = body.pos + translation.
              • grounded : boolean — Standing on ground after applying translation. 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.
              #optdatumhue.physics.CollisionLayerOptions options table
              • 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.
              #optdatumhue.physics.Contact options table
              • point : Vec3 — World-space contact point (the deepest point of the manifold).
              • normal : Vec3 — World-space contact normal, pointing out of this body toward the other.
              • penetration : number — Penetration depth in metres (positive when overlapping).
              #optdatumhue.physics.JointOptions options table
              • type : physics.JointType optional — Joint kind; defaults to fixed.
              • 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 toward motor_target (default 1000 when a target is set).
              • motor_damping : number optional — Damper gain toward motor_speed (default 100 for velocity motors, 30 for position motors).
              #optdatumhue.physics.LockedAxesOptions options table
              • 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).
              #optdatumhue.physics.PointQueryOptions options table
              • layers : integer[] optional — Only include bodies in these layer bit indices 0..=31 (default all).
              • exclude : DrawPrimitive | SceneNode optional — A body to ignore.
              #optdatumhue.physics.RayHit options table
              • 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.
              #optdatumhue.physics.RaycastAllOptions options table
              • 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).
              #optdatumhue.physics.RaycastOptions options table
              • 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).
              #optdatumhue.physics.RelativeLength options table
              • relative : number — Fraction of the character shape's relevant extent.
              #optdatumhue.physics.ShapecastOptions options table
              • 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.
              #optdatumhue.scene.AnimateOptions options table

              Inherits all fields of scene.Transform3dOptions.

              • color : Color optional — Target color, blended perceptually (Oklab, like Color: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).
              #optdatumhue.scene.BlendClip options table
              • clip : string — Animation clip label, e.g. Animation0.
              • weight : number — Relative blend weight (normalized across the set).
              #optdatumhue.scene.CameraAnimateOptions options table
              • pos : Vec3 optional — Target world-space position.
              • rotation : Quat optional — Target orientation. Mutually exclusive with look_at.
              • look_at : Vec3 optional — World-space point to end up facing. Resolved to a target rotation once, when the tween starts — against pos when both are given, so the end pose faces the point; the camera does not track the point afterwards. Mutually exclusive with rotation.
              • fov : number optional — Target vertical field of view in radians. Ignored on a non-perspective camera, like .fov assignment.
              • duration : number optional — Tween duration in seconds (default 1).
              • easing : Easing optional — Easing curve (default linear).
              #optdatumhue.scene.ClipDef options table
              • frames : integer[] — 0-based atlas cell indices in play order.
              • fps : number optional — Frames per second (default 8). Ignored when durations is 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 as frames); overrides fps.
              • markers : table<integer, string> optional — 1-based frame position within this clip's frames list → marker name; fires on_marker when the playhead crosses that frame.
              #optdatumhue.scene.DeformOptions options table
              • 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).
              #optdatumhue.scene.DirectionalLightOptions options table

              Inherits all fields of scene.LightOptions.

              • direction : Vec3 optional — Light direction (default down).
              #optdatumhue.scene.EnvironmentOptions options table
              • 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).
              #optdatumhue.scene.LightOptions options table
              • color : Color optional — Light color (default white).
              • intensity : number optional — Luminous intensity (default 1000).
              • shadows : boolean optional — Cast shadows (default false).
              #optdatumhue.scene.MeshBounds options table
              • min : Vec3 — Minimum corner.
              • max : Vec3 — Maximum corner.
              • size : Vec3 — Extent along each axis (max - min).
              • center : Vec3 — Center of the box.
              #optdatumhue.scene.MeshOptions options table

              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).
              #optdatumhue.scene.MeshUpdateOptions options table
              • 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 with normals.
              #optdatumhue.scene.ModelOptions options table
              • asset : SceneAsset — External glTF / GLB scene asset (from file:read():scene() / dir:read(rel):scene()).
              • pos : Vec3 optional — World-space position (default origin).
              • rotation : Quat optional — Rotation quaternion (default identity). Build with datumhue.math.quat.from_euler etc.
              • scale : Vec3 optional — Per-axis scale (default (1, 1, 1)).
              #optdatumhue.scene.NodeUpdateOptions options table

              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.
              #optdatumhue.scene.PlaneOptions options table

              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 gives mesh:update and node:deform vertices to move.
              #optdatumhue.scene.PlayAnimationOptions options table
              • clip : string optional — Animation clip label, e.g. Animation0, Animation1 (default Animation0).
              • 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).
              #optdatumhue.scene.PlayOpts options table
              • 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 own looping.
              #optdatumhue.scene.PointLightOptions options table

              Inherits all fields of scene.LightOptions.

              • pos : Vec3 optional — World-space position (default origin).
              • range : number optional — Falloff range (default 20).
              #optdatumhue.scene.RaycastHit options table
              • node : SceneNode — The node the ray hit.
              • distance : number — Distance from the ray origin to the hit point.
              • point : Vec3 — World-space hit point.
              • normal : Vec3 — Surface normal at the hit point.
              #optdatumhue.scene.SceneNewOptions options table
              • 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).
              #optdatumhue.scene.SpotLightOptions options table

              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 (default pi/4).
              #optdatumhue.scene.SpriteOptions options table
              • source : Sprite optional — The appearance to draw, from image:sprite() or atlas:sprite(i). Provide this or image, not both.
              • image : Image optional — A whole Image to draw, as an alternative to source. Provide this or source, not both.
              • pos : Vec3 optional — World-space position (default origin).
              • billboard : scene.BillboardMode optional — How the sprite turns to face the camera; default y_locked (stays upright, turning horizontally toward the camera — the 2.5D character look).
              • size_mode : scene.SpriteSizeMode optional — Whether size is measured in scene units or in constant on-screen pixels; default world.
              • size : Vec2 optional — Quad extent, in the unit chosen by size_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; default cutout (crisp alpha-tested edges that depth-sort correctly without draw-order dependence).
              • cutoff : number optional — Alpha-test threshold for the cutout mode (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.
              #optdatumhue.scene.Transform3dOptions options table
              • pos : Vec3 optional — World-space position (default origin).
              • rotation : Quat optional — Rotation quaternion (default identity). Build with datumhue.math.quat.from_euler etc.
              • scale : Vec3 optional — Per-axis scale (default (1, 1, 1)).
              #optdatumhue.screen.DesignResolution options table
              • width : number — Design width in points.
              • height : number — Design height in points.
              #optdatumhue.screen.Monitor options table
              • 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.
              #optdatumhue.screen.Resolution options table
              • 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.
              #optdatumhue.shader.CompileOptions options table
              • uniforms : table optional — Table of name = initial declarations the source reads as u.<name>. A number declares an f32, a vec2/vec3 its vector type, a color a vec4<f32>. Capacity 16.
              • channels : table optional — Array of up to 4 texture sources (pixel canvas, draw canvas, or scene) bound as dh_channel0..3; unset channels sample white.
              #optdatumhue.shader.CreateOptions options table
              • 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).
              #optdatumhue.shader.UpdateOptions options table
              • 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.
              #optdatumhue.time.FromCalendarOptions options table
              • 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).
              #optdatumhue.time.TweenOptions options table
              • from : number | Vec2 | Vec3 | Color — Start value. Same type as to.
              • to : number | Vec2 | Vec3 | Color — End value. Same type as from.
              • 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 exactly to.
              • on_finish : fun() optional — Runs once, after the final on_update delivery. Skipped when the tween is unsubscribed before it finishes.
              #optdatumhue.ui.ButtonOptions options table

              Inherits all fields of ui.NodeStyle.

              • text : string | Message — Button label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale.
              • enabled : boolean optional — 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 : 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.
              #optdatumhue.ui.CheckboxOptions options table

              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 (default false).
              • enabled : boolean optional — Whether it starts enabled (default true). A disabled checkbox ignores clicks and keyboard toggling until elem.enabled = true.
              • on_change : function optional — Called with the new checked state (boolean) each time the user toggles it. A programmatic elem.checked = ... write does not fire it.
              #optdatumhue.ui.ColorPickerOptions options table

              Inherits all fields of ui.NodeStyle.

              • initial : Color | ThemedColor optional — Initial color (a Color or a theme token); default opaque white.
              • alpha : boolean optional — Add an alpha strip and widen the hex field to #RRGGBBAA (default false, 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 (default true).
              • open : boolean optional — Start with the popover open (default false).
              • on_change : function optional — Called with the picked Color when the user drags the square/strips, commits the hex field, or clicks a preset. A programmatic value write does not fire it.
              #optdatumhue.ui.CopyButtonOptions options table

              Inherits all fields of ui.NodeStyle.

              • label : string | Message — Button label (required) — a plain string, or a datumhue.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-8 Bytes (non-UTF-8 raises — the clipboard is text). Omit and bind later with elem:on_copy_source to 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.
              #optdatumhue.ui.DatePickerOptions options table

              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 (default true).
              • open : boolean optional — Start with the popover open (default false).
              • on_change : function optional — Called with the selected instant (Unix microseconds) when the user picks a day or edits the time. A programmatic value write does not fire it.
              #optdatumhue.ui.ElemUpdateOptions options table

              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 a datumhue.theme.token(...) to follow the theme.
              • text : string | Message optional — New text — a plain string (stops following any locale), or a datumhue.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 (bold is 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 (a bytes:font() / datumhue.font.builtin() handle); pins the face. Unchanged when omitted.
              • visible : boolean optional — Show or hide the element.
              • material : Shader optional — Shader material.
              #optdatumhue.ui.ImageOptions options table

              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 (default fill); 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 — use fit).
              • 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.
              #optdatumhue.ui.LabelOptions options table

              Inherits all fields of ui.NodeStyle.

              • text : string | Message optional — 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 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 a datumhue.theme.token(...) to follow the theme and repaint on change.
              • strikethrough : boolean optional — Draw a line through the text (default false). Also a read/write property.
              • underline : boolean optional — Draw a line under the text (default false). Also a read/write property.
              • font_weight : number | FontWeight optional — 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 : FontStyle optional — Font face: upright, the calligraphic cursive, or a mechanical slant. Defaults to upright.
              • font : Font optional — Font (a bytes:font() / datumhue.font.builtin() handle); pins this label's face, overriding datumhue.font.default. Defaults to the app default face.
              #optdatumhue.ui.LinkOptions options table

              Inherits all fields of ui.NodeStyle.

              • text : string | Message — Link text (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale.
              • url : 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.
              #optdatumhue.ui.ListOptions options table

              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 (default false).
              • enabled : boolean optional — Whether it starts enabled (default true). A disabled list ignores clicks and keyboard navigation until elem.enabled = true.
              • on_change : function optional — Called on user selection with the new selected value — a 1-based integer for a single-select list, a 1-based index array for multi. A programmatic elem.selected = ... write does not fire it.
              #optdatumhue.ui.MenuOptions options table

              Inherits all fields of ui.NodeStyle.

              • label : string — The menu button's label.
              • enabled : boolean optional — Whether it starts enabled (default true).
              #optdatumhue.ui.NodeStyle options table
              • 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 the scroll / scroll_max element properties.
              • display : ui.Display optional — 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 | ThemedColor optional — 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 | 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.
              #optdatumhue.ui.NumberInputOptions options table

              Inherits all fields of ui.NodeStyle.

              • value : number optional — Initial value, clamped to the range (default min, or 0).
              • 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 (default 1).
              • precision : integer optional — Decimal places the value is displayed and snapped to (default 0).
              • enabled : boolean optional — Whether it starts enabled (default true). A disabled number input ignores typing and the steppers until elem.enabled = true.
              • on_change : function optional — 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.
              #optdatumhue.ui.OpenButtonOptions options table

              Inherits all fields of ui.NodeStyle.

              • text : string | Message — Button label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale.
              • mode : ui.PickMode — What the click picks; selects the on_pick payload.
              • 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 with elem:on_pick (e.g. from a hosting app via book:element). With no handler bound a click opens no dialog.
              • enabled : boolean optional — Whether the button starts enabled (default true). Setting false grays it out and ignores clicks.
              #optdatumhue.ui.Outline options table
              • 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.
              #optdatumhue.ui.PanelOptions options table

              Inherits all fields of ui.NodeStyle.

              • color : Color | ThemedColor optional — Background color; defaults to the theme panel background. Pass a datumhue.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.
              #optdatumhue.ui.PopoverOptions options table

              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 to side (default "start").
              • gap : number optional — Gap in logical px between the anchor and the popover (default 4).
              • visible : boolean optional — Whether it starts shown (default false); toggle later via the visible property.
              • light_dismiss : boolean optional — 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).
              #optdatumhue.ui.RadioGroupOptions options table

              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 (default true). A disabled group ignores clicks and keyboard navigation until elem.enabled = true.
              • on_change : function optional — Called with the selected 1-based index (integer) when the user picks an option. A programmatic elem.selected = ... write does not fire it.
              #optdatumhue.ui.RouteOptions options table
              • title : string | Message optional — Accessible title (a plain string or a datumhue.i18n.t(...) message), announced to a screen reader on navigation and readable as route.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). Return false to veto and keep it (confirm-before-leave).
              #optdatumhue.ui.SaveButtonOptions options table

              Inherits all fields of ui.NodeStyle.

              • text : string | Message — Button label (required) — a plain string, or a datumhue.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 with elem:on_save_source to 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-only File handle (never on cancel). Optional; bind later with elem:on_save.
              • enabled : boolean optional — Whether the button starts enabled (default true).
              #optdatumhue.ui.Shadow options table
              • 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.
              #optdatumhue.ui.SliderOptions options table

              Inherits all fields of ui.NodeStyle.

              • value : number optional — Initial value, clamped to [min, max] (default the range midpoint).
              • min : number optional — Range minimum (default 0).
              • max : number optional — Range maximum (default 1).
              • step : number optional — Keyboard / track-click step increment (default 0.1).
              • enabled : boolean optional — Whether it starts enabled (default true). A disabled slider ignores drag and keyboard input until elem.enabled = true.
              • on_change : function optional — Called with the new value (number) continuously as the user drags or steps it. A programmatic elem.value = ... write does not fire it.
              #optdatumhue.ui.TableColumn options table
              • 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.
              #optdatumhue.ui.TableOptions options table

              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. Default false.
              • multi : boolean optional — Allow selecting multiple rows at once (default false).
              • on_change : function optional — Called on user row selection with the new selected value — a 1-based display index for a single-select table, an index array when multi. A programmatic elem.selected = ... write does not fire it.
              #optdatumhue.ui.TextInputOptions options table

              Inherits all fields of ui.NodeStyle.

              • value : string optional — Initial text content (default empty). Read/write later via the text property.
              • 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 (default false).
              • 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 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 optional — Select all the text when the field gains keyboard focus (default false).
              • enabled : boolean optional — Whether it starts enabled (default true). A disabled input ignores keyboard and pointer input until elem.enabled = true.
              • on_change : function optional — Called with the new text (string) on each user edit. A programmatic elem.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 (default false). 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.
              #optdatumhue.voxel.FillNoiseOptions options table
              • 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.
              #optdatumhue.voxel.HeightmapOptions options table
              • 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.
              #optdatumhue.voxel.NewOptions options table
              • 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. Requires physics.
              • collides_with : integer[] optional — Collision filter: only collide with bodies in these layer bit indices 0..=31. Omitted = all. Requires physics.
              #optdatumhue.voxel.PaletteOptions options table
              • 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 via voxel:atlas. At most one of texture / frames.
              • frames : integer[] optional — Animated tile sequence shown on every face, advancing at fps.
              • fps : number optional — Animation frames per second (default 4).
              #optdatumhue.voxel.PlayOptions options table
              • 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.
              #optdatumhue.voxel.RaycastHit options table
              • 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.
              #optdatumhue.voxel.Region options table
              • min : Vec3 — Minimum cell corner (inclusive).
              • max : Vec3 — Maximum cell corner (inclusive, clamped to the volume).
              #optdatumhue.voxel.StampGridOptions options table
              • grid : Grid — 2D source; its (x, y) maps onto the plane's axes.
              • plane : voxel.StampPlane — Slice orientation: xz is a floor plan at height at, xy a wall at depth at, zy a wall at column at.
              • 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.
              #optdatumhue.voxel.StampImageOptions options table
              • image : Image — Pixel source; must carry readable pixel data.
              • plane : voxel.StampPlane — Slice orientation (see stamp_grid).
              • at : integer — The fixed coordinate of the slice.
              #optdatumhue.voxel.TextureFaces options table
              • 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.
              #optdatumhue.voxel.WorldOptions options table
              • 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; fill chunk.voxel with content or restore a snapshot via chunk: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. Persist data and hand it back to chunk:write on the next load.
              #optdatumhue.wm.FrameInsets options table
              • 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).
              #optdatumhue.wm.SetAppBoundsOptions options table
              • 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.
              #optdatumhue.wm.SetAppMinimizedOptions options table
              • app : App — The managed app to minimize or restore.
              • minimized : boolean — true to minimize, false to restore.
              #optdatumhue.wm.SetAppWeightOptions options table
              • app : App — The managed app whose layout weight to set.
              • weight : number — Relative layout weight among siblings.
              String enums84
              #enumdatumhue.Dir.EntryKind

              One of "file", "dir"

              #enumdatumhue.Easing

              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"

              #enumdatumhue.FontScript

              One of "Arab", "Hebr", "Cyrl", "Deva", "Beng", "Thai", "Hani"

              #enumdatumhue.FontStyle

              One of "normal", "italic", "oblique"

              #enumdatumhue.FontWeight

              One of "thin", "extralight", "light", "regular", "normal", "medium", "semibold", "bold"

              #enumdatumhue.ReadyState

              One of "pending", "ready", "failed"

              #enumdatumhue.StatKey

              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.
              #enumdatumhue.app.Permission

              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.
              #enumdatumhue.app.PreopenMode

              One of "r", "rw"

              #enumdatumhue.audio.Waveform

              One of "sine", "square", "triangle", "sawtooth", "noise"

              #enumdatumhue.chart.AxisSide

              One of "bottom", "left", "top", "right"

              #enumdatumhue.chart.BandAxis

              One of "x", "y"

              #enumdatumhue.chart.BarsAggregate

              One of "sum", "mean", "min", "max", "count"

              #enumdatumhue.chart.BarsMode

              One of "stacked", "grouped"

              #enumdatumhue.chart.BrushAxis

              One of "x", "y", "both"

              #enumdatumhue.chart.HeatAggregate

              One of "count", "sum", "mean"

              #enumdatumhue.chart.Histogram2dNormalize

              One of "count", "fraction"

              #enumdatumhue.chart.HistogramNormalize

              One of "count", "fraction", "density"

              #enumdatumhue.chart.LegendAnchor

              One of "top_left", "top_right", "bottom_left", "bottom_right", "top_center", "bottom_center"

              #enumdatumhue.chart.LegendKind

              One of "items", "gradient"

              #enumdatumhue.chart.Orientation

              One of "vertical", "horizontal"

              #enumdatumhue.chart.Palette

              One of "viridis", "plasma", "inferno", "magma", "turbo", "diverging"

              #enumdatumhue.chart.ReadoutMode

              One of "interpolate", "nearest"

              #enumdatumhue.chart.TextAnchor

              One of "center", "top_left", "top_center", "top_right", "center_left", "center_right", "bottom_left", "bottom_center", "bottom_right"

              #enumdatumhue.chart.TitleAlign

              One of "left", "center", "right"

              #enumdatumhue.chart.TitleSide

              One of "top", "bottom"

              #enumdatumhue.color.MixSpace

              One of "oklab", "oklch", "linear", "srgb", "hsl"

              #enumdatumhue.data.DownsampleStrategy

              One of "none", "lttb_pixel", "stride", "bin_2d"

              #enumdatumhue.data.Dtype

              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.
              #enumdatumhue.dialogue.DriveEvent

              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.
              #enumdatumhue.documents.GrantMode

              One of "read", "write"

              #enumdatumhue.documents.SchemaFieldType

              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`.
              #enumdatumhue.documents.Scope

              One of "local", "network"

              #enumdatumhue.draw.LineBreak

              One of "word", "character", "word_or_character", "none"

              #enumdatumhue.draw.TextAlign

              One of "left", "center", "right", "justified"

              #enumdatumhue.events.EventName

              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"

              #enumdatumhue.grid.DistanceType

              One of "euclidean", "manhattan", "chebyshev"

              #enumdatumhue.image.BlendMode

              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.
              #enumdatumhue.image.Filter

              One of "nearest", "linear"

              #enumdatumhue.input.CursorIcon

              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"

              #enumdatumhue.input.GamepadButton

              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"

              #enumdatumhue.input.InputSource

              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.
              #enumdatumhue.input.Key

              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"

              #enumdatumhue.input.MouseButton

              One of "left", "right", "middle", "back", "forward"

              #enumdatumhue.input.StickSide

              One of "left", "right"

              #enumdatumhue.material.AlphaMode

              One of "opaque", "mask", "blend", "premultiplied", "add", "multiply"

              #enumdatumhue.messaging.Scope

              One of "local", "network"

              #enumdatumhue.noise.CellularDistance

              One of "euclidean", "euclidean_sq", "manhattan", "hybrid"

              #enumdatumhue.noise.CellularReturn

              One of "cell_value", "distance", "distance2", "distance2_add", "distance2_sub", "distance2_mul", "distance2_div"

              #enumdatumhue.noise.FractalType

              One of "fbm", "ridged", "ping_pong"

              #enumdatumhue.noise.NoiseSource

              One of "perlin", "simplex", "simplex_smooth", "value", "value_cubic"

              #enumdatumhue.packages.InstallChangeKind

              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.
              #enumdatumhue.packages.Kind

              One of "app", "library", "asset_pack"

              #enumdatumhue.particles.Blend

              One of "alpha", "add"

              #enumdatumhue.particles.ShapeKind

              One of "point", "sphere", "box", "cone"

              #enumdatumhue.particles.Space

              One of "world", "local"

              • "world" — Spawned particles stay put when the emitter moves.
              • "local" — Spawned particles follow the emitter.
              #enumdatumhue.physics.Axis

              One of "x", "y", "z"

              #enumdatumhue.physics.BodyType

              One of "dynamic", "static", "kinematic"

              #enumdatumhue.physics.JointType

              One of "fixed", "revolute", "prismatic", "distance", "spherical"

              #enumdatumhue.physics.Shape

              One of "rect", "circle", "capsule", "convex_hull", "polyline", "cube", "sphere", "cylinder", "cone", "trimesh"

              #enumdatumhue.scene.BillboardMode

              One of "y_locked", "full", "none"

              #enumdatumhue.scene.ClipDirection

              One of "forward", "reverse", "ping_pong"

              #enumdatumhue.scene.DeformKind

              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.
              #enumdatumhue.scene.SpriteAlphaMode

              One of "cutout", "blend", "opaque", "hash"

              #enumdatumhue.scene.SpriteSizeMode

              One of "world", "screen"

              #enumdatumhue.scene.Tonemapping

              One of "none", "reinhard", "reinhard_luminance", "aces", "agx", "somewhat_boring", "blender_filmic", "tony_mcmapface", "khronos_pbr_neutral"

              #enumdatumhue.screen.FullscreenMode

              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.
              #enumdatumhue.screen.StretchMode

              One of "fill", "letterbox", "pixel_perfect"

              #enumdatumhue.shader.ShaderType

              One of "solid", "gradient", "radial_gradient", "animated_glow", "glassmorphism", "scanline", "noise", "border", "checkerboard", "stripe", "dissolve", "outline", "wave", "color_ramp"

              #enumdatumhue.theme.ColorToken

              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"

              #enumdatumhue.theme.MetricToken

              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"

              #enumdatumhue.ui.AlignContent

              One of "default", "start", "end", "flex_start", "flex_end", "center", "stretch", "space_between", "space_around", "space_evenly"

              #enumdatumhue.ui.AlignItems

              One of "default", "start", "end", "flex_start", "flex_end", "center", "baseline", "stretch"

              #enumdatumhue.ui.AlignSelf

              One of "auto", "start", "end", "flex_start", "flex_end", "center", "baseline", "stretch"

              #enumdatumhue.ui.Display

              One of "flex", "grid", "block", "none"

              #enumdatumhue.ui.FlexDirection

              One of "row", "row_reverse", "column", "column_reverse"

              #enumdatumhue.ui.FlexWrap

              One of "nowrap", "wrap", "wrap_reverse"

              #enumdatumhue.ui.ImageFit

              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.
              #enumdatumhue.ui.JustifyContent

              One of "default", "start", "end", "flex_start", "flex_end", "center", "stretch", "space_between", "space_around", "space_evenly"

              #enumdatumhue.ui.Overflow

              One of "visible", "clip", "clip_x", "clip_y", "hidden", "scroll", "scroll_x", "scroll_y"

              #enumdatumhue.ui.PickMode

              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`.
              #enumdatumhue.ui.PopoverAlign

              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.
              #enumdatumhue.ui.PopoverSide

              One of "top", "bottom", "left", "right"

              • "top" — Above the anchor.
              • "bottom" — Below the anchor.
              • "left" — Left of the anchor.
              • "right" — Right of the anchor.
              #enumdatumhue.voxel.StampPlane

              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              decode(expression, format)Decode binary data from textual representation in string.
              encode(expression, format)Encode binary data into a textual representation.

              Conditional Functions

              FunctionDescription
              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

              FunctionDescription
              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_orReturns 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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              corr(expression1, expression2)Returns the coefficient of correlation between two numeric values.
              covar_popReturns 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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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

              FunctionDescription
              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**.
              
              ![Site photo](assets/array.png)
              
              ```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 (![alt](path)) 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.

              PropertyTypeDescription
              value (required)string | messageButton label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale.
              enabledbooleanWhether 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.

              PropertyTypeDescription
              baselinenumberNumeric baseline the area fills to.
              series_columnstringCategory 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_columnstringX column name (data / view marks).
              y_columnstringY 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.
              colorcolor ("#rrggbb")Mark color.
              namestringLegend name.
              max_pointsnumberRing-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.

              PropertyTypeDescription
              axis (required)"x" | "y"Axis the [from, to] range spans.
              from (required)numberRange start (data space).
              to (required)numberRange end (data space).
              colorcolor ("#rrggbb")Fill color.

              bar

              One category of the enclosing bars mark.

              Takes no children.

              PropertyTypeDescription
              category (required)stringCategory label.
              value (required)numberBar 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.

              PropertyTypeDescription
              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_columnstringCategory column to group by (data sources).
              value_columnstringNumeric column to aggregate; required for every aggregate except count.
              series_columnstringCategory 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_paddingnumberGap between grouped sub-bars as a 0..1 fraction (default 0.1).
              orientation"vertical" | "horizontal"Bar orientation (default vertical).
              colorcolor ("#rrggbb")Bar color.
              baselinenumberNumeric baseline the bars grow from.
              namestringLegend 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.

              PropertyTypeDescription
              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_columnstringCategory column to group by (data sources).
              value_columnstringNumeric column to summarize (data sources).
              box_widthnumberBox 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.
              colorcolor ("#rrggbb")Box and whisker color.
              median_colorcolor ("#rrggbb")Median line color (defaults to black).
              outlier_colorcolor ("#rrggbb")Outlier point color (defaults to the box color).
              namestringLegend 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.

              PropertyTypeDescription
              category (required)stringCategory label.
              low (required)numberLower whisker.
              q1 (required)numberFirst quartile.
              median (required)numberMedian.
              q3 (required)numberThird quartile.
              high (required)numberUpper whisker.

              cell

              One categorical cell of the enclosing heatmap.

              Takes no children.

              PropertyTypeDescription
              x (required)stringX-axis category.
              y (required)stringY-axis category.
              value (required)numberCell magnitude.

              heatmap

              A categorical heatmap on the enclosing chart; cell children are its data.

              Children: cell only.

              PropertyTypeDescription
              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_columnstringCategory column for cell columns (data sources).
              y_columnstringCategory column for cell rows (data sources).
              value_columnstringValue 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.
              namestringLegend 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.

              PropertyTypeDescription
              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.
              columnstringColumn to bin (data sources).
              binsnumber | stringBin count, or "auto" (default) for width-by-spread with a count floor. Mutually exclusive with bin_width.
              bin_widthnumberExplicit 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.
              colorcolor ("#rrggbb")Bar color.
              namestringLegend 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.

              PropertyTypeDescription
              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_columnstringNumeric column for x (data sources).
              y_columnstringNumeric column for y (data sources).
              x_binsnumber | stringBin count for x, or "auto" (default).
              y_binsnumber | stringBin 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.
              namestringLegend 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.

              PropertyTypeDescription
              series_columnstringCategory 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_columnstringX column name (data / view marks).
              y_columnstringY 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.
              colorcolor ("#rrggbb")Mark color.
              namestringLegend name.
              max_pointsnumberRing-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.

              PropertyTypeDescription
              value (required)numberThe outlier value (data space).

              point

              One data point of the enclosing mark.

              Takes no children.

              PropertyTypeDescription
              x (required)numberX value (data space).
              y (required)numberY value (data space).

              points

              A scatter (dots) mark on the enclosing chart; point children are its data.

              Children: point only.

              PropertyTypeDescription
              sizenumberDot size.
              size_columnstringColumn 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_columnstringColumn 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_columnstringX column name (data / view marks).
              y_columnstringY 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.
              colorcolor ("#rrggbb")Mark color.
              namestringLegend name.
              max_pointsnumberRing-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.

              PropertyTypeDescription
              orientation (required)"vertical" | "horizontal"Reference-line direction.
              value (required)number | stringData-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.
              colorcolor ("#rrggbb")Line color.
              value_labelstringOptional 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.

              PropertyTypeDescription
              namestringLegend name.
              colorcolor ("#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.

              PropertyTypeDescription
              x (required)numberX position (data space).
              y (required)numberY position (data space).
              text (required)stringAnnotation text.
              colorcolor ("#rrggbb")Text color.
              font_sizenumber | stringFont 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_xnumberPixel offset X from (x, y).
              offset_ynumberPixel offset Y from (x, y).

              value

              One sample value to bin in the enclosing histogram.

              Takes no children.

              PropertyTypeDescription
              n (required)numberThe 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.

              PropertyTypeDescription
              valuestringLabel shown beside the box; omit for a bare checkbox.
              checkedbooleanWhether it starts checked (default false).
              enabledbooleanWhether 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.

              PropertyTypeDescription
              colorcolor ("#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.

              PropertyTypeDescription
              var (required)stringLoop variable name.
              in (required)stringA Lua expression evaluating to an array table.

              if

              Renders its children when cond evaluates truthy.

              Children: any element.

              PropertyTypeDescription
              cond (required)stringA 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.

              PropertyTypeDescription
              file (required)stringPage path inside the book.

              label

              A text label; the positional argument is the content.

              Takes no children.

              PropertyTypeDescription
              valuestring | messageText content — a plain string, or a datumhue.i18n.t(...) message that follows the active locale and re-renders when it changes.
              font_sizenumber | stringFont size: a number (pixels) or a unit string like "1.5rem"/ "50vw"/"4vmin" (defaults to the theme's normal text size).
              colorcolor ("#rrggbb")Text color; defaults to the theme text color. Pass a datumhue.theme.token(...) to follow the theme and repaint on change.
              strikethroughbooleanDraw a line through the text (default false). Also a read/write property.
              underlinebooleanDraw a line under the text (default false). Also a read/write property.
              font_weightnumberFont 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.

              A link; the positional argument is the text and url is the destination. Clicking opens it in a new browser tab.

              Takes no children.

              PropertyTypeDescription
              value (required)string | messageLink text (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale.
              url (required)stringDestination 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.

              PropertyTypeDescription
              items{{ }} template (handle / table)Row labels as a Lua array (alternative to inline item children).
              selectednumber1-based index of the initially-selected row.
              multibooleanAllow selecting multiple rows at once (default false).
              enabledbooleanWhether 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.

              PropertyTypeDescription
              value (required)stringThe row label.

              menu

              A dropdown menu; label names the trigger button and child elements become the menu items.

              Children: any element.

              PropertyTypeDescription
              label (required)stringThe menu button's label.
              enabledbooleanWhether 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.

              PropertyTypeDescription
              valuenumberInitial value, clamped to the range (default min, or 0).
              minnumberMinimum value (default: unbounded below).
              maxnumberMaximum value (default: unbounded above).
              stepnumberAmount the -/+ steppers add or subtract (default 1).
              precisionnumberDecimal places the value is displayed and snapped to (default 0).
              enabledbooleanWhether 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.

              PropertyTypeDescription
              value (required)string | messageButton 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.
              titlestringDialog 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.
              enabledbooleanWhether 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.

              PropertyTypeDescription
              colorcolor ("#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.

              PropertyTypeDescription
              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").
              visiblebooleanWhether it starts shown (default false); toggle later via the visible property.
              light_dismissbooleanClose 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.

              PropertyTypeDescription
              options{{ }} template (handle / table)Option labels as a Lua array (alternative to inline radio children).
              selectednumber1-based index of the initially-selected option.
              enabledbooleanWhether 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.

              PropertyTypeDescription
              value (required)stringThe option label.

              row

              A panel with row flex direction.

              Children: any element.

              PropertyTypeDescription
              colorcolor ("#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.

              PropertyTypeDescription
              value (required)string | messageButton label (required) — a plain string, or a datumhue.i18n.t(...) message that follows the active locale.
              sourcestringThe 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_namestringDefault 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.
              titlestringDialog 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.
              enabledbooleanWhether 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.

              PropertyTypeDescription
              valuenumberInitial value, clamped to [min, max] (default the range midpoint).
              minnumberRange minimum (default 0).
              maxnumberRange maximum (default 1).
              stepnumberKeyboard / track-click step increment (default 0.1).
              enabledbooleanWhether 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.

              PropertyTypeDescription
              colorcolor ("#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.

              PropertyTypeDescription
              valuestringInitial text content (default empty). Read/write later via the text property.
              placeholderstringPlaceholder shown while the field is empty.
              max_lengthnumberMaximum number of characters the field accepts.
              multilinebooleanAllow multiple lines: Enter inserts a newline instead of submitting (default false).
              filterstringA 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_focusbooleanSelect all the text when the field gains keyboard focus (default false).
              enabledbooleanWhether 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.
              autofocusbooleanTake 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.

              PropertyTypeDescription
              leftnumber | stringLeft anchor (px or "%").
              rightnumber | stringRight anchor (px or "%").
              topnumber | stringTop anchor (px or "%").
              bottomnumber | stringBottom anchor (px or "%").
              widthnumber | stringWidth (px or "%").
              heightnumber | stringHeight (px or "%").
              min_widthnumber | stringMinimum width.
              max_widthnumber | stringMaximum width.
              min_heightnumber | stringMinimum height.
              max_heightnumber | stringMaximum height.
              aspect_rationumberAspect ratio (width / height).
              marginnumber | stringOuter margin: scalar, string, or {top,bottom,left,right}.
              paddingnumber | stringInner padding: scalar, string, or {top,bottom,left,right}.
              bordernumber | stringBorder widths: scalar, string, or {top,bottom,left,right}.
              flex_grownumberFlex grow factor.
              flex_shrinknumberFlex shrink factor.
              flex_basisnumber | stringFlex 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.
              gapnumber | stringShorthand for row_gap + column_gap.
              row_gapnumber | stringRow gap (overrides gap).
              column_gapnumber | stringColumn 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_colorcolor ("#rrggbb")Border color; defaults to the theme panel border. Pass a datumhue.theme.token(...) to follow the theme and repaint on change.
              border_radiusnumber | stringCorner rounding: scalar, string, or per-corner table.
              z_indexnumberStacking 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.

              TokenGroupDarkLightDescription
              panel_backgroundSurfaces0x343f440xf4f0d9Panel / card fill.
              panel_borderSurfaces0x4752580xe6e2ccPanel / card border.
              surface_sunkenSurfaces0x2d353b0xfdf6e3Recessed surface: wells, insets, trays.
              surface_raisedSurfaces0x4f585e0xe0dcc7Raised surface: cards, headers.
              surface_overlaySurfaces0x56635f0xbdc3afFloating overlay: menus, tooltips.
              selection_backgroundSurfaces0x543a480xeaedc8Selection / row-highlight background.
              focus_ringSurfaces0xa7c0800x8da101Keyboard-focus ring outline.
              button_normalButtons0x3d484d0xefebd4Button rest fill.
              button_hoverButtons0x4752580xe6e2ccButton hover fill.
              button_pressedButtons0x343f440xf4f0d9Button pressed fill.
              button_textButtons0xd3c6aa0x5c6a72Button label text.
              button_disabledButtons0x2d353b0xfdf6e3Disabled button fill.
              button_text_disabledButtons0x7a84780xa6b0a0Disabled button label text.
              checkbox_backgroundCheckbox0x2d353b0xfdf6e3Checkbox box fill when unchecked.
              checkbox_background_checkedCheckbox0xa7c0800x8da101Checkbox box fill when checked.
              checkbox_borderCheckbox0x4f585e0xe0dcc7Checkbox box border.
              checkbox_markCheckbox0x2d353b0xfdf6e3Checkbox mark drawn inside when checked.
              slider_trackSlider0x2d353b0xfdf6e3Slider track groove.
              slider_fillSlider0xa7c0800x8da101Slider filled portion left of the thumb.
              slider_thumbSlider0x4f585e0xe0dcc7Slider draggable thumb.
              radio_borderRadio0x8592890x939f91Radio option circle border (unselected).
              radio_markRadio0xa7c0800x8da101Radio inner dot + selected circle border.
              scrollbar_trackScrollbar0x2d353b0xfdf6e3Scrollbar track gutter.
              scrollbar_thumbScrollbar0x4f585e0xe0dcc7Scrollbar draggable thumb.
              list_row_selectedList0x4250470xf0f1d2Selected list row background.
              list_row_activeList0xa7c0800x8da101Active (focused) list row outline.
              input_backgroundText Input0x2d353b0xfdf6e3Text input field background.
              input_borderText Input0x4f585e0xe0dcc7Text input field border.
              input_textText Input0xd3c6aa0x5c6a72Entered text.
              input_placeholderText Input0x8592890x939f91Placeholder text shown when empty.
              input_cursorText Input0xa7c0800x8da101Text input caret.
              popover_backgroundOverlay0x3d484d0xefebd4Popover panel background.
              popover_borderOverlay0x56635f0xbdc3afPopover panel border.
              menu_backgroundOverlay0x3d484d0xefebd4Dropdown menu popup background.
              menu_borderOverlay0x56635f0xbdc3afDropdown menu popup border.
              text_primaryText0xd3c6aa0x5c6a72Primary text.
              text_secondaryText0x8592890x939f91Secondary / muted text.
              text_disabledText0x7a84780xa6b0a0Disabled / faint text.
              accent_primaryAccents0xa7c0800x8da101Primary accent (brand green).
              accent_secondaryAccents0x83c0920x35a77cSecondary accent.
              accent_dataAccents0xe698750xf57d26Data-point accent (brand orange).
              accent_tertiaryAccents0xd699b60xdf69baTertiary accent.
              successStatus0xa7c0800x8da101Success foreground.
              warningStatus0xdbbc7f0xdfa000Warning foreground.
              errorStatus0xe67e800xf85552Error foreground.
              infoStatus0x7fbbb30x3a94c5Info foreground.
              success_backgroundStatus surfaces0x4250470xf0f1d2Muted success banner surface.
              warning_backgroundStatus surfaces0x4d4c430xfaedcdMuted warning banner surface.
              error_backgroundStatus surfaces0x5140450xfde3daMuted error banner surface.
              info_backgroundStatus surfaces0x3a515d0xe9f0e9Muted info banner surface.
              accent_tertiary_backgroundStatus surfaces0x4a444e0xfae8e2Muted tertiary-accent surface.
              statusline_primaryStatus bar0xa7c0800x93b259Status bar, primary state.
              statusline_secondaryStatus bar0xd3c6aa0x708089Status bar, secondary state.
              statusline_tertiaryStatus bar0xe67e800xe66868Status bar, tertiary state.
              chart_axisChart0x8592890x939f91Axis / tick lines.
              chart_gridChart0x4752580xe6e2ccGridlines.
              chart_axis_labelChart0x9da9a00x829181Tick labels.
              chart_backgroundChart0x232a2e0xefebd4Plot-area background.
              chart_legend_backgroundChart0x2d353b0xfdf6e3Legend backing (translucent).
              chart_legend_borderChart0x4752580xe6e2ccLegend border.
              chart_legend_textChart0xd3c6aa0x5c6a72Legend text.

              metrics

              Each line is a token name followed by one number, in pixels:

              metrics {
                  padding_medium 10
                  border_radius 6
              }
              
              TokenGroupDefaultDescription
              padding_smallSpacing4 pxSmall inner padding.
              padding_mediumSpacing8 pxMedium inner padding.
              padding_largeSpacing16 pxLarge inner padding.
              input_padding_verticalSpacing6 pxVertical padding inside a text input field.
              gap_smallSpacing4 pxSmall gap between items.
              gap_mediumSpacing8 pxMedium gap between items.
              gap_largeSpacing16 pxLarge gap between items.
              border_widthBorders1 pxDefault border width.
              border_radiusBorders4 pxDefault corner radius.
              font_size_smallTypography12 pxSmall font size.
              font_size_normalTypography14 pxNormal font size.
              font_size_largeTypography16 pxLarge font size.
              font_size_headingTypography20 pxHeading / section-title font size.
              font_size_titleTypography24 pxDialog and modal title font size.
              font_size_displayTypography28 pxLargest display font size (top-level document headings, hero text).
              font_weight_normalTypography500 wghtBody text weight on the variable axis.
              font_weight_headingTypography600 wghtHeading and title weight on the variable axis.
              button_min_widthButtons80 pxMinimum button width.
              button_min_heightButtons32 pxMinimum 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.

              TypeAnimcolor1color2param1param2Description
              solidFill colorFlat fill.
              gradientStart colorEnd colorAngle in radians (0 = left-to-right)Linear gradient between two colors.
              radial_gradientInner / center colorOuter / edge colorCenter offset X (UV; 0 = centered)Center offset Y (UV; 0 = centered)Radial gradient from a center point.
              animated_glowyesBase colorGlow colorGlow intensityPulse speedBase color under a pulsing glow.
              glassmorphismGlass tint (alpha = transparency)Border highlightBorder width (0-1)Noise intensityFrosted-glass panel with a highlighted border.
              scanlineyesBase color (alpha = scanline darkness)Beam tintScanline densityBeam sweep speedCRT scanlines with a moving phosphor beam.
              noiseBase colorNoise tintNoise intensityNoise scale (higher = finer grain)Static value noise over a base color.
              borderBorder colorFill colorBorder width (UV)Corner radius (UV)Rounded border over a fill.
              checkerboardFirst colorSecond colorTile count acrossTwo-color checkerboard.
              stripeStripe colorGap colorStripe countAngle in radians (0 = horizontal)Parallel stripes.
              dissolveVisible colorEdge glow colorThreshold (0 = visible, 1 = dissolved)Edge widthThreshold burn / dissolve with a glowing edge.
              outlineFill colorOutline colorOutline width (0-1)Glow falloffFilled shape with a glowing outline.
              waveyesBase colorBlend colorWave amplitudeWave frequencyTime-distorted wave blend between two colors.
              color_rampStart colorEnd color0 = linear, 1 = steppedStep 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"
              }
              
              SlotDescription
              buttonDefault shader material for buttons.
              panelDefault 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.

              KeyVarsDefault (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-start1First 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.

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

              FieldTypeDescription
              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

              FieldTypeDescription
              timeout_frames?integerPer-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 via datumhue.args.argv

              Options:

              • [--bootstrap <NAME>] — Bootstrap package to launch. Falls back to DATUMHUE_BOOTSTRAP_PACKAGE
              • [--namespace <NAME>] — Catalog namespace to bootstrap from. The bootstrap package and datumhue.packages queries resolve against this namespace. Falls back to DATUMHUE_BOOTSTRAP_NAMESPACE, then datumhue
              • [--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] — Allow datumhue.debug.input for 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 as datumhue.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 as datumhue.args.data_mounts.<name> and runs SQL queries via mount: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 as datumhue.args.http_mounts.<name> and makes requests via mount:get(path) / mount:post(path, opts) etc
              • [--ingress-mount <NAME:MOUNT>] — Grant an ingress mount capability (NAME:MOUNT). The script reaches it as datumhue.args.ingress_mounts.<name> and subscribes to its channel via mount: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 .lua script, package directory, or .dhpkg archive to run. Defaults to the current directory (default: .)
              • [<SCRIPT_ARGS>] — Everything after -- reaches the script via datumhue.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 as datumhue.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 as datumhue.args.data_mounts.<name> and runs SQL queries via mount: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 as datumhue.args.http_mounts.<name> and makes requests via mount:get(path) / mount:post(path, opts) etc
              • [--ingress-mount <NAME:MOUNT>] — Grant an ingress mount capability (NAME:MOUNT). The script reaches it as datumhue.args.ingress_mounts.<name> and subscribes to its channel via mount:subscribe({callback = ...})
              • [--service] — Run the script as a service app — no UI, and the UI subtables of datumhue are unavailable. Only applies to a .lua file; for a package directory or .dhpkg archive the manifest's own service field is authoritative and passing this flag errors
              • [--debug-input] — Allow datumhue.debug.input for 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; use 127.0.0.1:0 to 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 as datumhue.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 as datumhue.args.data_mounts.<name> and runs SQL queries via mount: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 as datumhue.args.http_mounts.<name> and makes requests via mount:get(path) / mount:post(path, opts) etc
              • [--ingress-mount <NAME:MOUNT>] — Grant an ingress mount capability (NAME:MOUNT). The script reaches it as datumhue.args.ingress_mounts.<name> and subscribes to its channel via mount: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 contain package.kdl. Defaults to the current directory (default: .)

              Options:

              • [--out <PATH>] — Destination .dhpkg path. If omitted, the archive is written next to source as <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, stamps licensed-to into the packed manifest, and writes the redistributable <scope>-<name>.dhruntime binding 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. Give NAME:PATH, where NAME matches a requires_plugin entry 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 .dhpkg file 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 .dhpkg file 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 .dhpkg file 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 .dhpkg file 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>.dhpkg archive 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>] — Manifest kind. The refinements (theme, book, dataset, ...) scaffold as asset_pack packages with the matching content_type (default: app)
              • [--service] — Scaffold a service app: sets service #true in the manifest and uses an init.lua template 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 contain package.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 contain package.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 a tests/ 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 via datumhue.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's tests/test.kdl timeout-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 send launch
              • [--dap-listen <HOST:PORT>] — Address for the --dap listener (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 as datumhue.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 as datumhue.args.data_mounts.<name> and runs SQL queries via mount: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 as datumhue.args.http_mounts.<name> and makes requests via mount:get(path) / mount:post(path, opts) etc
              • [--ingress-mount <NAME:MOUNT>] — Grant an ingress mount capability (NAME:MOUNT). The script reaches it as datumhue.args.ingress_mounts.<name> and subscribes to its channel via mount: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 a tests/ 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 via datumhue.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's tests/test.kdl timeout-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 an a and b condition 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 as datumhue.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 as datumhue.args.data_mounts.<name> and runs SQL queries via mount: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 as datumhue.args.http_mounts.<name> and makes requests via mount:get(path) / mount:post(path, opts) etc
              • [--ingress-mount <NAME:MOUNT>] — Grant an ingress mount capability (NAME:MOUNT). The script reaches it as datumhue.args.ingress_mounts.<name> and subscribes to its channel via mount: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 enclosing workspace.kdl in 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 --out when 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 contain package.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 enclosing workspace.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

              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 in pkg 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/name to 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 .dhlicense file

              datumhue license apply

              Verify a license file and install it so DatumHue runs under it

              Arguments:

              • <PATH> — Path to the .dhlicense file

              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 by data-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 --out when 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 by http-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 --out when 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 by ingress 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 --out when 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 by identity 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 .lua script, package directory, or .dhpkg archive to load before the prompt. Omit for an empty service app
              • [<SCRIPT_ARGS>] — Tokens forwarded to the loaded script via datumhue.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 as datumhue.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 as datumhue.args.data_mounts.<name> and runs SQL queries via mount: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 as datumhue.args.http_mounts.<name> and makes requests via mount:get(path) / mount:post(path, opts) etc
              • [--ingress-mount <NAME:MOUNT>] — Grant an ingress mount capability (NAME:MOUNT). The script reaches it as datumhue.args.ingress_mounts.<name> and subscribes to its channel via mount:subscribe({callback = ...})
              • [--service] — Run the loaded .lua script as a service app. Same meaning as datumhue 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 --out when 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.