a2ui_tui/components/
modal.rs1use ratatui::{Frame, layout::Rect};
4
5use a2ui_base::model::component_context::ComponentContext;
6use a2ui_base::protocol::common_types::DynamicBoolean;
7use crate::component_impl::TuiComponent;
8
9pub struct ModalComponent;
15
16impl TuiComponent for ModalComponent {
17 fn name(&self) -> &'static str {
18 "Modal"
19 }
20
21 fn render(
22 &self,
23 ctx: &ComponentContext,
24 area: Rect,
25 frame: &mut Frame,
26 render_child: &mut dyn FnMut(&str, Rect, &mut Frame, &str),
27 _measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
28 ) {
29 let comp_model = match ctx.components.get(&ctx.component_id) {
30 Some(m) => m,
31 None => return,
32 };
33
34 let is_open = comp_model
36 .get_property::<DynamicBoolean>("isOpen")
37 .map(|db| ctx.data_context.resolve_dynamic_boolean(&db))
38 .unwrap_or(false);
39
40 if is_open {
41 if let Some(content_id) = comp_model.get_property::<String>("content") {
43 if area.width > 0 && area.height > 0 {
44 render_child(&content_id, area, frame, "");
45 }
46 }
47 } else {
48 if let Some(trigger_id) = comp_model.get_property::<String>("trigger") {
50 if area.width > 0 && area.height > 0 {
51 render_child(&trigger_id, area, frame, "");
52 }
53 }
54 }
55 }
56
57 fn natural_height(
58 &self,
59 ctx: &ComponentContext,
60 available_width: u16,
61 measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
62 ) -> Option<u16> {
63 let comp_model = ctx.components.get(&ctx.component_id)?;
64 let is_open = comp_model
65 .get_property::<DynamicBoolean>("isOpen")
66 .map(|db| ctx.data_context.resolve_dynamic_boolean(&db))
67 .unwrap_or(false);
68 let child_id = comp_model.get_property::<String>(if is_open { "content" } else { "trigger" })?;
69 measure_child(&child_id, "", available_width)
70 }
71}