ratatui_kit/components/
border.rs1use ratatui::{
2 symbols::border,
3 text::Line,
4 widgets::{Block, Padding, Widget},
5};
6use ratatui_kit_macros::{Props, with_layout_style};
7
8use crate::{AnyElement, Component};
9
10#[with_layout_style]
11#[derive(Props)]
12pub struct BorderProps<'a> {
13 pub padding: Padding,
14 pub border_style: ratatui::style::Style,
15 pub borders: ratatui::widgets::Borders,
16 pub border_set: border::Set,
17 pub style: ratatui::style::Style,
18 pub children: Vec<AnyElement<'a>>,
19 pub top_title: Option<Line<'static>>,
20 pub bottom_title: Option<Line<'static>>,
21}
22
23impl Default for BorderProps<'_> {
24 fn default() -> Self {
25 Self {
26 padding: Padding::default(),
27 border_style: ratatui::style::Style::default(),
28 borders: ratatui::widgets::Borders::ALL,
29 children: Vec::new(),
30 border_set: border::Set::default(),
31 style: ratatui::style::Style::default(),
32 top_title: None,
33 bottom_title: None,
34 margin: Default::default(),
35 offset: Default::default(),
36 width: Default::default(),
37 height: Default::default(),
38 gap: Default::default(),
39 flex_direction: Default::default(),
40 justify_content: Default::default(),
41 }
42 }
43}
44
45pub struct Border {
46 pub padding: Padding,
47 pub border_style: ratatui::style::Style,
48 pub borders: ratatui::widgets::Borders,
49 pub border_set: border::Set,
50 pub style: ratatui::style::Style,
51 pub top_title: Option<Line<'static>>,
52 pub bottom_title: Option<Line<'static>>,
53}
54
55impl Component for Border {
56 type Props<'a> = BorderProps<'a>;
57
58 fn new(props: &Self::Props<'_>) -> Self {
59 Self {
60 padding: props.padding,
61 border_style: props.border_style,
62 borders: props.borders,
63 border_set: props.border_set,
64 style: props.style,
65 top_title: props.top_title.clone(),
66 bottom_title: props.bottom_title.clone(),
67 }
68 }
69
70 fn update(
71 &mut self,
72 props: &mut Self::Props<'_>,
73 _hooks: crate::Hooks,
74 updater: &mut crate::ComponentUpdater,
75 ) {
76 let layout_style = props.layout_style();
77 *self = Self {
78 padding: props.padding,
79 border_style: props.border_style,
80 borders: props.borders,
81 border_set: props.border_set,
82 style: props.style,
83 top_title: props.top_title.clone(),
84 bottom_title: props.bottom_title.clone(),
85 };
86 updater.set_layout_style(layout_style);
87 updater.update_children(&mut props.children, None);
88 }
89
90 fn draw(&mut self, drawer: &mut crate::ComponentDrawer<'_, '_>) {
91 let mut block = Block::new()
92 .style(self.style)
93 .borders(self.borders)
94 .border_set(self.border_set)
95 .border_style(self.border_style)
96 .padding(self.padding);
97
98 if let Some(top_title) = &self.top_title {
99 block = block.title_top(top_title.clone());
100 }
101
102 if let Some(bottom_title) = &self.bottom_title {
103 block = block.title_bottom(bottom_title.clone());
104 }
105
106 let inner_area = block.inner(drawer.area);
107 block.render(drawer.area, drawer.buffer_mut());
108 drawer.area = inner_area;
109 }
110}