generated from mitchell/rust_template
second round of impl
This commit is contained in:
parent
bf6529cc1d
commit
fbe746702a
@ -1,30 +1,37 @@
|
||||
use leptos::View;
|
||||
|
||||
use crate::{ControlBuilder, ControlData, FormBuilder, FormData, FormStyleProvider};
|
||||
use super::{VanityControl, VanityControlBuilder, VanityControlData};
|
||||
use crate::{
|
||||
form::{FormBuilder, FormData},
|
||||
styles::FormStyle,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct HeadingData {
|
||||
pub(crate) title: String,
|
||||
}
|
||||
|
||||
impl HeadingData {
|
||||
fn new(title: String) -> Self {
|
||||
HeadingData { title }
|
||||
impl VanityControlData for HeadingData {
|
||||
fn build_control<FD: FormData, FS: FormStyle>(
|
||||
fs: &FS,
|
||||
control: VanityControl<FS, Self>,
|
||||
) -> View {
|
||||
fs.heading(control)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FS: FormStyleProvider> ControlData<FS> for HeadingData {
|
||||
fn build_control(self, fs: &FS, attributes: Vec<FS::StylingAttributes>) -> View {
|
||||
fs.heading(self, attributes)
|
||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn heading(
|
||||
self,
|
||||
builder: impl Fn(VanityControlBuilder<FS, HeadingData>) -> VanityControl<FS, HeadingData>,
|
||||
) -> Self {
|
||||
self.new_vanity(builder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> FormBuilder<FD, FS> {
|
||||
pub fn heading(self, title: impl ToString) -> ControlBuilder<FD, FS, HeadingData> {
|
||||
ControlBuilder {
|
||||
fb: self,
|
||||
parse_fn: None,
|
||||
style_attributes: Vec::new(),
|
||||
data: HeadingData::new(title.to_string()),
|
||||
}
|
||||
impl<FS: FormStyle> VanityControlBuilder<FS, HeadingData> {
|
||||
pub fn title(mut self, title: impl ToString) -> Self {
|
||||
self.data.title = title.to_string();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,119 @@
|
||||
use crate::{form::FormData, styles::FormStyle};
|
||||
use leptos::View;
|
||||
|
||||
pub mod heading;
|
||||
pub mod select;
|
||||
pub mod submit;
|
||||
pub mod text_area;
|
||||
pub mod text_input;
|
||||
|
||||
pub type ValidationFn<FD> = dyn Fn(&FD) -> Result<(), String> + 'static;
|
||||
pub type ParseFn<FD, CReturnType> = dyn Fn(CReturnType, &mut FD) -> Result<(), String> + 'static;
|
||||
|
||||
pub trait VanityControlData: 'static {
|
||||
fn build_control<FD: FormData, FS: FormStyle>(
|
||||
fs: &FS,
|
||||
control: VanityControl<FS, Self>,
|
||||
) -> View;
|
||||
}
|
||||
|
||||
pub trait ControlData: 'static {
|
||||
type ReturnType;
|
||||
|
||||
// TODO: this should also return a getter for the data
|
||||
fn build_control<FD: FormData, FS: FormStyle>(fs: &FS, control: Control<FD, FS, Self>) -> View;
|
||||
}
|
||||
|
||||
pub struct VanityControl<FS: FormStyle + ?Sized, C: VanityControlData + ?Sized> {
|
||||
pub data: Box<C>,
|
||||
pub style: Vec<FS::StylingAttributes>,
|
||||
}
|
||||
|
||||
pub struct Control<FD: FormData + ?Sized, FS: FormStyle + ?Sized, C: ControlData + ?Sized> {
|
||||
pub data: Box<C>,
|
||||
pub parse_fn: Box<ParseFn<FD, C::ReturnType>>,
|
||||
pub validation: Box<ValidationFn<FD>>,
|
||||
pub style: Vec<FS::StylingAttributes>,
|
||||
}
|
||||
pub struct VanityControlBuilder<FS: FormStyle, C: VanityControlData> {
|
||||
style_attributes: Vec<FS::StylingAttributes>,
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<FS: FormStyle, C: VanityControlData> VanityControlBuilder<FS, C> {
|
||||
pub(crate) fn new(data: C) -> Self {
|
||||
VanityControlBuilder {
|
||||
data,
|
||||
style_attributes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(self) -> VanityControl<FS, C> {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
impl<FS: FormStyle, C: VanityControlData> Into<VanityControl<FS, C>>
|
||||
for VanityControlBuilder<FS, C>
|
||||
{
|
||||
fn into(self) -> VanityControl<FS, C> {
|
||||
VanityControl {
|
||||
data: Box::new(self.data),
|
||||
style: self.style_attributes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ControlBuilder<FD: FormData, FS: FormStyle, C: ControlData> {
|
||||
parse_fn: Box<ParseFn<FD, C::ReturnType>>,
|
||||
validation_fn: Box<ValidationFn<FD>>,
|
||||
style_attributes: Vec<FS::StylingAttributes>,
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyle, C: ControlData> ControlBuilder<FD, FS, C> {
|
||||
pub(crate) fn new(data: C) -> Self {
|
||||
ControlBuilder {
|
||||
data,
|
||||
parse_fn: Box::new(|_, _| Ok(())),
|
||||
validation_fn: Box::new(|_| Ok(())),
|
||||
style_attributes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(self) -> Control<FD, FS, C> {
|
||||
self.into()
|
||||
}
|
||||
|
||||
pub fn parse_fn(
|
||||
mut self,
|
||||
parse_fn: impl Fn(C::ReturnType, &mut FD) -> Result<(), String> + 'static,
|
||||
) -> Self {
|
||||
self.parse_fn = Box::new(parse_fn) as Box<ParseFn<FD, C::ReturnType>>;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn validation_fn(
|
||||
mut self,
|
||||
validation_fn: impl Fn(&FD) -> Result<(), String> + 'static,
|
||||
) -> Self {
|
||||
self.validation_fn = Box::new(validation_fn) as Box<ValidationFn<FD>>;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn style(mut self, attribute: FS::StylingAttributes) -> Self {
|
||||
self.style_attributes.push(attribute);
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<FD: FormData, FS: FormStyle, C: ControlData> Into<Control<FD, FS, C>>
|
||||
for ControlBuilder<FD, FS, C>
|
||||
{
|
||||
fn into(self) -> Control<FD, FS, C> {
|
||||
Control {
|
||||
data: Box::new(self.data),
|
||||
style: self.style_attributes,
|
||||
parse_fn: self.parse_fn,
|
||||
validation: self.validation_fn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,41 +1,42 @@
|
||||
use leptos::View;
|
||||
|
||||
use crate::{ControlBuilder, ControlData, FormBuilder, FormData, FormStyleProvider};
|
||||
use super::{Control, ControlBuilder, ControlData};
|
||||
use crate::{
|
||||
form::{FormBuilder, FormData},
|
||||
styles::FormStyle,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct SelectData {
|
||||
pub(crate) name: String,
|
||||
pub(crate) options: Vec<String>,
|
||||
}
|
||||
|
||||
impl SelectData {
|
||||
fn new(name: String) -> Self {
|
||||
SelectData {
|
||||
name,
|
||||
options: Vec::new(),
|
||||
}
|
||||
impl ControlData for SelectData {
|
||||
type ReturnType = String;
|
||||
|
||||
fn build_control<FD: FormData, FS: FormStyle>(fs: &FS, control: Control<FD, FS, Self>) -> View {
|
||||
fs.select(control)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FS: FormStyleProvider> ControlData<FS> for SelectData {
|
||||
fn build_control(self, fs: &FS, attributes: Vec<FS::StylingAttributes>) -> View {
|
||||
fs.select(self, attributes)
|
||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn select(
|
||||
self,
|
||||
builder: impl Fn(ControlBuilder<FD, FS, SelectData>) -> Control<FD, FS, SelectData>,
|
||||
) -> Self {
|
||||
self.new_control(builder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> FormBuilder<FD, FS> {
|
||||
pub fn select(self, name: impl ToString) -> ControlBuilder<FD, FS, SelectData> {
|
||||
ControlBuilder {
|
||||
fb: self,
|
||||
parse_fn: None,
|
||||
style_attributes: Vec::new(),
|
||||
data: SelectData::new(name.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> ControlBuilder<FD, FS, SelectData> {
|
||||
impl<FD: FormData, FS: FormStyle> ControlBuilder<FD, FS, SelectData> {
|
||||
pub fn options(mut self, options: Vec<String>) -> Self {
|
||||
self.data.options = options;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn and_option(mut self, option: impl ToString) -> Self {
|
||||
self.data.options.push(option.to_string());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +1,37 @@
|
||||
use leptos::View;
|
||||
|
||||
use crate::{ControlBuilder, ControlData, FormBuilder, FormData, FormStyleProvider};
|
||||
use super::{VanityControl, VanityControlBuilder, VanityControlData};
|
||||
use crate::{
|
||||
form::{FormBuilder, FormData},
|
||||
styles::FormStyle,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct SubmitData {
|
||||
pub(crate) text: String,
|
||||
}
|
||||
|
||||
impl SubmitData {
|
||||
fn new(text: String) -> Self {
|
||||
SubmitData { text }
|
||||
impl VanityControlData for SubmitData {
|
||||
fn build_control<FD: FormData, FS: FormStyle>(
|
||||
fs: &FS,
|
||||
control: VanityControl<FS, Self>,
|
||||
) -> View {
|
||||
fs.submit(control)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FS: FormStyleProvider> ControlData<FS> for SubmitData {
|
||||
fn build_control(self, fs: &FS, attributes: Vec<FS::StylingAttributes>) -> View {
|
||||
fs.submit(self, attributes)
|
||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn submit(
|
||||
self,
|
||||
builder: impl Fn(VanityControlBuilder<FS, SubmitData>) -> VanityControl<FS, SubmitData>,
|
||||
) -> Self {
|
||||
self.new_vanity(builder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> FormBuilder<FD, FS> {
|
||||
pub fn submit(self, text: impl ToString) -> ControlBuilder<FD, FS, SubmitData> {
|
||||
ControlBuilder {
|
||||
fb: self,
|
||||
parse_fn: None,
|
||||
style_attributes: Vec::new(),
|
||||
data: SubmitData::new(text.to_string()),
|
||||
}
|
||||
impl<FS: FormStyle> VanityControlBuilder<FS, SubmitData> {
|
||||
pub fn text(mut self, text: impl ToString) -> Self {
|
||||
self.data.text = text.to_string();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,39 +1,35 @@
|
||||
use leptos::View;
|
||||
|
||||
use crate::{ControlBuilder, ControlData, FormBuilder, FormData, FormStyleProvider};
|
||||
use super::{Control, ControlBuilder, ControlData};
|
||||
use crate::{
|
||||
form::{FormBuilder, FormData},
|
||||
styles::FormStyle,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct TextAreaData {
|
||||
pub(crate) name: String,
|
||||
pub(crate) placeholder: Option<String>,
|
||||
}
|
||||
|
||||
impl TextAreaData {
|
||||
fn new(name: String) -> Self {
|
||||
TextAreaData {
|
||||
name,
|
||||
placeholder: None,
|
||||
}
|
||||
impl ControlData for TextAreaData {
|
||||
type ReturnType = String;
|
||||
|
||||
fn build_control<FD: FormData, FS: FormStyle>(fs: &FS, control: Control<FD, FS, Self>) -> View {
|
||||
fs.text_area(control)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FS: FormStyleProvider> ControlData<FS> for TextAreaData {
|
||||
fn build_control(self, fs: &FS, attributes: Vec<FS::StylingAttributes>) -> View {
|
||||
fs.text_area(self, attributes)
|
||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn text_area(
|
||||
self,
|
||||
builder: impl Fn(ControlBuilder<FD, FS, TextAreaData>) -> Control<FD, FS, TextAreaData>,
|
||||
) -> Self {
|
||||
self.new_control(builder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> FormBuilder<FD, FS> {
|
||||
pub fn text_area(self, name: impl ToString) -> ControlBuilder<FD, FS, TextAreaData> {
|
||||
ControlBuilder {
|
||||
fb: self,
|
||||
parse_fn: None,
|
||||
style_attributes: Vec::new(),
|
||||
data: TextAreaData::new(name.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> ControlBuilder<FD, FS, TextAreaData> {
|
||||
impl<FD: FormData, FS: FormStyle> ControlBuilder<FD, FS, TextAreaData> {
|
||||
pub fn placeholder(mut self, placeholder: impl ToString) -> Self {
|
||||
self.data.placeholder = Some(placeholder.to_string());
|
||||
self
|
||||
|
||||
@ -1,45 +1,50 @@
|
||||
use leptos::View;
|
||||
|
||||
use crate::{ControlBuilder, ControlData, FormBuilder, FormData, FormStyleProvider};
|
||||
use super::{Control, ControlBuilder, ControlData};
|
||||
use crate::{
|
||||
form::{FormBuilder, FormData},
|
||||
styles::FormStyle,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct TextInputData {
|
||||
pub(crate) name: String,
|
||||
pub(crate) placeholder: Option<String>,
|
||||
pub(crate) label: Option<String>,
|
||||
pub(crate) initital_text: String,
|
||||
pub(crate) initial_text: String,
|
||||
pub(crate) input_type: &'static str,
|
||||
}
|
||||
|
||||
impl TextInputData {
|
||||
fn new(name: String) -> Self {
|
||||
impl Default for TextInputData {
|
||||
fn default() -> Self {
|
||||
TextInputData {
|
||||
name,
|
||||
name: String::new(),
|
||||
placeholder: None,
|
||||
label: None,
|
||||
initital_text: String::new(),
|
||||
initial_text: String::new(),
|
||||
input_type: "input",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<FS: FormStyleProvider> ControlData<FS> for TextInputData {
|
||||
fn build_control(self, fs: &FS, attributes: Vec<FS::StylingAttributes>) -> View {
|
||||
fs.text_input(self, attributes)
|
||||
impl ControlData for TextInputData {
|
||||
type ReturnType = String;
|
||||
|
||||
fn build_control<FD: FormData, FS: FormStyle>(fs: &FS, control: Control<FD, FS, Self>) -> View {
|
||||
fs.text_input(control)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> FormBuilder<FD, FS> {
|
||||
pub fn text_input(self, name: impl ToString) -> ControlBuilder<FD, FS, TextInputData> {
|
||||
ControlBuilder {
|
||||
fb: self,
|
||||
parse_fn: None,
|
||||
style_attributes: Vec::new(),
|
||||
data: TextInputData::new(name.to_string()),
|
||||
}
|
||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn text_input(
|
||||
self,
|
||||
builder: impl Fn(ControlBuilder<FD, FS, TextInputData>) -> Control<FD, FS, TextInputData>,
|
||||
) -> Self {
|
||||
self.new_control(builder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider> ControlBuilder<FD, FS, TextInputData> {
|
||||
impl<FD: FormData, FS: FormStyle> ControlBuilder<FD, FS, TextInputData> {
|
||||
pub fn placeholder(mut self, placeholder: impl ToString) -> Self {
|
||||
self.data.placeholder = Some(placeholder.to_string());
|
||||
self
|
||||
@ -51,7 +56,7 @@ impl<FD: FormData, FS: FormStyleProvider> ControlBuilder<FD, FS, TextInputData>
|
||||
}
|
||||
|
||||
pub fn initial_text(mut self, text: impl ToString) -> Self {
|
||||
self.data.initital_text = text.to_string();
|
||||
self.data.initial_text = text.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
68
src/form.rs
Normal file
68
src/form.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use crate::{
|
||||
controls::{
|
||||
Control, ControlBuilder, ControlData, ValidationFn, VanityControl, VanityControlBuilder,
|
||||
VanityControlData,
|
||||
},
|
||||
styles::FormStyle,
|
||||
};
|
||||
use leptos::{IntoView, View};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct FormBuilder<FD: FormData, FS: FormStyle> {
|
||||
_fd: PhantomData<FD>,
|
||||
fs: FS,
|
||||
validations: Vec<Box<ValidationFn<FD>>>,
|
||||
views: Vec<View>,
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn new(form_style: FS) -> FormBuilder<FD, FS> {
|
||||
FormBuilder {
|
||||
_fd: PhantomData::default(),
|
||||
fs: form_style,
|
||||
validations: Vec::new(),
|
||||
views: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_vanity<C: VanityControlData + Default>(
|
||||
mut self,
|
||||
builder: impl Fn(VanityControlBuilder<FS, C>) -> VanityControl<FS, C>,
|
||||
) -> Self {
|
||||
let vanity_builder = VanityControlBuilder::new(C::default());
|
||||
let control = builder(vanity_builder);
|
||||
self.add_vanity(control);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn new_control<C: ControlData + Default>(
|
||||
mut self,
|
||||
builder: impl Fn(ControlBuilder<FD, FS, C>) -> Control<FD, FS, C>,
|
||||
) -> Self {
|
||||
let control_builder = ControlBuilder::new(C::default());
|
||||
let control = builder(control_builder);
|
||||
self.add_control(control);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_vanity<C: VanityControlData>(&mut self, vanity_control: VanityControl<FS, C>) {
|
||||
let view = VanityControlData::build_control::<FD, FS>(&self.fs, vanity_control);
|
||||
self.views.push(view);
|
||||
}
|
||||
|
||||
fn add_control<C: ControlData>(&mut self, control: Control<FD, FS, C>) {
|
||||
let view = ControlData::build_control(&self.fs, control);
|
||||
self.views.push(view);
|
||||
}
|
||||
|
||||
// TODO: this should return a Form object
|
||||
// The Form should have `form_view()`, and `validate(&FD)` functions.
|
||||
pub fn build(self) -> View {
|
||||
self.views.into_view()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FormData: Default {
|
||||
// TODO: this should return a Form Object
|
||||
fn create_form() -> View;
|
||||
}
|
||||
62
src/lib.rs
62
src/lib.rs
@ -1,59 +1,3 @@
|
||||
use controls::{
|
||||
heading::HeadingData, select::SelectData, submit::SubmitData, text_area::TextAreaData,
|
||||
text_input::TextInputData,
|
||||
};
|
||||
use leptos::*;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
mod controls;
|
||||
mod provider_impl;
|
||||
|
||||
pub trait FormStyleProvider {
|
||||
type StylingAttributes;
|
||||
|
||||
fn heading(&self, data: HeadingData, attributes: Vec<Self::StylingAttributes>) -> View;
|
||||
fn text_input(&self, data: TextInputData, attributes: Vec<Self::StylingAttributes>) -> View;
|
||||
fn select(&self, data: SelectData, attributes: Vec<Self::StylingAttributes>) -> View;
|
||||
fn submit(&self, data: SubmitData, attributes: Vec<Self::StylingAttributes>) -> View;
|
||||
fn text_area(&self, data: TextAreaData, attributes: Vec<Self::StylingAttributes>) -> View;
|
||||
fn custom_component(&self, component: View) -> View;
|
||||
// TODO: add group
|
||||
}
|
||||
|
||||
pub trait ControlData<FS: FormStyleProvider>: 'static {
|
||||
fn build_control(self, fs: &FS, attributes: Vec<FS::StylingAttributes>) -> View;
|
||||
}
|
||||
|
||||
pub struct FormBuilder<FD: FormData, FS: FormStyleProvider> {
|
||||
_fd: PhantomData<FD>,
|
||||
fs: FS,
|
||||
controls: Vec<(Box<dyn ControlData<FS>>, Vec<FS::StylingAttributes>)>,
|
||||
}
|
||||
|
||||
pub trait FormData {}
|
||||
|
||||
pub struct ControlBuilder<FD: FormData, FS: FormStyleProvider, C: ControlData<FS>> {
|
||||
fb: FormBuilder<FD, FS>,
|
||||
parse_fn: Option<Box<dyn Fn(&str, &mut FD)>>,
|
||||
style_attributes: Vec<FS::StylingAttributes>,
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<FD: FormData, FS: FormStyleProvider, C: ControlData<FS>> ControlBuilder<FD, FS, C> {
|
||||
pub fn parse_fn(mut self, parse_fn: Box<dyn Fn(&str, &mut FD)>) -> Self {
|
||||
self.parse_fn = Some(parse_fn);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn style(mut self, attribute: FS::StylingAttributes) -> Self {
|
||||
self.style_attributes.push(attribute);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn end(mut self) -> FormBuilder<FD, FS> {
|
||||
self.fb
|
||||
.controls
|
||||
.push((Box::new(self.data), self.style_attributes));
|
||||
self.fb
|
||||
}
|
||||
}
|
||||
pub mod controls;
|
||||
pub mod form;
|
||||
pub mod styles;
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
use crate::{
|
||||
controls::{select::SelectData, submit::SubmitData, text_area::TextAreaData},
|
||||
FormStyleProvider, HeadingData, TextInputData,
|
||||
};
|
||||
use leptos::*;
|
||||
|
||||
pub enum TailwindStylingAttibutes {
|
||||
Width(u32),
|
||||
}
|
||||
|
||||
pub struct TailwindFormStyleProvider;
|
||||
|
||||
impl FormStyleProvider for TailwindFormStyleProvider {
|
||||
type StylingAttributes = TailwindFormStyleProvider;
|
||||
|
||||
// fn label(&self, data: LabelData) -> View {
|
||||
// view! {
|
||||
// }.into_view()
|
||||
// }
|
||||
|
||||
fn heading(&self, data: HeadingData, attributes: Vec<Self::StylingAttributes>) -> View {
|
||||
view! {
|
||||
<h2 class="text-xl py-2 text-center font-bold text-gray-700 border-b-2 border-gray-800/60 mb-8">
|
||||
{&data.title}
|
||||
</h2>
|
||||
}
|
||||
.into_view()
|
||||
}
|
||||
|
||||
fn text_input(&self, data: TextInputData, attributes: Vec<Self::StylingAttributes>) -> View {
|
||||
view! {
|
||||
<label
|
||||
for={&data.name}
|
||||
class="block uppercase tracking-wide text-left text-gray-700 text-md font-bold ml-2 mb-1"
|
||||
>
|
||||
{data.label.as_ref()}
|
||||
</label>
|
||||
<input
|
||||
// TODO:
|
||||
// type=text_type
|
||||
id=&data.name
|
||||
name=data.name
|
||||
// placeholder=placeholder
|
||||
class="block w-full bg-gray-100 border-2 border-gray-300 text-gray-700 py-2 px-4 rounded-lg leading-tight focus:outline-none focus:bg-white focus:border-sky-400"
|
||||
/>
|
||||
}.into_view()
|
||||
}
|
||||
|
||||
fn select(&self, data: SelectData, attributes: Vec<Self::StylingAttributes>) -> View {
|
||||
view! {
|
||||
<select
|
||||
id=&data.name
|
||||
name=data.name
|
||||
class="block w-full bg-gray-100 border-2 border-gray-300 text-gray-700 py-2 px-4 rounded-lg leading-tight focus:outline-none focus:bg-white focus:border-sky-400"
|
||||
>
|
||||
{data.options}
|
||||
</select>
|
||||
}.into_view()
|
||||
}
|
||||
|
||||
fn submit(&self, data: SubmitData, attributes: Vec<Self::StylingAttributes>) -> View {
|
||||
view! {
|
||||
<input
|
||||
type="submit"
|
||||
value=data.text
|
||||
class="col-span-full rounded-2xl bg-sky-700 text-white font-bold hover:cursor-pointer hover:bg-sky-600 px-5 py-3 mx-auto mt-4"
|
||||
/>
|
||||
}
|
||||
.into_view()
|
||||
}
|
||||
|
||||
fn text_area(&self, data: TextAreaData, attributes: Vec<Self::StylingAttributes>) -> View {
|
||||
view! {
|
||||
<textarea
|
||||
id=&data.name
|
||||
name=data.name
|
||||
placeholder=data.placeholder
|
||||
class="block w-full bg-gray-100 border-2 border-gray-300 text-gray-700 py-2 px-4 rounded-lg leading-tight focus:outline-none focus:bg-white focus:border-sky-400"
|
||||
/>
|
||||
}.into_view()
|
||||
}
|
||||
|
||||
fn custom_component(&self, component: View) -> View {
|
||||
component
|
||||
}
|
||||
}
|
||||
25
src/styles/mod.rs
Normal file
25
src/styles/mod.rs
Normal file
@ -0,0 +1,25 @@
|
||||
mod tw_grid;
|
||||
|
||||
pub use tw_grid::{TailwindGridFormStyle, TailwindGridStylingAttributes};
|
||||
|
||||
use crate::{
|
||||
controls::{
|
||||
heading::HeadingData, select::SelectData, submit::SubmitData, text_area::TextAreaData,
|
||||
text_input::TextInputData, Control, VanityControl,
|
||||
},
|
||||
form::FormData,
|
||||
};
|
||||
use leptos::View;
|
||||
|
||||
pub trait FormStyle: 'static {
|
||||
type StylingAttributes;
|
||||
|
||||
// TODO: add form frame
|
||||
fn heading(&self, control: VanityControl<Self, HeadingData>) -> View;
|
||||
fn text_input<FD: FormData>(&self, control: Control<FD, Self, TextInputData>) -> View;
|
||||
fn select<FD: FormData>(&self, control: Control<FD, Self, SelectData>) -> View;
|
||||
fn submit(&self, control: VanityControl<Self, SubmitData>) -> View;
|
||||
fn text_area<FD: FormData>(&self, control: Control<FD, Self, TextAreaData>) -> View;
|
||||
fn custom_component(&self, view: View) -> View;
|
||||
// TODO: add group
|
||||
}
|
||||
89
src/styles/tw_grid.rs
Normal file
89
src/styles/tw_grid.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use super::FormStyle;
|
||||
use crate::{
|
||||
controls::{
|
||||
heading::HeadingData, select::SelectData, submit::SubmitData, text_area::TextAreaData,
|
||||
text_input::TextInputData, Control, VanityControl,
|
||||
},
|
||||
form::FormData,
|
||||
};
|
||||
use leptos::CollectView;
|
||||
use leptos::{view, IntoView, View};
|
||||
|
||||
pub enum TailwindGridStylingAttributes {
|
||||
Width(u32),
|
||||
}
|
||||
|
||||
pub struct TailwindGridFormStyle;
|
||||
|
||||
impl FormStyle for TailwindGridFormStyle {
|
||||
type StylingAttributes = TailwindGridStylingAttributes;
|
||||
|
||||
fn heading(&self, control: VanityControl<Self, HeadingData>) -> View {
|
||||
view! {
|
||||
<h2 class="text-xl py-2 text-center font-bold text-gray-700 border-b-2 border-gray-800/60 mb-8">
|
||||
{&control.data.title}
|
||||
</h2>
|
||||
}
|
||||
.into_view()
|
||||
}
|
||||
|
||||
fn text_input<FD: FormData>(&self, control: Control<FD, Self, TextInputData>) -> View {
|
||||
view! {
|
||||
<div>
|
||||
<label
|
||||
for={&control.data.name}
|
||||
class="block uppercase tracking-wide text-left text-gray-700 text-md font-bold ml-2 mb-1"
|
||||
>
|
||||
{control.data.label.as_ref()}
|
||||
</label>
|
||||
<input
|
||||
// TODO:
|
||||
type=control.data.input_type
|
||||
id=&control.data.name
|
||||
name=control.data.name
|
||||
placeholder=control.data.placeholder
|
||||
value=control.data.initial_text
|
||||
class="block w-full bg-gray-100 border-2 border-gray-300 text-gray-700 py-2 px-4 rounded-lg leading-tight focus:outline-none focus:bg-white focus:border-sky-400"
|
||||
/>
|
||||
</div>
|
||||
}.into_view()
|
||||
}
|
||||
|
||||
fn select<FD: FormData>(&self, control: Control<FD, Self, SelectData>) -> View {
|
||||
view! {
|
||||
<select
|
||||
id=&control.data.name
|
||||
name=control.data.name
|
||||
class="block w-full bg-gray-100 border-2 border-gray-300 text-gray-700 py-2 px-4 rounded-lg leading-tight focus:outline-none focus:bg-white focus:border-sky-400"
|
||||
>
|
||||
{control.data.options.iter().map(|option| view!{<option>{option}</option>}).collect_view()}
|
||||
</select>
|
||||
}.into_view()
|
||||
}
|
||||
|
||||
fn submit(&self, control: VanityControl<Self, SubmitData>) -> View {
|
||||
view! {
|
||||
<input
|
||||
type="submit"
|
||||
value=control.data.text
|
||||
class="col-span-full rounded-2xl bg-sky-700 text-white font-bold hover:cursor-pointer hover:bg-sky-600 px-5 py-3 mx-auto mt-4"
|
||||
/>
|
||||
}
|
||||
.into_view()
|
||||
}
|
||||
|
||||
fn text_area<FD: FormData>(&self, control: Control<FD, Self, TextAreaData>) -> View {
|
||||
view! {
|
||||
<textarea
|
||||
id=&control.data.name
|
||||
name=control.data.name
|
||||
placeholder=control.data.placeholder
|
||||
class="block w-full bg-gray-100 border-2 border-gray-300 text-gray-700 py-2 px-4 rounded-lg leading-tight focus:outline-none focus:bg-white focus:border-sky-400"
|
||||
/>
|
||||
}.into_view()
|
||||
}
|
||||
|
||||
fn custom_component(&self, view: View) -> View {
|
||||
view
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user