diff --git a/README.md b/README.md index 09caee6..116727c 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ All properties are set in the `animate` prop as flat values (no transform array) `scale` is a shorthand that sets both `scaleX` and `scaleY`. When `scaleX` or `scaleY` is also specified, it overrides the `scale` value for that axis. -You can animate any combination of properties simultaneously. All properties share the same transition config. +You can animate any combination of properties simultaneously. Use a single transition config for all properties, or a [per-property map](#per-property-transitions) for different configs per category. ### Looping Animations @@ -415,10 +415,11 @@ A `View` that animates property changes using native platform APIs. | ------------------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | `animate` | `AnimateProps` | Target values for animated properties | | `initialAnimate` | `AnimateProps` | Starting values for enter animations (animates to `animate` on mount) | -| `transition` | `Transition` | Animation configuration (timing, spring, or none) | +| `transition` | `Transition` | Animation configuration — a single config (timing, spring, or none) or a [per-property map](#per-property-transitions) | | `onTransitionEnd` | `(event) => void` | Called when all animations complete with `{ finished: boolean }` | | `transformOrigin` | `{ x?: number; y?: number }` | Pivot point for scale/rotation as 0–1 fractions. Default: `{ x: 0.5, y: 0.5 }` (center) | | `useHardwareLayer` | `boolean` | Android only — rasterize to GPU texture during animations. See [Hardware Layers](#hardware-layers-android). Default: `false` | +| `className` | `string` | NativeWind / Tailwind CSS class string. Requires NativeWind in your project. | | `style` | `ViewStyle` | Non-animated styles (layout, colors, borders, etc.) | | `children` | `ReactNode` | Child elements | | ...rest | `ViewProps` | All other standard View props | @@ -475,6 +476,18 @@ Properties not specified in `animate` default to their identity values. Applies values instantly with no animation. `onTransitionEnd` fires immediately with `{ finished: true }`. +### `TransitionMap` + +A per-property map that applies different transition configs to different property categories. See [Per-Property Transitions](#per-property-transitions). + +| Key | Properties | +| ----------------- | ---------------------------------------------------------------- | +| `default` | Fallback for categories not explicitly listed | +| `transform` | translateX, translateY, scaleX, scaleY, rotate, rotateX, rotateY | +| `opacity` | opacity | +| `borderRadius` | borderRadius | +| `backgroundColor` | backgroundColor | + ## Hardware Layers (Android) Setting `useHardwareLayer` rasterizes the view into a GPU texture for the duration of the animation. This means animated property changes (opacity, scale, rotation) are composited on the RenderThread without redrawing the view hierarchy — useful for complex views with many children. diff --git a/skills/react-native-ease-refactor/SKILL.md b/skills/react-native-ease-refactor/SKILL.md index 3c65981..16bc60d 100644 --- a/skills/react-native-ease-refactor/SKILL.md +++ b/skills/react-native-ease-refactor/SKILL.md @@ -58,7 +58,7 @@ Apply these checks in order. The first match determines the result: 6. **Uses complex `interpolate()`?** (more than 2 input/output values) → NOT migratable — "Complex interpolation" 7. **Uses `layout={...}` prop?** → NOT migratable — "Layout animation" 8. **Animates unsupported properties?** (anything besides: opacity, translateX, translateY, scale, scaleX, scaleY, rotate, rotateX, rotateY, borderRadius, backgroundColor) → NOT migratable — "Animates unsupported property: ``" -9. **Uses different transition configs per property?** (e.g., opacity uses 200ms timing, scale uses spring) → NOT migratable — "Per-property transition configs" +9. **Uses different transition configs per property?** (e.g., opacity uses 200ms timing, scale uses spring) → MIGRATABLE — map to `TransitionMap` with category keys (`transform`, `opacity`, `borderRadius`, `backgroundColor`, `default`) 10. **Not driven by state?** (animation triggered by gesture/scroll value, not React state) → NOT migratable — "Not state-driven" 11. **Otherwise** → MIGRATABLE @@ -87,6 +87,7 @@ Use this table to convert Reanimated/Animated patterns to EaseView: | `Animated.Value` + `Animated.spring` | `animate` + `transition={{ type: 'spring' }}` — convert to state-driven | | `withDelay(ms, withTiming(...))` or `withDelay(ms, withSpring(...))` | `transition={{ ..., delay: ms }}` — add `delay` to the transition config | | `entering={FadeIn.delay(ms)}` / any entering preset with `.delay()` | `initialAnimate` + `animate` + `transition={{ ..., delay: ms }}` | +| Different `withTiming`/`withSpring` per property in `useAnimatedStyle` | `transition={{ opacity: { type: 'timing', ... }, transform: { type: 'spring', ... } }}` (per-property map) | ### Default Value Mapping @@ -391,15 +392,16 @@ transition={{ type: 'none' }} - `animate` — target values for animated properties - `initialAnimate` — starting values (animates to `animate` on mount) -- `transition` — animation config (timing or spring) +- `transition` — animation config: a single `SingleTransition` (timing/spring/none) OR a `TransitionMap` with category keys (`default`, `transform`, `opacity`, `borderRadius`, `backgroundColor`) - `onTransitionEnd` — callback with `{ finished: boolean }` - `transformOrigin` — pivot point as `{ x: 0-1, y: 0-1 }`, default center - `useHardwareLayer` — Android GPU optimization (boolean, default false) +- `className` — NativeWind / Tailwind CSS class string (requires NativeWind in the project) ### Important Constraints - **Loop requires timing** (not spring) and `initialAnimate` must define the start value -- **No per-property transitions** — one transition config applies to all animated properties +- **Per-property transitions supported** — pass a `TransitionMap` with category keys (`default`, `transform`, `opacity`, `borderRadius`, `backgroundColor`) to use different configs per property group - **No animation sequencing** — no equivalent to `withSequence`. Simple `withDelay` IS supported via the `delay` transition prop - **No gesture/scroll-driven animations** — EaseView is state-driven only - **Style/animate conflict** — if a property appears in both `style` and `animate`, the animated value wins