You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add EaseText component for animated text with color interpolation
EaseText wraps EaseView + Text to provide native transform/opacity
animations on text with optional JS-side color interpolation.
- `animate` for transforms/opacity (native 60fps via EaseView)
- `interpolateColor` for smooth color transitions (JS rAF, opt-in)
- `style.color` for instant color changes (zero JS cost)
- All standard TextProps passthrough (numberOfLines, onPress, etc.)
- TextAnimateProps derived from AnimateProps (minus borderRadius/backgroundColor)
- useColorTransition hook with easing, delay, and spring approximation
- 4 example demos: Text Color, Floating Label, Text Enter, Text Props
- Updated AGENTS.md and migration skill with EaseText documentation
Copy file name to clipboardExpand all lines: AGENTS.md
+24-3Lines changed: 24 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
## Overview
4
4
5
-
`react-native-ease` is a React Native library that provides declarative, native-powered animations via a single `EaseView` component. It uses Core Animation (iOS) and ObjectAnimator/SpringAnimation (Android) — no JS animation loop, no worklets, no C++ runtime.
5
+
`react-native-ease` is a React Native library that provides declarative, native-powered animations via `EaseView` and `EaseText` components. It uses Core Animation (iOS) and ObjectAnimator/SpringAnimation (Android) — no JS animation loop, no worklets, no C++ runtime.
6
6
7
7
**Fabric (new architecture) only.** Does not support the old architecture.
8
8
@@ -11,6 +11,8 @@
11
11
```
12
12
src/ # TypeScript source (library)
13
13
EaseView.tsx # React component — flattens props to native
14
+
EaseText.tsx # Text component — EaseView wrapper + Text with color interpolation
15
+
useColorTransition.ts # JS-side color interpolation hook (requestAnimationFrame)
**Key design pattern:** All animation logic lives on the native side. The JS layer is purely a prop resolver — no animation state, no timers, no refs.
45
46
47
+
## EaseText Architecture
48
+
49
+
`EaseText` is a **JS-only component** — no native code. It composes `EaseView` (for native transforms/opacity) with a standard `<Text>` (for text rendering).
<Text style={{ color: interpolated }}> ← JS color interpolation
55
+
```
56
+
57
+
**Color:** Two modes:
58
+
-`style.color` — instant change, zero JS cost (same as `<Text>`)
59
+
-`interpolateColor` prop — smooth JS interpolation via `requestAnimationFrame`, follows the `color` key in `transition` (or falls back to `default`)
60
+
61
+
**Why not native text color animation:** Fabric's text rendering pipeline (`RCTParagraphComponentView` on iOS) manages text via `NSAttributedString` in the shadow tree. The `attributedText` is readonly — color can't be mutated from outside the Fabric commit cycle. Android's `ReactTextView.setTextColor()` works, but iOS doesn't. JS interpolation keeps behavior consistent cross-platform.
62
+
63
+
**TextAnimateProps:**`Omit<AnimateProps, 'borderRadius' | 'backgroundColor'>` — same transform/opacity props as EaseView. Color is handled separately via `interpolateColor`.
64
+
46
65
## Adding a New Animatable Property
47
66
48
67
1. Add to `AnimateProps` in `src/types.ts`
@@ -111,3 +130,5 @@ Use conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, etc.
111
130
-**Spring damping ratio on Android is derived** from `damping`, `stiffness`, and `mass` using: `dampingRatio = damping / (2 * sqrt(stiffness * mass))`. iOS passes these values directly to `CASpringAnimation`.
112
131
-**Animation batching:** Both platforms track animation batches with a generation ID. When new animations start, any pending old-batch callbacks are fired as interrupted (`finished: false`).
113
132
-**Loop only works with timing animations**, not springs. Loop requires `initialAnimate` to define the start value.
133
+
-**EaseText color has two modes:**`style.color` for instant changes (zero cost), `interpolateColor` prop for smooth JS interpolation via requestAnimationFrame. Transforms/opacity are always native via EaseView.
134
+
-**EaseText wraps EaseView + Text.** Layout behaves like a View containing a Text, not a bare Text. Use a wrapper View with `position: 'absolute'` for floating label patterns (see FloatingLabelDemo).
0 commit comments