ratatui-kit 0.6.0

A framework for building interactive terminal user interfaces with ratatui
Documentation
use ratatui::TerminalOptions;

use super::{Element, ElementKey, element_ext::ElementExt};
use crate::{
    component::{Component, ComponentHelper, ComponentHelperExt},
    props::AnyProps,
    render::tree::render_loop,
    terminal::{CrossTerminal, Terminal},
};
use std::io;

pub struct AnyElement<'a> {
    key: ElementKey,
    props: AnyProps<'a>,
    helper: Box<dyn ComponentHelperExt>,
}

impl<'a, T> From<Element<'a, T>> for AnyElement<'a>
where
    T: Component,
{
    fn from(value: Element<'a, T>) -> Self {
        Self {
            key: value.key,
            props: AnyProps::owned(value.props),
            helper: ComponentHelper::<T>::boxed(),
        }
    }
}

impl<'a, 'b: 'a, T> From<&'a mut Element<'b, T>> for AnyElement<'a>
where
    T: Component,
{
    fn from(value: &'a mut Element<'b, T>) -> Self {
        Self {
            key: value.key.clone(),
            props: AnyProps::borrowed(&mut value.props),
            helper: ComponentHelper::<T>::boxed(),
        }
    }
}

impl<'a, 'b: 'a> From<&'a mut AnyElement<'b>> for AnyElement<'b> {
    fn from(value: &'a mut AnyElement<'b>) -> Self {
        Self {
            key: value.key.clone(),
            props: value.props.borrow(),
            helper: value.helper.copy(),
        }
    }
}

impl<'a> ElementExt for AnyElement<'a> {
    fn key(&self) -> &ElementKey {
        &self.key
    }

    fn helper(&self) -> Box<dyn ComponentHelperExt> {
        self.helper.copy()
    }

    fn props_mut(&'_ mut self) -> AnyProps<'_> {
        self.props.borrow()
    }

    async fn render_loop(&mut self, options: TerminalOptions) -> io::Result<()> {
        let terminal = Terminal::new(CrossTerminal::with_options(options)?)?;
        render_loop(self, terminal).await?;
        Ok(())
    }

    async fn fullscreen(&mut self) -> io::Result<()> {
        let terminal = Terminal::new(CrossTerminal::new()?)?;
        render_loop(self, terminal).await?;
        Ok(())
    }
}

impl<'a> ElementExt for &mut AnyElement<'a> {
    fn key(&self) -> &ElementKey {
        &self.key
    }

    fn helper(&self) -> Box<dyn ComponentHelperExt> {
        self.helper.copy()
    }

    fn props_mut(&'_ mut self) -> AnyProps<'_> {
        self.props.borrow()
    }

    async fn render_loop(&mut self, options: TerminalOptions) -> io::Result<()> {
        let terminal = Terminal::new(CrossTerminal::with_options(options)?)?;
        render_loop(&mut **self, terminal).await?;
        Ok(())
    }

    async fn fullscreen(&mut self) -> io::Result<()> {
        let terminal = Terminal::new(CrossTerminal::new()?)?;
        render_loop(&mut **self, terminal).await?;
        Ok(())
    }
}