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
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::node::{Node, NodeContainer};
use std::borrow::BorrowMut;
use crate::DefaultModifiers;
use crate::renderer::{ToHtml, Renderable};
use crate::components::{View, TextStyle, Text};

#[derive(Debug, Clone)]
pub enum FieldType {
    Text,
    Password,
    Email,
    Number,
    Tel,
    Date,
    DateTimeLocal,
    Month,
    Search,
    Time,
    Url,
    Week,
}

#[derive(Debug, Clone)]
pub struct TextField {
    node: Node,
    pub label: Option<String>,
    pub helper_text: Option<String>,
    pub placeholder: Option<String>,
    pub leading_icon: Option<String>,
    pub trailing_icon: Option<String>,
    pub field_type: FieldType,
    pub name: String,
    pub auto_sizing: bool,
}

impl NodeContainer for TextField {
    fn get_node(&mut self) -> &mut Node {
        self.node.borrow_mut()
    }
}

impl DefaultModifiers<TextField> for TextField {}

impl TextField {
    pub fn new(name: &str, field_type: FieldType) -> Self {
        TextField {
            node: Default::default(),
            label: None,
            helper_text: None,
            placeholder: None,
            leading_icon: None,
            trailing_icon: None,
            field_type,
            name: name.to_string(),
            auto_sizing: false
        }
    }

    pub fn label(&mut self, label: &str) -> Self {
        self.label = Some(label.to_string());
        self.clone()
    }

    pub fn helper_text(&mut self, helper_text: &str) -> Self {
        self.helper_text = Some(helper_text.to_string());
        self.clone()
    }
    pub fn placeholder(&mut self, placeholder: &str) -> Self {
        self.placeholder = Some(placeholder.to_string());
        self.clone()
    }

    pub fn trailing_icon(&mut self, name: &str) -> Self {
        self.trailing_icon = Some(name.to_string());
        self.clone()
    }

    pub fn leading_icon(&mut self, name: &str) -> Self {
        self.leading_icon = Some(name.to_string());
        self.clone()
    }
}

impl ToHtml for TextField {}

impl Renderable for TextField {
    fn render(&self) -> Node {
        let mut field = self.clone()
            .add_class("textfield");

        let mut input = View::new()
            .tag("input")
            .add_class("textfield__input")
            .set_attr("type", format!("{:?}", field.field_type).to_lowercase().as_str())
            .set_attr("id", self.name.as_str())
            .set_attr("name", self.name.as_str());

        if let Some(placeholder) = field.placeholder {
            input.set_attr("placeholder", placeholder.as_str());
        }

        if let Some(label) = field.label {
            let text = Text::new(label.as_str(), TextStyle::Label)
                .set_attr("for", self.name.as_str())
                .tag("label");
            field.node.children.push(text.render());
        }
        field.node.children.push(input.render());
        if let Some(helper_text) = field.helper_text {
            let text = Text::new(helper_text.as_str(), TextStyle::Caption)
                .color("var(--color-text-secondary)");
            field.node.children.push(text.render());
        }
        field.node
    }
}