Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,28 @@ The skill will:
4. Let you select which components to migrate
5. Apply the changes, preserving all non-animation logic

### NativeWind Support

If you're using [NativeWind](https://www.nativewind.dev/) (v4+), add this import once in your app's entry point (e.g., `_layout.tsx` or `App.tsx`):

```tsx
import 'react-native-ease/nativewind';
```

This registers `EaseView` with NativeWind's `cssInterop` so `className` is properly converted to styles:

```tsx
<EaseView
className="flex-1 bg-white rounded-2xl p-4"
animate={{ opacity: visible ? 1 : 0 }}
transition={{ type: 'timing', duration: 300 }}
>
{children}
</EaseView>
```

> **Tip:** If you use the [migration skill](#migration-skill), it detects NativeWind automatically and adds this import for you.

### Example

```tsx
Expand Down
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"types": "./lib/typescript/src/index.d.ts",
"default": "./lib/module/index.js"
},
"./nativewind": {
"source": "./src/nativewind.ts",
"types": "./lib/typescript/src/nativewind.d.ts",
"default": "./lib/module/nativewind.js"
},
"./package.json": "./package.json"
},
"files": [
Expand Down Expand Up @@ -97,9 +102,15 @@
"typescript": "^5.9.2"
},
"peerDependencies": {
"nativewind": ">=4",
"react": "*",
"react-native": "*"
},
"peerDependenciesMeta": {
"nativewind": {
"optional": true
}
},
"workspaces": [
"example"
],
Expand Down
10 changes: 9 additions & 1 deletion skills/react-native-ease-refactor/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ Follow these 6 phases exactly. Do not skip phases or reorder them.

Scan the user's project for animation code:

1. Use Grep to find all files importing from `react-native-reanimated`:
1. Use Grep to detect if the project uses NativeWind:

- Pattern: `from ['"]nativewind['"]` in `**/*.{ts,tsx,js,jsx}`
- Also check `package.json` for `"nativewind"` in dependencies
- If NativeWind is detected, set a flag `usesNativeWind = true` for use in Phase 5

2. Use Grep to find all files importing from `react-native-reanimated`:

- Pattern: `from ['"]react-native-reanimated['"]`
- Search in `**/*.{ts,tsx,js,jsx}`
Expand Down Expand Up @@ -251,6 +257,8 @@ For each confirmed component, apply the migration:
import { EaseView } from 'react-native-ease';
```

1b. **If `usesNativeWind` is true**, check if `import 'react-native-ease/nativewind'` already exists in the project (search all files). If not, add it to the app's root entry point (e.g., `_layout.tsx`, `App.tsx`, or `index.tsx` — whichever is the earliest entry). This only needs to be done once across all migrations, not per component.

2. **Replace the animated view:**

- `Animated.View` → `EaseView`
Expand Down
23 changes: 23 additions & 0 deletions src/__tests__/nativewind.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const mockCssInterop = jest.fn();

jest.mock(
'nativewind',
() => ({
cssInterop: mockCssInterop,
}),
{ virtual: true },
);

// Import after mock is set up
import { EaseView } from '../EaseView';

describe('nativewind entry point', () => {
it('calls cssInterop with EaseView and className → style mapping', () => {
require('../nativewind');

expect(mockCssInterop).toHaveBeenCalledTimes(1);
expect(mockCssInterop).toHaveBeenCalledWith(EaseView, {
className: 'style',
});
});
});
5 changes: 5 additions & 0 deletions src/nativewind.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @ts-ignore – nativewind is an optional peer dependency
import { cssInterop } from 'nativewind';
import { EaseView } from './EaseView';

cssInterop(EaseView, { className: 'style' });
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"compilerOptions": {
"rootDir": ".",
"paths": {
"react-native-ease": ["./src/index"]
"react-native-ease": ["./src/index"],
"react-native-ease/nativewind": ["./src/nativewind"]
},
"allowUnreachableCode": false,
"allowUnusedLabels": false,
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13310,8 +13310,12 @@ __metadata:
turbo: "npm:^2.5.6"
typescript: "npm:^5.9.2"
peerDependencies:
nativewind: ">=4"
react: "*"
react-native: "*"
peerDependenciesMeta:
nativewind:
optional: true
languageName: unknown
linkType: soft

Expand Down
Loading