/// This module provides functions to create Ink components import gleam/json.{type Json} import pink/attribute.{type Attribute} /// A ReactNode is a representation of a component in the Ink library. pub type ReactNode /// Make a ReactNode from a function /// This is needed to use React hooks in the function /// /// ## Examples /// ```gleam /// use <- component() /// let is_loading = hook.state(False) /// ```` @external(javascript, "./react_ffi.mjs", "component") pub fn component(element: fn() -> ReactNode) -> ReactNode /// Wrapper for a fragment element @external(javascript, "./react_ffi.mjs", "fragment") fn react_fragment(attributes: Json, children: List(ReactNode)) -> ReactNode /// Render a ReactNode to the terminal /// This is the main function to use to render components /// /// ## Examples /// ```gleam /// render( /// box( /// [ /// attribute.flex_direction(attribute.FlexColumn), /// attribute.gap(1), /// ], /// [ /// text([], "Hello, "), /// text([attribute.underline(True)], "world!"), /// ] /// ) /// ) /// ``` @external(javascript, "./ink_ffi.mjs", "render") pub fn render(component: ReactNode) -> Nil /// Wrapper for a box element @external(javascript, "./ink_ffi.mjs", "box") fn ink_box(attributes: Json, children: List(ReactNode)) -> ReactNode /// Wrapper for a text element @external(javascript, "./ink_ffi.mjs", "text") fn ink_text(attributes: Json, content: String) -> ReactNode /// Wrapper for a text element with children elements @external(javascript, "./ink_ffi.mjs", "text") fn ink_text_nested(attributes: Json, children: List(ReactNode)) -> ReactNode /// Wrapper for a newline element @external(javascript, "./ink_ffi.mjs", "newline") fn ink_newline(attributes: Json) -> ReactNode /// Wrapper for a spacer element @external(javascript, "./ink_ffi.mjs", "spacer") fn ink_spacer() -> ReactNode /// Wrapper for a static element @external(javascript, "./ink_ffi.mjs", "static_") fn ink_static(items: List(a), child: fn(a, Int) -> ReactNode) -> ReactNode /// Spinner component for Ink. Uses [cli-spinners](https://github.com/sindresorhus/cli-spinners) for the collection of spinners. /// /// ## Examples /// ```gleam /// spinner(type_: "dots") /// ``` @external(javascript, "./ink_spinner_ffi.mjs", "spinner") pub fn spinner(type_ type_: String) -> ReactNode /// Wrapper for a transform element @external(javascript, "./ink_ffi.mjs", "transform") fn ink_transform( transform: fn(String, Int) -> String, children: List(ReactNode), ) -> ReactNode /// This component can display text, and change its style to make it bold, underline, italic or strikethrough. /// It only supports text content. If you need to display other components within text, use `text_nested` instead. /// /// ## Examples /// ```gleam /// text(with: [], displaying: "Hello, world!") /// ``` pub fn text( with attributes: List(Attribute), displaying content: String, ) -> ReactNode { attributes |> attribute.encode |> ink_text(content) } /// The same as `text`, but allows you to nest other components within text. /// /// ## Examples /// ```gleam /// text_nested(attr: [], content: [ /// text([attribute.bold(True)], "Hello, "), /// text([attribute.underline(True)], "world!"), /// ]) /// ``` pub fn text_nested( attr attributes: List(Attribute), content children: List(ReactNode), ) -> ReactNode { attributes |> attribute.encode |> ink_text_nested(children) } /// Creates a new ReactNode with the given element and children fn node( element: fn(Json, List(ReactNode)) -> ReactNode, attributes: List(Attribute), children: List(ReactNode), ) -> ReactNode { attributes |> attribute.encode |> element(children) } /// A React fragment is a way to group multiple elements together /// without adding extra nodes to the DOM. /// /// ## Examples /// ```gleam /// fragment(attr: [], elements: [ /// box([attribute.padding(1)], [pink.text([], "Hello, ")]), /// text([attribute.underline(True)], "world!"), /// ]) /// ``` pub fn fragment( attr attributes: List(Attribute), elements children: List(ReactNode), ) -> ReactNode { node(react_fragment, attributes, children) } /// `box` is an essential Ink component to build your layout. /// /// It's like a `