Compile-time functions
The functions of brumate/signals describe state and behavior to the compiler. The compiler replaces every call and removes the import, so none of them ship.
import { $memo, $signal } from 'brumate/signals';
- A call needs the import. A call of a function that the file does not import is a compile error.
- A renamed import works, as in
import { $signal as signal } from 'brumate/signals'. - They work only in
.brmfiles. A call anywhere else throws. - "Top level of a script" means a statement of the component's
<script>, or of a<script>at the start of a block body. It is not inside a function or another statement.
Summary
| Function | Returns | Where | Guide |
|---|---|---|---|
$props<T>() |
T |
const in the component script |
Components |
$signal<T>(value?) |
T |
let at the top level of a script |
State |
$memo<T>(value) |
MemoValue<T> |
const at the top level of a script |
State, Async data |
$debounced(value, ms) |
MemoValue<T> |
const at the top level of a script |
Async data |
$throttled(value, ms) |
MemoValue<T> |
const at the top level of a script |
Async data |
$isPending(memo) |
boolean |
Any expression | Async data |
$isPassed(prop) |
boolean |
const in the component script |
Components |
$isBound(prop) |
boolean |
Any expression | Components |
$effect(callback) |
void |
Statement at the top level of a script | Effects |
$client(callback, trigger?) |
void |
Statement at the top level of a script | Effects |
$untrack(value) |
the value | Any expression | State |
$produce(signal, recipe) |
void |
Where a signal can be written | State |
$setContext(context, value) |
void |
Statement at the top level of a script | Context |
$getContext(context) |
the value | const at the top level of a script |
Context |
$route(path?) |
{ url, search, params } |
const at the top level of a script |
Navigation |
$navigation() |
{ pending, from, to } |
const at the top level of a script |
Navigation |
$id() |
string |
const at the top level of a script |
Page metadata |
$title(value) |
void |
Statement at the top level of a script. Replaced by <title> in #head |
Page metadata |
$action(fn) |
the result, or undefined |
const at the top level of a script |
Forms |
$optimistic(source) |
the value of source |
let at the top level of a script |
Forms |
$handler(fn, ...args) |
a handler | Any expression of a script or a module function | Components |
$props
function $props<T = Record<string, any>>(): Unbound<T>;
type Bindable<T> = T | BindableMark<T>;
Returns the props of the component.
- Assign it to a
constor alet, as a name or an object pattern. It takes no arguments. - Props from a
let, such aslet { open = false } = $props(), are props that the component writes. Without a binding, a write changes the component's own copy, and a new value from the parent replaces it. With$bindin the parent, a write goes to the parent's value. Bindable<T>in the type marks a prop that a parent can bind.$props<T>()gives it asT.- It can be called only in the component script, not in a block script.
- Destructuring the call keeps each prop reactive:
const { value } = $props(). - Server: the props that the parent passed.
- Client: a prop changes only when the parent passes a value that can change.
$signal
function $signal<T>(value: T): T;
function $signal<T>(): T | undefined;
Declares writable state. Reading the variable reads the value, and assigning to it writes the value.
- Declare it with
let, as a single name. It takes at most one argument. - Server: the initial value is computed once. It does not track what it reads.
- Client: it can be written in event handlers,
$effectand$clientcallbacks, and the functions that they call. A write anywhere else is a compile error. - Its value is sent to the browser only when client code needs it.
$memo
function $memo<T>(value: T): MemoValue<T>;
type MemoValue<T> = Awaited<T> extends AsyncIterable<infer U> ? U : Awaited<T>;
Declares a read-only value computed from other values.
- Declare it with
const, as a single name. It needs one argument.awaitcan be used in it. - A promise is awaited where the memo is read. An async iterable gives each of its values in turn.
const name = await $memo(value)makes the server wait for the memo where it is declared.await nameof a memo, in a script or in markup, makes the render around the read wait for it. In the browser both are plain reads. See Async data.- Assigning to it is a compile error.
- Server: computed when first read. Markup outside every
#loadingbody waits for a promise. A#loadingbody that reads it renders in place when it is ready, and after the rest of the page otherwise. - Client: computed again when the values it reads change. While a new promise loads, the memo keeps its old value. Only the latest run is written.
$isPending
function $isPending(memo: unknown): boolean;
True while a new value of the memo loads in the browser, or a value that it reads loads.
- Its only argument is the name of a memo.
- Server: always
false. - Client:
truefrom the start of a load until its value is written.
$isPassed
function $isPassed(prop: unknown): boolean;
True when the caller passed the prop, also as undefined or null.
- Assign it to a
constin the component script. Its argument is a prop that the component destructures. - The caller's attributes decide it, so it never changes.
- A default value does not count:
const { value = 0 } = $props()with novaluegives false. - A prop in a spread that the caller passes counts when the key is in the object.
$isBound
function $isBound(prop: unknown): boolean;
True when the caller passed the prop with $bind, so a write of it changes the caller's value.
- Its argument is a prop that the component destructures with
let. - Server: always false, because nothing writes there.
$effect
function $effect(callback: () => void | (() => void)): void;
Runs callback when the values that it reads change.
- A statement at the top level of a script. The callback takes no parameters and cannot be
async. - Server: never runs.
- Client: never runs on page load. Its first run is after the first change of a value it reads. The returned function runs before the next run and when the scope is removed.
- Reads inside functions that the callback calls count too. Wrap a call in
$untrackto read without depending on it.
$client
function $client(callback: () => void | (() => void), trigger?: 'visible' | 'idle' | 'load'): void;
Runs callback in the browser once, when a trigger fires.
| Trigger | Runs when |
|---|---|
'visible' |
The first element of the scope enters the viewport. This is the default. |
'idle' |
The browser is idle after the page loads. |
'load' |
The page loads. The compiler warns, because this runs before any event. |
- A statement at the top level of a script. The callback takes no parameters and cannot be
async. - Server: never runs.
- Client: the returned function runs when the scope is removed.
$untrack
function $untrack<T>(value: T): T;
Reads a value without depending on it. A memo or effect that reads $untrack(count) does not run again when count changes. A function called inside it, such as $untrack(save()), adds no dependencies either.
$produce
function $produce<T>(signal: T, recipe: (draft: T) => T | void): void;
Changes an object or array in a signal through a draft, and writes the signal with the result.
- The first argument is a signal. The second is a function.
- It is allowed where a signal can be written.
- The new value shares the objects that the recipe did not change. If the recipe changes nothing, the signal keeps its value.
- Only plain objects and arrays are drafted.
$setContext
function $setContext<T>(context: Context<T>, value: T): void;
Provides a value of a context to the components inside this one. A statement at the top level of a script. When value changes in the browser, every component that reads it updates. Create the context with createContext from brumate/context.
$getContext
function $getContext<T>(context: Context<T>): T;
Reads a context from the nearest component above that provides it, or its default value. Assign it to a const at the top level of a script.
$id
function $id(): string;
Returns an ID that is unique in the page, for attributes such as for and aria-describedby. Assign it to a const at the top level of a script. Server and client make the same ID. In the script of a block, such as the body of a #for, each instance gets its own. It has only letters, digits, - and _, so it works as a CSS selector too.
$title
function $title(value: unknown): void;
Sets the title of the page. A statement at the top level of a script, with one argument. It is replaced by a <title> in #head, the compiler warns about it, and it goes in a later version. See Page metadata.
- Server: writes
<title>into the head. If several components set it, the last one that renders wins. - Client: when the value changes, the title changes.
$action
function $action<F extends (...args: never[]) => unknown>(fn: F): Awaited<ReturnType<F>> | undefined;
The latest result of a server function that a form of this component posts to.
- Assign it to a
constat the top level of a script. The argument is a server function of the same file. - It is
undefinedbefore the first post.$isPending(result)is true while the form sends. - Without scripts, the page renders again with the result.
$handler
function $handler<A extends unknown[], E = Event>(
fn: (...args: [...A, E]) => unknown,
...args: A
): (event: E) => unknown;
Marks a function that a script makes as an event handler, so a spread can pass it on, as it passes on a handler that a caller writes in markup.
fnis a function expression or a function of the script, in wrappers ofbrumate/eventsor not. It compiles as a handler in markup does, with its own part.argsare JSON values, such as numbers, strings, arrays and plain objects. They go with the handler, which runs asfn(...args, event).- It can be called in any expression of a script, such as in a function that makes the attributes of a button, and in a module function.
fnreads the values of the scope where$handleris called. A value of a function around the call, such as its parameter, is a compile error: pass it as an argument.- The handler of a spread goes into
b-on, on the server and in markup that the browser renders. The loader applies its wrappers, such asprevent, before its code loads.
$bind
function $bind<T>(value: T, set?: (next: T) => unknown): BindableMark<T>;
Passes a value that the receiver writes back.
- Pass it as the whole value of a prop of a component, or of
valueorcheckedof an<input>, a<select>or a<textarea>. - Its argument is the name of a signal, or of a prop that the component destructures with
let. Anything else is a compile error. - On a component, the child's writes of the prop write the value. A binding of a
letprop passes on to the parent of the component, through any number of levels. - On an element, the browser writes the value on
input, or onchangefor a box and a<select>. It loads no code of the component to do it. A handler of the element, such asonInput=search, runs after it and reads the new value. - With
set, a write callsset(next)in place of writing the value, so the parent can refuse a value or change it:open=$bind(open, (next) => { if (!dirty) open = next; }). The child then shows the value that the parent keeps.setis a function expression or a function of the script, and it loads with its own part, as a handler does. - A rest prop keeps the bindings that it holds. Spread on an element, it binds
valueandchecked. Spread on a component, it binds the props of that component. - Only a prop of type
Bindable<T>takes a binding.brumate-tscreports a binding of another prop, or of another type. - The compiler warns about a prop that the type marks
Bindablebut that the component reads only withconst.
$optimistic
let shown = $optimistic(names);
- It follows
source, a memo, an action or a prop, and handlers can write it. - A write shows a guess. The guess stays until
sourcechanges, or until every server call of the page finishes. - Write it with
=.++and--are compile errors. sourceis a name. A signal is a compile error, because a handler can write a signal directly.
$debounced and $throttled
function $debounced<T>(value: T, ms: number): MemoValue<T>;
function $throttled<T>(value: T, ms: number): MemoValue<T>;
Memos of value that the browser writes after a wait.
$debouncedtakes the value once it stops changing formsmilliseconds.$throttledtakes it at most once everymsmilliseconds: the first change at once, and the last one after the wait.- Server: the value itself. Client: pending while it waits.
msis a number literal. Any other value is a compile error.
Not supported
These names are reserved, and calling one is a compile error that names the replacement:
| Name | Use instead |
|---|---|
$ref |
A $signal with ref=$bind(name) on the element. |
$watch |
$effect. |
$settled |
$client. |
$cleanup |
A function returned from $effect or $client. |
$store |
A $signal with a new value, or $produce. |
$get, $set |
Nothing. Signals cannot leave the file. |