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, 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 + Unpin {
65 type Props<'a>: Props
66 where
67 Self: 'a;
68
69 fn new(props: &Self::Props<'_>) -> Self;
70
71 fn update(
72 &mut self,
73 _props: &mut Self::Props<'_>,
74 _hooks: Hooks,
75 _updater: &mut ComponentUpdater,
76 ) {
77 }
78
79 fn draw(&mut self, _drawer: &mut ComponentDrawer<'_, '_>) {}
80
81 fn calc_children_areas(
83 &self,
84 children: &Components,
85 layout_style: &LayoutStyle,
86 drawer: &mut ComponentDrawer<'_, '_>,
87 ) -> Vec<ratatui::prelude::Rect> {
88 let layout = layout_style
89 .get_layout()
90 .constraints(children.get_constraints(layout_style.flex_direction));
91
92 let areas = layout.split(drawer.area);
93
94 let mut children_areas: Vec<ratatui::prelude::Rect> = vec![];
95
96 let rev_direction = match layout_style.flex_direction {
97 Direction::Horizontal => Direction::Vertical,
98 Direction::Vertical => Direction::Horizontal,
99 };
100 for (area, constraint) in areas.iter().zip(children.get_constraints(rev_direction)) {
101 let area = Layout::new(rev_direction, [constraint]).split(*area)[0];
102 children_areas.push(area);
103 }
104
105 children_areas
106 }
107
108 fn poll_change(&mut self, _cx: &mut Context<'_>) -> std::task::Poll<()> {
109 std::task::Poll::Pending
110 }
111}
112
113#[doc(hidden)]
114pub trait AnyComponent: Any + 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(&mut self, cx: &mut Context) -> std::task::Poll<()>;
127}
128
129impl<C> ElementType for C
130where
131 C: Component,
132{
133 type Props<'a> = C::Props<'a>;
134}
135
136impl<C> AnyComponent for C
137where
138 C: Any + Component,
139{
140 fn update(&mut self, mut props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater) {
141 Component::update(
142 self,
143 unsafe { props.downcast_mut_unchecked(ComponentHelper::<C>::props_type_id()) },
144 hooks,
145 updater,
146 );
147 }
148
149 fn draw(&mut self, drawer: &mut ComponentDrawer) {
150 Component::draw(self, drawer);
151 }
152
153 fn calc_children_areas(
154 &self,
155 children: &Components,
156 layout_style: &LayoutStyle,
157 drawer: &mut ComponentDrawer,
158 ) -> Vec<ratatui::prelude::Rect> {
159 Component::calc_children_areas(self, children, layout_style, drawer)
160 }
161
162 fn poll_change(&mut self, cx: &mut Context) -> std::task::Poll<()> {
163 Component::poll_change(self, cx)
164 }
165}