wip: docs and router
This commit is contained in:
1 parent
8bf57dc21d
commit
a5f05d73ac
50 files changed
+1263
-234
No files matched your search
+20
-2
@@ -11,10 +11,17 @@ license = "MIT/Apache-2.0"
|
||||
dioxus-core = { path = "../core", version = "0.1.2" }
|
||||
dioxus-html = { path = "../html" }
|
||||
js-sys = "0.3"
|
||||
# wasm-bindgen-shared = { path = "../../../Tinkering/wasm-bindgen/crates/shared" }
|
||||
# wasm-bindgen-macro-support = { path = "../../../Tinkering/wasm-bindgen/crates/macro-support" }
|
||||
# wasm-bindgen = { features = [
|
||||
|
||||
|
||||
wasm-bindgen = { version = "0.2.78", features = ["enable-interning"] }
|
||||
# wasm-bindgen = { version = "0.2.78", features = ["enable-interning"] }
|
||||
# wasm-bindgen = { version = "0.2.78", features = ["enable-interning"] }
|
||||
lazy_static = "1.4.0"
|
||||
wasm-bindgen-futures = "0.4.20"
|
||||
log = "0.4.14"
|
||||
log = { version = "0.4.14", features = ["release_max_level_off"] }
|
||||
fxhash = "0.2.1"
|
||||
wasm-logger = "0.2.0"
|
||||
console_error_panic_hook = "0.1.6"
|
||||
@@ -24,6 +31,11 @@ async-channel = "1.6.1"
|
||||
anyhow = "1.0"
|
||||
gloo-timers = { version = "0.2.1", features = ["futures"] }
|
||||
futures-util = "0.3.15"
|
||||
smallstr = "0.2.0"
|
||||
|
||||
[patch.crates-io]
|
||||
wasm-bindgen = { path = "../../../Tinkering/wasm-bindgen/" }
|
||||
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.51"
|
||||
@@ -65,6 +77,7 @@ features = [
|
||||
"IdleDeadline",
|
||||
]
|
||||
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
@@ -76,7 +89,12 @@ serde = { version = "1.0.126", features = ["derive"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
dioxus-hooks = { path = "../hooks" }
|
||||
dioxus-core-macro = { path = "../core-macro" }
|
||||
# rand = { version="0.8.4", features=["small_rng"] }
|
||||
rand = { version = "0.8.4", features = ["small_rng"] }
|
||||
|
||||
[dev-dependencies.getrandom]
|
||||
version = "0.2"
|
||||
features = ["js"]
|
||||
|
||||
# surf = { version = "2.3.1", default-features = false, features = [
|
||||
# "wasm-client",
|
||||
# ] }
|
||||
@@ -0,0 +1,243 @@
|
||||
use std::cell::Cell;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core_macro::*;
|
||||
use dioxus_hooks::{use_ref, use_state};
|
||||
use dioxus_html as dioxus_elements;
|
||||
use dioxus_web;
|
||||
use gloo_timers::future::TimeoutFuture;
|
||||
use rand::prelude::*;
|
||||
|
||||
fn main() {
|
||||
console_error_panic_hook::set_once();
|
||||
if cfg!(debug_assertions) {
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
log::debug!("hello world");
|
||||
}
|
||||
|
||||
for a in ADJECTIVES {
|
||||
wasm_bindgen::intern(*a);
|
||||
}
|
||||
for a in COLOURS {
|
||||
wasm_bindgen::intern(*a);
|
||||
}
|
||||
for a in NOUNS {
|
||||
wasm_bindgen::intern(*a);
|
||||
}
|
||||
for a in [
|
||||
"container",
|
||||
"jumbotron",
|
||||
"row",
|
||||
"Dioxus",
|
||||
"col-md-6",
|
||||
"col-md-1",
|
||||
"Create 1,000 rows",
|
||||
"run",
|
||||
"Create 10,000 rows",
|
||||
"runlots",
|
||||
"Append 1,000 rows",
|
||||
"add",
|
||||
"Update every 10th row",
|
||||
"update",
|
||||
"Clear",
|
||||
"clear",
|
||||
"Swap rows",
|
||||
"swaprows",
|
||||
"preloadicon glyphicon glyphicon-remove", //
|
||||
"aria-hidden",
|
||||
"onclick",
|
||||
"true",
|
||||
"false",
|
||||
"danger",
|
||||
"type",
|
||||
"id",
|
||||
"class",
|
||||
"glyphicon glyphicon-remove remove",
|
||||
"dioxus-id",
|
||||
"dioxus-event-click",
|
||||
"dioxus",
|
||||
"click",
|
||||
"1.10",
|
||||
"lbl",
|
||||
"remove",
|
||||
"dioxus-event",
|
||||
"col-sm-6 smallpad",
|
||||
"btn btn-primary btn-block",
|
||||
"",
|
||||
" ",
|
||||
] {
|
||||
wasm_bindgen::intern(a);
|
||||
}
|
||||
for x in 0..100_000 {
|
||||
wasm_bindgen::intern(&x.to_string());
|
||||
}
|
||||
|
||||
dioxus_web::launch(App, |c| c.rootname("main"));
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy)]
|
||||
struct Label {
|
||||
key: usize,
|
||||
labels: [&'static str; 3],
|
||||
}
|
||||
|
||||
static mut Counter: Cell<usize> = Cell::new(1);
|
||||
|
||||
impl Label {
|
||||
fn new_list(num: usize) -> Vec<Self> {
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
let mut labels = Vec::with_capacity(num);
|
||||
|
||||
let offset = unsafe { Counter.get() };
|
||||
unsafe { Counter.set(offset + num) };
|
||||
|
||||
for k in offset..(offset + num) {
|
||||
labels.push(Label {
|
||||
key: k,
|
||||
labels: [
|
||||
ADJECTIVES.choose(&mut rng).unwrap(),
|
||||
COLOURS.choose(&mut rng).unwrap(),
|
||||
NOUNS.choose(&mut rng).unwrap(),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
labels
|
||||
}
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, _props| {
|
||||
let mut items = use_ref(cx, || vec![]);
|
||||
let mut selected = use_state(cx, || None);
|
||||
|
||||
cx.render(rsx! {
|
||||
div { class: "container"
|
||||
div { class: "jumbotron"
|
||||
div { class: "row"
|
||||
div { class: "col-md-6", h1 { "Dioxus" } }
|
||||
div { class: "col-md-6"
|
||||
div { class: "row"
|
||||
ActionButton { name: "Create 1,000 rows", id: "run",
|
||||
onclick: move || items.set(Label::new_list(1_000)),
|
||||
}
|
||||
ActionButton { name: "Create 10,000 rows", id: "runlots",
|
||||
onclick: move || items.set(Label::new_list(10_000)),
|
||||
}
|
||||
ActionButton { name: "Append 1,000 rows", id: "add",
|
||||
onclick: move || items.write().extend(Label::new_list(1_000)),
|
||||
}
|
||||
ActionButton { name: "Update every 10th row", id: "update",
|
||||
onclick: move || items.write().iter_mut().step_by(10).for_each(|item| item.labels[2] = "!!!"),
|
||||
}
|
||||
ActionButton { name: "Clear", id: "clear",
|
||||
onclick: move || items.write().clear(),
|
||||
}
|
||||
ActionButton { name: "Swap Rows", id: "swaprows",
|
||||
onclick: move || items.write().swap(0, 998),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
table { class: "table table-hover table-striped test-data"
|
||||
tbody { id: "tbody"
|
||||
{items.read().iter().enumerate().map(|(id, item)| {
|
||||
let [adj, col, noun] = item.labels;
|
||||
let is_in_danger = if (*selected).map(|s| s == id).unwrap_or(false) {"danger"} else {""};
|
||||
rsx!(tr {
|
||||
class: "{is_in_danger}",
|
||||
key: "{id}",
|
||||
td { class:"col-md-1" }
|
||||
td { class:"col-md-1", "{item.key}" }
|
||||
td { class:"col-md-1", onclick: move |_| selected.set(Some(id)),
|
||||
a { class: "lbl", "{adj} {col} {noun}" }
|
||||
}
|
||||
td { class: "col-md-1"
|
||||
a { class: "remove", onclick: move |_| { items.write().remove(id); },
|
||||
span { class: "glyphicon glyphicon-remove remove" aria_hidden: "true" }
|
||||
}
|
||||
}
|
||||
td { class: "col-md-6" }
|
||||
})
|
||||
})}
|
||||
}
|
||||
}
|
||||
span { class: "preloadicon glyphicon glyphicon-remove" aria_hidden: "true" }
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
#[derive(Props)]
|
||||
struct ActionButtonProps<'a> {
|
||||
name: &'static str,
|
||||
id: &'static str,
|
||||
onclick: &'a dyn Fn(),
|
||||
}
|
||||
|
||||
fn ActionButton(cx: Context, props: &ActionButtonProps) -> Element {
|
||||
rsx!(cx, div { class: "col-sm-6 smallpad"
|
||||
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: move |_| (props.onclick)(),
|
||||
"{props.name}"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static ADJECTIVES: &[&str] = &[
|
||||
"pretty",
|
||||
"large",
|
||||
"big",
|
||||
"small",
|
||||
"tall",
|
||||
"short",
|
||||
"long",
|
||||
"handsome",
|
||||
"plain",
|
||||
"quaint",
|
||||
"clean",
|
||||
"elegant",
|
||||
"easy",
|
||||
"angry",
|
||||
"crazy",
|
||||
"helpful",
|
||||
"mushy",
|
||||
"odd",
|
||||
"unsightly",
|
||||
"adorable",
|
||||
"important",
|
||||
"inexpensive",
|
||||
"cheap",
|
||||
"expensive",
|
||||
"fancy",
|
||||
];
|
||||
|
||||
static COLOURS: &[&str] = &[
|
||||
"red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black",
|
||||
"orange",
|
||||
];
|
||||
|
||||
static NOUNS: &[&str] = &[
|
||||
"table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger",
|
||||
"pizza", "mouse", "keyboard",
|
||||
];
|
||||
|
||||
// #[derive(PartialEq, Props)]
|
||||
// struct RowProps<'a> {
|
||||
// row_id: usize,
|
||||
// label: &'a Label,
|
||||
// }
|
||||
|
||||
// fn Row(cx: Context, props: &RowProps) -> Element {
|
||||
// rsx!(cx, tr {
|
||||
// td { class:"col-md-1", "{props.row_id}" }
|
||||
// td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
|
||||
// a { class: "lbl", {props.label.labels} }
|
||||
// }
|
||||
// td { class: "col-md-1"
|
||||
// a { class: "remove", onclick: move |_| {/* remove */}
|
||||
// span { class: "glyphicon glyphicon-remove remove" aria_hidden: "true" }
|
||||
// }
|
||||
// }
|
||||
// td { class: "col-md-6" }
|
||||
// })
|
||||
// }
|
||||
@@ -0,0 +1,46 @@
|
||||
//! Example: README.md showcase
|
||||
//!
|
||||
//! The example from the README.md.
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core_macro::*;
|
||||
use dioxus_hooks::use_state;
|
||||
use dioxus_html as dioxus_elements;
|
||||
use dioxus_web;
|
||||
use gloo_timers::future::TimeoutFuture;
|
||||
|
||||
fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
dioxus_web::launch(App, |c| c);
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
let show = use_state(cx, || true);
|
||||
|
||||
let inner = match *show {
|
||||
true => {
|
||||
rsx!( div {
|
||||
"hello world"
|
||||
})
|
||||
}
|
||||
false => {
|
||||
rsx!( div {
|
||||
// h1 {
|
||||
"bello world"
|
||||
// }
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
rsx!(cx, div {
|
||||
button {
|
||||
"toggle"
|
||||
onclick: move |_| {
|
||||
let cur = *show;
|
||||
show.set(!cur);
|
||||
}
|
||||
}
|
||||
{inner}
|
||||
})
|
||||
};
|
||||
@@ -7,6 +7,11 @@
|
||||
/// Eventually we might want to procedurally generate these strings for common words, phrases, and values.
|
||||
pub(crate) fn intern_cached_strings() {
|
||||
let cached_words = [
|
||||
// Important tags to dioxus
|
||||
"dioxus-id",
|
||||
"dioxus",
|
||||
"dioxus-event-click", // todo: more events
|
||||
"click",
|
||||
// All the HTML Tags
|
||||
"a",
|
||||
"abbr",
|
||||
|
||||
@@ -17,7 +17,7 @@ impl Default for WebConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
hydrate: false,
|
||||
rootname: "dioxusroot".to_string(),
|
||||
rootname: "main".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-23
@@ -213,7 +213,7 @@ impl WebsysDom {
|
||||
|
||||
fn create_placeholder(&mut self, id: u64) {
|
||||
self.create_element("pre", None, id);
|
||||
// self.set_attribute("hidden", "", None);
|
||||
self.set_attribute("hidden", "", None, id);
|
||||
}
|
||||
|
||||
fn create_text_node(&mut self, text: &str, id: u64) {
|
||||
@@ -246,8 +246,15 @@ impl WebsysDom {
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
use smallstr;
|
||||
use smallstr::SmallString;
|
||||
use std::fmt::Write;
|
||||
|
||||
let mut s: SmallString<[u8; 8]> = smallstr::SmallString::new();
|
||||
write!(s, "{}", id).unwrap();
|
||||
|
||||
let el2 = el.dyn_ref::<Element>().unwrap();
|
||||
el2.set_attribute("dioxus-id", &format!("{}", id)).unwrap();
|
||||
el2.set_attribute("dioxus-id", s.as_str()).unwrap();
|
||||
|
||||
self.stack.push(el.clone());
|
||||
self.nodes[(id as usize)] = Some(el);
|
||||
@@ -263,18 +270,21 @@ impl WebsysDom {
|
||||
|
||||
let el = self.stack.top();
|
||||
|
||||
let el = el
|
||||
.dyn_ref::<Element>()
|
||||
.expect(&format!("not an element: {:?}", el));
|
||||
let el = el.dyn_ref::<Element>().unwrap();
|
||||
// let el = el.dyn_ref::<Element>().unwrap();
|
||||
// .expect(&format!("not an element: {:?}", el));
|
||||
|
||||
// let scope_id = scope.data().as_ffi();
|
||||
let scope_id = scope.0 as u64;
|
||||
// let scope_id = scope.0 as u64;
|
||||
// "dioxus-event-click",
|
||||
// "1.10"
|
||||
// &format!("", scope_id, real_id),
|
||||
// &format!("dioxus-event-{}", event),
|
||||
// &format!("{}.{}", scope_id, real_id),
|
||||
// &format!("dioxus-event-{}", event),
|
||||
// &format!("{}.{}", scope_id, real_id),
|
||||
|
||||
el.set_attribute(
|
||||
&format!("dioxus-event-{}", event),
|
||||
&format!("{}.{}", scope_id, real_id),
|
||||
)
|
||||
.unwrap();
|
||||
el.set_attribute("dioxus-event", event).unwrap();
|
||||
|
||||
// el.set_attribute(&format!("dioxus-event"), &format!("{}", event))
|
||||
// .unwrap();
|
||||
@@ -488,6 +498,8 @@ unsafe impl Sync for DioxusWebsysEvent {}
|
||||
fn virtual_event_from_websys_event(event: web_sys::Event) -> Arc<dyn Any + Send + Sync> {
|
||||
use dioxus_html::on::*;
|
||||
use dioxus_html::KeyCode;
|
||||
// event.prevent_default();
|
||||
|
||||
// use dioxus_core::events::on::*;
|
||||
match event.type_().as_str() {
|
||||
"copy" | "cut" | "paste" => Arc::new(ClipboardEvent {}),
|
||||
@@ -682,30 +694,40 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<UserEvent> {
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
let element_id = target
|
||||
.get_attribute("dioxus-id")
|
||||
.context("Could not find element id on event target")?
|
||||
.parse()?;
|
||||
|
||||
// The error handling here is not very descriptive and needs to be replaced with a zero-cost error system
|
||||
let val: String = target
|
||||
.get_attribute(&format!("dioxus-event-{}", typ))
|
||||
.get_attribute("dioxus-event")
|
||||
.context(format!("wrong format - received {:#?}", typ))?;
|
||||
// .get_attribute(&format!("dioxus-event-{}", typ))
|
||||
// .context(format!("wrong format - received {:#?}", typ))?;
|
||||
|
||||
let mut fields = val.splitn(3, ".");
|
||||
|
||||
let gi_id = fields
|
||||
.next()
|
||||
.and_then(|f| f.parse::<u64>().ok())
|
||||
.context("failed to parse gi id")?;
|
||||
// let gi_id = fields
|
||||
// .next()
|
||||
// .and_then(|f| f.parse::<u64>().ok())
|
||||
// .context("failed to parse gi id")?;
|
||||
|
||||
let real_id = fields
|
||||
.next()
|
||||
.and_then(|raw_id| raw_id.parse::<u64>().ok())
|
||||
.context("failed to parse real id")?;
|
||||
// let real_id = fields
|
||||
// .next()
|
||||
// .and_then(|raw_id| raw_id.parse::<u64>().ok())
|
||||
// .context("failed to parse real id")?;
|
||||
|
||||
let triggered_scope = gi_id;
|
||||
// let triggered_scope = gi_id;
|
||||
|
||||
Ok(UserEvent {
|
||||
name: event_name_from_typ(&typ),
|
||||
data: virtual_event_from_websys_event(event.clone()),
|
||||
element: Some(ElementId(real_id as usize)),
|
||||
scope_id: Some(ScopeId(triggered_scope as usize)),
|
||||
element: Some(ElementId(element_id)),
|
||||
scope_id: None,
|
||||
// scope_id: Some(ScopeId(triggered_scope as usize)),
|
||||
// element: Some(ElementId(real_id as usize)),
|
||||
// scope_id: Some(ScopeId(triggered_scope as usize)),
|
||||
priority: dioxus_core::EventPriority::Medium,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ mod ric_raf;
|
||||
/// dioxus_web::launch(App, |c| c);
|
||||
/// }
|
||||
///
|
||||
/// static App: FC<()> = |(cx, props)| {
|
||||
/// static App: FC<()> = |cx, props| {
|
||||
/// rsx!(cx, div {"hello world"})
|
||||
/// }
|
||||
/// ```
|
||||
@@ -109,7 +109,7 @@ pub fn launch(root_component: FC<()>, configuration: impl FnOnce(WebConfig) -> W
|
||||
/// name: String
|
||||
/// }
|
||||
///
|
||||
/// static App: FC<RootProps> = |(cx, props)| {
|
||||
/// static App: FC<RootProps> = |cx, props| {
|
||||
/// rsx!(cx, div {"hello {props.name}"})
|
||||
/// }
|
||||
/// ```
|
||||
@@ -155,7 +155,7 @@ pub async fn run_with_props<T: 'static + Send>(root: FC<T>, root_props: T, cfg:
|
||||
// hydrating is simply running the dom for a single render. If the page is already written, then the corresponding
|
||||
// ElementIds should already line up because the web_sys dom has already loaded elements with the DioxusID into memory
|
||||
if !should_hydrate {
|
||||
log::info!("Applying rebuild edits..., {:?}", mutations);
|
||||
// log::info!("Applying rebuild edits..., {:?}", mutations);
|
||||
websys_dom.process_edits(&mut mutations.edits);
|
||||
}
|
||||
|
||||
@@ -166,17 +166,20 @@ pub async fn run_with_props<T: 'static + Send>(root: FC<T>, root_props: T, cfg:
|
||||
// if there is work then this future resolves immediately.
|
||||
dom.wait_for_work().await;
|
||||
|
||||
// wait for the mainthread to schedule us in
|
||||
let mut deadline = work_loop.wait_for_idle_time().await;
|
||||
// // wait for the mainthread to schedule us in
|
||||
// let mut deadline = work_loop.wait_for_idle_time().await;
|
||||
|
||||
// run the virtualdom work phase until the frame deadline is reached
|
||||
let mutations = dom.work_with_deadline(|| (&mut deadline).now_or_never().is_some());
|
||||
let mutations = dom.work_with_deadline(|| false);
|
||||
// // run the virtualdom work phase until the frame deadline is reached
|
||||
// let mutations = dom.work_with_deadline(|| (&mut deadline).now_or_never().is_some());
|
||||
|
||||
// wait for the animation frame to fire so we can apply our changes
|
||||
work_loop.wait_for_raf().await;
|
||||
|
||||
for mut edit in mutations {
|
||||
// actually apply our changes during the animation frame
|
||||
// log::info!("Applying change edits..., {:?}", edit);
|
||||
websys_dom.process_edits(&mut edit.edits);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user