dioxus_html/events/generated.rs
1use super::*;
2
3#[doc(hidden)]
4#[macro_export]
5macro_rules! with_html_event_groups {
6 ($macro:ident) => {
7 $macro! {
8 enum Event {
9 #[convert = convert_animation_data]
10 #[events = [
11 onanimationstart => animationstart,
12 onanimationend => animationend,
13 onanimationiteration => animationiteration,
14 ]]
15 Animation(AnimationData),
16
17 #[convert = convert_before_input_data]
18 #[events = [
19 /// The `beforeinput` event fires before an editable element (an `<input>`,
20 /// `<textarea>`, or any element with `contenteditable="true"`) is about to
21 /// be modified. Unlike `oninput`, this event is cancellable — calling
22 /// `event.prevent_default()` from the handler blocks the change.
23 ///
24 /// Use [`BeforeInputData::input_type`] to identify the kind of mutation
25 /// (e.g. [`InputType::InsertText`], [`InputType::DeleteContentBackward`],
26 /// [`InputType::InsertFromPaste`]) and [`BeforeInputData::data`] to read
27 /// the text being inserted.
28 ///
29 /// ```rust
30 /// use dioxus::prelude::*;
31 ///
32 /// fn App() -> Element {
33 /// rsx! {
34 /// input {
35 /// onbeforeinput: move |event| {
36 /// // Block any attempt to insert a digit
37 /// if event.data.input_type() == InputType::InsertText
38 /// && event.data.data().is_some_and(|d| d.chars().any(|c| c.is_ascii_digit()))
39 /// {
40 /// event.prevent_default();
41 /// }
42 /// }
43 /// }
44 /// }
45 /// }
46 /// ```
47 ///
48 /// See <https://developer.mozilla.org/en-US/docs/Web/API/Element/beforeinput_event>.
49 onbeforeinput => beforeinput,
50 ]]
51 BeforeInput(BeforeInputData),
52
53 #[convert = convert_cancel_data]
54 #[events = [
55 oncancel => cancel,
56 ]]
57 Cancel(CancelData),
58
59 #[convert = convert_clipboard_data]
60 #[events = [
61 oncopy => copy,
62 oncut => cut,
63 onpaste => paste,
64 ]]
65 Clipboard(ClipboardData),
66
67 #[convert = convert_composition_data]
68 #[events = [
69 oncompositionstart => compositionstart,
70 oncompositionend => compositionend,
71 oncompositionupdate => compositionupdate,
72 ]]
73 Composition(CompositionData),
74
75 #[convert = convert_drag_data]
76 #[events = [
77 ondrag => drag,
78 ondragend => dragend,
79 ondragenter => dragenter,
80 ondragexit => dragexit,
81 ondragleave => dragleave,
82 ondragover => dragover,
83 ondragstart => dragstart,
84 ondrop => drop,
85 ]]
86 Drag(DragData),
87
88 #[convert = convert_focus_data]
89 #[events = [
90 onfocus => focus,
91 onfocusout => focusout,
92 onfocusin => focusin,
93 onblur => blur,
94 ]]
95 Focus(FocusData),
96
97 #[convert = convert_form_data]
98 #[events = [
99 onchange => change,
100 /// The `oninput` event is fired when the value of a `<input>`, `<select>`, or `<textarea>` element is changed.
101 ///
102 /// There are two main approaches to updating your input element:
103 /// 1) Controlled inputs directly update the value of the input element as the user interacts with the element
104 ///
105 /// ```rust
106 /// use dioxus::prelude::*;
107 ///
108 /// fn App() -> Element {
109 /// let mut value = use_signal(|| "hello world".to_string());
110 ///
111 /// rsx! {
112 /// input {
113 /// value: "{value}",
114 /// oninput: move |event| value.set(event.value())
115 /// }
116 /// button {
117 /// onclick: move |_| value.write().clear(),
118 /// "Clear"
119 /// }
120 /// }
121 /// }
122 /// ```
123 ///
124 /// 2) Uncontrolled inputs just read the value of the input element as it changes
125 ///
126 /// ```rust
127 /// use dioxus::prelude::*;
128 ///
129 /// fn App() -> Element {
130 /// rsx! {
131 /// input {
132 /// oninput: move |event| println!("{}", event.value()),
133 /// }
134 /// }
135 /// }
136 /// ```
137 oninput => input,
138 oninvalid => invalid,
139 onreset => reset,
140 onsubmit => submit,
141 ]]
142 Form(FormData),
143
144 #[convert = convert_image_data]
145 #[events = [
146 onerror => error,
147 onload => load,
148 ]]
149 Image(ImageData),
150
151 #[convert = convert_keyboard_data]
152 #[events = [
153 onkeydown => keydown,
154 onkeypress => keypress,
155 onkeyup => keyup,
156 ]]
157 Keyboard(KeyboardData),
158
159 #[convert = convert_media_data]
160 #[events = [
161 onabort => abort,
162 oncanplay => canplay,
163 oncanplaythrough => canplaythrough,
164 ondurationchange => durationchange,
165 onemptied => emptied,
166 onencrypted => encrypted,
167 onended => ended,
168 onloadeddata => loadeddata,
169 onloadedmetadata => loadedmetadata,
170 onloadstart => loadstart,
171 onpause => pause,
172 onplay => play,
173 onplaying => playing,
174 onprogress => progress,
175 onratechange => ratechange,
176 onseeked => seeked,
177 onseeking => seeking,
178 onstalled => stalled,
179 onsuspend => suspend,
180 ontimeupdate => timeupdate,
181 onvolumechange => volumechange,
182 onwaiting => waiting,
183 ]]
184 #[raw = [interruptbegin, interruptend, loadend, timeout]]
185 Media(MediaData),
186
187 #[convert = convert_mounted_data]
188 #[events = [
189 #[doc(alias = "ref")]
190 #[doc(alias = "createRef")]
191 #[doc(alias = "useRef")]
192 /// The onmounted event is fired when the element is first added to the DOM. This event gives you a [`MountedData`] object and lets you interact with the raw DOM element.
193 ///
194 /// This event is fired once per element. If you need to access the element multiple times, you can store the [`MountedData`] object in a [`use_signal`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_signal.html) hook and use it as needed.
195 ///
196 /// # Examples
197 ///
198 /// ```rust, no_run
199 /// # use dioxus::prelude::*;
200 /// fn App() -> Element {
201 /// let mut header_element = use_signal(|| None);
202 ///
203 /// rsx! {
204 /// div {
205 /// h1 {
206 /// // The onmounted event will run the first time the h1 element is mounted
207 /// onmounted: move |element| header_element.set(Some(element.data())),
208 /// "Scroll to top example"
209 /// }
210 ///
211 /// for i in 0..100 {
212 /// div { "Item {i}" }
213 /// }
214 ///
215 /// button {
216 /// // When you click the button, if the header element has been mounted, we scroll to that element
217 /// onclick: move |_| async move {
218 /// if let Some(header) = header_element.cloned() {
219 /// let _ = header.scroll_to(ScrollBehavior::Smooth).await;
220 /// }
221 /// },
222 /// "Scroll to top"
223 /// }
224 /// }
225 /// }
226 /// }
227 /// ```
228 ///
229 /// The `MountedData` struct contains cross platform APIs that work on the desktop, mobile, liveview and web platforms. For the web platform, you can also downcast the `MountedData` event to the `web-sys::Element` type for more web specific APIs:
230 ///
231 /// ```rust, ignore
232 /// use dioxus::prelude::*;
233 /// use dioxus_web::WebEventExt; // provides [`as_web_event()`] method
234 ///
235 /// fn App() -> Element {
236 /// rsx! {
237 /// div {
238 /// id: "some-id",
239 /// onmounted: move |element| {
240 /// // You can use the web_event trait to downcast the element to a web specific event. For the mounted event, this will be a web_sys::Element
241 /// let web_sys_element = element.as_web_event();
242 /// assert_eq!(web_sys_element.id(), "some-id");
243 /// }
244 /// }
245 /// }
246 /// }
247 /// ```
248 onmounted => mounted,
249 ]]
250 Mounted(MountedData),
251
252 #[convert = convert_mouse_data]
253 #[events = [
254 /// Execute a callback when a button is clicked.
255 ///
256 /// ## Description
257 ///
258 /// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
259 /// is both pressed and released while the pointer is located inside the element.
260 ///
261 /// - Bubbles: Yes
262 /// - Cancelable: Yes
263 /// - Interface(InteData): [`MouseEvent`]
264 ///
265 /// If the button is pressed on one element and the pointer is moved outside the element before the button
266 /// is released, the event is fired on the most specific ancestor element that contained both elements.
267 /// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
268 ///
269 /// ## Example
270 /// ```rust, ignore
271 /// rsx!( button { onclick: move |_| tracing::info!("Clicked!"), "click me" } )
272 /// ```
273 ///
274 /// ## Reference
275 /// - <https://www.w3schools.com/tags/ev_onclick.asp>
276 /// - <https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event>
277 onclick => click,
278 oncontextmenu => contextmenu,
279 #[deprecated(since = "0.5.0", note = "use ondoubleclick instead")]
280 ondblclick => dblclick,
281 #[doc(alias = "ondblclick")]
282 ondoubleclick => dblclick,
283 onmousedown => mousedown,
284 onmouseenter => mouseenter,
285 onmouseleave => mouseleave,
286 onmousemove => mousemove,
287 onmouseout => mouseout,
288 /// Triggered when the users's mouse hovers over an element.
289 onmouseover => mouseover,
290 onmouseup => mouseup,
291 ]]
292 #[raw = [doubleclick]]
293 Mouse(MouseData),
294
295 #[convert = convert_pointer_data]
296 #[events = [
297 onpointerdown => pointerdown,
298 onpointermove => pointermove,
299 onpointerup => pointerup,
300 onpointercancel => pointercancel,
301 ongotpointercapture => gotpointercapture,
302 onlostpointercapture => lostpointercapture,
303 onpointerenter => pointerenter,
304 onpointerleave => pointerleave,
305 onpointerover => pointerover,
306 onpointerout => pointerout,
307 onauxclick => auxclick,
308 ]]
309 #[raw = [pointerlockchange, pointerlockerror]]
310 Pointer(PointerData),
311
312 #[convert = convert_resize_data]
313 #[events = [
314 onresize => resize,
315 ]]
316 Resize(ResizeData),
317
318 #[convert = convert_scroll_data]
319 #[events = [
320 onscroll => scroll,
321 onscrollend => scrollend,
322 ]]
323 Scroll(ScrollData),
324
325 #[convert = convert_selection_data]
326 #[events = [
327 onselect => select,
328 onselectstart => selectstart,
329 onselectionchange => selectionchange,
330 ]]
331 Selection(SelectionData),
332
333 #[convert = convert_toggle_data]
334 #[events = [
335 ontoggle => toggle,
336 onbeforetoggle => beforetoggle,
337 ]]
338 Toggle(ToggleData),
339
340 #[convert = convert_touch_data]
341 #[events = [
342 ontouchstart => touchstart,
343 ontouchmove => touchmove,
344 ontouchend => touchend,
345 ontouchcancel => touchcancel,
346 ]]
347 Touch(TouchData),
348
349 #[convert = convert_transition_data]
350 #[events = [
351 ontransitionend => transitionend,
352 ]]
353 Transition(TransitionData),
354
355 #[convert = convert_visible_data]
356 #[events = [
357 onvisible => visible,
358 ]]
359 Visible(VisibleData),
360
361 #[convert = convert_wheel_data]
362 #[events = [
363 /// Called when the mouse wheel is rotated over an element.
364 onwheel => wheel,
365 ]]
366 Wheel(WheelData),
367 }
368 }
369 };
370}
371
372macro_rules! expand_html_event_converter {
373 (
374 enum Event {
375 $(
376 #[convert = $converter:ident]
377 #[events = [
378 $(
379 $( #[$attr:meta] )*
380 $name:ident => $raw:ident,
381 )*
382 ]]
383 $(#[raw = [$($raw_only:ident),* $(,)?]])?
384 $group:ident($data:ident),
385 )*
386 }
387 ) => {
388 /// A converter between a platform specific event and a general event. All code in a renderer that has a large binary size should be placed in this trait. Each of these functions should be snipped in high levels of optimization.
389 pub trait HtmlEventConverter: Send + Sync {
390 $(
391 fn $converter(&self, event: &PlatformEventData) -> $data;
392 )*
393 }
394
395 $(
396 impl From<&PlatformEventData> for $data {
397 fn from(val: &PlatformEventData) -> Self {
398 with_event_converter(|c| c.$converter(val))
399 }
400 }
401 )*
402 };
403}
404
405#[cfg(feature = "serialize")]
406macro_rules! expand_html_event_deserialize {
407 (
408 enum Event {
409 $(
410 #[convert = $converter:ident]
411 #[events = [
412 $(
413 $( #[$attr:meta] )*
414 $name:ident => $raw:ident,
415 )*
416 ]]
417 $(#[raw = [$($raw_only:ident),* $(,)?]])?
418 $group:ident($data:ident),
419 )*
420 }
421 ) => {
422 pub(crate) fn deserialize_raw_event(
423 name: &str,
424 data: &serde_json::Value,
425 ) -> Result<Option<crate::transit::EventData>, serde_json::Error> {
426 #[inline]
427 fn de<'de, F>(f: &'de serde_json::Value) -> Result<F, serde_json::Error>
428 where
429 F: serde::Deserialize<'de>,
430 {
431 F::deserialize(f)
432 }
433
434 Ok(match name {
435 $(
436 $( stringify!($raw) )|* $($(| stringify!($raw_only))*)? => {
437 Some(expand_html_event_deserialize!(@deserialize $group, data))
438 }
439 )*
440 _ => None,
441 })
442 }
443 };
444 (@deserialize Mounted, $data:ident) => {
445 crate::transit::EventData::Mounted
446 };
447 (@deserialize $group:ident, $data:ident) => {
448 crate::transit::EventData::$group(de($data)?)
449 };
450}
451
452macro_rules! expand_html_event_listeners {
453 (
454 enum Event {
455 $(
456 #[convert = $converter:ident]
457 #[events = [
458 $(
459 $( #[$attr:meta] )*
460 $name:ident => $raw:ident,
461 )*
462 ]]
463 $(#[raw = [$($raw_only:ident),* $(,)?]])?
464 $group:ident($data:ident),
465 )*
466 }
467 ) => {
468 $(
469 impl_event! {
470 $data;
471 $(
472 #[doc = concat!(stringify!($name))]
473 $( #[$attr] )*
474 $name: concat!("on", stringify!($raw));
475 )*
476 }
477 )*
478 };
479}
480
481with_html_event_groups!(expand_html_event_converter);
482#[cfg(feature = "serialize")]
483with_html_event_groups!(expand_html_event_deserialize);
484with_html_event_groups!(expand_html_event_listeners);