Compare commits

...

33 Commits
0.8.8 ... 0.9.3

Author SHA1 Message Date
Nicolas Gallagher
d6e8530f4d 0.9.3 2018-10-11 17:40:41 -07:00
Charlie Croom
ad188a7ad6 [fix] Memory leak in applyLayout registry
Remove component instances from the layout registry when umounting views
that are using ResizeObserver.

Fix #1133
Close #1134
2018-10-11 17:35:04 -07:00
Nicolas Gallagher
bfaeae904e [add] View/Text prop nativeID
Maps the View and Text prop 'nativeID' to DOM 'id' as these are
equivalent.  Enables declarative use of various 'aria-*' properties that
require ID references.

Ref #1116
Close #1130
2018-10-11 17:33:08 -07:00
Nicolas Gallagher
a54bdeec09 0.9.2 2018-10-09 18:02:55 -07:00
atp
8fa7dc63ec [add] TextInput support for 'caretColor' CSS property
Close #1127
2018-10-09 17:59:57 -07:00
Bruno Lemos
d841db2337 [fix] VirtualizedList sticky header support
The way that sticky headers work on web requires the ScrollView to apply
'position:sticky' to a clone of the element. This wasn't working for
VirtualizedList because the style prop was not passed to the default
CellRendererComponent implementation.

Fix #1066
Close #1122
2018-10-09 17:54:10 -07:00
Rick
8e7d31cff5 [fix] ignore native-only TextInput props
TextInput inherits ViewPropTypes but many of them do nothing (even in
React Native).

Close #1123
2018-10-09 17:46:19 -07:00
Nicolas Gallagher
0764687a8f [fix] VirtualizedList disabled virtualization in tests
Fix #1077
Close #1118
2018-10-09 17:37:02 -07:00
Charlie Croom
d31bdf2cf8 [fix] ResizeObserve only on elements using 'onLayout' prop
Only observe nodes when the 'onLayout' prop is specified on the
element. Fixes performance regression for browsers that rely on
MutationObserver-based shim for ResizeObserver.

Fix #1128
Close #1129
2018-10-09 17:31:32 -07:00
Nicolas Gallagher
1f3a77dada 0.9.1 2018-09-27 14:30:26 -07:00
Nicolas Gallagher
c3cbd53a8a [fix] ResponderEventPlugin removal of emulated mouse events
If the work related to a touch/press event takes a long enough time
(i.e., CPU intensive, old device, etc.) the browser may produce emulated
mouse events >500ms after the original touch event. This causes the
related Responder events to fire twice. To avoid that happening, this
patch increases the filter threshold used by the ResponderEventPlugin
from 200ms to 1000ms.

Fix #1078
2018-09-22 16:33:46 -07:00
Nicolas Gallagher
4f5ee15e4b Fix website TouchableHighlight example 2018-09-22 16:20:49 -07:00
Nicolas Gallagher
9a1cade1f0 0.9.0 2018-09-17 10:55:16 -07:00
Nicolas Gallagher
506dba933c [change] Support React DOM 16.5
React DOM 16.5 changed unstable APIs that this project depends upon.
This regression was fixed in React DOM 16.5.1 but requires React Native
for Web to migrate to a different unstable API exported by React DOM.

Fix #1096
Close #1106
2018-09-17 10:16:33 -07:00
Nicolas Gallagher
c0de9dddf3 0.8.11 2018-09-17 09:47:04 -07:00
David Calhoun
96c9c06272 Update the Docz integration link
Close #1102
2018-09-17 09:37:32 -07:00
Charlie Croom
505e3faee8 [fix] 'menuitem' role supports Enter/Space keyboard interaction
The 'menuitem' ARIA role should support Enter/Space keyboard interaction
as if it were a button. This is required because the ARIA spec makes it
so that the ARIA properties of 'menuitem' children are ignored, i.e.,
you can't just wrap a button in a 'menuitem' and expect Assistive
Technologies to surface the button to users.

Fix #1068
Close #1069
2018-09-17 09:30:06 -07:00
Nicolas Gallagher
1f06229289 [fix] react-native-web@0.8 pinned to React 16.4 2018-09-17 08:47:37 -07:00
Nicolas Gallagher
fc743e6eee Fix sandbox placeholder 2018-09-17 08:44:52 -07:00
Tomoya Hirano
ef97adec6e [fix] Picker doesn't pass 'onValueChange' to DOM node
Fix #1104
Close #1107
2018-09-17 08:19:13 -07:00
Nicolas Gallagher
f196335281 0.8.10 2018-09-09 13:10:51 -07:00
Anton Nyman
d29e31d9d6 [fix] better cross-browser support for textDecoration styles
Safari requires '-webkit' prefixes for CSS3 text-decoration styles, and
IE/Edge only support CSS2 text-decoration styles. This patch provides a
fallback for the CSS2 case and relies on the CSS3 properties for color
and style.

Close #1053

Co-authored-by: Nicolas Gallagher <nicolasgallagher@gmail.com>
2018-09-09 12:03:10 -07:00
Nicolas Gallagher
c7c1f29016 Reorganize documentation
Close #1092
Close #1095
2018-09-09 11:33:09 -07:00
Nicolas Gallagher
b56a737d62 [fix] prevent findNodeHandle throwing on unmounted components
Fix #1097
2018-09-09 11:11:18 -07:00
Nicolas Gallagher
f062eded40 [fix] Switch applies accessibilityLabel to native control
VoiceOver requires that the aria-label for the checkbox is applied to
the checkbox itself and not a wrapping element.

Fix #1072
2018-08-17 15:16:38 -07:00
Nicolas Gallagher
fcc4fbf678 [fix] TextInput defaults to numberOfLines={1} for multiline
Fix #1071
2018-08-17 11:23:23 -07:00
James Long
a18d30c809 [fix] Add inputAccessoryViewID to TextInput props
Close #1076
2018-08-17 11:12:56 -07:00
Marcel Miranda Ackerman
b9172ceb8e [fix] Image EncodingError for SVG in Safari iOS 11
Fixes an EncodingError exception being thrown in Safari iOS 11 when
decoding an SVG URL. The exception prevents the onLoad handler from
being called.

Close #1063
2018-08-17 11:09:32 -07:00
Michael S. Kazmier
744aaa26d4 [fix] Picker supports View props
Close #1064
2018-08-17 11:07:22 -07:00
Justine De Caires
2b5ddf753e [add] objectFit and objectPosition to style validation
Close #1046
2018-08-17 10:58:05 -07:00
Ben Milman
b84e3b938a Fix typo in docs
Close #1049
2018-08-17 10:56:54 -07:00
Nicolas Gallagher
9c8407162e 0.8.9 2018-07-19 12:32:40 -07:00
Jeremy
16b9ec2917 [fix] nested ScrollView scroll behaviour propagation
Allow ScrollView to be scrolled from gestures originating in a
descendent ScrollView.

Fix #1042
Close #1043
2018-07-19 12:17:42 -07:00
48 changed files with 817 additions and 597 deletions

View File

@@ -33,6 +33,9 @@ Steps to reproduce:
**Expected behavior**
<!--
REQUIRED: A clear and concise description of what you expected to happen.
Please check that the behaviour is not expected React Native behaviour by
running your test case on iOS or Android using https://snack.expo.io.
-->
**Environment (include versions). Did this work in previous versions?**

217
README.md
View File

@@ -25,7 +25,7 @@ using Node.js.
Who is using React Native in production web apps?
[Twitter](https://mobile.twitter.com), [Major League
Soccer](https://matchcenter.mlssoccer.com),
[Flipkart](https://www.flipkart.com/), Playstation, Uber, [The
[Flipkart](https://www.flipkart.com/), Uber, [The
Times](https://github.com/newsuk/times-components).
Browser support: Chrome, Firefox, Edge, Safari 7+, IE 10+.
@@ -38,34 +38,56 @@ The easiest way to get started is to edit this
anything to try it out.
For installation and configuration details please read the [getting
started](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/getting-started.md)
started](https://github.com/necolas/react-native-web/blob/master/docs/guides/getting-started.md)
guide.
## Documentation
You can find the API documentation [on the website][website-url].
Please refer to the [React Native documentation][react-native-url] for more
design details, and for information about the [Gesture Responder
Please refer to the [React Native documentation][react-native-url] for the
overall API, design details, and information about the [Gesture Responder
system](https://facebook.github.io/react-native/docs/gesture-responder-system.html)
and [animations](https://facebook.github.io/react-native/docs/animations.html).
Some components and APIs are extended with additional features for the web. And
in a few cases, features present for Android or iOS are missing on the web.
These differences are documented [on the website][website-url].
### Guides
* [Getting started](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/getting-started.md)
* [Style](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/style.md)
* [Accessibility](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/accessibility.md)
* [Internationalization](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/internationalization.md)
* [Direct manipulation](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/direct-manipulation.md)
* [Experimental / unstable use](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/advanced.md)
These guides provide a detailed look at using React Native to create accessible
web experiences. Certain web-specific patterns are documented in the "web
recipes" guide.
* [Getting started](https://github.com/necolas/react-native-web/blob/master/docs/guides/getting-started.md)
* [Client-side rendering](https://github.com/necolas/react-native-web/blob/master/docs/guides/client-side-rendering.md)
* [Server-side rendering](https://github.com/necolas/react-native-web/blob/master/docs/guides/server-side-rendering.md)
* [Style](https://github.com/necolas/react-native-web/blob/master/docs/guides/style.md)
* [Accessibility](https://github.com/necolas/react-native-web/blob/master/docs/guides/accessibility.md)
* [Internationalization](https://github.com/necolas/react-native-web/blob/master/docs/guides/internationalization.md)
* [Direct manipulation](https://github.com/necolas/react-native-web/blob/master/docs/guides/direct-manipulation.md)
* [Web recipes](https://github.com/necolas/react-native-web/blob/master/docs/guides/web-recipes.md)
* [Multi-platform apps](https://github.com/necolas/react-native-web/blob/master/docs/guides/multi-platform-apps.md)
* [Experimental / unstable use](https://github.com/necolas/react-native-web/blob/master/docs/guides/advanced.md)
## Integrations
Examples of using React Native for Web with other web tools:
* [Docz](https://github.com/pedronauck/docz-plugin-react-native)
* [Gatsby](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-react-native-web)
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web)
* [Phenomic](https://github.com/phenomic/phenomic/tree/master/examples/react-native-web-app)
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
* [Storybook](https://github.com/necolas/react-native-web/tree/master/packages/website/storybook/.storybook)
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
## Examples
There are examples [on the website][website-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/website).
And all the [React Native examples][examples-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/examples))
are also available. Here is an example to get you started:
Check out all the [React Native examples][examples-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/examples)).
There are more examples [on the website][website-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/website)).
And here is a simple example to get you started:
```js
import React from 'react';
@@ -96,104 +118,87 @@ You'll notice that there is no reference to `react-dom`; the `App` component is
defined using the platform-agnostic APIs and Components introduced by React
Native. This allows the app to be rendered to web and native platforms.
## Integrations
Examples of using React Native for Web with other web tools:
* [Gatsby](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-react-native-web)
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web)
* [Phenomic](https://github.com/phenomic/phenomic/tree/master/examples/react-native-web-app)
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
* [Storybook](https://github.com/necolas/react-native-web/tree/master/packages/website/storybook/.storybook)
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
Example recipes for web-specific UI patterns:
* [Links](https://codesandbox.io/s/53r88k5opx)
* [Hover styles](https://codesandbox.io/s/o9q8vy70l5)
* [Root element styles](https://codesandbox.io/s/52x1871vjl)
## Compatibility with React Native
React Native v0.55
### Components
| Name | Status | Notes |
| :----------------------- | :------------------ | :---- |
| ActivityIndicator | Available | |
| ART | Available | |
| Button | Available | |
| CheckBox | Available | |
| FlatList | Available | |
| Image | Available (partial) | Missing multiple sources and HTTP headers. |
| ImageBackground | Available | |
| KeyboardAvoidingView | Available (mock) | |
| ListView | Available | |
| Modal | Not started | |
| Picker | Available | |
| RefreshControl | Not started | |
| SafeAreaView | Available | |
| ScrollView | Available (partial) | Missing momentum scroll events. |
| SectionList | Available | |
| Slider | Not started | |
| StatusBar | Mock | |
| SwipeableFlatList | Available | |
| SwipeableListView | Available | |
| Switch | Available | |
| Text | Available (partial) | Missing `onLongPress` support. |
| TextInput | Available (partial) | Missing rich text features and auto-expanding behaviour. |
| Touchable | Available | Includes additional support for mouse and keyboard interactions. |
| TouchableHighlight | Available | |
| TouchableNativeFeedback | Not started | |
| TouchableOpacity | Available | |
| TouchableWithoutFeedback | Available | |
| View | Available | |
| VirtualizedList | Available | |
| WebView | Not started | |
| YellowBox | Mock | |
| Name | Status | Notes |
| :----------------------- | :----- | :---- |
| ActivityIndicator | | |
| ART | | |
| Button | | |
| CheckBox | | |
| FlatList | | |
| Image | | Missing multiple sources ([#515](https://github.com/necolas/react-native-web/issues/515)) and HTTP headers ([#1019](https://github.com/necolas/react-native-web/issues/1019)). |
| ImageBackground | | |
| KeyboardAvoidingView | (✓) | Mock. No equivalent web APIs. |
| ListView | | |
| Modal | ✘ | Not started ([#1020](https://github.com/necolas/react-native-web/issues/1020)). |
| Picker | | |
| RefreshControl | ✘ | Not started ([#1027](https://github.com/necolas/react-native-web/issues/1027)). |
| SafeAreaView | | |
| ScrollView | | Missing momentum scroll events ([#1021](https://github.com/necolas/react-native-web/issues/1021)) and `pagingEnabled` ([#1057](https://github.com/necolas/react-native-web/issues/1057)). |
| SectionList | | |
| Slider | ✘ | Not started ([#1022](https://github.com/necolas/react-native-web/issues/1022)). |
| StatusBar | (✓) | Mock. No equivalent web APIs. |
| SwipeableFlatList | | |
| SwipeableListView | | |
| Switch | | |
| Text | | Missing `onLongPress` ([#1011](https://github.com/necolas/react-native-web/issues/1011)) and `numberOfLines` ([#13](https://github.com/necolas/react-native-web/issues/13)) support. |
| TextInput | ✓ | Missing `onContentSizeChange` ([#793](https://github.com/necolas/react-native-web/issues/793)), rich text features ([#1023](https://github.com/necolas/react-native-web/issues/1023)), and auto-expanding behaviour ([#795](https://github.com/necolas/react-native-web/issues/795)). |
| Touchable | | Includes additional support for mouse and keyboard interactions. |
| TouchableHighlight | | |
| TouchableNativeFeedback | ✘ | Not started ([#1024](https://github.com/necolas/react-native-web/issues/1024)). |
| TouchableOpacity | | |
| TouchableWithoutFeedback | | |
| View | | |
| VirtualizedList | | |
| WebView | ✘ | Not started ([1025](https://github.com/necolas/react-native-web/issues/1025)). |
| YellowBox | (✓) | Mock. No YellowBox functionality. |
### Modules
| Name | Status | Notes |
| :----------------------- | :------------------ | :---- |
| AccessibilityInfo | Mock | No equivalent web APIs. |
| Alert | Not started | |
| Animated | Available | Missing `useNativeDriver` support. |
| AppRegistry | Available | Includes additional support for SSR with `getApplication`. |
| AppState | Available | |
| AsyncStorage | Available | |
| BackHandler | Mock | No equivalent web APIs. |
| CameraRoll | Not started | No equivalent web APIs. |
| Clipboard | Available | |
| ColorPropType | Available | |
| DeviceInfo | Available (partial) | |
| Dimensions | Available | |
| Easing | Available | |
| EdgeInsetsPropType | Available | |
| Geolocation | Available | |
| I18nManager | Available | Includes additional support for runtime switch to RTL. |
| ImageEditor | Not started | No equivalent web APIs. |
| ImageStore | Not started | No equivalent web APIs. |
| InteractionManager | Available (partial) | |
| Keyboard | Mock | |
| LayoutAnimation | Available (partial) | Missing transform to web animation. |
| Linking | Available | |
| NativeEventEmitter | Available | |
| NativeMethodsMixin | Available | |
| NativeModules | Available (partial) | Mocked. Missing ability to load native modules. |
| NetInfo | Available (partial) | Missing functionality to detect extensive connections. |
| PanResponder | Available | |
| PixelRatio | Available | |
| Platform | Available | |
| PointPropType | Available | |
| Settings | Not started | |
| Share | Available | Only available over HTTPS. Read about the [Web Share API](https://wicg.github.io/web-share/). |
| StyleSheet | Available | |
| TextPropTypes | Available | |
| UIManager | Available | |
| Vibration | Available | |
| ViewPropTypes | Available | |
| Name | Status | Notes |
| :----------------------- | :----- | :---- |
| AccessibilityInfo | (✓) | Mock. No equivalent web APIs. |
| Alert | ✘ | Not started ([#1026](https://github.com/necolas/react-native-web/issues/1026)). |
| Animated | | Missing `useNativeDriver` support. |
| AppRegistry | | Includes additional support for server rendering with `getApplication`. |
| AppState | | |
| AsyncStorage | | |
| BackHandler | (✓) | Mock. No equivalent web APIs. |
| CameraRoll | | No equivalent web APIs. |
| Clipboard | | |
| ColorPropType | | |
| DeviceInfo | (✓) | Limited information. |
| Dimensions | | |
| Easing | | |
| EdgeInsetsPropType | | |
| Geolocation | | |
| I18nManager | | Includes additional support for runtime switch to RTL. |
| ImageEditor | | No equivalent web APIs. |
| ImageStore | | No equivalent web APIs. |
| InteractionManager | (✓) | |
| Keyboard | (✓) | Mock. |
| LayoutAnimation | (✓) | Missing translation to web animations. |
| Linking | | |
| NativeEventEmitter | | |
| NativeMethodsMixin | | |
| NativeModules | (✓) | Mocked. Missing ability to load native modules. |
| NetInfo | | Missing functionality to detect expensive connections as there are no equivalent web APIs. |
| PanResponder | | |
| PixelRatio | | |
| Platform | | |
| PointPropType | | |
| Settings | ✘ | No equivalent web APIs. |
| Share | | Only available over HTTPS. Read about the [Web Share API](https://wicg.github.io/web-share/). |
| StyleSheet | | |
| TextPropTypes | | |
| UIManager | | |
| Vibration | | |
| ViewPropTypes | | |
## Contributing

View File

@@ -0,0 +1,42 @@
# Client-side rendering
Render apps using `AppRegistry`:
```js
// index.web.js
import App from './src/App';
import React from 'react';
import { AppRegistry } from 'react-native';
// register the app
AppRegistry.registerComponent('App', () => App);
AppRegistry.runApplication('App', {
initialProps: {},
rootTag: document.getElementById('react-app')
});
```
Or render individual components:
```js
import AppHeader from './src/AppHeader';
import React from 'react';
import { render } from 'react-native';
render(<AppHeader />, document.getElementById('react-app-header'))
```
(Components will also be rendered within a tree produced by calling
`ReactDOM.render` (i.e., an existing web app), but
otherwise it is not recommended.)
You might need to adjust the styles of the HTML document's root elements for
your app to fill the viewport.
```html
<html style="height:100%">
<body style="height:100%">
<div id="react-root" style="display:flex;height:100%"></div>
```

View File

@@ -0,0 +1,116 @@
# Getting started
This guide will help you render components and applications with React Native
for Web.
Your application may need to polyfill `Promise`, `Object.assign`, `Array.from`,
and [`ResizeObserver`](https://github.com/que-etc/resize-observer-polyfill) as
necessary for your desired browser support.
If you're not familiar with setting up a new React web project, please follow
the recommendations in the [React documentation](https://reactjs.org/).
## Install
```
yarn add react react-dom react-native-web
```
And if you need to use `ART`:
```
yarn add react-art
```
## Starter kits
Web: [create-react-app](https://github.com/facebookincubator/create-react-app)
includes built-in support for aliasing `react-native-web` to `react-native`.
```
create-react-app my-app
```
Multi-platform: [create-react-native-app](https://github.com/react-community/create-react-native-app)
includes experimental support for Web.
```
create-react-native-app my-app --with-web-support
```
## Configuring a module bundler
If you have a custom setup, you may choose to configure your module bundler to
alias the package to `react-native`.
For example, modify your [webpack](https://github.com/webpack/webpack)
configuration as follows:
```js
// webpack.config.js
module.exports = {
// ...the rest of your config
resolve: {
alias: {
'react-native$': 'react-native-web'
}
}
}
```
Now you can create your components and applications with the React Native API.
## Configuring Babel
If you need to do the aliasing with Babel you can use
[babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver)
```
{
"plugins": [
["module-resolver", {
"alias": {
"^react-native$": "react-native-web"
}
}]
]
}
```
## Configuring Jest
[Jest](https://facebook.github.io/jest/) can be configured using the provided
preset. This will map `react-native` to `react-native-web` and provide
appropriate mocks:
```
{
"preset": "react-native-web"
}
```
Please refer to the Jest documentation for more information.
## Configuring Flow
[Flow](https://flow.org) can be configured to understand the aliased module:
```
[options]
module.name_mapper='^react-native$' -> 'react-native-web'
```
You may also need to include a custom libdef
([example](https://gist.github.com/paularmstrong/f60b40d16fc83e1e8e532d483336f9bb))
in your config.
## Other notes
### Safari flexbox performance
Safari prior to version 10.1 can suffer from extremely [poor flexbox
performance](https://bugs.webkit.org/show_bug.cgi?id=150445). The recommended
way to work around this issue (as used on mobile.twitter.com) is to set
`display:block` on Views in your element hierarchy that you know don't need
flexbox layout.

View File

@@ -0,0 +1,154 @@
# Multi-platform applications
## Web-specific code
Minor platform differences can use the `Platform` module.
```js
import { Platform } from 'react-native';
const styles = StyleSheet.create({
height: (Platform.OS === 'web') ? 200 : 100,
});
```
More significant platform differences should use platform-specific files (see
the webpack configuration below for resolving `*.web.js` files):
For example, with the following files in your project:
```
MyComponent.android.js
MyComponent.ios.js
MyComponent.web.js
```
And the following import:
```js
import MyComponent from './MyComponent';
```
React Native will automatically import the correct variant for each specific
target platform.
## Web packaging for existing React Native apps
What follows is merely an _example_ of one basic way to package a web app using
[Webpack](https://webpack.js.org) and [Babel](https://babeljs.io/). (You can
also the React Native bundler, [Metro](https://github.com/facebook/metro), to
build web apps.)
Packaging web apps is subtly different to packaging React Native apps and is
complicated by the need to tree-shake and code-split non-trivial apps.
Install webpack-related dependencies, for example:
```
yarn add --dev babel-loader url-loader webpack webpack-cli webpack-dev-server
```
React Native's Babel preset rewrites ES modules to CommonJS modules, preventing
bundlers from automatically performing "tree-shaking" to remove unused modules
from your web app build. To help with this, you can install the following Babel
plugin:
```
yarn install --dev babel-plugin-react-native-web
```
Create a `web/webpack.config.js` file:
```js
// web/webpack.config.js
const path = require('path');
const webpack = require('webpack');
const appDirectory = path.resolve(__dirname, '../');
// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// `node_module`.
const babelLoaderConfiguration = {
test: /\.js$/,
// Add every directory that needs to be compiled by Babel during the build.
include: [
path.resolve(appDirectory, 'index.web.js'),
path.resolve(appDirectory, 'src'),
path.resolve(appDirectory, 'node_modules/react-native-uncompiled')
],
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// The 'react-native' preset is recommended to match React Native's packager
presets: ['react-native'],
// Re-write paths to import only the modules needed by the app
plugins: ['react-native-web']
}
}
};
// This is needed for webpack to import static images in JavaScript files.
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]'
}
}
};
module.exports = {
entry: [
// load any web API polyfills
// path.resolve(appDirectory, 'polyfills-web.js'),
// your web-specific entry file
path.resolve(appDirectory, 'index.web.js')
],
// configures where the build ends up
output: {
filename: 'bundle.web.js',
path: path.resolve(appDirectory, 'dist')
},
// ...the rest of your config
module: {
rules: [
babelLoaderConfiguration,
imageLoaderConfiguration
]
},
resolve: {
// This will only alias the exact import "react-native"
alias: {
'react-native$': 'react-native-web'
},
// If you're working on a multi-platform React Native app, web-specific
// module implementations should be written in files using the extension
// `.web.js`.
extensions: [ '.web.js', '.js' ]
}
}
```
To run in development from the root of your application:
```
./node_modules/.bin/webpack-dev-server -d --config ./web/webpack.config.js --inline --hot --colors
```
To build for production:
```
./node_modules/.bin/webpack -p --config ./web/webpack.config.js
```
Please refer to the Webpack documentation for more information on configuration.

View File

@@ -0,0 +1,33 @@
# Server-side rendering
Server-side rendering to HTML is supported using `AppRegistry`:
```js
import App from './src/App';
import ReactDOMServer from 'react-dom/server';
import { AppRegistry } from 'react-native-web';
// register the app
AppRegistry.registerComponent('App', () => App);
// prerender the app
const { element, getStyleElement } = AppRegistry.getApplication('App', { initialProps });
// first the element
const html = ReactDOMServer.renderToString(element);
// then the styles (optionally include a nonce if your CSP policy requires it)
const css = ReactDOMServer.renderToStaticMarkup(getStyleElement({ nonce }));
// example HTML document string
const document = `
<!DOCTYPE html>
<html style="height:100%">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${css}
<body style="height:100%; overflow-y:hidden">
<div id="root" style="display:flex; height: 100%">
${html}
</div>
<script nonce="${nonce}" src="${bundlePath}"></script>
`
```

View File

@@ -0,0 +1,51 @@
# Web recipes
Examples of how to implement web patterns with React Native.
#### `html` and `body` styles
The `html` and `body` elements require certain styles to support full-screen
React Native apps, and disable "features" like pull-to-refresh in mobile
browsers. Using the `body` as the root scroll view is [not reliably
supported](https://github.com/necolas/react-native-web/issues/829).
[Example code](https://codesandbox.io/s/52x1871vjl).
#### Hover styles
Relying on the web's native hover styles can result in several unwanted UX
consequences. Hover styles might be displayed during touch interactions and can
remain visually "stuck". Furthermore, there's no way to delay or persist hover
for accessibility purposes. This recipe shows how to apply hover styles that
integrate with the Responder event system (e.g., the `Touchable*` press styles)
and display styles *only* when the mouse is active. It can also be used as the
basis for programmatic hover delays and rendering of components (e.g., hover
cards).
[Example code](https://codesandbox.io/s/o9q8vy70l5)
#### Link styles
Cross-platform link components are straight-forward to create and can be
combined with the hover recipe.
[Example code](https://codesandbox.io/s/53r88k5opx)
<!--
#### Typography
Rather than relying on inhereted global typography styles, React Native allows
you to define components that encapsulate a typographic system. This has the
added benefit of enabling content-specific typography adjustments, e.g.,
different font sizes or weights for different languages.
[Example code]()
#### Responsive font size
[Example code]()
#### SVG icons
[Example code]()
-->

View File

@@ -1,6 +1,6 @@
{
"private": true,
"version": "0.8.8",
"version": "0.9.3",
"name": "react-native-web-monorepo",
"scripts": {
"clean": "del ./packages/*/dist",
@@ -39,8 +39,8 @@
"babel-preset-react-native": "^4.0.0",
"caniuse-api": "^2.0.0",
"del-cli": "^1.1.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.0",
"enzyme": "^3.6.0",
"enzyme-adapter-react-16": "^1.5.0",
"enzyme-to-json": "^3.3.3",
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
@@ -54,10 +54,10 @@
"lint-staged": "^7.1.0",
"npm-run-all": "^4.1.3",
"prettier": "^1.12.1",
"react": "^16.4.1",
"react-art": "^16.4.1",
"react-dom": "^16.4.1",
"react-test-renderer": "^16.4.1"
"react": "^16.5.1",
"react-art": "^16.5.1",
"react-dom": "^16.5.1",
"react-test-renderer": "^16.5.1"
},
"workspaces": [
"packages/*"

View File

@@ -1,6 +1,6 @@
{
"name": "babel-plugin-react-native-web",
"version": "0.8.8",
"version": "0.9.3",
"description": "Babel plugin for React Native for Web",
"main": "index.js",
"devDependencies": {

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "benchmarks",
"version": "0.8.8",
"version": "0.9.3",
"scripts": {
"build": "mkdir -p dist && cp -f index.html dist/index.html && ./node_modules/.bin/webpack-cli --config ./webpack.config.js",
"release": "yarn build && git checkout gh-pages && rm -rf ../../benchmarks && mv dist ../../benchmarks && git add -A && git commit -m \"Benchmarks deploy\" && git push origin gh-pages && git checkout -"
@@ -14,11 +14,11 @@
"fela": "^6.1.9",
"glamor": "2.20.40",
"radium": "^0.24.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react": "^16.5.1",
"react-dom": "^16.5.1",
"react-fela": "^7.3.1",
"react-jss": "^8.6.1",
"react-native-web": "0.8.8",
"react-native-web": "0.9.3",
"reactxp": "^1.3.0",
"styled-components": "^3.3.3",
"styled-jsx": "^2.2.7",
@@ -26,7 +26,7 @@
"styletron-react": "^4.3.1"
},
"devDependencies": {
"babel-plugin-react-native-web": "0.8.8",
"babel-plugin-react-native-web": "0.9.3",
"css-loader": "^1.0.0",
"style-loader": "^0.21.0",
"url-loader": "^1.0.1",

View File

@@ -1,19 +1,19 @@
{
"private": true,
"name": "react-native-examples",
"version": "0.8.8",
"version": "0.9.3",
"scripts": {
"build": "mkdir -p dist && cp -f src/index.html dist/index.html && ./node_modules/.bin/webpack-cli --config ./webpack.config.js",
"release": "yarn build && git checkout gh-pages && rm -rf ../../examples && mv dist ../../examples && git add -A && git commit -m \"Examples deploy\" && git push origin gh-pages && git checkout -"
},
"dependencies": {
"babel-runtime": "^6.26.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-native-web": "0.8.8"
"react": "^16.5.1",
"react-dom": "^16.5.1",
"react-native-web": "0.9.3"
},
"devDependencies": {
"babel-plugin-react-native-web": "0.8.8",
"babel-plugin-react-native-web": "0.9.3",
"babel-plugin-transform-runtime": "^6.23.0",
"file-loader": "^1.1.11",
"webpack": "^4.8.1",

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.8.8",
"version": "0.9.3",
"description": "React Native for Web",
"module": "dist/index.js",
"main": "dist/cjs/index.js",
@@ -25,9 +25,9 @@
"react-timer-mixin": "^0.13.3"
},
"peerDependencies": {
"react": "16.x.x",
"react-art": "16.x.x",
"react-dom": "16.x.x"
"react": ">=16.5.1",
"react-art": ">=16.5.1",
"react-dom": ">=16.5.1"
},
"author": "Nicolas Gallagher",
"license": "MIT",

View File

@@ -18,10 +18,11 @@ import StyleSheetPropType from '../../modules/StyleSheetPropType';
import StyleSheet from '../StyleSheet';
import TextPropTypes from '../Text/TextPropTypes';
import { arrayOf, bool, func, number, oneOfType, string } from 'prop-types';
import ViewPropTypes, { type ViewProps } from '../ViewPropTypes';
const pickerStyleType = StyleSheetPropType(PickerStylePropTypes);
type Props = {
type Props = ViewProps & {
children?: PickerItem | Array<typeof PickerItem>,
enabled?: boolean,
onValueChange?: Function,
@@ -36,6 +37,7 @@ type Props = {
class Picker extends Component<Props> {
static propTypes = {
...ViewPropTypes,
children: oneOfType([PickerItemPropType, arrayOf(PickerItemPropType)]),
enabled: bool,
onValueChange: func,
@@ -56,8 +58,10 @@ class Picker extends Component<Props> {
/* eslint-disable */
itemStyle,
mode,
prompt
prompt,
onValueChange,
/* eslint-enable */
...otherProps
} = this.props;
return createElement('select', {
@@ -66,7 +70,8 @@ class Picker extends Component<Props> {
onChange: this._handleChange,
style: [styles.initial, style],
testID,
value: selectedValue
value: selectedValue,
...otherProps
});
}

View File

@@ -266,7 +266,6 @@ const ScrollView = createReactClass({
const commonStyle = {
flexGrow: 1,
flexShrink: 1,
overscrollBehavior: 'contain',
// Enable hardware compositing in modern browsers.
// Creates a new layer with its own backing surface that can significantly
// improve scroll performance.

View File

@@ -100,6 +100,8 @@ StyleSheetValidation.addValidStylePropTypes({
fill: string,
float: oneOf(['end', 'left', 'none', 'right', 'start']),
listStyle: string,
objectFit: oneOf(['fill', 'contain', 'cover', 'none', 'scale-down']),
objectPosition: string,
pointerEvents: string,
tableLayout: string,
/* @private */

View File

@@ -247,7 +247,9 @@ describe('StyleSheet/createReactDOMStyle', () => {
textDecorationStyle: 'dashed'
})
).toEqual({
textDecoration: 'underline dashed rgba(255,0,0,1.00)'
textDecoration: 'underline',
textDecorationColor: 'rgba(255,0,0,1.00)',
textDecorationStyle: 'dashed'
});
});
});

View File

@@ -95,10 +95,18 @@ const resolveShadow = (resolvedStyle, style) => {
const resolveTextDecoration = (resolvedStyle, style) => {
const { textDecorationColor, textDecorationLine, textDecorationStyle } = style;
const color = normalizeColor(textDecorationColor) || '';
const lineStyle = textDecorationStyle || '';
const color = normalizeColor(textDecorationColor);
if (textDecorationLine) {
resolvedStyle.textDecoration = `${textDecorationLine} ${lineStyle} ${color}`.trim();
// use 'text-decoration' for browsers that support CSS2 text-decoration (e.g., IE, Edge)
resolvedStyle.textDecoration = textDecorationLine;
if (textDecorationColor) {
resolvedStyle.textDecorationColor = color;
}
if (textDecorationStyle) {
resolvedStyle.textDecorationStyle = textDecorationStyle;
}
}
};

View File

@@ -7,6 +7,11 @@ import Switch from '..';
const checkboxSelector = 'input[type="checkbox"]';
describe('components/Switch', () => {
test('accessibilityLabel is applied to native checkbox', () => {
const component = shallow(<Switch accessibilityLabel="switch" />);
expect(component.find(checkboxSelector).prop('aria-label')).toBe('switch');
});
describe('disabled', () => {
test('when "false" a default checkbox is rendered', () => {
const component = shallow(<Switch />);

View File

@@ -67,6 +67,7 @@ class Switch extends Component<*> {
render() {
const {
accessibilityLabel,
activeThumbColor,
activeTrackColor,
disabled,
@@ -115,6 +116,7 @@ class Switch extends Component<*> {
];
const nativeControl = createElement('input', {
accessibilityLabel,
checked: value,
disabled: disabled,
onBlur: this._handleFocusState,

View File

@@ -21,6 +21,7 @@ const TextPropTypes = {
accessible: bool,
children: any,
importantForAccessibility: oneOf(['auto', 'no', 'no-hide-descendants', 'yes']),
nativeID: string,
numberOfLines: number,
onBlur: func,
onContextMenu: func,

View File

@@ -7,12 +7,14 @@
* @flow
*/
import ColorPropType from '../ColorPropType';
import TextStylePropTypes from '../Text/TextStylePropTypes';
import { oneOf } from 'prop-types';
const TextInputStylePropTypes = {
...TextStylePropTypes,
/* @platform web */
caretColor: ColorPropType,
resize: oneOf(['none', 'vertical', 'horizontal', 'both'])
};

View File

@@ -81,6 +81,7 @@ class TextInput extends Component<*> {
clearTextOnFocus: bool,
defaultValue: string,
editable: bool,
inputAccessoryViewID: string,
keyboardType: oneOf([
'default',
'email-address',
@@ -142,7 +143,7 @@ class TextInput extends Component<*> {
editable: true,
keyboardType: 'default',
multiline: false,
numberOfLines: 2,
numberOfLines: 1,
secureTextEntry: false,
style: emptyObject
};
@@ -190,22 +191,34 @@ class TextInput extends Component<*> {
selectTextOnFocus,
spellCheck,
/* react-native compat */
accessibilityViewIsModal,
allowFontScaling,
caretHidden,
clearButtonMode,
dataDetectorTypes,
disableFullscreenUI,
enablesReturnKeyAutomatically,
hitSlop,
inlineImageLeft,
inlineImagePadding,
inputAccessoryViewID,
keyboardAppearance,
needsOffscreenAlphaCompositing,
onAccessibilityTap,
onContentSizeChange,
onEndEditing,
onMagicTap,
onScroll,
removeClippedSubviews,
renderToHardwareTextureAndroid,
returnKeyLabel,
returnKeyType,
scrollEnabled,
selectionColor,
selectionState,
shouldRasterizeIOS,
textBreakStrategy,
textContentType,
underlineColorAndroid,
/* eslint-enable */
...otherProps

View File

@@ -38,6 +38,7 @@ export type ViewProps = {
children?: any,
hitSlop?: EdgeInsetsProp,
importantForAccessibility?: 'auto' | 'yes' | 'no' | 'no-hide-descendants',
nativeID?: string,
onBlur?: Function,
onClick?: Function,
onClickCapture?: Function,
@@ -87,6 +88,7 @@ const ViewPropTypes = {
children: any,
hitSlop: EdgeInsetsPropType,
importantForAccessibility: oneOf(['auto', 'no', 'no-hide-descendants', 'yes']),
nativeID: string,
onBlur: func,
onClick: func,
onClickCapture: func,

View File

@@ -36,24 +36,38 @@ describe('modules/createElement', () => {
expect(component.find('div').length).toBe(1);
});
[{ disabled: true }, { disabled: false }].forEach(({ disabled }) => {
describe(`value is "button" and disabled is "${disabled}"`, () => {
[{ name: 'Enter', which: 13 }, { name: 'Space', which: 32 }].forEach(({ name, which }) => {
test(`"onClick" is ${disabled ? 'not ' : ''}called when "${name}" is pressed`, () => {
const onClick = jest.fn();
const component = shallow(
createElement('span', { accessibilityRole: 'button', disabled, onClick })
);
component.find('span').simulate('keyPress', {
isDefaultPrevented() {},
nativeEvent: {},
preventDefault() {},
which
});
expect(onClick).toHaveBeenCalledTimes(disabled ? 0 : 1);
const testRole = ({ accessibilityRole, disabled }) => {
[{ key: 'Enter', which: 13 }, { key: 'Space', which: 32 }].forEach(({ key, which }) => {
test(`"onClick" is ${disabled ? 'not ' : ''}called when "${key}" key is pressed`, () => {
const onClick = jest.fn();
const component = shallow(
createElement('span', { accessibilityRole, disabled, onClick })
);
component.find('span').simulate('keyPress', {
isDefaultPrevented() {},
nativeEvent: {},
preventDefault() {},
which
});
expect(onClick).toHaveBeenCalledTimes(disabled ? 0 : 1);
});
});
};
describe('value is "button" and disabled is "true"', () => {
testRole({ accessibilityRole: 'button', disabled: true });
});
describe('value is "button" and disabled is "false"', () => {
testRole({ accessibilityRole: 'button', disabled: false });
});
describe('value is "menuitem" and disabled is "true"', () => {
testRole({ accessibilityRole: 'menuitem', disabled: true });
});
describe('value is "menuitem" and disabled is "false"', () => {
testRole({ accessibilityRole: 'menuitem', disabled: false });
});
});
});

View File

@@ -9,14 +9,12 @@
import AccessibilityUtil from '../../modules/AccessibilityUtil';
import createDOMProps from '../../modules/createDOMProps';
import { injectEventPluginsByName } from 'react-dom/unstable-native-dependencies';
import normalizeNativeEvent from '../../modules/normalizeNativeEvent';
import React from 'react';
import ReactDOM from 'react-dom';
import ResponderEventPlugin from '../../modules/ResponderEventPlugin';
const { EventPluginHub } = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
EventPluginHub.injection.injectEventPluginsByName({
injectEventPluginsByName({
ResponderEventPlugin
});
@@ -48,7 +46,7 @@ const eventHandlerNames = {
const adjustProps = domProps => {
const { onClick, onResponderRelease, role } = domProps;
const isButtonRole = role === 'button';
const isButtonLikeRole = AccessibilityUtil.buttonLikeRoles[role];
const isDisabled = AccessibilityUtil.isDisabled(domProps);
const isLinkRole = role === 'link';
@@ -56,7 +54,7 @@ const adjustProps = domProps => {
const prop = domProps[propName];
const isEventHandler = typeof prop === 'function' && eventHandlerNames[propName];
if (isEventHandler) {
if (isButtonRole && isDisabled) {
if (isButtonLikeRole && isDisabled) {
domProps[propName] = undefined;
} else {
// TODO: move this out of the render path
@@ -80,8 +78,8 @@ const adjustProps = domProps => {
};
}
// Button role should trigger 'onClick' if SPACE or ENTER keys are pressed.
if (isButtonRole && !isDisabled) {
// Button-like roles should trigger 'onClick' if SPACE or ENTER keys are pressed.
if (isButtonLikeRole && !isDisabled) {
domProps.onKeyPress = function(e) {
if (!e.isDefaultPrevented() && (e.which === 13 || e.which === 32)) {
e.preventDefault();

View File

@@ -8,4 +8,15 @@
*/
import { findDOMNode } from 'react-dom';
export default findDOMNode;
const findNodeHandle = component => {
let node;
try {
node = findDOMNode(component);
} catch (e) {}
return node;
};
export default findNodeHandle;

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
const buttonLikeRoles: { [string]: boolean } = {
// ARIA button behaves like native 'button' element
button: true,
// ARIA menuitem responds to Enter/Space like a button. Spec requires AT to
// ignore ARIA roles of any children.
// https://www.w3.org/WAI/GL/wiki/Using_ARIA_menus
menuitem: true
};
export default buttonLikeRoles;

View File

@@ -7,11 +7,13 @@
* @flow
*/
import buttonLikeRoles from './buttonLikeRoles';
import isDisabled from './isDisabled';
import propsToAccessibilityComponent from './propsToAccessibilityComponent';
import propsToAriaRole from './propsToAriaRole';
const AccessibilityUtil = {
buttonLikeRoles,
isDisabled,
propsToAccessibilityComponent,
propsToAriaRole

View File

@@ -52,12 +52,14 @@ const ImageLoader = {
image.onerror = onError;
image.onload = e => {
// avoid blocking the main thread
const onDecode = () => onLoad(e);
if (typeof image.decode === 'function') {
image.decode().then(() => { onLoad(e) });
// Safari currently throws exceptions when decoding svgs.
// We want to catch that error and allow the load handler
// to be forwarded to the onLoad handler in this case
image.decode().then(onDecode, onDecode);
} else {
setTimeout(() => {
onLoad(e);
}, 0);
setTimeout(onDecode, 0);
}
};
image.src = uri;

View File

@@ -100,12 +100,14 @@ const NativeMethodsMixin = {
return;
}
const node = findNodeHandle(this);
// Next state is determined by comparison to existing state (in the DOM).
// Existing state has already gone through i18n transform
const domProps = createDOMProps(null, nativeProps, style =>
styleResolver.resolveWithNode(style, node)
);
UIManager.updateView(node, domProps, this);
if (node) {
// Next state is determined by comparison to existing state (in the DOM).
// Existing state has already gone through i18n transform
const domProps = createDOMProps(null, nativeProps, style =>
styleResolver.resolveWithNode(style, node)
);
UIManager.updateView(node, domProps, this);
}
}
};

View File

@@ -44,6 +44,9 @@ if (!ResponderEventPlugin.eventTypes.responderMove.dependencies) {
}
let lastActiveTouchTimestamp = null;
// The length of time after a touch that we ignore the browser's emulated mouse events
// https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Using_Touch_Events
const EMULATED_MOUSE_THERSHOLD_MS = 1000;
const originalExtractEvents = ResponderEventPlugin.extractEvents;
ResponderEventPlugin.extractEvents = (topLevelType, targetInst, nativeEvent, nativeEventTarget) => {
@@ -55,7 +58,7 @@ ResponderEventPlugin.extractEvents = (topLevelType, targetInst, nativeEvent, nat
lastActiveTouchTimestamp = Date.now();
} else if (lastActiveTouchTimestamp && eventType.indexOf('mouse') > -1) {
const now = Date.now();
shouldSkipMouseAfterTouch = now - lastActiveTouchTimestamp < 250;
shouldSkipMouseAfterTouch = now - lastActiveTouchTimestamp < EMULATED_MOUSE_THERSHOLD_MS;
}
if (

View File

@@ -63,14 +63,15 @@ const observe = instance => {
};
const unobserve = instance => {
delete registry[instance._layoutId];
if (resizeObserver) {
const node = findNodeHandle(instance);
if (node) {
delete registry[node._layoutId];
delete node._layoutId;
resizeObserver.unobserve(node);
}
} else {
delete registry[instance._layoutId];
delete instance._layoutId;
}
};
@@ -97,7 +98,9 @@ const applyLayout = Component => {
function componentDidMount() {
this._layoutState = emptyObject;
this._isMounted = true;
observe(this);
if (this.props.onLayout) {
observe(this);
}
}
);
@@ -116,7 +119,9 @@ const applyLayout = Component => {
componentWillUnmount,
function componentWillUnmount() {
this._isMounted = false;
unobserve(this);
if (this.props.onLayout) {
unobserve(this);
}
}
);

View File

@@ -65,9 +65,7 @@ describe('modules/createDOMProps', () => {
});
});
describe('"accessibilityRole" of "button"', () => {
const accessibilityRole = 'button';
const testFocusableRole = accessibilityRole => {
test('default case', () => {
expect(createProps({ accessibilityRole })).toEqual(
expect.objectContaining({ 'data-focusable': true, tabIndex: '0' })
@@ -118,6 +116,14 @@ describe('modules/createDOMProps', () => {
})
).not.toEqual(expect.objectContaining({ 'data-focusable': true, tabIndex: '0' }));
});
};
describe('"accessibilityRole" of "button"', () => {
testFocusableRole('button');
});
describe('"accessibilityRole" of "menuitem"', () => {
testFocusableRole('menuitem');
});
describe('with unfocusable accessibilityRole', () => {
@@ -177,6 +183,12 @@ describe('modules/createDOMProps', () => {
expect(props['aria-hidden']).toEqual(true);
});
test('prop "nativeID" becomes "id"', () => {
const nativeID = 'Example.nativeID';
const props = createProps({ nativeID });
expect(props.id).toEqual(nativeID);
});
test('prop "testID" becomes "data-testid"', () => {
const testID = 'Example.testID';
const props = createProps({ testID });

View File

@@ -77,6 +77,7 @@ const createDOMProps = (component, props, styleResolver) => {
accessibilityLabel,
accessibilityLiveRegion,
importantForAccessibility,
nativeID,
placeholderTextColor,
pointerEvents,
style: providedStyle,
@@ -131,7 +132,7 @@ const createDOMProps = (component, props, styleResolver) => {
} else {
domProps['data-focusable'] = true;
}
} else if (role === 'button' || role === 'textbox') {
} else if (AccessibilityUtil.buttonLikeRoles[role] || role === 'textbox') {
if (accessible !== false && focusable) {
domProps['data-focusable'] = true;
domProps.tabIndex = '0';
@@ -164,10 +165,15 @@ const createDOMProps = (component, props, styleResolver) => {
}
// OTHER
// Native element ID
if (nativeID && nativeID.constructor === String) {
domProps.id = nativeID;
}
// Link security and automation test ids
if (component === 'a' && domProps.target === '_blank') {
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
}
// Automated test IDs
if (testID && testID.constructor === String) {
domProps['data-testid'] = testID;
}

View File

@@ -410,7 +410,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
}
static defaultProps = {
disableVirtualization: false,
disableVirtualization: process.env.NODE_ENV === 'test',
horizontal: false,
initialNumToRender: 10,
keyExtractor: (item: Item, index: number) => {
@@ -1562,6 +1562,7 @@ class CellRenderer extends React.Component<
renderItem: renderItemType,
},
prevCellKey: ?string,
style: ?DangerouslyImpreciseStyleProp,
},
$FlowFixMeState,
> {
@@ -1630,6 +1631,7 @@ class CellRenderer extends React.Component<
index,
inversionStyle,
parentProps,
style,
} = this.props;
const {renderItem, getItemLayout} = parentProps;
invariant(renderItem, 'no renderItem!');
@@ -1649,9 +1651,9 @@ class CellRenderer extends React.Component<
);
const cellStyle = inversionStyle
? horizontal
? [{flexDirection: 'row-reverse'}, inversionStyle]
: [{flexDirection: 'column-reverse'}, inversionStyle]
: horizontal ? [{flexDirection: 'row'}, inversionStyle] : inversionStyle;
? [styles.rowReverse, inversionStyle, style]
: [styles.columnReverse, inversionStyle, style]
: horizontal ? [styles.row, inversionStyle, style] : [inversionStyle, style];
if (!CellRendererComponent) {
return (
<View style={cellStyle} onLayout={onLayout}>
@@ -1702,6 +1704,15 @@ const styles = StyleSheet.create({
horizontallyInverted: {
transform: [{scaleX: -1}],
},
row: {
flexDirection: 'row'
},
rowReverse: {
flexDirection: 'row-reverse'
},
columnReverse: {
flexDirection: 'column-reverse'
}
});
export default VirtualizedList;

View File

@@ -1,353 +0,0 @@
# Getting started
This guide will help you render components and applications with React Native
for Web.
Your application may need to polyfill `Promise`, `Object.assign`, `Array.from`,
and [`ResizeObserver`](https://github.com/que-etc/resize-observer-polyfill) as
necessary for your desired browser support.
If you're not familiar with setting up a new React web project, please follow
the recommendations in the [React documentation](https://reactjs.org/).
## Install
```
yarn add react react-dom react-native-web
```
And if you need to use `ART`:
```
yarn add react-art
```
## Starter kits
Web: [create-react-app](https://github.com/facebookincubator/create-react-app)
includes built-in support for aliasing `react-native-web` to `react-native`.
```
create-react-app my-app
```
Multi-platform: [create-react-native-app](https://github.com/react-community/create-react-native-app)
includes experimental support for Web.
```
create-react-native-app my-app --with-web-support
```
## Configuring a module bundler
If you have a custom setup, you may choose to configure your module bundler to
alias the package to `react-native`.
For example, modify your [webpack](https://github.com/webpack/webpack)
configuration as follows:
```js
// webpack.config.js
module.exports = {
// ...the rest of your config
resolve: {
alias: {
'react-native$': 'react-native-web'
}
}
}
```
Now you can create your components and applications with the React Native API.
## Configuring babel
If you need to do the aliasing with Babel you can use
[babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver)
```
{
"plugins": [
["module-resolver", {
"alias": {
"^react-native$": "react-native-web"
}
}]
]
}
```
## Client-side rendering
Render apps using `AppRegistry`:
```js
// index.web.js
import App from './src/App';
import React from 'react';
import { AppRegistry } from 'react-native';
// register the app
AppRegistry.registerComponent('App', () => App);
AppRegistry.runApplication('App', {
initialProps: {},
rootTag: document.getElementById('react-app')
});
```
Or render individual components:
```js
import AppHeader from './src/AppHeader';
import React from 'react';
import { render } from 'react-native';
render(<AppHeader />, document.getElementById('react-app-header'))
```
(Components will also be rendered within a tree produced by calling
`ReactDOM.render` (i.e., an existing web app), but
otherwise it is not recommended.)
You might need to adjust the styles of the HTML document's root elements for
your app to fill the viewport.
```html
<html style="height:100%">
<body style="height:100%">
<div id="react-root" style="display:flex;height:100%"></div>
```
## Server-side rendering
Server-side rendering to HTML is supported using `AppRegistry`:
```js
import App from './src/App';
import ReactDOMServer from 'react-dom/server';
import { AppRegistry } from 'react-native-web';
// register the app
AppRegistry.registerComponent('App', () => App);
// prerender the app
const { element, getStyleElement } = AppRegistry.getApplication('App', { initialProps });
// first the element
const html = ReactDOMServer.renderToString(element);
// then the styles (optionally include a nonce if your CSP policy requires it)
const css = ReactDOMServer.renderToStaticMarkup(getStyleElement({ nonce }));
// example HTML document string
const document = `
<!DOCTYPE html>
<html style="height:100%">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${css}
<body style="height:100%; overflow-y:hidden">
<div id="root" style="display:flex; height: 100%">
${html}
</div>
<script nonce="${nonce}" src="${bundlePath}"></script>
`
```
## Testing with Jest
[Jest](https://facebook.github.io/jest/) can be configured using the provided
preset. This will map `react-native` to `react-native-web` and provide
appropriate mocks:
```
{
"preset": "react-native-web"
}
```
Please refer to the Jest documentation for more information.
## Using Flow
[Flow](https://flow.org) can be configured to understand the aliased module:
```
[options]
module.name_mapper='^react-native$' -> 'react-native-web'
```
You may also need to inlucde a custom libdef
([example](https://gist.github.com/paularmstrong/f60b40d16fc83e1e8e532d483336f9bb))
in your config.
## Multi-platform applications
### Web-specific code
Minor platform differences can use the `Platform` module.
```js
import { Platform } from 'react-native';
const styles = StyleSheet.create({
height: (Platform.OS === 'web') ? 200 : 100,
});
```
More significant platform differences should use platform-specific files (see
the webpack configuration below for resolving `*.web.js` files):
For example, with the following files in your project:
```
MyComponent.android.js
MyComponent.ios.js
MyComponent.web.js
```
And the following import:
```js
import MyComponent from './MyComponent';
```
React Native will automatically import the correct variant for each specific
target platform.
## Web packaging for existing React Native apps
What follows is merely an _example_ of one basic way to package a web app using
[Webpack](https://webpack.js.org) and [Babel](https://babeljs.io/). (You can
also the React Native bundler, [Metro](https://github.com/facebook/metro), to
build web apps.)
Packaging web apps is subtly different to packaging React Native apps and is
complicated by the need to tree-shake and code-split non-trivial apps.
Install webpack-related dependencies, for example:
```
yarn add --dev babel-loader url-loader webpack webpack-cli webpack-dev-server
```
React Native's Babel preset rewrites ES modules to CommonJS modules, preventing
bundlers from automatically performing "tree-shaking" to remove unused modules
from your web app build. To help with this, you can install the following Babel
plugin:
```
yarn install --dev babel-plugin-react-native-web
```
Create a `web/webpack.config.js` file:
```js
// web/webpack.config.js
const path = require('path');
const webpack = require('webpack');
const appDirectory = path.resolve(__dirname, '../');
// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// `node_module`.
const babelLoaderConfiguration = {
test: /\.js$/,
// Add every directory that needs to be compiled by Babel during the build.
include: [
path.resolve(appDirectory, 'index.web.js'),
path.resolve(appDirectory, 'src'),
path.resolve(appDirectory, 'node_modules/react-native-uncompiled')
],
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// The 'react-native' preset is recommended to match React Native's packager
presets: ['react-native'],
// Re-write paths to import only the modules needed by the app
plugins: ['react-native-web']
}
}
};
// This is needed for webpack to import static images in JavaScript files.
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]'
}
}
};
module.exports = {
entry: [
// load any web API polyfills
// path.resolve(appDirectory, 'polyfills-web.js'),
// your web-specific entry file
path.resolve(appDirectory, 'index.web.js')
],
// configures where the build ends up
output: {
filename: 'bundle.web.js',
path: path.resolve(appDirectory, 'dist')
},
// ...the rest of your config
module: {
rules: [
babelLoaderConfiguration,
imageLoaderConfiguration
]
},
resolve: {
// This will only alias the exact import "react-native"
alias: {
'react-native$': 'react-native-web'
},
// If you're working on a multi-platform React Native app, web-specific
// module implementations should be written in files using the extension
// `.web.js`.
extensions: [ '.web.js', '.js' ]
}
}
```
To run in development from the root of your application:
```
./node_modules/.bin/webpack-dev-server -d --config ./web/webpack.config.js --inline --hot --colors
```
To build for production:
```
./node_modules/.bin/webpack -p --config ./web/webpack.config.js
```
Please refer to the Webpack documentation for more information on configuration.
## Other notes
### Safari flexbox performance
Safari prior to version 10.1 can suffer from extremely [poor flexbox
performance](https://bugs.webkit.org/show_bug.cgi?id=150445). The recommended
way to work around this issue (as used on mobile.twitter.com) is to set
`display:block` on Views in your element hierarchy that you know don't need
flexbox layout.
### Platform-specific component props
There are properties that do not work across all platforms. All web-specific
props are annotated with `(web)` in the documentation.

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "website",
"version": "0.8.8",
"version": "0.9.3",
"scripts": {
"build": "build-storybook -o ./dist -c ./storybook/.storybook",
"start": "start-storybook -p 9001 -c ./storybook/.storybook",
@@ -10,12 +10,12 @@
"dependencies": {
"@storybook/addon-options": "^3.4.3",
"@storybook/react": "^3.4.3",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-native-web": "0.8.8"
"react": "^16.5.1",
"react-dom": "^16.5.1",
"react-native-web": "0.9.3"
},
"devDependencies": {
"babel-plugin-react-native-web": "0.8.8",
"babel-plugin-react-native-web": "0.9.3",
"url-loader": "^1.0.1",
"webpack": "^4.8.1"
}

View File

@@ -23,6 +23,8 @@ const PickerScreen = () => (
<AppText>Renders the native &lt;select&gt; component.</AppText>
</Description>
<Section title="Props">
<DocItem name="...View props" />
<DocItem
name="children"
typeInfo="?Array<Picker.Item>"

View File

@@ -116,6 +116,12 @@ const TextScreen = () => (
]}
/>
<DocItem
name="nativeID"
typeInfo="?string"
description="Used to locate this view from any native DOM code, or to define accessibility relationships. This is rendered to the native 'id' DOM attribute"
/>
<DocItem
name="numberOfLines"
typeInfo="?number"

View File

@@ -3,7 +3,7 @@
*/
import React from 'react';
import { processColor, StyleSheet, View, Text, TouchableHighlight } from 'react-native';
import { StyleSheet, View, Text, TouchableHighlight } from 'react-native';
export default class TouchableCustomStyleOverridesExample extends React.Component {
buttons = ['One', 'Two', 'Three'];
@@ -26,7 +26,7 @@ export default class TouchableCustomStyleOverridesExample extends React.Componen
key={button}
onPress={this.select(button)}
style={[styles.touchable, this.state[button] && styles.blue]}
underlayColor={processColor('#1B95E0', 0.125)}
underlayColor="#1b95e020"
>
<Text style={[!this.state[button] && styles.text]}>{button}</Text>
</TouchableHighlight>
@@ -39,7 +39,7 @@ export default class TouchableCustomStyleOverridesExample extends React.Componen
const styles = StyleSheet.create({
blue: {
backgroundColor: processColor('#1B95E0', 0.25),
backgroundColor: '#1b95e040',
borderColor: '#1B95E0'
},
text: {

View File

@@ -119,6 +119,12 @@ const ViewScreen = () => (
]}
/>
<DocItem
name="nativeID"
typeInfo="?string"
description="Used to locate this view from any native DOM code, or to define accessibility relationships. This is rendered to the native 'id' DOM attribute"
/>
<DocItem name="onBlur" typeInfo="?function" />
<DocItem name="onContextMenu" typeInfo="?function" />
<DocItem name="onFocus" typeInfo="?function" />

View File

@@ -3,7 +3,7 @@ import { View, StyleSheet } from 'react-native';
export default class Sandbox extends React.PureComponent {
render() {
return <View styles={styles.root} />;
return <View style={styles.root} />;
}
}

133
yarn.lock
View File

@@ -3568,25 +3568,25 @@ envinfo@^5.7.0:
version "5.10.0"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.10.0.tgz#503a9774ae15b93ea68bdfae2ccd6306624ea6df"
enzyme-adapter-react-16@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz#a8f4278b47e082fbca14f5bfb1ee50ee650717b4"
enzyme-adapter-react-16@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.5.0.tgz#50af8d76a45fe0915de932bd95d34cdca75c0be3"
dependencies:
enzyme-adapter-utils "^1.3.0"
lodash "^4.17.4"
object.assign "^4.0.4"
enzyme-adapter-utils "^1.8.0"
function.prototype.name "^1.1.0"
object.assign "^4.1.0"
object.values "^1.0.4"
prop-types "^15.6.0"
react-reconciler "^0.7.0"
prop-types "^15.6.2"
react-is "^16.4.2"
react-test-renderer "^16.0.0-0"
enzyme-adapter-utils@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.3.0.tgz#d6c85756826c257a8544d362cc7a67e97ea698c7"
enzyme-adapter-utils@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.8.0.tgz#ee9f07250663a985f1f2caaf297720787da559f1"
dependencies:
lodash "^4.17.4"
object.assign "^4.0.4"
prop-types "^15.6.0"
function.prototype.name "^1.1.0"
object.assign "^4.1.0"
prop-types "^15.6.2"
enzyme-to-json@^3.3.3:
version "3.3.4"
@@ -3594,26 +3594,29 @@ enzyme-to-json@^3.3.3:
dependencies:
lodash "^4.17.4"
enzyme@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.3.0.tgz#0971abd167f2d4bf3f5bd508229e1c4b6dc50479"
enzyme@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.6.0.tgz#d213f280a258f61e901bc663d4cc2d6fd9a9dec8"
dependencies:
array.prototype.flat "^1.2.1"
cheerio "^1.0.0-rc.2"
function.prototype.name "^1.0.3"
has "^1.0.1"
function.prototype.name "^1.1.0"
has "^1.0.3"
is-boolean-object "^1.0.0"
is-callable "^1.1.3"
is-callable "^1.1.4"
is-number-object "^1.0.3"
is-string "^1.0.4"
is-subset "^0.1.1"
lodash "^4.17.4"
object-inspect "^1.5.0"
lodash.escape "^4.0.1"
lodash.isequal "^4.5.0"
object-inspect "^1.6.0"
object-is "^1.0.1"
object.assign "^4.1.0"
object.entries "^1.0.4"
object.values "^1.0.4"
raf "^3.4.0"
rst-selector-parser "^2.2.3"
string.prototype.trim "^1.1.2"
errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
@@ -3634,7 +3637,7 @@ error@^7.0.2:
string-template "~0.2.1"
xtend "~4.0.0"
es-abstract@^1.10.0, es-abstract@^1.12.0, es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0, es-abstract@^1.9.0:
es-abstract@^1.10.0, es-abstract@^1.12.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0, es-abstract@^1.9.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
dependencies:
@@ -4414,7 +4417,7 @@ function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
function.prototype.name@^1.0.3, function.prototype.name@^1.1.0:
function.prototype.name@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327"
dependencies:
@@ -5231,7 +5234,7 @@ is-builtin-module@^1.0.0:
dependencies:
builtin-modules "^1.0.0"
is-callable@^1.1.1, is-callable@^1.1.3:
is-callable@^1.1.1, is-callable@^1.1.3, is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
@@ -6363,6 +6366,10 @@ lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
lodash.escape@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
lodash.flattendeep@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
@@ -6375,6 +6382,10 @@ lodash.isarray@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
@@ -7111,7 +7122,7 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
object-inspect@^1.5.0:
object-inspect@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
@@ -7129,7 +7140,7 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
object.assign@^4.0.4, object.assign@^4.1.0:
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
dependencies:
@@ -8097,16 +8108,16 @@ react-addons-shallow-compare@^15.6.2:
fbjs "^0.8.4"
object-assign "^4.1.0"
react-art@^16.4.1:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react-art/-/react-art-16.4.1.tgz#3544c13038d7ddfe8b1cc1170b02d99492c03b50"
react-art@^16.5.1:
version "16.5.1"
resolved "https://registry.yarnpkg.com/react-art/-/react-art-16.5.1.tgz#534a265dafc5c0e310da9ef9afbf76d6e221be56"
dependencies:
art "^0.10.1"
create-react-class "^15.6.2"
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
schedule "^0.4.0"
react-deep-force-update@^1.0.0:
version "1.1.1"
@@ -8147,14 +8158,14 @@ react-docgen@^3.0.0-beta11:
node-dir "^0.1.10"
recast "^0.12.6"
react-dom@^16.4.1:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.1.tgz#7f8b0223b3a5fbe205116c56deb85de32685dad6"
react-dom@^16.5.1:
version "16.5.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.1.tgz#29d0c5a01ed3b6b4c14309aa91af6ec4eb4f292c"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
schedule "^0.4.0"
react-error-overlay@^4.0.0:
version "4.0.0"
@@ -8204,6 +8215,10 @@ react-is@^16.3.1, react-is@^16.4.1:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.1.tgz#d624c4650d2c65dbd52c72622bbf389435d9776e"
react-is@^16.4.2, react-is@^16.5.1:
version "16.5.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.5.1.tgz#c6e8734fd548a22e1cef4fd0833afbeb433b85ee"
react-jss@^8.6.1:
version "8.6.1"
resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-8.6.1.tgz#a06e2e1d2c4d91b4d11befda865e6c07fbd75252"
@@ -8234,15 +8249,6 @@ react-proxy@^1.1.7:
lodash "^4.6.1"
react-deep-force-update "^1.0.0"
react-reconciler@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.7.0.tgz#9614894103e5f138deeeb5eabaf3ee80eb1d026d"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
react-split-pane@^0.1.77:
version "0.1.81"
resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.81.tgz#b1e8b82e0a6edd10f18fd639a5f512db3cbbb4e6"
@@ -8258,7 +8264,7 @@ react-style-proptype@^3.0.0:
dependencies:
prop-types "^15.5.4"
react-test-renderer@^16.0.0-0, react-test-renderer@^16.4.1:
react-test-renderer@^16.0.0-0:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.1.tgz#f2fb30c2c7b517db6e5b10ed20bb6b0a7ccd8d70"
dependencies:
@@ -8267,6 +8273,15 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.4.1:
prop-types "^15.6.0"
react-is "^16.4.1"
react-test-renderer@^16.5.1:
version "16.5.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.5.1.tgz#17f020fb0cf884cadebb5240d9d9c23452f18299"
dependencies:
object-assign "^4.1.1"
prop-types "^15.6.2"
react-is "^16.5.1"
schedule "^0.4.0"
react-timer-mixin@^0.13.3:
version "0.13.3"
resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.3.tgz#0da8b9f807ec07dc3e854d082c737c65605b3d22"
@@ -8298,14 +8313,14 @@ react-treebeard@^2.1.0:
shallowequal "^0.2.2"
velocity-react "^1.3.1"
react@^16.4.1:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
react@^16.5.1:
version "16.5.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.5.1.tgz#8cb8e9f8cdcb4bde41c9a138bfbf907e66132372"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
schedule "^0.4.0"
reactxp@^1.3.0:
version "1.3.0"
@@ -8836,6 +8851,12 @@ sax@^1.2.4, sax@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
schedule@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.4.0.tgz#fa20cfd0bfbf91c47d02272fd7096780d3170bbb"
dependencies:
object-assign "^4.1.1"
schema-utils@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
@@ -9299,6 +9320,14 @@ string.prototype.padstart@^3.0.0:
es-abstract "^1.4.3"
function-bind "^1.0.2"
string.prototype.trim@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
dependencies:
define-properties "^1.1.2"
es-abstract "^1.5.0"
function-bind "^1.0.2"
string_decoder@^1.0.0, string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"