Merge branch 'upstream' into optimize-templates-v3

This commit is contained in:
Evan Almloff committed 2022-12-07 18:29:02 -06:00
commit 99a4a9d45b
113 files changed
+347 -828

No files matched your search

+2 -1
View File
@@ -21,7 +21,8 @@ use std::{
/// }
/// ```
pub struct Event<T: 'static + ?Sized> {
pub(crate) data: Rc<T>,
/// The data associated with this event
pub data: Rc<T>,
pub(crate) propogates: Rc<Cell<bool>>,
}
+8
View File
@@ -514,6 +514,14 @@ impl<'a> IntoTemplate<'a> for VNode<'a> {
self
}
}
impl<'a> IntoTemplate<'a> for Element<'a> {
fn into_template(self, _cx: &'a ScopeState) -> VNode<'a> {
match self {
Ok(val) => val.into_template(_cx),
_ => VNode::empty().unwrap(),
}
}
}
impl<'a, 'b> IntoTemplate<'a> for LazyNodes<'a, 'b> {
fn into_template(self, cx: &'a ScopeState) -> VNode<'a> {
self.call(cx)
+5 -2
View File
@@ -21,9 +21,12 @@ pub fn use_window(cx: &ScopeState) -> &DesktopContext {
/// Get a closure that executes any JavaScript in the WebView context.
pub fn use_eval(cx: &ScopeState) -> &Rc<dyn Fn(String)> {
let desktop = use_window(cx).clone();
let desktop = use_window(cx);
&*cx.use_hook(|| Rc::new(move |script| desktop.eval(script)) as Rc<dyn Fn(String)>)
&*cx.use_hook(|| {
let desktop = desktop.clone();
Rc::new(move |script| desktop.eval(script))
} as Rc<dyn Fn(String)>)
}
/// An imperative interface to the current window.
+8 -8
View File
@@ -4,26 +4,26 @@ use rand::prelude::*;
fn main() {
let mut dom = VirtualDom::new(app);
dom.rebuild();
_ = dom.rebuild();
for _ in 0..1000 {
dom.rebuild();
_ = dom.rebuild();
}
}
fn app(cx: Scope) -> Element {
let mut rng = SmallRng::from_entropy();
render! (
cx.render(rsx! (
table {
tbody {
(0..10_000_usize).map(|f| {
let label = Label::new(&mut rng);
rsx!( Row { row_id: f, label: label } )
rsx!( table_row { row_id: f, label: label } )
})
}
}
)
))
}
#[derive(PartialEq, Props)]
@@ -31,9 +31,9 @@ struct RowProps {
row_id: usize,
label: Label,
}
fn Row(cx: Scope<RowProps>) -> Element {
fn table_row(cx: Scope<RowProps>) -> Element {
let [adj, col, noun] = cx.props.label.0;
render! {
cx.render(rsx! {
tr {
td { class:"col-md-1", "{cx.props.row_id}" }
td { class:"col-md-1", onclick: move |_| { /* run onselect */ },
@@ -46,7 +46,7 @@ fn Row(cx: Scope<RowProps>) -> Element {
}
td { class: "col-md-6" }
}
}
})
}
#[derive(PartialEq)]
+2 -2
View File
@@ -44,7 +44,7 @@ From anywhere in our app, we can read our the value of our atom:
```rust, ignore
fn NameCard(cx: Scope) -> Element {
let name = use_read(&cx, NAME);
let name = use_read(cx, NAME);
cx.render(rsx!{ h1 { "Hello, {name}"} })
}
```
@@ -53,7 +53,7 @@ We can also set the value of our atom, also from anywhere in our app:
```rust, ignore
fn NameCard(cx: Scope) -> Element {
let set_name = use_set(&cx, NAME);
let set_name = use_set(cx, NAME);
cx.render(rsx!{
button {
onclick: move |_| set_name("Fermi"),
+8 -8
View File
@@ -19,7 +19,7 @@ use std::{
/// static COUNT: Atom<u32> = |_| 0;
///
/// fn Example(cx: Scope) -> Element {
/// let mut count = use_atom_state(&cx, COUNT);
/// let mut count = use_atom_state(cx, COUNT);
///
/// cx.render(rsx! {
/// div {
@@ -74,7 +74,7 @@ impl<T: 'static> AtomState<T> {
///
/// ```rust, ignore
/// fn component(cx: Scope) -> Element {
/// let count = use_state(&cx, || 0);
/// let count = use_state(cx, || 0);
/// cx.spawn({
/// let set_count = count.to_owned();
/// async move {
@@ -101,7 +101,7 @@ impl<T: 'static> AtomState<T> {
///
/// ```rust, ignore
/// fn component(cx: Scope) -> Element {
/// let value = use_state(&cx, || 0);
/// let value = use_state(cx, || 0);
///
/// rsx!{
/// Component {
@@ -128,7 +128,7 @@ impl<T: 'static> AtomState<T> {
/// # use dioxus_core::prelude::*;
/// # use dioxus_hooks::*;
/// fn component(cx: Scope) -> Element {
/// let value = use_state(&cx, || 0);
/// let value = use_state(cx, || 0);
///
/// // to increment the value
/// value.modify(|v| v + 1);
@@ -168,7 +168,7 @@ impl<T: 'static> AtomState<T> {
/// # use dioxus_core::prelude::*;
/// # use dioxus_hooks::*;
/// fn component(cx: Scope) -> Element {
/// let value = use_state(&cx, || 0);
/// let value = use_state(cx, || 0);
///
/// let as_rc = value.get();
/// assert_eq!(as_rc.as_ref(), &0);
@@ -190,7 +190,7 @@ impl<T: 'static> AtomState<T> {
///
/// ```rust, ignore
/// fn component(cx: Scope) -> Element {
/// let count = use_state(&cx, || 0);
/// let count = use_state(cx, || 0);
/// cx.spawn({
/// let count = count.to_owned();
/// async move {
@@ -220,7 +220,7 @@ impl<T: Clone> AtomState<T> {
/// # Examples
///
/// ```ignore
/// let val = use_state(&cx, || 0);
/// let val = use_state(cx, || 0);
///
/// val.with_mut(|v| *v = 1);
/// ```
@@ -243,7 +243,7 @@ impl<T: Clone> AtomState<T> {
/// # Examples
///
/// ```ignore
/// let val = use_state(&cx, || 0);
/// let val = use_state(cx, || 0);
///
/// *val.make_mut() += 1;
/// ```
+2 -2
View File
@@ -15,8 +15,8 @@ You can always use it "normally" with the `split` method:
```rust
// Rusty-smart-pointer usage:
let value = use_state(&cx, || 10);
let value = use_state(cx, || 10);
// "Classic" usage:
let (value, set_value) = use_state(&cx, || 0).split();
let (value, set_value) = use_state(cx, || 0).split();
```
+3 -3
View File
@@ -5,7 +5,7 @@
///
///
/// ```ignore
/// let (data) = use_ref(&cx, || {});
/// let (data) = use_ref(cx, || {});
///
/// let handle_thing = move |_| {
/// to_owned![data]
@@ -30,8 +30,8 @@ pub use usestate::{use_state, UseState};
mod useref;
pub use useref::*;
// mod use_shared_state;
// pub use use_shared_state::*;
mod use_shared_state;
pub use use_shared_state::*;
mod usecoroutine;
pub use usecoroutine::*;
+3 -10
View File
@@ -60,10 +60,10 @@ impl<T> ProvidedStateInner<T> {
///
///
///
pub fn use_context<T: 'static>(cx: &ScopeState) -> Option<UseSharedState<T>> {
pub fn use_shared_state<T: 'static>(cx: &ScopeState) -> Option<UseSharedState<T>> {
let state = cx.use_hook(|| {
let scope_id = cx.scope_id();
let root = cx.consume_context::<ProvidedState<T>>().cloned();
let root = cx.consume_context::<ProvidedState<T>>();
if let Some(root) = root.as_ref() {
root.borrow_mut().consumers.insert(scope_id);
@@ -165,14 +165,7 @@ where
}
/// Provide some state for components down the hierarchy to consume without having to drill props.
///
///
///
///
///
///
///
pub fn use_context_provider<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) {
pub fn use_shared_state_provider<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) {
cx.use_hook(|| {
let state: ProvidedState<T> = Rc::new(RefCell::new(ProvidedStateInner {
value: Rc::new(RefCell::new(f())),
+1 -1
View File
@@ -16,7 +16,7 @@ This is moderately efficient because the fields of the map are moved, but the da
However, if you used similar approach with Dioxus:
```rust
let (map, set_map) = use_state(&cx, || HashMap::new());
let (map, set_map) = use_state(cx, || HashMap::new());
set_map({
let mut newmap = map.clone();
newmap.set(key, value);
+2
View File
@@ -1,6 +1,8 @@
use dioxus_core::ScopeState;
/// Consume some context in the tree, providing a sharable handle to the value
///
/// Does not regenerate the value if the value is changed at the parent.
pub fn use_context<T: 'static + Clone>(cx: &ScopeState) -> Option<&T> {
cx.use_hook(|| cx.consume_context::<T>()).as_ref()
}
+8 -9
View File
@@ -2,8 +2,6 @@ use dioxus_core::{ScopeState, TaskId};
pub use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
use std::future::Future;
use crate::{use_context, use_context_provider};
/// Maintain a handle over a future that can be paused, resumed, and canceled.
///
/// This is an upgraded form of [`use_future`] with an integrated channel system.
@@ -44,7 +42,7 @@ use crate::{use_context, use_context_provider};
/// Stop,
/// }
///
/// let chat_client = use_coroutine(&cx, |rx: UnboundedReceiver<Action>| async move {
/// let chat_client = use_coroutine(cx, |rx: UnboundedReceiver<Action>| async move {
/// while let Some(action) = rx.next().await {
/// match action {
/// Action::Start => {}
@@ -67,10 +65,10 @@ where
G: FnOnce(UnboundedReceiver<M>) -> F,
F: Future<Output = ()> + 'static,
{
use_context_provider(cx, || {
cx.use_hook(|| {
let (tx, rx) = futures_channel::mpsc::unbounded();
let task = cx.push_future(init(rx));
Coroutine { tx, task }
cx.provide_context(Coroutine { tx, task })
})
}
@@ -78,7 +76,8 @@ where
///
/// See the docs for [`use_coroutine`] for more details.
pub fn use_coroutine_handle<M: 'static>(cx: &ScopeState) -> Option<&Coroutine<M>> {
use_context::<Coroutine<M>>(cx)
cx.use_hook(|| cx.consume_context::<Coroutine<M>>())
.as_ref()
}
pub struct Coroutine<T> {
@@ -119,15 +118,15 @@ mod tests {
use futures_util::StreamExt;
fn app(cx: Scope, name: String) -> Element {
let task = use_coroutine(&cx, |mut rx: UnboundedReceiver<i32>| async move {
let task = use_coroutine(cx, |mut rx: UnboundedReceiver<i32>| async move {
while let Some(msg) = rx.next().await {
println!("got message: {}", msg);
}
});
let task2 = use_coroutine(&cx, view_task);
let task2 = use_coroutine(cx, view_task);
let task3 = use_coroutine(&cx, |rx| complex_task(rx, 10));
let task3 = use_coroutine(cx, |rx| complex_task(rx, 10));
todo!()
}
+4 -4
View File
@@ -17,7 +17,7 @@ use crate::UseFutureDep;
///
/// #[inline_props]
/// fn app(cx: Scope, name: &str) -> Element {
/// use_effect(&cx, (name,), |(name,)| async move {
/// use_effect(cx, (name,), |(name,)| async move {
/// set_title(name);
/// }))
/// }
@@ -72,17 +72,17 @@ mod tests {
fn app(cx: Scope<MyProps>) -> Element {
// should only ever run once
use_effect(&cx, (), |_| async move {
use_effect(cx, (), |_| async move {
//
});
// runs when a is changed
use_effect(&cx, (&cx.props.a,), |(a,)| async move {
use_effect(cx, (&cx.props.a,), |(a,)| async move {
//
});
// runs when a or b is changed
use_effect(&cx, (&cx.props.a, &cx.props.b), |(a, b)| async move {
use_effect(cx, (&cx.props.a, &cx.props.b), |(a, b)| async move {
//
});
+9 -9
View File
@@ -19,7 +19,7 @@ use std::{
///
/// ```ignore
/// const Example: Component = |cx| {
/// let count = use_state(&cx, || 0);
/// let count = use_state(cx, || 0);
///
/// cx.render(rsx! {
/// div {
@@ -92,7 +92,7 @@ impl<T: 'static> UseState<T> {
///
/// ```rust, ignore
/// fn component(cx: Scope) -> Element {
/// let count = use_state(&cx, || 0);
/// let count = use_state(cx, || 0);
/// cx.spawn({
/// let set_count = count.to_owned();
/// async move {
@@ -119,7 +119,7 @@ impl<T: 'static> UseState<T> {
///
/// ```rust, ignore
/// fn component(cx: Scope) -> Element {
/// let value = use_state(&cx, || 0);
/// let value = use_state(cx, || 0);
///
/// rsx!{
/// Component {
@@ -144,7 +144,7 @@ impl<T: 'static> UseState<T> {
/// # use dioxus_core::prelude::*;
/// # use dioxus_hooks::*;
/// fn component(cx: Scope) -> Element {
/// let value = use_state(&cx, || 0);
/// let value = use_state(cx, || 0);
///
/// // to increment the value
/// value.modify(|v| v + 1);
@@ -185,7 +185,7 @@ impl<T: 'static> UseState<T> {
/// # use dioxus_core::prelude::*;
/// # use dioxus_hooks::*;
/// fn component(cx: Scope) -> Element {
/// let value = use_state(&cx, || 0);
/// let value = use_state(cx, || 0);
///
/// let as_rc = value.get();
/// assert_eq!(as_rc.as_ref(), &0);
@@ -207,7 +207,7 @@ impl<T: 'static> UseState<T> {
///
/// ```rust, ignore
/// fn component(cx: Scope) -> Element {
/// let count = use_state(&cx, || 0);
/// let count = use_state(cx, || 0);
/// cx.spawn({
/// let count = count.to_owned();
/// async move {
@@ -237,7 +237,7 @@ impl<T: Clone> UseState<T> {
/// # Examples
///
/// ```rust, ignore
/// let val = use_state(&cx, || 0);
/// let val = use_state(cx, || 0);
///
/// val.with_mut(|v| *v = 1);
/// ```
@@ -269,7 +269,7 @@ impl<T: Clone> UseState<T> {
/// # Examples
///
/// ```rust, ignore
/// let val = use_state(&cx, || 0);
/// let val = use_state(cx, || 0);
///
/// *val.make_mut() += 1;
/// ```
@@ -448,7 +448,7 @@ impl<T: Div<Output = T> + Copy> std::ops::DivAssign<T> for UseState<T> {
fn api_makes_sense() {
#[allow(unused)]
fn app(cx: Scope) -> Element {
let val = use_state(&cx, || 0);
let val = use_state(cx, || 0);
val.set(0);
val.modify(|v| v + 1);
-3
View File
@@ -1,6 +1,3 @@
mod keys;
pub use keys::*;
macro_rules! impl_event {
(
$data:ty;
-370
View File
@@ -1,370 +0,0 @@
#[cfg_attr(
feature = "serialize",
derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u8)]
pub enum KeyCode {
// That key has no keycode, = 0
// break, = 3
// backspace / delete, = 8
// tab, = 9
// clear, = 12
// enter, = 13
// shift, = 16
// ctrl, = 17
// alt, = 18
// pause/break, = 19
// caps lock, = 20
// hangul, = 21
// hanja, = 25
// escape, = 27
// conversion, = 28
// non-conversion, = 29
// spacebar, = 32
// page up, = 33
// page down, = 34
// end, = 35
// home, = 36
// left arrow, = 37
// up arrow, = 38
// right arrow, = 39
// down arrow, = 40
// select, = 41
// print, = 42
// execute, = 43
// Print Screen, = 44
// insert, = 45
// delete, = 46
// help, = 47
// 0, = 48
// 1, = 49
// 2, = 50
// 3, = 51
// 4, = 52
// 5, = 53
// 6, = 54
// 7, = 55
// 8, = 56
// 9, = 57
// :, = 58
// semicolon (firefox), equals, = 59
// <, = 60
// equals (firefox), = 61
// ß, = 63
// @ (firefox), = 64
// a, = 65
// b, = 66
// c, = 67
// d, = 68
// e, = 69
// f, = 70
// g, = 71
// h, = 72
// i, = 73
// j, = 74
// k, = 75
// l, = 76
// m, = 77
// n, = 78
// o, = 79
// p, = 80
// q, = 81
// r, = 82
// s, = 83
// t, = 84
// u, = 85
// v, = 86
// w, = 87
// x, = 88
// y, = 89
// z, = 90
// Windows Key / Left ⌘ / Chromebook Search key, = 91
// right window key, = 92
// Windows Menu / Right ⌘, = 93
// sleep, = 95
// numpad 0, = 96
// numpad 1, = 97
// numpad 2, = 98
// numpad 3, = 99
// numpad 4, = 100
// numpad 5, = 101
// numpad 6, = 102
// numpad 7, = 103
// numpad 8, = 104
// numpad 9, = 105
// multiply, = 106
// add, = 107
// numpad period (firefox), = 108
// subtract, = 109
// decimal point, = 110
// divide, = 111
// f1, = 112
// f2, = 113
// f3, = 114
// f4, = 115
// f5, = 116
// f6, = 117
// f7, = 118
// f8, = 119
// f9, = 120
// f10, = 121
// f11, = 122
// f12, = 123
// f13, = 124
// f14, = 125
// f15, = 126
// f16, = 127
// f17, = 128
// f18, = 129
// f19, = 130
// f20, = 131
// f21, = 132
// f22, = 133
// f23, = 134
// f24, = 135
// f25, = 136
// f26, = 137
// f27, = 138
// f28, = 139
// f29, = 140
// f30, = 141
// f31, = 142
// f32, = 143
// num lock, = 144
// scroll lock, = 145
// airplane mode, = 151
// ^, = 160
// !, = 161
// ؛ (arabic semicolon), = 162
// #, = 163
// $, = 164
// ù, = 165
// page backward, = 166
// page forward, = 167
// refresh, = 168
// closing paren (AZERTY), = 169
// *, = 170
// ~ + * key, = 171
// home key, = 172
// minus (firefox), mute/unmute, = 173
// decrease volume level, = 174
// increase volume level, = 175
// next, = 176
// previous, = 177
// stop, = 178
// play/pause, = 179
// e-mail, = 180
// mute/unmute (firefox), = 181
// decrease volume level (firefox), = 182
// increase volume level (firefox), = 183
// semi-colon / ñ, = 186
// equal sign, = 187
// comma, = 188
// dash, = 189
// period, = 190
// forward slash / ç, = 191
// grave accent / ñ / æ / ö, = 192
// ?, / or °, = 193
// numpad period (chrome), = 194
// open bracket, = 219
// back slash, = 220
// close bracket / å, = 221
// single quote / ø / ä, = 222
// `, = 223
// left or right ⌘ key (firefox), = 224
// altgr, = 225
// < /git >, left back slash, = 226
// GNOME Compose Key, = 230
// ç, = 231
// XF86Forward, = 233
// XF86Back, = 234
// non-conversion, = 235
// alphanumeric, = 240
// hiragana/katakana, = 242
// half-width/full-width, = 243
// kanji, = 244
// unlock trackpad (Chrome/Edge), = 251
// toggle touchpad, = 255
NA = 0,
Break = 3,
Backspace = 8,
Tab = 9,
Clear = 12,
Enter = 13,
Shift = 16,
Ctrl = 17,
Alt = 18,
Pause = 19,
CapsLock = 20,
// hangul, = 21
// hanja, = 25
Escape = 27,
// conversion, = 28
// non-conversion, = 29
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
LeftArrow = 37,
UpArrow = 38,
RightArrow = 39,
DownArrow = 40,
// select, = 41
// print, = 42
// execute, = 43
// Print Screen, = 44
Insert = 45,
Delete = 46,
// help, = 47
Num0 = 48,
Num1 = 49,
Num2 = 50,
Num3 = 51,
Num4 = 52,
Num5 = 53,
Num6 = 54,
Num7 = 55,
Num8 = 56,
Num9 = 57,
// :, = 58
// semicolon (firefox), equals, = 59
// <, = 60
// equals (firefox), = 61
// ß, = 63
// @ (firefox), = 64
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftWindow = 91,
RightWindow = 92,
SelectKey = 93,
Numpad0 = 96,
Numpad1 = 97,
Numpad2 = 98,
Numpad3 = 99,
Numpad4 = 100,
Numpad5 = 101,
Numpad6 = 102,
Numpad7 = 103,
Numpad8 = 104,
Numpad9 = 105,
Multiply = 106,
Add = 107,
Subtract = 109,
DecimalPoint = 110,
Divide = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
// f13, = 124
// f14, = 125
// f15, = 126
// f16, = 127
// f17, = 128
// f18, = 129
// f19, = 130
// f20, = 131
// f21, = 132
// f22, = 133
// f23, = 134
// f24, = 135
// f25, = 136
// f26, = 137
// f27, = 138
// f28, = 139
// f29, = 140
// f30, = 141
// f31, = 142
// f32, = 143
NumLock = 144,
ScrollLock = 145,
// airplane mode, = 151
// ^, = 160
// !, = 161
// ؛ (arabic semicolon), = 162
// #, = 163
// $, = 164
// ù, = 165
// page backward, = 166
// page forward, = 167
// refresh, = 168
// closing paren (AZERTY), = 169
// *, = 170
// ~ + * key, = 171
// home key, = 172
// minus (firefox), mute/unmute, = 173
// decrease volume level, = 174
// increase volume level, = 175
// next, = 176
// previous, = 177
// stop, = 178
// play/pause, = 179
// e-mail, = 180
// mute/unmute (firefox), = 181
// decrease volume level (firefox), = 182
// increase volume level (firefox), = 183
Semicolon = 186,
EqualSign = 187,
Comma = 188,
Dash = 189,
Period = 190,
ForwardSlash = 191,
GraveAccent = 192,
// ?, / or °, = 193
// numpad period (chrome), = 194
OpenBracket = 219,
BackSlash = 220,
CloseBraket = 221,
SingleQuote = 222,
// `, = 223
// left or right ⌘ key (firefox), = 224
// altgr, = 225
// < /git >, left back slash, = 226
// GNOME Compose Key, = 230
// ç, = 231
// XF86Forward, = 233
// XF86Back, = 234
// non-conversion, = 235
// alphanumeric, = 240
// hiragana/katakana, = 242
// half-width/full-width, = 243
// kanji, = 244
// unlock trackpad (Chrome/Edge), = 251
// toggle touchpad, = 255
#[cfg_attr(feature = "serialize", serde(other))]
Unknown,
}
+2 -2
View File
@@ -2,7 +2,7 @@
use js_sys::Function;
use wasm_bindgen::prelude::*;
use web_sys::{Element, Node};
use web_sys::Element;
#[wasm_bindgen(module = "/src/interpreter.js")]
extern "C" {
@@ -18,7 +18,7 @@ extern "C" {
pub fn MountToRoot(this: &Interpreter);
#[wasm_bindgen(method)]
pub fn AppendChildren(this: &Interpreter, m: u32);
pub fn AppendChildren(this: &Interpreter, m: u32, id: u32);
#[wasm_bindgen(method)]
pub fn AssignId(this: &Interpreter, path: &[u8], id: u32);
+1 -1
View File
@@ -40,7 +40,7 @@ async fn order_shoes(mut req: WebsocketRequest) -> Response {
}
fn App(cx: Scope) -> Element {
let mut count = use_state(&cx, || 0);
let mut count = use_state(cx, || 0);
cx.render(rsx!(
button { onclick: move |_| count += 1, "Incr" }
button { onclick: move |_| count -= 1, "Decr" }
+2 -2
View File
@@ -6,7 +6,7 @@ use std::any::Any;
use std::sync::Arc;
use dioxus_core::ElementId;
use dioxus_html::event_bubbles;
// use dioxus_html::event_bubbles;
use dioxus_html::events::*;
#[derive(serde::Serialize, serde::Deserialize)]
@@ -29,7 +29,7 @@ struct ImEvent {
contents: serde_json::Value,
}
pub fn trigger_from_serialized(val: serde_json::Value) -> () {
pub fn trigger_from_serialized(_val: serde_json::Value) {
todo!()
// let ImEvent {
// event,
@@ -1,4 +1,3 @@
use anymap::AnyMap;
use dioxus::prelude::*;
use dioxus_native_core::node_ref::*;
use dioxus_native_core::real_dom::*;
@@ -1,10 +1,8 @@
use dioxus::core::ElementId;
use dioxus::core::{AttributeValue, Mutations};
use dioxus::prelude::*;
use dioxus_native_core::real_dom::*;
use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
use dioxus_native_core::tree::TreeView;
use dioxus_native_core::{node_ref::*, NodeId, RealNodeId, SendAnyMap};
use dioxus_native_core::{node_ref::*, NodeId, SendAnyMap};
use dioxus_native_core_macro::State;
#[derive(Debug, Clone, Default, State)]
+3 -1
View File
@@ -36,7 +36,9 @@ fn BlogList(cx: Scope) -> Element {
}
fn BlogPost(cx: Scope) -> Element {
let id = use_route(&cx).segment("id")?;
let Some(id) = use_route(cx).segment("id") else {
return cx.render(rsx! { div { "No blog post id" } })
};
log::trace!("rendering blog post {}", id);
+3 -3
View File
@@ -39,15 +39,15 @@ pub struct RouterProps<'a> {
/// Will fallback to HashRouter is BrowserRouter is not available, or through configuration.
#[allow(non_snake_case)]
pub fn Router<'a>(cx: Scope<'a, RouterProps<'a>>) -> Element {
let svc = use_context_provider(cx, || {
RouterService::new(
let svc = cx.use_hook(|| {
cx.provide_context(RouterService::new(
cx,
RouterCfg {
base_url: cx.props.base_url.map(|s| s.to_string()),
active_class: cx.props.active_class.map(|s| s.to_string()),
initial_url: cx.props.initial_url.clone(),
},
)
))
});
// next time we run the rout_found will be filled
+1 -1
View File
@@ -415,7 +415,7 @@ mod web {
}
}
fn attach_listeners(&self, svc: std::sync::Weak<crate::RouterService>) {
fn attach_listeners(&self, svc: std::rc::Weak<crate::RouterService>) {
self._listener.set(Some(EventListener::new(
&web_sys::window().unwrap(),
"popstate",
+6 -8
View File
@@ -13,13 +13,13 @@ fn simple_test() {
fn main() {
console_error_panic_hook::set_once();
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
dioxus_web::launch(APP);
dioxus_web::launch(app);
}
static APP: Component = |cx| {
fn app(cx: Scope) -> Element {
cx.render(rsx! {
Router {
onchange: move |route: RouterService| log::trace!("route changed to {:?}", route.current_location()),
onchange: move |router: RouterContext| log::trace!("route changed to {:?}", router.current_location()),
active_class: "is-active",
Route { to: "/", Home {} }
Route { to: "blog"
@@ -28,7 +28,7 @@ fn simple_test() {
}
}
})
};
}
fn Home(cx: Scope) -> Element {
cx.render(rsx! {
@@ -47,12 +47,10 @@ fn simple_test() {
}
fn BlogPost(cx: Scope) -> Element {
let _id = use_route(&cx).parse_segment::<usize>("id")?;
let _id = use_route(cx).parse_segment::<usize>("id").unwrap();
cx.render(rsx! {
div {
}
div { }
})
}
+4 -4
View File
@@ -89,7 +89,7 @@ You must provide a valid URL `{scheme}://{?authority}/{?path}`.
```rust
Router {
initial_url: "https://dioxuslab.com/blog", // Set the initial url.
initial_url: "https://dioxuslab.com/blog", // Set the initial url.
Link { to: "/", "Home" },
Link { to: "/blog", "Blog" }, // The router will render this route.
}
@@ -109,7 +109,7 @@ For any route, you can get a handle the current route with the `use_route` hook.
```rust
fn Title(cx: Scope) -> Element {
let route = use_route(&cx);
let route = use_route(cx);
assert_eq!(route.segments(), &["dogs", "breeds", "yorkie", "hugo"]);
@@ -130,7 +130,7 @@ Router {
}
fn BlogPost(cx: Scope) -> Element {
let route = use_route(&cx);
let route = use_route(cx);
match route.segment("post").and_then(parse) {
Some(post) => cx.render(rsx!{ div { "Post {post}" } })
@@ -168,7 +168,7 @@ Listeners can also be attached downstream in your app with the `RouteListener` h
```rust
fn TitleCard(cx: Scope) -> Element {
let (title, set_title) = use_state(&cx, || "First");
let (title, set_title) = use_state(cx, || "First");
cx.render(rsx!{
h1 { "render {title}" }
+4 -4
View File
@@ -192,16 +192,16 @@ impl ToTokens for Element {
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
pub enum ElementAttr {
/// attribute: "valuee {}"
/// `attribute: "value"`
AttrText { name: Ident, value: IfmtInput },
/// attribute: true,
/// `attribute: true`
AttrExpression { name: Ident, value: Expr },
/// "attribute": "value {}"
/// `"attribute": "value"`
CustomAttrText { name: LitStr, value: IfmtInput },
/// "attribute": true,
/// `"attribute": true`
CustomAttrExpression { name: LitStr, value: Expr },
// /// onclick: move |_| {}
+2 -2
View File
@@ -199,8 +199,8 @@ impl<'a> DynamicContext<'a> {
let value = value.source.as_ref().unwrap();
quote! {
::dioxus::core::TemplateAttribute::Static {
name: dioxus_elements::#el_name::#name.0,
namespace: dioxus_elements::#el_name::#name.1,
name: #name,
namespace: None,
value: #value,
// todo: we don't diff these so we never apply the volatile flag
+1
View File
@@ -1,6 +1,7 @@
use dioxus_core::prelude::*;
use std::fmt::Write;
#[derive(Debug)]
pub struct StringCache {
pub segments: Vec<Segment>,
pub template: Template<'static>,
+22 -19
View File
@@ -156,26 +156,29 @@ fn to_string_works() {
_ = dom.rebuild();
let mut renderer = Renderer::new();
let out = renderer.render(&dom);
use Segment::*;
assert_eq!(
renderer.template_cache.iter().next().unwrap().1.segments,
vec![
PreRendered("<div class=\"asdasdasd\" class=\"asdasdasd\"".into(),),
Attr(0,),
PreRendered(">Hello world 1 -->".into(),),
Node(0,),
PreRendered("<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),),
Node(1,),
Node(2,),
PreRendered("</div>".into(),),
]
);
for item in renderer.template_cache.iter() {
if item.1.segments.len() > 5 {
assert_eq!(
item.1.segments,
vec![
PreRendered("<div class=\"asdasdasd\" class=\"asdasdasd\"".into(),),
Attr(0,),
PreRendered(">Hello world 1 -->".into(),),
Node(0,),
PreRendered(
"<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),
),
Node(1,),
Node(2,),
PreRendered("</div>".into(),),
]
);
}
}
assert_eq!(
out,
"<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 --><!--#-->123<!--/#--><-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div><!--#--></diiiiiiiiv><!--/#--><div><!--#-->finalize 0<!--/#--></div><div><!--#-->finalize 1<!--/#--></div><div><!--#-->finalize 2<!--/#--></div><div><!--#-->finalize 3<!--/#--></div><div><!--#-->finalize 4<!--/#--></div></div>"
);
use Segment::*;
assert_eq!(out, "<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 -->123<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div></diiiiiiiiv><div>finalize 0</div><div>finalize 1</div><div>finalize 2</div><div>finalize 3</div><div>finalize 4</div></div>");
}
+3 -3
View File
@@ -41,7 +41,7 @@ struct BoxProps {
}
#[allow(non_snake_case)]
fn Box(cx: Scope<BoxProps>) -> Element {
let count = use_state(&cx, || 0);
let count = use_state(cx, || 0);
let x = cx.props.x * 2;
let y = cx.props.y * 2;
@@ -70,8 +70,8 @@ struct GridProps {
#[allow(non_snake_case)]
fn Grid(cx: Scope<GridProps>) -> Element {
let size = cx.props.size;
let count = use_state(&cx, || 0);
let counts = use_ref(&cx, || vec![0; size * size]);
let count = use_state(cx, || 0);
let counts = use_ref(cx, || vec![0; size * size]);
let ctx: &TuiContext = cx.consume_context().unwrap();
if *count.get() + 1 >= (size * size) {
+1 -1
View File
@@ -27,7 +27,7 @@ enum Event {
const MAX_EVENTS: usize = 8;
fn app(cx: Scope) -> Element {
let events = use_ref(&cx, Vec::new);
let events = use_ref(cx, Vec::new);
let events_lock = events.read();
let first_index = events_lock.len().saturating_sub(MAX_EVENTS);
+1 -1
View File
@@ -5,7 +5,7 @@ fn main() {
}
fn app(cx: Scope) -> Element {
let radius = use_state(&cx, || 0);
let radius = use_state(cx, || 0);
cx.render(rsx! {
div {
+2 -2
View File
@@ -13,8 +13,8 @@ struct ButtonProps {
#[allow(non_snake_case)]
fn Button(cx: Scope<ButtonProps>) -> Element {
let toggle = use_state(&cx, || false);
let hovered = use_state(&cx, || false);
let toggle = use_state(cx, || false);
let hovered = use_state(cx, || false);
let hue = cx.props.color_offset % 255;
let saturation = if *toggle.get() { 50 } else { 25 } + if *hovered.get() { 50 } else { 25 };
+2 -2
View File
@@ -8,8 +8,8 @@ fn main() {
}
fn app(cx: Scope) -> Element {
let hue = use_state(&cx, || 0.0);
let brightness = use_state(&cx, || 0.0);
let hue = use_state(cx, || 0.0);
let brightness = use_state(cx, || 0.0);
let tui_query: &Query = cx.consume_context().unwrap();
// disable templates so that every node has an id and can be queried
cx.render(rsx! {
+9 -9
View File
@@ -1,7 +1,7 @@
use dioxus::{events::MouseData, prelude::*};
use dioxus_core::Event;
use std::convert::TryInto;
use std::rc::Rc;
use std::{convert::TryInto, sync::Arc};
fn main() {
dioxus_tui::launch(app);
@@ -17,20 +17,20 @@ fn app(cx: Scope) -> Element {
127 * b
}
let q1_color = use_state(&cx, || [200; 3]);
let q2_color = use_state(&cx, || [200; 3]);
let q3_color = use_state(&cx, || [200; 3]);
let q4_color = use_state(&cx, || [200; 3]);
let q1_color = use_state(cx, || [200; 3]);
let q2_color = use_state(cx, || [200; 3]);
let q3_color = use_state(cx, || [200; 3]);
let q4_color = use_state(cx, || [200; 3]);
let q1_color_str = to_str(q1_color);
let q2_color_str = to_str(q2_color);
let q3_color_str = to_str(q3_color);
let q4_color_str = to_str(q4_color);
let page_coordinates = use_state(&cx, || "".to_string());
let element_coordinates = use_state(&cx, || "".to_string());
let buttons = use_state(&cx, || "".to_string());
let modifiers = use_state(&cx, || "".to_string());
let page_coordinates = use_state(cx, || "".to_string());
let element_coordinates = use_state(cx, || "".to_string());
let buttons = use_state(cx, || "".to_string());
let modifiers = use_state(cx, || "".to_string());
let update_data = move |event: Event<MouseData>| {
let mouse_data = event.inner();
+2 -2
View File
@@ -5,9 +5,9 @@ fn main() {
}
fn app(cx: Scope) -> Element {
let count = use_state(&cx, || 0);
let count = use_state(cx, || 0);
use_future(&cx, (), move |_| {
use_future(cx, (), move |_| {
let count = count.to_owned();
let update = cx.schedule_update();
async move {
+1 -1
View File
@@ -5,7 +5,7 @@ fn main() {
}
fn app(cx: Scope) -> Element {
let alpha = use_state(&cx, || 100);
let alpha = use_state(cx, || 100);
cx.render(rsx! {
div {
+2 -2
View File
@@ -26,8 +26,8 @@ use crate::{layout_to_screen_space, TuiDom};
/// }
///
/// fn app(cx: Scope) -> Element {
/// let hue = use_state(&cx, || 0.0);
/// let brightness = use_state(&cx, || 0.0);
/// let hue = use_state(cx, || 0.0);
/// let brightness = use_state(cx, || 0.0);
/// let tui_query: Query = cx.consume_context().unwrap();
/// cx.render(rsx! {
/// div{
+9 -9
View File
@@ -33,7 +33,7 @@ fn key_down() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -70,7 +70,7 @@ fn mouse_down() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -104,7 +104,7 @@ fn mouse_up() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -143,7 +143,7 @@ fn mouse_enter() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -182,7 +182,7 @@ fn mouse_exit() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -221,7 +221,7 @@ fn mouse_move() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -260,7 +260,7 @@ fn wheel() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -300,7 +300,7 @@ fn click() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
@@ -339,7 +339,7 @@ fn context_menu() {
dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
fn app(cx: Scope) -> Element {
let render_count = use_state(&cx, || 0);
let render_count = use_state(cx, || 0);
let tui_ctx: TuiContext = cx.consume_context().unwrap();
let render_count_handle = render_count.clone();
cx.spawn(async move {
-91
View File
@@ -1,91 +0,0 @@
#[test]
fn margin_and_flex_row() {
let mut taffy = taffy::Taffy::new();
let node0 = taffy
.new_node(
taffy::style::Style {
flex_grow: 1f32,
margin: taffy::geometry::Rect {
start: taffy::style::Dimension::Points(10f32),
end: taffy::style::Dimension::Points(10f32),
..Default::default()
},
..Default::default()
},
&[],
)
.unwrap();
let node = taffy
.new_node(
taffy::style::Style {
size: taffy::geometry::Size {
width: taffy::style::Dimension::Points(100f32),
height: taffy::style::Dimension::Points(100f32),
},
..Default::default()
},
&[node0],
)
.unwrap();
taffy
.compute_layout(node, taffy::geometry::Size::undefined())
.unwrap();
assert_eq!(taffy.layout(node).unwrap().size.width, 100f32);
assert_eq!(taffy.layout(node).unwrap().size.height, 100f32);
assert_eq!(taffy.layout(node).unwrap().location.x, 0f32);
assert_eq!(taffy.layout(node).unwrap().location.y, 0f32);
assert_eq!(taffy.layout(node0).unwrap().size.width, 80f32);
assert_eq!(taffy.layout(node0).unwrap().size.height, 100f32);
assert_eq!(taffy.layout(node0).unwrap().location.x, 10f32);
assert_eq!(taffy.layout(node0).unwrap().location.y, 0f32);
}
#[test]
fn margin_and_flex_row2() {
let mut taffy = taffy::Taffy::new();
let node0 = taffy
.new_node(
taffy::style::Style {
flex_grow: 1f32,
margin: taffy::geometry::Rect {
// left
start: taffy::style::Dimension::Points(10f32),
// right?
end: taffy::style::Dimension::Points(10f32),
// top?
// top: taffy::style::Dimension::Points(10f32),
// bottom?
// bottom: taffy::style::Dimension::Points(10f32),
..Default::default()
},
..Default::default()
},
&[],
)
.unwrap();
let node = taffy
.new_node(
taffy::style::Style {
size: taffy::geometry::Size {
width: taffy::style::Dimension::Points(100f32),
height: taffy::style::Dimension::Points(100f32),
},
..Default::default()
},
&[node0],
)
.unwrap();
taffy
.compute_layout(node, taffy::geometry::Size::undefined())
.unwrap();
assert_eq!(taffy.layout(node).unwrap().size.width, 100f32);
assert_eq!(taffy.layout(node).unwrap().size.height, 100f32);
assert_eq!(taffy.layout(node).unwrap().location.x, 0f32);
assert_eq!(taffy.layout(node).unwrap().location.y, 0f32);
}
+1 -1
View File
@@ -48,7 +48,7 @@ fn main() {
let mut dom = VirtualDom::new(app);
let _ = dom.rebuild();
let pre = dioxus_ssr::pre_render_vdom(&dom);
let pre = dioxus_ssr::pre_render(&dom);
log::trace!("{}", pre);
// set the inner content of main to the pre-rendered content
+1 -1
View File
@@ -155,7 +155,7 @@ impl WebsysDom {
i.set_attribute(id.0 as u32, name, if *value { "true" } else { "false" }, "")
}
SetText { value, id } => i.set_text(id.0 as u32, value),
NewEventListener { name, scope: _, id } => {
NewEventListener { name, id, .. } => {
i.new_event_listener(name, id.0 as u32, event_bubbles(&name[2..]) as u8);
}
RemoveEventListener { name, id } => {
-8
View File
@@ -53,8 +53,6 @@
// - Do the VDOM work during the idlecallback
// - Do DOM work in the next requestAnimationFrame callback
pub use crate::cfg::Config;
use crate::dom::virtual_event_from_websys_event;
pub use crate::util::use_eval;
@@ -62,7 +60,6 @@ use dioxus_core::{Element, ElementId, Scope, VirtualDom};
use futures_util::{pin_mut, FutureExt, StreamExt};
mod cache;
mod cfg;
mod dom;
@@ -193,8 +190,6 @@ pub async fn run_with_props<T: 'static>(root: fn(Scope<T>) -> Element, root_prop
// } else {
let edits = dom.rebuild();
log::debug!("Initial edits {:#?}", edits);
websys_dom.load_templates(&edits.templates);
websys_dom.apply_edits(edits.edits);
@@ -216,7 +211,6 @@ pub async fn run_with_props<T: 'static>(root: fn(Scope<T>) -> Element, root_prop
_ = work => None,
_new_template = hotreload_rx.next() => {
todo!("Implement hot reload");
None
}
evt = rx.next() => evt
}
@@ -252,8 +246,6 @@ pub async fn run_with_props<T: 'static>(root: fn(Scope<T>) -> Element, root_prop
// wait for the animation frame to fire so we can apply our changes
// work_loop.wait_for_raf().await;
log::debug!("edits {:#?}", edits);
websys_dom.load_templates(&edits.templates);
websys_dom.apply_edits(edits.edits);
}
+1 -1
View File
@@ -50,7 +50,7 @@ fn rehydrates() {
let mut dom = VirtualDom::new(app);
let _ = dom.rebuild();
let out = dioxus_ssr::render_vdom_cfg(&dom, Default::default());
let out = dioxus_ssr::render(&dom);
window()
.unwrap()