agnostic/platform
This module contains the platform abstraction used by Lustre’s reconciler. A platform configuration provides the low-level mutation methods needed to create, modify, and remove nodes in a render target.
Types
A deferred effect phase declared by a platform. name identifies which
tagged tasks the phase drains: effects constructed with
effect.deferred — or a platform module’s typed
constructor built on it — carry a phase name, and at the end of each render
pass the runtime hands the pending tasks of every declared phase to that
phase’s schedule function. Phases are drained in the platform’s
declaration order; the relative timing between phases is then determined by
the schedulers themselves.
Tasks tagged with a phase name the running platform does not declare are silently dropped.
Note:
schedulemust defer — it must never invoke its callback synchronously. The runtime’s render bookkeeping assumes control returns to it before any scheduled callback runs.
pub type Phase {
Phase(name: String, schedule: fn(fn() -> Nil) -> Nil)
}
Constructors
-
Phase(name: String, schedule: fn(fn() -> Nil) -> Nil)
A platform configuration provides the low-level mutation methods needed to create, modify, and remove nodes in a render target. Lustre’s reconciler calls these methods instead of hardcoded DOM APIs, allowing applications to render to arbitrary targets beyond the browser DOM.
Use dom.dom() from agnostic/platform/dom for the browser DOM.
Use headless for server components that don’t render to a DOM.
Custom targets can provide their own implementations via new.
pub opaque type Platform(node, target, value, event, message, raw)
An error type returned by platform operations.
pub type PlatformError {
NotABrowser
ElementNotFound(selector: String)
NotMountable
}
Constructors
-
NotABrowser -
ElementNotFound(selector: String) -
NotMountable
Values
pub fn headless() -> Platform(
node,
target,
value,
event,
message,
raw,
)
Returns a headless Platform for server components. Server
components don’t render to a DOM target — they send patches over the network
to connected clients instead.
Headless platforms declare no deferred phases: effects deferred to a
platform phase (such as dom.before_paint or dom.after_paint) are
dropped and never run.
Example
import agnostic/platform
import agnostic/platform/dom
let p = platform.headless()
pub fn is_browser() -> Bool
Gleam’s conditional compilation makes it possible to have different implementations of a function for different targets, but it’s not possible to know what runtime you’re targeting at compile-time.
This is problematic if you’re using server components with a JavaScript backend because you’ll want to know whether you’re currently running on your server or in the browser: this function tells you that!
pub fn new(
target target: target,
mount mount: fn(target) -> #(node, vnode.Element(message)),
create_element create_element: fn(String, String) -> node,
create_text_node create_text_node: fn(String) -> node,
create_fragment create_fragment: fn() -> node,
create_comment create_comment: fn(String) -> node,
insert_before insert_before: fn(node, node, Result(node, Nil)) -> Nil,
move_before move_before: fn(node, node, Result(node, Nil)) -> Nil,
remove_child remove_child: fn(node, node) -> Nil,
next_sibling next_sibling: fn(node) -> Result(node, Nil),
get_attribute get_attribute: fn(node, String) -> Result(
String,
Nil,
),
set_attribute set_attribute: fn(node, String, String) -> Nil,
remove_attribute remove_attribute: fn(node, String) -> Nil,
set_property set_property: fn(node, String, value) -> Nil,
set_text set_text: fn(node, String) -> Nil,
set_raw_content set_raw_content: fn(node, raw) -> Nil,
create_raw_node create_raw_node: fn(raw) -> node,
add_event_listener add_event_listener: fn(
node,
String,
fn(event) -> Nil,
Bool,
) -> Nil,
remove_event_listener remove_event_listener: fn(
node,
String,
fn(event) -> Nil,
) -> Nil,
schedule_render schedule_render: fn(fn() -> Nil) -> fn() -> Nil,
after_render after_render: fn() -> Nil,
phases phases: List(Phase),
) -> Platform(node, target, value, event, message, raw)
Construct a custom Platform with user-provided mutation
methods. This is useful for rendering to non-DOM targets.
Non-DOM targets can no-op create_comment, create_fragment,
set_raw_content, create_raw_node, add_event_listener, and
remove_event_listener and provide minimal implementations for the rest.
phases declares the platform’s deferred effect Phases in
drain order. Pass an empty list for no deferred phases — deferred effects
are then dropped. To run effects constructed by another platform module’s
typed constructors, declare a phase whose name matches that platform’s
public phase-name constant (for example
dom.before_paint_phase).
Note:
schedule_renderand everyPhase’sschedulefunction must defer — they must never invoke their callback synchronously. The runtime’s render bookkeeping assumes control returns to it first.