Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add NativeWind plugin #841

Merged
merged 29 commits into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
004ec72
[WIP] feat: add NativeWind plugin
borisyankov Dec 19, 2024
e448df4
chore: setup
jbroma Dec 29, 2024
8037d67
fix: use nativewind import for now
jbroma Dec 29, 2024
5de053d
feat: working on webpack
jbroma Dec 29, 2024
1c4d3d7
chore: webpack setup alignment
jbroma Dec 29, 2024
6111fa5
fix: hmr with swc/rspack
jbroma Dec 30, 2024
37995c4
chore: cleanup and comments
jbroma Dec 30, 2024
de4f5a9
chore: cleanup tsconfig
jbroma Dec 30, 2024
f09f5fa
chore: cleanup in tester app
jbroma Dec 30, 2024
3001b8f
fix: double stringify
jbroma Dec 30, 2024
cad34da
chore: update Podfile.lock
borisyankov Jan 2, 2025
0414d8b
feat: add examples for NativeWind functionality
borisyankov Jan 2, 2025
c0319d0
feat: add a demo using NativeWind with RN Reusables
borisyankov Jan 2, 2025
81a029e
feat: add several more NativeWind features to tester app
borisyankov Jan 6, 2025
305f64e
fix: don't set ScriptManager storage in dev
borisyankov Jan 13, 2025
4f05b19
feat: set importSource to nativewind
jbroma Jan 17, 2025
506aa9f
chore: remove hardcoded nativewind in core
jbroma Jan 17, 2025
21f5403
chore: add missing clsx
jbroma Jan 17, 2025
a58e712
chore: make webpack tester app work with nativewind
jbroma Jan 17, 2025
51be68e
chore: update webpack config in tester app
jbroma Jan 17, 2025
8892d0d
chore: cleanup
jbroma Jan 17, 2025
d811f02
Merge remote-tracking branch 'origin/main' into feat/nativewind
jbroma Jan 17, 2025
e5963ea
chore: update podfile locks
jbroma Jan 17, 2025
69ffc7c
chore: update package.json
jbroma Jan 18, 2025
5bd2199
chore: update lockfile
jbroma Jan 18, 2025
75c6b69
chore: remove redundant README.md in tester-app
jbroma Jan 18, 2025
bb04431
chore: update README.md
jbroma Jan 18, 2025
63ee95c
chore: update babel config in tester app
jbroma Jan 18, 2025
155ff64
chore: add changeset
jbroma Jan 18, 2025
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
5 changes: 5 additions & 0 deletions .changeset/nervous-geese-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@callstack/repack": minor
---

Add support for NativeWind through a dedicated optional plugin called `@callstack/repack-plugin-nativewind`
9 changes: 9 additions & 0 deletions apps/tester-app/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
module.exports = {
presets: ['module:@react-native/babel-preset'],
comments: true,
plugins: [
[
'@babel/plugin-transform-react-jsx',
{
runtime: 'automatic',
importSource: 'nativewind',
},
],
],
};
26 changes: 26 additions & 0 deletions apps/tester-app/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

.custom-style-test {
color: mediumpurple;
}

.calc-element {
width: calc(var(--my-variable) - (20px + 2rem));
}

:root {
--H: 200;
--S: 50%;
--L: 40%;
--color-values: purple;
}

.color-element {
background-color: hsl(
calc(var(--H) + 20),
calc(var(--S) - 10%),
calc(var(--L) + 30%)
);
}
6 changes: 4 additions & 2 deletions apps/tester-app/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Script, ScriptManager } from '@callstack/repack/client';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { AppRegistry } from 'react-native';
import { name as appName } from './app.json';
import App from './src/App';

ScriptManager.shared.setStorage(AsyncStorage);
if (!__DEV__) {
ScriptManager.shared.setStorage(AsyncStorage);
}

ScriptManager.shared.addResolver((scriptId, _caller) => {
if (__DEV__) {
return {
Expand Down
78 changes: 74 additions & 4 deletions apps/tester-app/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PODS:
- boost (1.84.0)
- callstack-repack (5.0.0-rc.4):
- callstack-repack (5.0.0-rc.6):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -1266,6 +1266,72 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-safe-area-context (4.14.0):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- react-native-safe-area-context/common (= 4.14.0)
- react-native-safe-area-context/fabric (= 4.14.0)
- React-NativeModulesApple
- React-RCTFabric
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-safe-area-context/common (4.14.0):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-safe-area-context/fabric (4.14.0):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- react-native-safe-area-context/common
- React-NativeModulesApple
- React-RCTFabric
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- React-nativeconfig (0.76.3)
- React-NativeModulesApple (0.76.3):
- glog
Expand Down Expand Up @@ -1756,6 +1822,7 @@ DEPENDENCIES:
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
Expand Down Expand Up @@ -1871,6 +1938,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
React-microtasksnativemodule:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
React-nativeconfig:
:path: "../node_modules/react-native/ReactCommon"
React-NativeModulesApple:
Expand Down Expand Up @@ -1942,7 +2011,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
boost: 1dca942403ed9342f98334bf4c3621f011aa7946
callstack-repack: 8972107231b7175b8340e84ca0370aa2c735dcc7
callstack-repack: 99484a3f899fab09d6dc72bddb20c72f2ba4f948
DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385
FBLazyVector: be7314029d6ec6b90f0f75ce1195b8130ed9ac4f
fmt: 10c6e61f4be25dc963c36bd73fc7b1705fe975be
Expand Down Expand Up @@ -1978,6 +2047,7 @@ SPEC CHECKSUMS:
React-logger: 26155dc23db5c9038794db915f80bd2044512c2e
React-Mapbuffer: ad1ba0205205a16dbff11b8ade6d1b3959451658
React-microtasksnativemodule: e771eb9eb6ace5884ee40a293a0e14a9d7a4343c
react-native-safe-area-context: 2500e4fe998caad50ad3bc51ec23ef951308569e
React-nativeconfig: aeed6e2a8ac02b2df54476afcc7c663416c12bf7
React-NativeModulesApple: c5b7813da94136f50ef084fa1ac077332dcfc658
React-perflogger: 6afb7eebf7d9521cc70481688ccddf212970e9d3
Expand Down Expand Up @@ -2005,7 +2075,7 @@ SPEC CHECKSUMS:
React-utils: 2bcaf4f4dfe361344bce2fae428603d518488630
ReactCodegen: ae99a130606068ed40d1d9c0d5f25fda142a0647
ReactCommon: 89c87b343deacc8610b099ac764848f0ce937e3e
ReactNativeHost: ac28612b0443705f9aa90563ffb9647f5608613c
ReactNativeHost: 40da1d9878e16dd3b647d4c31e5afeb0ed84683d
ReactTestApp-DevSupport: 4aa6f6bc658a2577bcf896c63c411cb375b89d7d
ReactTestApp-Resources: 8d72c3deef156833760694a288ff334af4d427d7
RNCAsyncStorage: 3ad840f7b17b45ca7ebbbb0e80948564a9513315
Expand All @@ -2015,6 +2085,6 @@ SPEC CHECKSUMS:
SwiftyRSA: 8c6dd1ea7db1b8dc4fb517a202f88bb1354bc2c6
Yoga: f6dc1b6029519815d5516a1241821c6a9074af6d

PODFILE CHECKSUM: 591811811bdab95f1675c6871b0554706bf77020
PODFILE CHECKSUM: 6d7cbe03444d5e87210979fb32a0eca299d758fe

COCOAPODS: 1.15.2
3 changes: 3 additions & 0 deletions apps/tester-app/nativewind-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// <reference types="nativewind/types" />

// NOTE: This file should not be edited and should be committed with your source code. It is generated by NativeWind.
15 changes: 14 additions & 1 deletion apps/tester-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,23 @@
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.23.1",
"@rn-primitives/slot": "^1.1.0",
"@rn-primitives/types": "^1.1.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"nativewind": "^4.1.23",
"react": "18.3.1",
"react-native": "0.76.3",
"react-native-css-interop": "0.1.22",
"react-native-reanimated": "^3.16.3",
"react-native-svg": "15.8.0"
"react-native-safe-area-context": "^4.14.0",
"react-native-svg": "15.8.0",
"tailwind-merge": "^2.6.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@callstack/repack": "workspace:*",
"@callstack/repack-plugin-nativewind": "workspace:*",
"@callstack/repack-plugin-reanimated": "workspace:*",
"@react-native-community/cli": "15.0.1",
"@react-native-community/cli-platform-android": "15.0.1",
Expand All @@ -38,11 +47,15 @@
"@swc/helpers": "^0.5.13",
"@types/jest": "^29.5.12",
"@types/react": "^18.2.51",
"autoprefixer": "^10.4.20",
"execa": "^6.1.0",
"get-port": "^6.1.2",
"globby": "^13.1.2",
"http-server": "^14.1.1",
"postcss": "^8.4.49",
"postcss-loader": "^8.1.1",
"react-native-test-app": "^4.0.7",
"tailwindcss": "^3.4.17",
"terser-webpack-plugin": "^5.3.10",
"typescript": "^5.7.2",
"vitest": "^2.0.5",
Expand Down
4 changes: 3 additions & 1 deletion apps/tester-app/rspack.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { createRequire } from 'node:module';
import path from 'node:path';
import * as Repack from '@callstack/repack';
import { NativeWindPlugin } from '@callstack/repack-plugin-nativewind';
import { ReanimatedPlugin } from '@callstack/repack-plugin-reanimated';
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';

Expand Down Expand Up @@ -74,6 +75,7 @@ export default (env) => {
transform: {
react: {
runtime: 'automatic',
importSource: 'nativewind',
},
},
},
Expand Down Expand Up @@ -155,7 +157,6 @@ export default (env) => {
},
],
},

plugins: [
/**
* Configure other required and additional plugins to make the bundle
Expand Down Expand Up @@ -196,6 +197,7 @@ export default (env) => {
// }),
process.env.RSDOCTOR && new RsdoctorRspackPlugin(),
new ReanimatedPlugin(),
new NativeWindPlugin(),
].filter(Boolean),
};
};
12 changes: 9 additions & 3 deletions apps/tester-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { Appearance } from 'react-native';

import { AppContainer } from './ui/AppContainer';
import { Section } from './ui/Section';
import { SectionContainer } from './ui/SectionContainer';
// nativewind styles
import '../global.css';

import { AssetsTestContainer } from './assetsTest/AssetsTestContainer';
import { AsyncContainer } from './asyncChunks/AsyncContainer';
import { MiniAppsContainer } from './miniapp/MiniAppsContainer';
import { NativeWindView } from './nativewind/NativeWindView';
import { ReanimatedBox } from './reanimated/ReanimatedBox';
import { RemoteContainer } from './remoteChunks/RemoteContainer';
import { AppContainer } from './ui/AppContainer';
import { Section } from './ui/Section';
import { SectionContainer } from './ui/SectionContainer';

Appearance.setColorScheme('light');

Expand All @@ -31,6 +34,9 @@ const App = () => {
<Section title="Reanimated test">
<ReanimatedBox />
</Section>
<Section title="NativeWind test">
<NativeWindView />
</Section>
</SectionContainer>
</AppContainer>
);
Expand Down
16 changes: 16 additions & 0 deletions apps/tester-app/src/nativewind/Basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { StyleSheet, Text, View } from 'react-native';

export default function Basic() {
return (
<View className="bg-blue-100 p-5 rounded-full" style={styles.container}>
<Text className="custom-style-test">Colored through CSS!</Text>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
},
});
29 changes: 29 additions & 0 deletions apps/tester-app/src/nativewind/ComponentWithVariants.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Text } from 'react-native';

const variantStyles = {
default: 'rounded',
primary: 'bg-blue-500 text-white',
secondary: 'bg-white-500 text-black',
};

type Props = {
variant: keyof typeof variantStyles;
className?: string;
} & React.ComponentProps<typeof Text>;

export default function ComponentWithVariants({
variant,
className,
...props
}: Props) {
return (
<Text
className={`
${variantStyles.default}
${variantStyles[variant]}
${className}
`}
{...props}
/>
);
}
10 changes: 10 additions & 0 deletions apps/tester-app/src/nativewind/CustomComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Text } from 'react-native';

export default function CustomComponent({ className }: { className: string }) {
const defaultStyles = 'p-2 text-black dark:text-white';
return (
<Text className={`${defaultStyles} ${className}`}>
I am a custom component
</Text>
);
}
13 changes: 13 additions & 0 deletions apps/tester-app/src/nativewind/DarkMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { colorScheme } from 'nativewind';
import { Button } from 'react-native';

export default function DarkMode() {
return (
<Button
onPress={() => {
colorScheme.set('dark');
}}
title="Toggle dark mode"
/>
);
}
15 changes: 15 additions & 0 deletions apps/tester-app/src/nativewind/FuncsDirs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { vars } from 'nativewind';
import { Text, View } from 'react-native';

export default function FuncsDirs() {
return (
<>
<View style={vars({ '--my-custom-color': 'green' })}>
<Text className="text-custom">Custom color</Text>
</View>
<View className="p-2 calc-element color-element">
<Text>Calculated size</Text>
</View>
</>
);
}
Loading
Loading