1use animato_wasm::ScrollSmoother as CoreScrollSmoother;
4use wasm_bindgen::prelude::*;
5
6#[wasm_bindgen(js_name = ScrollSmoother)]
8#[derive(Clone, Debug)]
9pub struct ScrollSmoother {
10 inner: CoreScrollSmoother,
11}
12
13#[wasm_bindgen(js_class = ScrollSmoother)]
14impl ScrollSmoother {
15 #[wasm_bindgen(constructor)]
17 pub fn new() -> Self {
18 Self {
19 inner: CoreScrollSmoother::new(),
20 }
21 }
22
23 #[wasm_bindgen(js_name = snapTo)]
25 pub fn snap_to(&mut self, value: f32) {
26 self.inner.snap_to(value);
27 }
28
29 #[wasm_bindgen(js_name = scrollTo)]
31 pub fn scroll_to(&mut self, value: f32) {
32 self.inner.scroll_to(value);
33 }
34
35 #[wasm_bindgen(js_name = onWheel)]
37 pub fn on_wheel(&mut self, delta_y: f32) {
38 self.inner.on_wheel(delta_y);
39 }
40
41 pub fn update(&mut self, dt: f32) -> bool {
43 self.inner.update(dt)
44 }
45
46 pub fn current(&self) -> f32 {
48 self.inner.current()
49 }
50
51 pub fn target(&self) -> f32 {
53 self.inner.target()
54 }
55
56 #[wasm_bindgen(js_name = isSettled)]
58 pub fn is_settled(&self) -> bool {
59 self.inner.is_settled()
60 }
61}
62
63impl Default for ScrollSmoother {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69#[cfg(target_arch = "wasm32")]
70mod dom {
71 use super::*;
72 use crate::easing::parse_easing;
73 use crate::error::non_negative;
74 use animato_wasm::{
75 Draggable as CoreDraggable, FlipAnimation as CoreFlipAnimation, FlipState,
76 LayoutAnimator as CoreLayoutAnimator, Observer as CoreObserver, ObserverEvent, SplitMode,
77 SplitText as CoreSplitText,
78 };
79 use web_sys::{Element, PointerEvent, WheelEvent};
80
81 #[wasm_bindgen(js_name = FlipAnimation)]
83 #[derive(Clone, Debug)]
84 pub struct FlipAnimation {
85 inner: CoreFlipAnimation,
86 }
87
88 #[wasm_bindgen(js_class = FlipAnimation)]
89 impl FlipAnimation {
90 #[wasm_bindgen(constructor)]
92 pub fn new(first: &Element, last: &Element) -> Self {
93 Self {
94 inner: CoreFlipAnimation::new(FlipState::capture(first), FlipState::capture(last)),
95 }
96 }
97
98 pub fn duration(&mut self, seconds: f32) {
100 self.inner = self.inner.clone().duration(non_negative(seconds, 0.3));
101 }
102
103 #[wasm_bindgen(js_name = setEasing)]
105 pub fn set_easing(&mut self, easing: &str) -> Result<(), JsValue> {
106 self.inner = self.inner.clone().easing(parse_easing(easing)?);
107 Ok(())
108 }
109
110 pub fn update(&mut self, dt: f32) -> bool {
112 self.inner.update(dt)
113 }
114
115 pub fn reset(&mut self) {
117 self.inner.reset();
118 }
119
120 pub fn progress(&self) -> f32 {
122 self.inner.progress()
123 }
124
125 #[wasm_bindgen(js_name = cssTransform)]
127 pub fn css_transform(&self) -> String {
128 self.inner.css_transform()
129 }
130
131 #[wasm_bindgen(js_name = applyTo)]
133 pub fn apply_to(&self, element: &Element) -> Result<(), JsValue> {
134 self.inner.apply_to(element)
135 }
136 }
137
138 #[wasm_bindgen(js_name = LayoutAnimator)]
140 #[derive(Debug, Default)]
141 pub struct LayoutAnimator {
142 inner: CoreLayoutAnimator,
143 }
144
145 #[wasm_bindgen(js_class = LayoutAnimator)]
146 impl LayoutAnimator {
147 #[wasm_bindgen(constructor)]
149 pub fn new() -> Self {
150 Self::default()
151 }
152
153 pub fn snapshot(&mut self, key: &str, element: &Element) {
155 self.inner.snapshot(key, element);
156 }
157
158 #[wasm_bindgen(js_name = computeTransition)]
160 pub fn compute_transition(
161 &mut self,
162 key: &str,
163 element: &Element,
164 duration: f32,
165 easing: &str,
166 ) -> Result<(), JsValue> {
167 self.inner
168 .compute_transitions(&[(key, element)], duration, parse_easing(easing)?);
169 Ok(())
170 }
171
172 pub fn update(&mut self, dt: f32) {
174 self.inner.update(dt);
175 }
176
177 pub fn apply(&self, key: &str, element: &Element) -> Result<(), JsValue> {
179 self.inner.apply(&[(key, element)])
180 }
181
182 #[wasm_bindgen(js_name = cssTransform)]
184 pub fn css_transform(&self, key: &str) -> String {
185 self.inner.css_transform(key).unwrap_or_default()
186 }
187
188 #[wasm_bindgen(js_name = isComplete)]
190 pub fn is_complete(&self) -> bool {
191 self.inner.is_complete()
192 }
193
194 #[wasm_bindgen(js_name = animationCount)]
196 pub fn animation_count(&self) -> usize {
197 self.inner.animation_count()
198 }
199
200 #[wasm_bindgen(js_name = clearCompleted)]
202 pub fn clear_completed(&mut self) {
203 self.inner.clear_completed();
204 }
205 }
206
207 #[wasm_bindgen(js_name = SplitText)]
209 #[derive(Debug)]
210 pub struct SplitText {
211 inner: CoreSplitText,
212 }
213
214 #[wasm_bindgen(js_class = SplitText)]
215 impl SplitText {
216 #[wasm_bindgen(constructor)]
218 pub fn new(element: &Element, mode: &str) -> Result<Self, JsValue> {
219 let mode = match crate::types::normalize_name(mode).as_str() {
220 "chars" | "characters" => SplitMode::Chars,
221 "words" => SplitMode::Words,
222 _ => return Err(JsValue::from_str("split mode must be `chars` or `words`")),
223 };
224 Ok(Self {
225 inner: CoreSplitText::split(element, mode)?,
226 })
227 }
228
229 pub fn len(&self) -> usize {
231 self.inner.spans().len()
232 }
233
234 #[wasm_bindgen(js_name = isEmpty)]
236 pub fn is_empty(&self) -> bool {
237 self.inner.spans().is_empty()
238 }
239
240 pub fn restore(&self) {
242 self.inner.restore();
243 }
244 }
245
246 #[wasm_bindgen(js_name = Draggable)]
248 #[derive(Debug)]
249 pub struct Draggable {
250 inner: CoreDraggable,
251 }
252
253 #[wasm_bindgen(js_class = Draggable)]
254 impl Draggable {
255 #[wasm_bindgen(constructor)]
257 pub fn new(element: Element, x: f32, y: f32) -> Result<Self, JsValue> {
258 Ok(Self {
259 inner: CoreDraggable::attach(element, [x, y])?,
260 })
261 }
262
263 #[wasm_bindgen(js_name = toArray)]
265 pub fn to_array(&self) -> js_sys::Float32Array {
266 crate::types::f32_array(&self.inner.position())
267 }
268
269 #[wasm_bindgen(js_name = isDragging)]
271 pub fn is_dragging(&self) -> bool {
272 self.inner.is_dragging()
273 }
274 }
275
276 #[wasm_bindgen(js_name = Observer)]
278 #[derive(Clone, Debug, Default)]
279 pub struct Observer;
280
281 #[wasm_bindgen(js_class = Observer)]
282 impl Observer {
283 #[wasm_bindgen(constructor)]
285 pub fn new() -> Self {
286 Self
287 }
288
289 #[wasm_bindgen(js_name = pointerDown)]
291 pub fn pointer_down(event: &PointerEvent) -> Result<JsValue, JsValue> {
292 observer_event_to_value(CoreObserver::pointer_down(event))
293 }
294
295 #[wasm_bindgen(js_name = pointerMove)]
297 pub fn pointer_move(event: &PointerEvent) -> Result<JsValue, JsValue> {
298 observer_event_to_value(CoreObserver::pointer_move(event))
299 }
300
301 #[wasm_bindgen(js_name = pointerUp)]
303 pub fn pointer_up(event: &PointerEvent) -> Result<JsValue, JsValue> {
304 observer_event_to_value(CoreObserver::pointer_up(event))
305 }
306
307 pub fn wheel(event: &WheelEvent) -> Result<JsValue, JsValue> {
309 observer_event_to_value(CoreObserver::wheel(event))
310 }
311 }
312
313 fn observer_event_to_value(event: ObserverEvent) -> Result<JsValue, JsValue> {
314 Ok(match event {
315 ObserverEvent::PointerDown { x, y, pointer_id } => object(&[
316 ("type", JsValue::from_str("pointerDown")),
317 ("x", JsValue::from_f64(x as f64)),
318 ("y", JsValue::from_f64(y as f64)),
319 ("pointerId", JsValue::from_f64(pointer_id as f64)),
320 ]),
321 ObserverEvent::PointerMove { x, y, pointer_id } => object(&[
322 ("type", JsValue::from_str("pointerMove")),
323 ("x", JsValue::from_f64(x as f64)),
324 ("y", JsValue::from_f64(y as f64)),
325 ("pointerId", JsValue::from_f64(pointer_id as f64)),
326 ]),
327 ObserverEvent::PointerUp { x, y, pointer_id } => object(&[
328 ("type", JsValue::from_str("pointerUp")),
329 ("x", JsValue::from_f64(x as f64)),
330 ("y", JsValue::from_f64(y as f64)),
331 ("pointerId", JsValue::from_f64(pointer_id as f64)),
332 ]),
333 ObserverEvent::Wheel { delta_x, delta_y } => object(&[
334 ("type", JsValue::from_str("wheel")),
335 ("deltaX", JsValue::from_f64(delta_x as f64)),
336 ("deltaY", JsValue::from_f64(delta_y as f64)),
337 ]),
338 })
339 }
340
341 fn object(entries: &[(&str, JsValue)]) -> JsValue {
342 let object = js_sys::Object::new();
343 for (key, value) in entries {
344 let _ = js_sys::Reflect::set(&object, &JsValue::from_str(key), value);
345 }
346 object.into()
347 }
348}
349
350#[cfg(not(target_arch = "wasm32"))]
351mod dom {
352 use super::*;
353
354 macro_rules! stub_class {
355 ($name:ident) => {
356 #[wasm_bindgen(js_name = $name)]
357 #[derive(Clone, Debug, Default)]
359 pub struct $name;
360 };
361 }
362
363 stub_class!(FlipAnimation);
364 stub_class!(LayoutAnimator);
365 stub_class!(SplitText);
366 stub_class!(Draggable);
367 stub_class!(Observer);
368}
369
370pub use dom::{Draggable, FlipAnimation, LayoutAnimator, Observer, SplitText};