Current section
Files
Jump to
Current section
Files
src/agnostic@platform@opentui@element.erl
-module(agnostic@platform@opentui@element).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/agnostic/platform/opentui/element.gleam").
-export([box/2, text/1, input/1, textarea/1, scrollbox/2, select/2, code/2, markdown/2, diff/2, ascii_font/1, tab_select/1, line_number/2, slider/1, frame_buffer/1, frame_buffer_with_handler/2, raw_node/2]).
-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(
" TUI element constructors for OpenTUI. These map to @opentui/core renderables.\n"
"\n"
).
-file("src/agnostic/platform/opentui/element.gleam", 27).
?DOC(" A box container — the primary layout primitive in TUI. Maps to BoxRenderable.\n").
-spec box(
list(agnostic@vdom@vattr:attribute(QJK)),
list(agnostic@vdom@vnode:element(QJK))
) -> agnostic@vdom@vnode:element(QJK).
box(Attributes, Children) ->
agnostic@element:element(<<"box"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 37).
?DOC(
" A styled text element. Maps to TextRenderable.\n"
" Pass content(\"...\") as an attribute alongside styling attributes.\n"
).
-spec text(list(agnostic@vdom@vattr:attribute(QJQ))) -> agnostic@vdom@vnode:element(QJQ).
text(Attributes) ->
agnostic@element:element(<<"text"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 43).
?DOC(" A text input field. Maps to InputRenderable.\n").
-spec input(list(agnostic@vdom@vattr:attribute(QJU))) -> agnostic@vdom@vnode:element(QJU).
input(Attributes) ->
agnostic@element:element(<<"input"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 49).
?DOC(" A multi-line text area. Maps to TextareaRenderable.\n").
-spec textarea(list(agnostic@vdom@vattr:attribute(QJY))) -> agnostic@vdom@vnode:element(QJY).
textarea(Attributes) ->
agnostic@element:element(<<"textarea"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 55).
?DOC(" A scrollable container. Maps to ScrollBoxRenderable.\n").
-spec scrollbox(
list(agnostic@vdom@vattr:attribute(QKC)),
list(agnostic@vdom@vnode:element(QKC))
) -> agnostic@vdom@vnode:element(QKC).
scrollbox(Attributes, Children) ->
agnostic@element:element(<<"scrollbox"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 64).
?DOC(" A select dropdown. Maps to SelectRenderable.\n").
-spec select(
list(agnostic@vdom@vattr:attribute(QKI)),
list(agnostic@vdom@vnode:element(QKI))
) -> agnostic@vdom@vnode:element(QKI).
select(Attributes, Children) ->
agnostic@element:element(<<"select"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 73).
?DOC(" A code block with syntax highlighting. Maps to CodeRenderable.\n").
-spec code(
list(agnostic@vdom@vattr:attribute(QKO)),
list(agnostic@vdom@vnode:element(QKO))
) -> agnostic@vdom@vnode:element(QKO).
code(Attributes, Children) ->
agnostic@element:element(<<"code"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 82).
?DOC(" A markdown renderer. Maps to MarkdownRenderable.\n").
-spec markdown(
list(agnostic@vdom@vattr:attribute(QKU)),
list(agnostic@vdom@vnode:element(QKU))
) -> agnostic@vdom@vnode:element(QKU).
markdown(Attributes, Children) ->
agnostic@element:element(<<"markdown"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 91).
?DOC(" A diff viewer. Maps to DiffRenderable.\n").
-spec diff(
list(agnostic@vdom@vattr:attribute(QLA)),
list(agnostic@vdom@vnode:element(QLA))
) -> agnostic@vdom@vnode:element(QLA).
diff(Attributes, Children) ->
agnostic@element:element(<<"diff"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 100).
?DOC(" An ASCII art font element. Maps to ASCIIFontRenderable.\n").
-spec ascii_font(list(agnostic@vdom@vattr:attribute(QLG))) -> agnostic@vdom@vnode:element(QLG).
ascii_font(Attributes) ->
agnostic@element:element(<<"asciifont"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 106).
?DOC(" A tab-based select element. Maps to TabSelectRenderable.\n").
-spec tab_select(list(agnostic@vdom@vattr:attribute(QLK))) -> agnostic@vdom@vnode:element(QLK).
tab_select(Attributes) ->
agnostic@element:element(<<"tabselect"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 113).
?DOC(
" A line number gutter element. Maps to LineNumberRenderable. Wrap a code or\n"
" textarea element as a child.\n"
).
-spec line_number(
list(agnostic@vdom@vattr:attribute(QLO)),
list(agnostic@vdom@vnode:element(QLO))
) -> agnostic@vdom@vnode:element(QLO).
line_number(Attributes, Children) ->
agnostic@element:element(<<"linenumber"/utf8>>, Attributes, Children).
-file("src/agnostic/platform/opentui/element.gleam", 122).
?DOC(" A slider element. Maps to SliderRenderable.\n").
-spec slider(list(agnostic@vdom@vattr:attribute(QLU))) -> agnostic@vdom@vnode:element(QLU).
slider(Attributes) ->
agnostic@element:element(<<"slider"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 129).
?DOC(
" A frame buffer element for direct pixel-level rendering. Maps to\n"
" FrameBufferRenderable.\n"
).
-spec frame_buffer(list(agnostic@vdom@vattr:attribute(QLY))) -> agnostic@vdom@vnode:element(QLY).
frame_buffer(Attributes) ->
agnostic@element:element(<<"framebuffer"/utf8>>, Attributes, []).
-file("src/agnostic/platform/opentui/element.gleam", 160).
?DOC(
" Create a FrameBuffer element with a custom JS handler.\n"
" The handler receives the FrameBufferRenderable node when mounted,\n"
" allowing direct manipulation via node.setCell().\n"
"\n"
" Example usage:\n"
" ```gleam\n"
" // spinner.ffi.mjs\n"
" export function make_spinner_handler(color, interval_ms) {\n"
" return (node) => {\n"
" let frameIndex = 0;\n"
" const fg = parseColor(color);\n"
" const bg = { r: 0, g: 0, b: 0, a: 0 };\n"
" setInterval(() => {\n"
" node.setCell(0, 0, [\"|\", \"/\", \"-\", \"\\\\\"][frameIndex], fg, bg);\n"
" frameIndex = (frameIndex + 1) % 4;\n"
" }, interval_ms);\n"
" };\n"
" }\n"
"\n"
" // spinner.gleam\n"
" @external(javascript, \"./spinner.ffi.mjs\", \"make_spinner_handler\")\n"
" fn make_handler(color: String, interval_ms: Int) -> Json\n"
"\n"
" pub fn spinner(handler: Json, attrs: List(Attribute(msg))) -> Element(msg) {\n"
" element.frame_buffer_with_handler(handler, attrs)\n"
" }\n"
" ```\n"
).
-spec frame_buffer_with_handler(
gleam@json:json(),
list(agnostic@vdom@vattr:attribute(QMC))
) -> agnostic@vdom@vnode:element(QMC).
frame_buffer_with_handler(Handler, Attrs) ->
agnostic@element:element(
<<"framebuffer"/utf8>>,
[agnostic@attribute:property(<<"__fb_handler"/utf8>>, Handler) | Attrs],
[]
).
-file("src/agnostic/platform/opentui/element.gleam", 229).
?DOC(
" Create a raw element using a named factory function.\n"
" The factory receives the OpenTUI renderer at mount time and should return\n"
" the created renderable node.\n"
"\n"
" The `name` parameter is used for diffing: when the name changes, the old\n"
" node is destroyed and a new one is created from the factory. When the name\n"
" stays the same, the existing node persists across renders (factories are\n"
" closures that get recreated each render, so we can't compare them directly).\n"
"\n"
" This allows creating custom OpenTUI renderables (spinners, animated widgets, etc.)\n"
" without needing direct access to the renderer instance.\n"
"\n"
" For cleanup (clearing intervals, subscriptions, etc.), override `destroySelf()`\n"
" on your renderable class — OpenTUI calls this automatically when the node is\n"
" removed from the tree.\n"
"\n"
" Example usage:\n"
" ```gleam\n"
" // spinner.ffi.mjs\n"
" import { TextRenderable } from \"@opentui/core\";\n"
"\n"
" class Spinner extends TextRenderable {\n"
" #intervalId = null;\n"
" #frameIndex = 0;\n"
"\n"
" constructor(renderer, color, interval_ms) {\n"
" super(renderer, {});\n"
" this.content = FRAMES[0];\n"
" this.fg = color;\n"
" this.#intervalId = setInterval(() => {\n"
" this.#frameIndex = (this.#frameIndex + 1) % FRAMES.length;\n"
" this.content = FRAMES[this.#frameIndex];\n"
" }, interval_ms);\n"
" }\n"
"\n"
" destroySelf() {\n"
" if (this.#intervalId) clearInterval(this.#intervalId);\n"
" super.destroySelf();\n"
" }\n"
" }\n"
"\n"
" export function spinner_factory(color, interval_ms) {\n"
" return (renderer) => new Spinner(renderer, color, interval_ms);\n"
" }\n"
"\n"
" // spinner.gleam\n"
" @external(javascript, \"./spinner.ffi.mjs\", \"spinner_factory\")\n"
" fn spinner_factory(color: String, interval_ms: Int) -> RawNodeFactory\n"
"\n"
" pub fn spinner(color: String) -> Element(msg) {\n"
" raw_node(\"text-spinner\", \"box\", [], spinner_factory(color, 150))\n"
" }\n"
" ```\n"
).
-spec raw_node(
binary(),
fun((agnostic@platform@opentui:renderer()) -> agnostic@platform@opentui:node_())
) -> agnostic@vdom@vnode:element(any()).
raw_node(Name, Factory) ->
Content = {Name, Factory},
agnostic@element:unsafe_raw(
<<""/utf8>>,
Content,
{some, fun(A, B) -> erlang:element(1, A) =:= erlang:element(1, B) end}
).