wip: start moving events to rc<event>
This commit is contained in:
1 parent
9222d8ece3
commit
b9ff95fa12
21 files changed
+249
-605
No files matched your search
@@ -45,81 +45,3 @@ impl Render for Button {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// #[fc]
|
||||
// fn Button(ctx: Context, onhover: Option<&dyn Fn()>) -> VNode {}
|
||||
|
||||
// h1 {
|
||||
// tag: "type", abc: 123, class: "big small wide short",
|
||||
// "title1"
|
||||
// "title1"
|
||||
// "title1"
|
||||
// "title"
|
||||
// }
|
||||
|
||||
// h1 ("title") {
|
||||
// tag: "type",
|
||||
// abc: 123,
|
||||
// class: "big small wide short",
|
||||
// }
|
||||
|
||||
// // <button
|
||||
// // class="inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
|
||||
// // onclick={move |_| set_name("jill")}
|
||||
// // onclick={move |_| set_name("jill")}
|
||||
// // >
|
||||
// // "Jill!"
|
||||
// // </button>
|
||||
|
||||
// button { "Jill!",
|
||||
// class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
|
||||
// onclick: move |_| set_name("jill"),
|
||||
// onclick: move |_| set_name("jill"),
|
||||
// }
|
||||
|
||||
// button {
|
||||
// class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
|
||||
// onclick: move |_| set_name("jill"),
|
||||
// onclick: move |_| set_name("jill"),
|
||||
// // this is valid
|
||||
// "Jill!",
|
||||
// // this is also valid
|
||||
// {"Jill!"}
|
||||
// }
|
||||
|
||||
// h1 { "Text", class: "inline-block py-4 px-8 mr-6 leading-none" }
|
||||
|
||||
// // <h1 class="inline-block py-4 px-8 mr-6 leading-none">
|
||||
// // "Text"
|
||||
// // </h1>
|
||||
|
||||
// h1 {
|
||||
// div {
|
||||
// h1 {}
|
||||
// h2 {}
|
||||
// Brick {}
|
||||
|
||||
// p {}
|
||||
// p {
|
||||
// tag: "type",
|
||||
// abc: 123,
|
||||
// enabled: true,
|
||||
// class: "big small wide short",
|
||||
|
||||
// a { "abcder" },
|
||||
// h2 { "whatsup", class: "abc-123" },
|
||||
// CustomComponent { a: 123, b: 456, key: "1" },
|
||||
// }
|
||||
|
||||
// div { class: "big small wide short",
|
||||
// div {},
|
||||
// div {},
|
||||
// div {},
|
||||
// div {},
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// h2 {}
|
||||
// h3 {}
|
||||
// "abcd123"
|
||||
+46
-97
@@ -1,9 +1,8 @@
|
||||
//! Virtual Events
|
||||
//! This module provides a wrapping of platform-specific events with a list of events easier to work with.
|
||||
//! 3rd party renderers are responsible for forming this virtual events from events.
|
||||
//! The goal here is to provide a consistent event interface across all renderer types.
|
||||
//! This module provides a set of common events for all Dioxus apps to target, regardless of host platform.
|
||||
//! -------------------------------------------------------------------------------------------------------
|
||||
//!
|
||||
//! also... websys integerates poorly with rust analyzer, so we handle that for you automatically.
|
||||
//! 3rd party renderers are responsible for converting their native events into these virtual event types. Events might
|
||||
//! be heavy or need to interact through FFI, so the events themselves are designed to be lazy.
|
||||
|
||||
use crate::innerlude::ScopeIdx;
|
||||
|
||||
@@ -46,15 +45,13 @@ pub enum VirtualEvent {
|
||||
MouseEvent(on::MouseEvent),
|
||||
PointerEvent(on::PointerEvent),
|
||||
|
||||
// todo
|
||||
|
||||
// ImageEvent(event_data::ImageEvent),
|
||||
OtherEvent,
|
||||
}
|
||||
|
||||
pub mod on {
|
||||
#![allow(unused)]
|
||||
use std::ops::Deref;
|
||||
use std::{ops::Deref, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
builder::ElementBuilder,
|
||||
@@ -64,15 +61,10 @@ pub mod on {
|
||||
|
||||
use super::VirtualEvent;
|
||||
|
||||
macro_rules! event_builder {
|
||||
(
|
||||
$eventdata:ident;
|
||||
macro_rules! event_directory {
|
||||
( $( $eventdata:ident: [ $( $name:ident )* ]; )* ) => {
|
||||
$(
|
||||
$(#[$attr:meta])*
|
||||
$name:ident
|
||||
)* ) => {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
pub fn $name<'a>(
|
||||
c: &'_ NodeCtx<'a>,
|
||||
callback: impl Fn($eventdata) + 'a,
|
||||
@@ -84,41 +76,61 @@ pub mod on {
|
||||
scope: c.scope_ref.arena_idx,
|
||||
callback: bump.alloc(move |evt: VirtualEvent| match evt {
|
||||
VirtualEvent::$eventdata(event) => callback(event),
|
||||
_ => {
|
||||
unreachable!("Downcasted VirtualEvent to wrong event type - this is a bug!")
|
||||
}
|
||||
_ => unreachable!("Downcasted VirtualEvent to wrong event type - this is an internal bug!")
|
||||
}),
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
event_directory! {
|
||||
ClipboardEvent: [copy cut paste];
|
||||
CompositionEvent: [compositionend compositionstart compositionupdate];
|
||||
KeyboardEvent: [keydown keypress keyup];
|
||||
FocusEvent: [focus blur];
|
||||
FormEvent: [change input invalid reset submit];
|
||||
GenericEvent: [];
|
||||
MouseEvent: [
|
||||
click contextmenu doubleclick drag dragend dragenter dragexit
|
||||
dragleave dragover dragstart drop mousedown mouseenter mouseleave
|
||||
mousemove mouseout mouseover mouseup
|
||||
];
|
||||
PointerEvent: [
|
||||
pointerdown pointermove pointerup pointercancel gotpointercapture
|
||||
lostpointercapture pointerenter pointerleave pointerover pointerout
|
||||
];
|
||||
SelectionEvent: [select];
|
||||
TouchEvent: [touchcancel touchend touchmove touchstart];
|
||||
UIEvent: [scroll];
|
||||
WheelEvent: [wheel];
|
||||
MediaEvent: [
|
||||
abort canplay canplaythrough durationchange emptied encrypted
|
||||
ended error loadeddata loadedmetadata loadstart pause play
|
||||
playing progress ratechange seeked seeking stalled suspend
|
||||
timeupdate volumechange waiting
|
||||
];
|
||||
AnimationEvent: [animationstart animationend animationiteration];
|
||||
TransitionEvent: [transitionend];
|
||||
ToggleEvent: [toggle];
|
||||
}
|
||||
|
||||
pub struct GetModifierKey(pub Box<dyn Fn(usize) -> bool>);
|
||||
impl std::fmt::Debug for GetModifierKey {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// just skip for now
|
||||
Ok(())
|
||||
Ok(()) // just skip for now
|
||||
}
|
||||
}
|
||||
|
||||
// DOMDataTransfer clipboardData
|
||||
#[derive(Debug)]
|
||||
pub struct ClipboardEvent {}
|
||||
event_builder! {
|
||||
ClipboardEvent;
|
||||
copy cut paste
|
||||
}
|
||||
|
||||
// string data
|
||||
#[derive(Debug)]
|
||||
pub struct CompositionEvent {
|
||||
data: String,
|
||||
}
|
||||
event_builder! {
|
||||
CompositionEvent;
|
||||
compositionend compositionstart compositionupdate
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KeyboardEvent {
|
||||
@@ -134,12 +146,11 @@ pub mod on {
|
||||
which: usize,
|
||||
get_modifier_state: GetModifierKey,
|
||||
}
|
||||
pub struct KeyboardEvent2(pub Box<dyn KeyboardEventT>);
|
||||
pub struct KeyboardEvent2(pub Rc<dyn KeyboardEventT>);
|
||||
impl std::ops::Deref for KeyboardEvent2 {
|
||||
type Target = Box<dyn KeyboardEventT>;
|
||||
|
||||
type Target = dyn KeyboardEventT;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,32 +168,16 @@ pub mod on {
|
||||
fn get_modifier_state(&self) -> GetModifierKey;
|
||||
}
|
||||
|
||||
event_builder! {
|
||||
KeyboardEvent;
|
||||
keydown keypress keyup
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FocusEvent {/* DOMEventTarget relatedTarget */}
|
||||
event_builder! {
|
||||
FocusEvent;
|
||||
focus blur
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FormEvent {
|
||||
pub value: String,
|
||||
}
|
||||
event_builder! {
|
||||
FormEvent;
|
||||
change input invalid reset submit
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GenericEvent {/* Error Load */}
|
||||
event_builder! {
|
||||
GenericEvent;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MouseEvent(pub Box<RawMouseEvent>);
|
||||
@@ -210,12 +205,6 @@ pub mod on {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
event_builder! {
|
||||
MouseEvent;
|
||||
click contextmenu doubleclick drag dragend dragenter dragexit
|
||||
dragleave dragover dragstart drop mousedown mouseenter mouseleave
|
||||
mousemove mouseout mouseover mouseup
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PointerEvent(Box<RawPointerEvent>);
|
||||
@@ -255,18 +244,9 @@ pub mod on {
|
||||
pointer_type: String,
|
||||
is_primary: bool,
|
||||
}
|
||||
event_builder! {
|
||||
PointerEvent;
|
||||
pointerdown pointermove pointerup pointercancel gotpointercapture
|
||||
lostpointercapture pointerenter pointerleave pointerover pointerout
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SelectionEvent {}
|
||||
event_builder! {
|
||||
SelectionEvent;
|
||||
select
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TouchEvent {
|
||||
@@ -282,20 +262,12 @@ pub mod on {
|
||||
// touches: DOMTouchList,
|
||||
// getModifierState(key): boolean
|
||||
}
|
||||
event_builder! {
|
||||
TouchEvent;
|
||||
touchcancel touchend touchmove touchstart
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UIEvent {
|
||||
// DOMAbstractView view
|
||||
detail: i32,
|
||||
}
|
||||
event_builder! {
|
||||
UIEvent;
|
||||
scroll
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WheelEvent {
|
||||
@@ -304,20 +276,9 @@ pub mod on {
|
||||
delta_y: i32,
|
||||
delta_z: i32,
|
||||
}
|
||||
event_builder! {
|
||||
WheelEvent;
|
||||
wheel
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MediaEvent {}
|
||||
event_builder! {
|
||||
MediaEvent;
|
||||
abort canplay canplaythrough durationchange emptied encrypted
|
||||
ended error loadeddata loadedmetadata loadstart pause play
|
||||
playing progress ratechange seeked seeking stalled suspend
|
||||
timeupdate volumechange waiting
|
||||
}
|
||||
|
||||
// todo!
|
||||
// imageevent clashes with media event
|
||||
@@ -336,10 +297,6 @@ pub mod on {
|
||||
pseudo_element: String,
|
||||
elapsed_time: f32,
|
||||
}
|
||||
event_builder! {
|
||||
AnimationEvent;
|
||||
animationstart animationend animationiteration
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TransitionEvent {
|
||||
@@ -347,15 +304,7 @@ pub mod on {
|
||||
pseudo_element: String,
|
||||
elapsed_time: f32,
|
||||
}
|
||||
event_builder! {
|
||||
TransitionEvent;
|
||||
transitionend
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ToggleEvent {}
|
||||
event_builder! {
|
||||
ToggleEvent;
|
||||
toggle
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,7 @@ impl VirtualDom {
|
||||
// Now, there are events in the queue
|
||||
let mut updates = self.event_queue.0.as_ref().borrow_mut();
|
||||
|
||||
// Order the nodes by their height, we want the biggest nodes on the top
|
||||
// Order the nodes by their height, we want the nodes with the smallest depth on top
|
||||
// This prevents us from running the same component multiple times
|
||||
updates.sort_unstable();
|
||||
|
||||
@@ -300,6 +300,7 @@ impl VirtualDom {
|
||||
// let cur_component = inner.get_mut(update.idx).unwrap();
|
||||
|
||||
cur_component.run_scope()?;
|
||||
// diff_machine.change_list.load_known_root(1);
|
||||
|
||||
diff_machine.diff_node(cur_component.old_frame(), cur_component.next_frame());
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "dioxus-inputs"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Cross-platform controlled inputs
|
||||
|
||||
Dioxus does not include controlled inputs in Dioxus-Core. This would require core integration with HTML that is inherently not cross platform. Instead, this crate exists to provide a bunch of cross-platform input types that abstract over renderer quirks.
|
||||
|
||||
Included is:
|
||||
|
||||
- Button
|
||||
- Checkbox
|
||||
- Color
|
||||
- Date
|
||||
- Datetime-local
|
||||
- Email
|
||||
- File
|
||||
- Hidden
|
||||
- Image
|
||||
- Month
|
||||
- Number
|
||||
- Password
|
||||
- Radio
|
||||
- Range
|
||||
- Reset
|
||||
- Search
|
||||
- Submit
|
||||
- Tel
|
||||
- Text
|
||||
- Time
|
||||
- Url
|
||||
- Week
|
||||
@@ -0,0 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,12 @@ version = "0.3.50"
|
||||
features = [
|
||||
"Comment",
|
||||
"Document",
|
||||
# "DataTransfer",
|
||||
"Element",
|
||||
"HtmlElement",
|
||||
"HtmlInputElement",
|
||||
"HtmlSelectElement",
|
||||
"HtmlTextAreaElement",
|
||||
"EventTarget",
|
||||
"HtmlCollection",
|
||||
"Node",
|
||||
@@ -60,6 +63,7 @@ features = [
|
||||
"DocumentType",
|
||||
"CharacterData",
|
||||
"HtmlOptionElement",
|
||||
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_web::WebsysRenderer;
|
||||
|
||||
fn main() {
|
||||
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
log::info!("hello world");
|
||||
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
|
||||
}
|
||||
|
||||
static App: FC<()> = |ctx| {
|
||||
let (val, set_val) = use_state(&ctx, || "asd".to_string());
|
||||
|
||||
ctx.render(rsx! {
|
||||
div { class: "max-w-lg max-w-xs bg-blue-800 shadow-2xl rounded-lg mx-auto text-center py-12 mt-4 rounded-xl"
|
||||
div { class: "container py-5 max-w-md mx-auto"
|
||||
h1 { class: "text-gray-200 text-center font-extrabold -mt-3 text-3xl",
|
||||
"Text Input Example"
|
||||
}
|
||||
div { class: "mb-4"
|
||||
input {
|
||||
placeholder: "Username"
|
||||
class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
|
||||
id: "username"
|
||||
type: "text"
|
||||
value: "{val}"
|
||||
oninput: move |evet| {
|
||||
log::debug!("Value is {:#?}", evet);
|
||||
set_val(evet.value);
|
||||
}
|
||||
}
|
||||
p { "Val is: {val}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
static Example: FC<()> = |ctx| {
|
||||
ctx.render(rsx! {
|
||||
div { class: "max-w-lg max-w-xs bg-blue-800 shadow-2xl rounded-lg mx-auto text-center py-12 mt-4 rounded-xl"
|
||||
div { class: "container py-5 max-w-md mx-auto"
|
||||
h1 { class: "text-gray-200 text-center font-extrabold -mt-3 text-3xl",
|
||||
"Text Input Example"
|
||||
}
|
||||
UserInput {}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
static UserInput: FC<()> = |ctx| {
|
||||
let (val, set_val) = use_state(&ctx, || "asd".to_string());
|
||||
|
||||
rsx!{ in ctx,
|
||||
div { class: "mb-4"
|
||||
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"
|
||||
id: "username"
|
||||
type: "text"
|
||||
oninput: move |evet| {
|
||||
log::debug!("Value is {:#?}", evet);
|
||||
set_val(evet.value);
|
||||
}
|
||||
}
|
||||
p { "Val is: {val}" }
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -7,7 +7,9 @@ use dioxus_core::{
|
||||
};
|
||||
use fxhash::FxHashMap;
|
||||
use wasm_bindgen::{closure::Closure, JsCast};
|
||||
use web_sys::{window, Document, Element, Event, HtmlInputElement, HtmlOptionElement, Node};
|
||||
use web_sys::{
|
||||
window, Document, Element, Event, HtmlElement, HtmlInputElement, HtmlOptionElement, Node,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct CacheId(u32);
|
||||
@@ -564,11 +566,38 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
|
||||
todo!()
|
||||
}
|
||||
|
||||
"change" | "input" | "invalid" | "reset" | "submit" => {
|
||||
"change" => {
|
||||
let evt: web_sys::Event = event.clone().dyn_into().expect("wrong error typ");
|
||||
todo!()
|
||||
// VirtualEvent::FormEvent(FormEvent {value:})
|
||||
}
|
||||
|
||||
"input" | "invalid" | "reset" | "submit" => {
|
||||
// is a special react events
|
||||
let evt: web_sys::InputEvent = event.clone().dyn_into().expect("wrong event type");
|
||||
let value: Option<String> = (&evt).data();
|
||||
let value = value.unwrap_or_default();
|
||||
let this: web_sys::EventTarget = evt.target().unwrap();
|
||||
|
||||
let value = (&this)
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlInputElement| input.value())
|
||||
.or_else(|| {
|
||||
(&this)
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlTextAreaElement| input.value())
|
||||
})
|
||||
.or_else(|| {
|
||||
(&this)
|
||||
.dyn_ref::<web_sys::HtmlElement>()
|
||||
.unwrap()
|
||||
.text_content()
|
||||
})
|
||||
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
|
||||
|
||||
// let p2 = evt.data_transfer();
|
||||
|
||||
// let value: Option<String> = (&evt).data();
|
||||
// let value = val;
|
||||
// let value = value.unwrap_or_default();
|
||||
// let value = (&evt).data().expect("No data to unwrap");
|
||||
|
||||
// todo - this needs to be a "controlled" event
|
||||
|
||||
Reference in new issue
Block a user