1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Copyright © The Daybrite Project
// SPDX-License-Identifier: MPL-2.0
//! Ambient animation intent (§8.4). [`with_animation`] sets a thread-local `AnimSpec` for the
//! duration of a state mutation; the tree's `patch` / layout's `set_frame` read it (via
//! `Tree::resolve_anim`) and hand it to the backend as *backend-executed* animation intent: Day
//! passes intent, the toolkit animates. A node-scoped `.animation(anim)` stores its own `AnimSpec`
//! on the node (`NodeData::implicit_anim`); the ambient one wins when both are present.
use Cell;
use AnimSpec;
tls_slots!
/// The ambient animation set by the innermost enclosing [`with_animation`], if any.
/// Restores the previous ambient animation on drop (panic-safe).
;
/// Run `f` with `spec` as the ambient animation, restoring the previous value afterwards.
pub
/// Explicitly animate every state change made in `f`, Day's equivalent of SwiftUI's
/// `withAnimation`. The mutation runs inside a [`day_reactive::batch`]; that batch's synchronous
/// fixpoint drain (bindings → `patch`, plus the turn-end layout → `set_frame`) executes while
/// `spec` is ambient, so the resulting native updates carry the animation intent and the toolkit
/// animates them on its own compositor. Nesting overrides; the previous ambient restores after.
///
/// Edge case: if called from *inside* an in-progress drain (rare: mutating within a reactive
/// effect), the batch defers to the ongoing drain and the intent is not captured; the change then
/// applies instantly. This matches SwiftUI's transaction boundaries.