diff --git a/grid_form.scss b/grid_form.scss index fe58d19..7877d6f 100644 --- a/grid_form.scss +++ b/grid_form.scss @@ -69,7 +69,7 @@ color: #ef4444; } -.form_submit { +.form_button { display: block; outline: none; border: none; @@ -89,7 +89,6 @@ background-color: #005fb3; } - // column widths .col-span-full { grid-column: 1 / -1; diff --git a/src/controls/button.rs b/src/controls/button.rs new file mode 100644 index 0000000..1b72b24 --- /dev/null +++ b/src/controls/button.rs @@ -0,0 +1,55 @@ +use super::{ControlRenderData, VanityControlBuilder, VanityControlData}; +use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; +use leptos::{RwSignal, Signal, View}; +use std::rc::Rc; +use web_sys::MouseEvent; + +#[derive(Clone)] +pub struct ButtonData { + pub(crate) text: String, + pub(crate) action: Option>, + + // this will need to be set before calling the build method + pub(crate) fd_signal: RwSignal, +} + +impl VanityControlData for ButtonData { + fn build_control( + fs: &FS, + control: ControlRenderData, + _value_getter: Option>, + ) -> View { + fs.button(control) + } +} + +impl FormBuilder { + pub fn button( + mut self, + builder: impl Fn( + VanityControlBuilder>, + ) -> VanityControlBuilder>, + ) -> Self { + let data = ButtonData { + text: String::default(), + action: None, + fd_signal: self.fd, + }; + let vanity_builder = VanityControlBuilder::new(data); + let control = builder(vanity_builder); + self.add_vanity(control); + self + } +} + +impl VanityControlBuilder> { + pub fn text(mut self, text: impl ToString) -> Self { + self.data.text = text.to_string(); + self + } + + pub fn action(mut self, action: impl Fn(MouseEvent, &mut FD) + 'static) -> Self { + self.data.action = Some(Rc::new(action)); + self + } +} diff --git a/src/controls/mod.rs b/src/controls/mod.rs index 65dedae..c18825f 100644 --- a/src/controls/mod.rs +++ b/src/controls/mod.rs @@ -2,6 +2,7 @@ use crate::{form::FormToolData, styles::FormStyle}; use leptos::{RwSignal, Signal, View}; use std::{fmt::Display, rc::Rc, str::FromStr}; +pub mod button; pub mod checkbox; pub mod group; pub mod heading; diff --git a/src/form_builder.rs b/src/form_builder.rs index 204cbd4..bf9a004 100644 --- a/src/form_builder.rs +++ b/src/form_builder.rs @@ -21,7 +21,7 @@ use web_sys::{FormData, SubmitEvent}; /// This builder allows you to specify what components should make up the form. pub struct FormBuilder { /// The [`ToolFormData`] signal. - fd: RwSignal, + pub(crate) fd: RwSignal, /// The [`FormStyle`]. fs: FS, /// The list of [`ValidationFn`]s. diff --git a/src/styles/grid_form.rs b/src/styles/grid_form.rs index e010949..b79a0de 100644 --- a/src/styles/grid_form.rs +++ b/src/styles/grid_form.rs @@ -6,6 +6,7 @@ use crate::controls::{ }; use leptos::*; use std::rc::Rc; +use web_sys::MouseEvent; pub enum GridFormStylingAttributes { Width(u32), @@ -112,8 +113,10 @@ impl FormStyle for GridFormStyle { } fn submit(&self, control: ControlRenderData) -> View { - view! { } - .into_view() + view! { + + } + .into_view() } fn text_area( @@ -353,4 +356,31 @@ impl FormStyle for GridFormStyle { fn group(&self, _control: ControlRenderData) -> View { todo!() } + + fn button( + &self, + control: ControlRenderData>, + ) -> View { + let mut width = 1; + for style in control.style { + match style { + GridFormStylingAttributes::Width(w) => width = w, + } + } + + let action = control.data.action.clone(); + let signal = control.data.fd_signal.clone(); + let on_click = move |ev: MouseEvent| { + if let Some(action) = action.clone() { + signal.update(|fd| action(ev, fd)); + } + }; + + view! { + + } + .into_view() + } } diff --git a/src/styles/mod.rs b/src/styles/mod.rs index dcd2ab7..6fb1812 100644 --- a/src/styles/mod.rs +++ b/src/styles/mod.rs @@ -1,11 +1,14 @@ mod grid_form; pub use grid_form::{GridFormStyle, GridFormStylingAttributes}; -use crate::controls::{ - checkbox::CheckboxData, group::GroupData, heading::HeadingData, hidden::HiddenData, - output::OutputData, radio_buttons::RadioButtonsData, select::SelectData, slider::SliderData, - stepper::StepperData, submit::SubmitData, text_area::TextAreaData, text_input::TextInputData, - ControlData, ControlRenderData, +use crate::{ + controls::{ + button::ButtonData, checkbox::CheckboxData, group::GroupData, heading::HeadingData, + hidden::HiddenData, output::OutputData, radio_buttons::RadioButtonsData, + select::SelectData, slider::SliderData, stepper::StepperData, submit::SubmitData, + text_area::TextAreaData, text_input::TextInputData, ControlData, ControlRenderData, + }, + FormToolData, }; use leptos::{Signal, View}; @@ -54,6 +57,7 @@ pub trait FormStyle: Default + 'static { value_setter: Box::ReturnType)>, validation_state: Signal>, ) -> View; + fn button(&self, control: ControlRenderData>) -> View; fn checkbox( &self, control: ControlRenderData,