♻️ (form): Mueve componentes de formulario a base

This commit is contained in:
Manuel Cillero 2026-06-22 02:12:09 +02:00
parent 26f1cda831
commit 9435678e01
38 changed files with 2211 additions and 1826 deletions

View file

@ -0,0 +1,141 @@
use crate::prelude::*;
use crate::base::component::form;
/// Componente para crear un **formulario** HTML ([`form`]).
///
/// Renderiza un formulario estándar con soporte para los atributos más habituales:
///
/// - `id`: identificador opcional del formulario.
/// - `classes`: clases CSS adicionales (p. ej. utilidades CSS).
/// - `action`: URL/ruta de destino para el envío.
/// - `method`: método usado por el formulario para el envío de los datos (ver [`form::Method`]).
/// - `accept-charset`: juego de caracteres aceptado (por defecto es `"UTF-8"`).
/// - `children`: contenido del formulario.
///
/// # Ejemplo
///
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// let form_login = Form::new()
/// .with_id("login")
/// .with_action("/login")
/// .with_child(
/// form::input::Field::email()
/// .with_name("email")
/// .with_label(L10n::n("Email"))
/// .with_required(true),
/// )
/// .with_child(
/// form::input::Field::password()
/// .with_name("password")
/// .with_label(L10n::n("Password"))
/// .with_required(true),
/// )
/// .with_child(
/// form::Checkbox::check()
/// .with_name("remember")
/// .with_label(L10n::n("Remember me")),
/// )
/// .with_child(
/// Button::submit(L10n::n("Sign in"))
/// );
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]
pub struct Form {
/// Devuelve identificador, clases CSS y atributos HTML del componente.
props: Props,
/// Devuelve la URL/ruta de destino del formulario.
action: AttrValue,
/// Devuelve el método para enviar el formulario.
method: form::Method,
/// Devuelve el juego de caracteres aceptado por el formulario.
#[default(_code = "AttrValue::new(\"UTF-8\")")]
charset: AttrValue,
/// Devuelve la lista de componentes del formulario.
children: Children,
}
impl Component for Form {
fn new() -> Self {
Self::default()
}
fn id(&self) -> Option<String> {
self.props.get_id()
}
fn setup(&mut self, _cx: &Context) {
self.alter_prop(PropsOp::prepend_classes("form"));
}
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
let method = match self.method() {
form::Method::Post => Some("post"),
form::Method::Get => None,
};
Ok(html! {
form
(self.props())
action=[self.action().get()]
method=[method]
accept-charset=[self.charset().get()]
{
(self.children().render(cx))
}
})
}
}
impl Form {
// **< Form BUILDER >***************************************************************************
/// Establece el identificador único del componente; igual a `with_prop(PropsOp::set_id(id))`.
#[builder_fn]
pub fn with_id(mut self, id: impl Into<CowStr>) -> Self {
self.props.alter_id(id);
self
}
/// Modifica identificador, clases CSS o atributos HTML del componente.
#[builder_fn]
pub fn with_prop(mut self, op: PropsOp) -> Self {
self.props.alter_prop(op);
self
}
/// Establece la URL/ruta de destino del formulario.
#[builder_fn]
pub fn with_action(mut self, action: impl AsRef<str>) -> Self {
self.action.alter_str(action);
self
}
/// Establece el método para enviar el formulario.
///
/// - `GET`: el atributo `method` se omite.
/// - `POST`: se establece `method="post"`.
#[builder_fn]
pub fn with_method(mut self, method: form::Method) -> Self {
self.method = method;
self
}
/// Establece el juego de caracteres aceptado por el formulario.
///
/// Por defecto se utiliza `"UTF-8"`.
#[builder_fn]
pub fn with_charset(mut self, charset: impl AsRef<str>) -> Self {
self.charset.alter_str(charset);
self
}
/// Añade un nuevo componente al formulario o modifica la lista de componentes (`children`) con
/// una operación [`ChildOp`].
#[builder_fn]
pub fn with_child(mut self, op: impl Into<ChildOp>) -> Self {
self.children.alter_child(op.into());
self
}
}