Skip to content

Commit

Permalink
Convert default values with Into
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Oct 25, 2023
1 parent 2a68dba commit ca24340
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 56 deletions.
7 changes: 2 additions & 5 deletions examples/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn TaskPreview<'a>(
content: &'a str,

/// List of tags.
#[lookbook(default = Json(vec![String::from("A")]))]
#[lookbook(default = vec![String::from("A")])]
tags: Json<Vec<String>>,
) -> Element<'a> {
render!(
Expand All @@ -29,10 +29,7 @@ pub fn TaskPreview<'a>(
}

fn app(cx: Scope) -> Element {
render!(LookBook {
home: |cx| render!("Home"),
previews: [TaskPreview]
})
render!( LookBook { home: |cx| render!("Home"), previews: [TaskPreview] } )
}

fn main() {
Expand Down
10 changes: 6 additions & 4 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub fn preview(_attrs: TokenStream, input: TokenStream) -> TokenStream {
match arg {
FnArg::Typed(typed_arg) => {
let mut docs = String::new();
let mut default = quote!(None);
let mut default = None;

for attr in typed_arg.attrs {
let path = attr.path().get_ident().unwrap().to_string();
Expand All @@ -41,7 +41,7 @@ pub fn preview(_attrs: TokenStream, input: TokenStream) -> TokenStream {
if let Meta::NameValue(meta_name_value) = meta {
if meta_name_value.path.is_ident("default") {
let value = meta_name_value.value;
default = quote!(Some(#value));
default = Some(quote!(#value));
}
}
}
Expand All @@ -51,16 +51,18 @@ pub fn preview(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let pat = typed_arg.pat;
let pat_name = pat.to_token_stream().to_string();

states.push(quote!(let #pat = use_state(cx, || <#ty>::state(#default));));
states.push(quote!(let #pat = use_state(cx, || <#ty>::state(Some(#default)));));
from_states.push(quote!(let #pat = <#ty>::from_state(cx, &**#pat);));

let ty_name = ty.to_token_stream().to_string();
let default_string = default.map(|tokens| tokens.to_string()).unwrap_or_default();

controls.push(quote!(tr {
border_bottom: "2px solid #e7e7e7",
td { padding_left: "20px", p { color: "#222", font_weight: 600, #pat_name } }
td { code { #ty_name } }
td { p { #docs } }
td { code { #default } }
td { code { #default_string } }
td { <#ty>::control(cx, #pat_name, #pat) }
}));
}
Expand Down
81 changes: 37 additions & 44 deletions src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub trait Control<'a>: Sized {
type State;

/// Create the initial state.
fn state(default: Option<Self>) -> Self::State;
fn state(default: Option<impl Into<Self>>) -> Self::State;

/// Convert the current state to `Self`.
fn from_state<T>(cx: Scope<'a, T>, state: &Self::State) -> Self;
Expand All @@ -21,45 +21,34 @@ pub trait Control<'a>: Sized {
impl<'a> Control<'a> for &'a str {
type State = String;

fn state(default: Option<Self>) -> Self::State {
default.map(String::from).unwrap_or_default()
fn state(default: Option<impl Into<Self>>) -> Self::State {
default.map(Into::into).map(String::from).unwrap_or_default()
}

fn from_state<T>(cx: Scope<'a, T>, state: &Self::State) -> Self {
cx.bump().alloc(state.clone())
}

fn control(cx: Scope<'a>, name: &'static str, state: &'a UseState<Self::State>) -> Element<'a> {
render!(Input {
value: &***state,
oninput: move |event: FormEvent| state.set(event.data.value.clone())
})
render!(
Input {
value: &***state,
oninput: move |event: FormEvent| state.set(event.data.value.clone())
}
)
}
}

impl<'a> Control<'a> for u32 {
type State = u32;

fn state(_default: Option<Self>) -> Self::State {
0
}

fn from_state<T>(_cx: Scope<'a, T>, state: &Self::State) -> Self {
*state
}
#[derive(Default)]
pub struct Json<T>(pub T);

fn control(cx: Scope<'a>, name: &'static str, state: &'a UseState<Self::State>) -> Element<'a> {
render!(dioxus_material::TextField {
label: name,
value: "{state}",
onchange: move |event: FormEvent| state.set(event.data.value.parse().unwrap())
})
impl<T> From<T> for Json<T> {
fn from(value: T) -> Self {
Self(value)
}
}

#[derive(Default)]
pub struct Json<T>(pub T);

impl<'a, T> IntoDynNode<'a> for Json<T>
where
T: Clone + Default + Deserialize<'a> + Serialize,
Expand All @@ -76,8 +65,8 @@ where
{
type State = T;

fn state(default: Option<Self>) -> Self::State {
default.unwrap_or_default().0
fn state(default: Option<impl Into<Self>>) -> Self::State {
default.map(Into::into).unwrap_or_default().0
}

fn from_state<U>(cx: Scope<'a, U>, state: &Self::State) -> Self {
Expand All @@ -87,30 +76,34 @@ where
fn control(cx: Scope<'a>, name: &'static str, state: &'a UseState<Self::State>) -> Element<'a> {
let json = serde_json::to_string(&**state).unwrap();

render!(Input {
value: "{json}",
oninput: move |event: FormEvent| {
let value = cx.bump().alloc(event.data.value.clone());
if let Ok(new_state) = serde_json::from_str(value) {
state.set(new_state);
render!(
Input {
value: "{json}",
oninput: move |event: FormEvent| {
let value = cx.bump().alloc(event.data.value.clone());
if let Ok(new_state) = serde_json::from_str(value) {
state.set(new_state);
}
}
}
})
)
}
}

#[component]
fn Input<'a>(cx: Scope<'a>, value: &'a str, oninput: EventHandler<'a, FormEvent>) -> Element<'a> {
let theme = use_theme(cx);

render!(input {
border: "2px solid #e7e7e7",
padding: "10px",
border_radius: &*theme.border_radius_small,
font_size: "{theme.label_small}px",
outline: "none",
background: "none",
value: *value,
oninput: move |event| oninput.call(event)
})
render!(
input {
border: "2px solid #e7e7e7",
padding: "10px",
border_radius: &*theme.border_radius_small,
font_size: "{theme.label_small}px",
outline: "none",
background: "none",
value: *value,
oninput: move |event| oninput.call(event)
}
)
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn Home<'a>(cx: Scope<'a>) -> Element<'a> {
let Child = HOME
.try_with(|cell| cell.borrow().clone().unwrap())
.unwrap();
render!(Child {})
render!( Child {} )
}

#[component]
Expand All @@ -63,5 +63,5 @@ fn ComponentScreen(cx: Scope, name: String) -> Element {
.try_with(|cx| cx.borrow().iter().find(|(n, _)| n == name).unwrap().clone())
.unwrap();

render!(Child {})
render!( Child {} )
}
2 changes: 1 addition & 1 deletion src/ui/wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn Wrap(cx: Scope) -> Element {
}
);

let right = render!(Outlet::<PrefixedRoute> {});
let right = render!( Outlet::<PrefixedRoute> {} );

cx.render(rsx! {
IconFont {}
Expand Down

0 comments on commit ca24340

Please sign in to comment.