zgx

API index

Every function and value of ui and anime, with the type luau-lsp checks it against, read from zgx.d.luau when the site builds.

Each entry is a member of declare ui or declare anime in zgx.d.luau, the definitions zgx check gives luau-lsp, with the comment it carries there. A name links to the page that covers it.

ui

ui.theme
ThemeApi
ui.prefers
{ reduced_motion: Readable<boolean>, more_contrast: Readable<boolean>, reduced_transparency: Readable<boolean> }
The system's display settings, as CSS's media queries read them (prefers-reduced-motion, prefers-contrast: more, prefers-reduced-transparency): each follows the system (:get() tracked). The themes' tokens already take them (zero motion durations, stronger borders, opaque glass); read them for the rest.
ui.every
(ms: number, fn: () -> ...unknown) -> () -> ()
Call fn every ms milliseconds on zgx's clock (no frames between); returning false stops it. Returns a function that stops it. It lives as long as what made it: a component, a builder, or the script.
ui.after
(ms: number, fn: () -> ()) -> () -> ()
Call fn once, after ms milliseconds; returns a function that cancels it.
ui.column
(props: ContainerProps?) -> Node
ui.row
(props: ContainerProps?) -> Node
ui.div
(props: ContainerProps?) -> Node
ui.overlay
(props: ContainerProps?) -> Node
Children stack in one box, each aligned on its own.
ui.button
(props: ContainerProps?) -> Node
ui.grid
(props: ContainerProps?) -> Node
A div with grid = true.
ui.scroll
(props: ScrollProps?) -> Node
ui.scroll_x
(props: ScrollProps?) -> Node
ui.text
(content: Text | TextProps) -> Node
ui.span
(content: Text | SpanProps) -> Span
ui.rich
(props: RichProps) -> Node
ui.image
(props: ImageProps) -> Node
ui.svg
(props: SvgProps) -> Node
ui.canvas
(props: CanvasProps) -> Node
ui.webview
(props: WebViewProps) -> Node
ui.web
((opts: WebOptions?) -> Web) & ((id: string, opts: WebOptions?) -> Web)
ui.web(opts): a page for this run. ui.web(id, opts): the host's page for id, made with opts the first time, kept across reloads.
ui.terminal
(props: TerminalProps) -> Node
ui.term
(id: string, opts: TermOptions?) -> Term
The session for id, started the first time; ui.term(id) without options only looks it up.
ui.command
(opts: CommandOptions) -> ()
ui.shortcut_text
(keys: string) -> string
Keys ("cmd+shift+z") as this platform shows them: "⇧⌘Z" on macOS, "Ctrl+Shift+Z" elsewhere (cmd is Command on macOS, Control elsewhere); a lone modifier ("cmd") as itself, "⌘" or "Ctrl".
ui.window
WindowApi
ui.checkbox
(props: CheckboxProps) -> Node
ui.input
(props: InputProps) -> Node
ui.textarea
(props: InputProps) -> Node
ui.progress
(props: ProgressProps) -> Node
ui.slider
(props: SliderProps) -> Node
ui.split
(props: SplitProps) -> Node
Resizable panes: ui.split { size = width, Sidebar(), Content() }; the divider drags (no script runs), takes the arrow keys focused, and resets on a double click.
ui.segmented
(props: SegmentedProps) -> Node
ui.tabs
(props: TabsProps) -> Node
ui.tree
(props: TreeProps) -> Node
ui.data_grid
(props: DataGridProps) -> Node
ui.calendar
(props: CalendarProps) -> Node
ui.date_picker
(props: DatePickerProps) -> Node
ui.time_field
(props: TimeFieldProps) -> Node
ui.combobox
(props: ComboboxProps) -> Node
ui.command_palette
(props: CommandPaletteProps) -> Node
ui.select
(props: SelectProps) -> Node
ui.stepper
(props: StepperProps) -> Node
ui.disclosure
(props: DisclosureProps) -> Node
ui.accordion
(props: AccordionProps) -> Node
ui.section
(props: SectionProps) -> Node
An accordion's section: ui.section { id = "a", title = "Shipping", … }.
ui.separator
(props: SeparatorProps?) -> Node
A line between groups, across (vertical = true: down a toolbar).
ui.modal
(props: ModalProps) -> Node
ui.layer
(props: LayerProps) -> Node
Over the window and non-modal (toasts): no focus, no backdrop; the pointer passes through but for what it holds, which stays live while a dialog holds focus. Raised over everything as it opens (open, a state; open unless given).
ui.popover
(props: PopoverProps) -> Node
ui.menu
(props: PopoverProps) -> Node
ui.menu_item
(props: MenuItemProps) -> Node
ui.submenu
(props: SubmenuProps) -> Node
ui.list
(props: ListProps) -> Node
ui.show
(cond: boolean | Readable<unknown> | (() -> unknown), node: Node, otherwise: Node?) -> Node
node while cond is truthy, else otherwise (or nothing).
ui.switch
(value: string | Readable<unknown> | (() -> unknown), cases: { [CaseKey]: Node }, default: Node?) -> Node
ui.each
(list: State<{ any }>, build: (item: any, index: number, row: State<any>) -> Node, opts: EachOptions?) -> Node
A row per item of a list state; build gets the item and its index (from 1). The item is any: annotate it to check it, function(tab: Tab, i) (Luau infers a generic callback's parameter from its uses, which misfires). A row whose item changes is built again; a build taking a third parameter gets the row's item as state instead, kept current, and its row updates in place.
ui.presence
(value: string | Readable<unknown> | (() -> unknown), build: (value: any) -> Node, opts: PresenceOptions?) -> Node
What build makes of the value, entering and exiting as it changes; nil shows nothing. The value is any, as each's item is.
ui.slot
(name: string, props: SlotProps?) -> Node
Where plugins' contributions to name go. A plugin extension point. context reaches what is contributed to it: a contributed component gets it as props.slot (one component, an instance per slot: a panel per pane).
ui.contribute
(name: string, node: Node) -> ()
ui.state
<T>(key: string, initial: T) -> State<T>
The script's (or module's) state for key, kept across reloads.
ui.shared
<T>(key: string, initial: T) -> State<T>
State shared with Rust and every script.
ui.persist
<T>(key: string, initial: T) -> State<T>
State saved across runs, in the host's storage (ScriptHost::app_id).
ui.use_state
<T>(initial: T) -> State<T>
A component instance's own state.
ui.computed
<T>(f: () -> T) -> State<T>
ui.sorted
(list: State<any>, spec: SortedSpec<any> | (() -> SortedSpec<any>)) -> State<any>
A list state's items in order, kept in order as it changes: a write re-places the items it wrote (by and filter called for those alone), and a new spec (a spec function's reads changed) sorts it all again. by is a field's name (read in Rust) or a function of an item; filter keeps the items it is true for. (Annotate the view's type: local view: State<{ Row }> = ui.sorted(rows, …).)
ui.variants
<D>(definition: D) -> (choice: VariantChoice<D, Readable<any> | (() -> any)>) -> Variants
A component's styles by variant (shadcn's cva): base, then the chosen option of each axis in variants (by name), then the matching compound rules, then the element's own properties; each replaces what it covers (p an earlier px). Returns a recipe: call it with the options (names, or states or functions choosing them) and give the result to an element as variants = ….
ui.raw
<T>(value: T, reason: string) -> T
A style value the design lint lets through, with the reason.
ui.markdown
(text: string, opts: MarkdownOptions?) -> { MarkdownBlock }
Markdown parsed into blocks (t: p, h, code, ul, ol, quote, hr, table, img; runs { x, b?, i?, c?, s?, a?, f? }). With key (a reply's id), text growing under it parses only its new end, and its earlier blocks are the same tables as before.
ui.markdown_view
(props: MarkdownViewProps) -> Node
Markdown drawn: paragraphs, headings, lists, quotes, tables, and code blocks with a Copy button, in the theme's colours and sizes, selectable. As its text changes it parses only what changed and builds only the blocks that did: a reply streaming in grows by its last block.
ui.effect
(f: () -> ...unknown) -> ()
ui.batch
<R...>(f: () -> R...) -> R...
One update for many writes; returns what f returns.
ui.on_mount
(f: () -> ...unknown) -> ()
Runs once it is mounted: a component instance, or (outside one) the app's interface, again after each reload.
ui.ref
() -> Ref
ui.component
<P>(build: (props: P) -> Node) -> (props: P) -> Node
Card { title = "…", child }: build(props) runs as each instance mounts; children also arrive as props.children. Annotate props with your own type (and [number]: Child if it takes children).
ui.action
(name: string, arg: unknown?) -> Action
A host action (ScriptHost::action) as a handler. arg is plain data (what state holds: no functions); Luau cannot say so of a table typed as a record, so it is unknown here.
ui.invoke
(name: string, arg: unknown?) -> ()
Call a host action now.
ui.null
any
JSON's null, as a value that keeps its key in a table (nil drops it): { caps = ui.null } reaches Rust as {"caps": null}.
ui.on_cleanup
(f: () -> ()) -> ()
Runs f when what is being built goes away: a component unmounting, an effect running again, the script reloading.
ui.use_context
(name: string, default: any?) -> any
In a component's, row's or presence's build: what the nearest provide = { [name] = … } above it gave, else default.
ui.now
() -> number
Milliseconds since the epoch, to the microsecond (os.time counts whole seconds). Not tracked.
ui.object
<T>(t: T?) -> T
t (or a new table) marked a JSON object: empty, it sends {}, not [] (a Lua table can't tell). An empty object from the host comes marked, so it goes back as one.
ui.call_sync
(name: string, arg: unknown?) -> any
A host function's value, now (ScriptHost::function): a read of data the host keeps, so large data is never copied into the script whole.
ui.call
(name: string, arg: unknown?) -> Promise
Call a host action for its result (ScriptHost::async_action; a plain action settles at once with nil): a promise of what it returns.
ui.task
<A...>(f: (A...) -> (), A...) -> Task
Run f(...) as a task: p:await() inside it waits for a promise without blocking anything else. Its handle cancels it.
ui.try
<T, A...>(f: (A...) -> ...T, A...) -> (T?, string?)
f(...)'s value and nil, or nil and what it raised, as a string a person reads (an error's text, no traceback): pcall with its error typed. Awaits inside f work in a task, as through pcall.
ui.resource
<T>(load: () -> T, opts: { initial: T }?) -> Resource<T>
What load returns, loaded in a task (it may await), as states: data, loading, error and status. It loads again on reload() and when a state it read before its first await changes; only the last load's answer is kept. initial: data until one answers.
ui.form
(spec: FormSpec) -> Form
A form's fields, checked as they are typed, and its submit with its pending and failure states; controls bind with field.
ui.fetch
(url: string, opts: FetchOptions?) -> Promise<Response>
An HTTP request through the host's transport (ScriptHost::fetcher): a promise of a Response. A plugin needs the host's grant.
ui.clipboard
{ read: () -> string?, write: (text: string) -> boolean, read_image: () -> Promise<Bitmap?>, write_image: (image: Bitmap) -> Promise<boolean> }
The clipboard's text (nil if it holds none), and putting text on it; its image as a Bitmap (nil if it holds none), and putting one on it: promises, as a large image is decoded and encoded off the main thread.
ui.open_files
(opts: FilePickerOptions?) -> Promise<{ File }>
The files the user picks: a promise of a list of File (empty if they cancel).
ui.save_file
(opts: FilePickerOptions?) -> Promise<File?>
Where the user chooses to save: a promise of a File, or nil.
ui.read_file
(file: File | string) -> Promise<string>
A file the user picked, read as text off the main thread: a promise.
ui.write_file
(file: File | string, text: string) -> Promise<nil>
Write text to a file the user picked (beside it, then over it).
ui.args
{ string }
What the app was launched with after its script (zgx-run app/ notes.txt gives { "notes.txt" }).
ui.on_open
(handler: (e: { files: { File }, urls: { string } }) -> ()) -> ()
Files and URLs the system asks the app to open (a file opened with it, a link to it, a second launch's), the launch's included: the files are the user's choice, as a dialog's are (ui.read_file takes them). The app's only: a plugin's is an error.
ui.set
<T>(state: { read set: (self: any, value: T) -> () }, value: T) -> Action
T comes from the state's set, so a literal fits a state of a union (ui.set(density, "compact") for "comfortable" | "compact") and anything else is still an error.
ui.toggle
(state: State<boolean>) -> Action
ui.add
(state: State<number>, by: number?) -> Action
ui.tween
(state: State<any>, opts: TweenOptions?) -> Binding
The state's truthiness (or number) drives a 0-to-1 scalar, or from to to. Durations are milliseconds, as in anime.
ui.spring
(state: State<any>, opts: SpringOptions?) -> Binding
ui.loop
(opts: LoopOptions?) -> Binding
ui.bitmap
(w: number, h: number, alpha: (x: number, y: number) -> number) -> Bitmap
White pixels with the alpha alpha(x, y) gives (0 to 1), for masks.
ui.shader
(source: string, opts: { fps: number? }?) -> Shader
A WGSL fill: fn fill(input: FillInput) -> vec4<f32>, with input.p, input.size, input.time, input.scale and input.params (four vec4s).
ui.sort
<T>(list: { T }, by: string | (item: T) -> any, descending: boolean?) -> { T }
Sorts list in place, stably, by a field of each item ("price") or a function of it (called once an item); returns it. Use it over table.sort with a comparator for long lists: that calls Luau some 1.7 million times for 100,000 rows. Nil keys go last.
ui.toast
(opts: ToastOptions) -> number
A toast in the window's corner: it goes after duration ms (5000; 7000 a warning; an error stays), or at its ×. Returns its id.
ui.dismiss_toast
(id: number) -> ()
ui.json
{ encode: (value: any, opts: { pretty: boolean? }?) -> string, decode: (text: string) -> any }
JSON: encode(value, { pretty = true }) writes what state could hold (lists as arrays, tables as objects, ui.null as null); decode(text) gives tables the script may change, and fails saying where.
ui.number
(n: number, opts: NumberOptions?) -> string
n formatted, as Intl.NumberFormat would: ui.number(1234.5) is "1,234.50", { style = "percent" } takes a fraction (0.05 is "5%"), { notation = "compact" } gives "1.2K", { sign = "always" } "+3".
ui.path
() -> Path
ui.linear
(x1: number, y1: number, x2: number, y2: number, colors: { read [number]: Color }) -> Brush

anime

anime.animate
((targets: ElementTargets, params: ElementParams) -> Animation) & ((targets: State<any> | { [string]: any }, params: TableParams) -> Animation)
anime.createTimeline
(params: TimelineParams?) -> Animation
anime.timeline
(params: TimelineParams?) -> Animation
anime.js v3's name.
anime.createTimer
(params: Timing?) -> Animation
Endless unless given a duration.
anime.createAnimatable
(targets: ElementTargets | State<any> | { [string]: any }, params: { [string]: number | Ease | Modifier | Composition | Tween }) -> Animatable
anime.createDraggable
(target: ElementTargets, params: DraggableParams?) -> Draggable
anime.onScroll
(params: ScrollParams?) -> ScrollObserver
anime.stagger
(value: number | string | { read [number]: number | string }, params: StaggerParams?) -> Stagger
A value (5, "1rem") or a range ({ -100, 100 }).
anime.createSpring
(params: { mass: number?, stiffness: number?, damping: number?, velocity: number? }?) -> AnimeEase
anime.spring
(params: { bounce: number?, duration: number? }?) -> AnimeEase
A spring of that perceived bounce, settling in duration ms.
anime.createScope
(params: { defaults: Merge<Timing, { [string]: AnimValue }>? }?) -> Scope
anime.eases
{ linear: EaseMaker, none: EaseMaker, ["in"]: EaseMaker, out: EaseMaker, inOut: EaseMaker, outIn: EaseMaker, inQuad: EaseMaker, outQuad: EaseMaker, inOutQuad: EaseMaker, outInQuad: EaseMaker, inCubic: EaseMaker, outCubic: EaseMaker, inOutCubic: EaseMaker, outInCubic: EaseMaker, inQuart: EaseMaker, outQuart: EaseMaker, inOutQuart: EaseMaker, outInQuart: EaseMaker, inQuint: EaseMaker, outQuint: EaseMaker, inOutQuint: EaseMaker, outInQuint: EaseMaker, inSine: EaseMaker, outSine: EaseMaker, inOutSine: EaseMaker, outInSine: EaseMaker, inCirc: EaseMaker, outCirc: EaseMaker, inOutCirc: EaseMaker, outInCirc: EaseMaker, inExpo: EaseMaker, outExpo: EaseMaker, inOutExpo: EaseMaker, outInExpo: EaseMaker, inBounce: EaseMaker, outBounce: EaseMaker, inOutBounce: EaseMaker, outInBounce: EaseMaker, inBack: EaseMaker, outBack: EaseMaker, inOutBack: EaseMaker, outInBack: EaseMaker, inElastic: EaseMaker, outElastic: EaseMaker, inOutElastic: EaseMaker, outInElastic: EaseMaker, steps: EaseMaker, cubicBezier: EaseMaker, irregular: EaseMaker }
anime.engine
{ speed: number, playbackRate: number, -- nil: every display frame. fps: number?, timeUnit: "ms" | "s", read currentTime: number, read paused: boolean, pause: () -> (), resume: () -> () }
anime.utils
{ set: (targets: ElementTargets | State<any> | { [string]: any }, params: { [string]: AnimValue }) -> (), -- The current value: a number (angles in degrees) or a string. get: (target: ElementTargets | State<any> | { [string]: any }, property: string) -> (number | string)?, -- Stops every animation of the targets. remove: (targets: ElementTargets | State<any> | { [string]: any }) -> (), -- Animated values return to the node's own: all, or the named ones. cleanInlineStyles: (targets: ElementTargets | Animation, props: (string | { string })?) -> (), -- Without decimals, whole bounds give whole numbers. random: (min: number?, max: number?, decimals: number?) -> number, randomPick: <T>(items: { T }) -> T?, shuffle: <T>(items: { T }) -> { T }, -- `round(value, decimals)`; `round(decimals)` is a modifier. round: ((value: number, decimals: number) -> number) & ((decimals: number) -> AnimeModifier), clamp: (value: number, min: number, max: number) -> number, snap: (value: number, step: number) -> number, wrap: (value: number, min: number, max: number) -> number, mapRange: (value: number, inLow: number, inHigh: number, outLow: number, outHigh: number) -> number, lerp: (a: number, b: number, t: number) -> number, -- Frame-rate independent `lerp`: `dt` in ms. damp: (a: number, b: number, dt: number, factor: number) -> number, degToRad: (deg: number) -> number, radToDeg: (rad: number) -> number, roundPad: (value: number, decimals: number) -> string, padStart: (value: string | number, length: number, pad: string?) -> string, padEnd: (value: string | number, length: number, pad: string?) -> string, createSeededRandom: (seed: number?) -> (min: number?, max: number?, decimals: number?) -> number }
anime.svg
{ -- Animate `x` (or translateX), `y` and `rotate` with these to follow -- the path. createMotionPath: (d: string) -> { translateX: MotionPathValue, translateY: MotionPathValue, rotate: MotionPathValue, x: MotionPathValue, y: MotionPathValue, length: number }, getTotalLength: (d: string) -> number }
anime.text
{ -- A row of one text per character (`chars`) or word (`words`), each -- with a class to animate; `style` styles each piece, `props` the row. split: (text: string, params: { words: (boolean | { class: string? })?, chars: (boolean | { class: string? })?, class: string?, style: Props?, props: Props? }?) -> Node }
Edit on GitHub