Skip to main content

gpui_ce_motion/
lib.rs

1//! Declarative transitions with retained, explicitly owned motion state.
2//!
3//! Keep one [`MotionState`] per logical object, or a keyed [`Motions`] collection
4//! in its owning view. Recreate the [`Motion`] description each render; changing
5//! a target interrupts from the current presentation. Springs also preserve
6//! velocity. Sampling existing state needs no tasks, allocations, global registries,
7//! or timers. New collection keys, clips, and timelines may allocate during
8//! preparation; their sampling reuses retained state.
9//!
10//! ```
11//! use gpui_ce_motion::{Motion, MotionState, Target, Transition};
12//! use std::time::Duration;
13//!
14//! let mut state = MotionState::default();
15//! let motion = Motion::new(Target::default().x(120.0).width(240.0).border_radius(12.0))
16//!     .initial(Target::default().width(0.0).border_radius(0.0).opacity(0.0))
17//!     .exit(Target::default().y(16.0).opacity(0.0))
18//!     .transition(Transition::default());
19//! assert!(state.sample(motion, Duration::ZERO, false).is_animating());
20//! let frame = state.sample(motion, Duration::from_secs(5), false);
21//! assert_eq!(frame.target().x_px(), 120.0);
22//! assert_eq!(frame.target().width_px(), Some(240.0));
23//! assert!(!frame.is_animating());
24//! ```
25//!
26//! The optional `gpui` feature adds `MotionState::frame` and GPUI rendering
27//! helpers. See the crate README for integration and publication constraints.
28
29//!
30//! Prepared playback uses the same explicit clocks and ownership:
31//!
32//! ```
33//! use gpui_ce_motion::{Animation, AnimationState, Easing, Repeat, RepeatMode, Target};
34//! use std::time::Duration;
35//! # fn main() -> Result<(), gpui_ce_motion::AnimationError> {
36//! let clip = Animation::to(Target::default().x(120.0), Duration::from_millis(600), Easing::Linear)
37//!     .repeat(Repeat::Forever, RepeatMode::Mirror, Duration::ZERO)?;
38//! let mut state = AnimationState::default();
39//! state.sample(&clip, Duration::ZERO, false);
40//! state.pause(Duration::from_millis(300));
41//! let held = state.sample(&clip, Duration::from_millis(900), false);
42//! assert_eq!(held.target().x_px(), 60.0);
43//! assert!(!held.is_animating());
44//! # Ok(())
45//! # }
46//! ```
47
48mod animation;
49mod color;
50mod interaction;
51mod layout;
52#[cfg(feature = "gpui")]
53mod layout_native;
54mod motion;
55mod motions;
56mod presence;
57mod svg;
58mod transition;
59mod value;
60
61#[cfg(feature = "gpui")]
62mod native;
63
64pub use motion::{Frame, Motion, MotionState, Presence, Property, Target};
65
66pub use motions::Motions;
67
68pub use transition::{
69    Bezier, CustomEasing, Easing, InvalidEasing, InvalidSpring, Spring, Transition,
70};
71
72pub use value::{Inertia, MotionValue, ValueFrame};
73
74pub use animation::{
75    Animation, AnimationError, AnimationState, Keyframe, Playback, Repeat, RepeatMode, StaggerFrom,
76    Timeline, stagger,
77};
78
79pub use color::{Color, ColorState};
80
81pub use interaction::{
82    Drag, GestureTargets, InView, Interaction, Variants, move_item, reorder_index, scroll_progress,
83    transform,
84};
85
86pub use presence::{PresenceChild, PresenceGroup, PresenceMode};
87
88pub use svg::{SvgFrame, SvgMotion, SvgMotionState, SvgTarget};
89
90pub use layout::{LayoutPositionFrame, LayoutPositionState};
91#[cfg(feature = "gpui")]
92pub use layout_native::{LayoutGroup, LayoutPositionElement};
93
94mod style_motion;
95
96pub use style_motion::{
97    ColorProperty, StyleFrame, StyleMotion, StyleMotionState, StyleProperty, StyleTarget,
98};
99
100#[cfg(feature = "gpui")]
101mod measured_size;
102
103#[cfg(feature = "gpui")]
104pub use measured_size::{AutoSize, SizeAxis};
105
106#[cfg(feature = "gpui")]
107mod pop_layout;
108
109#[cfg(feature = "gpui")]
110pub use pop_layout::{PopElement, PopLayout, PopRequest};
111
112#[cfg(feature = "gpui")]
113mod gesture_native;
114
115#[cfg(feature = "gpui")]
116pub use gesture_native::{GestureElement, GestureState};
117
118#[cfg(feature = "gpui")]
119mod scroll_native;
120
121#[cfg(feature = "gpui")]
122pub use scroll_native::{Axis, ScrollMotion, native_scroll_progress};
123
124#[cfg(feature = "gpui")]
125mod shared_layout;
126
127#[cfg(feature = "gpui")]
128pub use shared_layout::{SharedElement, SharedLayout};
129
130#[cfg(feature = "gpui")]
131mod reorder_native;
132
133#[cfg(feature = "gpui")]
134pub use reorder_native::{ReorderElement, ReorderGroup};
135
136mod vector;
137
138pub use vector::{PathCommand, PathError, PathFrame, PathMorphState, PathShape, StrokeReveal};
139
140#[cfg(feature = "gpui")]
141mod vector_native;
142
143#[cfg(feature = "gpui")]
144pub use vector_native::{VectorElement, VectorState};
145
146#[cfg(feature = "text")]
147mod text;
148
149#[cfg(feature = "text")]
150pub use text::{
151    NumberEffect, Scramble, TextClip, TextError, TextLayoutUnit, TextMatch, TextOptions,
152    TextPlaybackState, TextPresentation, TextPreset, TextRevealAxis, TextTarget, TextUnit,
153    TextUnitInfo, text_ranges,
154};
155
156#[cfg(feature = "gpui")]
157mod text_native {
158    use gpui::ColorExt as _;
159
160    fn text_color_to_native(color: crate::Color) -> gpui::Hsla {
161        gpui::rgb_to_hsla(color.to_rgba())
162    }
163
164    fn text_color_from_native(color: gpui::Hsla) -> crate::Color {
165        let color = gpui::hsla_to_rgba(color);
166
167        crate::Color::rgba(
168            color.red.into(),
169            color.green.into(),
170            color.blue.into(),
171            color.alpha.into(),
172        )
173    }
174
175    crate::__motion_text_adapter!(gpui, text_color_to_native, text_color_from_native);
176}
177
178#[cfg(feature = "gpui")]
179pub use text_native::{NumberElement, NumberMotionState, TextElement, TextMotionState};
180
181mod graph;
182
183pub use graph::{
184    GraphError, GraphSubscription, MotionEvent, MotionEventKind, MotionGraph, ValueId,
185};
186
187mod geometry;
188
189pub use geometry::{
190    AutoScroll, DragBounds, GeometryError, LayoutRect, ReorderAxis, ScrollEdge, ScrollOffsets,
191};
192
193mod completion;
194
195pub use completion::{Completion, CompletionStatus};
196
197mod typed_animation;
198
199pub use typed_animation::{
200    MotionData, TrackId, TypedAnimation, TypedFrame, TypedKeyframe, TypedState, TypedTimeline,
201};
202
203mod orchestration;
204
205pub use orchestration::{ChildrenOrder, MotionConfig, MotionNode, MotionTree, TreeError};
206
207#[cfg(feature = "svg-path")]
208pub use vector::SvgPathError;
209pub use vector::{PathMeasure, PathPoint};
210
211#[cfg(feature = "text")]
212pub use text::{FixedNumber, FormattedNumber, NumberFormat, NumberFormatError, RichText, TextSpan};
213
214mod spatial_native;
215
216#[cfg(feature = "gpui")]
217mod spatial {
218    crate::__motion_spatial_adapter!(gpui, crate);
219}
220
221pub use geometry::ScrollFrame;
222
223#[cfg(feature = "gpui")]
224pub use spatial::{
225    AnchorElement, GraphState, MotionAnchor, MotionTreeState, ScrollTracker, SharedOverlay,
226    SharedOverlayElement,
227};
228
229pub use geometry::{DragEvent, GesturePhase, PinchGesture};