Current section
Files
Jump to
Current section
Files
src/agnostic@platform.erl
-module(agnostic@platform).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/agnostic/platform.gleam").
-export([headless/0, new/22, mount/1, is_headless/1, is_browser/0]).
-export_type([platform_error/0, phase/0, platform/6]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" This module contains the platform abstraction used by Lustre's reconciler.\n"
" A platform configuration provides the low-level mutation methods needed to\n"
" create, modify, and remove nodes in a render target.\n"
"\n"
).
-type platform_error() :: not_a_browser |
{element_not_found, binary()} |
not_mountable.
-type phase() :: {phase, binary(), fun((fun(() -> nil)) -> nil)}.
-opaque platform(ILA, ILB, ILC, ILD, ILE, ILF) :: headless |
{platform,
ILB,
fun((ILB) -> {ILA, agnostic@vdom@vnode:element(ILE)}),
fun((binary(), binary()) -> ILA),
fun((binary()) -> ILA),
fun(() -> ILA),
fun((binary()) -> ILA),
fun((ILA, ILA, {ok, ILA} | {error, nil}) -> nil),
fun((ILA, ILA, {ok, ILA} | {error, nil}) -> nil),
fun((ILA, ILA) -> nil),
fun((ILA) -> {ok, ILA} | {error, nil}),
fun((ILA, binary()) -> {ok, binary()} | {error, nil}),
fun((ILA, binary(), binary()) -> nil),
fun((ILA, binary()) -> nil),
fun((ILA, binary(), ILC) -> nil),
fun((ILA, binary()) -> nil),
fun((ILA, ILF) -> nil),
fun((ILF) -> ILA),
fun((ILA, binary(), fun((ILD) -> nil), boolean()) -> nil),
fun((ILA, binary(), fun((ILD) -> nil)) -> nil),
fun((fun(() -> nil)) -> fun(() -> nil)),
fun(() -> nil),
list(phase())}.
-file("src/agnostic/platform.gleam", 96).
?DOC(
" Returns a headless [`Platform`](#Platform) for server components. Server\n"
" components don't render to a DOM target — they send patches over the network\n"
" to connected clients instead.\n"
"\n"
" Headless platforms declare no deferred phases: effects deferred to a\n"
" platform phase (such as `dom.before_paint` or `dom.after_paint`) are\n"
" dropped and never run.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import agnostic/platform\n"
" import agnostic/platform/dom\n"
"\n"
" let p = platform.headless()\n"
" ```\n"
).
-spec headless() -> platform(any(), any(), any(), any(), any(), any()).
headless() ->
headless.
-file("src/agnostic/platform.gleam", 118).
?DOC(
" Construct a custom [`Platform`](#Platform) with user-provided mutation\n"
" methods. This is useful for rendering to non-DOM targets.\n"
"\n"
" Non-DOM targets can no-op `create_comment`, `create_fragment`,\n"
" `set_raw_content`, `create_raw_node`, `add_event_listener`, and\n"
" `remove_event_listener` and provide minimal implementations for the rest.\n"
"\n"
" `phases` declares the platform's deferred effect [`Phase`](#Phase)s in\n"
" drain order. Pass an empty list for no deferred phases — deferred effects\n"
" are then dropped. To run effects constructed by another platform module's\n"
" typed constructors, declare a phase whose name matches that platform's\n"
" public phase-name constant (for example\n"
" [`dom.before_paint_phase`](./platform/dom.html#before_paint_phase)).\n"
"\n"
" > **Note**: `schedule_render` and every `Phase`'s `schedule` function must\n"
" > defer — they must never invoke their callback synchronously. The\n"
" > runtime's render bookkeeping assumes control returns to it first.\n"
).
-spec new(
ILS,
fun((ILS) -> {ILT, agnostic@vdom@vnode:element(ILU)}),
fun((binary(), binary()) -> ILT),
fun((binary()) -> ILT),
fun(() -> ILT),
fun((binary()) -> ILT),
fun((ILT, ILT, {ok, ILT} | {error, nil}) -> nil),
fun((ILT, ILT, {ok, ILT} | {error, nil}) -> nil),
fun((ILT, ILT) -> nil),
fun((ILT) -> {ok, ILT} | {error, nil}),
fun((ILT, binary()) -> {ok, binary()} | {error, nil}),
fun((ILT, binary(), binary()) -> nil),
fun((ILT, binary()) -> nil),
fun((ILT, binary(), IME) -> nil),
fun((ILT, binary()) -> nil),
fun((ILT, IMF) -> nil),
fun((IMF) -> ILT),
fun((ILT, binary(), fun((IMG) -> nil), boolean()) -> nil),
fun((ILT, binary(), fun((IMG) -> nil)) -> nil),
fun((fun(() -> nil)) -> fun(() -> nil)),
fun(() -> nil),
list(phase())
) -> platform(ILT, ILS, IME, IMG, ILU, IMF).
new(
Target,
Mount,
Create_element,
Create_text_node,
Create_fragment,
Create_comment,
Insert_before,
Move_before,
Remove_child,
Next_sibling,
Get_attribute,
Set_attribute,
Remove_attribute,
Set_property,
Set_text,
Set_raw_content,
Create_raw_node,
Add_event_listener,
Remove_event_listener,
Schedule_render,
After_render,
Phases
) ->
{platform,
Target,
Mount,
Create_element,
Create_text_node,
Create_fragment,
Create_comment,
Insert_before,
Move_before,
Remove_child,
Next_sibling,
Get_attribute,
Set_attribute,
Remove_attribute,
Set_property,
Set_text,
Set_raw_content,
Create_raw_node,
Add_event_listener,
Remove_event_listener,
Schedule_render,
After_render,
Phases}.
-file("src/agnostic/platform.gleam", 182).
?DOC(false).
-spec mount(platform(IMO, any(), any(), any(), IMS, any())) -> {ok,
{IMO, agnostic@vdom@vnode:element(IMS)}} |
{error, platform_error()}.
mount(Platform) ->
case Platform of
headless ->
{error, not_mountable};
{platform,
T,
M,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_} ->
{ok, M(T)}
end.
-file("src/agnostic/platform.gleam", 194).
?DOC(false).
-spec is_headless(platform(any(), any(), any(), any(), any(), any())) -> boolean().
is_headless(Platform) ->
case Platform of
headless ->
true;
{platform,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_,
_} ->
false
end.
-file("src/agnostic/platform.gleam", 212).
?DOC(
" Gleam's conditional compilation makes it possible to have different implementations\n"
" of a function for different targets, but it's not possible to know what runtime\n"
" you're targeting at compile-time.\n"
"\n"
" This is problematic if you're using server components with a JavaScript\n"
" backend because you'll want to know whether you're currently running on your\n"
" server or in the browser: this function tells you that!\n"
).
-spec is_browser() -> boolean().
is_browser() ->
false.