ratatui_kit/element/
mod.rs

1use crate::{
2    AnyProps, Component, ComponentHelper, ComponentHelperExt, CrossTerminal, Terminal,
3    tree::render_loop,
4};
5use std::io;
6mod key;
7pub use key::ElementKey;
8mod any_element;
9pub use any_element::AnyElement;
10mod element_ext;
11pub use element_ext::ElementExt;
12mod extend_with_elements;
13pub use extend_with_elements::{ExtendWithElements, extend_with_elements};
14use ratatui::TerminalOptions;
15
16pub trait ElementType {
17    type Props<'a>
18    where
19        Self: 'a;
20}
21
22#[derive(Clone)]
23pub struct Element<'a, T: ElementType + 'a> {
24    pub key: ElementKey,
25    pub props: T::Props<'a>,
26}
27
28impl<'a, T> Element<'a, T>
29where
30    T: Component + 'a,
31{
32    pub fn into_any(self) -> AnyElement<'a> {
33        self.into()
34    }
35}
36
37impl<'a, T> ElementExt for Element<'a, T>
38where
39    T: Component,
40{
41    fn key(&self) -> &ElementKey {
42        &self.key
43    }
44
45    fn helper(&self) -> Box<dyn ComponentHelperExt> {
46        ComponentHelper::<T>::boxed()
47    }
48
49    fn props_mut(&mut self) -> AnyProps {
50        AnyProps::borrowed(&mut self.props)
51    }
52
53    async fn render_loop(&mut self, options: TerminalOptions) -> io::Result<()> {
54        let terminal = Terminal::new(CrossTerminal::with_options(options)?)?;
55        render_loop(self, terminal).await?;
56        Ok(())
57    }
58
59    async fn fullscreen(&mut self) -> io::Result<()> {
60        let terminal = Terminal::new(CrossTerminal::new()?)?;
61        render_loop(self, terminal).await?;
62        Ok(())
63    }
64}
65
66impl<'a, T> ElementExt for &mut Element<'a, T>
67where
68    T: Component,
69{
70    fn key(&self) -> &ElementKey {
71        &self.key
72    }
73
74    fn helper(&self) -> Box<dyn ComponentHelperExt> {
75        ComponentHelper::<T>::boxed()
76    }
77
78    fn props_mut(&mut self) -> AnyProps {
79        AnyProps::borrowed(&mut self.props)
80    }
81
82    async fn render_loop(&mut self, options: TerminalOptions) -> io::Result<()> {
83        let terminal = Terminal::new(CrossTerminal::with_options(options)?)?;
84        render_loop(&mut **self, terminal).await?;
85        Ok(())
86    }
87
88    async fn fullscreen(&mut self) -> io::Result<()> {
89        let terminal = Terminal::new(CrossTerminal::new()?)?;
90        render_loop(&mut **self, terminal).await?;
91        Ok(())
92    }
93}