import glink/style.{type Style} import glink/text import glink/use_focus import redraw.{type Component} import redraw/dom/attribute.{type Attribute} /// `box` is an essential Ink component to build your layout. It's like `
` in the browser. @external(javascript, "./glink.ffi.mjs", "box") pub fn box( styles styles: List(Style), attributes attrs: List(Attribute), children children: List(Component), ) -> Component /// [`box`](#box) without `attributes`. pub fn box_( styles styles: List(Style), children children: List(Component), ) -> Component { box(styles, [], children) } /// [`box`](#box) without `styles` and `attributes`. pub fn box__(children: List(Component)) -> Component { box([], [], children) } /// Adds one or more newline (\n) characters. Must be used within [`text`](#text) components. @external(javascript, "./glink.ffi.mjs", "newline") pub fn newline(count: Int) -> Component /// [`newline`](#newline) with `count` set to `1`. pub fn newline_() -> Component { newline(1) } /// A flexible space that expands along the major axis of its containing layout. /// It's useful as a shortcut for filling all the available spaces between elements. @external(javascript, "./glink.ffi.mjs", "spacer") pub fn spacer() -> Component /// `static` component permanently renders its output above everything else. /// It's useful for displaying activity like completed tasks or logs - things that /// are not changing after they're rendered (hence the name "static"). /// /// It's preferred to use `static` for use cases like these, when you can't know /// or control the amount of items that need to be rendered. @external(javascript, "./glink.ffi.mjs", "static_") pub fn static( items: List(a), styles: List(style.Style), children: fn(a, Int) -> #(String, Component), ) -> Component /// [`static`](#static) without `styles`. pub fn static_( items: List(a), children: fn(a, Int) -> #(String, Component), ) -> Component { static(items, [], children) } /// This component can display text, and change its style to make it colorful, bold, underline, italic or strikethrough. @external(javascript, "./glink.ffi.mjs", "text") pub fn text(props: List(text.Prop), children: List(Component)) -> Component /// [`text`](#text) that use a single `String` for its `children`. @external(javascript, "./glink.ffi.mjs", "text_") pub fn text_(props: List(text.Prop), text: String) -> Component /// [`text`](#text) without `props` and uses a single `String` for its `children`. pub fn text__(text: String) -> Component { text_([], text) } /// Function which transforms children output. It accepts children and must return transformed children too. pub type Transform = fn(String, Int) -> String /// Transform a string representation of React components before they are written to output. /// For example, you might want to apply a gradient to text, add a clickable link or create some text effects. /// These use cases can't accept React nodes as input, they are expecting a string. /// That's what `transform` component does, it gives you an output string of its child components and lets you transform it in any way. @external(javascript, "./glink.ffi.mjs", "transform") pub fn transform(transform: Transform, children: List(Component)) -> Component pub type Size { Size( /// Element width. width: Float, /// Element height. height: Float, ) } /// Measure the dimensions of a particular [`box`](#box) element. @external(javascript, "./glink.ffi.mjs", "measure_element") pub fn measure_element(node: node) -> Size pub type Instance(error) { Instance( /// Replace previous root node with a new one or update props of the current root node. rerender: fn(Component) -> Nil, /// Manually unmount the whole Ink app. unmount: fn(error) -> Nil, /// Awaits a promise, which resolves when app is unmounted. wait_until_exit: fn(fn() -> Nil) -> Nil, cleanup: fn() -> Nil, /// Clear output. clear: fn() -> Nil, ) } /// Mount a component and render the output. @external(javascript, "./glink.ffi.mjs", "render") pub fn render(component: Component) -> Instance(error) pub type App(error) { App( /// Exit (unmount) the whole Ink app. exit: fn(error) -> Nil, ) } /// `use_app` is a React hook, which exposes a method to manually exit the app (unmount). @external(javascript, "./glink.ffi.mjs", "use_app") pub fn use_app() -> App(error) pub type Focus { Focus( /// Determines whether this component is focused or not. is_focused: Bool, /// Allows focusing a specific element with the provided ID. focus: fn(String) -> Nil, ) } /// Component that uses `use_focus` hook becomes "focusable" to Ink, /// so when user presses `Tab`, Ink will switch focus to this component. /// If there are multiple components that execute `use_focus` hook, focus will be /// given to them in the order that these components are rendered in. /// This hook returns an object with `is_focused` boolean property, which /// determines if this component is focused or not. @external(javascript, "./glink.ffi.mjs", "use_focus") pub fn use_focus(props: List(use_focus.Prop)) -> Focus /// [`use_focus`](#use_focus) without `props`. pub fn use_focus_() -> Focus { use_focus([]) } pub type FocusManager { FocusManager( /// Enable focus management for all components. enable_focus: fn() -> Nil, /// Disable focus management for all components. Currently active component (if there's one) will lose its focus. disable_focus: fn() -> Nil, /// Switch focus to the next focusable component. /// If there's no active component right now, focus will be given to the first focusable component. /// If active component is the last in the list of focusable components, focus will be switched to the first component. focus_next: fn() -> Nil, /// Switch focus to the previous focusable component. /// If there's no active component right now, focus will be given to the first focusable component. /// If active component is the first in the list of focusable components, focus will be switched to the last component. focus_previous: fn() -> Nil, /// Switch focus to the element with provided ID. /// If there's no element with that ID, focus will be given to the first focusable component. focus: fn(String) -> Nil, ) } /// This hook exposes methods to enable or disable focus management for all /// components or manually switch focus to next or previous components. @external(javascript, "./glink.ffi.mjs", "use_focus_manager") pub fn use_focus_manager() -> FocusManager pub type InputHandler = fn(String, Key) -> Nil pub type Key { /// Handy information about a key that was pressed. Key( /// Up arrow key was pressed. up_arrow: Bool, /// Down arrow key was pressed. down_arrow: Bool, /// Left arrow key was pressed. left_arrow: Bool, /// Right arrow key was pressed. right_arrow: Bool, /// Page Down key was pressed. page_down: Bool, /// Page Up key was pressed. page_up: Bool, /// Return (Enter) key was pressed. return: Bool, /// Escape key was pressed. escape: Bool, /// Ctrl key was pressed. ctrl: Bool, /// Shift key was pressed. shift: Bool, /// Tab key was pressed. tab: Bool, /// Backspace key was pressed. backspace: Bool, /// Delete key was pressed. delete: Bool, /// [Meta key](https://en.wikipedia.org/wiki/Meta_key) was pressed. meta: Bool, ) } /// This hook is used for handling user input. /// It's a more convenient alternative to using `StdinContext` and listening to `data` events. /// The callback you pass to `use_input` is called for each character when user enters any input. /// However, if user pastes text and it's more than one character, the callback will be called only once and the whole string will be passed as `input`. @external(javascript, "./glink.ffi.mjs", "use_input") pub fn use_input(handler: InputHandler, is_active: Bool) -> Nil /// [use_input](#use_input) with `is_active` set to `True`. pub fn use_input_(handler: InputHandler) -> Nil { use_input(handler, True) } pub type ReadStream pub type EventEmitter pub type Stdin { Stdin( /// Stdin stream passed to `render()` in `options.stdin` or `process.stdin` by default. Useful if your app needs to handle user input. /// **NOTE: Not yet useable.** stdin: ReadStream, /// Ink exposes this function via own `` to be able to handle Ctrl+C, that's why you should use Ink's `set_raw_mode`. /// If the `stdin` stream passed to Ink does not support `set_raw_mode`, this function does nothing. set_raw_mode: fn(Bool) -> Nil, /// A boolean flag determining if the current `stdin` supports `set_raw_mode`. A component using `set_raw_mode` might want to use `is_raw_mode_supported` to nicely fall back in environments where raw mode is not supported. is_raw_mode_supported: Bool, internal_exit_on_ctrl_c: Bool, internal_event_emitter: EventEmitter, ) } /// `use_stdin` is a React hook, which exposes stdin stream. @external(javascript, "./glink.ffi.mjs", "use_stdin") pub fn use_stdin() -> Stdin pub type WriteStream pub type Stderr { Stderr( /// Stderr stream passed to `render()` in `options.stderr` or `process.stderr` by default. /// **NOTE: Not yet useable.** stderr: WriteStream, /// Write any string to stderr, while preserving Ink's output. /// It's useful when you want to display some external information outside of Ink's rendering and ensure there's no conflict between the two. /// It's similar to ``, except it can't accept components, it only works with strings. write: fn(String) -> Nil, ) } /// `use_stderr` is a React hook, which exposes stderr stream. @external(javascript, "./glink.ffi.mjs", "use_stderr") pub fn use_stderr() -> Stderr pub type Stdout { Stdout( /// Stdout stream passed to `render()` in `options.stdout` or `process.stdout` by default. /// **NOTE: Not yet useable.** stdout: WriteStream, /// Write any string to stdout, while preserving Ink's output. /// It's useful when you want to display some external information outside of Ink's rendering and ensure there's no conflict between the two. /// It's similar to ``, except it can't accept components, it only works with strings. write: fn(String) -> Nil, ) } /// `use_stdout` is a React hook, which exposes stdout stream. @external(javascript, "./glink.ffi.mjs", "use_stdout") pub fn use_stdout() -> Stdout