wip: move examples around

This commit is contained in:
Jonathan Kelley committed 2021-11-03 15:13:50 -04:00
1 parent d298b626d3
commit 1e6e5e611b
86 files changed
+160 -216

No files matched your search

+1
View File
@@ -19,6 +19,7 @@ use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
use rand::prelude::*;
fn main() {}
criterion_group!(mbenches, create_rows);
criterion_main!(mbenches);
-34
View File
@@ -1,34 +0,0 @@
use dioxus_core::prelude::*;
use dioxus_core_macro::format_args_f;
use dioxus_core_macro::rsx;
use dioxus_html as dioxus_elements;
fn main() {
let mut dom = VirtualDom::new(EXAMPLE);
dom.rebuild();
println!("{}", dom);
}
pub static EXAMPLE: FC<()> = |(cx, _)| {
let list = (0..10).map(|_f| {
rsx! {
"{_f}"
}
});
// let list = (0..10).map(|_f| Some(Box::new(move |_f| todo!())));
cx.render(Some(LazyNodes::new(move |cx| {
cx.raw_element(
"div",
None,
[],
[],
[
cx.text(format_args!("hello")),
cx.text(format_args!("hello")),
cx.fragment_from_iter(list),
],
None,
)
})))
};
-15
View File
@@ -1,15 +0,0 @@
use dioxus_core::prelude::*;
fn main() {
let mut dom = VirtualDom::new(App);
dom.rebuild();
}
const App: FC<()> = |(cx, props)| {
let id = cx.scope_id();
// cx.submit_task(Box::pin(async move { id }));
// let (handle, contents) = use_task(cx, || async { "hello world".to_string() });
todo!()
};
-78
View File
@@ -1,78 +0,0 @@
//! Demonstrate that borrowed data is possible as a property type
//! Borrowing (rather than cloning) is very important for speed and ergonomics.
//!
//! It's slightly more advanced than just cloning, but well worth the investment.
//!
//! If you use the FC macro, we handle the lifetimes automatically, making it easy to write efficient & performant components.
fn main() {}
use dioxus_core::prelude::*;
use std::rc::Rc;
struct AppProps {
items: Vec<Rc<ListItem>>,
}
#[derive(PartialEq)]
struct ListItem {
name: String,
age: u32,
}
fn app<'a>(cx: Context<'a>, props: &AppProps) -> Element<'a> {
// let (val, set_val) = use_state_classic(cx, || 0);
todo!()
// cx.render(LazyNodes::new(move |_nodecx| {
// todo!()
// // builder::ElementBuilder::new(_nodecx, "div")
// // .iter_child({
// // cx.items.iter().map(|child| {
// // builder::virtual_child(
// // _nodecx,
// // ChildItem,
// // ChildProps {
// // item: child.clone(),
// // item_handler: set_val.clone(),
// // },
// // None,
// // &[],
// // )
// // })
// // })
// // .iter_child([builder::ElementBuilder::new(_nodecx, "div")
// // .iter_child([builder::text3(_nodecx.bump(), format_args!("{}", val))])
// // .finish()])
// // .finish()
// }))
}
// props should derive a partialeq implementation automatically, but implement ptr compare for & fields
struct ChildProps {
// Pass down complex structs
item: Rc<ListItem>,
// Even pass down handlers!
item_handler: Rc<dyn Fn(i32)>,
}
fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> Element<'a> {
todo!()
}
impl PartialEq for ChildProps {
fn eq(&self, _other: &Self) -> bool {
false
}
}
impl Properties for ChildProps {
type Builder = ();
const IS_STATIC: bool = true;
fn builder() -> Self::Builder {
()
}
unsafe fn memoize(&self, other: &Self) -> bool {
self == other
}
}
-36
View File
@@ -1,36 +0,0 @@
use dioxus_core::prelude::*;
fn main() {}
struct SomeContext {
items: Vec<String>,
}
#[allow(unused)]
static Example: FC<()> = |(cx, props)| {
todo!()
// let value = cx.use_context(|c: &SomeContext| c.items.last().unwrap());
// cx.render(LazyNodes::new(move |bump| {
// builder::ElementBuilder::new(bump, "button")
// .on("click", move |_| {
// println!("Value is {}", cx.name);
// println!("Value is {}", value.as_str());
// println!("Value is {}", *value);
// })
// .on("click", move |_| {
// println!("Value is {}", cx.name);
// })
// .finish()
// }))
// cx.render(html! {
// <div>
// <button onclick={move |_| println!("Value is {}", value)} />
// <button onclick={move |_| println!("Value is {}", value)} />
// <button onclick={move |_| println!("Value is {}", value)} />
// <div>
// <p> "Value is: {val}" </p>
// </div>
// </div>
// })
};
-1
View File
@@ -1 +0,0 @@
fn main( ) {}
@@ -1,46 +0,0 @@
use dioxus_core::prelude::*;
fn main() {}
fn app<'a>(cx: Context<'a>, props: &()) -> Element<'a> {
// let vak = use_suspense(
// cx,
// || async {},
// |c, _res| c.render(LazyNodes::new(move |f| f.text(format_args!("")))),
// );
// let d1 = cx.render(to_lazy_nodes(move |f| {
// f.raw_element(
// "div",
// None,
// [],
// [],
// [
// // f.fragment_from_iter(vak),
// f.text(format_args!("")),
// f.text(format_args!("")),
// f.text(format_args!("")),
// f.text(format_args!("")),
// ],
// None,
// )
// }));
todo!()
// cx.render(LazyNodes::new(move |f| {
// f.raw_element(
// "div",
// None,
// [],
// [],
// [
// f.text(format_args!("")),
// f.text(format_args!("")),
// f.text(format_args!("")),
// f.text(format_args!("")),
// d1.unwrap(),
// ],
// None,
// )
// }))
}
-108
View File
@@ -1,108 +0,0 @@
use bumpalo::Bump;
fn main() {}
fn build(factory: Factory) {
factory.text();
div::new(factory)
.r#class()
.r#tag()
.r#type()
.add_children()
.iter_children()
.finish();
}
/// # The `div` element
///
///
/// The <div> HTML element is the generic container for flow content. It has no effect on the content or layout until
/// styled in some way using CSS (e.g. styling is directly applied to it, or some kind of layout model like Flexbox is
/// applied to its parent element).
///
/// As a "pure" container, the <div> element does not inherently represent anything. Instead, it's used to group content
/// so it can be easily styled using the class or id attributes, marking a section of a document as being written in a
/// different language (using the lang attribute), and so on.
///
/// ## Usage
/// ```
/// rsx!{
/// div { class: "tall", id: "unique id"
/// h1 {}
/// p {}
/// }
/// }
///
/// ```
///
/// ## Specifications
/// - Content categories: Flow content, palpable content.
/// - Permitted content: Flow content.
/// - Permitted parents: Any element that accepts flow content.
#[allow(non_camel_case_types)]
struct div {}
struct h1 {}
struct h2 {}
trait BasicElement: Sized {
const TagName: &'static str;
fn get_bump(&self) -> &Bump;
fn new(factory: Factory) -> Self;
fn add_children(self) -> Self {
self
}
fn iter_children(self) -> Self {
self
}
fn finish(self) -> Self {
self
}
}
impl BasicElement for div {
const TagName: &'static str = "div";
fn get_bump(&self) -> &Bump {
todo!()
}
fn new(_factory: Factory) -> Self {
todo!()
}
}
impl div {
fn class(self) -> Self {
self
}
fn tag(self) -> Self {
self
}
fn r#type(self) -> Self {
self
}
}
#[derive(Clone, Copy)]
struct Factory<'a> {
bump: &'a bumpalo::Bump,
}
impl<'a> Factory<'a> {
fn text(&self) -> &str {
todo!()
}
fn new_el(&'a self, tag: &'static str) -> ElementBuilder<'a> {
ElementBuilder {
bump: self.bump,
tag,
}
}
}
struct ElementBuilder<'a> {
tag: &'static str,
bump: &'a bumpalo::Bump,
}
-118
View File
@@ -1,118 +0,0 @@
#![allow(non_snake_case)]
use dioxus::component::Scope;
use dioxus::events::on::MouseEvent;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
use rand::prelude::*;
use std::fmt::Display;
fn main() {
let mut dom = VirtualDom::new(App);
let g = dom.rebuild();
assert!(g.edits.len() > 1);
}
fn App((cx, props): Scope<()>) -> Element {
let mut rng = SmallRng::from_entropy();
let rows = (0..10_000_usize).map(|f| {
let label = Label::new(&mut rng);
rsx! {
Row {
row_id: f,
label: label
}
}
});
cx.render(rsx! {
table {
tbody {
{rows}
}
}
})
}
#[derive(PartialEq, Props)]
struct RowProps {
row_id: usize,
label: Label,
}
fn Row<'a>((cx, props): Scope<'a, RowProps>) -> Element<'a> {
let handler = move |evt: MouseEvent| {
let g = evt.button;
};
cx.render(rsx! {
tr {
// td { class:"col-md-1", "{props.row_id}" }
// td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
// a { class: "lbl", "{props.label}" }
// }
// td { class: "col-md-1"
// a { class: "remove", onclick: {handler}
// span { class: "glyphicon glyphicon-remove remove" aria_hidden: "true" }
// }
// }
// td { class: "col-md-6" }
}
})
}
#[derive(PartialEq)]
struct Label([&'static str; 3]);
impl Label {
fn new(rng: &mut SmallRng) -> Self {
Label([
ADJECTIVES.choose(rng).unwrap(),
COLOURS.choose(rng).unwrap(),
NOUNS.choose(rng).unwrap(),
])
}
}
impl Display for Label {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {} {}", self.0[0], self.0[1], self.0[2])
}
}
static ADJECTIVES: &[&str] = &[
"pretty",
"large",
"big",
"small",
"tall",
"short",
"long",
"handsome",
"plain",
"quaint",
"clean",
"elegant",
"easy",
"angry",
"crazy",
"helpful",
"mushy",
"odd",
"unsightly",
"adorable",
"important",
"inexpensive",
"cheap",
"expensive",
"fancy",
];
static COLOURS: &[&str] = &[
"red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black",
"orange",
];
static NOUNS: &[&str] = &[
"table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger",
"pizza", "mouse", "keyboard",
];
-148
View File
@@ -1,148 +0,0 @@
use std::marker::PhantomData;
use dioxus::component::Scope;
use dioxus::events::on::MouseEvent;
use dioxus::nodes::IntoVNode;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
fn main() {}
fn html_usage() {
let mo = move |_| {};
let r = rsx! {
div {
onclick: move |_| {}
onmouseover: {mo}
"type": "bar",
"hello world"
}
};
let items = ["bob", "bill", "jack"];
let f = items
.iter()
.filter(|f| f.starts_with('b'))
.map(|f| rsx!("hello {f}"));
// let p = rsx!(div { {f} });
}
static App2: FC<()> = |(cx, _)| cx.render(rsx!("hello world!"));
static App: FC<()> = |(cx, props)| {
let name = cx.use_state(|| 0);
cx.render(rsx!(div {
h1 {}
h2 {}
}))
};
pub trait UseState<'a, T: 'static> {
fn use_state(self, f: impl FnOnce() -> T) -> &'a T;
}
impl<'a, T: 'static> UseState<'a, T> for Context<'a> {
fn use_state(self, f: impl FnOnce() -> T) -> &'a T {
todo!()
}
}
fn App3((cx, props): Scope<()>) -> Element {
let p = rsx! {
Child {
bame: 10,
}
};
todo!()
// cx.render(rsx!(Child {
// bame: 102,
// ..ChildProps { bame: 10 }
// }))
}
#[derive(Props, PartialEq, Debug)]
struct ChildProps {
bame: i32, // children: Children<'a>,
}
fn Child<'a>((cx, props): Scope<'a, ChildProps>) -> Element<'a> {
cx.render(rsx!(div {
// {props.children}
}))
}
// Some(LazyNodes::new(|f| {
// //
// // let r = f.fragment_from_iter(&props.children);
// r
// // todo!()
// }))
// todo!()
// rsx!({ Some(p) })
// todo!()
pub struct Children<'a> {
children: VNode<'static>,
_p: PhantomData<&'a ()>,
}
impl<'a> Children<'a> {
pub fn new(children: VNode<'a>) -> Self {
Self {
children: unsafe { std::mem::transmute(children) },
_p: PhantomData,
}
}
}
static Bapp: FC<()> = |(cx, props)| {
let name = cx.use_state(|| 0);
cx.render(rsx!(
div {
div {
}
div {
}
}
))
};
static Match: FC<()> = |(cx, props)| {
//
let b: Box<dyn Fn(NodeFactory) -> VNode> = Box::new(|f| todo!());
let b = match "ag" {
"a" => {
let __b: Box<dyn FnOnce(NodeFactory) -> VNode> = Box::new(|f: NodeFactory| todo!());
__b
}
_ => {
let __b: Box<dyn FnOnce(NodeFactory) -> VNode> = Box::new(|f: NodeFactory| todo!());
__b
}
};
// let b: Box<dyn Fn(NodeFactory) -> VNode> = match "alph" {
// "beta" => Box::new(|f: NodeFactory| {
// //
// todo!()
// }),
// _ => Box::new(|f: NodeFactory| {
// //
// todo!()
// }),
// };
cx.render(rsx! {
div {
}
})
};
-259
View File
@@ -1,259 +0,0 @@
use std::borrow::BorrowMut;
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;
use dioxus::component::Scope;
use dioxus::events::on::MouseEvent;
use dioxus::nodes::{IntoVNode, VComponent, VFragment, VText};
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
fn main() {}
fn t() {
let g = rsx! {
div {
div {
}
}
};
let g = {
let ___p: Box<dyn FnOnce(NodeFactory) -> VNode> = Box::new(|__cx: NodeFactory| {
use dioxus_elements::{GlobalAttributes, SvgAttributes};
__cx.element(dioxus_elements::div, [], [], [], None)
});
// let __z = ___p as ;
// __z
};
}
// #[derive(PartialEq, Props)]
// struct OurProps {
// foo: String,
// }
// fn App<'a>((cx, props): Scope<'a, OurProps>) -> Element<'a> {
// let a = rsx! {
// div {
// "asd"
// "{props.foo}"
// }
// };
// let p = (0..10).map(|f| {
// rsx! {
// div {
// }
// }
// });
// let g = match "text" {
// "a" => {
// rsx!("asd")
// }
// _ => {
// rsx!("asd")
// }
// };
// let items = ["bob", "bill", "jack"];
// let f = items
// .iter()
// .filter(|f| f.starts_with('b'))
// .map(|f| rsx!("hello {f}"));
// // use dioxus_hooks;
// // let g = use_state(|| "hello".to_string());
// let s: &'a mut String = cx.use_hook(|_| String::new(), |f| f, |_| {});
// /*
// the final closure is allowed to borrow anything provided it
// */
// // cx.render({
// // let p: Option<Box<dyn FnOnce(_) -> _>> = Some(Box::new(move |__cx: NodeFactory| {
// // use dioxus_elements::{GlobalAttributes, SvgAttributes};
// // let props = Child2Props { foo: s };
// // let ch: VNode = __cx.component(Child2, props, None, []);
// // __cx.element(
// // dioxus_elements::div,
// // [],
// // [],
// // [ch],
// // // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])],
// // None,
// // )
// // }));
// // p
// // // let ___p: Box<dyn FnOnce(NodeFactory) -> VNode> = Box::new(move |__cx| {
// // // use dioxus_elements::{GlobalAttributes, SvgAttributes};
// // // let props = Child2Props { foo: s };
// // // let ch: VNode = __cx.component(Child2, props, None, []);
// // // __cx.element(
// // // dioxus_elements::div,
// // // [],
// // // [],
// // // [ch],
// // // // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])],
// // // None,
// // // )
// // // });
// // // Some(___p)
// // })
// let a = annotate_lazy(move |f| {
// //
// todo!()
// });
// let b = annotate_lazy(move |f| {
// //
// f.text(format_args!("{}", props.foo))
// });
// let c = annotate_lazy(move |f| {
// //
// f.component(
// Child,
// OurProps {
// //
// foo: "hello".to_string(),
// },
// None,
// [],
// )
// });
// let st: &'a String = cx.use_hook(|_| "hello".to_string(), |f| f, |_| {});
// let d = annotate_lazy(move |f| {
// //
// f.component(
// Child2,
// Child2Props {
// //
// foo: st,
// },
// None,
// [],
// )
// });
// let e = match "asd" {
// b => {
// //
// annotate_lazy(move |f| {
// //
// f.text(format_args!("{}", props.foo))
// })
// }
// a => {
// //
// annotate_lazy(move |f| {
// //
// f.text(format_args!("{}", props.foo))
// })
// }
// };
// cx.render(annotate_lazy(move |f| {
// //
// f.raw_element(
// "div",
// None,
// [],
// [],
// [
// //
// f.fragment_from_iter(a),
// f.fragment_from_iter(b),
// f.fragment_from_iter(c),
// f.fragment_from_iter(e),
// ],
// None,
// )
// // todo!()
// }))
// // cx.render(rsx! {
// // div {
// // div {
// // {a}
// // // {p}
// // // {g}
// // // {f}
// // }
// // // div {
// // // "asd"
// // // div {
// // // "asd"
// // // }
// // // }
// // // Child {
// // // foo: "asd".to_string(),
// // // }
// // Child2 {
// // foo: s,
// // }
// // }
// // })
// }
// fn Child((cx, props): Scope<OurProps>) -> Element {
// cx.render(rsx! {
// div {
// div {}
// }
// })
// }
#[derive(Props)]
struct Child2Props<'a> {
foo: &'a String,
}
fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
let node = cx
.render(rsx! {
div {
}
})
.unwrap();
cx.render(rsx! {
div {
ChildrenComp {
div {}
}
}
})
}
#[derive(Props)]
struct ChildrenTest<'a> {
children: ScopeChildren<'a>,
}
fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> {
cx.render(rsx! {
div {
div {
{&props.children}
}
}
})
}
fn ChildrenMemo((cx, props): Scope<()>) -> Element {
todo!()
}
-1
View File
@@ -1 +0,0 @@
fn main() {}
-17
View File
@@ -1,17 +0,0 @@
use std::time::Duration;
use dioxus_core::{lazynodes::LazyNodes, prelude::*};
// #[async_std::main]
fn main() {
static App: FC<()> =
|(cx, props)| cx.render(Some(LazyNodes::new(move |f| f.text(format_args!("hello")))));
let mut dom = VirtualDom::new(App);
dom.rebuild();
// let deadline = async_std::task::sleep(Duration::from_millis(50));
// let _fut = dom.run_with_deadline(|| deadline.);
}
+30 -9
View File
@@ -5,7 +5,10 @@
//! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
//! that ensures compile-time required and optional fields on cx.
use crate::innerlude::{Context, Element, VNode};
use crate::{
innerlude::{Context, Element, VAnchor, VFragment, VNode},
LazyNodes, ScopeChildren,
};
/// A component is a wrapper around a Context and some Props that share a lifetime
///
///
@@ -41,23 +44,39 @@ use crate::innerlude::{Context, Element, VNode};
pub type Scope<'a, T> = (Context<'a>, &'a T);
pub struct FragmentProps<'a> {
childen: &'a VNode<'a>,
children: ScopeChildren<'a>,
}
pub struct FragmentPropsBuilder<'a> {
childen: Option<&'a VNode<'a>>,
pub struct FragmentBuilder<'a, const BUILT: bool> {
children: Option<ScopeChildren<'a>>,
}
impl<'a> FragmentBuilder<'a, false> {
pub fn children(mut self, children: ScopeChildren<'a>) -> FragmentBuilder<'a, true> {
FragmentBuilder {
children: Some(children),
}
}
}
impl<'a, const A: bool> FragmentBuilder<'a, A> {
pub fn build(self) -> FragmentProps<'a> {
FragmentProps {
children: self.children.unwrap_or_default(),
}
}
}
impl<'a> Properties for FragmentProps<'a> {
type Builder = FragmentPropsBuilder<'a>;
type Builder = FragmentBuilder<'a, false>;
const IS_STATIC: bool = false;
fn builder() -> Self::Builder {
todo!()
FragmentBuilder { children: None }
}
unsafe fn memoize(&self, other: &Self) -> bool {
todo!()
false
}
}
@@ -83,8 +102,10 @@ impl<'a> Properties for FragmentProps<'a> {
/// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
///
#[allow(non_upper_case_globals, non_snake_case)]
pub fn Fragment<'a>((_, props): Scope<'a, FragmentProps<'a>>) -> Element<'a> {
Some(props.childen.decouple())
pub fn Fragment<'a>((cx, props): Scope<'a, FragmentProps<'a>>) -> Element<'a> {
cx.render(Some(LazyNodes::new(|f| {
f.fragment_from_iter(&props.children)
})))
}
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
+5 -3
View File
@@ -11,7 +11,7 @@
//! The logic for this was borrowed from https://docs.rs/stack_dst/0.6.1/stack_dst/. Unfortunately, this crate does not
//! support non-static closures, so we've implemented the core logic of `ValueA` in this module.
use crate::innerlude::{NodeFactory, VNode};
use crate::prelude::{NodeFactory, VNode};
use std::mem;
/// A concrete type provider for closures that build VNode structures.
@@ -27,7 +27,7 @@ pub struct LazyNodes<'a, 'b> {
inner: StackNodeStorage<'a, 'b>,
}
type StackHeapSize = [usize; 12];
type StackHeapSize = [usize; 0];
enum StackNodeStorage<'a, 'b> {
Stack(LazyStack),
@@ -77,7 +77,7 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
}
} else {
log::debug!("lazy nodes fits on stack!");
let mut buf: StackHeapSize = [0; 12];
let mut buf: StackHeapSize = StackHeapSize::default();
assert!(info.len() + round_to_words(size) <= buf.as_ref().len());
@@ -97,6 +97,8 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
*dataptr.add(i) = *src_ptr.add(i);
}
std::mem::forget(val);
Self {
inner: StackNodeStorage::Stack(LazyStack { _align: [], buf }),
}
+3 -3
View File
@@ -65,9 +65,9 @@ pub(crate) mod innerlude {
}
pub use crate::innerlude::{
Context, DioxusElement, DomEdit, Element, ElementId, EventPriority, MountType, Mutations,
NodeFactory, Properties, SchedulerMsg, ScopeChildren, ScopeId, SuspendedContext, TaskHandle,
TestDom, ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC,
Context, DioxusElement, DomEdit, Element, ElementId, EventPriority, LazyNodes, MountType,
Mutations, NodeFactory, Properties, SchedulerMsg, ScopeChildren, ScopeId, SuspendedContext,
TaskHandle, TestDom, ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC,
};
pub mod prelude {
+4 -1
View File
@@ -765,6 +765,9 @@ impl<'a> ScopeChildren<'a> {
pub fn new(root: VNode<'a>) -> Self {
Self { root: Some(root) }
}
pub fn new_option(root: Option<VNode<'a>>) -> Self {
Self { root }
}
}
impl IntoIterator for &ScopeChildren<'_> {
@@ -773,7 +776,7 @@ impl IntoIterator for &ScopeChildren<'_> {
type IntoIter = std::iter::Once<Self>;
fn into_iter(self) -> Self::IntoIter {
todo!()
std::iter::once(self)
}
}
+1 -20
View File
@@ -303,27 +303,8 @@ fn anchors() {
#[test]
fn suspended() {
static App: FC<()> = |(cx, props)| {
let val = use_suspense(
cx,
|| async {
//
},
|cx, p| todo!(),
// |cx, p| rsx! { "hi "},
);
let val = use_suspense(cx, || async {}, |cx, p| todo!());
// let prom = use_task(fetch());
// Value {
// a: value.await,
// b: value.await,
// f: a.await
// div {
// div {
// hidden: should_hide.await,
// }
// }
// }
cx.render(rsx! { {val} })
};
-3
View File
@@ -34,6 +34,3 @@ tokio_runtime = ["tokio"]
dioxus-html = { path = "../html" }
dioxus-hooks = { path = "../hooks" }
simple_logger = "1.13.0"
[build-dependencies]
-5
View File
@@ -1,5 +0,0 @@
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
fn main() {}
-109
View File
@@ -1,109 +0,0 @@
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
fn main() {
dioxus_desktop::launch(App, |c| c)
}
enum Scene {
ClientsList,
NewClientForm,
Settings,
}
#[derive(Clone, Debug, Default)]
pub struct Client {
pub first_name: String,
pub last_name: String,
pub description: String,
}
static App: FC<()> = |(cx, _)| {
let mut scene = use_state(cx, || Scene::ClientsList);
let clients = use_ref(cx, || vec![] as Vec<Client>);
let mut firstname = use_state(cx, String::new);
let mut lastname = use_state(cx, String::new);
let mut description = use_state(cx, String::new);
let scene = match scene.get() {
Scene::ClientsList => {
rsx!(cx, div { class: "crm"
h2 { "List of clients" margin_bottom: "10px" }
div { class: "clients" margin_left: "10px"
{clients.read().iter().map(|client| rsx!(
div { class: "client" style: "margin-bottom: 50px"
p { "First Name: {client.first_name}" }
p { "Last Name: {client.last_name}" }
p {"Description: {client.description}"}
})
)}
}
button { class: "pure-button pure-button-primary" onclick: move |_| scene.set(Scene::NewClientForm), "Add New" }
button { class: "pure-button" onclick: move |_| scene.set(Scene::Settings), "Settings" }
})
}
Scene::NewClientForm => {
let add_new = move |_| {
clients.write().push(Client {
description: (*description).clone(),
first_name: (*firstname).clone(),
last_name: (*lastname).clone(),
});
description.set(String::new());
firstname.set(String::new());
lastname.set(String::new());
};
rsx!(cx, div { class: "crm"
h2 {"Add new client" margin_bottom: "10px" }
form { class: "pure-form"
input { class: "new-client firstname" placeholder: "First name" value: "{firstname}"
oninput: move |evt| firstname.set(evt.value)
}
input { class: "new-client lastname" placeholder: "Last name" value: "{lastname}"
oninput: move |evt| lastname.set(evt.value)
}
textarea { class: "new-client description" placeholder: "Description" value: "{description}"
oninput: move |evt| description.set(evt.value)
}
}
button { class: "pure-button pure-button-primary", onclick: {add_new}, "Add New" }
button { class: "pure-button", onclick: move |_| scene.set(Scene::ClientsList), "Go Back" }
})
}
Scene::Settings => {
rsx!(cx, div {
h2 { "Settings" margin_bottom: "10px" }
button {
background: "rgb(202, 60, 60)"
class: "pure-button pure-button-primary"
onclick: move |_| {
clients.write().clear();
scene.set(Scene::ClientsList);
},
"Remove all clients"
}
button {
class: "pure-button pure-button-primary"
onclick: move |_| scene.set(Scene::ClientsList),
"Go Back"
}
})
}
};
rsx!(cx, body {
link {
rel: "stylesheet"
href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css"
integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5"
crossorigin: "anonymous"
}
margin_left: "35%"
h1 {"Dioxus CRM Example"}
{scene}
})
};
-18
View File
@@ -1,18 +0,0 @@
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
fn main() {
dioxus_desktop::launch(App, |c| c);
}
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div {
"hello world!"
}
{(0..10).map(|f| rsx!( div {"abc {f}"}))}
))
};
-8
View File
@@ -1,8 +0,0 @@
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
fn main() {}
-1
View File
@@ -1 +0,0 @@
fn main() {}
-379
View File
@@ -1,379 +0,0 @@
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
}
:focus {
outline: 0;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
.toggle-all {
text-align: center;
border: none;
/* Mobile Safari */
opacity: 0;
position: absolute;
}
.toggle-all+label {
width: 60px;
height: 34px;
font-size: 0;
position: absolute;
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.toggle-all+label:before {
content: '❯';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked+label:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 12px 16px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none;
/* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle {
opacity: 0;
}
.todo-list li .toggle+label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
}
.todo-list li .toggle:checked+label {
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}
.todo-list li label {
word-break: break-all;
padding: 15px 15px 15px 60px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}
-171
View File
@@ -1,171 +0,0 @@
#![allow(non_upper_case_globals, non_snake_case)]
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
use simple_logger::SimpleLogger;
use std::collections::HashMap;
fn main() {
if cfg!(debug_assertions) {
SimpleLogger::new().init().unwrap();
}
dioxus_desktop::launch(App, |c| c)
}
#[derive(PartialEq)]
pub enum FilterState {
All,
Active,
Completed,
}
#[derive(Debug, PartialEq)]
pub struct TodoItem {
pub id: u32,
pub checked: bool,
pub contents: String,
}
pub type Todos = HashMap<u32, TodoItem>;
pub static App: FC<()> = |(cx, _)| {
// Share our TodoList to the todos themselves
use_provide_state(cx, || Todos::new());
// Save state for the draft, filter
let mut draft = use_state(cx, || "".to_string());
let mut filter = use_state(cx, || FilterState::All);
let mut todo_id = use_state(cx, || 0);
// Consume the todos
let todos = use_shared_state::<Todos>(cx)?;
// Filter the todos based on the filter state
let mut filtered_todos = todos
.read()
.iter()
.filter(|(_, item)| match *filter {
FilterState::All => true,
FilterState::Active => !item.checked,
FilterState::Completed => item.checked,
})
.map(|f| *f.0)
.collect::<Vec<_>>();
filtered_todos.sort_unstable();
// Define the actions to manage the todolist
let mut submit_todo = move || {
if !draft.is_empty() {
todos.write().insert(
*todo_id,
TodoItem {
id: *todo_id,
checked: false,
contents: draft.get().clone(),
},
);
todo_id += 1;
draft.set("".to_string());
}
};
let clear_completed = move || {
todos.write().retain(|_, todo| todo.checked == false);
};
// Some assists in actually rendering the content
let show_clear_completed = todos.read().values().any(|todo| todo.checked);
let items_left = filtered_todos.len();
let item_text = match items_left {
1 => "item",
_ => "items",
};
cx.render(rsx!{
section { class: "todoapp"
style { {[include_str!("./todomvc.css")]} }
div {
header { class: "header"
h1 {"todos"}
input {
class: "new-todo"
placeholder: "What needs to be done?"
value: "{draft}"
autofocus: "true"
oninput: move |evt| draft.set(evt.value.clone())
onkeydown: move |evt| {
if evt.key == "Enter" {
submit_todo();
}
}
}
}
ul { class: "todo-list"
{filtered_todos.iter().map(|id| rsx!(TodoEntry { key: "{id}", id: *id }))}
}
{(!todos.read().is_empty()).then(|| rsx!(
footer { class: "footer"
span { class: "todo-count" strong {"{items_left} "} span {"{item_text} left"} }
ul { class: "filters"
li { class: "All", a { onclick: move |_| filter.set(FilterState::All), "All" }}
li { class: "Active", a { onclick: move |_| filter.set(FilterState::Active), "Active" }}
li { class: "Completed", a { onclick: move |_| filter.set(FilterState::Completed), "Completed" }}
}
{(show_clear_completed).then(|| rsx!(
button { class: "clear-completed", onclick: move |_| clear_completed(),
"Clear completed"
}
))}
}
))}
}
}
footer { class: "info"
p {"Double-click to edit a todo"}
p { "Created by ", a { "jkelleyrtp", href: "http://github.com/jkelleyrtp/" }}
p { "Part of ", a { "TodoMVC", href: "http://todomvc.com" }}
}
})
};
#[derive(PartialEq, Props)]
pub struct TodoEntryProps {
id: u32,
}
pub fn TodoEntry((cx, props): Scope<TodoEntryProps>) -> Element {
let todos = use_shared_state::<Todos>(cx)?;
let _todos = todos.read();
let todo = _todos.get(&props.id)?;
let is_editing = use_state(cx, || false);
let completed = if todo.checked { "completed" } else { "" };
cx.render(rsx!{
li { class: "{completed}"
div { class: "view"
input { class: "toggle" r#type: "checkbox" id: "cbg-{todo.id}" checked: "{todo.checked}"
onchange: move |evt| {
todos.write().get_mut(&props.id).map(|todo| todo.checked = evt.value.parse().unwrap());
}
}
label { r#for: "cbg-{todo.id}" pointer_events: "none"
"{todo.contents}"
}
{is_editing.then(|| rsx!{
input { value: "{todo.contents}"
oninput: move |evt| {
todos.write().get_mut(&props.id).map(|todo| todo.contents = evt.value.clone());
},
}
})}
}
}
})
}
+7 -3
View File
@@ -1,6 +1,7 @@
use std::cell::RefCell;
use dioxus::prelude::Scope;
use dioxus::ScopeChildren;
use dioxus_core as dioxus;
use dioxus_core::{Context, Element, LazyNodes, NodeFactory, Properties};
use dioxus_core_macro::Props;
@@ -42,6 +43,8 @@ pub struct WebviewWindowProps<'a> {
/// focuse me
onfocused: &'a dyn FnMut(()),
children: ScopeChildren<'a>,
}
/// A handle to a
@@ -70,9 +73,10 @@ pub fn WebviewWindow<'a>((cx, props): Scope<'a, WebviewWindowProps>) -> Element<
);
// render the children directly
cx.render(LazyNodes::new(move |f: NodeFactory| {
f.fragment_from_iter(cx.children())
}))
todo!()
// cx.render(LazyNodes::new(move |f: NodeFactory| {
// f.fragment_from_iter(cx.children())
// }))
}
pub struct WindowHandle {}
+2
View File
@@ -13,6 +13,8 @@
position: fixed;
}
</style> -->
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css">
<script src="https://cdn.plot.ly/plotly-1.52.3.min.js"></script>
</head>
+41 -6
View File
@@ -20,9 +20,9 @@ use serde::{Deserialize, Serialize};
pub use wry;
use wry::application::accelerator::{Accelerator, SysMods};
use wry::application::event::{Event, StartCause, WindowEvent};
use wry::application::event::{ElementState, Event, StartCause, WindowEvent};
use wry::application::event_loop::{self, ControlFlow, EventLoop};
use wry::application::keyboard::KeyCode;
use wry::application::keyboard::{Key, KeyCode, ModifiersState};
use wry::application::menu::{MenuBar, MenuItem, MenuItemAttributes};
use wry::application::window::Fullscreen;
use wry::webview::{WebView, WebViewBuilder};
@@ -94,6 +94,11 @@ pub fn run<T: 'static + Send + Sync>(
let props_shared = Cell::new(Some(props));
// create local modifier state
let mut modifiers = ModifiersState::default();
let quit_hotkey = Accelerator::new(SysMods::Cmd, KeyCode::KeyQ);
event_loop.run(move |event, event_loop, control_flow| {
*control_flow = ControlFlow::Wait;
@@ -112,10 +117,8 @@ pub fn run<T: 'static + Send + Sync>(
first_menu.add_native_item(MenuItem::HideOthers);
first_menu.add_native_item(MenuItem::ShowAll);
let quit_item = first_menu.add_item(
MenuItemAttributes::new("Quit")
.with_accelerators(&Accelerator::new(SysMods::Cmd, KeyCode::KeyQ)),
);
first_menu.add_native_item(MenuItem::Quit);
first_menu.add_native_item(MenuItem::CloseWindow);
// create second menu
let mut second_menu = MenuBar::new();
@@ -129,6 +132,7 @@ pub fn run<T: 'static + Send + Sync>(
menu_bar_menu.add_submenu("Second menu", true, second_menu);
let window = WindowBuilder::new()
.with_maximized(true)
.with_menu(menu_bar_menu)
.with_title("Dioxus App")
.build(event_loop)
@@ -197,6 +201,37 @@ pub fn run<T: 'static + Send + Sync>(
event, window_id, ..
} => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Destroyed { .. } => {
webviews.remove(&window_id);
if webviews.is_empty() {
*control_flow = ControlFlow::Exit;
}
}
// catch only pressed event
WindowEvent::KeyboardInput { event, .. } => {
log::debug!("keybowrd input");
if quit_hotkey.matches(&modifiers, &event.physical_key) {
log::debug!("quitting");
webviews.remove(&window_id);
if webviews.is_empty() {
*control_flow = ControlFlow::Exit;
}
}
// println!(
// "KeyEvent: `Shift` + `1` | logical_key: {:?}",
// &event.logical_key
// );
// we can match manually without `Accelerator`
// else if event.key_without_modifiers() == Key::Character("1")
// && modifiers.is_empty()
// {
// println!("KeyEvent: `1`");
// }
}
WindowEvent::Resized(_) | WindowEvent::Moved(_) => {
if let Some(view) = webviews.get_mut(&window_id) {
let _ = view.resize();
-52
View File
@@ -1,52 +0,0 @@
fn main() {}
// struct CompState {
// tasks: Vec<()>,
// }
// enum Actions {
// Add,
// MoveUp,
// MoveDown,
// Remvoe,
// }
// static Component: FC<()> = |(cx, props)|{
// let (tasks, dispatch) = use_reducer(
// cx,
// || CompState { tasks: Vec::new() },
// |state, action: Actions| match action {
// Actions::Add => state,
// Actions::MoveUp => state,
// Actions::MoveDown => state,
// Actions::Remvoe => state,
// },
// );
// let tasklist = { (0..10).map(|f| html! { <li></li> }) }.collect::<Vec<_>>();
// html! {
// <div>
// <div>
// <h1>"Tasks: "</h1>
// <ul>
// {tasklist}
// </ul>
// </div>
// <div>
// <button onclick=|_| dispatch(Action::Add)>{"Add"}</button>
// <button onclick=|_| dispatch(Action::MoveUp)>{"MoveUp"}</button>
// <button onclick=|_| dispatch(Action::MoveDown)>{"MoveDown"}</button>
// <button onclick=|_| dispatch(Action::Remvoe)>{"Remvoe"}</button>
// </div>
// </div>
// }
// };
// fn use_reducer<Props, State, Action>(
// cx: &mut Context<Props>,
// init: fn() -> State,
// reducer: fn(State, Action) -> State,
// ) -> (State, impl Fn(Action)) {
// let ii = init();
// (ii, |_| {})
// }
-1
View File
@@ -1 +0,0 @@
fn main() {}
+1 -1
View File
@@ -126,7 +126,7 @@ impl<'a, T: 'static> UseSharedState<'a, T> {
///
///
/// TODO: We prevent unncessary notifications only in the hook, but we should figure out some more global lock
pub fn write(&mut self) -> RefMut<'_, T> {
pub fn write(&self) -> RefMut<'_, T> {
self.cx.needs_update();
self.notify_consumers();
self.value.borrow_mut()
+1 -1
View File
@@ -102,7 +102,7 @@ impl<'a, T: 'static> UseState<'a, T> {
}
}
pub fn set(&mut self, new_val: T) {
pub fn set(&self, new_val: T) {
*self.inner.wip.borrow_mut() = Some(new_val);
self.needs_update();
}
-28
View File
@@ -1,28 +0,0 @@
use dioxus::prelude::*;
fn main() {}
enum Routes {
Home,
Blog,
}
static App: FC<()> = |(cx, props)| {
let route = use_router::<Routes>(cx);
let content = match route {
Routes::Home => rsx!(Home {}),
Routes::Blog => rsx!(Blog {}),
};
cx.render(rsx! {
{content}
})
};
fn use_router<P>(cx: Context) -> &P {
todo!()
}
static Home: FC<()> = |(cx, props)| todo!();
static Blog: FC<()> = |(cx, props)| todo!();
-88
View File
@@ -1,88 +0,0 @@
use dioxus::prelude::*;
use dioxus_router::{use_router, Link, Routable};
fn main() {
dbg!(App as *const fn());
}
#[derive(PartialEq, Debug, Clone)]
pub enum Route {
// #[at("/")]
Home,
// #[at("/:id")]
AllUsers { page: u32 },
// #[at("/:id")]
User { id: u32 },
// #[at("/:id")]
BlogList { page: u32 },
// #[at("/:id")]
BlogPost { post_id: u32 },
// #[at("/404")]
// #[not_found]
NotFound,
}
static App: FC<()> = |(cx, props)| {
let route = use_router(cx, Route::parse)?;
cx.render(rsx! {
nav {
Link { to: Route::Home, "Go home!" }
Link { to: Route::AllUsers { page: 0 }, "List all users" }
Link { to: Route::BlogList { page: 0 }, "Blog posts" }
}
{match route {
Route::Home => rsx!("Home"),
Route::AllUsers { page } => rsx!("All users - page {page}"),
Route::User { id } => rsx!("User - id: {id}"),
Route::BlogList { page } => rsx!("Blog posts - page {page}"),
Route::BlogPost { post_id } => rsx!("Blog post - post {post_id}"),
Route::NotFound => rsx!("Not found"),
}}
footer {}
})
};
impl Route {
// Generate the appropriate route from the "tail" end of the URL
fn parse(url: &str) -> Self {
use Route::*;
match url {
"/" => Home,
"/users" => AllUsers { page: 1 },
"/users/:page" => AllUsers { page: 1 },
"/users/:page/:id" => User { id: 1 },
"/blog" => BlogList { page: 1 },
"/blog/:page" => BlogList { page: 1 },
"/blog/:page/:id" => BlogPost { post_id: 1 },
_ => NotFound,
}
}
}
impl Routable for Route {
fn from_path(path: &str, params: &std::collections::HashMap<&str, &str>) -> Option<Self> {
todo!()
}
fn to_path(&self) -> String {
todo!()
}
fn routes() -> Vec<&'static str> {
todo!()
}
fn not_found_route() -> Option<Self> {
todo!()
}
fn recognize(pathname: &str) -> Option<Self> {
todo!()
}
}
-25
View File
@@ -1,25 +0,0 @@
use dioxus::virtual_dom::VirtualDom;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
fn main() {
let mut dom = VirtualDom::new(App);
dom.rebuild();
println!(
"{}",
dioxus_ssr::render_vdom(&dom, |c| c.newline(true).indent(true))
)
}
pub static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div {
class: "overflow-hidden"
ul {
{(0..10).map(|i| rsx!{ li { class: "flex flex-col", "entry: {i}"}})}
}
"hello world!"
}
))
};
-10
View File
@@ -1,10 +0,0 @@
//! Example: realworld usage of hydration
//!
//!
use dioxus::virtual_dom::VirtualDom;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_hooks::use_state;
use dioxus_html as dioxus_elements;
fn main() {}
-298
View File
@@ -1,298 +0,0 @@
<!-- a js-only interpreter for the dioxus patch stream :) -->
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<meta charset="UTF-8" />
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
</head>
<body>
<div>hello dioxus</div>
</body>
<script>
class Interpreter {
constructor(root) {
this.stack = [root];
}
top() {
return this.stack[this.stack.length - 1];
}
pop() {
return this.stack.pop();
}
}
class OPTABLE {
// 0
SetText(edit, interp) {
interp.top(interp.stack).textContent = edit.text;
}
// 1
RemoveSelfAndNextSiblings(edit) {
const node = interp.pop();
let sibling = node.nextSibling;
while (sibling) {
const temp = sibling.nextSibling;
sibling.remove();
sibling = temp;
}
node.remove();
}
// 2
ReplaceWith(edit, interp) {
const newNode = interp.pop();
const oldNode = interp.pop();
oldNode.replaceWith(newNode);
interp.stack.push(newNode);
}
// 3
SetAttribute(edit, interp) {
const name = edit.name;
const value = edit.value;
const node = interp.top(interp.stack);
node.setAttribute(name, value);
// Some attributes are "volatile" and don't work through `setAttribute`.
if ((name === "value", interp)) {
node.value = value;
}
if ((name === "checked", interp)) {
node.checked = true;
}
if ((name === "selected", interp)) {
node.selected = true;
}
}
// 4
RemoveAttribute(edit, interp) {
const name = edit.name;
const node = interp.top(interp.stack);
node.removeAttribute(name);
// Some attributes are "volatile" and don't work through `removeAttribute`.
if ((name === "value", interp)) {
node.value = null;
}
if ((name === "checked", interp)) {
node.checked = false;
}
if ((name === "selected", interp)) {
node.selected = false;
}
}
// 5
PushReverseChild(edit, interp) {
const n = edit.n;
const parent = interp.top(interp.stack);
const children = parent.childNodes;
const child = children[children.length - n - 1];
interp.stack.push(child);
}
// 6
PopPushChild(edit, interp) {
const n = edit.n;
interp.pop();
const parent = interp.top(interp.stack);
const children = parent.childNodes;
const child = children[n];
interp.stack.push(child);
}
// 7
Pop(edit, interp) {
interp.pop();
}
// 8
AppendChild(edit, interp) {
console.log(interp.stack);
const child = interp.pop();
console.log(interp.stack);
interp.top().appendChild(child);
}
// 9
CreateTextNode(edit, interp) {
// interp.stack.push(document.createTextNode("asd"));
console.log(interp.stack);
interp.stack.push(document.createTextNode(edit.text));
console.log(interp.stack);
}
// 10
CreateElement(edit, interp) {
const tagName = edit.tag_name;
interp.stack.push(document.createElement(tagName));
}
// 11
NewEventListener(edit, interp) {
// todo!
const eventId = mem32[i++];
const eventType = interp.getCachedString(eventId);
const a = mem32[i++];
const b = mem32[i++];
const el = interp.top(interp.stack);
el.addEventListener(eventType, interp.eventHandler);
el[`dodrio-a-${eventType}`] = a;
el[`dodrio-b-${eventType}`] = b;
}
// 12
UpdateEventListener(edit, interp) {
// todo!
const eventId = mem32[i++];
const eventType = interp.getCachedString(eventId);
const el = interp.top(interp.stack);
el[`dodrio-a-${eventType}`] = mem32[i++];
el[`dodrio-b-${eventType}`] = mem32[i++];
}
// 13
RemoveEventListener(edit, interp) {
// todo!
const eventId = mem32[i++];
const eventType = interp.getCachedString(eventId);
const el = interp.top(interp.stack);
el.removeEventListener(eventType, interp.eventHandler);
}
// 14
AddCachedString(edit, interp) {
// todo!
const pointer = mem32[i++];
const length = mem32[i++];
const id = mem32[i++];
const str = string(mem8, pointer, length);
interp.addCachedString(str, id);
}
// 15
DropCachedString(edit, interp) {
// todo!
const id = mem32[i++];
interp.dropCachedString(id);
}
// 16
CreateElementNS(edit, interp) {
// const tagNameId = mem32[i++];
// const tagName = interp.getCachedString(tagNameId);
// const nsId = mem32[i++];
// const ns = interp.getCachedString(nsId);
interp.stack.push(document.createElementNS(edit.ns, edit.tag_name));
}
// 17
SaveChildrenToTemporaries(edit, interp) {
// let temp = mem32[i++];
// const start = mem32[i++];
// const end = mem32[i++];
let temp = edit.temp;
const start = edit.start;
const end = edit.end;
const parent = interp.top(interp.stack);
const children = parent.childNodes;
for (let i = start; i < end; i++, interp) {
interp.temporaries[temp++] = children[i];
}
}
// 18
PushChild(edit, interp) {
const parent = interp.top(interp.stack);
// const n = mem32[i++];
const n = edit.n;
const child = parent.childNodes[n];
interp.stack.push(child);
}
// 19
PushTemporary(edit, interp) {
// const temp = mem32[i++];
const temp = edit.temp;
interp.stack.push(interp.temporaries[temp]);
}
// 20
InsertBefore(edit, interp) {
const before = interp.pop();
const after = interp.pop();
after.parentNode.insertBefore(before, after);
interp.stack.push(before);
}
// 21
PopPushReverseChild(edit, interp) {
// const n = mem32[i++];
const n = edit.n;
interp.pop();
const parent = interp.top(interp.stack);
const children = parent.childNodes;
const child = children[children.length - n - 1];
interp.stack.push(child);
}
// 22
RemoveChild(edit, interp) {
// const n = mem32[i++];
const n = edit.n;
const parent = interp.top(interp.stack);
const child = parent.childNodes[n];
child.remove();
}
// 23
SetClass(edit, interp) {
// const classId = mem32[i++];
const className = edit.class_name;
interp.top(interp.stack).className = className;
}
// 24
SaveTemplate(edit, interp) {
const id = mem32[i++];
const template = interp.top(interp.stack);
interp.saveTemplate(id, template.cloneNode(true));
}
// 25
PushTemplate(edit, interp) {
const id = mem32[i++];
const template = interp.getTemplate(id);
interp.stack.push(template.cloneNode(true));
}
NewListener(edit, interp) {}
}
const op_table = new OPTABLE();
const interpreter = new Interpreter(window.document.body);
function EditListReceived(rawEditList) {
let editList = JSON.parse(rawEditList);
editList.forEach(function (edit, index) {
op_table[edit.type](edit, interpreter);
});
}
let socket = new WebSocket("ws://127.0.0.1:8080/session/itsworkinggg");
socket.onmessage = function(event) {
console.log(event.data);
EditListReceived(event.data);
}
// external.invoke("initiate");
</script>
</html>
-61
View File
@@ -1,61 +0,0 @@
//!
//!
//!
use dioxus::virtual_dom::VirtualDom;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::use_state;
use dioxus_html as dioxus_elements;
fn main() {}
// use tide::{Request, Response};
// #[async_std::main]
// async fn main() -> Result<(), std::io::Error> {
// let mut app = tide::new();
// app.at("/:name").get(|req: Request<()>| async move {
// let initial_name: String = req
// .param("name")
// .map(|f| f.parse().unwrap_or("...?".to_string()))
// .unwrap_or("...?".to_string());
// let mut dom = VirtualDom::new_with_props(Example, ExampleProps { initial_name });
// dom.rebuild();
// Ok(Response::builder(200)
// .body(format!("{}", dioxus_ssr::render_vdom(&dom, |c| c)))
// .content_type(tide::http::mime::HTML)
// .build())
// });
// println!("Server available at [http://127.0.0.1:8080/bill]");
// app.listen("127.0.0.1:8080").await?;
// Ok(())
// }
// #[derive(PartialEq, Props)]
// struct ExampleProps {
// initial_name: String,
// }
// static Example: FC<ExampleProps> = |(cx, props)| {
// let dispaly_name = use_state(cx, move || props.initial_name.clone());
// cx.render(rsx! {
// div { class: "py-12 px-4 text-center w-full max-w-2xl mx-auto",
// span { class: "text-sm font-semibold"
// "Dioxus Example: Jack and Jill"
// }
// h2 { class: "text-5xl mt-2 mb-6 leading-tight font-semibold font-heading"
// "Hello, {dispaly_name}"
// }
// ul {
// {(0..10).map(|f| rsx!( li {"Element {f}"} ))}
// }
// }
// })
// };
-147
View File
@@ -1,147 +0,0 @@
use dioxus::virtual_dom::VirtualDom;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::use_state;
use dioxus_html as dioxus_elements;
use dioxus_html::{GlobalAttributes, SvgAttributes};
use dioxus_ssr::TextRenderer;
fn main() {
use std::fs::File;
use std::io::Write;
let mut file = File::create("example.html").unwrap();
let mut dom = VirtualDom::new(App);
dom.rebuild();
file.write_fmt(format_args!(
"{}",
TextRenderer::from_vdom(&dom, Default::default())
))
.unwrap();
}
pub static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div { class: "overflow-hidden"
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel:"stylesheet" }
Header {}
Entry {}
Hero {}
Hero {}
Hero {}
Hero {}
Hero {}
}
))
};
pub static Header: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
header { class: "text-gray-400 bg-gray-900 body-font"
div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center"
a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0"
StacksIcon {}
span { class: "ml-3 text-xl" "Hello Dioxus!"}
}
nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center"
a { class: "mr-5 hover:text-white" "First Link"}
a { class: "mr-5 hover:text-white" "Second Link"}
a { class: "mr-5 hover:text-white" "Third Link"}
a { class: "mr-5 hover:text-white" "Fourth Link"}
}
button {
class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0"
"Button"
RightArrowIcon {}
}
}
}
}
})
};
pub static Hero: FC<()> = |(cx, props)| {
//
cx.render(rsx! {
section{ class: "text-gray-400 bg-gray-900 body-font"
div { class: "container mx-auto flex px-5 py-24 md:flex-row flex-col items-center"
div { class: "lg:flex-grow md:w-1/2 lg:pr-24 md:pr-16 flex flex-col md:items-start md:text-left mb-16 md:mb-0 items-center text-center"
h1 { class: "title-font sm:text-4xl text-3xl mb-4 font-medium text-white"
br { class: "hidden lg:inline-block" }
"Dioxus Sneak Peek"
}
p {
class: "mb-8 leading-relaxed"
"Dioxus is a new UI framework that makes it easy and simple to write cross-platform apps using web
technologies! It is functional, fast, and portable. Dioxus can run on the web, on the desktop, and
on mobile and embedded platforms."
}
div { class: "flex justify-center"
button {
class: "inline-flex text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg"
"Learn more"
}
button {
class: "ml-4 inline-flex text-gray-400 bg-gray-800 border-0 py-2 px-6 focus:outline-none hover:bg-gray-700 hover:text-white rounded text-lg"
"Build an app"
}
}
}
div { class: "lg:max-w-lg lg:w-full md:w-1/2 w-5/6"
img { class: "object-cover object-center rounded" alt: "hero" src: "https://i.imgur.com/oK6BLtw.png"
referrerpolicy:"no-referrer"
}
}
}
}
})
};
pub static Entry: FC<()> = |(cx, props)| {
//
cx.render(rsx! {
section{ class: "text-gray-400 bg-gray-900 body-font"
div { class: "container mx-auto flex px-5 py-24 md:flex-row flex-col items-center"
textarea {
}
}
}
})
};
pub static StacksIcon: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
// xmlns: "http://www.w3.org/2000/svg"
fill: "none"
stroke: "currentColor"
stroke_linecap: "round"
stroke_linejoin: "round"
stroke_width: "2"
// class: "w-10 h-10 text-white p-2 bg-indigo-500 rounded-full"
viewBox: "0 0 24 24"
path { d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"}
}
))
};
pub static RightArrowIcon: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
fill: "none"
stroke: "currentColor"
stroke_linecap: "round"
stroke_linejoin: "round"
stroke_width: "2"
// class: "w-4 h-4 ml-1"
viewBox: "0 0 24 24"
path { d: "M5 12h14M12 5l7 7-7 7"}
}
))
};
+4 -10
View File
@@ -31,10 +31,7 @@ impl SsrRenderer {
}
}
pub fn render_lazy<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>>(
&'a mut self,
f: LazyNodes<'a, F>,
) -> String {
pub fn render_lazy<'a>(&'a mut self, f: Option<LazyNodes<'a, '_>>) -> String {
let bump = &mut self.inner as *mut _;
let s = self.render_inner(f);
// reuse the bump's memory
@@ -42,10 +39,7 @@ impl SsrRenderer {
s
}
fn render_inner<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>>(
&'a self,
f: LazyNodes<'a, F>,
) -> String {
fn render_inner<'a>(&'a self, f: Option<LazyNodes<'a, '_>>) -> String {
let factory = NodeFactory::new(&self.inner);
let root = f.into_vnode(factory);
format!(
@@ -59,7 +53,7 @@ impl SsrRenderer {
}
}
pub fn render_lazy<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>>(f: LazyNodes<'a, F>) -> String {
pub fn render_lazy<'a>(f: Option<LazyNodes<'a, '_>>) -> String {
let bump = bumpalo::Bump::new();
let borrowed = &bump;
@@ -398,7 +392,7 @@ mod tests {
fn styles() {
static STLYE_APP: FC<()> = |(cx, _)| {
cx.render(rsx! {
div { style: { color: "blue", font_size: "46px" } }
div { color: "blue", font_size: "46px" }
})
};
-3
View File
@@ -1,3 +0,0 @@
{
"rust-analyzer.inlayHints.enable": false
}
-53
View File
@@ -1,53 +0,0 @@
//! Basic example that renders a simple VNode to the browser.
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
fn main() {
console_error_panic_hook::set_once();
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
dioxus_web::launch(APP, |c| c)
}
#[derive(serde::Deserialize)]
struct DogApi {
message: String,
}
static APP: FC<()> = |(cx, _props)| {
let state = use_state(cx, || 0);
const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random/";
let doggo = use_suspense(
cx,
|| async { reqwest::get(ENDPOINT).await.unwrap().json::<DogApi>().await },
|cx, res| match res {
Ok(res) => rsx!(
cx,
img {
src: "{res.message}"
}
),
Err(_err) => rsx!(cx, div { "No doggos for you :(" }),
},
);
rsx!(cx, div { align_items: "center"
section { class: "py-12 px-4 text-center"
div { class: "w-full max-w-2xl mx-auto"
span { class: "text-sm font-semibold"
"count: {state}"
}
div {
button { onclick: move |_| state.set(state + 1), "incr" }
button { onclick: move |_| state.set(state - 1), "decr" }
}
div {
{doggo}
}
}
}
})
};
-89
View File
@@ -1,89 +0,0 @@
//! Basic example that renders a simple VNode to the browser.
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
fn main() {
// Setup logging
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
// Run the app
dioxus_web::launch(APP, |c| c)
}
static APP: FC<()> = |(cx, _)| {
let mut count = use_state(cx, || 3);
let content = use_state(cx, || String::from("h1"));
let text_content = use_state(cx, || String::from("Hello, world!"));
cx.render(rsx! {
div {
h1 { "content val is {content}" }
input {
r#type: "text",
value: "{text_content}"
oninput: move |e| text_content.set(e.value.clone())
}
{(0..10).map(|_| {
rsx!(
button {
onclick: move |_| count += 1,
"Click to add."
"Current count: {count}"
}
br {}
)
})}
select {
name: "cars"
id: "cars"
value: "{content}"
oninput: move |ev| {
content.set(ev.value.clone());
match ev.value.as_str() {
"h1" => count.set(0),
"h2" => count.set(5),
"h3" => count.set(10),
_ => {}
}
},
option { value: "h1", "h1" }
option { value: "h2", "h2" }
option { value: "h3", "h3" }
}
{render_list(cx, *count)}
{render_bullets(cx)}
CHILD {}
}
})
};
fn render_bullets(cx: Context) -> Element {
rsx!(cx, div {
"bite me"
})
}
fn render_list(cx: Context, count: usize) -> Element {
let items = (0..count).map(|f| {
rsx! {
li { "a - {f}" }
li { "b - {f}" }
li { "c - {f}" }
}
});
rsx!(cx, ul { {items} })
}
static CHILD: FC<()> = |(cx, _)| rsx!(cx, div {"hello child"});
-55
View File
@@ -1,55 +0,0 @@
//! Basic example that renders a simple VNode to the browser.
use dioxus::events::on::MouseEvent;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
use std::future::Future;
use std::{pin::Pin, time::Duration};
use dioxus::prelude::*;
use dioxus_web::*;
fn main() {
// Setup logging
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
// Run the app
dioxus_web::launch(App, |c| c)
}
static App: FC<()> = |(cx, props)| {
let mut state = use_state(cx, || 0);
cx.render(rsx! {
div {
style: {
align_items: "center"
}
section { class: "py-12 px-4 text-center"
div { class: "w-full max-w-2xl mx-auto"
span { class: "text-sm font-semibold"
"static subtree"
}
}
}
section { class: "py-12 px-4 text-center"
div { class: "w-full max-w-2xl mx-auto"
span { class: "text-sm font-semibold"
"dynamic subtree {state}"
}
div {
button { onclick: move |e| state+=1, "incr" }
br {}
button { onclick: move |e| state-=1, "decr" }
}
}
}
}
})
};
-69
View File
@@ -1,69 +0,0 @@
//! Example: Webview Renderer
//! -------------------------
//!
//! This example shows how to use the dioxus_desktop crate to build a basic desktop application.
//!
//! Under the hood, the dioxus_desktop crate bridges a native Dioxus VirtualDom with a custom prebuit application running
//! in the webview runtime. Custom handlers are provided for the webview instance to consume patches and emit user events
//! into the native VDom instance.
//!
//! Currently, NodeRefs won't work properly, but all other event functionality will.
use dioxus::prelude::*;
use dioxus_core as dioxus;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
// #[cfg]
fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
dioxus_web::launch(App, |c| c);
// env_logger::init();
// dioxus::web::launch(App, |c| c);
}
static App: FC<()> = |(cx, props)| {
dbg!("rednering parent");
cx.render(rsx! {
div {
But {
h1 {"he"}
}
// But {
// h1 {"llo"}
// }
// But {
// h1 {"world"}
// }
}
})
};
static But: FC<()> = |(cx, props)| {
let mut count = use_state(cx, || 0);
// let d = Dropper { name: "asd" };
// let handler = move |_| {
// dbg!(d.name);
// };
cx.render(rsx! {
div {
h1 { "Hifive counter: {count}" }
{cx.children()}
button { onclick: move |_| count += 1, "Up high!" }
button { onclick: move |_| count -= 1, "Down low!" }
// button { onclick: {handler}, "Down low!" }
}
})
};
// struct Dropper {
// name: &'static str,
// }
// impl Drop for Dropper {
// fn drop(&mut self) {
// dbg!("dropped");
// }
// }
-116
View File
@@ -1,116 +0,0 @@
/*
Tiny CRM: A port of the Yew CRM example to Dioxus.
*/
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
fn main() {
// Setup logging
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
dioxus_web::launch(App, |c| c)
}
enum Scene {
ClientsList,
NewClientForm,
Settings,
}
#[derive(Clone, Debug, Default)]
pub struct Client {
pub first_name: String,
pub last_name: String,
pub description: String,
}
static App: FC<()> = |(cx, _)| {
let scene = use_state(cx, || Scene::ClientsList);
let clients = use_ref(cx, || vec![] as Vec<Client>);
let firstname = use_state(cx, || String::new());
let lastname = use_state(cx, || String::new());
let description = use_state(cx, || String::new());
let scene = match *scene {
Scene::ClientsList => {
rsx!(cx, div { class: "crm"
h2 { "List of clients" margin_bottom: "10px" }
div { class: "clients" margin_left: "10px"
{clients.read().iter().map(|client| rsx!(
div { class: "client" style: "margin-bottom: 50px"
p { "First Name: {client.first_name}" }
p { "Last Name: {client.last_name}" }
p {"Description: {client.description}"}
})
)}
}
button { class: "pure-button pure-button-primary" onclick: move |_| scene.set(Scene::NewClientForm), "Add New" }
button { class: "pure-button" onclick: move |_| scene.set(Scene::Settings), "Settings" }
})
}
Scene::NewClientForm => {
let add_new = move |_| {
clients.write().push(Client {
description: (*description).clone(),
first_name: (*firstname).clone(),
last_name: (*lastname).clone(),
});
description.set(String::new());
firstname.set(String::new());
lastname.set(String::new());
};
rsx!(cx, div { class: "crm"
h2 {"Add new client" margin_bottom: "10px" }
form { class: "pure-form"
input { class: "new-client firstname" placeholder: "First name" value: "{firstname}"
oninput: move |evt| firstname.set(evt.value.clone())
}
input { class: "new-client lastname" placeholder: "Last name" value: "{lastname}"
oninput: move |evt| lastname.set(evt.value.clone())
}
textarea { class: "new-client description" placeholder: "Description" value: "{description}"
oninput: move |evt| description.set(evt.value.clone())
}
}
button { class: "pure-button pure-button-primary", onclick: {add_new}, "Add New" }
button { class: "pure-button", onclick: move |_| scene.set(Scene::ClientsList), "Go Back" }
})
}
Scene::Settings => {
rsx!(cx, div {
h2 { "Settings" margin_bottom: "10px" }
button {
background: "rgb(202, 60, 60)"
class: "pure-button pure-button-primary"
onclick: move |_| {
clients.write().clear();
scene.set(Scene::ClientsList);
},
"Remove all clients"
}
button {
class: "pure-button pure-button-primary"
onclick: move |_| scene.set(Scene::ClientsList),
"Go Back"
}
})
}
};
rsx!(cx, body {
link {
rel: "stylesheet"
href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css"
integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5"
crossorigin: "anonymous"
}
margin_left: "35%"
h1 {"Dioxus CRM Example"}
{scene}
})
};
-147
View File
@@ -1,147 +0,0 @@
//! Basic example that renders a simple VNode to the browser.
use dioxus::events::on::MouseEvent;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
use std::future::Future;
use std::{pin::Pin, time::Duration};
use dioxus::prelude::*;
use dioxus_html::SvgAttributes;
use dioxus_web::*;
fn main() {
// Setup logging
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
// Run the app
dioxus_web::launch(App, |c| c)
}
pub static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div { class: "overflow-hidden"
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel:"stylesheet" }
Header {}
// Entry {}
Hero {}
Hero {}
Hero {}
Hero {}
Hero {}
}
))
};
pub static Header: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
header { class: "text-gray-400 bg-gray-900 body-font"
div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center"
a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0"
StacksIcon {}
span { class: "ml-3 text-xl" "Hello Dioxus!"}
}
nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center"
a { class: "mr-5 hover:text-white" "First Link"}
a { class: "mr-5 hover:text-white" "Second Link"}
a { class: "mr-5 hover:text-white" "Third Link"}
a { class: "mr-5 hover:text-white" "Fourth Link"}
}
button {
class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0"
"Button"
RightArrowIcon {}
}
}
}
}
})
};
pub static Hero: FC<()> = |(cx, props)| {
//
cx.render(rsx! {
section{ class: "text-gray-400 bg-gray-900 body-font"
div { class: "container mx-auto flex px-5 py-24 md:flex-row flex-col items-center"
div { class: "lg:flex-grow md:w-1/2 lg:pr-24 md:pr-16 flex flex-col md:items-start md:text-left mb-16 md:mb-0 items-center text-center"
h1 { class: "title-font sm:text-4xl text-3xl mb-4 font-medium text-white"
br { class: "hidden lg:inline-block" }
"Dioxus Sneak Peek"
}
p {
class: "mb-8 leading-relaxed"
"Dioxus is a new UI framework that makes it easy and simple to write cross-platform apps using web
technologies! It is functional, fast, and portable. Dioxus can run on the web, on the desktop, and
on mobile and embedded platforms."
}
div { class: "flex justify-center"
button {
class: "inline-flex text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg"
"Learn more"
}
button {
class: "ml-4 inline-flex text-gray-400 bg-gray-800 border-0 py-2 px-6 focus:outline-none hover:bg-gray-700 hover:text-white rounded text-lg"
"Build an app"
}
}
}
div { class: "lg:max-w-lg lg:w-full md:w-1/2 w-5/6"
img { class: "object-cover object-center rounded" alt: "hero" src: "https://i.imgur.com/oK6BLtw.png"
referrerpolicy:"no-referrer"
}
}
}
}
})
};
pub static Entry: FC<()> = |(cx, props)| {
//
cx.render(rsx! {
section{ class: "text-gray-400 bg-gray-900 body-font"
div { class: "container mx-auto flex px-5 py-24 md:flex-row flex-col items-center"
textarea {
}
}
}
})
};
pub static StacksIcon: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
// xmlns: "http://www.w3.org/2000/svg"
fill: "none"
stroke: "currentColor"
stroke_linecap: "round"
stroke_linejoin: "round"
stroke_width: "2"
// class: "w-10 h-10 text-white p-2 bg-indigo-500 rounded-full"
viewBox: "0 0 24 24"
path { d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"}
}
))
};
pub static RightArrowIcon: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
fill: "none"
stroke: "currentColor"
stroke_linecap: "round"
stroke_linejoin: "round"
stroke_width: "2"
// class: "w-4 h-4 ml-1"
viewBox: "0 0 24 24"
path { d: "M5 12h14M12 5l7 7-7 7"}
}
))
};
-8
View File
@@ -1,8 +0,0 @@
[package]
name = "dioxus-webview-client"
version = "0.0.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-8
View File
@@ -1,8 +0,0 @@
# the client part of the vdom
this crate is designed to be the "receiving end" of the dioxus virtualdom, using wasm_bindgen to expose an API for the receiving end.
-3
View File
@@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}