mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-02-16 21:58:25 +00:00
wip: fix issues with lifetimes
this commit fixes some lifetime issues regarding having to "move" data into the IntoVNode closure.
This commit is contained in:
parent
22e659c2bd
commit
a38a81e129
39 changed files with 566 additions and 255 deletions
18
README.md
18
README.md
|
@ -107,29 +107,29 @@ Dioxus is heavily inspired by React, but we want your transition to feel like an
|
||||||
| Feature | Dioxus | React | Notes for Dioxus |
|
| Feature | Dioxus | React | Notes for Dioxus |
|
||||||
| ----------------------- | ------ | ----- | ----------------------------------------------------- |
|
| ----------------------- | ------ | ----- | ----------------------------------------------------- |
|
||||||
| Conditional Rendering | ✅ | ✅ | if/then to hide/show component |
|
| Conditional Rendering | ✅ | ✅ | if/then to hide/show component |
|
||||||
| Map, Iterator | ✅ | ✅ | map/filter/reduce rsx! |
|
| Map, Iterator | ✅ | ✅ | map/filter/reduce to produce rsx! |
|
||||||
| Keyed Components | ✅ | ✅ | advanced diffing with keys |
|
| Keyed Components | ✅ | ✅ | advanced diffing with keys |
|
||||||
| Web | ✅ | ✅ | renderer for web browser |
|
| Web | ✅ | ✅ | renderer for web browser |
|
||||||
| Desktop (webview) | ✅ | ✅ | renderer for desktop |
|
| Desktop (webview) | ✅ | ✅ | renderer for desktop |
|
||||||
| Context | ✅ | ✅ | share state through the tree |
|
| Shared State (Context) | ✅ | ✅ | share state through the tree |
|
||||||
| Hook | ✅ | ✅ | memory cells in components |
|
| Hook | ✅ | ✅ | memory cells in components |
|
||||||
| SSR | ✅ | ✅ | render directly to string |
|
| SSR | ✅ | ✅ | render directly to string |
|
||||||
| Component Children | ✅ | ✅ | cx.children() as a list of nodes |
|
| Component Children | ✅ | ✅ | cx.children() as a list of nodes |
|
||||||
| Null components | ✅ | ✅ | allow returning no components |
|
| Headless components | ✅ | ✅ | components that don't return real elements |
|
||||||
| No-div components | ✅ | ✅ | components that render components |
|
| Fragments | ✅ | ✅ | multiple elements without a real root |
|
||||||
| Fragments | ✅ | ✅ | rsx! can return multiple elements without a root |
|
|
||||||
| Manual Props | ✅ | ✅ | Manually pass in props with spread syntax |
|
| Manual Props | ✅ | ✅ | Manually pass in props with spread syntax |
|
||||||
| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs |
|
| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs |
|
||||||
| CSS/Inline Styles | ✅ | ✅ | syntax for inline styles/attribute groups[2] |
|
| CSS/Inline Styles | ✅ | ✅ | syntax for inline styles/attribute groups |
|
||||||
| NodeRef | 🛠 | ✅ | gain direct access to nodes [1] |
|
| Custom elements | ✅ | ✅ | Define new element primitives |
|
||||||
| 1st class global state | 🛠 | ✅ | redux/recoil/mobx on top of context |
|
| Compile-time correct | ✅ | ✅ | Throw errors on invalid template layouts |
|
||||||
|
| 1st class global state | ✅ | ❓ | redux/recoil/mobx on top of context |
|
||||||
| Suspense | 🛠 | ✅ | schedule future render from future/promise |
|
| Suspense | 🛠 | ✅ | schedule future render from future/promise |
|
||||||
| Cooperative Scheduling | 🛠 | ✅ | Prioritize important events over non-important events |
|
| Cooperative Scheduling | 🛠 | ✅ | Prioritize important events over non-important events |
|
||||||
| Fine-grained reactivity | 🛠 | ❓ | Skip diffing for fine-grain updates |
|
| Fine-grained reactivity | 🛠 | ❓ | Skip diffing for fine-grain updates |
|
||||||
| Runs natively | ✅ | ❓ | runs as a portable binary w/o a runtime (Node) |
|
| Runs natively | ✅ | ❓ | runs as a portable binary w/o a runtime (Node) |
|
||||||
|
| NodeRef | 🛠 | ✅ | gain direct access to nodes [1] |
|
||||||
|
|
||||||
- [1] Currently blocked until we figure out a cross-platform way of exposing an imperative Node API.
|
- [1] Currently blocked until we figure out a cross-platform way of exposing an imperative Node API.
|
||||||
- [2] Would like to solve this in a more general way. Something like attribute groups that's not styling-specific.
|
|
||||||
|
|
||||||
### Phase 2: Advanced Toolkits
|
### Phase 2: Advanced Toolkits
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! The example from the README.md
|
//! The example from the README.md
|
||||||
|
|
||||||
use dioxus::{events::on::MouseEvent, prelude::*};
|
use dioxus::prelude::*;
|
||||||
use dioxus_html_namespace::{button, div, h1};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus::web::launch(Example)
|
dioxus::web::launch(Example)
|
||||||
|
@ -12,11 +11,27 @@ fn main() {
|
||||||
fn Example(cx: Context<()>) -> VNode {
|
fn Example(cx: Context<()>) -> VNode {
|
||||||
let name = use_state(&cx, || "..?");
|
let name = use_state(&cx, || "..?");
|
||||||
|
|
||||||
let handler = move |e: MouseEvent| e.cl;
|
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "Hello, {name}" }
|
h1 { "Hello, {name}" }
|
||||||
button { "?", onclick: move |event| name.set("world!")}
|
button { "?", onclick: move |_| name.set("world!")}
|
||||||
button { "?", onclick: move |_| name.set("Dioxus 🎉")}
|
button { "?", onclick: move |_| name.set("Dioxus 🎉")}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Example2: FC<()> = |cx| {
|
||||||
|
let (g, set_g) = use_state_classic(&cx, || 0);
|
||||||
|
let v = (0..10).map(|f| {
|
||||||
|
dioxus::prelude::LazyNodes::new(move |__cx: &NodeFactory| {
|
||||||
|
__cx.element(dioxus_elements::li)
|
||||||
|
.listeners([dioxus::events::on::onclick(__cx, move |_| set_g(10))])
|
||||||
|
.finish()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
cx.render(dioxus::prelude::LazyNodes::new(
|
||||||
|
move |__cx: &NodeFactory| {
|
||||||
|
__cx.element(dioxus_elements::div)
|
||||||
|
.children([__cx.fragment_from_iter(v)])
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
|
@ -20,23 +20,6 @@ pub fn html(s: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
|
|
||||||
/// ```
|
|
||||||
/// rsx! {
|
|
||||||
/// div {
|
|
||||||
/// class: "some special class"
|
|
||||||
/// h1 { "Children too" }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn rsx(s: TokenStream) -> TokenStream {
|
|
||||||
match syn::parse::<rsx::RsxRender>(s) {
|
|
||||||
Err(e) => e.to_compile_error().into(),
|
|
||||||
Ok(s) => s.to_token_stream().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
|
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
|
||||||
/// We aim to keep functional parity with html templates.
|
/// We aim to keep functional parity with html templates.
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
|
@ -97,3 +80,165 @@ pub fn derive_typed_builder(input: proc_macro::TokenStream) -> proc_macro::Token
|
||||||
Err(error) => error.to_compile_error().into(),
|
Err(error) => error.to_compile_error().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
|
||||||
|
///
|
||||||
|
/// ## Complete Reference Guide:
|
||||||
|
/// ```
|
||||||
|
/// const Example: FC<()> = |cx| {
|
||||||
|
/// let formatting = "formatting!";
|
||||||
|
/// let formatting_tuple = ("a", "b");
|
||||||
|
/// let lazy_fmt = format_args!("lazily formatted text");
|
||||||
|
/// cx.render(rsx! {
|
||||||
|
/// div {
|
||||||
|
/// // Elements
|
||||||
|
/// div {}
|
||||||
|
/// h1 {"Some text"}
|
||||||
|
/// h1 {"Some text with {formatting}"}
|
||||||
|
/// h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
|
||||||
|
/// h2 {
|
||||||
|
/// "Multiple"
|
||||||
|
/// "Text"
|
||||||
|
/// "Blocks"
|
||||||
|
/// "Use comments as separators in html"
|
||||||
|
/// }
|
||||||
|
/// div {
|
||||||
|
/// h1 {"multiple"}
|
||||||
|
/// h2 {"nested"}
|
||||||
|
/// h3 {"elements"}
|
||||||
|
/// }
|
||||||
|
/// div {
|
||||||
|
/// class: "my special div"
|
||||||
|
/// h1 {"Headers and attributes!"}
|
||||||
|
/// }
|
||||||
|
/// div {
|
||||||
|
/// // pass simple rust expressions in
|
||||||
|
/// class: lazy_fmt,
|
||||||
|
/// id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
|
||||||
|
/// div {
|
||||||
|
/// class: {
|
||||||
|
/// const WORD: &str = "expressions";
|
||||||
|
/// format_args!("Arguments can be passed in through curly braces for complex {}", WORD)
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Expressions can be used in element position too:
|
||||||
|
/// {rsx!(p { "More templating!" })}
|
||||||
|
/// {html!(<p>"Even HTML templating!!"</p>)}
|
||||||
|
///
|
||||||
|
/// // Iterators
|
||||||
|
/// {(0..10).map(|i| rsx!(li { "{i}" }))}
|
||||||
|
/// {{
|
||||||
|
/// let data = std::collections::HashMap::<&'static str, &'static str>::new();
|
||||||
|
/// // Iterators *should* have keys when you can provide them.
|
||||||
|
/// // Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
|
||||||
|
/// // Using an "ID" associated with your data is a good idea.
|
||||||
|
/// data.into_iter().map(|(k, v)| rsx!(li { key: "{k}" "{v}" }))
|
||||||
|
/// }}
|
||||||
|
///
|
||||||
|
/// // Matching
|
||||||
|
/// // Matching will throw a Rust error about "no two closures are the same type"
|
||||||
|
/// // To fix this, call "render" method or use the "in" syntax to produce VNodes.
|
||||||
|
/// // There's nothing we can do about it, sorry :/ (unless you want *really* unhygenic macros)
|
||||||
|
/// {match true {
|
||||||
|
/// true => rsx!(in cx, h1 {"Top text"}),
|
||||||
|
/// false => cx.render(rsx!( h1 {"Bottom text"}))
|
||||||
|
/// }}
|
||||||
|
///
|
||||||
|
/// // Conditional rendering
|
||||||
|
/// // Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
|
||||||
|
/// // You can convert a bool condition to rsx! with .then and .or
|
||||||
|
/// {true.then(|| rsx!(div {}))}
|
||||||
|
///
|
||||||
|
/// // True conditions need to be rendered (same reasons as matching)
|
||||||
|
/// {if true {
|
||||||
|
/// rsx!(in cx, h1 {"Top text"})
|
||||||
|
/// } else {
|
||||||
|
/// rsx!(in cx, h1 {"Bottom text"})
|
||||||
|
/// }}
|
||||||
|
///
|
||||||
|
/// // returning "None" is a bit noisy... but rare in practice
|
||||||
|
/// {None as Option<()>}
|
||||||
|
///
|
||||||
|
/// // Use the Dioxus type-alias for less noise
|
||||||
|
/// {NONE_ELEMENT}
|
||||||
|
///
|
||||||
|
/// // can also just use empty fragments
|
||||||
|
/// Fragment {}
|
||||||
|
///
|
||||||
|
/// // Fragments let you insert groups of nodes without a parent.
|
||||||
|
/// // This lets you make components that insert elements as siblings without a container.
|
||||||
|
/// div {"A"}
|
||||||
|
/// Fragment {
|
||||||
|
/// div {"B"}
|
||||||
|
/// div {"C"}
|
||||||
|
/// Fragment {
|
||||||
|
/// "D"
|
||||||
|
/// Fragment {
|
||||||
|
/// "heavily nested fragments is an antipattern"
|
||||||
|
/// "they cause Dioxus to do unnecessary work"
|
||||||
|
/// "don't use them carelessly if you can help it"
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Components
|
||||||
|
/// // Can accept any paths
|
||||||
|
/// // Notice how you still get syntax highlighting and IDE support :)
|
||||||
|
/// Baller {}
|
||||||
|
/// baller::Baller { }
|
||||||
|
/// crate::baller::Baller {}
|
||||||
|
///
|
||||||
|
/// // Can take properties
|
||||||
|
/// Taller { a: "asd" }
|
||||||
|
///
|
||||||
|
/// // Can take optional properties
|
||||||
|
/// Taller { a: "asd" }
|
||||||
|
///
|
||||||
|
/// // Can pass in props directly as an expression
|
||||||
|
/// {{
|
||||||
|
/// let props = TallerProps {a: "hello"};
|
||||||
|
/// rsx!(Taller { ..props })
|
||||||
|
/// }}
|
||||||
|
///
|
||||||
|
/// // Spreading can also be overridden manually
|
||||||
|
/// Taller {
|
||||||
|
/// ..TallerProps { a: "ballin!" }
|
||||||
|
/// a: "not ballin!"
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Can take children too!
|
||||||
|
/// Taller { a: "asd", div {"hello world!"} }
|
||||||
|
/// }
|
||||||
|
/// })
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// mod baller {
|
||||||
|
/// use super::*;
|
||||||
|
/// pub struct BallerProps {}
|
||||||
|
///
|
||||||
|
/// /// This component totally balls
|
||||||
|
/// pub fn Baller(cx: Context<()>) -> VNode {
|
||||||
|
/// todo!()
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[derive(Debug, PartialEq, Props)]
|
||||||
|
/// pub struct TallerProps {
|
||||||
|
/// a: &'static str,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// /// This component is taller than most :)
|
||||||
|
/// pub fn Taller(cx: Context<TallerProps>) -> VNode {
|
||||||
|
/// let b = true;
|
||||||
|
/// todo!()
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn rsx(s: TokenStream) -> TokenStream {
|
||||||
|
match syn::parse::<rsx::RsxRender>(s) {
|
||||||
|
Err(e) => e.to_compile_error().into(),
|
||||||
|
Ok(s) => s.to_token_stream().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ impl ToTokens for Element {
|
||||||
// let name = &self.name.to_string();
|
// let name = &self.name.to_string();
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
__cx.element(#name)
|
__cx.element(dioxus_elements::#name)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add attributes
|
// Add attributes
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl ToTokens for RsxRender {
|
||||||
quote! {#inner}
|
quote! {#inner}
|
||||||
} else {
|
} else {
|
||||||
let childs = &self.roots;
|
let childs = &self.roots;
|
||||||
quote! { __cx.fragment_from_iter(&[ #(#childs),* ]) }
|
quote! { __cx.fragment_from_iter([ #(#childs),* ]) }
|
||||||
};
|
};
|
||||||
|
|
||||||
match &self.custom_context {
|
match &self.custom_context {
|
||||||
|
|
|
@ -1,27 +1,29 @@
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
mod dioxus_elements {
|
||||||
|
use super::*;
|
||||||
|
pub struct div;
|
||||||
|
impl DioxusElement for div {
|
||||||
|
const TAG_NAME: &'static str = "str";
|
||||||
|
const NAME_SPACE: Option<&'static str> = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Example: FC<()> = |cx| {
|
static Example: FC<()> = |cx| {
|
||||||
cx.render(dioxus_core::prelude::LazyNodes::new(move |cx| {
|
let list = (0..10).map(|f| {
|
||||||
|
//
|
||||||
|
LazyNodes::new(move |f: NodeFactory| todo!())
|
||||||
|
});
|
||||||
|
cx.render(LazyNodes::new(move |cx| {
|
||||||
let bump = cx.bump();
|
let bump = cx.bump();
|
||||||
dioxus_core::builder::ElementBuilder::new(cx, "h1")
|
dioxus_core::builder::ElementBuilder::new(&cx, "h1")
|
||||||
.children([dioxus_core::builder::text3(bump, format_args!("hello"))])
|
.children([
|
||||||
.finish()
|
cx.text(format_args!("hello")),
|
||||||
}))
|
cx.text(format_args!("hello")),
|
||||||
};
|
cx.fragment_from_iter(list),
|
||||||
|
])
|
||||||
struct Props {
|
|
||||||
text: String,
|
|
||||||
}
|
|
||||||
static Example2: FC<Props> = |cx| {
|
|
||||||
cx.render(dioxus_core::prelude::LazyNodes::new(move |__cx| {
|
|
||||||
let bump = __cx.bump();
|
|
||||||
dioxus_core::builder::ElementBuilder::new(__cx, "h1")
|
|
||||||
.children([dioxus_core::builder::text3(
|
|
||||||
bump,
|
|
||||||
format_args!("{}", cx.props.text),
|
|
||||||
)])
|
|
||||||
.finish()
|
.finish()
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,10 +49,23 @@ pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
|
||||||
///
|
///
|
||||||
/// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
|
/// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
|
||||||
/// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
|
/// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
|
||||||
#[allow(non_upper_case_globals)]
|
use crate::prelude::*;
|
||||||
pub const Fragment: FC<()> = |cx| {
|
pub fn Fragment<'a>(cx: Context<'a, ()>) -> VNode<'a> {
|
||||||
use crate::prelude::*;
|
let childs: &'a [VNode<'a>] = cx.children();
|
||||||
cx.render(LazyNodes::new(move |c| {
|
cx.render(LazyNodes::new({
|
||||||
crate::nodebuilder::vfragment(c, None, cx.children())
|
move |f| {
|
||||||
|
//
|
||||||
|
f.fragment_from_iter(childs)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
};
|
}
|
||||||
|
// #[allow(non_upper_case_globals)]
|
||||||
|
// pub const Fragment: FC<()> = |cx| {
|
||||||
|
// use crate::prelude::*;
|
||||||
|
// let childs = cx.children();
|
||||||
|
// cx.render(LazyNodes::new(move |c| {
|
||||||
|
// c.fragment_from_iter(childs)
|
||||||
|
// // c.text(format_args!(""))
|
||||||
|
// // crate::nodebuilder::vfragment(c, None, cx.children())
|
||||||
|
// }))
|
||||||
|
// };
|
||||||
|
|
|
@ -49,18 +49,18 @@ impl DebugRenderer {
|
||||||
// If you have a list or "nth" child, you do need to list those children, but you don't need to
|
// If you have a list or "nth" child, you do need to list those children, but you don't need to
|
||||||
// fill in their children/attrs/etc
|
// fill in their children/attrs/etc
|
||||||
// Does not handle children or lifecycles and will always fail the test if they show up in the rhs
|
// Does not handle children or lifecycles and will always fail the test if they show up in the rhs
|
||||||
pub fn compare<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
|
pub fn compare<F>(&self, other: LazyNodes<F>) -> Result<()>
|
||||||
where
|
where
|
||||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
|
||||||
{
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a full compare - everything must match
|
// Do a full compare - everything must match
|
||||||
// Ignores listeners and children components
|
// Ignores listeners and children components
|
||||||
pub fn compare_full<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
|
pub fn compare_full<F>(&self, other: LazyNodes<F>) -> Result<()>
|
||||||
where
|
where
|
||||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
|
||||||
{
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -69,9 +69,9 @@ impl DebugRenderer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_nodes<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
|
pub fn render_nodes<F>(&self, other: LazyNodes<F>) -> Result<()>
|
||||||
where
|
where
|
||||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
|
||||||
{
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,14 +124,12 @@ pub mod on {
|
||||||
|
|
||||||
macro_rules! event_directory {
|
macro_rules! event_directory {
|
||||||
( $(
|
( $(
|
||||||
$(
|
$( #[$attr:meta] )*
|
||||||
#[$attr:meta]
|
|
||||||
)*
|
|
||||||
$eventdata:ident($wrapper:ident): [
|
$eventdata:ident($wrapper:ident): [
|
||||||
$(
|
$(
|
||||||
#[$method_attr:meta]
|
$( #[$method_attr:meta] )*
|
||||||
|
$name:ident
|
||||||
)*
|
)*
|
||||||
$( $name:ident )*
|
|
||||||
];
|
];
|
||||||
)* ) => {
|
)* ) => {
|
||||||
$(
|
$(
|
||||||
|
@ -149,8 +147,8 @@ pub mod on {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(#[$method_attr])*
|
|
||||||
$(
|
$(
|
||||||
|
$(#[$method_attr])*
|
||||||
pub fn $name<'a>(
|
pub fn $name<'a>(
|
||||||
c: &'_ NodeFactory<'a>,
|
c: &'_ NodeFactory<'a>,
|
||||||
callback: impl Fn($wrapper) + 'a,
|
callback: impl Fn($wrapper) + 'a,
|
||||||
|
@ -181,35 +179,51 @@ pub mod on {
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
event_directory! {
|
event_directory! {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClipboardEventInner(ClipboardEvent): [
|
ClipboardEventInner(ClipboardEvent): [
|
||||||
/// Called when "copy"
|
/// Called when "copy"
|
||||||
oncopy
|
oncopy
|
||||||
|
/// oncut
|
||||||
oncut
|
oncut
|
||||||
|
/// onpaste
|
||||||
onpaste
|
onpaste
|
||||||
];
|
];
|
||||||
|
|
||||||
CompositionEventInner(CompositionEvent): [
|
CompositionEventInner(CompositionEvent): [
|
||||||
|
/// oncompositionend
|
||||||
oncompositionend
|
oncompositionend
|
||||||
|
/// oncompositionstart
|
||||||
oncompositionstart
|
oncompositionstart
|
||||||
|
/// oncompositionupdate
|
||||||
oncompositionupdate
|
oncompositionupdate
|
||||||
];
|
];
|
||||||
|
|
||||||
KeyboardEventInner(KeyboardEvent): [
|
KeyboardEventInner(KeyboardEvent): [
|
||||||
|
/// onkeydown
|
||||||
onkeydown
|
onkeydown
|
||||||
|
/// onkeypress
|
||||||
onkeypress
|
onkeypress
|
||||||
|
/// onkeyup
|
||||||
onkeyup
|
onkeyup
|
||||||
];
|
];
|
||||||
|
|
||||||
FocusEventInner(FocusEvent): [
|
FocusEventInner(FocusEvent): [
|
||||||
|
/// onfocus
|
||||||
onfocus
|
onfocus
|
||||||
|
/// onblur
|
||||||
onblur
|
onblur
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
FormEventInner(FormEvent): [
|
FormEventInner(FormEvent): [
|
||||||
|
/// onchange
|
||||||
onchange
|
onchange
|
||||||
|
/// oninput
|
||||||
oninput
|
oninput
|
||||||
|
/// oninvalid
|
||||||
oninvalid
|
oninvalid
|
||||||
|
/// onreset
|
||||||
onreset
|
onreset
|
||||||
|
/// onsubmit
|
||||||
onsubmit
|
onsubmit
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -237,63 +251,202 @@ pub mod on {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Event Handlers
|
/// ## Event Handlers
|
||||||
/// - click
|
/// - [`onclick`]
|
||||||
/// - contextmenu
|
/// - [`oncontextmenu`]
|
||||||
/// - doubleclick
|
/// - [`ondoubleclick`]
|
||||||
/// - drag
|
/// - [`ondrag`]
|
||||||
/// - dragend
|
/// - [`ondragend`]
|
||||||
/// - dragenter
|
/// - [`ondragenter`]
|
||||||
/// - dragexit
|
/// - [`ondragexit`]
|
||||||
/// - dragleave
|
/// - [`ondragleave`]
|
||||||
/// - dragover
|
/// - [`ondragover`]
|
||||||
/// - dragstart
|
/// - [`ondragstart`]
|
||||||
/// - drop
|
/// - [`ondrop`]
|
||||||
/// - mousedown
|
/// - [`onmousedown`]
|
||||||
/// - mouseenter
|
/// - [`onmouseenter`]
|
||||||
/// - mouseleave
|
/// - [`onmouseleave`]
|
||||||
/// - mousemove
|
/// - [`onmousemove`]
|
||||||
/// - mouseout
|
/// - [`onmouseout`]
|
||||||
/// - mouseover
|
/// - [`onmouseover`]
|
||||||
/// - mouseup
|
/// - [`onmouseup`]
|
||||||
MouseEventInner(MouseEvent): [
|
MouseEventInner(MouseEvent): [
|
||||||
/// Onclick!
|
/// Execute a callback when a button is clicked.
|
||||||
|
///
|
||||||
|
/// ## Description
|
||||||
|
///
|
||||||
|
/// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
|
||||||
|
/// is both pressed and released while the pointer is located inside the element.
|
||||||
|
///
|
||||||
|
/// - Bubbles: Yes
|
||||||
|
/// - Cancelable: Yes
|
||||||
|
/// - Interface: [`MouseEvent`]
|
||||||
|
///
|
||||||
|
/// If the button is pressed on one element and the pointer is moved outside the element before the button
|
||||||
|
/// is released, the event is fired on the most specific ancestor element that contained both elements.
|
||||||
|
/// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```
|
||||||
|
/// rsx!( button { "click me", onclick: move |_| log::info!("Clicked!`") } )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Reference
|
||||||
|
/// - https://www.w3schools.com/tags/ev_onclick.asp
|
||||||
|
/// - https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
|
||||||
|
///
|
||||||
onclick
|
onclick
|
||||||
|
/// oncontextmenu
|
||||||
oncontextmenu
|
oncontextmenu
|
||||||
|
/// ondoubleclick
|
||||||
ondoubleclick
|
ondoubleclick
|
||||||
|
/// ondrag
|
||||||
ondrag
|
ondrag
|
||||||
|
/// ondragend
|
||||||
ondragend
|
ondragend
|
||||||
|
/// ondragenter
|
||||||
ondragenter
|
ondragenter
|
||||||
|
/// ondragexit
|
||||||
ondragexit
|
ondragexit
|
||||||
|
/// ondragleave
|
||||||
ondragleave
|
ondragleave
|
||||||
|
/// ondragover
|
||||||
ondragover
|
ondragover
|
||||||
|
/// ondragstart
|
||||||
ondragstart
|
ondragstart
|
||||||
|
/// ondrop
|
||||||
ondrop
|
ondrop
|
||||||
|
/// onmousedown
|
||||||
onmousedown
|
onmousedown
|
||||||
|
/// onmouseenter
|
||||||
onmouseenter
|
onmouseenter
|
||||||
|
/// onmouseleave
|
||||||
onmouseleave
|
onmouseleave
|
||||||
|
/// onmousemove
|
||||||
onmousemove
|
onmousemove
|
||||||
|
/// onmouseout
|
||||||
onmouseout
|
onmouseout
|
||||||
|
/// onmouseover
|
||||||
onmouseover
|
onmouseover
|
||||||
|
/// onmouseup
|
||||||
onmouseup
|
onmouseup
|
||||||
];
|
];
|
||||||
|
|
||||||
PointerEventInner(PointerEvent): [
|
PointerEventInner(PointerEvent): [
|
||||||
pointerdown pointermove pointerup pointercancel gotpointercapture
|
/// pointerdown
|
||||||
lostpointercapture pointerenter pointerleave pointerover pointerout
|
onpointerdown
|
||||||
|
/// pointermove
|
||||||
|
onpointermove
|
||||||
|
/// pointerup
|
||||||
|
onpointerup
|
||||||
|
/// pointercancel
|
||||||
|
onpointercancel
|
||||||
|
/// gotpointercapture
|
||||||
|
ongotpointercapture
|
||||||
|
/// lostpointercapture
|
||||||
|
onlostpointercapture
|
||||||
|
/// pointerenter
|
||||||
|
onpointerenter
|
||||||
|
/// pointerleave
|
||||||
|
onpointerleave
|
||||||
|
/// pointerover
|
||||||
|
onpointerover
|
||||||
|
/// pointerout
|
||||||
|
onpointerout
|
||||||
];
|
];
|
||||||
SelectionEventInner(SelectionEvent): [select];
|
|
||||||
TouchEventInner(TouchEvent): [touchcancel touchend touchmove touchstart];
|
SelectionEventInner(SelectionEvent): [
|
||||||
UIEventInner(UIEvent): [scroll];
|
/// onselect
|
||||||
WheelEventInner(WheelEvent): [wheel];
|
onselect
|
||||||
|
];
|
||||||
|
|
||||||
|
TouchEventInner(TouchEvent): [
|
||||||
|
/// ontouchcancel
|
||||||
|
ontouchcancel
|
||||||
|
/// ontouchend
|
||||||
|
ontouchend
|
||||||
|
/// ontouchmove
|
||||||
|
ontouchmove
|
||||||
|
/// ontouchstart
|
||||||
|
ontouchstart
|
||||||
|
];
|
||||||
|
|
||||||
|
UIEventInner(UIEvent): [
|
||||||
|
///
|
||||||
|
scroll
|
||||||
|
];
|
||||||
|
|
||||||
|
WheelEventInner(WheelEvent): [
|
||||||
|
///
|
||||||
|
wheel
|
||||||
|
];
|
||||||
|
|
||||||
MediaEventInner(MediaEvent): [
|
MediaEventInner(MediaEvent): [
|
||||||
abort canplay canplaythrough durationchange emptied encrypted
|
///abort
|
||||||
ended error loadeddata loadedmetadata loadstart pause play
|
onabort
|
||||||
playing progress ratechange seeked seeking stalled suspend
|
///canplay
|
||||||
timeupdate volumechange waiting
|
oncanplay
|
||||||
|
///canplaythrough
|
||||||
|
oncanplaythrough
|
||||||
|
///durationchange
|
||||||
|
ondurationchange
|
||||||
|
///emptied
|
||||||
|
onemptied
|
||||||
|
///encrypted
|
||||||
|
onencrypted
|
||||||
|
///ended
|
||||||
|
onended
|
||||||
|
///error
|
||||||
|
onerror
|
||||||
|
///loadeddata
|
||||||
|
onloadeddata
|
||||||
|
///loadedmetadata
|
||||||
|
onloadedmetadata
|
||||||
|
///loadstart
|
||||||
|
onloadstart
|
||||||
|
///pause
|
||||||
|
onpause
|
||||||
|
///play
|
||||||
|
onplay
|
||||||
|
///playing
|
||||||
|
onplaying
|
||||||
|
///progress
|
||||||
|
onprogress
|
||||||
|
///ratechange
|
||||||
|
onratechange
|
||||||
|
///seeked
|
||||||
|
onseeked
|
||||||
|
///seeking
|
||||||
|
onseeking
|
||||||
|
///stalled
|
||||||
|
onstalled
|
||||||
|
///suspend
|
||||||
|
onsuspend
|
||||||
|
///timeupdate
|
||||||
|
ontimeupdate
|
||||||
|
///volumechange
|
||||||
|
onvolumechange
|
||||||
|
///waiting
|
||||||
|
onwaiting
|
||||||
|
];
|
||||||
|
|
||||||
|
AnimationEventInner(AnimationEvent): [
|
||||||
|
/// onanimationstart
|
||||||
|
onanimationstart
|
||||||
|
/// onanimationend
|
||||||
|
onanimationend
|
||||||
|
/// onanimationiteration
|
||||||
|
onanimationiteration
|
||||||
|
];
|
||||||
|
|
||||||
|
TransitionEventInner(TransitionEvent): [
|
||||||
|
///
|
||||||
|
ontransitionend
|
||||||
|
];
|
||||||
|
|
||||||
|
ToggleEventInner(ToggleEvent): [
|
||||||
|
///
|
||||||
|
ontoggle
|
||||||
];
|
];
|
||||||
AnimationEventInner(AnimationEvent): [animationstart animationend animationiteration];
|
|
||||||
TransitionEventInner(TransitionEvent): [transitionend];
|
|
||||||
ToggleEventInner(ToggleEvent): [toggle];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GenericEventInner {
|
pub trait GenericEventInner {
|
||||||
|
@ -404,7 +557,6 @@ pub mod on {
|
||||||
fn alt_key(&self) -> bool;
|
fn alt_key(&self) -> bool;
|
||||||
fn button(&self) -> i16;
|
fn button(&self) -> i16;
|
||||||
fn buttons(&self) -> u16;
|
fn buttons(&self) -> u16;
|
||||||
|
|
||||||
/// Get the X coordinate of the mouse relative to the window
|
/// Get the X coordinate of the mouse relative to the window
|
||||||
fn client_x(&self) -> i32;
|
fn client_x(&self) -> i32;
|
||||||
fn client_y(&self) -> i32;
|
fn client_y(&self) -> i32;
|
||||||
|
@ -709,26 +861,3 @@ pub mod on {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mod tests {
|
|
||||||
|
|
||||||
// use std::rc::Rc;
|
|
||||||
|
|
||||||
// use crate as dioxus;
|
|
||||||
// use crate::events::on::MouseEvent;
|
|
||||||
// use crate::prelude::*;
|
|
||||||
|
|
||||||
// fn autocomplete() {
|
|
||||||
// // let v = move |evt| {
|
|
||||||
// // let r = evt.alt_key();
|
|
||||||
// // };
|
|
||||||
|
|
||||||
// let g = rsx! {
|
|
||||||
// button {
|
|
||||||
// onclick: move |evt| {
|
|
||||||
// let r = evt.alt_key();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub mod component;
|
||||||
pub mod styles;
|
pub mod styles;
|
||||||
pub mod util; // Logic for extending FC
|
pub mod util; // Logic for extending FC
|
||||||
|
|
||||||
pub mod debug_renderer;
|
// pub mod debug_renderer;
|
||||||
pub mod diff;
|
pub mod diff;
|
||||||
|
|
||||||
pub mod error; // Error type we expose to the renderers
|
pub mod error; // Error type we expose to the renderers
|
||||||
|
@ -62,7 +62,6 @@ pub mod prelude {
|
||||||
|
|
||||||
pub use crate::nodebuilder::LazyNodes;
|
pub use crate::nodebuilder::LazyNodes;
|
||||||
|
|
||||||
pub use crate::nodebuilder::ChildrenList;
|
|
||||||
pub use crate::nodebuilder::{DioxusElement, NodeFactory};
|
pub use crate::nodebuilder::{DioxusElement, NodeFactory};
|
||||||
// pub use nodes::iterables::IterableNodes;
|
// pub use nodes::iterables::IterableNodes;
|
||||||
/// This type alias is an internal way of abstracting over the static functions that represent components.
|
/// This type alias is an internal way of abstracting over the static functions that represent components.
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
fmt::Arguments,
|
fmt::Arguments,
|
||||||
intrinsics::transmute,
|
intrinsics::transmute,
|
||||||
|
marker::PhantomData,
|
||||||
u128,
|
u128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -511,8 +512,9 @@ where
|
||||||
pub fn iter_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
pub fn iter_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
||||||
let len_before = self.children.len();
|
let len_before = self.children.len();
|
||||||
for item in nodes {
|
for item in nodes {
|
||||||
let child = item.into_vnode(&self.cx);
|
todo!()
|
||||||
self.children.push(child);
|
// let child = item.into_vnode(&self.cx);
|
||||||
|
// self.children.push(child);
|
||||||
}
|
}
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
if self.children.len() > len_before + 1 {
|
if self.children.len() > len_before + 1 {
|
||||||
|
@ -541,52 +543,53 @@ impl<'a> IntoIterator for VNode<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> IntoVNode<'a> for VNode<'a> {
|
impl<'a> IntoVNode<'a> for VNode<'a> {
|
||||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoVNode<'a> for &VNode<'a> {
|
impl<'a> IntoVNode<'a> for &VNode<'a> {
|
||||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>
|
||||||
|
// where
|
||||||
|
// 'a: 'c,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
// cloning is cheap since vnodes are just references into bump arenas
|
// cloning is cheap since vnodes are just references into bump arenas
|
||||||
self.clone()
|
// self.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoVNode<'a> {
|
pub trait IntoVNode<'a> {
|
||||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a>;
|
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
|
// pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
|
||||||
where
|
// where
|
||||||
G: IntoVNode<'a>,
|
// G: IntoVNode<'a>,
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<'a, F> VNodeBuilder<'a, LazyNodes<'a, F>> for LazyNodes<'a, F> where
|
// impl<'a, F> VNodeBuilder<'a, LazyNodes<F>> for LazyNodes<F> where F: FnOnce(NodeFactory) -> VNode {}
|
||||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap the the node-builder closure in a concrete type.
|
// Wrap the the node-builder closure in a concrete type.
|
||||||
// ---
|
// ---
|
||||||
// This is a bit of a hack to implement the IntoVNode trait for closure types.
|
// This is a bit of a hack to implement the IntoVNode trait for closure types.
|
||||||
pub struct LazyNodes<'a, G>
|
pub struct LazyNodes<'a, G>
|
||||||
where
|
where
|
||||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||||
{
|
{
|
||||||
inner: G,
|
inner: G,
|
||||||
_p: std::marker::PhantomData<&'a ()>,
|
_p: PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, G> LazyNodes<'a, G>
|
impl<'a, G> LazyNodes<'a, G>
|
||||||
where
|
where
|
||||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||||
{
|
{
|
||||||
pub fn new(f: G) -> Self {
|
pub fn new(f: G) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: f,
|
inner: f,
|
||||||
_p: std::default::Default::default(),
|
_p: PhantomData {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,9 +601,9 @@ where
|
||||||
// rsx! { {nodes } }
|
// rsx! { {nodes } }
|
||||||
impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
|
impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
|
||||||
where
|
where
|
||||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||||
{
|
{
|
||||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||||
(self.inner)(cx)
|
(self.inner)(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,7 +611,7 @@ where
|
||||||
// Required because anything that enters brackets in the rsx! macro needs to implement IntoIterator
|
// Required because anything that enters brackets in the rsx! macro needs to implement IntoIterator
|
||||||
impl<'a, G> IntoIterator for LazyNodes<'a, G>
|
impl<'a, G> IntoIterator for LazyNodes<'a, G>
|
||||||
where
|
where
|
||||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||||
{
|
{
|
||||||
type Item = Self;
|
type Item = Self;
|
||||||
type IntoIter = std::iter::Once<Self::Item>;
|
type IntoIter = std::iter::Once<Self::Item>;
|
||||||
|
@ -617,23 +620,23 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoVNode<'a> for () {
|
// impl IntoVNode<'_> for () {
|
||||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||||
todo!();
|
// todo!();
|
||||||
VNode::Suspended {
|
// VNode::Suspended {
|
||||||
real: Cell::new(RealDomNode::empty()),
|
// real: Cell::new(RealDomNode::empty()),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<'a> IntoVNode<'a> for Option<()> {
|
// impl IntoVNode<'_> for Option<()> {
|
||||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||||
todo!();
|
// todo!();
|
||||||
VNode::Suspended {
|
// VNode::Suspended {
|
||||||
real: Cell::new(RealDomNode::empty()),
|
// real: Cell::new(RealDomNode::empty()),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Construct a text VNode.
|
/// Construct a text VNode.
|
||||||
///
|
///
|
||||||
|
@ -702,7 +705,7 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn virtual_child<'a, T: Properties + 'a>(
|
pub fn virtual_child<'a, T: Properties + 'a>(
|
||||||
cx: &NodeFactory<'a>,
|
cx: NodeFactory<'a>,
|
||||||
f: FC<T>,
|
f: FC<T>,
|
||||||
props: T,
|
props: T,
|
||||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||||
|
@ -713,54 +716,28 @@ pub fn virtual_child<'a, T: Properties + 'a>(
|
||||||
// todo!()
|
// todo!()
|
||||||
VNode::Component(
|
VNode::Component(
|
||||||
cx.bump()
|
cx.bump()
|
||||||
.alloc(crate::nodes::VComponent::new(cx, f, props, key, children)),
|
.alloc(crate::nodes::VComponent::new(&cx, f, props, key, children)),
|
||||||
// cx.bump()
|
// cx.bump()
|
||||||
// .alloc(crate::nodes::VComponent::new(f, props, key)),
|
// .alloc(crate::nodes::VComponent::new(f, props, key)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vfragment<'a>(
|
pub fn vfragment<'a>(
|
||||||
cx: &NodeFactory<'a>,
|
cx: NodeFactory<'a>,
|
||||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||||
children: &'a [VNode<'a>],
|
children: &'a [VNode<'a>],
|
||||||
) -> VNode<'a> {
|
) -> VNode<'a> {
|
||||||
VNode::Fragment(cx.bump().alloc(VFragment::new(key, children)))
|
VNode::Fragment(cx.bump().alloc(VFragment::new(key, children)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ChildrenList<'a, 'b> {
|
|
||||||
cx: &'b NodeFactory<'a>,
|
|
||||||
children: bumpalo::collections::Vec<'a, VNode<'a>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b> ChildrenList<'a, 'b> {
|
|
||||||
pub fn new(cx: &'b NodeFactory<'a>) -> Self {
|
|
||||||
Self {
|
|
||||||
cx,
|
|
||||||
children: bumpalo::collections::Vec::new_in(cx.bump()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
|
||||||
for item in nodes {
|
|
||||||
let child = item.into_vnode(&self.cx);
|
|
||||||
self.children.push(child);
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn finish(self) -> &'a [VNode<'a>] {
|
|
||||||
self.children.into_bump_slice()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This struct provides an ergonomic API to quickly build VNodes.
|
/// This struct provides an ergonomic API to quickly build VNodes.
|
||||||
///
|
///
|
||||||
/// NodeFactory is used to build VNodes in the component's memory space.
|
/// NodeFactory is used to build VNodes in the component's memory space.
|
||||||
/// This struct adds metadata to the final VNode about listeners, attributes, and children
|
/// This struct adds metadata to the final VNode about listeners, attributes, and children
|
||||||
#[derive(Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct NodeFactory<'a> {
|
pub struct NodeFactory<'a> {
|
||||||
pub scope_ref: &'a Scope,
|
pub scope_ref: &'a Scope,
|
||||||
pub listener_id: Cell<usize>,
|
pub listener_id: &'a Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NodeFactory<'a> {
|
impl<'a> NodeFactory<'a> {
|
||||||
|
@ -791,7 +768,7 @@ impl<'a> NodeFactory<'a> {
|
||||||
pub fn attr(
|
pub fn attr(
|
||||||
&self,
|
&self,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
val: Arguments<'a>,
|
val: Arguments,
|
||||||
namespace: Option<&'static str>,
|
namespace: Option<&'static str>,
|
||||||
) -> Attribute<'a> {
|
) -> Attribute<'a> {
|
||||||
let value = raw_text(self.bump(), val);
|
let value = raw_text(self.bump(), val);
|
||||||
|
@ -802,18 +779,6 @@ impl<'a> NodeFactory<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn child_list(&self) -> ChildrenList {
|
|
||||||
ChildrenList::new(&self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fragment_builder<'b>(
|
|
||||||
&'b self,
|
|
||||||
key: Option<&'a str>,
|
|
||||||
builder: impl FnOnce(ChildrenList<'a, 'b>) -> &'a [VNode<'a>],
|
|
||||||
) -> VNode<'a> {
|
|
||||||
self.fragment(builder(ChildrenList::new(&self)), key)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fragment(&self, children: &'a [VNode<'a>], key: Option<&'a str>) -> VNode<'a> {
|
pub fn fragment(&self, children: &'a [VNode<'a>], key: Option<&'a str>) -> VNode<'a> {
|
||||||
VNode::Fragment(self.bump().alloc(VFragment {
|
VNode::Fragment(self.bump().alloc(VFragment {
|
||||||
children,
|
children,
|
||||||
|
@ -822,12 +787,12 @@ impl<'a> NodeFactory<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fragment_from_iter(
|
pub fn fragment_from_iter(
|
||||||
&self,
|
self,
|
||||||
node_iter: impl IntoIterator<Item = impl IntoVNode<'a>>,
|
node_iter: impl IntoIterator<Item = impl IntoVNode<'a>>,
|
||||||
) -> VNode<'a> {
|
) -> VNode<'a> {
|
||||||
let mut nodes = bumpalo::collections::Vec::new_in(self.bump());
|
let mut nodes = bumpalo::collections::Vec::new_in(self.bump());
|
||||||
for node in node_iter.into_iter() {
|
for node in node_iter.into_iter() {
|
||||||
nodes.push(node.into_vnode(&self));
|
nodes.push(node.into_vnode(self));
|
||||||
}
|
}
|
||||||
VNode::Fragment(
|
VNode::Fragment(
|
||||||
self.bump()
|
self.bump()
|
||||||
|
|
|
@ -393,6 +393,8 @@ pub struct Scope {
|
||||||
// could also use ourborous
|
// could also use ourborous
|
||||||
hooks: RefCell<Vec<Hook>>,
|
hooks: RefCell<Vec<Hook>>,
|
||||||
|
|
||||||
|
pub(crate) listener_idx: Cell<usize>,
|
||||||
|
|
||||||
// Unsafety:
|
// Unsafety:
|
||||||
// - is self-refenrential and therefore needs to point into the bump
|
// - is self-refenrential and therefore needs to point into the bump
|
||||||
// Stores references into the listeners attached to the vnodes
|
// Stores references into the listeners attached to the vnodes
|
||||||
|
@ -463,6 +465,7 @@ impl Scope {
|
||||||
height,
|
height,
|
||||||
event_channel,
|
event_channel,
|
||||||
arena_link,
|
arena_link,
|
||||||
|
listener_idx: Default::default(),
|
||||||
frames: ActiveFrame::new(),
|
frames: ActiveFrame::new(),
|
||||||
hooks: Default::default(),
|
hooks: Default::default(),
|
||||||
shared_contexts: Default::default(),
|
shared_contexts: Default::default(),
|
||||||
|
@ -506,13 +509,9 @@ impl Scope {
|
||||||
|
|
||||||
// Remove all the outdated listeners
|
// Remove all the outdated listeners
|
||||||
self.listeners.borrow_mut().clear();
|
self.listeners.borrow_mut().clear();
|
||||||
// self.listeners
|
|
||||||
// .try_borrow_mut()
|
|
||||||
// .ok()
|
|
||||||
// .ok_or(Error::FatalInternal("Borrowing listener failed"))?
|
|
||||||
// .drain(..);
|
|
||||||
|
|
||||||
self.hookidx.set(0);
|
self.hookidx.set(0);
|
||||||
|
self.listener_idx.set(0);
|
||||||
|
|
||||||
let caller = self
|
let caller = self
|
||||||
.caller
|
.caller
|
||||||
|
@ -522,12 +521,8 @@ impl Scope {
|
||||||
// Cast the caller ptr from static to one with our own reference
|
// Cast the caller ptr from static to one with our own reference
|
||||||
let c2: &OpaqueComponent = caller.as_ref();
|
let c2: &OpaqueComponent = caller.as_ref();
|
||||||
let c3: &OpaqueComponent = unsafe { std::mem::transmute(c2) };
|
let c3: &OpaqueComponent = unsafe { std::mem::transmute(c2) };
|
||||||
// let c2: &OpaqueComponent<'static> = caller.as_ref();
|
|
||||||
// let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
|
|
||||||
|
|
||||||
let unsafe_head = unsafe { self.own_vnodes(c3) };
|
self.frames.cur_frame_mut().head_node = unsafe { self.own_vnodes(c3) };
|
||||||
|
|
||||||
self.frames.cur_frame_mut().head_node = unsafe_head;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -685,13 +680,15 @@ pub trait Scoped<'src>: Sized {
|
||||||
/// cx.render(lazy_tree)
|
/// cx.render(lazy_tree)
|
||||||
/// }
|
/// }
|
||||||
///```
|
///```
|
||||||
fn render<'a, F: for<'b> FnOnce(&'b NodeFactory<'src>) -> VNode<'src> + 'src + 'a>(
|
fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
|
||||||
self,
|
self,
|
||||||
lazy_nodes: LazyNodes<'src, F>,
|
lazy_nodes: LazyNodes<'src, F>,
|
||||||
) -> VNode<'src> {
|
) -> VNode<'src> {
|
||||||
lazy_nodes.into_vnode(&NodeFactory {
|
let scope_ref = self.get_scope();
|
||||||
scope_ref: self.get_scope(),
|
let listener_id = &scope_ref.listener_idx;
|
||||||
listener_id: 0.into(),
|
lazy_nodes.into_vnode(NodeFactory {
|
||||||
|
scope_ref,
|
||||||
|
listener_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,14 +887,14 @@ Any function prefixed with "use" should not be called conditionally.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SuspendedContext {}
|
pub struct SuspendedContext {}
|
||||||
|
|
||||||
impl SuspendedContext {
|
// impl SuspendedContext {
|
||||||
pub fn render<'a, 'src, F: for<'b> FnOnce(&'b NodeFactory<'src>) -> VNode<'src> + 'src + 'a>(
|
// pub fn render<'a, F: for<'b, 'src> FnOnce(&'b NodeFactory<'src>) -> VNode<'src>>(
|
||||||
self,
|
// &self,
|
||||||
lazy_nodes: LazyNodes<'src, F>,
|
// lazy_nodes: LazyNodes<F>,
|
||||||
) -> VNode<'src> {
|
// ) -> VNode {
|
||||||
todo!()
|
// todo!()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// ==================================================================================
|
// ==================================================================================
|
||||||
// Supporting structs for the above abstractions
|
// Supporting structs for the above abstractions
|
||||||
|
|
|
@ -26,7 +26,18 @@ macro_rules! builder_constructors {
|
||||||
( $(
|
( $(
|
||||||
$(#[$attr:meta])*
|
$(#[$attr:meta])*
|
||||||
$name:ident <> $namespace:tt;
|
$name:ident <> $namespace:tt;
|
||||||
)* ) => {};
|
)* ) => {
|
||||||
|
$(
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
$(#[$attr])*
|
||||||
|
pub struct $name;
|
||||||
|
|
||||||
|
impl DioxusElement for $name {
|
||||||
|
const TAG_NAME: &'static str = stringify!($name);
|
||||||
|
const NAME_SPACE: Option<&'static str> = Some(stringify!($namespace));
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Organized in the same order as
|
// Organized in the same order as
|
||||||
|
@ -554,6 +565,7 @@ builder_constructors! {
|
||||||
/// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
|
/// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
|
||||||
/// element.
|
/// element.
|
||||||
slot;
|
slot;
|
||||||
|
|
||||||
/// Build a
|
/// Build a
|
||||||
/// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
|
/// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
|
||||||
/// element.
|
/// element.
|
||||||
|
|
|
@ -9,6 +9,7 @@ license = "MIT/Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus-core = { path="../core", version="0.1.2" }
|
dioxus-core = { path="../core", version="0.1.2" }
|
||||||
|
dioxus-html-namespace = { path="../html-namespace" }
|
||||||
js-sys = "0.3"
|
js-sys = "0.3"
|
||||||
wasm-bindgen = { version="0.2.71", features=["enable-interning"] }
|
wasm-bindgen = { version="0.2.71", features=["enable-interning"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use dioxus::events::on::MouseEvent;
|
use dioxus::events::on::MouseEvent;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::*;
|
use dioxus_web::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
use dioxus::events::on::*;
|
use dioxus::events::on::*;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
|
const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
|
||||||
|
@ -159,7 +160,7 @@ struct CalculatorKeyProps<'a> {
|
||||||
onclick: &'a dyn Fn(MouseEvent),
|
onclick: &'a dyn Fn(MouseEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CalculatorKey<'a>(cx: Context<'a, CalculatorKeyProps>) -> VNode<'a> {
|
fn CalculatorKey<'a, 'r>(cx: Context<'a, CalculatorKeyProps<'r>>) -> VNode<'a> {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
button {
|
button {
|
||||||
class: "calculator-key {cx.name}"
|
class: "calculator-key {cx.name}"
|
||||||
|
@ -181,7 +182,7 @@ fn CalculatorDisplay<'a>(cx: Context<'a, CalculatorDisplayProps>) -> VNode<'a> {
|
||||||
// TODO: make it autoscaling with css
|
// TODO: make it autoscaling with css
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { class: "calculator-display"
|
div { class: "calculator-display"
|
||||||
div { class: "auto-scaling-text", "{display_value}" }
|
div { class: "auto-scaling-text", "{formatted}" }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Basic example that renders a simple VNode to the browser.
|
//! Basic example that renders a simple VNode to the browser.
|
||||||
|
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::*;
|
use dioxus_web::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
|
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use dioxus::prelude::*;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(CustomA))
|
wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(CustomA))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CustomA(cx: Context<()>) -> VNode {
|
fn CustomA(cx: Context<()>) -> VNode {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
use dioxus_html_namespace::*;
|
||||||
use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
|
use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -9,7 +11,7 @@ fn main() {
|
||||||
|
|
||||||
fn App(cx: Context<()>) -> VNode {
|
fn App(cx: Context<()>) -> VNode {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
main { class: "dark:bg-gray-800 bg-white relative h-screen"
|
div { class: "dark:bg-gray-800 bg-white relative h-screen"
|
||||||
NavBar {}
|
NavBar {}
|
||||||
{(0..10).map(|f| rsx!(Landing { key: "{f}" }))}
|
{(0..10).map(|f| rsx!(Landing { key: "{f}" }))}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use dioxus::{events::on::MouseEvent, prelude::*};
|
use dioxus::{events::on::MouseEvent, prelude::*};
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Basic example that renders a simple VNode to the browser.
|
//! Basic example that renders a simple VNode to the browser.
|
||||||
|
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::*;
|
use dioxus_web::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -12,6 +12,9 @@ use dioxus::events::on::MouseEvent;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||||
|
@ -21,7 +24,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use a special immutable hashmap to make hashmap operations efficient
|
// We use a special immutable hashmap to make hashmap operations efficient
|
||||||
type RowList = im_rc::HashMap<usize, Rc<str>, nohash_hasher::BuildNoHashHasher<usize>>;
|
type RowList = im_rc::HashMap<usize, Rc<str>, FxBuildHasher>;
|
||||||
|
// type RowList = im_rc::HashMap<usize, Rc<str>, nohash_hasher::BuildNoHashHasher<usize>>;
|
||||||
|
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx| {
|
||||||
let (items, set_items) = use_state_classic(&cx, || RowList::default());
|
let (items, set_items) = use_state_classic(&cx, || RowList::default());
|
||||||
|
@ -90,15 +94,15 @@ static App: FC<()> = |cx| {
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
struct ActionButtonProps<F: Fn(Rc<dyn MouseEvent>)> {
|
struct ActionButtonProps<F: Fn(MouseEvent)> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
id: &'static str,
|
id: &'static str,
|
||||||
action: F,
|
action: F,
|
||||||
}
|
}
|
||||||
fn ActionButton<F: Fn(Rc<dyn MouseEvent>)>(cx: Context<ActionButtonProps<F>>) -> VNode {
|
fn ActionButton<F: Fn(MouseEvent)>(cx: Context<ActionButtonProps<F>>) -> VNode {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { class: "col-sm-6 smallpad"
|
div { class: "col-sm-6 smallpad"
|
||||||
button {class:"btn btn-primary btn-block", type: "button", id: "{cx.id}", onclick: {&cx.action},
|
button {class:"btn btn-primary btn-block", r#type: "button", id: "{cx.id}", onclick: {&cx.action},
|
||||||
"{cx.name}"
|
"{cx.name}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +132,7 @@ fn Row<'a>(cx: Context<'a, RowProps>) -> VNode {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use fxhash::{FxBuildHasher, FxHasher32};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
fn create_new_row_label(rng: &mut SmallRng) -> Rc<str> {
|
fn create_new_row_label(rng: &mut SmallRng) -> Rc<str> {
|
||||||
let mut label = String::new();
|
let mut label = String::new();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::prelude::*;
|
use dioxus_web::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::{events::on::MouseEvent, prelude::*};
|
use dioxus_core::{events::on::MouseEvent, prelude::*};
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Setup logging
|
// Setup logging
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||||
|
@ -24,7 +26,7 @@ static App: FC<()> = |cx| {
|
||||||
placeholder: "Username"
|
placeholder: "Username"
|
||||||
class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
||||||
id: "username"
|
id: "username"
|
||||||
type: "text"
|
r#type: "text"
|
||||||
value: "{val}"
|
value: "{val}"
|
||||||
oninput: move |evet| set_val(evet.value())
|
oninput: move |evet| set_val(evet.value())
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,7 @@ static UserInput: FC<()> = |cx| {
|
||||||
input { class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
input { class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
||||||
placeholder: "Username"
|
placeholder: "Username"
|
||||||
id: "username"
|
id: "username"
|
||||||
type: "text"
|
r#type: "text"
|
||||||
oninput: move |evet| set_val(evet.value())
|
oninput: move |evet| set_val(evet.value())
|
||||||
}
|
}
|
||||||
p { "Val is: {val}" }
|
p { "Val is: {val}" }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::*;
|
use dioxus_web::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Setup logging
|
// Setup logging
|
||||||
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! Basic example that renders a simple VNode to the browser.
|
//! Basic example that renders a simple VNode to the browser.
|
||||||
|
|
||||||
use std::{future::Future, pin::Pin, rc::Rc};
|
|
||||||
|
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::*;
|
use dioxus_web::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Setup logging and panic handling
|
// Setup logging and panic handling
|
||||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ static App: FC<()> = |cx| {
|
||||||
"{todo.contents}"
|
"{todo.contents}"
|
||||||
input {
|
input {
|
||||||
class: "toggle"
|
class: "toggle"
|
||||||
type: "checkbox"
|
r#type: "checkbox"
|
||||||
"{todo.checked}"
|
"{todo.checked}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
use dioxus::events::on::*;
|
use dioxus::events::on::*;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
|
const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
|
||||||
|
|
|
@ -4,6 +4,8 @@ use std::rc::Rc;
|
||||||
use dioxus::{events::on::MouseEvent, prelude::*};
|
use dioxus::{events::on::MouseEvent, prelude::*};
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
|
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
|
||||||
|
@ -50,7 +52,7 @@ static Example: FC<ExampleProps> = |cx| {
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
struct ButtonProps<'src, F: Fn(Rc<dyn MouseEvent>)> {
|
struct ButtonProps<'src, F: Fn(MouseEvent)> {
|
||||||
name: &'src str,
|
name: &'src str,
|
||||||
handler: F,
|
handler: F,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
|
static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
|
||||||
|
@ -112,7 +113,7 @@ pub fn TodoEntry(cx: Context<TodoEntryProps>) -> VNode {
|
||||||
"{todo.id}"
|
"{todo.id}"
|
||||||
input {
|
input {
|
||||||
class: "toggle"
|
class: "toggle"
|
||||||
type: "checkbox"
|
r#type: "checkbox"
|
||||||
"{todo.checked}"
|
"{todo.checked}"
|
||||||
}
|
}
|
||||||
{is_editing.then(|| rsx!{
|
{is_editing.then(|| rsx!{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::{prelude::*, WebsysRenderer};
|
use dioxus_web::{prelude::*, WebsysRenderer};
|
||||||
|
|
||||||
// mod filtertoggles;
|
// mod filtertoggles;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html_namespace as dioxus_elements;
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
|
static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
|
||||||
|
@ -115,7 +116,7 @@ pub fn TodoEntry(cx: Context<TodoEntryProps>) -> VNode {
|
||||||
"{todo.id}"
|
"{todo.id}"
|
||||||
input {
|
input {
|
||||||
class: "toggle"
|
class: "toggle"
|
||||||
type: "checkbox"
|
r#type: "checkbox"
|
||||||
"{todo.checked}"
|
"{todo.checked}"
|
||||||
}
|
}
|
||||||
{is_editing.then(|| rsx!{
|
{is_editing.then(|| rsx!{
|
||||||
|
|
|
@ -169,6 +169,7 @@ pub mod prelude {
|
||||||
//! A glob import that includes helper types like FC, rsx!, html!, and required traits
|
//! A glob import that includes helper types like FC, rsx!, html!, and required traits
|
||||||
pub use dioxus_core::prelude::*;
|
pub use dioxus_core::prelude::*;
|
||||||
pub use dioxus_core_macro::fc;
|
pub use dioxus_core_macro::fc;
|
||||||
|
pub use dioxus_html_namespace as dioxus_elements;
|
||||||
}
|
}
|
||||||
// pub mod builder {
|
// pub mod builder {
|
||||||
// // pub use dioxus_core::builder::*;
|
// // pub use dioxus_core::builder::*;
|
||||||
|
|
Loading…
Add table
Reference in a new issue