Packages

A platform agnostic Elm-like framework (soft-fork of Lustre)

Current section

Files

Jump to
agnostic src agnostic@element.erl
Raw

src/agnostic@element.erl

-module(agnostic@element).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/agnostic/element.gleam").
-export([element/3, namespaced/4, text/1, none/0, fragment/1, unsafe_raw_content/6, unsafe_raw/3, memo/2, ref/1, map/2, to_string/1, to_document_string/1, to_readable_string/1, unsafe_raw_html/4]).
-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(
" Lustre wouldn't be much use as a frontend library if it didn't provide a\n"
" way to create HTML elements. This module contains the basic functions\n"
" necessary to construct and manipulate different HTML elements.\n"
"\n"
" It is also possible to use Lustre as a HTML templating library, without\n"
" using its runtime features, by passing elements to functions like\n"
" [`to_string_tree`](#to_string_tree) or [`to_document_string`](#to_document_string). \n"
"\n"
).
-file("src/agnostic/element.gleam", 88).
?DOC(
" A general function for constructing any kind of element. In most cases you\n"
" will want to use the [`agnostic/element/html`](./element/html.html) instead but this\n"
" function is particularly handy when constructing custom elements, either\n"
" from your own Lustre components or from external JavaScript libraries.\n"
"\n"
" When rendering elements to strings with [`to_string`](#to_string), the default\n"
" HTML serializer will render standard HTML void elements (like `<br>`, `<img>`,\n"
" `<input>`) without closing tags. To customize which elements are treated as\n"
" void or self-closing, use [`dom.serialize`](./platform/dom.html#serialize)\n"
" with a custom [`SerializerConfig`](./platform/dom.html#SerializerConfig).\n"
).
-spec element(
binary(),
list(agnostic@vdom@vattr:attribute(HCD)),
list(agnostic@vdom@vnode:element(HCD))
) -> agnostic@vdom@vnode:element(HCD).
element(Tag, Attributes, Children) ->
agnostic@vdom@vnode:element(
<<""/utf8>>,
<<""/utf8>>,
Tag,
Attributes,
Children,
maps:new()
).
-file("src/agnostic/element.gleam", 106).
?DOC(
" A function for constructing elements in a specific XML namespace. This can\n"
" be used to construct SVG or MathML elements, for example.\n"
).
-spec namespaced(
binary(),
binary(),
list(agnostic@vdom@vattr:attribute(HCJ)),
list(agnostic@vdom@vnode:element(HCJ))
) -> agnostic@vdom@vnode:element(HCJ).
namespaced(Namespace, Tag, Attributes, Children) ->
agnostic@vdom@vnode:element(
<<""/utf8>>,
Namespace,
Tag,
Attributes,
Children,
maps:new()
).
-file("src/agnostic/element.gleam", 127).
?DOC(
" A function for turning a Gleam string into a text node. Gleam doesn't have\n"
" union types like some other languages you may be familiar with, like TypeScript.\n"
" Instead, we need a way to take a `String` and turn it into an `Element` somehow:\n"
" this function is exactly that!\n"
).
-spec text(binary()) -> agnostic@vdom@vnode:element(any()).
text(Content) ->
agnostic@vdom@vnode:text(<<""/utf8>>, Content).
-file("src/agnostic/element.gleam", 135).
?DOC(
" A function for rendering nothing. This is mostly useful for conditional\n"
" rendering, where you might want to render something only if a certain\n"
" condition is met.\n"
).
-spec none() -> agnostic@vdom@vnode:element(any()).
none() ->
agnostic@vdom@vnode:text(<<""/utf8>>, <<""/utf8>>).
-file("src/agnostic/element.gleam", 144).
?DOC(
" A function for constructing a wrapper element with no tag name. This is\n"
" useful for wrapping a list of elements together without adding an extra\n"
" `<div>` or other container element, or returning multiple elements in places\n"
" where only one `Element` is expected.\n"
).
-spec fragment(list(agnostic@vdom@vnode:element(HCT))) -> agnostic@vdom@vnode:element(HCT).
fragment(Children) ->
agnostic@vdom@vnode:fragment(<<""/utf8>>, Children, maps:new()).
-file("src/agnostic/element.gleam", 163).
?DOC(
" A function for constructing a wrapper element with platform-specific raw\n"
" content. This is the generic version of `unsafe_raw_html` that accepts any\n"
" content type, allowing platforms to inject their own node types.\n"
"\n"
" For DOM platforms, use `unsafe_raw_html` with a String instead.\n"
" For other platforms (like OpenTUI), this allows inserting raw platform nodes.\n"
"\n"
" The platform's `set_raw_content` function receives this content and decides\n"
" how to handle it.\n"
"\n"
" The optional `compare` parameter allows custom equality checking for the content.\n"
" When provided, the diff algorithm uses this comparator instead of `==` to\n"
" determine if the content has changed. This is useful for content types like\n"
" closures where reference equality isn't appropriate.\n"
).
-spec unsafe_raw_content(
binary(),
binary(),
binary(),
list(agnostic@vdom@vattr:attribute(HCX)),
HDA,
gleam@option:option(fun((HDA, HDA) -> boolean()))
) -> agnostic@vdom@vnode:element(HCX).
unsafe_raw_content(Key, Namespace, Tag, Attributes, Content, Compare) ->
agnostic@vdom@vnode:raw_container(
Key,
Namespace,
Tag,
Attributes,
Content,
Compare
).
-file("src/agnostic/element.gleam", 185).
?DOC(
" A function for inserting a raw platform node directly into the virtual DOM\n"
" tree without a wrapper element. The content is treated as an opaque platform\n"
" node and inserted directly using the platform's `insert_before` method.\n"
"\n"
" For inserting raw HTML strings, use [`html.unsafe_raw`](./element/html.html#unsafe_raw)\n"
" instead, which wraps the content in a container element (required for innerHTML).\n"
"\n"
" The optional `compare` parameter allows custom equality checking for the content.\n"
" When provided, the diff algorithm uses this comparator instead of `==` to\n"
" determine if the content has changed.\n"
).
-spec unsafe_raw(
binary(),
HDD,
gleam@option:option(fun((HDD, HDD) -> boolean()))
) -> agnostic@vdom@vnode:element(any()).
unsafe_raw(Key, Content, Compare) ->
agnostic@vdom@vnode:raw_node(Key, Content, Compare).
-file("src/agnostic/element.gleam", 223).
?DOC(
" A function for creating \"memoised\" or \"lazy\" elements. Lustre will use the\n"
" dependencies list to skip calling the provided view function if all of the\n"
" dependencies are _reference equal_ to their previous values.\n"
"\n"
" `memo` can be used to optimise performance-critical parts of your application,\n"
" for example in cases where many instances of the same element are rendered but\n"
" only one may change at a time, or cases where a part of your view may update\n"
" very frequently but other parts remain largely static. When Lustre can tell\n"
" that the dependencies haven't changed, almost all the work typically done to\n"
" update the DOM can be skipped.\n"
"\n"
" In many cases `memo` will not be necessary, so think twice before considering\n"
" its use! Lustre is designed to handle rerenders and large vdom trees efficiently,\n"
" so in most cases the naive approach of re-rendering everything will be perfectly\n"
" fine.\n"
"\n"
" > **Note**: reference equality is not the same as Gleam's normal equality.\n"
" > Two custom types with the same values are not reference equal unless they\n"
" > are the exact same instance in memory! Because of this, it's important to\n"
" > avoid list literals or constructing custom types in the dependencies list.\n"
"\n"
" > **Note**: memoisation comes with its own trade-offs and can cause performance\n"
" > regressions in two ways. First, every use of `memo` increases your application's\n"
" > memory usage slightly, as Lustre needs to keep dependencies around to compare\n"
" > them on subsequent renders. Second, if dependencies change regularly, the\n"
" > overhead of comparing dependencies and managing memoisation may be more than\n"
" > the naive cost of re-rendering the element each time.\n"
).
-spec memo(
list(agnostic@internals@ref:ref()),
fun(() -> agnostic@vdom@vnode:element(HDI))
) -> agnostic@vdom@vnode:element(HDI).
memo(Dependencies, View) ->
agnostic@vdom@vnode:memo(<<""/utf8>>, Dependencies, View).
-file("src/agnostic/element.gleam", 239).
?DOC(
" Create a `Ref` dependency value used for [`memo`](#memo) elements.\n"
"\n"
" Lustre uses reference equality to compare dependencies. On JavaScript, values\n"
" are compared using [same-value-zero](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness#same-value-zero_equality)\n"
" semantics. This means Lustre will treat `+0` and `-0` as equal, and any errant\n"
" `NaN` values (which are not typically producible in Gleam code) as equal. On\n"
" Erlang, there is no difference between reference equality and value equality,\n"
" so all values are compared using normal equality semantics.\n"
).
-spec ref(any()) -> agnostic@internals@ref:ref().
ref(Value) ->
gleam@function:identity(Value).
-file("src/agnostic/element.gleam", 252).
?DOC(
" The `Element` type is parameterised by the type of messages it can produce\n"
" from events. Sometimes you might end up with a fragment of HTML from another\n"
" library or module that produces a different type of message: this function lets\n"
" you map the messages produced from one type to another.\n"
"\n"
" Think of it like `list.map` or `result.map` but for HTML events!\n"
).
-spec map(agnostic@vdom@vnode:element(HDM), fun((HDM) -> HDO)) -> agnostic@vdom@vnode:element(HDO).
map(Element, F) ->
agnostic@vdom@vnode:map(Element, F).
-file("src/agnostic/element.gleam", 273).
?DOC(
" DEPRECATED: Use `agnostic/platform/dom.to_string` instead.\n"
" This shim exists only for lustre_dev_tools compatibility.\n"
).
-spec to_string(agnostic@vdom@vnode:element(any())) -> binary().
to_string(_el) ->
agnostic@platform@dom:to_string(_el).
-file("src/agnostic/element.gleam", 282).
?DOC(
" DEPRECATED: Use `agnostic/platform/dom.to_document_string` instead.\n"
" This shim exists only for lustre_dev_tools compatibility.\n"
).
-spec to_document_string(agnostic@vdom@vnode:element(any())) -> binary().
to_document_string(_el) ->
agnostic@platform@dom:to_document_string(_el).
-file("src/agnostic/element.gleam", 291).
?DOC(
" DEPRECATED: Use `agnostic/platform/dom.to_readable_string` instead.\n"
" This shim exists only for lustre_dev_tools compatibility.\n"
).
-spec to_readable_string(agnostic@vdom@vnode:element(any())) -> binary().
to_readable_string(_el) ->
agnostic@platform@dom:to_readable_string(_el).
-file("src/agnostic/element.gleam", 299).
?DOC(
" DEPRECATED: Use `element.unsafe_raw_content` instead.\n"
" This shim exists only for lustre_dev_tools compatibility.\n"
).
-spec unsafe_raw_html(
binary(),
binary(),
list(agnostic@vdom@vattr:attribute(HDW)),
binary()
) -> agnostic@vdom@vnode:element(HDW).
unsafe_raw_html(Namespace, Tag, Attributes, Content) ->
agnostic@vdom@vnode:raw_container(
<<""/utf8>>,
Namespace,
Tag,
Attributes,
Content,
none
).