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
113pub trait AnyComponent: Any + Unpin {
114 fn update(&mut self, props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater);
115
116 fn draw(&mut self, drawer: &mut ComponentDrawer);
117
118 fn calc_children_areas(
119 &self,
120 children: &Components,
121 layout_style: &LayoutStyle,
122 drawer: &mut ComponentDrawer,
123 ) -> Vec<ratatui::prelude::Rect>;
124
125 fn poll_change(&mut self, cx: &mut Context) -> std::task::Poll<()>;
126}
127
128impl<C> ElementType for C
129where
130 C: Component,
131{
132 type Props<'a> = C::Props<'a>;
133}
134
135impl<C> AnyComponent for C
136where
137 C: Any + Component,
138{
139 fn update(&mut self, mut props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater) {
140 Component::update(
141 self,
142 unsafe { props.downcast_mut_unchecked(ComponentHelper::<C>::props_type_id()) },
143 hooks,
144 updater,
145 );
146 }
147
148 fn draw(&mut self, drawer: &mut ComponentDrawer) {
149 Component::draw(self, drawer);
150 }
151
152 fn calc_children_areas(
153 &self,
154 children: &Components,
155 layout_style: &LayoutStyle,
156 drawer: &mut ComponentDrawer,
157 ) -> Vec<ratatui::prelude::Rect> {
158 Component::calc_children_areas(self, children, layout_style, drawer)
159 }
160
161 fn poll_change(&mut self, cx: &mut Context) -> std::task::Poll<()> {
162 Component::poll_change(self, cx)
163 }
164}