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
78 fn calc_children_areas(
80 &self,
81 children: &Components,
82 layout_style: &LayoutStyle,
83 drawer: &mut ComponentDrawer<'_, '_>,
84 ) -> Vec<ratatui::prelude::Rect> {
85 let layout = layout_style
86 .get_layout()
87 .constraints(children.get_constraints(layout_style.flex_direction));
88
89 let areas = layout.split(drawer.area);
90
91 let mut children_areas: Vec<ratatui::prelude::Rect> = vec![];
92
93 let rev_direction = match layout_style.flex_direction {
94 Direction::Horizontal => Direction::Vertical,
95 Direction::Vertical => Direction::Horizontal,
96 };
97 for (area, constraint) in areas.iter().zip(children.get_constraints(rev_direction)) {
98 let area = Layout::new(rev_direction, [constraint]).split(*area)[0];
99 children_areas.push(area);
100 }
101
102 children_areas
103 }
104
105 fn poll_change(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> std::task::Poll<()> {
106 std::task::Poll::Pending
107 }
108}
109
110pub trait AnyComponent: Any + Send + Sync + Unpin {
111 fn update(&mut self, props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater);
112
113 fn draw(&mut self, drawer: &mut ComponentDrawer);
114
115 fn calc_children_areas(
116 &self,
117 children: &Components,
118 layout_style: &LayoutStyle,
119 drawer: &mut ComponentDrawer,
120 ) -> Vec<ratatui::prelude::Rect>;
121
122 fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> std::task::Poll<()>;
123}
124
125impl<C> ElementType for C
126where
127 C: Component,
128{
129 type Props<'a> = C::Props<'a>;
130}
131
132impl<C> AnyComponent for C
133where
134 C: Any + Component,
135{
136 fn update(&mut self, mut props: AnyProps, hooks: Hooks, updater: &mut ComponentUpdater) {
137 Component::update(
138 self,
139 unsafe { props.downcast_mut_unchecked() },
140 hooks,
141 updater,
142 );
143 }
144
145 fn draw(&mut self, drawer: &mut ComponentDrawer) {
146 Component::draw(self, drawer);
147 }
148
149 fn calc_children_areas(
150 &self,
151 children: &Components,
152 layout_style: &LayoutStyle,
153 drawer: &mut ComponentDrawer,
154 ) -> Vec<ratatui::prelude::Rect> {
155 Component::calc_children_areas(self, children, layout_style, drawer)
156 }
157
158 fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> std::task::Poll<()> {
159 Component::poll_change(self, cx)
160 }
161}