leptos_struct_table/
cell_value.rs

1use std::borrow::Cow;
2
3use leptos::{view, Fragment, IntoView, View};
4
5#[derive(Default)]
6pub struct NumberRenderOptions {
7    /// Specifies the number of digits to display after the decimal point
8    pub precision: Option<usize>,
9}
10
11/// A value that can be rendered as part of a table, required for types if the [`crate::DefaultTableCellRenderer()`] is used
12pub trait CellValue {
13    /// Formatting options for this cell value type, needs to implement default and have public named fields,
14    /// the empty tuple: () is fine if no formatting options can be accepted.
15    type RenderOptions: Default;
16
17    /// This is called to actually render the value. The parameter `options` is filled by the `#[table(format(...))]` macro attribute or `Default::default()` if omitted.
18    fn render_value(self, options: &Self::RenderOptions) -> impl IntoView;
19}
20
21macro_rules! viewable_identity {
22    ($($ty:ty),* $(,)?) => {
23        $(
24            impl CellValue for $ty {
25                type RenderOptions = ();
26
27                fn render_value(self, _options: &Self::RenderOptions) -> impl IntoView {
28                    self
29                }
30            }
31        )*
32    };
33}
34
35viewable_identity![String, &'static str, Cow<'static, str>, View, Fragment];
36
37macro_rules! viewable_primitive {
38  ($($child_type:ty),* $(,)?) => {
39    $(
40      impl CellValue for $child_type {
41        type RenderOptions = ();
42
43        #[inline(always)]
44        fn render_value(self, _options: &Self::RenderOptions) -> impl IntoView {
45            self.to_string()
46        }
47      }
48    )*
49  };
50}
51
52viewable_primitive![
53    &String,
54    char,
55    bool,
56    std::net::IpAddr,
57    std::net::SocketAddr,
58    std::net::SocketAddrV4,
59    std::net::SocketAddrV6,
60    std::net::Ipv4Addr,
61    std::net::Ipv6Addr,
62    std::char::ToUppercase,
63    std::char::ToLowercase,
64    std::num::NonZeroI8,
65    std::num::NonZeroU8,
66    std::num::NonZeroI16,
67    std::num::NonZeroU16,
68    std::num::NonZeroI32,
69    std::num::NonZeroU32,
70    std::num::NonZeroI64,
71    std::num::NonZeroU64,
72    std::num::NonZeroI128,
73    std::num::NonZeroU128,
74    std::num::NonZeroIsize,
75    std::num::NonZeroUsize,
76    std::panic::Location<'_>,
77];
78
79macro_rules! viewable_number_primitive {
80  ($($child_type:ty),* $(,)?) => {
81    $(
82      impl CellValue for $child_type {
83        type RenderOptions = NumberRenderOptions;
84
85        #[inline(always)]
86        fn render_value(self, options: &Self::RenderOptions) -> impl IntoView {
87        if let Some(value) = options.precision.as_ref() {
88            view! {
89                <>{format!("{:.value$}", self)}</>
90            }
91        }
92        else {
93            view! {
94                <>{self.to_string()}</>
95            }
96        }
97        }
98      }
99    )*
100  };
101}
102
103viewable_number_primitive![
104    usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64,
105];