Skip to main content

liora_components/
empty.rs

1use gpui::{AnyElement, App, IntoElement, RenderOnce, SharedString, Window, div, prelude::*, px};
2use liora_core::Config;
3use liora_icons::Icon;
4use liora_icons_lucide::IconName;
5
6pub struct Empty {
7    image: Option<AnyElement>,
8    description: SharedString,
9    extra: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyElement + 'static>>,
10}
11
12impl Empty {
13    pub fn new() -> Self {
14        Self {
15            image: None,
16            description: "暂无数据".into(),
17            extra: None,
18        }
19    }
20
21    pub fn image(mut self, image: impl IntoElement) -> Self {
22        self.image = Some(image.into_any_element());
23        self
24    }
25
26    pub fn description(mut self, d: impl Into<SharedString>) -> Self {
27        self.description = d.into();
28        self
29    }
30
31    pub fn extra<F>(mut self, f: F) -> Self
32    where
33        F: Fn(&mut Window, &mut App) -> AnyElement + 'static,
34    {
35        self.extra = Some(Box::new(f));
36        self
37    }
38}
39
40impl RenderOnce for Empty {
41    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
42        let theme = cx.global::<Config>().theme.clone();
43
44        div()
45            .flex()
46            .flex_col()
47            .items_center()
48            .justify_center()
49            .w_full()
50            .p_10()
51            .gap_4()
52            .child(
53                div()
54                    .flex()
55                    .items_center()
56                    .justify_center()
57                    .w(px(160.0))
58                    .h(px(160.0))
59                    .child(match self.image {
60                        Some(img) => img,
61                        None => Icon::new(IconName::PackageOpen)
62                            .size(px(100.0))
63                            .color(theme.neutral.text_3)
64                            .into_any_element(),
65                    }),
66            )
67            .child(
68                div()
69                    .text_sm()
70                    .text_color(theme.neutral.text_3)
71                    .child(self.description),
72            )
73            .when_some(self.extra, |s, extra| {
74                s.child(div().mt_2().child((extra)(window, cx)))
75            })
76    }
77}
78
79impl IntoElement for Empty {
80    type Element = gpui::Component<Self>;
81    fn into_element(self) -> Self::Element {
82        gpui::Component::new(self)
83    }
84}