app-studio 0.6.46 → 0.6.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,3 +23,8 @@ export declare const Comparison: ComponentStory<typeof View>;
23
23
  * Multiple animations with mixed triggers
24
24
  */
25
25
  export declare const MixedTriggers: ComponentStory<typeof View>;
26
+ /**
27
+ * Special Case: Timeline Override
28
+ * If you provide an explicit timeline (e.g. scroll()), it is respected even if animateOn="View" is set.
29
+ */
30
+ export declare const TimelineOverride: ComponentStory<typeof View>;
@@ -18,3 +18,13 @@ export declare const ClickAnimation: ComponentStory<typeof View>;
18
18
  export declare const AnimateInExample: ComponentStory<typeof View>;
19
19
  export declare const AnimateOutExample: ComponentStory<typeof View>;
20
20
  export declare const VisibleAnimation: ComponentStory<typeof View>;
21
+ /**
22
+ * Special Use Cases: Scroll-Driven Animations using Scroll Timeline
23
+ * These animations progress as the user scrolls, rather than just triggering on view.
24
+ */
25
+ export declare const ScrollDrivenAnimations: ComponentStory<typeof View>;
26
+ /**
27
+ * Special Use Cases: View Timeline Presets
28
+ * Performant, pure-CSS animations that trigger when elements enter the viewport.
29
+ */
30
+ export declare const ViewDrivenPresets: ComponentStory<typeof View>;
package/docs/Animation.md CHANGED
@@ -2,16 +2,23 @@
2
2
 
3
3
  ## 1. Introduction
4
4
 
5
- App-Studio provides a powerful animation system through the `Animation` object. This system allows you to easily add dynamic and engaging animations to any component that extends from `Element`. The animations are based on CSS animations and can be customized with various properties.
5
+ App-Studio provides a powerful animation system through the `Animation` object and the `Element` component. This system allows you to easily add dynamic and engaging animations, including:
6
6
 
7
- ## 2. Usage
7
+ - **Standard CSS Animations**: Immediate animations on mount or loop.
8
+ - **Scroll-Triggered Animations** (`view()`): Animations that play when elements enter the viewport.
9
+ - **Scroll-Linked Animations** (`scroll()`): Animations driven by the scroll progress (e.g., parallax, reading progress).
10
+ - **Interactive Animations**: Triggered by events like hover, click, or focus.
8
11
 
9
- ### Basic Usage
12
+ ## 2. Basic Usage
13
+
14
+ ### Standard Animations
15
+
16
+ Use the `Animation` object to access standard animation presets.
10
17
 
11
18
  ```jsx
12
19
  import { View, Animation } from 'app-studio';
13
20
 
14
- // Simple animation
21
+ // Simple animation running immediately on mount
15
22
  <View
16
23
  animate={Animation.fadeIn({
17
24
  duration: '1s',
@@ -27,349 +34,208 @@ Each animation function accepts an options object with these properties:
27
34
 
28
35
  ```typescript
29
36
  type AnimationOptions = {
30
- duration?: string; // e.g., '1s', '500ms'
31
- timingFunction?: string; // e.g., 'ease', 'linear', 'ease-in-out'
37
+ duration?: string; // e.g., '1s', '500ms'
38
+ timingFunction?: string; // e.g., 'ease', 'linear', 'cubic-bezier(...)'
32
39
  iterationCount?: string | number; // e.g., '1', 'infinite'
40
+ delay?: string; // e.g., '0.5s'
41
+ direction?: string; // e.g., 'normal', 'reverse', 'alternate'
42
+ fillMode?: string; // e.g., 'forwards', 'both'
43
+ playState?: string; // e.g., 'running', 'paused'
33
44
  }
34
45
  ```
35
46
 
36
- ## 3. Animation Types
37
-
38
- ### Transition Animations
47
+ ## 3. Element Props for Animation
48
+
49
+ The `Element` component (and components extending it like `View`, `Text`, `Image`) supports several props to control animations:
39
50
 
40
- Animations that involve changes in opacity or position:
51
+ ### `animate`
52
+ The main property to apply animations. Accepts a single animation object or an array of animations.
41
53
 
42
54
  ```jsx
43
- // Fade animations (change opacity)
44
- Animation.fadeIn()
45
- Animation.fadeOut()
46
-
47
- // Slide animations (move elements)
48
- Animation.slideInLeft()
49
- Animation.slideInRight()
50
- Animation.slideOutLeft()
51
- Animation.slideOutRight()
52
- Animation.slideInUp()
53
- Animation.slideOutDown()
55
+ <View animate={Animation.bounce()} />
56
+ <View animate={[Animation.fadeIn(), Animation.slideInUp()]} />
54
57
  ```
55
58
 
56
- ### Transform Animations
57
-
58
- Animations that modify the element's transformation:
59
-
60
- ```jsx
61
- // Rotate
62
- Animation.rotate()
63
-
64
- // Scale
65
- Animation.scale()
66
-
67
- // Translate
68
- Animation.translate()
69
- ```
59
+ ### `animateIn` & `animateOut`
60
+ Useful for mounting and unmounting transitions, or conditional rendering effects.
61
+ - `animateIn`: Applied when the component mounts or becomes visible (if `IntersectionObserver` is used internally).
62
+ - `animateOut`: Applied during unmount cleanup (requires immediate re-render or external handling to be visible).
70
63
 
71
- ### Effect Animations
64
+ ### `animateOn`
65
+ Controls *when* the animation defined in `animate` starts.
72
66
 
73
- Animations that create special effects:
67
+ - `'Mount'` (default): Animation starts immediately when the component is added to the DOM.
68
+ - `'View'`: Animation is converted to a CSS `view()` timeline animation. It plays as the element enters the viewport. **No JavaScript required.**
69
+ - `'Both'`: Technically same as Mount for most cases, ensuring visibility.
74
70
 
75
71
  ```jsx
76
- // Attention seekers
77
- Animation.bounce()
78
- Animation.pulse()
79
- Animation.shake()
80
- Animation.flash()
81
-
82
- // Special effects
83
- Animation.flip()
84
- Animation.rubberBand()
85
- Animation.heartBeat()
72
+ // Trigger animation only when user scrolls it into view
73
+ <View animate={Animation.slideInUp()} animateOn="View" />
86
74
  ```
87
75
 
88
- ## 4. Event-Based Animations
76
+ ## 4. Animation Presets
89
77
 
90
- Animations can be triggered by various events using the `on` prop:
78
+ App-Studio comes with a comprehensive library of ready-to-use animations available under the `Animation` namespace.
91
79
 
92
- ```jsx
93
- <View
94
- on={{
95
- // Animation on hover
96
- hover: {
97
- backgroundColor: 'lightblue', // Example: change background color on hover
98
- animate: Animation.pulse({
99
- duration: "1s",
100
- iterationCount: "infinite",
101
- }),
102
- },
103
-
104
- // Animation on click
105
- click: {
106
- animate: Animation.flash({ duration: '0.5s' })
107
- }
108
- }}
109
- />
110
- ```
80
+ ### Fades
81
+ - `Animation.fadeIn()`
82
+ - `Animation.fadeOut()`
83
+ - `Animation.fadeInDown()`
84
+ - `Animation.fadeInUp()`
85
+ - `Animation.fadeInScroll()` - Scroll-progress driven fade
111
86
 
112
- ## 5. Responsive Animations
87
+ ### Slides
88
+ - `Animation.slideInLeft()`
89
+ - `Animation.slideInRight()`
90
+ - `Animation.slideInDown()`
91
+ - `Animation.slideInUp()`
92
+ - `Animation.slideOutLeft()`
93
+ - `Animation.slideOutRight()`
94
+ - `Animation.slideInLeftScroll()` - Scroll-progress driven slide
113
95
 
114
- You can define different animations for different screen sizes using the `media` prop:
96
+ ### Zooms & Scales
97
+ - `Animation.zoomIn()`
98
+ - `Animation.zoomOut()`
99
+ - `Animation.zoomInDown()`
100
+ - `Animation.zoomOutUp()`
101
+ - `Animation.scale()` - Pulse scale effect
102
+ - `Animation.scaleDownScroll()`
103
+ - `Animation.listItemScaleScroll()`
115
104
 
116
- ```jsx
117
- <View
118
- media={{
119
- mobile: {
120
- animate: Animation.fadeIn({ duration: '1s' })
121
- },
122
- tablet: {
123
- animate: Animation.slideInLeft({ duration: '0.5s' })
124
- },
125
- desktop: {
126
- animate: Animation.bounce({ duration: '2s' })
127
- }
128
- }}
129
- />
130
- ```
131
-
132
- ## 6. Custom Animation Sequences
133
-
134
- You can create complex animation sequences by defining an array of animation states. Each state in the sequence is an object with `from` and `to` properties that define the CSS styles at the start and end of that animation segment.
105
+ ### Bounces
106
+ - `Animation.bounce()`
107
+ - `Animation.bounceIn()`
108
+ - `Animation.bounceOut()`
135
109
 
136
- Here's a simple example:
110
+ ### Flips & Rotations
111
+ - `Animation.rotate()`
112
+ - `Animation.flip()`
113
+ - `Animation.flipInX()`
114
+ - `Animation.flipInY()`
115
+ - `Animation.rollIn()`
116
+ - `Animation.rollOut()`
117
+ - `Animation.swing()`
137
118
 
138
- ```jsx
139
- const simpleSequence = [
140
- {
141
- from: { opacity: 0 }, // Start fully transparent
142
- to: { opacity: 1 }, // End fully opaque
143
- duration: "1s",
144
- timingFunction: "ease-in",
145
- },
146
- ];
147
-
148
- <View animate={simpleSequence} />
149
- ```
119
+ ### Attention Seekers & Effects
120
+ - `Animation.pulse()`
121
+ - `Animation.flash()`
122
+ - `Animation.shake()`
123
+ - `Animation.headShake()`
124
+ - `Animation.rubberBand()`
125
+ - `Animation.wobble()`
126
+ - `Animation.heartBeat()`
127
+ - `Animation.tada()`
128
+ - `Animation.jello()`
150
129
 
151
- And here's a more complex example:
152
-
153
- ```jsx
154
- const complexSequence = [
155
- {
156
- from: { opacity: 0, transform: "translateY(-100px)" },
157
- to: { opacity: 1, transform: "translateY(0)" },
158
- duration: "2s",
159
- timingFunction: "ease-in",
160
- },
161
- {
162
- from: { opacity: 1, transform: "translateY(100px)" },
163
- to: { opacity: 0, transform: "translateY(0)" },
164
- duration: "2s",
165
- timingFunction: "ease-out",
166
- },
167
- ];
168
-
169
- <View animate={complexSequence} />
170
- ```
130
+ ### Extrances & Exits
131
+ - `Animation.lightSpeedIn()`
132
+ - `Animation.lightSpeedOut()`
133
+ - `Animation.jackInTheBox()`
134
+ - `Animation.hinge()`
135
+ - `Animation.backInDown()`
136
+ - `Animation.backOutUp()`
171
137
 
172
- ## 7. Animation Trigger Control
138
+ ### Special / Scroll-Driven
139
+ - `Animation.shimmer()` - Loading shimmer effect
140
+ - `Animation.typewriter()` - Typing effect
141
+ - `Animation.blinkCursor()`
142
+ - `Animation.handWaveScroll()`
143
+ - `Animation.ctaCollapseScroll()`
144
+ - `Animation.fillTextScroll()`
173
145
 
174
- By default, animations trigger when elements are mounted (immediate animation). You can control this behavior with the `animateOn` prop.
146
+ ## 5. View Timeline Animations (Scroll-Driven)
175
147
 
176
- ### animateOn Prop
148
+ There are two ways to create animations that trigger on scroll into view:
149
+
150
+ ### 1. Using `animateOn="View"`
151
+ This works with any standard animation.
177
152
 
178
153
  ```jsx
179
- // Default: Animations trigger on mount (immediate)
180
- <View animate={Animation.fadeIn()} />
181
-
182
- // Explicitly set to trigger on mount (same as default)
183
- <View animate={Animation.fadeIn()} animateOn="Both" />
184
- <View animate={Animation.fadeIn()} animateOn="Mount" />
185
-
186
- // Trigger only when scrolling into viewport
187
154
  <View animate={Animation.fadeIn()} animateOn="View" />
188
155
  ```
189
156
 
190
- ### Benefits of Each Mode
191
-
192
- **Both / Mount (Default)**
193
- - ✅ **Immediate feedback** - Animates as soon as element appears
194
- - ✅ **Familiar behavior** - Works like traditional CSS animations
195
- - ✅ **No dependencies** - Works in all browsers
196
- - 📌 **Best for**: Hero sections, immediately visible content
197
-
198
- **View**
199
- - ✅ **Better performance** - Pure CSS, no JavaScript state
200
- - ✅ **No re-renders** - Browser handles visibility detection
201
- - ✅ **Scroll-triggered** - Animates when user scrolls to it
202
- - 📌 **Best for**: Content below the fold that should animate on scroll
203
-
204
- ### When to Use Each Mode
205
-
206
- ```jsx
207
- // Hero section - animate immediately
208
- <View animate={Animation.fadeIn()} animateOn="Mount">
209
- <Text>Welcome!</Text>
210
- </View>
211
-
212
- // Content card - animate on scroll into view
213
- <View animate={Animation.slideUp()} animateOn="View">
214
- <Text>This card animates when scrolled into view</Text>
215
- </View>
216
- ```
217
-
218
- ## 8. View Timeline Animations (CSS Scroll-Driven)
219
-
220
-
221
- App-Studio provides performant scroll-driven animations using CSS `animation-timeline: view()`. These animations trigger when elements enter/exit the viewport **without any JavaScript state or IntersectionObserver**.
222
-
223
- ### Benefits
224
-
225
- - ✅ **No JavaScript state** - Pure CSS, no `useState` or re-renders
226
- - ✅ **No IntersectionObserver** - Browser handles visibility detection
227
- - ✅ **Compositor thread** - Smooth 60fps animations
228
- - ✅ **JSON configurable** - Define animations as data
229
-
230
- ### Basic Usage
157
+ ### 2. Using `*OnView` Helper Functions
158
+ These are performant, pure CSS animations explicitly designed for entry/exit effects. Imported directly from `app-studio`.
231
159
 
232
160
  ```jsx
233
- import { fadeInOnView, slideUpOnView, scaleUpOnView } from 'app-studio';
161
+ import {
162
+ fadeInOnView,
163
+ slideUpOnView,
164
+ scaleUpOnView,
165
+ blurInOnView,
166
+ rotateInOnView,
167
+ revealOnView,
168
+ flipXOnView,
169
+ flipYOnView
170
+ } from 'app-studio';
234
171
 
235
- // Elements animate when scrolling into view
236
172
  <View animate={fadeInOnView()} />
237
173
  <View animate={slideUpOnView({ distance: '50px' })} />
238
- <View animate={scaleUpOnView({ scale: 0.8 })} />
174
+ <View animate={revealOnView()} /> // Clip-path reveal
239
175
  ```
240
176
 
241
- ### Available Presets
242
-
243
- | Function | Effect | Default Range |
244
- |----------|--------|---------------|
245
- | `fadeInOnView()` | Fade in | entry |
246
- | `fadeOutOnView()` | Fade out | exit |
247
- | `slideUpOnView()` | Slide up + fade | entry |
248
- | `slideDownOnView()` | Slide down + fade | entry |
249
- | `slideLeftOnView()` | Slide from left | entry |
250
- | `slideRightOnView()` | Slide from right | entry |
251
- | `scaleUpOnView()` | Scale up (0.9→1) | entry |
252
- | `scaleDownOnView()` | Scale down | entry |
253
- | `blurInOnView()` | Blur in | entry |
254
- | `blurOutOnView()` | Blur out | exit |
255
- | `rotateInOnView()` | Rotate + scale | entry |
256
- | `revealOnView()` | Clip-path reveal | entry |
257
- | `flipXOnView()` | 3D flip X | entry |
258
- | `flipYOnView()` | 3D flip Y | entry |
259
-
260
- ### Custom Options
261
-
262
- ```jsx
263
- // All presets accept customization options
264
- <View animate={fadeInOnView({
265
- duration: '1s',
266
- timingFunction: 'ease-out',
267
- delay: '0.2s',
268
- range: 'entry 0% entry 80%'
269
- })} />
270
-
271
- <View animate={slideUpOnView({ distance: '60px' })} />
272
- <View animate={blurInOnView({ blur: '20px' })} />
273
- <View animate={scaleUpOnView({ scale: 0.7 })} />
274
- ```
177
+ ## 6. Scroll Progress Animations
275
178
 
276
- ### Custom JSON Configuration
179
+ These animations are linked to the scroll position associated with a timeline (usually the nearest scroller). As you scroll active range, the animation progresses.
277
180
 
278
181
  ```jsx
279
- import { animateOnView } from 'app-studio';
280
-
281
- <View animate={animateOnView({
282
- keyframes: {
283
- from: { opacity: 0, transform: 'rotate(-10deg) scale(0.9)' },
284
- to: { opacity: 1, transform: 'rotate(0) scale(1)' }
285
- },
286
- timing: {
287
- duration: '0.8s',
288
- timingFunction: 'ease-out'
289
- },
290
- range: 'entry'
291
- })} />
292
- ```
182
+ // Text that fills efficiently as you scroll (requires CSS variable support)
183
+ <View animate={Animation.fillTextScroll()} />
293
184
 
294
- ### Entry and Exit Animations
185
+ // Image that unclips/expands as you scroll
186
+ <View animate={Animation.unclipScroll()} />
295
187
 
296
- ```jsx
297
- // Combine entry and exit animations
298
- <View animate={[
299
- fadeInOnView({ range: 'entry' }),
300
- fadeOutOnView({ range: 'exit' })
301
- ]} />
302
-
303
- <View animate={[
304
- slideUpOnView({ range: 'entry' }),
305
- blurOutOnView({ range: 'exit' })
306
- ]} />
188
+ // Item that fades in based on scroll progress
189
+ <View animate={Animation.fadeInScroll()} />
307
190
  ```
308
191
 
309
- ### Staggered Animations
192
+ ## 7. Event-Based Animations
193
+
194
+ You can trigger animations on interactions like hover, click, or focus using the `on` prop or underscore props (`_hover`, `_active`).
310
195
 
311
196
  ```jsx
312
- // Create staggered effects with delay
313
- {items.map((item, index) => (
314
- <View
315
- key={item.id}
316
- animate={slideUpOnView({ delay: `${index * 0.1}s` })}
317
- >
318
- {item.content}
319
- </View>
320
- ))}
197
+ <View
198
+ _hover={{
199
+ // Pulse animation while hovering
200
+ animate: Animation.pulse({ duration: '0.5s' }),
201
+ scale: 1.05
202
+ }}
203
+
204
+ on={{
205
+ click: {
206
+ animate: Animation.flash()
207
+ }
208
+ }}
209
+ >
210
+ <Text>Hover or Click Me</Text>
211
+ </View>
321
212
  ```
322
213
 
323
- ### Using Preset Configurations
214
+ ## 8. Custom Animation Sequences
215
+
216
+ You can create complex animation sequences by configuring keyframes directly.
324
217
 
325
218
  ```jsx
326
- import { viewAnimationPresets, createViewAnimation } from 'app-studio';
219
+ const customTwist = {
220
+ from: { transform: 'rotate(0deg) scale(1)' },
221
+ '50%': { transform: 'rotate(180deg) scale(1.5)' },
222
+ to: { transform: 'rotate(360deg) scale(1)' },
223
+ duration: '2s',
224
+ iterationCount: 'infinite'
225
+ };
327
226
 
328
- // Use predefined JSON configs
329
- <View animate={createViewAnimation(viewAnimationPresets.fadeIn)} />
330
- <View animate={createViewAnimation(viewAnimationPresets.slideUp)} />
331
- <View animate={createViewAnimation(viewAnimationPresets.reveal)} />
227
+ <View animate={customTwist} />
332
228
  ```
333
229
 
334
- ### Browser Support
335
-
336
- | Browser | Support |
337
- |---------|---------|
338
- | Chrome 115+ | ✅ Full |
339
- | Edge 115+ | ✅ Full |
340
- | Safari 17.4+ | ✅ Full |
341
- | Firefox 110+ | ⚠️ Partial |
342
-
343
- > **Note:** In unsupported browsers, elements appear without animation (graceful degradation).
344
-
345
230
  ## 9. Best Practices
346
231
 
347
-
348
- 1. **Performance**
349
- - Use view timeline animations (`fadeInOnView`, etc.) for scroll-triggered effects
350
- - Prefer transform and opacity animations for better performance
351
- - Avoid animating layout properties (width, height, margin)
352
-
353
- 2. **User Experience**
354
- - Keep animations short and subtle
355
- - Use appropriate timing functions for natural movement
356
- - Consider `prefers-reduced-motion` for accessibility
357
-
358
- 3. **Code Organization**
359
- - Define reusable animation configurations as JSON
360
- - Use meaningful names for custom sequences
361
- - Keep animation logic separate from component logic:
362
- ```jsx
363
- const myAnimation = fadeInOnView({ duration: '1s' });
364
- <View animate={myAnimation} />
365
- ```
366
-
367
- 4. **Responsive Design**
368
- - Adjust animation duration for different screen sizes
369
- - Consider disabling complex animations on mobile
370
- - Test animations on real devices
371
-
372
- 5. **View Timeline Animations**
373
- - Use for on-scroll reveal effects instead of `animateIn`
374
- - Combine entry and exit animations for complete interactions
375
- - Use staggered delays for list animations
232
+ 1. **Performance**: Prefer standard transforms (`translate`, `scale`, `rotate`) and `opacity`. Avoid animating layout properties like `width` or `margin`.
233
+ 2. **Scroll Animations**: Use `animateOn="View"` or `*OnView` helpers for "reveal" effects, as they run on the compositor thread and don't require JavaScript listeners.
234
+ 3. **Accessibility**: Respect user motion preferences.
235
+ 4. **Composability**: You can mix standard styles with animations.
236
+ ```jsx
237
+ <View
238
+ style={{ opacity: 0 }} // Initial state
239
+ animate={Animation.fadeIn({ delay: '0.5s', fillMode: 'forwards' })}
240
+ />
241
+ ```
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.46",
2
+ "version": "0.6.47",
3
3
  "name": "app-studio",
4
4
  "description": "App Studio is a responsive and themeable framework to build cross platform applications",
5
5
  "repository": "git@github.com:rize-network/app-studio.git",