leptos_struct_table/
cell_value.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use leptos::prelude::*;

#[derive(Default, Clone, Copy)]
pub struct NumberRenderOptions {
    /// Specifies the number of digits to display after the decimal point
    pub precision: Option<usize>,
}

/// A value that can be rendered as part of a table, required for types if the [`crate::DefaultTableCellRenderer()`] is used
pub trait CellValue<M: ?Sized = ()> {
    /// Formatting options for this cell value type, needs to implement default and have public named fields,
    /// the empty tuple: () is fine if no formatting options can be accepted.
    type RenderOptions: Default + Clone + Send + Sync + 'static;

    /// This is called to actually render the value. The parameter `options` is filled by the `#[table(format(...))]` macro attribute or `Default::default()` if omitted.
    fn render_value(self, options: Self::RenderOptions) -> impl IntoView;
}

impl<V> CellValue<()> for V
where
    V: IntoView,
{
    type RenderOptions = ();

    fn render_value(self, _options: Self::RenderOptions) -> impl IntoView {
        self
    }
}

macro_rules! viewable_primitive {
  ($($child_type:ty),* $(,)?) => {
    $(
      impl CellValue<$child_type> for $child_type {
        type RenderOptions = ();

        #[inline(always)]
        fn render_value(self, _options: Self::RenderOptions) -> impl IntoView {
            self.to_string()
        }
      }
    )*
  };
}

viewable_primitive![
    &String,
    char,
    bool,
    std::net::IpAddr,
    std::net::SocketAddr,
    std::net::SocketAddrV4,
    std::net::SocketAddrV6,
    std::net::Ipv4Addr,
    std::net::Ipv6Addr,
    std::char::ToUppercase,
    std::char::ToLowercase,
    std::num::NonZeroI8,
    std::num::NonZeroU8,
    std::num::NonZeroI16,
    std::num::NonZeroU16,
    std::num::NonZeroI32,
    std::num::NonZeroU32,
    std::num::NonZeroI64,
    std::num::NonZeroU64,
    std::num::NonZeroI128,
    std::num::NonZeroU128,
    std::num::NonZeroIsize,
    std::num::NonZeroUsize,
    std::panic::Location<'_>,
];

macro_rules! viewable_number_primitive {
  ($($child_type:ty),* $(,)?) => {
    $(
      impl CellValue<$child_type> for $child_type {
        type RenderOptions = NumberRenderOptions;

        #[inline(always)]
        fn render_value(self, options: Self::RenderOptions) -> impl IntoView {
        if let Some(value) = options.precision.as_ref() {
            view! {
                <>{format!("{:.value$}", self)}</>
            }
        }
        else {
            view! {
                <>{self.to_string()}</>
            }
        }
        }
      }
    )*
  };
}

viewable_number_primitive![
    usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64,
];