mirror of
https://github.com/yewprint/yewprint
synced 2024-11-22 03:23:03 +00:00
Use classes within html (#23)
This commit is contained in:
parent
a5813d0fc0
commit
8a7c0ee6ff
6 changed files with 106 additions and 71 deletions
17
src/app.rs
17
src/app.rs
|
@ -1,15 +1,15 @@
|
|||
use crate::buttons::doc::*;
|
||||
use crate::collapse::doc::*;
|
||||
use crate::icon::doc::*;
|
||||
use crate::menu::*;
|
||||
use crate::switch::doc::SwitchDoc;
|
||||
use crate::switch::doc::*;
|
||||
use crate::tree::doc::*;
|
||||
use crate::{ConditionalClass, Menu, MenuItem};
|
||||
use yew::prelude::*;
|
||||
|
||||
pub struct App {
|
||||
link: ComponentLink<Self>,
|
||||
doc_menu: DocMenu,
|
||||
dark_theme: bool,
|
||||
dark_theme: ConditionalClass,
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
|
@ -23,7 +23,7 @@ impl Component for App {
|
|||
|
||||
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||
App {
|
||||
dark_theme: true,
|
||||
dark_theme: true.into(),
|
||||
doc_menu: DocMenu::Button,
|
||||
link,
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ impl Component for App {
|
|||
|
||||
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
||||
match msg {
|
||||
Msg::ToggleLight => self.dark_theme ^= true,
|
||||
Msg::ToggleLight => *self.dark_theme ^= true,
|
||||
Msg::GoToMenu(doc_menu) => {
|
||||
self.doc_menu = doc_menu;
|
||||
}
|
||||
|
@ -44,13 +44,8 @@ impl Component for App {
|
|||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let mut class = Classes::from("docs-app");
|
||||
if self.dark_theme {
|
||||
class.push("bp3-dark");
|
||||
}
|
||||
|
||||
html! {
|
||||
<div class=class>
|
||||
<div class=("docs-app", self.dark_theme.map_some("bp3-dark"))>
|
||||
<div class="docs-nav-wrapper">
|
||||
<div class="docs-nav">
|
||||
<div class="docs-nav-title">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(feature = "doc")]
|
||||
pub mod doc;
|
||||
|
||||
use crate::{Icon, IconName, Intent};
|
||||
use crate::{ConditionalClass, Icon, IconName, Intent};
|
||||
use yew::prelude::*;
|
||||
|
||||
pub struct Button {
|
||||
|
@ -11,9 +11,9 @@ pub struct Button {
|
|||
#[derive(Clone, PartialEq, Properties)]
|
||||
pub struct Props {
|
||||
#[prop_or_default]
|
||||
pub fill: bool,
|
||||
pub fill: ConditionalClass,
|
||||
#[prop_or_default]
|
||||
pub minimal: bool,
|
||||
pub minimal: ConditionalClass,
|
||||
#[prop_or_default]
|
||||
pub icon: Option<IconName>,
|
||||
#[prop_or_default]
|
||||
|
@ -47,17 +47,16 @@ impl Component for Button {
|
|||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let mut class = Classes::from("bp3-button");
|
||||
if self.props.fill {
|
||||
class.push("bp3-fill");
|
||||
}
|
||||
if self.props.minimal {
|
||||
class.push("bp3-minimal");
|
||||
}
|
||||
class = class.extend(&self.props.intent);
|
||||
|
||||
html! {
|
||||
<button class=class onclick={self.props.onclick.clone()}>
|
||||
<button
|
||||
class=(
|
||||
"bp3-button",
|
||||
self.props.fill.map_some("bp3-fill"),
|
||||
self.props.minimal.map_some("bp3-minimal"),
|
||||
self.props.intent,
|
||||
)
|
||||
onclick={self.props.onclick.clone()}
|
||||
>
|
||||
{
|
||||
if let Some(icon) = self.props.icon {
|
||||
html! {
|
||||
|
|
|
@ -58,10 +58,6 @@ impl Component for Icon {
|
|||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let mut class = Classes::from("bp3-icon");
|
||||
class.push(self.props.class.as_str());
|
||||
class = class.extend(&self.props.intent);
|
||||
|
||||
let paths = if self.props.icon_size == SIZE_STANDARD {
|
||||
icon_svg_paths_16(self.props.icon)
|
||||
} else {
|
||||
|
@ -75,7 +71,7 @@ impl Component for Icon {
|
|||
let icon_string = format!("{:?}", self.props.icon);
|
||||
|
||||
html! {
|
||||
<span class=class onclick?={self.props.onclick.clone()}>
|
||||
<span class=("bp3-icon", self.props.class.clone(), self.props.intent) onclick?={self.props.onclick.clone()}>
|
||||
<svg
|
||||
fill?={self.props.color.clone()}
|
||||
data-icon={icon_string.clone()}
|
||||
|
|
51
src/lib.rs
51
src/lib.rs
|
@ -26,7 +26,8 @@ pub use menu::*;
|
|||
pub use switch::*;
|
||||
pub use tree::*;
|
||||
|
||||
use yew::virtual_dom::Classes;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use yew::virtual_dom::{Classes, Transformer, VComp};
|
||||
|
||||
#[cfg(feature = "doc")]
|
||||
#[macro_export]
|
||||
|
@ -63,6 +64,54 @@ macro_rules! include_raw_html {
|
|||
}};
|
||||
}
|
||||
|
||||
// NOTE: this class needs to become deprecated when the feature bool_to_option lands in stable
|
||||
//
|
||||
// https://github.com/rust-lang/rust/issues/64260
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Default)]
|
||||
pub struct ConditionalClass(bool);
|
||||
|
||||
impl Transformer<bool, ConditionalClass> for VComp {
|
||||
fn transform(value: bool) -> ConditionalClass {
|
||||
ConditionalClass(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Transformer<ConditionalClass, bool> for VComp {
|
||||
fn transform(value: ConditionalClass) -> bool {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for ConditionalClass {
|
||||
fn from(value: bool) -> Self {
|
||||
ConditionalClass(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionalClass {
|
||||
pub fn map_some(&self, value: &'static str) -> Option<&'static str> {
|
||||
if self.0 {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ConditionalClass {
|
||||
type Target = bool;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ConditionalClass {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "doc")]
|
||||
#[wasm_bindgen::prelude::wasm_bindgen(start)]
|
||||
pub fn run_app() -> Result<(), wasm_bindgen::JsValue> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::icon::{Icon, IconName};
|
||||
use crate::Intent;
|
||||
use crate::{ConditionalClass, Intent};
|
||||
use yew::prelude::*;
|
||||
|
||||
pub struct Menu {
|
||||
|
@ -9,7 +9,7 @@ pub struct Menu {
|
|||
#[derive(Clone, PartialEq, Properties)]
|
||||
pub struct MenuProps {
|
||||
#[prop_or_default]
|
||||
pub large: bool,
|
||||
pub large: ConditionalClass,
|
||||
#[prop_or_default]
|
||||
pub class: Option<String>,
|
||||
#[prop_or_default]
|
||||
|
@ -39,14 +39,15 @@ impl Component for Menu {
|
|||
}
|
||||
|
||||
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! {
|
||||
<ul class=class ref={self.props.r#ref.clone()}>
|
||||
<ul
|
||||
class=(
|
||||
"bp3-menu",
|
||||
self.props.large.map_some("bp3-large"),
|
||||
self.props.class.clone(),
|
||||
)
|
||||
ref={self.props.r#ref.clone()}
|
||||
>
|
||||
{self.props.children.clone()}
|
||||
</ul>
|
||||
}
|
||||
|
@ -64,7 +65,7 @@ pub struct MenuItemProps {
|
|||
#[prop_or_default]
|
||||
pub text_class: Option<String>,
|
||||
#[prop_or_default]
|
||||
pub active: bool,
|
||||
pub active: ConditionalClass,
|
||||
#[prop_or_default]
|
||||
pub class: Option<String>,
|
||||
// TODO: pub disabled: bool,
|
||||
|
@ -105,37 +106,33 @@ impl Component for MenuItem {
|
|||
}
|
||||
|
||||
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 {
|
||||
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! {
|
||||
<li>
|
||||
<a
|
||||
class=anchor_class
|
||||
class=(
|
||||
"bp3-menu-item",
|
||||
self.props.active.map_some("bp3-active"),
|
||||
self.props.intent
|
||||
.and(self.props.active.map_some(Intent::Primary.as_ref())),
|
||||
self.props.class.clone(),
|
||||
)
|
||||
onclick={self.props.onclick.clone()}
|
||||
>
|
||||
<Icon icon={self.props.icon} />
|
||||
<div class=text_class>
|
||||
<div class=("bp3-text", "bp3-fill", self.props.text_class.clone())>
|
||||
{self.props.text.clone()}
|
||||
</div>
|
||||
{
|
||||
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!(<span class=label_class>{label}</span>)
|
||||
html! {
|
||||
<span
|
||||
class=(
|
||||
"bp3-menu-item-label",
|
||||
self.props.label_class.clone())
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
}
|
||||
} else {
|
||||
html!()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::collapse::Collapse;
|
||||
use crate::icon::{Icon, IconName};
|
||||
use crate::Intent;
|
||||
use crate::{ConditionalClass, Intent};
|
||||
use id_tree::*;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
|
@ -219,7 +219,7 @@ struct TreeNodeProps {
|
|||
icon_color: Option<String>,
|
||||
icon_intent: Option<Intent>,
|
||||
is_expanded: bool,
|
||||
is_selected: bool,
|
||||
is_selected: ConditionalClass,
|
||||
label: yew::virtual_dom::VNode,
|
||||
secondary_label: Option<yew::virtual_dom::VNode>,
|
||||
on_collapse: Option<Callback<(NodeId, MouseEvent)>>,
|
||||
|
@ -309,16 +309,15 @@ impl Component for TreeNode {
|
|||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let mut container_class = Classes::from("bp3-tree-node");
|
||||
if self.props.is_selected {
|
||||
container_class.push("bp3-tree-node-selected");
|
||||
}
|
||||
let mut content_class = Classes::from("bp3-tree-node-content");
|
||||
content_class.push(&format!("bp3-tree-node-content-{}", self.props.depth));
|
||||
let content_style = format!("padding-left: {}px;", 23 * self.props.depth);
|
||||
|
||||
html! {
|
||||
<li class=container_class>
|
||||
<div class=content_class onclick=self.handler_click.clone()>
|
||||
<li class=("bp3-tree-node", self.props.is_selected.map_some("bp3-tree-node-selected"))>
|
||||
<div
|
||||
class="bp3-tree-node-content"
|
||||
style=content_style
|
||||
onclick=self.handler_click.clone()
|
||||
>
|
||||
{
|
||||
if self.props.has_caret {
|
||||
let mut class = Classes::from("bp3-tree-node-caret");
|
||||
|
|
Loading…
Reference in a new issue