Skip to content

Commit 1abec6f

Browse files
feat: add typed CssAnimation property support
Add strongly-typed CssAnimation class and related sub-types (CssAnimationDirection, CssAnimationFillMode, CssAnimationPlayState, CssAnimationIterationCount) for the animation CSS shorthand property. Reuses existing CssDuration and CssTimingFunction from css_transition. Closes #66
1 parent 5f584fe commit 1abec6f

4 files changed

Lines changed: 524 additions & 0 deletions

File tree

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
import 'css_transition.dart';
2+
import 'css_value.dart';
3+
4+
/// CSS animation-direction values.
5+
sealed class CssAnimationDirection implements CssValue {
6+
const CssAnimationDirection._();
7+
8+
static const CssAnimationDirection normal =
9+
_CssAnimationDirectionKeyword('normal');
10+
static const CssAnimationDirection reverse =
11+
_CssAnimationDirectionKeyword('reverse');
12+
static const CssAnimationDirection alternate =
13+
_CssAnimationDirectionKeyword('alternate');
14+
static const CssAnimationDirection alternateReverse =
15+
_CssAnimationDirectionKeyword('alternate-reverse');
16+
17+
/// CSS variable reference.
18+
factory CssAnimationDirection.variable(String varName) =
19+
_CssAnimationDirectionVariable;
20+
21+
/// Raw CSS value escape hatch.
22+
factory CssAnimationDirection.raw(String value) = _CssAnimationDirectionRaw;
23+
24+
/// Global keyword (inherit, initial, unset, revert).
25+
factory CssAnimationDirection.global(CssGlobal global) =
26+
_CssAnimationDirectionGlobal;
27+
}
28+
29+
final class _CssAnimationDirectionKeyword extends CssAnimationDirection {
30+
final String keyword;
31+
const _CssAnimationDirectionKeyword(this.keyword) : super._();
32+
33+
@override
34+
String toCss() => keyword;
35+
}
36+
37+
final class _CssAnimationDirectionVariable extends CssAnimationDirection {
38+
final String varName;
39+
const _CssAnimationDirectionVariable(this.varName) : super._();
40+
41+
@override
42+
String toCss() => 'var(--$varName)';
43+
}
44+
45+
final class _CssAnimationDirectionRaw extends CssAnimationDirection {
46+
final String value;
47+
const _CssAnimationDirectionRaw(this.value) : super._();
48+
49+
@override
50+
String toCss() => value;
51+
}
52+
53+
final class _CssAnimationDirectionGlobal extends CssAnimationDirection {
54+
final CssGlobal global;
55+
const _CssAnimationDirectionGlobal(this.global) : super._();
56+
57+
@override
58+
String toCss() => global.toCss();
59+
}
60+
61+
/// CSS animation-fill-mode values.
62+
sealed class CssAnimationFillMode implements CssValue {
63+
const CssAnimationFillMode._();
64+
65+
static const CssAnimationFillMode none =
66+
_CssAnimationFillModeKeyword('none');
67+
static const CssAnimationFillMode forwards =
68+
_CssAnimationFillModeKeyword('forwards');
69+
static const CssAnimationFillMode backwards =
70+
_CssAnimationFillModeKeyword('backwards');
71+
static const CssAnimationFillMode both =
72+
_CssAnimationFillModeKeyword('both');
73+
74+
/// CSS variable reference.
75+
factory CssAnimationFillMode.variable(String varName) =
76+
_CssAnimationFillModeVariable;
77+
78+
/// Raw CSS value escape hatch.
79+
factory CssAnimationFillMode.raw(String value) = _CssAnimationFillModeRaw;
80+
81+
/// Global keyword (inherit, initial, unset, revert).
82+
factory CssAnimationFillMode.global(CssGlobal global) =
83+
_CssAnimationFillModeGlobal;
84+
}
85+
86+
final class _CssAnimationFillModeKeyword extends CssAnimationFillMode {
87+
final String keyword;
88+
const _CssAnimationFillModeKeyword(this.keyword) : super._();
89+
90+
@override
91+
String toCss() => keyword;
92+
}
93+
94+
final class _CssAnimationFillModeVariable extends CssAnimationFillMode {
95+
final String varName;
96+
const _CssAnimationFillModeVariable(this.varName) : super._();
97+
98+
@override
99+
String toCss() => 'var(--$varName)';
100+
}
101+
102+
final class _CssAnimationFillModeRaw extends CssAnimationFillMode {
103+
final String value;
104+
const _CssAnimationFillModeRaw(this.value) : super._();
105+
106+
@override
107+
String toCss() => value;
108+
}
109+
110+
final class _CssAnimationFillModeGlobal extends CssAnimationFillMode {
111+
final CssGlobal global;
112+
const _CssAnimationFillModeGlobal(this.global) : super._();
113+
114+
@override
115+
String toCss() => global.toCss();
116+
}
117+
118+
/// CSS animation-play-state values.
119+
sealed class CssAnimationPlayState implements CssValue {
120+
const CssAnimationPlayState._();
121+
122+
static const CssAnimationPlayState running =
123+
_CssAnimationPlayStateKeyword('running');
124+
static const CssAnimationPlayState paused =
125+
_CssAnimationPlayStateKeyword('paused');
126+
127+
/// CSS variable reference.
128+
factory CssAnimationPlayState.variable(String varName) =
129+
_CssAnimationPlayStateVariable;
130+
131+
/// Raw CSS value escape hatch.
132+
factory CssAnimationPlayState.raw(String value) = _CssAnimationPlayStateRaw;
133+
134+
/// Global keyword (inherit, initial, unset, revert).
135+
factory CssAnimationPlayState.global(CssGlobal global) =
136+
_CssAnimationPlayStateGlobal;
137+
}
138+
139+
final class _CssAnimationPlayStateKeyword extends CssAnimationPlayState {
140+
final String keyword;
141+
const _CssAnimationPlayStateKeyword(this.keyword) : super._();
142+
143+
@override
144+
String toCss() => keyword;
145+
}
146+
147+
final class _CssAnimationPlayStateVariable extends CssAnimationPlayState {
148+
final String varName;
149+
const _CssAnimationPlayStateVariable(this.varName) : super._();
150+
151+
@override
152+
String toCss() => 'var(--$varName)';
153+
}
154+
155+
final class _CssAnimationPlayStateRaw extends CssAnimationPlayState {
156+
final String value;
157+
const _CssAnimationPlayStateRaw(this.value) : super._();
158+
159+
@override
160+
String toCss() => value;
161+
}
162+
163+
final class _CssAnimationPlayStateGlobal extends CssAnimationPlayState {
164+
final CssGlobal global;
165+
const _CssAnimationPlayStateGlobal(this.global) : super._();
166+
167+
@override
168+
String toCss() => global.toCss();
169+
}
170+
171+
/// CSS animation-iteration-count values.
172+
sealed class CssAnimationIterationCount implements CssValue {
173+
const CssAnimationIterationCount._();
174+
175+
static const CssAnimationIterationCount infinite =
176+
_CssAnimationIterationCountKeyword('infinite');
177+
178+
/// Numeric iteration count.
179+
factory CssAnimationIterationCount.count(num value) =
180+
_CssAnimationIterationCountNumber;
181+
182+
/// CSS variable reference.
183+
factory CssAnimationIterationCount.variable(String varName) =
184+
_CssAnimationIterationCountVariable;
185+
186+
/// Raw CSS value escape hatch.
187+
factory CssAnimationIterationCount.raw(String value) =
188+
_CssAnimationIterationCountRaw;
189+
190+
/// Global keyword (inherit, initial, unset, revert).
191+
factory CssAnimationIterationCount.global(CssGlobal global) =
192+
_CssAnimationIterationCountGlobal;
193+
}
194+
195+
final class _CssAnimationIterationCountKeyword
196+
extends CssAnimationIterationCount {
197+
final String keyword;
198+
const _CssAnimationIterationCountKeyword(this.keyword) : super._();
199+
200+
@override
201+
String toCss() => keyword;
202+
}
203+
204+
final class _CssAnimationIterationCountNumber
205+
extends CssAnimationIterationCount {
206+
final num value;
207+
const _CssAnimationIterationCountNumber(this.value) : super._();
208+
209+
@override
210+
String toCss() => '$value';
211+
}
212+
213+
final class _CssAnimationIterationCountVariable
214+
extends CssAnimationIterationCount {
215+
final String varName;
216+
const _CssAnimationIterationCountVariable(this.varName) : super._();
217+
218+
@override
219+
String toCss() => 'var(--$varName)';
220+
}
221+
222+
final class _CssAnimationIterationCountRaw extends CssAnimationIterationCount {
223+
final String value;
224+
const _CssAnimationIterationCountRaw(this.value) : super._();
225+
226+
@override
227+
String toCss() => value;
228+
}
229+
230+
final class _CssAnimationIterationCountGlobal
231+
extends CssAnimationIterationCount {
232+
final CssGlobal global;
233+
const _CssAnimationIterationCountGlobal(this.global) : super._();
234+
235+
@override
236+
String toCss() => global.toCss();
237+
}
238+
239+
/// CSS animation shorthand value.
240+
sealed class CssAnimation implements CssValue {
241+
const CssAnimation._();
242+
243+
static const CssAnimation none = _CssAnimationKeyword('none');
244+
245+
/// Single animation.
246+
factory CssAnimation({
247+
required String name,
248+
CssDuration? duration,
249+
CssTimingFunction? timingFunction,
250+
CssDuration? delay,
251+
CssAnimationIterationCount? iterationCount,
252+
CssAnimationDirection? direction,
253+
CssAnimationFillMode? fillMode,
254+
CssAnimationPlayState? playState,
255+
}) = _CssAnimationSingle;
256+
257+
/// Multiple animations.
258+
factory CssAnimation.multiple(List<CssAnimation> animations) =
259+
_CssAnimationMultiple;
260+
261+
/// CSS variable reference.
262+
factory CssAnimation.variable(String varName) = _CssAnimationVariable;
263+
264+
/// Raw CSS value escape hatch.
265+
factory CssAnimation.raw(String value) = _CssAnimationRaw;
266+
267+
/// Global keyword (inherit, initial, unset, revert).
268+
factory CssAnimation.global(CssGlobal global) = _CssAnimationGlobal;
269+
}
270+
271+
final class _CssAnimationKeyword extends CssAnimation {
272+
final String keyword;
273+
const _CssAnimationKeyword(this.keyword) : super._();
274+
275+
@override
276+
String toCss() => keyword;
277+
}
278+
279+
final class _CssAnimationSingle extends CssAnimation {
280+
final String name;
281+
final CssDuration? duration;
282+
final CssTimingFunction? timingFunction;
283+
final CssDuration? delay;
284+
final CssAnimationIterationCount? iterationCount;
285+
final CssAnimationDirection? direction;
286+
final CssAnimationFillMode? fillMode;
287+
final CssAnimationPlayState? playState;
288+
289+
const _CssAnimationSingle({
290+
required this.name,
291+
this.duration,
292+
this.timingFunction,
293+
this.delay,
294+
this.iterationCount,
295+
this.direction,
296+
this.fillMode,
297+
this.playState,
298+
}) : super._();
299+
300+
@override
301+
String toCss() {
302+
final parts = [name];
303+
if (duration != null) parts.add(duration!.toCss());
304+
if (timingFunction != null) parts.add(timingFunction!.toCss());
305+
if (delay != null) parts.add(delay!.toCss());
306+
if (iterationCount != null) parts.add(iterationCount!.toCss());
307+
if (direction != null) parts.add(direction!.toCss());
308+
if (fillMode != null) parts.add(fillMode!.toCss());
309+
if (playState != null) parts.add(playState!.toCss());
310+
return parts.join(' ');
311+
}
312+
}
313+
314+
final class _CssAnimationMultiple extends CssAnimation {
315+
final List<CssAnimation> animations;
316+
const _CssAnimationMultiple(this.animations) : super._();
317+
318+
@override
319+
String toCss() => animations.map((a) => a.toCss()).join(', ');
320+
}
321+
322+
final class _CssAnimationVariable extends CssAnimation {
323+
final String varName;
324+
const _CssAnimationVariable(this.varName) : super._();
325+
326+
@override
327+
String toCss() => 'var(--$varName)';
328+
}
329+
330+
final class _CssAnimationRaw extends CssAnimation {
331+
final String value;
332+
const _CssAnimationRaw(this.value) : super._();
333+
334+
@override
335+
String toCss() => value;
336+
}
337+
338+
final class _CssAnimationGlobal extends CssAnimation {
339+
final CssGlobal global;
340+
const _CssAnimationGlobal(this.global) : super._();
341+
342+
@override
343+
String toCss() => global.toCss();
344+
}

packages/spark_css/lib/src/css_types/css_types.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// CSS type system for type-safe style declarations.
22
library;
33

4+
export 'css_animation.dart';
45
export 'css_angle.dart';
56
export 'css_background.dart';
67
export 'css_background_attachment.dart';

packages/spark_css/lib/src/style.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ class Style implements CssStyle {
312312
CssBackgroundOrigin? backgroundOrigin,
313313
CssBackgroundAttachment? backgroundAttachment,
314314
// Effects
315+
CssAnimation? animation,
315316
CssTransition? transition,
316317
CssTransform? transform,
317318
// Background shorthand
@@ -456,6 +457,7 @@ class Style implements CssStyle {
456457
}
457458

458459
// Effects
460+
if (animation != null) _properties['animation'] = animation.toCss();
459461
if (transition != null) _properties['transition'] = transition.toCss();
460462
if (transform != null) _properties['transform'] = transform.toCss();
461463

0 commit comments

Comments
 (0)