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