Example props (#25)

This commit is contained in:
Cecile Tonglet 2020-09-28 15:24:04 +02:00 committed by GitHub
parent ac387f9789
commit 03ea949699
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 426 additions and 132 deletions

2
.gitignore vendored
View file

@ -1,3 +1,3 @@
/target target
/public /public
/*.tgz /*.tgz

26
Cargo.lock generated
View file

@ -690,6 +690,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c" checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro", "wasm-bindgen-macro",
] ]
@ -854,6 +856,7 @@ dependencies = [
"regex", "regex",
"web-sys", "web-sys",
"yew", "yew",
"yewtil",
] ]
[[package]] [[package]]
@ -866,3 +869,26 @@ dependencies = [
"yew", "yew",
"yewprint", "yewprint",
] ]
[[package]]
name = "yewtil"
version = "0.3.1"
source = "git+https://github.com/yewstack/yew.git?rev=1507c21b#1507c21b39e7941f7b9fe8ff5af792cf55be1f6f"
dependencies = [
"futures",
"log",
"wasm-bindgen",
"wasm-bindgen-futures",
"yew",
"yewtil-macro",
]
[[package]]
name = "yewtil-macro"
version = "0.1.0"
source = "git+https://github.com/yewstack/yew.git?rev=1507c21b#1507c21b39e7941f7b9fe8ff5af792cf55be1f6f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -66,7 +66,7 @@ Roadmap
- [ ] AnchorButton - [ ] AnchorButton
- [ ] [ButtonGroup](https://blueprintjs.com/docs/#core/components/button-group) - [ ] [ButtonGroup](https://blueprintjs.com/docs/#core/components/button-group)
- depends on: Button - depends on: Button
- [ ] [Callout](https://blueprintjs.com/docs/#core/components/callout) - [x] [Callout](https://blueprintjs.com/docs/#core/components/callout)
- [ ] [Card](https://blueprintjs.com/docs/#core/components/card) - [ ] [Card](https://blueprintjs.com/docs/#core/components/card)
- [x] [Collapse](https://blueprintjs.com/docs/#core/components/collapse) - [x] [Collapse](https://blueprintjs.com/docs/#core/components/collapse)
- [ ] [CollapsibleList](https://blueprintjs.com/docs/#core/components/collapsible-list) - [ ] [CollapsibleList](https://blueprintjs.com/docs/#core/components/collapsible-list)

View file

@ -49,7 +49,7 @@
white-space: pre-wrap; white-space: pre-wrap;
} }
.docs-example-wrapper .bp3-code-block > pre { .docs-example-wrapper .bp3-code-block pre {
margin: 0; margin: 0;
white-space: pre-wrap; white-space: pre-wrap;
} }
@ -64,25 +64,25 @@
background-color: #293742; background-color: #293742;
} }
.docs-example-wrapper > .docs-source > .bp3-button { .docs-source > .bp3-button {
background-color: #ebf1f5; background-color: #ebf1f5;
} }
.bp3-dark .docs-example-wrapper > .docs-source > .bp3-button { .bp3-dark .docs-source > .bp3-button {
background-color: #394b59; background-color: #394b59;
} }
.docs-example-wrapper > .docs-source { .docs-source {
margin-bottom: 40px; margin-bottom: 40px;
margin-top: 10px; margin-top: 10px;
} }
.docs-example-wrapper > .docs-source .bp3-code-block { .docs-source .bp3-code-block {
filter: invert(1) hue-rotate(180deg) contrast(2); filter: invert(1) hue-rotate(180deg) contrast(2);
background-color: #002b36; background-color: #002b36;
} }
.bp3-dark .docs-example-wrapper > .docs-source .bp3-code-block { .bp3-dark .docs-source .bp3-code-block {
filter: inherit; filter: inherit;
} }
</style> </style>

View file

@ -4,6 +4,13 @@ use yewprint::Button;
pub struct Example { pub struct Example {
link: ComponentLink<Self>, link: ComponentLink<Self>,
counter: i64, counter: i64,
props: ExampleProps,
}
#[derive(Clone, PartialEq, Properties)]
pub struct ExampleProps {
pub minimal: bool,
pub fill: bool,
} }
pub enum Msg { pub enum Msg {
@ -12,10 +19,14 @@ pub enum Msg {
impl Component for Example { impl Component for Example {
type Message = Msg; type Message = Msg;
type Properties = (); type Properties = ExampleProps;
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self { fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
Example { counter: 0, link } Example {
counter: 0,
link,
props,
}
} }
fn update(&mut self, msg: Self::Message) -> ShouldRender { fn update(&mut self, msg: Self::Message) -> ShouldRender {
@ -25,16 +36,27 @@ impl Component for Example {
true true
} }
fn change(&mut self, _props: Self::Properties) -> ShouldRender { fn change(&mut self, props: Self::Properties) -> ShouldRender {
true if self.props != props {
self.props = props;
true
} else {
false
}
} }
fn view(&self) -> Html { fn view(&self) -> Html {
html! { html! {
<div> <div>
<p> {"Counter: "} { self.counter }</p> <p>{"Counter: "}{self.counter}</p>
<div> <div>
<Button onclick=self.link.callback(|_| Msg::AddOne)>{ "Add 1" }</Button> <Button
onclick=self.link.callback(|_| Msg::AddOne)
minimal=self.props.minimal
fill=self.props.fill
>
{"Add 1"}
</Button>
</div> </div>
</div> </div>
} }

View file

@ -1,16 +1,31 @@
use yew::prelude::*; mod example;
pub struct ButtonDoc; use crate::ExampleContainer;
use example::*;
use yew::prelude::*;
use yewprint::{Switch, H1, H5};
pub struct ButtonDoc {
callback: Callback<ExampleProps>,
state: ExampleProps,
}
impl Component for ButtonDoc { impl Component for ButtonDoc {
type Message = (); type Message = ExampleProps;
type Properties = (); type Properties = ();
fn create(_: Self::Properties, _link: ComponentLink<Self>) -> Self { fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
ButtonDoc ButtonDoc {
callback: link.callback(|x| x),
state: ExampleProps {
minimal: false,
fill: false,
},
}
} }
fn update(&mut self, _msg: Self::Message) -> ShouldRender { fn update(&mut self, msg: Self::Message) -> ShouldRender {
self.state = msg;
true true
} }
@ -19,13 +34,56 @@ impl Component for ButtonDoc {
} }
fn view(&self) -> Html { fn view(&self) -> Html {
let source = crate::include_example!(); let example_props = self.state.clone();
let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! { html! {
<div> <div>
<h1>{"Button"}</h1> <H1 class="docs-title">{"Button"}</H1>
<div>{source}</div> <div>
<ExampleContainer
source=source
props=Some(html! {
<ButtonProps
callback={self.callback.clone()}
props=example_props.clone()
/>
})
>
<Example with example_props />
</ExampleContainer>
</div>
</div> </div>
} }
} }
} }
crate::build_example_prop_component! {
ButtonProps for ExampleProps =>
fn view(&self) -> Html {
html! {
<div>
<H5>{"Props"}</H5>
<Switch
onclick=self.update_props(|props| ExampleProps {
minimal: !props.minimal,
..props
})
checked=self.props.minimal
label="Minimal"
/>
<Switch
onclick=self.update_props(|props| ExampleProps {
fill: !props.fill,
..props
})
checked=self.props.fill
label="Fill"
/>
</div>
}
}
}

View file

@ -1,66 +1,48 @@
use yew::prelude::*; use yew::prelude::*;
use yewprint::{Callout, Intent, Menu, MenuItem, Switch}; use yewprint::{Callout, Intent};
pub struct Example { pub struct Example {
link: ComponentLink<Self>, props: ExampleProps,
intent: Option<Intent>,
show_icon: bool,
show_title: bool,
} }
pub enum Msg { #[derive(Clone, PartialEq, Properties)]
ChangeIntent(Option<Intent>), pub struct ExampleProps {
ToggleIcon, pub intent: Option<Intent>,
ToggleTitle, pub show_icon: bool,
pub show_title: bool,
} }
impl Component for Example { impl Component for Example {
type Message = Msg; type Message = ();
type Properties = (); type Properties = ExampleProps;
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self { fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Example { Example { props }
link,
intent: None,
show_icon: false,
show_title: true,
}
} }
fn update(&mut self, msg: Self::Message) -> ShouldRender { fn update(&mut self, _msg: Self::Message) -> ShouldRender {
match msg {
Msg::ChangeIntent(new_intent) => self.intent = new_intent,
Msg::ToggleIcon => self.show_icon = !self.show_icon,
Msg::ToggleTitle => self.show_title = !self.show_title,
}
true true
} }
fn change(&mut self, _props: Self::Properties) -> ShouldRender { fn change(&mut self, props: Self::Properties) -> ShouldRender {
true if self.props != props {
self.props = props;
true
} else {
false
}
} }
fn view(&self) -> Html { fn view(&self) -> Html {
let title = if self.show_title { let title = if self.props.show_title {
Some("Visually important content") Some("Visually important content")
} else { } else {
None None
}; };
html! { html! {
<Callout title=title without_icon=self.show_icon intent=self.intent> <Callout title=title without_icon=!self.props.show_icon intent=self.props.intent>
<p> {"The Callout element's background reflects its intent, if any."}</p> <p>{"The Callout element's background reflects its intent, if any."}</p>
<div>
<Switch onclick=self.link.callback(|_| Msg::ToggleIcon) checked=self.show_icon label={ "Show/hide icon" } />
<Switch onclick=self.link.callback(|_| Msg::ToggleTitle) checked=self.show_title label={ "Show/hide title" } />
<p> {"Select intent:"}</p>
<Menu>
<MenuItem onclick=self.link.callback(|_| Msg::ChangeIntent(None)) text=html!{"None"}/>
<MenuItem onclick=self.link.callback(|_| Msg::ChangeIntent(Some(Intent::Primary))) text=html!{"Primary"}/>
<MenuItem onclick=self.link.callback(|_| Msg::ChangeIntent(Some(Intent::Success))) text=html!{"Success"}/>
<MenuItem onclick=self.link.callback(|_| Msg::ChangeIntent(Some(Intent::Warning))) text=html!{"Warning"}/>
<MenuItem onclick=self.link.callback(|_| Msg::ChangeIntent(Some(Intent::Danger))) text=html!{"Danger"}/>
</Menu>
</div>
</Callout> </Callout>
} }
} }

View file

@ -1,16 +1,32 @@
use yew::prelude::*; mod example;
pub struct CalloutDoc; use crate::ExampleContainer;
use example::*;
use yew::prelude::*;
use yewprint::{Intent, Menu, MenuItem, Switch, H1, H5};
pub struct CalloutDoc {
callback: Callback<ExampleProps>,
state: ExampleProps,
}
impl Component for CalloutDoc { impl Component for CalloutDoc {
type Message = (); type Message = ExampleProps;
type Properties = (); type Properties = ();
fn create(_: Self::Properties, _link: ComponentLink<Self>) -> Self { fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
CalloutDoc CalloutDoc {
callback: link.callback(|x| x),
state: ExampleProps {
show_icon: false,
intent: None,
show_title: true,
},
}
} }
fn update(&mut self, _msg: Self::Message) -> ShouldRender { fn update(&mut self, msg: Self::Message) -> ShouldRender {
self.state = msg;
true true
} }
@ -19,13 +35,98 @@ impl Component for CalloutDoc {
} }
fn view(&self) -> Html { fn view(&self) -> Html {
let source = crate::include_example!(); let example_props = self.state.clone();
let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! { html! {
<div> <div>
<h1>{"Callout"}</h1> <H1 class="docs-title">{"Callout"}</H1>
<div>{source}</div> <ExampleContainer
source=source
props=Some(html! {
<CalloutProps
callback={self.callback.clone()}
props=example_props.clone()
/>
})
>
<Example with example_props />
</ExampleContainer>
</div> </div>
} }
} }
} }
crate::build_example_prop_component! {
CalloutProps for ExampleProps =>
fn view(&self) -> Html {
html! {
<div>
<H5>{"Props"}</H5>
<div>
<Switch
onclick=self.update_props(|props| ExampleProps {
show_icon: !props.show_icon,
..props
})
checked=self.props.show_icon
label="Show/hide icon"
/>
<Switch
onclick=self.update_props(|props| ExampleProps {
show_title: !props.show_title,
..props
})
checked=self.props.show_title
label="Show/hide title"
/>
<p>{"Select intent:"}</p>
<Menu>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
intent: None,
..props
})
text=html!{"None"}
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
intent: Some(Intent::Primary),
..props
})
text=html!{"Primary"}
intent=Intent::Primary
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
intent: Some(Intent::Success),
..props
})
text=html!{"Success"}
intent=Intent::Success
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
intent: Some(Intent::Warning),
..props
})
text=html!{"Warning"}
intent=Intent::Warning
/>
<MenuItem
onclick=self.update_props(|props| ExampleProps {
intent: Some(Intent::Danger),
..props
})
text=html!{"Danger"}
intent=Intent::Danger
/>
</Menu>
</div>
</div>
}
}
}

View file

@ -1,5 +1,5 @@
use yew::prelude::*; use yew::prelude::*;
use yewprint::{Button,Collapse}; use yewprint::{Button, Collapse};
pub struct Example { pub struct Example {
link: ComponentLink<Self>, link: ComponentLink<Self>,

View file

@ -1,4 +1,9 @@
mod example;
use crate::ExampleContainer;
use example::*;
use yew::prelude::*; use yew::prelude::*;
use yewprint::H1;
pub struct CollapseDoc; pub struct CollapseDoc;
@ -19,12 +24,17 @@ impl Component for CollapseDoc {
} }
fn view(&self) -> Html { fn view(&self) -> Html {
let source = crate::include_example!(); let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! { html! {
<div> <div>
<h1>{"Tree"}</h1> <H1 class="docs-title">{"Collapse"}</H1>
<div>{source}</div> <ExampleContainer source=source>
<Example />
</ExampleContainer>
</div> </div>
} }
} }

View file

@ -15,6 +15,8 @@ pub enum Msg {
pub struct Props { pub struct Props {
pub source: yew::virtual_dom::VNode, pub source: yew::virtual_dom::VNode,
pub children: html::Children, pub children: html::Children,
#[prop_or_default]
pub props: Option<yew::virtual_dom::VNode>,
} }
impl Component for ExampleContainer { impl Component for ExampleContainer {
@ -36,16 +38,33 @@ impl Component for ExampleContainer {
true true
} }
fn change(&mut self, _props: Self::Properties) -> ShouldRender { fn change(&mut self, props: Self::Properties) -> ShouldRender {
// TODO: never re-render this component? How to optimize this if self.props != props {
false self.props = props;
true
} else {
false
}
} }
fn view(&self) -> Html { fn view(&self) -> Html {
html! { html! {
<div class="docs-example-wrapper"> <div class="docs-example-wrapper">
<div class="docs-example"> <div class="docs-example-frame docs-example-frame-row">
{self.props.children.clone()} <div class="docs-example">
{self.props.children.clone()}
</div>
{
if let Some(props) = self.props.props.clone() {
html! {
<div class="docs-example-options">
{props}
</div>
}
} else {
html!()
}
}
</div> </div>
<div class="docs-source"> <div class="docs-source">
<Button <Button
@ -70,25 +89,47 @@ impl Component for ExampleContainer {
} }
#[macro_export] #[macro_export]
macro_rules! include_example { macro_rules! build_example_prop_component {
() => {{ ($name:ident for $prop_component:ty => $($view:tt)*) => {
use crate::ExampleContainer; #[derive(Clone, PartialEq, Properties)]
pub struct $name {
let source = crate::include_raw_html!( callback: Callback<$prop_component>,
concat!(env!("OUT_DIR"), "/", file!(), ".html"), props: $prop_component,
"bp3-code-block"
);
mod source {
// TODO: example.rs files are not formatted because of this include
include!("example.rs");
} }
use source::Example;
html! { impl Component for $name {
<ExampleContainer source={source}> type Message = ();
<Example /> type Properties = Self;
</ExampleContainer>
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
props
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props.props || self.callback != props.callback {
self.props = props.props;
self.callback = props.callback;
true
} else {
false
}
}
$($view)*
} }
}};
impl $name {
fn update_props(
&self,
updater: impl Fn($prop_component) -> $prop_component + 'static,
) -> Callback<MouseEvent> {
let props = self.props.clone();
self.callback.clone().reform(move |_| updater(props.clone()))
}
}
};
} }

View file

@ -1,4 +1,9 @@
mod example;
use crate::ExampleContainer;
use example::*;
use yew::prelude::*; use yew::prelude::*;
use yewprint::H1;
pub struct IconDoc; pub struct IconDoc;
@ -19,12 +24,17 @@ impl Component for IconDoc {
} }
fn view(&self) -> Html { fn view(&self) -> Html {
let source = crate::include_example!(); let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! { html! {
<div> <div>
<h1>{"Icon"}</h1> <H1 class="docs-title">{"Icon"}</H1>
<div>{source}</div> <ExampleContainer source=source>
<Example />
</ExampleContainer>
</div> </div>
} }
} }

View file

@ -19,28 +19,19 @@ macro_rules! log {
#[macro_export] #[macro_export]
macro_rules! include_raw_html { macro_rules! include_raw_html {
($file:expr, $class:expr) => {{ ($file:expr $(, $class:expr)?) => {{
yew::virtual_dom::VNode::VRef(yew::web_sys::Node::from({ yew::virtual_dom::VNode::VRef(yew::web_sys::Node::from({
let div = crate::include_raw_html!(element $file); let div = web_sys::window()
div.set_class_name($class); .unwrap()
.document()
.unwrap()
.create_element("div")
.unwrap();
div.set_inner_html(include_str!($file));
$(div.set_class_name($class);)*
div div
})) }))
}}; }};
($file:expr) => {{
yew::virtual_dom::VNode::VRef(yew::web_sys::Node::from({
crate::include_raw_html!(element $file)
}))
}};
(element $file:expr) => {{
let div = web_sys::window()
.unwrap()
.document()
.unwrap()
.create_element("div")
.unwrap();
div.set_inner_html(include_str!($file));
div
}};
} }
#[wasm_bindgen::prelude::wasm_bindgen(start)] #[wasm_bindgen::prelude::wasm_bindgen(start)]

View file

@ -1,5 +1,5 @@
use yew::prelude::*; use yew::prelude::*;
use yewprint::*; use yewprint::{Switch, H1};
pub struct SwitchDoc { pub struct SwitchDoc {
props: Props, props: Props,
@ -30,7 +30,7 @@ impl Component for SwitchDoc {
fn view(&self) -> Html { fn view(&self) -> Html {
html! { html! {
<div> <div>
<h1>{"Switch"}</h1> <H1 class="docs-title">{"Switch"}</H1>
<Switch <Switch
onclick=self.props.onclick.clone() onclick=self.props.onclick.clone()
checked=self.props.dark_theme checked=self.props.dark_theme

View file

@ -1,6 +1,6 @@
use yew::prelude::*; use yew::prelude::*;
use yewprint::{Tree, Icon, NodeData, IconName, Intent, TreeData}; use yewprint::id_tree::{InsertBehavior, Node, NodeId, TreeBuilder};
use yewprint::id_tree::{InsertBehavior, Node, TreeBuilder, NodeId}; use yewprint::{Icon, IconName, Intent, NodeData, Tree, TreeData};
pub struct Example { pub struct Example {
tree: TreeData<i32>, tree: TreeData<i32>,

View file

@ -1,4 +1,9 @@
mod example;
use crate::ExampleContainer;
use example::*;
use yew::prelude::*; use yew::prelude::*;
use yewprint::H1;
pub struct TreeDoc; pub struct TreeDoc;
@ -19,12 +24,17 @@ impl Component for TreeDoc {
} }
fn view(&self) -> Html { fn view(&self) -> Html {
let source = crate::include_example!(); let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! { html! {
<div> <div>
<h1>{"Tree"}</h1> <H1 class="docs-title">{"Tree"}</H1>
<div>{source}</div> <ExampleContainer source=source>
<Example />
</ExampleContainer>
</div> </div>
} }
} }

View file

@ -15,6 +15,7 @@ is-it-maintained-open-issues = { repository = "cecton/yewprint" }
yew = { git = "https://github.com/yewstack/yew.git", rev = "1507c21b" } yew = { git = "https://github.com/yewstack/yew.git", rev = "1507c21b" }
web-sys = "0.3" web-sys = "0.3"
id_tree = "1.7" id_tree = "1.7"
yewtil = { git = "https://github.com/yewstack/yew.git", rev = "1507c21b", features = ["pure"] }
[build-dependencies] [build-dependencies]
regex = { version = "1", default-features = false, features = ["std"] } regex = { version = "1", default-features = false, features = ["std"] }

View file

@ -0,0 +1,40 @@
use yew::prelude::*;
use yewtil::{Pure, PureComponent};
macro_rules! build_component {
($name:ident, $props_name:ident, $tag:tt, $class:literal) => {
pub type $name = Pure<$props_name>;
#[derive(Debug, Clone, PartialEq, Properties)]
pub struct $props_name {
#[prop_or_default]
pub class: String,
#[prop_or_default]
pub children: html::Children,
}
impl PureComponent for $props_name {
fn render(&self) -> Html {
html! {
<$tag class=($class, self.class.clone())>
{self.children.clone()}
</$tag>
}
}
}
};
}
build_component!(H1, H1Props, h1, "bp3-heading");
build_component!(H2, H2Props, h2, "bp3-heading");
build_component!(H3, H3Props, h3, "bp3-heading");
build_component!(H4, H4Props, h4, "bp3-heading");
build_component!(H5, H5Props, h5, "bp3-heading");
build_component!(H6, H6Props, h6, "bp3-heading");
build_component!(Blockquote, BlockquoteProps, blockquote, "bp3-blockquote");
build_component!(Code, CodeProps, code, "bp3-code");
build_component!(Label, LabelProps, label, "bp3-label");
build_component!(Pre, PreProps, pre, "bp3-pre");
build_component!(Ol, OlProps, ol, "bp3-ol");
build_component!(Ul, UlProps, ul, "bp3-ul");

View file

@ -76,7 +76,7 @@ impl Component for Icon {
height={self.props.icon_size} height={self.props.icon_size}
viewBox={format!("0 0 {x} {x}", x=pixel_grid_size)} viewBox={format!("0 0 {x} {x}", x=pixel_grid_size)}
> >
<desc>{self.props.title.clone().unwrap_or_else(|| icon_string)}</desc> <desc>{self.props.title.clone().unwrap_or(icon_string)}</desc>
{ {
paths.iter() paths.iter()
.map(|x| html! { .map(|x| html! {

View file

@ -1,6 +1,7 @@
mod buttons; mod buttons;
mod callout; mod callout;
mod collapse; mod collapse;
mod html_elements;
mod icon; mod icon;
mod menu; mod menu;
mod switch; mod switch;
@ -9,6 +10,7 @@ mod tree;
pub use buttons::*; pub use buttons::*;
pub use callout::*; pub use callout::*;
pub use collapse::*; pub use collapse::*;
pub use html_elements::*;
pub use icon::*; pub use icon::*;
pub use id_tree; pub use id_tree;
pub use menu::*; pub use menu::*;
@ -43,7 +45,7 @@ impl From<bool> for ConditionalClass {
} }
impl ConditionalClass { impl ConditionalClass {
pub fn map_some(&self, value: &'static str) -> Option<&'static str> { pub fn map_some<T>(&self, value: T) -> Option<T> {
if self.0 { if self.0 {
Some(value) Some(value)
} else { } else {

View file

@ -113,7 +113,7 @@ impl Component for MenuItem {
"bp3-menu-item", "bp3-menu-item",
self.props.active.map_some("bp3-active"), self.props.active.map_some("bp3-active"),
self.props.intent self.props.intent
.and(self.props.active.map_some(Intent::Primary.as_ref())), .or_else(|| self.props.active.map_some(Intent::Primary)),
self.props.class.clone(), self.props.class.clone(),
) )
onclick={self.props.onclick.clone()} onclick={self.props.onclick.clone()}