use pagetop::prelude::*; include_locales!(LOC from "examples/locale"); struct IntroFlex; #[async_trait] impl Extension for IntroFlex { fn dependencies(&self) -> Vec { vec![&pagetop_bootsier::Bootsier] } fn configure_router(&self, router: Router) -> Router { router.route("/", web::get(intro_flex)) } } async fn intro_flex(request: HttpRequest) -> Result { Page::new(request) .with_assets(demo_box_styles()) .with_assets(demo_row_styles()) .with_child( Intro::default() .with_opening(IntroOpening::Custom) .with_title(Lc::n("PageTop")) .with_slogan(Lc::t("flex_slogan", &LOC)) .with_button(None::<(Lc, Route)>) .with_child(direction_block()) .with_child(justify_block()) .with_child(align_block()) .with_child(align_self_block()) .with_child(align_content_block()) .with_child(grow_shrink_block()) .with_child(other_block()), ) .render() .await } fn direction_block() -> Block { let mut block = Block::new().with_title(Lc::t("flex_block_title_direction", &LOC)); let direction_variants: [(&str, Flex, &str); 4] = [ ("flex_title_direction_row", Flex::new(), "Flex::new()"), ( "flex_title_direction_row_reverse", Flex::new().with_direction(flex::Direction::RowReverse), "Flex::new().with_direction(Direction::RowReverse)", ), ( "flex_title_direction_column", Flex::new().with_direction(flex::Direction::Column), "Flex::new().with_direction(Direction::Column)", ), ( "flex_title_direction_column_reverse", Flex::new().with_direction(flex::Direction::ColumnReverse), "Flex::new().with_direction(Direction::ColumnReverse)", ), ]; for (title_key, flex, code) in direction_variants { block = block .with_child(caption(Lc::t(title_key, &LOC), Lc::n(code))) .with_child( demo_row(flex) .with_child(demo_box(flex_item("1"))) .with_child(demo_box(flex_item("2"))) .with_child(demo_box(flex_item("3"))), ); } block } fn justify_block() -> Block { let mut block = Block::new().with_title(Lc::t("flex_block_title_justify", &LOC)); let justify_variants: [(&str, flex::ContentJustify, &str); 6] = [ ( "flex_title_justify_start", flex::ContentJustify::Start, "Flex::new().with_justify(ContentJustify::Start)", ), ( "flex_title_justify_center", flex::ContentJustify::Center, "Flex::new().with_justify(ContentJustify::Center)", ), ( "flex_title_justify_end", flex::ContentJustify::End, "Flex::new().with_justify(ContentJustify::End)", ), ( "flex_title_justify_between", flex::ContentJustify::SpaceBetween, "Flex::new().with_justify(ContentJustify::SpaceBetween)", ), ( "flex_title_justify_around", flex::ContentJustify::SpaceAround, "Flex::new().with_justify(ContentJustify::SpaceAround)", ), ( "flex_title_justify_evenly", flex::ContentJustify::SpaceEvenly, "Flex::new().with_justify(ContentJustify::SpaceEvenly)", ), ]; for (title_key, justify, code) in justify_variants { block = block .with_child(caption(Lc::t(title_key, &LOC), Lc::n(code))) .with_child( demo_row( Flex::new() .with_justify(justify) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_child(demo_box(flex_item("1"))) .with_child(demo_box(flex_item("2"))) .with_child(demo_box(flex_item("3"))), ); } block } fn align_block() -> Block { let mut block = Block::new().with_title(Lc::t("flex_block_title_align", &LOC)); let align_variants: [(&str, flex::Align, &str); 4] = [ ( "flex_title_align_start", flex::Align::Start, "Flex::new().with_align(Align::Start)", ), ( "flex_title_align_center", flex::Align::Center, "Flex::new().with_align(Align::Center)", ), ( "flex_title_align_end", flex::Align::End, "Flex::new().with_align(Align::End)", ), ( "flex_title_align_stretch", flex::Align::Stretch, "Flex::new().with_align(Align::Stretch)", ), ]; for (title_key, align, code) in align_variants { block = block .with_child(caption(Lc::t(title_key, &LOC), Lc::n(code))) .with_child( demo_row( Flex::new() .with_align(align) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_child(sized_box(Lc::t("flex_box_tall", &LOC), "2.5rem 1rem")) .with_child(demo_box(Lc::t("flex_box_medium", &LOC))) .with_child(sized_box(Lc::t("flex_box_short", &LOC), "0.15rem 1rem")), ); } block .with_child(caption( Lc::t("flex_title_align_baseline", &LOC), Lc::n("Flex::new().with_align(Align::Baseline)"), )) .with_child( demo_row( Flex::new() .with_align(flex::Align::Baseline) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_child( sized_box(Lc::t("flex_box_tall", &LOC), "2.5rem 1rem") .with_prop(PropsOp::add_style("font-size", "1.75rem")), ) .with_child(demo_box(Lc::t("flex_box_medium", &LOC))) .with_child(sized_box(Lc::t("flex_box_short", &LOC), "0.15rem 1rem")), ) } fn align_self_block() -> Block { let mut block = Block::new().with_title(Lc::t("flex_block_title_align_self", &LOC)); let align_self_variants: [(&str, flex::ItemAlign, &str); 4] = [ ( "flex_title_align_self_start", flex::ItemAlign::Start, "FlexItem::new().with_align_self(flex::ItemAlign::Start)", ), ( "flex_title_align_self_end", flex::ItemAlign::End, "FlexItem::new().with_align_self(flex::ItemAlign::End)", ), ( "flex_title_align_self_center", flex::ItemAlign::Center, "FlexItem::new().with_align_self(flex::ItemAlign::Center)", ), ( "flex_title_align_self_stretch", flex::ItemAlign::Stretch, "FlexItem::new().with_align_self(flex::ItemAlign::Stretch)", ), ]; for (title_key, align_self, code) in align_self_variants { block = block .with_child(caption(Lc::t(title_key, &LOC), Lc::n(code))) .with_child( demo_row( Flex::new() .with_align(flex::Align::Start) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_child(sized_box(Lc::t("flex_box_tall", &LOC), "2.5rem 1rem")) .with_child( demo_box(flex_item("1")).with_prop(FlexItem::new().with_align_self(align_self)), ) .with_child(sized_box(Lc::t("flex_box_tall", &LOC), "2.5rem 1rem")), ); } block .with_child(caption( Lc::t("flex_title_align_self_baseline", &LOC), Lc::n("FlexItem::new().with_align_self(flex::ItemAlign::Baseline)"), )) .with_child( demo_row( Flex::new() .with_align(flex::Align::Start) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_child( sized_box(Lc::t("flex_box_tall", &LOC), "2.5rem 1rem") .with_prop(PropsOp::add_style("font-size", "1.75rem")), ) .with_child( demo_box(flex_item("1")) .with_prop(FlexItem::new().with_align_self(flex::ItemAlign::Baseline)), ) .with_child(sized_box(Lc::t("flex_box_tall", &LOC), "2.5rem 1rem")), ) } fn align_content_block() -> Block { let mut block = Block::new().with_title(Lc::t("flex_block_title_align_content", &LOC)); let align_content_variants: [(&str, flex::AlignContent, &str); 7] = [ ( "flex_title_align_content_start", flex::AlignContent::Start, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::Start)", ), ( "flex_title_align_content_end", flex::AlignContent::End, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::End)", ), ( "flex_title_align_content_center", flex::AlignContent::Center, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::Center)", ), ( "flex_title_align_content_between", flex::AlignContent::SpaceBetween, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::SpaceBetween)", ), ( "flex_title_align_content_around", flex::AlignContent::SpaceAround, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::SpaceAround)", ), ( "flex_title_align_content_evenly", flex::AlignContent::SpaceEvenly, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::SpaceEvenly)", ), ( "flex_title_align_content_stretch", flex::AlignContent::Stretch, "Flex::new().with_wrap(Behavior::Wrap).with_align_content(AlignContent::Stretch)", ), ]; for (title_key, align_content, code) in align_content_variants { let mut row = demo_row( Flex::new() .with_wrap(flex::Behavior::Wrap) .with_align_content(align_content) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_prop(PropsOp::add_style("max-width", "21rem")) .with_prop(PropsOp::add_style("min-height", "11rem")); for label in ["1", "2", "3", "4"] { row = row.with_child( sized_box(flex_item(label), "0.5rem 1rem") .with_prop(PropsOp::add_style("width", "9rem")), ); } block = block .with_child(caption(Lc::t(title_key, &LOC), Lc::n(code))) .with_child(row); } block } fn grow_shrink_block() -> Block { Block::new() .with_title(Lc::t("flex_block_title_grow_shrink", &LOC)) .with_child(caption( Lc::t("flex_title_grow", &LOC), Lc::n("FlexItem::new().with_grow(flex::ItemGrow::Is1)"), )) .with_child( demo_row(Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(0.5)))) .with_child(demo_box(Lc::t("flex_box_fixed", &LOC))) .with_child( demo_box(Lc::t("flex_box_grows", &LOC)) .with_prop(FlexItem::new().with_grow(flex::ItemGrow::Is1)), ) .with_child(demo_box(Lc::t("flex_box_fixed", &LOC))), ) .with_child(caption( Lc::t("flex_title_shrink", &LOC), Lc::n("FlexItem::new().with_shrink(flex::ItemShrink::Is0)"), )) .with_child( demo_row(Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(0.5)))) .with_prop(PropsOp::add_style("max-width", "31rem")) .with_child( demo_box(flex_item("1")).with_prop(PropsOp::add_style("width", "10.5rem")), ) .with_child( demo_box(flex_item("2")) .with_prop(PropsOp::add_style("width", "10.5rem")) .with_prop(FlexItem::new().with_shrink(flex::ItemShrink::Is0)), ) .with_child( demo_box(flex_item("3")).with_prop(PropsOp::add_style("width", "10.5rem")), ), ) } fn other_block() -> Block { let mut block = Block::new().with_title(Lc::t("flex_block_title_other", &LOC)); block = block .with_child(caption( Lc::t("flex_title_push_end", &LOC), Lc::n("FlexItem::push_end()"), )) .with_child( demo_row(Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(0.5)))) .with_child(demo_box(Lc::t("flex_box_start_1", &LOC))) .with_child(demo_box(Lc::t("flex_box_start_2", &LOC))) .with_child(demo_box(Lc::t("flex_box_end", &LOC)).with_prop(FlexItem::push_end())), ); let mut wrap_row = demo_row( Flex::new() .with_wrap(flex::Behavior::Wrap) .with_align_content(flex::AlignContent::SpaceBetween) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_prop(PropsOp::add_style("max-width", "20rem")) .with_prop(PropsOp::add_style("min-height", "11rem")); for label in ["1", "2", "3", "4", "5", "6", "7", "8"] { wrap_row = wrap_row.with_child( sized_box(flex_item(label), "0.5rem 1rem") .with_prop(PropsOp::add_style("width", "4rem")), ); } block .with_child(caption( Lc::t("flex_title_wrap", &LOC), Lc::n(concat!( "Flex::new()", ".with_wrap(Behavior::Wrap)", ".with_align_content(AlignContent::SpaceBetween)", )), )) .with_child(wrap_row) .with_child(caption( Lc::t("flex_title_order", &LOC), Lc::n("FlexItem::new().with_order(ItemOrder::First) / .with_order(ItemOrder::Last)"), )) .with_child( demo_row(Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(0.5)))) .with_child( demo_box(Lc::n("A")) .with_prop(FlexItem::new().with_order(flex::ItemOrder::Last)), ) .with_child(demo_box(Lc::n("B"))) .with_child(demo_box(Lc::n("C"))) .with_child(demo_box(Lc::n("D"))) .with_child( demo_box(Lc::n("E")) .with_prop(FlexItem::new().with_order(flex::ItemOrder::First)), ), ) .with_child(caption( Lc::t("flex_title_gap_none", &LOC), Lc::n("Flex::new() (Gap::None por defecto)"), )) .with_child( demo_row(Flex::new()) .with_child(demo_box(flex_item("1"))) .with_child(demo_box(flex_item("2"))) .with_child(demo_box(flex_item("3"))), ) .with_child(caption( Lc::t("flex_title_gap_some", &LOC), Lc::n("Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(1.5)))"), )) .with_child( demo_row(Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(1.5)))) .with_child(demo_box(flex_item("1"))) .with_child(demo_box(flex_item("2"))) .with_child(demo_box(flex_item("3"))), ) .with_child(caption( Lc::t("flex_title_grid_thirds", &LOC), Lc::n("FlexItem::new().with_size(flex::ItemSize::Percent33)"), )) .with_child( demo_row(Flex::new()) .with_child( demo_box(Lc::n("1/3")) .with_prop(FlexItem::new().with_size(flex::ItemSize::Percent33)), ) .with_child( demo_box(Lc::n("1/3")) .with_prop(FlexItem::new().with_size(flex::ItemSize::Percent33)), ) .with_child( demo_box(Lc::n("1/3")) .with_prop(FlexItem::new().with_size(flex::ItemSize::Percent33)), ), ) .with_child(caption( Lc::t("flex_title_grid_offset", &LOC), Lc::n(concat!( "FlexItem::new()", ".with_size(ItemSize::Percent50)", ".with_offset(ItemOffset::Percent25)", )), )) .with_child( demo_row(Flex::new()).with_child( demo_box(Lc::t("flex_box_half_centered", &LOC)).with_prop( FlexItem::new() .with_size(flex::ItemSize::Percent50) .with_offset(flex::ItemOffset::Percent25), ), ), ) .with_child(caption( Lc::t("flex_title_toolbar", &LOC), Lc::t("flex_desc_toolbar", &LOC), )) .with_child( demo_row( Flex::new() .with_align(flex::Align::Center) .with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))), ) .with_child(demo_box(Lc::t("flex_box_file", &LOC))) .with_child(demo_box(Lc::t("flex_box_edit", &LOC))) .with_child(demo_box(Lc::t("flex_box_view", &LOC))) .with_child(demo_box(Lc::t("flex_box_profile", &LOC)).with_prop(FlexItem::push_end())) .with_child(demo_box(Lc::t("flex_box_logout", &LOC))), ) } // **< HELPERS >************************************************************************************ // Aspecto fijo de las cajas de muestra. fn demo_box_styles() -> AssetsOp { AssetsOp::add_responsive_styles( None, "flex-demo-box", [ ("background-color", "#0d6efd"), ("color", "#fff"), ("min-width", "3rem"), ("width", "auto"), ("max-width", "none"), ("margin", "0"), ("border-radius", "0.375rem"), ("text-align", "center"), ], ) } // Aspecto fijo de las filas de muestra. fn demo_row_styles() -> AssetsOp { AssetsOp::add_responsive_styles( None, "flex-demo-row", [ ("background-color", "#f1f3f5"), ("width", "100%"), ("max-width", "none"), ("margin", "0 0 1.5rem"), ("padding", "0.75rem"), ], ) } // Caja con fondo azul y relleno vertical configurable, para mostrar diferencias de altura. fn sized_box(label: Lc, padding: &'static str) -> Container { Container::new() .with_prop(PropsOp::add_classes("flex-demo-box")) .with_prop(PropsOp::add_style("padding", padding)) .with_child(Html::with(move |cx| html! { (label.using(cx)) })) } // Caja con el relleno vertical estandar del resto de ejemplos. fn demo_box(label: Lc) -> Container { sized_box(label, "0.5rem 1rem") } // Etiqueta "Flex item N" para las cajas que solo se distinguen por su posicion. fn flex_item(n: impl Into) -> Lc { Lc::t("flex_item_label", &LOC).with_arg("n", n) } // Fila de demostracion con fondo gris para visualizar los limites del propio contenedor flex. fn demo_row(flex: Flex) -> Container { Container::new() .with_prop(PropsOp::add_classes("flex-demo-row")) .with_flex(flex) } // Titulo y fragmento de codigo que introducen cada demostracion. fn caption(title: Lc, code: Lc) -> Html { Html::with(move |cx| { html! { h3 { (title.using(cx)) } p { code { (code.using(cx)) } } } }) } #[pagetop::main] async fn main() -> std::io::Result<()> { Application::prepare(&IntroFlex).await.run().await }