Sprites.Reactive
The reactive core. Values hold state, calculations read and derive, and the structure grows and shrinks with the data. Context injects a value for a subtree, read by any descendant.
Async work lives in drivers, outside the synchronous core. A value can be pending, with no value yet; reading a pending value under a Sprites.Ui.Loading shows a spinner. Sprites.Animate holds the time based drivers.
- Sprites.Reactive.Calculate
- Sprites.Reactive.Driver
- Sprites.Reactive.Each
- Sprites.Reactive.Field
- Sprites.Reactive.Freeze
- Sprites.Reactive.Get
- Sprites.Reactive.If
- Sprites.Reactive.IfNot
- Sprites.Reactive.Pending
- Sprites.Reactive.Repeat
- Sprites.Reactive.Set
- Sprites.Reactive.Value
Sprites.Reactive.Context
Sprites.Reactive.Calculate Sprites.Reactive.Value
Sprites.Reactive.Calculate(fn)
Read values and return a value. Going forward the result is a read-only reactive value, recomputed when a value it read changes. Inside a lens it builds the same live value, which a Set commits when it is ready, or when it lands if an async part is still on the way, so a calculation function reads the same in both directions.
| Input | Type | Description |
|---|---|---|
fn | Function | Reads values with Get and plain work, returning the computed result. |
Returns a read-only Sprites.Reactive.Value holding the result, recomputed when a value it read changes.
const w = Sprites.Reactive.Value(4);
const h = Sprites.Reactive.Value(3);
const area = Sprites.Reactive.Calculate(() => {
return Sprites.Reactive.Get(w) * Sprites.Reactive.Get(h);
});
Sprites.Ui.Input.Number(w);
Sprites.Ui.Input.Number(h);
Sprites.Ui.Dom.Text('Area: ', area);
Sprites.Reactive.Driver Object
Sprites.Reactive.Driver(name, resultBinding, request, make)
Ask a driver for async work. The driver runs the work and writes the result value, which opens the next update. The first request for a name builds the driver with make; the request lives until its scope ends. Drivers keep the core synchronous, so no calculation or handler waits.
The request may be a reactive value, so the driver follows it: when the request changes the driver reruns with the new value, cancelling any stale work, and writes the same result value. A read whose query is a reactive object stays live this way, with no rebuild. A plain request dispatches once.
A request emitted inside a handler freezes the values that handler read until the driver reports, and marks the result pending. A control that writes a frozen value disables on its own, and a control that reads a pending value shows a spinner under a Loading, so the interface locks the right parts while the work runs.
| Input | Type | Description |
|---|---|---|
name | String | The driver's name. The same name ties every call to one driver. |
resultBinding | Sprites.Reactive.Value | The value the driver writes as the work runs and completes. |
request | Any or Sprites.Reactive.Value | This request's parameters. A reactive value reruns the driver whenever it changes. |
make | Function | Builds the driver the first time the name is seen, returning onRequestAdd and onDriverDestroy. |
Returns the request control, with update and destroy.
const status = Sprites.Reactive.Pending('');
const go = Sprites.Reactive.Value(false);
const delay = () => {
return {
onRequestAdd: (binding, params) => {
const id = setTimeout(() => {
Sprites.Reactive.batch(() => {
Sprites.Reactive.Set(binding, params.text);
});
}, params.ms);
return { onRequestDestroy: () => { clearTimeout(id); } };
},
};
};
Sprites.Ui.Button.SetValue(go, true, 'Start');
Sprites.Ui.Loading(() => {
Sprites.Ui.Dom.Text(' status = ', status);
});
Sprites.Reactive.If(go, () => {
Sprites.Reactive.Driver('demo.delay', status, { text: 'ready', ms: 1500 }, delay);
});
Sprites.Reactive.Each Void
Sprites.Reactive.Each(list, build)
Repeat the content for each element of a list.
| Input | Type | Description |
|---|---|---|
list | Array or Sprites.Reactive.Value | The list to walk. A reactive list rebuilds as it changes, and each item is a two-way field. |
build | Function | Called as build(item, index) to build the content for each element. |
Returns nothing.
const items = Sprites.Reactive.Value(['Red', 'Green']);
Sprites.Ui.Button.Push(items, () => {
return 'Blue';
}, 'Add colour');
Sprites.Reactive.Each(items, (item) => {
Sprites.Ui.Dom.Tag('p', item);
});
Sprites.Reactive.Field Sprites.Reactive.Value
Sprites.Reactive.Field(source, key)
A two-way view of one field or element. Reading tracks the container; setting writes the whole container back, up any lens chain. Inside a lens or a reverse handler it fetches the field and returns it, with no binding; to write a field there, Set the whole container.
| Input | Type | Description |
|---|---|---|
source | Sprites.Reactive.Value | The container value, an object or an array. |
key | String or Number | The field name or array index to view. |
Returns a two-way Sprites.Reactive.Value over that field; setting it writes a fresh container back.
const point = Sprites.Reactive.Value({ x: 1, y: 2 });
const x = Sprites.Reactive.Field(point, 'x');
Sprites.Ui.Input.Number(x);
Sprites.Ui.Dom.Text('x = ', x);
Sprites.Reactive.Freeze Any
Sprites.Reactive.Freeze(value)
Read a snapshot of a value without following it. Unlike Get, it never subscribes, so the reader does not update when the value later changes; it hands back the value now. Use it in a lens, or in reactive value code outside a Calculate, where you want the value as it stands. Use Get inside a Calculate to derive a value that follows. In a reverse handler Freeze records the read, so the transaction can freeze what it depends on.
| Input | Type | Description |
|---|---|---|
value | Any or Sprites.Reactive.Value | A constant, returned as is, or a reactive value to snapshot. |
Returns the value now.
const step = Sprites.Reactive.Value(5);
const total = Sprites.Reactive.Value(0);
const add = Sprites.Reactive.Value(null, () => {
const s = Sprites.Reactive.Freeze(step);
const t = Sprites.Reactive.Freeze(total);
Sprites.Reactive.Set(total, t + s);
});
Sprites.Ui.Input.Number(step, 1, 100);
Sprites.Ui.Button.Act(add, 'Add step');
Sprites.Ui.Dom.Text('total = ', total);
Sprites.Reactive.Get Any
Sprites.Reactive.Get(value)
Read a value. A constant is returned as is. A reactive value gives its current value; in a calculate or binding it subscribes, and elsewhere it is a snapshot, so reading in build code captures the value once.
| Input | Type | Description |
|---|---|---|
value | Any or Sprites.Reactive.Value | A constant, returned as is, or a reactive value to read. |
Returns the current value.
const price = Sprites.Reactive.Value(5);
const label = Sprites.Reactive.Calculate(() => {
return 'Price: ' + Sprites.Reactive.Get(price);
});
Sprites.Ui.Input.Number(price);
Sprites.Ui.Dom.Text(label);
Sprites.Reactive.If Void
Sprites.Reactive.If(cond, build)
Show the content while a value is true.
| Input | Type | Description |
|---|---|---|
cond | Boolean, Sprites.Reactive.Value or Function | The condition. A reactive condition shows and hides the content as it changes. |
build | Function | Builds the content shown while the condition is true. |
Returns nothing.
const open = Sprites.Reactive.Value(true);
Sprites.Ui.Input.Checkbox(open);
Sprites.Reactive.If(open, () => {
Sprites.Ui.Dom.Tag('p', 'Now you see me');
});
Sprites.Reactive.IfNot Void
Sprites.Reactive.IfNot(cond, build)
The mirror of If: show the content while a value is false, so a part shown only while something is absent needs no separate negation.
| Input | Type | Description |
|---|---|---|
cond | Boolean, Sprites.Reactive.Value or Function | The condition. The content shows while it is false. |
build | Function | Builds the content shown while the condition is false. |
Returns nothing.
const full = Sprites.Reactive.Value(false);
Sprites.Ui.Input.Checkbox(full);
Sprites.Reactive.IfNot(full, () => {
Sprites.Ui.Dom.Tag('p', 'There is still room.');
});
Sprites.Reactive.Pending Sprites.Reactive.Value
Sprites.Reactive.Pending(initial)
A value that is loading. It holds a realistic stand-in of the right shape, an empty array, a blank string, zero or false, so a reader can use it while it waits. It is pending, so reading it under a Sprites.Ui.Loading shows the spinner and a calculation over it stays pending too. The first Set gives it the real value and clears the flag. It stays writable, so a driver may fill it.
| Input | Type | Description |
|---|---|---|
initial | Any | The stand-in value of the right shape, used while the value loads. |
Returns a pending Sprites.Reactive.Value, unreadable until set.
const result = Sprites.Reactive.Pending('');
const started = Sprites.Reactive.Value(false);
Sprites.Ui.Button.SetValue(started, true, 'Load');
Sprites.Ui.Loading(() => {
Sprites.Ui.Dom.Text(' result = ', result);
});
Sprites.Reactive.If(started, () => {
Sprites.Animate.SetAfter(result, 'done', 1500);
});
Sprites.Reactive.Repeat Void
Sprites.Reactive.Repeat(count, build)
Repeat the content count times, calling build with each index. count may be a constant or a reactive value, so the run grows and shrinks as it changes.
| Input | Type | Description |
|---|---|---|
count | Number, Sprites.Reactive.Value or Function | How many times to repeat. A reactive count grows and shrinks the run. |
build | Function | Called as build(index) for each repetition. |
Returns nothing.
const count = Sprites.Reactive.Value(3);
Sprites.Ui.Input.Number(count, 0, 6);
Sprites.Reactive.Repeat(count, (i) => {
Sprites.Ui.Dom.Tag('button', 'Item ' + (i + 1));
});
Sprites.Reactive.Set Any
Sprites.Reactive.Set(value, next)
Write a value, in an event handler or a lens. A lens set runs its onChange. Takes a reactive value or a constant, never a function; it throws on a function. Give it a live value, such as a calculation, and it commits when that value is ready, or when it lands if an async part is still on the way.
| Input | Type | Description |
|---|---|---|
value | Sprites.Reactive.Value | The value to write. Allowed only in a handler or a lens. |
next | Any or Sprites.Reactive.Value | The new value: a reactive value or a constant, never a function. |
Returns the value written.
const n = Sprites.Reactive.Value(0);
Sprites.Ui.Button.Increment(n, 'Add one');
Sprites.Ui.Dom.Text('n = ', n);
Sprites.Reactive.Value Sprites.Reactive.Value
Sprites.Reactive.Value(value, onChange)
A reactive value. The first argument is a constant or a reactive value; a reactive one makes it a binding that tracks that value. With onChange it is a lens, or a two-way binding when tracking, and setting it runs onChange to write other values. Made inside a lens or a reverse handler it is a nested reverse process: it holds no path or probe, and setting it runs its onChange in place, in the same reverse sweep, joining the transaction. A binding over a reactive source returns the source itself in that direction, since it has no tracking to do there.
| Input | Type | Description |
|---|---|---|
value | Any or Sprites.Reactive.Value | A constant for state, or a reactive value to track as a binding. |
onChange | Function | Optional. Makes it a lens, run on set to write other values. |
Returns a reactive Sprites.Reactive.Value.
const count = Sprites.Reactive.Value(2);
Sprites.Ui.Input.Number(count);
Sprites.Ui.Dom.Text('Count: ', count);
Sprites.Reactive.Context.Get Any
Sprites.Reactive.Context.Get(name, def)
Read the nearest value in scope for a name, or a default when no Set is in scope.
| Input | Type | Description |
|---|---|---|
name | String | The context name to read. |
def | Any | Optional value returned when the name is not in scope. |
Returns the nearest value in scope for the name, or the default.
const theme = Sprites.Reactive.Value('dark');
Sprites.Reactive.Context.Set('theme', theme, () => {
const t = Sprites.Reactive.Context.Get('theme', 'light');
Sprites.Ui.Input.Text(t);
Sprites.Ui.Dom.Text('theme = ', t);
});
Sprites.Reactive.Context.Set Any
Sprites.Reactive.Context.Set(name, value, build)
Inject a named value for the subtree that build creates, then restore. A nearer Set shadows a wider one of the same name.
| Input | Type | Description |
|---|---|---|
name | String | The context name. |
value | Any | The value to inject for the subtree. |
build | Function | Builds the subtree that can read the value. |
Returns the result of build.
const theme = Sprites.Reactive.Value('dark');
Sprites.Reactive.Context.Set('theme', theme, () => {
const t = Sprites.Reactive.Context.Get('theme');
Sprites.Ui.Input.Text(t);
Sprites.Ui.Dom.Text('theme = ', t);
});