✨ [bootsier] Nuevo componente Dropdown
This commit is contained in:
parent
13932dc930
commit
0b0ca31ad2
5 changed files with 221 additions and 0 deletions
|
|
@ -20,6 +20,10 @@ pub use offcanvas::{
|
||||||
pub mod navbar;
|
pub mod navbar;
|
||||||
pub use navbar::{Navbar, NavbarContent, NavbarToggler};
|
pub use navbar::{Navbar, NavbarContent, NavbarToggler};
|
||||||
|
|
||||||
|
// Dropdown.
|
||||||
|
pub mod dropdown;
|
||||||
|
pub use dropdown::Dropdown;
|
||||||
|
|
||||||
/// Define los puntos de interrupción (*breakpoints*) usados por Bootstrap para diseño responsivo.
|
/// Define los puntos de interrupción (*breakpoints*) usados por Bootstrap para diseño responsivo.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
|
|
|
||||||
5
packages/pagetop-bootsier/src/bs/dropdown.rs
Normal file
5
packages/pagetop-bootsier/src/bs/dropdown.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
mod component;
|
||||||
|
pub use component::Dropdown;
|
||||||
|
|
||||||
|
mod item;
|
||||||
|
pub use item::Item;
|
||||||
99
packages/pagetop-bootsier/src/bs/dropdown/component.rs
Normal file
99
packages/pagetop-bootsier/src/bs/dropdown/component.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::bs::dropdown;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Dropdown {
|
||||||
|
id : OptionId,
|
||||||
|
classes: OptionClasses,
|
||||||
|
items : Children,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentTrait for Dropdown {
|
||||||
|
fn new() -> Self {
|
||||||
|
Dropdown::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
self.id.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||||
|
self.alter_classes(ClassesOp::Prepend, "dropdown");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||||
|
let items = self.items().render(cx);
|
||||||
|
if items.is_empty() {
|
||||||
|
return PrepareMarkup::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrepareMarkup::With(html! {
|
||||||
|
div id=[self.id()] class=[self.classes().get()] {
|
||||||
|
button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-secondary dropdown-toggle"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-expanded="false"
|
||||||
|
{
|
||||||
|
("Dropdown button")
|
||||||
|
}
|
||||||
|
ul class="dropdown-menu" {
|
||||||
|
li {
|
||||||
|
a class="dropdown-item" href="#" {
|
||||||
|
("Action")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
a class="dropdown-item" href="#" {
|
||||||
|
("Another action")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
a class="dropdown-item" href="#" {
|
||||||
|
("Something else here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dropdown {
|
||||||
|
// Dropdown BUILDER.
|
||||||
|
|
||||||
|
#[fn_builder]
|
||||||
|
pub fn with_id(mut self, id: impl Into<String>) -> Self {
|
||||||
|
self.id.alter_value(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[fn_builder]
|
||||||
|
pub fn with_classes(mut self, op: ClassesOp, classes: impl Into<String>) -> Self {
|
||||||
|
self.classes.alter_value(op, classes);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_item(mut self, item: dropdown::Item) -> Self {
|
||||||
|
self.items.add(Child::with(item));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[fn_builder]
|
||||||
|
pub fn with_items(mut self, op: TypedOp<dropdown::Item>) -> Self {
|
||||||
|
self.items.alter_typed(op);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dropdown GETTERS.
|
||||||
|
|
||||||
|
pub fn classes(&self) -> &OptionClasses {
|
||||||
|
&self.classes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn items(&self) -> &Children {
|
||||||
|
&self.items
|
||||||
|
}
|
||||||
|
}
|
||||||
109
packages/pagetop-bootsier/src/bs/dropdown/item.rs
Normal file
109
packages/pagetop-bootsier/src/bs/dropdown/item.rs
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
type Label = L10n;
|
||||||
|
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum ItemType {
|
||||||
|
#[default]
|
||||||
|
Void,
|
||||||
|
Label(Label),
|
||||||
|
Link(Label, FnContextualPath),
|
||||||
|
LinkBlank(Label, FnContextualPath),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item.
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Item {
|
||||||
|
item_type: ItemType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentTrait for Item {
|
||||||
|
fn new() -> Self {
|
||||||
|
Item::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||||
|
let description: Option<String> = None;
|
||||||
|
|
||||||
|
// Obtiene la URL actual desde `cx.request`.
|
||||||
|
let current_path = cx.request().path();
|
||||||
|
|
||||||
|
match self.item_type() {
|
||||||
|
ItemType::Void => PrepareMarkup::None,
|
||||||
|
ItemType::Label(label) => PrepareMarkup::With(html! {
|
||||||
|
li class="dropdown-item" {
|
||||||
|
span title=[description] {
|
||||||
|
//(left_icon)
|
||||||
|
(label.escaped(cx.langid()))
|
||||||
|
//(right_icon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
ItemType::Link(label, path) => {
|
||||||
|
let item_path = path(cx);
|
||||||
|
let (class, aria) = if item_path == current_path {
|
||||||
|
("dropdown-item active", Some("page"))
|
||||||
|
} else {
|
||||||
|
("dropdown-item", None)
|
||||||
|
};
|
||||||
|
PrepareMarkup::With(html! {
|
||||||
|
li class=(class) aria-current=[aria] {
|
||||||
|
a class="nav-link" href=(item_path) title=[description] {
|
||||||
|
//(left_icon)
|
||||||
|
(label.escaped(cx.langid()))
|
||||||
|
//(right_icon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ItemType::LinkBlank(label, path) => {
|
||||||
|
let item_path = path(cx);
|
||||||
|
let (class, aria) = if item_path == current_path {
|
||||||
|
("dropdown-item active", Some("page"))
|
||||||
|
} else {
|
||||||
|
("dropdown-item", None)
|
||||||
|
};
|
||||||
|
PrepareMarkup::With(html! {
|
||||||
|
li class=(class) aria-current=[aria] {
|
||||||
|
a class="nav-link" href=(item_path) title=[description] target="_blank" {
|
||||||
|
//(left_icon)
|
||||||
|
(label.escaped(cx.langid()))
|
||||||
|
//(right_icon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Item {
|
||||||
|
pub fn label(label: L10n) -> Self {
|
||||||
|
Item {
|
||||||
|
item_type: ItemType::Label(label),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn link(label: L10n, path: FnContextualPath) -> Self {
|
||||||
|
Item {
|
||||||
|
item_type: ItemType::Link(label, path),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn link_blank(label: L10n, path: FnContextualPath) -> Self {
|
||||||
|
Item {
|
||||||
|
item_type: ItemType::LinkBlank(label, path),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item GETTERS.
|
||||||
|
|
||||||
|
pub fn item_type(&self) -> &ItemType {
|
||||||
|
&self.item_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use pagetop::prelude::*;
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::bs::Dropdown;
|
||||||
|
|
||||||
type Label = L10n;
|
type Label = L10n;
|
||||||
|
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
|
|
@ -9,6 +11,7 @@ pub enum ItemType {
|
||||||
Label(Label),
|
Label(Label),
|
||||||
Link(Label, FnContextualPath),
|
Link(Label, FnContextualPath),
|
||||||
LinkBlank(Label, FnContextualPath),
|
LinkBlank(Label, FnContextualPath),
|
||||||
|
Dropdown(Typed<Dropdown>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item.
|
// Item.
|
||||||
|
|
@ -75,6 +78,7 @@ impl ComponentTrait for Item {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
ItemType::Dropdown(menu) => PrepareMarkup::With(html! { (menu.render(cx)) }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue