diff --git a/.claude/skills/add-test/SKILL.md b/.claude/skills/add-test/SKILL.md new file mode 100644 index 0000000..f8c65e4 --- /dev/null +++ b/.claude/skills/add-test/SKILL.md @@ -0,0 +1,54 @@ +--- +name: add-test +description: Scaffold a test for a react-native-css feature following the project's testing conventions. +argument-hint: [feature-or-css-property] +allowed-tools: Read, Grep, Glob, Edit, Write +--- + +## Context + +react-native-css has three test domains in `src/__tests__/`: + +- `babel/` — Babel plugin tests using `babel-plugin-tester` +- `compiler/` — CSS compilation tests verifying JSON output +- `native/` — Runtime tests for style application + +## Conventions by domain + +### Babel tests (`src/__tests__/babel/`) + +Use `babel-plugin-tester`: + +```typescript +import { pluginTester } from "babel-plugin-tester"; + +pluginTester({ + plugin, + tests: { + "test name": { + code: `import { View } from 'react-native';`, + output: `import { View } from 'react-native-css/components';`, + }, + }, +}); +``` + +### Compiler tests (`src/__tests__/compiler/`) + +Verify CSS → JSON compilation output structure. + +### Native tests (`src/__tests__/native/`) + +Test runtime style application on native platform. + +## Steps + +1. **Identify the feature**: What needs testing? Use `$ARGUMENTS` as the starting point. + +2. **Determine the domain**: Is this a babel transform, compiler output, or runtime behavior? + +3. **Find existing tests**: Search the appropriate `src/__tests__/` subdirectory for similar tests. + +4. **Write the test**: Follow the conventions of the domain. + +5. **Run the test**: Execute `yarn test`. Note: ignore `ExperimentalWarning: VM Modules` warnings — they're expected. diff --git a/.claude/skills/architecture/SKILL.md b/.claude/skills/architecture/SKILL.md new file mode 100644 index 0000000..4ca3e15 --- /dev/null +++ b/.claude/skills/architecture/SKILL.md @@ -0,0 +1,32 @@ +--- +name: architecture +description: Explain the react-native-css architecture, compiler pipeline, and key files. Use when a contributor wants to understand how the codebase works. +allowed-tools: Read, Grep, Glob +--- + +You are explaining the architecture of **react-native-css** to a contributor. + +Start by reading `DEVELOPMENT.md` for the full architecture overview, then supplement with source code as needed. + +## How to explain + +1. **Start with the big picture**: react-native-css is a standalone CSS polyfill for React Native. It works independently of Tailwind — any `.css` file can be used. Nativewind v5 depends on this as its core engine. + +2. **Show the compiler pipeline**: Walk through how a CSS rule becomes a React Native style: + - Metro transformer intercepts `.css` files (`src/metro/metro-transformer.ts`) + - lightningcss parses the CSS AST + - `compile()` processes rules, media queries, keyframes, variables (`src/compiler/compiler.ts`) + - Output is a `ReactNativeCssStyleSheet` (JSON) + - Injection code registers styles with the native runtime (`src/metro/injection-code.ts`) + +3. **Explain the babel plugin**: It rewrites React Native imports so components get `className` support: + - `import { View } from 'react-native'` → `import { View } from 'react-native-css/components'` + +4. **Explain the runtime**: + - Reactive style system (`src/native/reactivity.ts`) — observables for media queries, color scheme + - StyleCollection singleton (`src/native-internal/`) — isolated to avoid circular deps + - Platform-aware: different outputs for native (JSON) vs web (browser CSS) + +5. **Show relevant code**: Read source files to illustrate. The compiler and runtime are the most complex parts. + +6. **Clarify the boundary**: This repo owns compilation, runtime, babel, and Metro integration. Nativewind adds Tailwind-specific theming on top. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..64fc1ea --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +## 3.0.5 (2026-03-15) + +* chore: add Claude Code skills for architecture and testing ([02bac92](https://github.com/nativewind/react-native-css/commit/02bac92)) +* chore: add conventional changelog for GitHub releases (#294) ([251cdfc](https://github.com/nativewind/react-native-css/commit/251cdfc)), closes [#294](https://github.com/nativewind/react-native-css/issues/294) +* chore(deps): bump basic-ftp from 5.0.5 to 5.2.0 (#286) ([930095f](https://github.com/nativewind/react-native-css/commit/930095f)), closes [#286](https://github.com/nativewind/react-native-css/issues/286) +* chore(deps): bump minimatch from 3.1.2 to 3.1.5 (#289) ([ae42457](https://github.com/nativewind/react-native-css/commit/ae42457)), closes [#289](https://github.com/nativewind/react-native-css/issues/289) +* chore(deps): bump tar from 7.5.9 to 7.5.11 (#296) ([431852a](https://github.com/nativewind/react-native-css/commit/431852a)), closes [#296](https://github.com/nativewind/react-native-css/issues/296) +* docs: add DEVELOPMENT.md and CLAUDE.md for contributor tooling ([ed4e5b3](https://github.com/nativewind/react-native-css/commit/ed4e5b3)) +* feat: add CSS @property rule support (#284) ([4ee27ab](https://github.com/nativewind/react-native-css/commit/4ee27ab)), closes [#284](https://github.com/nativewind/react-native-css/issues/284) +* feat: add inset shadow parsing support (#277) ([b0b35b1](https://github.com/nativewind/react-native-css/commit/b0b35b1)), closes [#277](https://github.com/nativewind/react-native-css/issues/277) +* fix(types): move @types/debug from devDependencies to dependencies (#290) ([43787dc](https://github.com/nativewind/react-native-css/commit/43787dc)), closes [#290](https://github.com/nativewind/react-native-css/issues/290) diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..95f4126 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,6 @@ +# Claude Code Context + +Read these files for project context: + +- @DEVELOPMENT.md — architecture, directory structure, commands, testing, pitfalls +- @CONTRIBUTING.md — contribution workflow, PR process, development notes diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..4ce5846 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,141 @@ +# react-native-css Development Guide + +## Project Overview + +A standalone CSS polyfill for React Native. Part of the Nativewind v5 ecosystem but can function independently of Tailwind CSS. Provides direct `.css` file support in React Native apps. + +### Relationship to Nativewind + +- **Nativewind** (`github.com/nativewind/nativewind`, main branch) provides the Tailwind CSS integration layer +- **This repo** provides the underlying CSS-to-React-Native engine +- Both are part of the v5 story, but this repo has no Tailwind dependency + +## Architecture + +``` +.css file + ↓ +Metro Transformer (src/metro/metro-transformer.ts) + ↓ delegates to Expo's CSS transformer +lightningcss parses CSS AST + ↓ +compile() in src/compiler/compiler.ts + ├→ parseMediaQuery() — media query conditions + ├→ parseContainerCondition() — container queries + ├→ parseDeclaration() — CSS properties → RN properties + ├→ extractKeyFrames() — animation extraction + └→ inlineVariables() — CSS variable optimization + ↓ +ReactNativeCssStyleSheet (JSON) + ↓ +getNativeInjectionCode() (src/metro/injection-code.ts) + ↓ +Native runtime consumes via StyleCollection +``` + +### Babel Plugin + +The Babel plugin (`src/babel/react-native.ts`) rewrites React Native imports: +``` +import { View } from 'react-native' + → import { View } from 'react-native-css/components' +``` +This enables `className` prop support on all React Native components. + +### Key Architectural Patterns + +- **Reactive style system** (`src/native/reactivity.ts`) — custom observables for media queries, container queries, color scheme changes +- **StyleCollection singleton** (`src/native-internal/`) — isolated to prevent circular dependencies between native runtime and CSS file imports +- **Platform-aware compilation** — different outputs for native (JSON) vs web (browser CSS) +- **Inline variable optimization** — single-use CSS variables are inlined at compile time; multi-use preserved + +## Package Entry Points + +| Import | Purpose | +|--------|---------| +| `react-native-css` | Runtime API | +| `react-native-css/compiler` | CSS-to-JSON compiler | +| `react-native-css/babel` | Babel plugin for import transformation | +| `react-native-css/metro` | `withReactNativeCSS()` Metro config | +| `react-native-css/components` | Pre-wrapped RN components with className support | +| `react-native-css/jest` | Jest test utilities | +| `react-native-css/native` | Native runtime API | +| `react-native-css/web` | Web runtime API | + +## Key Directories + +``` +src/ +├── babel/ # Babel plugin (rewrites RN imports) +├── compiler/ # CSS compilation engine (lightningcss-based) +│ ├── compiler.ts # Main entry +│ ├── declarations.ts # CSS property handling +│ ├── selectors.ts # Selector parsing +│ ├── media-query.ts # Media query parsing +│ ├── container-query.ts +│ ├── keyframes.ts # Animation extraction +│ └── inline-variables.ts +├── metro/ # Metro bundler integration +│ ├── metro-transformer.ts # Custom JS/CSS transformer +│ ├── resolver.ts # Module resolution +│ └── typescript.ts # TypeScript env generation +├── native/ # Native runtime (iOS/Android) +│ ├── api.tsx # styled(), useCssElement(), hooks +│ ├── reactivity.ts # Observable/reactive system +│ ├── styles/ # Runtime style resolution +│ ├── conditions/ # Media/container query evaluation +│ └── react/ # React integration hooks +├── native-internal/ # Shared singletons (avoids circular deps) +│ ├── root.ts # Global style collection root +│ ├── style-collection.ts +│ └── variables.tsx # CSS variable context +├── web/ # Web runtime +├── components/ # Pre-wrapped RN components (View, Text, etc.) +└── utilities/ # Type utilities (dot notation) +``` + +## Commands + +```bash +yarn # Install dependencies (npm is NOT supported) +yarn build # Build with react-native-builder-bob +yarn test # Run tests (Jest with ESM) +yarn typecheck # TypeScript validation +yarn lint --fix # ESLint + Prettier +yarn clean # Install deps, rebuild project and example app +``` + +### Example App + +```bash +yarn example ios # Build and run on iOS +yarn example android # Build and run on Android +yarn example start # Start Metro server +yarn example start:build # Rebuild library + start Metro (clears cache) +yarn example start:debug # Rebuild + start with debug logging +``` + +## Testing + +- **Runner:** Jest with experimental ESM support (`NODE_OPTIONS="--experimental-vm-modules"`) +- **Convention:** Tests in `src/__tests__/` organized by domain (`babel/`, `compiler/`, `native/`) +- **Babel tests** use `babel-plugin-tester` +- **Compiler tests** verify JSON output structure +- **Run specific suites:** `yarn test babel`, `yarn test compiler` +- Ignore `ExperimentalWarning: VM Modules` warnings — expected with ESM support + +## Code Conventions + +- TypeScript throughout +- **Yarn v4 only** — npm is not supported (enforced via `packageManager` field) +- Conventional commits required: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`, `chore:` +- Pre-commit hooks enforce linting and commit message format +- Publishing via `release-it` + +## Common Pitfalls + +- **No npm** — this repo uses Yarn workspaces; `npm install` will not work +- **No rebuild watch** — use `yarn example start:build` to rebuild + start in one command +- **Metro transformer / Babel plugin changes require full rebuild** — no fast refresh for these +- **native-internal exists to break circular deps** — don't import directly from `native/` in CSS file outputs; use `native-internal/` +- **Nested node_modules in example/** — can cause Metro issues; ensure dependency versions match root