✨ (pagetop): Añade Flex/FlexItem para usar Flexbox
Container y Navbar lo adoptan vía `with_flex()`/`PropsOp::flex_item()`. Y se elimina `ButtonSet` porque su funcionalidad queda cubierta por este mecanismo más general. Incluye el ejemplo `examples/intro-flex.rs` con los patrones de uso.
This commit is contained in:
parent
4e4fdf7b10
commit
17e16652e4
26 changed files with 2023 additions and 193 deletions
|
|
@ -17,7 +17,7 @@ pub use block::Block;
|
|||
|
||||
pub mod button;
|
||||
#[doc(inline)]
|
||||
pub use button::{Button, ButtonSet};
|
||||
pub use button::Button;
|
||||
|
||||
pub mod container;
|
||||
#[doc(inline)]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
//! Definiciones para crear botones ([`Button`]) y conjuntos de botones ([`ButtonSet`]).
|
||||
//! Definiciones para crear botones ([`Button`]).
|
||||
|
||||
mod props;
|
||||
pub use props::{Kind, Size, Style};
|
||||
|
||||
mod component;
|
||||
pub use component::Button;
|
||||
|
||||
mod set;
|
||||
pub use set::ButtonSet;
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
/// Componente para mostrar un **conjunto de botones**.
|
||||
///
|
||||
/// Envuelve los botones en un contenedor que cada tema estiliza para separarlos visualmente. Sólo
|
||||
/// admite componentes [`Button`].
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use pagetop::prelude::*;
|
||||
///
|
||||
/// let actions = button::ButtonSet::new()
|
||||
/// .with_button(Button::submit(Lc::n("Save")))
|
||||
/// .with_button(Button::plain(Lc::n("Cancel")));
|
||||
/// ```
|
||||
#[derive(AutoDefault, Clone, Debug, Getters)]
|
||||
pub struct ButtonSet {
|
||||
/// Devuelve identificador, clases CSS, atributos HTML y valores extra del componente.
|
||||
props: Props,
|
||||
/// Devuelve los botones del conjunto.
|
||||
buttons: Children,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for ButtonSet {
|
||||
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("button-set"));
|
||||
}
|
||||
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let buttons = self.buttons().render(cx).await;
|
||||
if buttons.is_empty() {
|
||||
return Ok(html! {});
|
||||
}
|
||||
Ok(html! {
|
||||
div (self.props()) { (buttons) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[builder_impl]
|
||||
impl ButtonSet {
|
||||
// **< ButtonSet BUILDER >*************************************************************************
|
||||
|
||||
/// Establece el identificador único del componente; igual a `with_prop(PropsOp::set_id(id))`.
|
||||
pub fn with_id(mut self, id: impl Into<CowStr>) -> Self {
|
||||
self.props.alter_id(id);
|
||||
self
|
||||
}
|
||||
|
||||
/// Modifica identificador, clases CSS, atributos HTML o valores extra del componente.
|
||||
pub fn with_prop(mut self, op: PropsOp) -> Self {
|
||||
self.props.alter_prop(op);
|
||||
self
|
||||
}
|
||||
|
||||
/// Añade un botón al conjunto, o modifica su lista de botones con una operación [`TypedOp`].
|
||||
pub fn with_button(mut self, op: impl Into<TypedOp<Button>>) -> Self {
|
||||
self.buttons.alter_child(op.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,9 @@ pub struct Container {
|
|||
props: Props,
|
||||
/// Devuelve el tipo semántico del contenedor.
|
||||
kind: Kind,
|
||||
/// Devuelve el posicionamiento Flexbox como contenedor, si tiene alguno.
|
||||
#[getters(copy)]
|
||||
flex: Option<Flex>,
|
||||
/// Devuelve la lista de componentes (`children`) del contenedor.
|
||||
children: Children,
|
||||
}
|
||||
|
|
@ -61,6 +64,12 @@ impl Component for Container {
|
|||
self.props.get_id()
|
||||
}
|
||||
|
||||
fn setup(&mut self, _cx: &Context) {
|
||||
if let Some(flex) = self.flex() {
|
||||
flex.apply_to(&mut self.props);
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let output = self.children().render(cx).await;
|
||||
|
|
@ -134,6 +143,12 @@ impl Container {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece el posicionamiento Flexbox como contenedor (usa `None` para quitarlo).
|
||||
pub fn with_flex(mut self, flex: impl Into<Option<Flex>>) -> Self {
|
||||
self.flex = flex.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Añade un nuevo componente al contenedor o modifica la lista de componentes (`children`) con
|
||||
/// una operación [`ChildOp`].
|
||||
pub fn with_child(mut self, op: impl Into<ChildOp>) -> Self {
|
||||
|
|
|
|||
|
|
@ -136,8 +136,7 @@ impl Dialog {
|
|||
/// lista de componentes (`children`) del pie con una operación [`ChildOp`].
|
||||
///
|
||||
/// El pie ya se maqueta en fila y alineado a la derecha por su propia clase CSS
|
||||
/// (`dialog-footer`); por lo que no requiere un [`ButtonSet`](super::ButtonSet) para alinear
|
||||
/// los botones, aunque puede usarse si se desea.
|
||||
/// (`dialog-footer`); no requiere ninguna configuración adicional para alinear los botones.
|
||||
pub fn with_footer(mut self, op: impl Into<ChildOp>) -> Self {
|
||||
self.footer.alter_child(op.into());
|
||||
self
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ pub struct Navbar {
|
|||
props: Props,
|
||||
/// Devuelve la disposición configurada para la barra de navegación.
|
||||
layout: navbar::Layout,
|
||||
/// Devuelve el posicionamiento Flexbox como contenedor, si tiene alguno.
|
||||
#[getters(copy)]
|
||||
flex: Option<Flex>,
|
||||
/// Devuelve la lista de contenidos.
|
||||
items: Children,
|
||||
}
|
||||
|
|
@ -128,37 +131,44 @@ impl Component for Navbar {
|
|||
let id = self.id().unwrap();
|
||||
let id_content = util::join!(id, "-content");
|
||||
|
||||
// Posicionamiento Flexbox opcional (no del `<nav>`, cuya estructura la fija `layout()`).
|
||||
let mut content_props = Props::default();
|
||||
if let Some(flex) = self.flex() {
|
||||
flex.apply_to(&mut content_props);
|
||||
}
|
||||
content_props.alter_prop(PropsOp::prepend_classes("navbar-content"));
|
||||
|
||||
Ok(html! {
|
||||
nav (self.props()) {
|
||||
@match self.layout() {
|
||||
// Barra más sencilla: sólo contenido, siempre visible.
|
||||
navbar::Layout::Simple => {
|
||||
div class="navbar-content" { (items) }
|
||||
div (content_props) { (items) }
|
||||
},
|
||||
|
||||
// Barra sencilla que se puede contraer/expandir.
|
||||
navbar::Layout::SimpleToggle => {
|
||||
(button(cx, &id_content))
|
||||
div id=(&id_content) class="navbar-content" { (items) }
|
||||
div id=(&id_content) (content_props) { (items) }
|
||||
},
|
||||
|
||||
// Barra con marca, siempre visible, sin botón.
|
||||
navbar::Layout::SimpleBrandLeft(brand) => {
|
||||
(brand.render(cx).await)
|
||||
div class="navbar-content" { (items) }
|
||||
div (content_props) { (items) }
|
||||
},
|
||||
|
||||
// Barra con marca y botón, en ese orden.
|
||||
navbar::Layout::BrandLeft(brand) => {
|
||||
(brand.render(cx).await)
|
||||
(button(cx, &id_content))
|
||||
div id=(&id_content) class="navbar-content" { (items) }
|
||||
div id=(&id_content) (content_props) { (items) }
|
||||
},
|
||||
|
||||
// Barra con botón y marca, en ese orden.
|
||||
navbar::Layout::BrandRight(brand) => {
|
||||
(button(cx, &id_content))
|
||||
div id=(&id_content) class="navbar-content" { (items) }
|
||||
div id=(&id_content) (content_props) { (items) }
|
||||
(brand.render(cx).await)
|
||||
},
|
||||
}
|
||||
|
|
@ -216,6 +226,15 @@ impl Navbar {
|
|||
self
|
||||
}
|
||||
|
||||
/// Establece el posicionamiento Flexbox como contenedor (usa `None` para quitarlo).
|
||||
///
|
||||
/// No afecta a la posición de la marca ni del botón de despliegue, que quedan fijados con
|
||||
/// [`with_layout()`](Self::with_layout).
|
||||
pub fn with_flex(mut self, flex: impl Into<Option<Flex>>) -> Self {
|
||||
self.flex = flex.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Añade un nuevo contenido a la barra de navegación o modifica la lista de contenidos de la
|
||||
/// barra con una operación [`TypedOp`].
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue