-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
React Native Web: Add framework, CLI integration, sandboxes #29520
Changes from all commits
949c687
59c10e8
4000182
0395ef8
6f9594f
ffdd93c
8031950
d94c342
2e504c0
531b4b0
ea86393
bb359ef
3204bec
c92aa93
cc9b1b2
654e0ed
e33053f
3efc796
907fe38
4fb8b02
ee7b69f
e85c723
fb477fd
b07a464
38c6859
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Storybook for React Native Web & Vite | ||
|
||
See [documentation](https://storybook.js.org/docs/get-started/frameworks/react-native-web-vite?renderer=react-native-web) for installation instructions, usage examples, APIs, and more. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
{ | ||
"name": "@storybook/react-native-web-vite", | ||
"version": "8.5.0-alpha.5", | ||
"description": "Develop react-native components an isolated web environment with hot reloading.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. syntax: typo in description: 'an isolated' should be 'in an isolated' |
||
"keywords": [ | ||
"storybook" | ||
], | ||
"homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/react-native-web-vite", | ||
"bugs": { | ||
"url": "https://github.com/storybookjs/storybook/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/storybookjs/storybook.git", | ||
"directory": "code/frameworks/react-native-web-vite" | ||
}, | ||
"funding": { | ||
"type": "opencollective", | ||
"url": "https://opencollective.com/storybook" | ||
}, | ||
"license": "MIT", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"node": "./dist/index.js", | ||
"import": "./dist/index.mjs", | ||
"require": "./dist/index.js" | ||
}, | ||
"./preset": { | ||
"types": "./dist/preset.d.ts", | ||
"require": "./dist/preset.js" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"main": "dist/index.js", | ||
"module": "dist/index.mjs", | ||
"types": "dist/index.d.ts", | ||
"files": [ | ||
"dist/**/*", | ||
"template/cli/**/*", | ||
"README.md", | ||
"*.js", | ||
"*.d.ts", | ||
"!src/**/*" | ||
], | ||
"scripts": { | ||
"check": "jiti ../../../scripts/prepare/check.ts", | ||
"prep": "jiti ../../../scripts/prepare/bundle.ts" | ||
}, | ||
"dependencies": { | ||
"@joshwooding/vite-plugin-react-docgen-typescript": "0.3.0", | ||
"@storybook/builder-vite": "workspace:*", | ||
"@storybook/react": "workspace:*", | ||
"@storybook/react-vite": "workspace:*", | ||
"@vitejs/plugin-react": "^4.3.2" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^22.0.0", | ||
"typescript": "^5.3.2" | ||
}, | ||
"peerDependencies": { | ||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", | ||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", | ||
"react-native": ">=0.74.5", | ||
"react-native-web": "^0.19.12", | ||
"storybook": "workspace:^", | ||
"vite": "^5.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=18.0.0" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for the allowed engine. Since this is a new framework, let's not support Node 18 anymore. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm more comfortable making the switch along with all the other frameworks. |
||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"bundler": { | ||
"entries": [ | ||
"./src/index.ts", | ||
"./src/preset.ts" | ||
], | ||
"platform": "node" | ||
}, | ||
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('./dist/preset'); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "react-native-web-vite", | ||
"$schema": "../../node_modules/nx/schemas/project-schema.json", | ||
"projectType": "library", | ||
"targets": { | ||
"build": {} | ||
} | ||
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Build target is empty. Consider adding standard NX build configuration like executor, options, and configurations for proper build integration. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type { FrameworkOptions, StorybookConfig } from './types'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// @ts-expect-error FIXME | ||
import { viteFinal as reactViteFinal } from '@storybook/react-vite/preset'; | ||
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: TODO needs to be addressed - ts-expect-error should be removed by properly typing the import |
||
|
||
import type { BabelOptions, Options as ReactOptions } from '@vitejs/plugin-react'; | ||
import react from '@vitejs/plugin-react'; | ||
import type { PluginOption } from 'vite'; | ||
|
||
import type { FrameworkOptions, StorybookConfig } from './types'; | ||
|
||
function reactNativeWeb( | ||
reactOptions: Omit<ReactOptions, 'babel'> & { babel?: BabelOptions } | ||
): PluginOption { | ||
return { | ||
name: 'vite:react-native-web', | ||
config(_userConfig, env) { | ||
return { | ||
define: { | ||
// reanimated support | ||
'global.__x': {}, | ||
_frameTimestamp: undefined, | ||
_WORKLET: false, | ||
__DEV__: `${env.mode === 'development'}`, | ||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || env.mode), | ||
}, | ||
optimizeDeps: { | ||
include: [], | ||
esbuildOptions: { | ||
Comment on lines
+26
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: empty include array may cause optimization issues - consider adding common dependencies |
||
jsx: 'transform', | ||
resolveExtensions: [ | ||
'.web.js', | ||
'.web.ts', | ||
'.web.tsx', | ||
'.js', | ||
'.jsx', | ||
'.json', | ||
'.ts', | ||
'.tsx', | ||
'.mjs', | ||
], | ||
loader: { | ||
'.js': 'jsx', | ||
}, | ||
}, | ||
}, | ||
resolve: { | ||
extensions: [ | ||
'.web.js', | ||
'.web.ts', | ||
'.web.tsx', | ||
'.js', | ||
'.jsx', | ||
'.json', | ||
'.ts', | ||
'.tsx', | ||
'.mjs', | ||
], | ||
alias: { | ||
'react-native': 'react-native-web', | ||
}, | ||
}, | ||
}; | ||
}, | ||
}; | ||
} | ||
|
||
export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) => { | ||
const { pluginReactOptions = {} } = | ||
await options.presets.apply<FrameworkOptions>('frameworkOptions'); | ||
|
||
const reactConfig = await reactViteFinal(config, options); | ||
const { plugins = [] } = reactConfig; | ||
|
||
plugins.unshift( | ||
react({ | ||
babel: { | ||
babelrc: false, | ||
configFile: false, | ||
}, | ||
jsxRuntime: 'automatic', | ||
...pluginReactOptions, | ||
}) | ||
); | ||
plugins.push(reactNativeWeb(pluginReactOptions)); | ||
|
||
return reactConfig; | ||
}; | ||
|
||
export const core = { | ||
builder: '@storybook/builder-vite', | ||
renderer: '@storybook/react', | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import type { CompatibleString } from 'storybook/internal/types'; | ||
|
||
import type { | ||
FrameworkOptions as FrameworkOptionsBase, | ||
StorybookConfig as StorybookConfigBase, | ||
} from '@storybook/react-vite'; | ||
|
||
import type { BabelOptions, Options as ReactOptions } from '@vitejs/plugin-react'; | ||
|
||
export type FrameworkOptions = FrameworkOptionsBase & { | ||
pluginReactOptions?: Omit<ReactOptions, 'babel'> & { babel?: BabelOptions }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: pluginReactOptions type allows overriding babel options which could break React Native Web compatibility |
||
}; | ||
|
||
type FrameworkName = CompatibleString<'@storybook/react-native-web-vite'>; | ||
|
||
/** The interface for Storybook configuration in `main.ts` files. */ | ||
export type StorybookConfig = Omit<StorybookConfigBase, 'framework'> & { | ||
framework: | ||
| FrameworkName | ||
| { | ||
name: FrameworkName; | ||
options: FrameworkOptions; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"rules": { | ||
"import/extensions": "off", | ||
"react/no-unknown-property": "off", | ||
"react/react-in-jsx-scope": "off" | ||
} | ||
Comment on lines
+2
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider adding additional React Native Web specific ESLint rules like react-native/no-inline-styles or react-native/no-raw-text |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Documentation URL uses 'react-native-web' as renderer but framework uses 'react' renderer internally. Consider aligning these or documenting the difference.