tablo_core/schema/fields/
custom.rs1use tablo_ui::checkbox as ui_checkbox;
5use topcoat::{context::Cx, view::*};
6
7pub trait Control: Send + Sync {
30 fn render<'a>(&self, cx: &'a Cx, input: ControlInput) -> BoxView<'a>;
31}
32
33#[derive(Debug, Clone)]
36pub struct ControlInput {
37 name: String,
38 id: String,
39 value: Option<String>,
40 required: bool,
41 invalid: bool,
42 described_by: Option<String>,
43}
44
45impl ControlInput {
46 pub(crate) fn new(
47 name: &str,
48 id: &str,
49 value: Option<&str>,
50 required: bool,
51 invalid: bool,
52 described_by: Option<String>,
53 ) -> Self {
54 Self {
55 name: name.to_string(),
56 id: id.to_string(),
57 value: value.map(str::to_string),
58 required,
59 invalid,
60 described_by,
61 }
62 }
63
64 pub fn name(&self) -> &str {
65 &self.name
66 }
67
68 pub fn id(&self) -> &str {
71 &self.id
72 }
73
74 pub fn value(&self) -> Option<&str> {
75 self.value.as_deref()
76 }
77
78 pub fn required(&self) -> bool {
79 self.required
80 }
81
82 pub fn invalid(&self) -> bool {
83 self.invalid
84 }
85
86 pub fn described_by(&self) -> Option<&str> {
87 self.described_by.as_deref()
88 }
89
90 pub fn attributes(&self, cx: &Cx) -> Attributes {
91 let required = self.required;
92 attributes! {
93 cx =>
94 id=(self.id.clone())
95 name=(self.name.clone())
96 value=(self.value.clone())
97 required=(required)
98 aria-required=(required.then_some("true"))
99 aria-invalid=(if self.invalid { "true" } else { "false" })
100 aria-describedby=(self.described_by.clone())
101 }
102 }
103}
104
105#[derive(Debug, Clone, Copy, Default)]
107pub struct Toggle;
108
109impl Control for Toggle {
110 fn render<'a>(&self, cx: &'a Cx, input: ControlInput) -> BoxView<'a> {
111 let name = input.name().to_string();
112 let id = input.id().to_string();
113 let checked = input.value().is_some_and(|v| v.trim() == "true");
114 let invalid = if input.invalid() { "true" } else { "false" };
115 let described_by = input.described_by().map(str::to_string);
116 view! {
117 cx =>
118 <input type="hidden" name=(name.clone()) value="false">
119 ui_checkbox(
120 attrs: attributes! {
121 id=(id)
122 name=(name)
123 value="true"
124 checked=(checked)
125 aria-invalid=(invalid)
126 aria-describedby=(described_by)
127 }
128 )
129 }
130 .boxed()
131 }
132}