1#![allow(non_snake_case)]
2use crate::{Direction, SortBy, Sortable, UseSorter};
3use dioxus::prelude::*;
4
5#[derive(Props)]
7pub struct ThProps<'a, F: 'static> {
8 sorter: UseSorter<'a, F>,
9 field: F,
10 children: Element<'a>,
11}
12
13pub fn Th<'a, F: Copy + Sortable>(cx: Scope<'a, ThProps<'a, F>>) -> Element<'a> {
15 let sorter = cx.props.sorter;
16 let field = cx.props.field;
17 cx.render(rsx! {
18 th {
19 onclick: move |_| sorter.toggle_field(field),
20 &cx.props.children
21 ThStatus {
22 sorter: sorter,
23 field: field,
24 }
25 }
26 })
27}
28
29#[derive(PartialEq, Props)]
31pub struct ThStatusProps<'a, F: 'static> {
32 sorter: UseSorter<'a, F>,
33 field: F,
34}
35
36pub fn ThStatus<'a, F: Copy + Sortable>(cx: Scope<'a, ThStatusProps<'a, F>>) -> Element<'a> {
43 let sorter = &cx.props.sorter;
44 let field = cx.props.field;
45 let (active_field, active_dir) = sorter.get_state();
46 let active = *active_field == field;
47
48 cx.render(match field.sort_by() {
49 None => rsx!(""),
50 Some(sort_by) => {
51 use Direction::*;
52 use SortBy::*;
53 match sort_by {
54 Fixed(Ascending) => rsx!(ThSpan { active: active, "↓" }),
55 Fixed(Descending) => rsx!(ThSpan { active: active, "↑" }),
56
57 Reversible(_) => rsx!(
58 ThSpan {
59 active: active,
60 match (active, active_dir) {
61 (true, Direction::Ascending) => "↓",
62 (true, Direction::Descending) => "↑",
63 (false, _) => "↕",
64 }
65 }),
66 }
67 }
68 })
69}
70
71#[derive(Props)]
73struct ThSpan<'a> {
74 active: bool,
75 children: Element<'a>,
76}
77
78fn ThSpan<'a>(cx: Scope<'a, ThSpan<'a>>) -> Element<'a> {
80 let colour = if cx.props.active { "#555" } else { "#ccc" };
81 let nbsp = " ";
82 cx.render(rsx! {
83 span {
84 style: "color: {colour};",
85 span { dangerous_inner_html: "{nbsp}", }
86 &cx.props.children
87 }
88 })
89}