1#[cfg(feature = "suspense")]
4use sycamore_futures::spawn_local_scoped;
5use wasm_bindgen::JsCast;
6pub use web_sys::{
7 AnimationEvent, BeforeUnloadEvent, CompositionEvent, DeviceMotionEvent, DeviceOrientationEvent,
8 DragEvent, ErrorEvent, Event, FocusEvent, GamepadEvent, HashChangeEvent, InputEvent,
9 KeyboardEvent, MessageEvent, MouseEvent, PageTransitionEvent, PointerEvent, PopStateEvent,
10 ProgressEvent, PromiseRejectionEvent, SecurityPolicyViolationEvent, StorageEvent, SubmitEvent,
11 TouchEvent, TransitionEvent, UiEvent, WheelEvent,
12};
13
14pub trait EventDescriptor {
16 type EventTy: Into<Event> + JsCast;
18 const NAME: &'static str;
20}
21
22macro_rules! impl_event {
23 ($name:ident: $ty:ty) => {
24 #[allow(non_camel_case_types)]
25 pub struct $name;
26 impl EventDescriptor for $name {
27 type EventTy = $ty;
28 const NAME: &'static str = stringify!($name);
29 }
30 };
31}
32
33macro_rules! impl_events {
34 ($($name:ident: $ty:ty,)*) => {
35 $(impl_event!($name: $ty);)*
36 };
37}
38
39impl_events! {
40 afterprint: Event,
41 beforeprint: Event,
42 beforeunload: BeforeUnloadEvent,
43 gamepadconnected: GamepadEvent,
44 gamepaddisconnected: GamepadEvent,
45 hashchange: HashChangeEvent,
46 languagechange: Event,
47 message: MessageEvent,
48 messageerror: MessageEvent,
49 offline: Event,
50 online: Event,
51 pagehide: PageTransitionEvent,
52 pageshow: PageTransitionEvent,
53 popstate: PopStateEvent,
54 rejectionhandled: PromiseRejectionEvent,
55 storage: StorageEvent,
56 unhandledrejection: PromiseRejectionEvent,
57 unload: Event,
58
59 abort: UiEvent,
63 animationcancel: AnimationEvent,
64 animationend: AnimationEvent,
65 animationiteration: AnimationEvent,
66 animationstart: AnimationEvent,
67 auxclick: MouseEvent,
68 beforeinput: InputEvent,
69 blur: FocusEvent,
70 canplay: Event,
71 canplaythrough: Event,
72 change: Event,
73 click: MouseEvent,
74 close: Event,
75 compositionend: CompositionEvent,
76 compositionstart: CompositionEvent,
77 compositionupdate: CompositionEvent,
78 contextmenu: MouseEvent,
79 cuechange: Event,
80 dblclick: MouseEvent,
81 drag: DragEvent,
82 dragend: DragEvent,
83 dragenter: DragEvent,
84 dragleave: DragEvent,
85 dragover: DragEvent,
86 dragstart: DragEvent,
87 drop: DragEvent,
88 durationchange: Event,
89 emptied: Event,
90 ended: Event,
91 error: ErrorEvent,
92 focus: FocusEvent,
93 focusin: FocusEvent,
94 focusout: FocusEvent,
95 formdata: Event, gotpointercapture: PointerEvent,
97 input: Event,
98 invalid: Event,
99 keydown: KeyboardEvent,
100 keypress: KeyboardEvent,
101 keyup: KeyboardEvent,
102 load: Event,
103 loadeddata: Event,
104 loadedmetadata: Event,
105 loadstart: Event,
106 lostpointercapture: PointerEvent,
107 mousedown: MouseEvent,
108 mouseenter: MouseEvent,
109 mouseleave: MouseEvent,
110 mousemove: MouseEvent,
111 mouseout: MouseEvent,
112 mouseover: MouseEvent,
113 mouseup: MouseEvent,
114 pause: Event,
115 play: Event,
116 playing: Event,
117 pointercancel: PointerEvent,
118 pointerdown: PointerEvent,
119 pointerenter: PointerEvent,
120 pointerleave: PointerEvent,
121 pointermove: PointerEvent,
122 pointerout: PointerEvent,
123 pointerover: PointerEvent,
124 pointerup: PointerEvent,
125 progress: ProgressEvent,
126 ratechange: Event,
127 reset: Event,
128 resize: UiEvent,
129 scroll: Event,
130 securitypolicyviolation: SecurityPolicyViolationEvent,
131 seeked: Event,
132 seeking: Event,
133 select: Event,
134 selectionchange: Event,
135 selectstart: Event,
136 slotchange: Event,
137 stalled: Event,
138 submit: SubmitEvent,
139 suspend: Event,
140 timeupdate: Event,
141 toggle: Event,
142 touchcancel: TouchEvent,
143 touchend: TouchEvent,
144 touchmove: TouchEvent,
145 touchstart: TouchEvent,
146 transitioncancel: TransitionEvent,
147 transitionend: TransitionEvent,
148 transitionrun: TransitionEvent,
149 transitionstart: TransitionEvent,
150 volumechange: Event,
151 waiting: Event,
152 webkitanimationend: Event,
153 webkitanimationiteration: Event,
154 webkitanimationstart: Event,
155 webkittransitionend: Event,
156 wheel: WheelEvent,
157
158 DOMContentLoaded: Event,
162 devicemotion: DeviceMotionEvent,
163 deviceorientation: DeviceOrientationEvent,
164 orientationchange: Event,
165
166 copy: Event, cut: Event, paste: Event, fullscreenchange: Event,
177 fullscreenerror: Event,
178 pointerlockchange: Event,
179 pointerlockerror: Event,
180 readystatechange: Event,
181 visibilitychange: Event,
182}
183
184pub trait EventHandler<E: EventDescriptor, R = ()>: 'static {
185 fn call(&mut self, event: E::EventTy);
186}
187
188impl<E, F> EventHandler<E, ()> for F
189where
190 E: EventDescriptor,
191 F: FnMut(E::EventTy) + 'static,
192{
193 fn call(&mut self, event: E::EventTy) {
194 self(event);
195 }
196}
197
198#[doc(hidden)]
200#[cfg(feature = "suspense")]
201pub struct AsyncHandler;
202
203#[cfg(feature = "suspense")]
205impl<E, F, R> EventHandler<E, AsyncHandler> for F
206where
207 E: EventDescriptor,
208 F: FnMut(E::EventTy) -> R + 'static,
209 R: std::future::Future<Output = ()> + 'static,
210{
211 fn call(&mut self, event: E::EventTy) {
212 spawn_local_scoped(self(event));
213 }
214}