ratatui_kit/component/
mod.rs1use crate::{
2 element::ElementType,
3 hooks::Hooks,
4 layout_style::LayoutStyle,
5 props::{AnyProps, Props},
6 render::{ComponentDrawer, ComponentUpdater},
7};
8use std::{any::Any, pin::Pin, task::Context};
9
10mod component_helper;
11pub(crate) use component_helper::{ComponentHelper, ComponentHelperExt};
12
13mod instantiated_component;
14pub use instantiated_component::{Components, InstantiatedComponent};
15use ratatui::layout::{Direction, Layout};
16
17pub trait Component: Any + Send + Sync + Unpin {
62 type Props<'a>: Props
63 where
64 Self: 'a;
65
66 fn new(props: &Self::Props<'_>) -> Self;
67
68 fn update(
69 &mut self,
70 _props: &mut Self::Props<'_>,
71 _hooks: Hooks,
72 _updater: &mut ComponentUpdater,
73 ) {
74 }
75
76 fn draw(&mut self, drawer: &mut ComponentDrawer<'_, '_>) {
77 self.render_ref(drawer.area, drawer.buffer_mut());
78 }
79
80 fn calc_children_areas(
82 &self,
83 children: &Components,
84 layout_style: &LayoutStyle,
85 drawer: &mut ComponentDrawer<'_, '_>,
86 ) -> Vec<ratatui::prelude::Rect> {
87 let layout = layout_style
88 .get_layout()
89 .constraints(children.get_constraints(layout_style.flex_direction));
90
91 let areas = layout.split(drawer.area);
92
93 let mut children_areas: Vec<ratatui::prelude::Rect> = vec![];
94
95 let rev_direction = match layout_style.flex_direction {
96 Direction::Horizontal => Direction::Vertical,
97 Direction::Vertical => Direction::Horizontal,
98 };
99 for (area, constraint) in areas.iter().zip(children.get_constraints(rev_direction)) {
100 let area = Layout::new(rev_direction, [constraint]).split(*area)[0];
101 children_areas.push(area);
102 }
103
104 children_areas
105 }
106
107 fn poll_change(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> std::task::Poll<()> {
108 std::task::Poll::Pending
109 }
110
111 fn render_ref(&self, _area: ratatui::layout::Rect, _buf: &mut ratatui::buffer::Buffer) {}
112}
113
114pub trait AnyComponent: Any + Send + Sync + Unpin {
115 fn update(&mut self, props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater);
116
117 fn draw(&mut self, drawer: &mut ComponentDrawer);
118
119 fn calc_children_areas(
120 &self,
121 children: &Components,
122 layout_style: &LayoutStyle,
123 drawer: &mut ComponentDrawer,
124 ) -> Vec<ratatui::prelude::Rect>;
125
126 fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> std::task::Poll<()>;
127
128 fn render_ref(&self, area: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer);
129}
130
131impl<C> ElementType for C
132where
133 C: Component,
134{
135 type Props<'a> = C::Props<'a>;
136}
137
138impl<C> AnyComponent for C
139where
140 C: Any + Component,
141{
142 fn update(&mut self, mut props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater) {
143 Component::update(
144 self,
145 unsafe { props.downcast_mut_unchecked() },
146 hooks,
147 updater,
148 );
149 }
150
151 fn draw(&mut self, drawer: &mut ComponentDrawer) {
152 Component::draw(self, drawer);
153 }
154
155 fn calc_children_areas(
156 &self,
157 children: &Components,
158 layout_style: &LayoutStyle,
159 drawer: &mut ComponentDrawer,
160 ) -> Vec<ratatui::prelude::Rect> {
161 Component::calc_children_areas(self, children, layout_style, drawer)
162 }
163
164 fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> std::task::Poll<()> {
165 Component::poll_change(self, cx)
166 }
167
168 fn render_ref(&self, area: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
169 Component::render_ref(self, area, buf);
170 }
171}