1use dioxus::prelude::*;
2use freya_elements::{
3 self as dioxus_elements,
4 events::MouseEvent,
5};
6use freya_hooks::{
7 use_applied_theme,
8 FontTheme,
9 TableTheme,
10 TableThemeWith,
11};
12
13use crate::icons::ArrowIcon;
14
15#[allow(non_snake_case)]
16#[component]
17fn TableArrow(order_direction: OrderDirection) -> Element {
18 let TableTheme { arrow_fill, .. } = use_applied_theme!(None, table);
19 let rotate = match order_direction {
20 OrderDirection::Down => "0",
21 OrderDirection::Up => "180",
22 };
23
24 rsx!(ArrowIcon {
25 rotate: "{rotate}",
26 fill: "{arrow_fill}"
27 })
28}
29
30#[derive(Props, Clone, PartialEq)]
32pub struct TableHeadProps {
33 pub children: Element,
35}
36
37#[allow(non_snake_case)]
39pub fn TableHead(TableHeadProps { children }: TableHeadProps) -> Element {
40 rsx!(
41 rect { width: "100%", {children} }
42 )
43}
44
45#[derive(Props, Clone, PartialEq)]
47pub struct TableBodyProps {
48 pub children: Element,
50}
51
52#[allow(non_snake_case)]
54pub fn TableBody(TableBodyProps { children }: TableBodyProps) -> Element {
55 rsx!(
56 rect { width: "100%", {children} }
57 )
58}
59
60#[derive(PartialEq, Clone, Copy)]
61enum TableRowState {
62 Idle,
63 Hovering,
64}
65
66#[derive(Props, Clone, PartialEq)]
68pub struct TableRowProps {
69 pub theme: Option<TableThemeWith>,
71 children: Element,
73}
74
75#[allow(non_snake_case)]
80pub fn TableRow(TableRowProps { theme, children }: TableRowProps) -> Element {
81 let theme = use_applied_theme!(&theme, table);
82 let mut state = use_signal(|| TableRowState::Idle);
83 let TableTheme {
84 divider_fill,
85 hover_row_background,
86 row_background,
87 ..
88 } = theme;
89 let background = if state() == TableRowState::Hovering {
90 hover_row_background
91 } else {
92 row_background
93 };
94
95 rsx!(
96 rect {
97 onmouseenter: move |_| state.set(TableRowState::Hovering),
98 onmouseleave: move |_| state.set(TableRowState::Idle),
99 direction: "horizontal",
100 width: "fill",
101 background: "{background}",
102 {children}
103 }
104 rect {
105 height: "1",
106 width: "fill",
107 background: "{divider_fill}"
108 }
109 )
110}
111
112#[derive(Clone, Copy, PartialEq, Debug, Default)]
114pub enum OrderDirection {
115 Up,
117 #[default]
119 Down,
120}
121
122#[derive(Props, Clone, PartialEq)]
124pub struct TableCellProps {
125 pub children: Element,
127 pub onpress: Option<EventHandler<MouseEvent>>,
129 #[props(into)]
133 pub order_direction: Option<Option<OrderDirection>>,
134 #[props(default = "5 25".to_string(), into)]
136 pub padding: String,
137 #[props(default = "35".to_string(), into)]
139 pub height: String,
140}
141
142#[allow(non_snake_case)]
144pub fn TableCell(props: TableCellProps) -> Element {
145 let config = consume_context::<TableConfig>();
146 let width = 100.0 / config.columns as f32;
147 let TableCellProps {
148 children,
149 order_direction,
150 padding,
151 height,
152 ..
153 } = &props;
154
155 rsx!(
156 rect {
157 overflow: "clip",
158 padding: "{padding}",
159 width: "{width}%",
160 main_align: "end",
161 cross_align: "center",
162 height: "{height}",
163 direction: "horizontal",
164 onclick: move |e| {
165 if let Some(onpress) = &props.onpress {
166 onpress.call(e);
167 }
168 },
169 if let Some(order_direction) = &order_direction {
170 rect {
171 margin: "10",
172 width: "10",
173 height: "10",
174 if let Some(order_direction) = &order_direction {
175 TableArrow {
176 order_direction: *order_direction
177 }
178 }
179 }
180 }
181 {children}
182 }
183 )
184}
185
186#[derive(Props, Clone, PartialEq)]
188pub struct TableProps {
189 #[props(default = "fill".into())]
191 pub height: String,
192 pub theme: Option<TableThemeWith>,
194 pub columns: usize,
196 pub children: Element,
198}
199
200#[allow(non_snake_case)]
205pub fn Table(
206 TableProps {
207 height,
208 theme,
209 columns,
210 children,
211 }: TableProps,
212) -> Element {
213 let TableTheme {
214 background,
215 corner_radius,
216 divider_fill,
217 font_theme: FontTheme { color },
218 ..
219 } = use_applied_theme!(&theme, table);
220 provide_context(TableConfig { columns });
221
222 rsx!(rect {
223 overflow: "clip",
224 color: "{color}",
225 background: "{background}",
226 corner_radius: "{corner_radius}",
227 height: "{height}",
228 border: "1 outer {divider_fill}",
229 {children}
230 })
231}
232
233#[doc(hidden)]
234#[derive(Clone)]
235pub struct TableConfig {
236 columns: usize,
237}