diff --git a/src/app.rs b/src/app.rs index d76e0ec..68a0d27 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,6 +2,7 @@ use crate::buttons::Button; use crate::collapse::Collapse; use crate::forms::controls::Switch; use crate::icon::*; +use crate::menu::*; use crate::tree::*; use crate::Intent; use yew::prelude::*; @@ -19,6 +20,7 @@ pub struct App { tree: TreeData, callback_expand_node: Callback<(NodeId, MouseEvent)>, callback_select_node: Callback<(NodeId, MouseEvent)>, + doc_menu: DocMenu, } pub enum Msg { @@ -27,6 +29,7 @@ pub enum Msg { ToggleCollapse, ExpandNode(NodeId), SelectNode(NodeId), + GoToMenu(DocMenu), } impl Component for App { @@ -102,6 +105,7 @@ impl Component for App { tree: tree.into(), callback_expand_node: link.callback(|(node_id, _)| Msg::ExpandNode(node_id)), callback_select_node: link.callback(|(node_id, _)| Msg::SelectNode(node_id)), + doc_menu: DocMenu::Tree, link, } } @@ -127,6 +131,9 @@ impl Component for App { let node = tree.get_mut(&node_id).unwrap(); node.data_mut().is_selected ^= true; } + Msg::GoToMenu(doc_menu) => { + self.doc_menu = doc_menu; + } } true } @@ -149,53 +156,93 @@ impl Component for App { html! {
-

{"Counter: "} { self.counter }

- -
-
- -
-
- - -
-                            
{"[INFO]: Installing wasm-bindgen..."}
-
{"[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended"}
-
{"[INFO]: :-) Done in 0.69s"}
-
{"[INFO]: :-) Your wasm pkg is ready to publish at /home/cecile/repos/blueprint-rs/./static."}
-
{" Index: enabled, Upload: disabled, Cache: disabled, Cors: enabled, Range: enabled, Sort: enabled, Threads: 3"}
-
{" Auth: disabled, Compression: disabled"}
-
{" https: disabled, Cert: , Cert-Password: "}
-
{" Root: /home/cecile/repos/blueprint-rs,"}
-
{" TryFile404: "}
-
{" Address: http://0.0.0.0:8000"}
-
{" ======== [2020-09-07 20:39:46] ========"}
-
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /"}
-
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /static/blueprint.css"}
-
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /static/wasm.js"}
-
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /static/wasm_bg.wasm"}
-
-
-
-
- - tree=self.tree.clone() - on_collapse=Some(self.callback_expand_node.clone()) - on_expand=Some(self.callback_expand_node.clone()) - onclick=Some(self.callback_select_node.clone()) - /> + + + + + + + +
+ { + match self.doc_menu { + DocMenu::Button => html! { +
+

{"Counter: "} { self.counter }

+
+ +
+
+ }, + DocMenu::Switch => html! { +
+ +
+ }, + DocMenu::Collapse => html! { +
+ + +
+                                        
{"[INFO]: Installing wasm-bindgen..."}
+
{"[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended"}
+
{"[INFO]: :-) Done in 0.69s"}
+
{"[INFO]: :-) Your wasm pkg is ready to publish at /home/cecile/repos/blueprint-rs/./static."}
+
{" Index: enabled, Upload: disabled, Cache: disabled, Cors: enabled, Range: enabled, Sort: enabled, Threads: 3"}
+
{" Auth: disabled, Compression: disabled"}
+
{" https: disabled, Cert: , Cert-Password: "}
+
{" Root: /home/cecile/repos/blueprint-rs,"}
+
{" TryFile404: "}
+
{" Address: http://0.0.0.0:8000"}
+
{" ======== [2020-09-07 20:39:46] ========"}
+
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /"}
+
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /static/blueprint.css"}
+
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /static/wasm.js"}
+
{"[2020-09-07 20:39:46] - 127.0.0.1 - 200 - GET /static/wasm_bg.wasm"}
+
+
+
+ }, + DocMenu::Tree => html! { +
+ + tree=self.tree.clone() + on_collapse=Some(self.callback_expand_node.clone()) + on_expand=Some(self.callback_expand_node.clone()) + onclick=Some(self.callback_select_node.clone()) + /> +
+ }, + DocMenu::Icon => html! { +
+ +
+ }, + DocMenu::Menu => html!(), + } + }
} } } + +#[derive(Debug, Copy, Clone)] +pub enum DocMenu { + Button, + Collapse, + Icon, + Menu, + Switch, + Tree, +} diff --git a/src/lib.rs b/src/lib.rs index 0ad9a81..1824a24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ pub mod buttons; pub mod collapse; pub mod forms; pub mod icon; +pub mod menu; pub mod tree; use yew::virtual_dom::Classes; diff --git a/src/menu.rs b/src/menu.rs new file mode 100644 index 0000000..f15f713 --- /dev/null +++ b/src/menu.rs @@ -0,0 +1,147 @@ +use crate::icon::{Icon, IconName}; +use crate::Intent; +use yew::prelude::*; + +pub struct Menu { + props: MenuProps, +} + +#[derive(Clone, PartialEq, Properties)] +pub struct MenuProps { + #[prop_or_default] + pub large: bool, + #[prop_or_default] + pub class: Option, + #[prop_or_default] + pub r#ref: NodeRef, + pub children: html::Children, +} + +impl Component for Menu { + type Message = (); + type Properties = MenuProps; + + fn create(props: Self::Properties, _link: ComponentLink) -> Self { + Menu { props } + } + + fn update(&mut self, _msg: Self::Message) -> ShouldRender { + true + } + + fn change(&mut self, props: Self::Properties) -> ShouldRender { + if self.props != props { + self.props = props; + true + } else { + false + } + } + + fn view(&self) -> Html { + let mut class = Classes::from("bp3-menu"); + if self.props.large { + class.push("bp3-large"); + } + class = class.extend(self.props.class.clone()); + + html! { +
    + {self.props.children.clone()} +
+ } + } +} + +pub struct MenuItem { + props: MenuItemProps, +} + +#[derive(Clone, PartialEq, Properties)] +pub struct MenuItemProps { + #[prop_or_default] + pub text: yew::virtual_dom::VNode, + #[prop_or_default] + pub text_class: Option, + #[prop_or_default] + pub active: bool, + #[prop_or_default] + pub class: Option, + // TODO: pub disabled: bool, + #[prop_or_default] + pub label: Option, + #[prop_or_default] + pub label_class: Option, + // TODO: pub multiline: bool, (requires ) + // TODO: popover_props, should_dismiss_popover + #[prop_or_default] + pub intent: Option, + #[prop_or_default] + pub icon: IconName, + #[prop_or_default] + pub onclick: Callback, + // TODO: pub children: html::Children, +} + +impl Component for MenuItem { + type Message = (); + type Properties = MenuItemProps; + + fn create(props: Self::Properties, _link: ComponentLink) -> Self { + MenuItem { props } + } + + fn update(&mut self, _msg: Self::Message) -> ShouldRender { + true + } + + fn change(&mut self, props: Self::Properties) -> ShouldRender { + if self.props != props { + self.props = props; + true + } else { + false + } + } + + fn view(&self) -> Html { + let mut anchor_class = Classes::from("bp3-menu-item"); + if self.props.active { + anchor_class.push("bp3-active"); + } + if let Some(intent) = self.props.intent.clone() { + anchor_class = anchor_class.extend(intent); + } else if self.props.active { + anchor_class = anchor_class.extend(Intent::Primary); + } + anchor_class = anchor_class.extend(self.props.class.clone()); + + let mut text_class = Classes::from("bp3-text"); + text_class.push("bp3-fill"); + text_class = text_class.extend(self.props.text_class.clone()); + + html! { +
  • + + +
    + {self.props.text.clone()} +
    + { + if let Some(label) = self.props.label.clone() { + let mut label_class = Classes::from("bp3-menu-item-label"); + label_class = label_class.extend(self.props.label_class.clone()); + + html!({label}) + } else { + html!() + } + } +
    +
  • + } + } +}