Compare commits

...

99 Commits
0.4.0 ... 0.7.0

Author SHA1 Message Date
Nicolas Gallagher
4a45595b7a 0.7.0 2018-05-18 17:29:47 -07:00
Nicolas Gallagher
45095fd300 Documentation updates 2018-05-18 17:27:39 -07:00
Nicolas Gallagher
004c7ce478 [change] export ES modules by default
ES modules are the default package export. Commonjs modules are exported
from 'dist/cjs'. Modern bundlers like webpack can consume ES modules.
The addition of the `sideEffects:false` to the `package.json` helps
webpack tree-shaking modules.
2018-05-18 17:27:36 -07:00
Nicolas Gallagher
96c3f09fac [fix] Firefox UI for numeric TextInput
Fix #900
2018-05-18 13:40:15 -07:00
Nicolas Gallagher
edc99e79eb [change] ResponderEventPlugin filters browser emulated mouse events
Browsers dispatch mouse events after touch events:
https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent

There have been several attempts to avoid this behaviour affecting the
ResponderEvent system. The previous approach of cancelling the event in
the `onResponderRelease` event handler can end up cancelling other
events that are expected, e.g., `focus`.

Instead, this patch changes the `ResponderEventPlugin.extractEvents`
function to filter the mouse events that occur a short time after a
touch event. (It's assumed that people will not be clicking a mouse
within a few hundred ms of performing a touch.) This allows the
ResponderEvent system to function as expected and leaves other callbacks
to fire as they would be expected to in React DOM, i.e., both
`onTouchStart` and `onMouseDown` will be called following a touch start.

Fix #835
Fix #888
Fix #932
Close #938
Ref #802
2018-05-18 13:39:25 -07:00
Nicolas Gallagher
e8f2c98786 [add] mark focusable DOM nodes with 'data-focusable'
Focus-based UIs can use out-of-tree focus algorithms to manage focus
using remote control devices. This patch marks DOM nodes that React
Native considers "focusable".

Close #827
2018-05-18 11:56:56 -07:00
Nicolas Gallagher
dcdf1468f9 [fix] onLayout timing without ResizeObserver
onLayout is called after the component is mounted to the DOM. This makes
both the fallback and ResizeObserver code path behave the same as React
Native.

Fix #911
Fix #941
Close #939
2018-05-18 11:44:30 -07:00
Nicolas Gallagher
ee5e80064f [add] support for CSP policy requiring 'nonce' on <style>
CSP policy may prevent writing to `<style>` unless a `nonce` attribute
is set. This change makes that possible by moving the modality-related
styles into the main style sheet, and allowing additional props to be
provided to the `<style>` element when rendering on the server. For
example:

```
const { element, getStyleElement } = AppRegistry.getApplication('App');
const html = renderToString(element);
const css = renderToStaticMarkup(getStyleElement({ nonce }));
```
2018-05-18 11:44:24 -07:00
Philipp Spiess
3e4d8d6b2f Upgrade React and all transitive dependencies
Close #942
2018-05-16 15:01:19 -07:00
Nicolas Gallagher
d3a8270d55 Add a development sandbox to storybook 2018-05-09 10:38:34 -07:00
Nicolas Gallagher
18933724d6 Remove @providesModule from all modules
Ref: d5e9e55fa3
2018-05-08 10:28:25 -07:00
Nicolas Gallagher
e7f84a9228 Add GitHub issue templates
Close #931
2018-05-08 10:11:27 -07:00
Scott Kyle
8b1e6f816f [change] remove NetInfo.isConnected.getConnectionInfo()
React Native doesn't have `NetInfo.isConnected.getConnectionInfo()`.
This was incorrectly added to the API while updating the main `NetInfo`
API.

Close #937
2018-05-08 10:01:41 -07:00
Scott Kyle
02b6f3ff3c [fix] findNodeHandle import in VirtualizedList
Close #936
2018-05-08 09:53:50 -07:00
odalay
6f52007cc8 Fix CheckboxScreen link on website
Close #926
2018-05-08 09:53:16 -07:00
Nicolas Gallagher
1e59e53e66 Update jest 2018-05-08 09:49:02 -07:00
Nicolas Gallagher
f6a65210ca Update formatter and linter 2018-05-08 09:24:08 -07:00
Nicolas Gallagher
2e9071eb0e Update benchmarks dependencies 2018-05-08 09:15:51 -07:00
Nicolas Gallagher
8f25fcc05b Update storybook dependencies 2018-05-07 15:00:22 -07:00
Nicolas Gallagher
1e8577fc9e [fix] setting flex styles as inline styles
Reverts #648 as browsers are inconsistent in how they handle
'flex-basis', so this hack isn't effective. And React has no support for
using '!important' in inline styles.

Fix #798
2018-04-30 11:51:18 -07:00
Nicolas Gallagher
c51f567d19 Simplify tests for several exported modules 2018-04-24 15:54:40 -07:00
Nicolas Gallagher
bce5957991 0.6.1 2018-04-21 12:16:05 -07:00
Nicolas Gallagher
34d8409d43 Update yarn.lock 2018-04-21 12:15:18 -07:00
Sébastien Lorber
8442f13e96 Add Gatsby integration to README
Close #868
2018-04-21 12:12:50 -07:00
Nicolas Gallagher
c6e2b584af [fix] AppRegistry.getApplication shouldn't throw if missing options
Fix #899
2018-04-21 12:05:42 -07:00
Philipp Spiess
38affa9bae Fix Game2048 on desktop browsers
The React Native example only listens for touch events but on web we can
listen to mouse events to improve support.

Close #909
2018-04-21 11:56:14 -07:00
Nicolas Gallagher
f9ebdb6327 Documentation layout fixes 2018-04-21 11:50:39 -07:00
Nicolas Gallagher
83a8758f68 0.6.0 2018-04-15 15:56:10 -07:00
MoOx
e022d166dd Update Phenomic integration link to official example 2018-04-15 15:26:24 -07:00
Nicolas Gallagher
1a225bc449 [fix] Text onPress event propagation
The press event should not propagate.

Fix #897
2018-04-15 15:23:32 -07:00
Nicolas Gallagher
cf2612663b [fix] createElement uses provided function component
If the component provided to 'createElement' is not a string alias for a
DOM component, it will no longer attempt to replace that component with
a DOM component inferred from the 'accessibility{Component,Role,Traits}'
prop.

Fix #895
2018-04-15 15:03:34 -07:00
Nicolas Gallagher
1aec803086 [fix] Picker.Item support for 'color' prop
Not well supported by browsers.

Fix #810
2018-04-08 11:43:20 -07:00
Nicolas Gallagher
2050730b77 [fix] consistency of nativeEvent.location{X,Y} between touch and mouse
Calculate `location{X,Y}` in the same way for both touch and mouse
events. Also defer the call to `getBoundingClientRect` to avoid
unnecessary DOM queries when the data is not used.
2018-04-08 11:05:12 -07:00
Nicolas Gallagher
a67bf0f490 [change] synchronous layout measurement 2018-04-08 10:38:31 -07:00
Nicolas Gallagher
4529a4ac0a Update benchmarks dependencies 2018-04-07 17:20:01 -07:00
Giuseppe Gurgone
5a04d07a35 [change] call 'onLayout' when elements are resized
Uses ResizeObserver to monitor layout changes. Falls back to
window.onresize (with initial firing).

Fix #60
Close #848
2018-04-07 17:03:17 -07:00
Nicolas Gallagher
9427eea293 [add] VirtualizedList support
Make changes needed to run VirtualizedList using React Native for Web.

Close #659
2018-04-07 10:25:15 -07:00
Nicolas Gallagher
b9803e1e07 Add snapshot of VirtualizedList from React Native
Exact source code of the module and its dependencies, for the given SHA.
2018-04-07 10:25:15 -07:00
slorber
7a3a9a5c3f [add] AppRegistry support for React render callback
Close #858

Co-authored-by: Nicolas Gallagher <nicolasgallagher@gmail.com>
2018-04-07 10:15:17 -07:00
Nicolas Gallagher
4c59343fd3 [fix] SafeAreaView inset padding for Safari
See https://webkit.org/blog/7929/designing-websites-for-iphone-x/

Fix #859
2018-04-02 14:32:15 -07:00
Nicolas Gallagher
ce89b7e3ec [change] move 'react-art' to peerDependencies 2018-04-02 14:31:26 -07:00
Nicolas Gallagher
23fa663a6e [fix] Text font styling
Don't use 'font' shorthand internally to reset font styles, as the
framework's internal styles may be injected after application styles,
causing 'font' to override 'font-*' properties.

Fix #881
2018-04-02 11:37:59 -07:00
Nicolas Gallagher
b96dd668d3 [add] AppRegistry provider methods
Adds support for the following methods in React Native:
- setComponentProviderInstrumentationHook
- setWrapperComponentProvider
2018-04-01 10:29:27 -07:00
Nicolas Gallagher
a9cacb2ef5 [change] AppRegistry container is not absolutely positioned
Aligned with latest layout of AppContainer in React Native.

Fix #871
2018-04-01 09:47:02 -07:00
Nicolas Gallagher
c122814591 0.5.4 2018-04-01 09:34:51 -07:00
Bruno Lemos
efe18f1b7e [fix] Linking.openURL on Firefox
Fix #883
Close #884
2018-04-01 09:25:16 -07:00
Nicolas Gallagher
e1b576e427 [add] StyleSheet support for 'System' in font stack
Allow 'System' to be used in a font-family stack, e.g., "Noto, System".

Update the 'System' font stack to include "system-ui", which is the
latest keyword for system fonts.
2018-03-31 14:57:29 -07:00
Nicolas Gallagher
5d77d6e30f [fix] TextInput focus management
Defer to the browser's native handling of 'blur' and 'focus'; directly
update the internal state of TextInputState. Fixes an issue with
preserving focus when the tab is backgrounded.

Also ensure the TextInputState is correctly set when a component mounts.
When 'autoFocus' is true, 'onFocus' can be called before the internal
ref is set.

Fix #880
2018-03-31 14:01:19 -07:00
Jesús Darío
8fb9a88ee6 Add webpack-cli to getting started guide 2018-03-29 15:49:43 -07:00
Kyle Goggin
a7cda988ef [fix] ignore 'tvParallaxProperties' prop
Close #867
2018-03-29 15:47:39 -07:00
Nicolas Gallagher
b239cfb04d [fix] update InteractionManager stub
Fix #875
2018-03-29 15:32:38 -07:00
Nicolas Gallagher
8e94d858b2 [fix] Picker prop types
Fix #879
2018-03-29 15:11:16 -07:00
Nicolas Gallagher
aa22b06359 0.5.3 2018-03-15 13:32:24 -07:00
Paul Armstrong
2aa565c7c3 [fix] Picker default fontFamily
Close #860
2018-03-15 13:08:23 -07:00
Sakamoto, Kazunori
7b9b57960d Update getting-started.md
Fix __DEV__ value in example web/webpack.config.js

Close #862
2018-03-15 13:06:58 -07:00
Nicolas Gallagher
eae3ee9dca 0.5.2 2018-03-07 19:56:46 -08:00
Nicolas Gallagher
74e1a196b6 [fix] Linking.openURL works with nonce use
`Linking` no longer uses an iframe hack to add 'noopener' support to
older Safari. Instead it relies on browsers having support for
'noopener'.

Fix #837
Close #846
2018-03-05 11:50:08 -08:00
Nicolas Gallagher
48da9814e7 Update benchmark libraries 2018-03-05 10:40:02 -08:00
Nicolas Gallagher
4d391ef57c Link to example integrations in README 2018-03-05 10:22:26 -08:00
Nicolas Gallagher
780df69a80 Update link to Glitch starter 2018-03-01 19:37:12 -08:00
Nicolas Gallagher
6c229da01f Minor improvement to AppRegistry console.log message 2018-02-26 15:20:35 -08:00
Nicolas Gallagher
ae7aa818fb 0.5.1 2018-02-20 17:48:12 -08:00
Nicolas Gallagher
306cf67932 [add] Image style support for animations, interactions, and filters 2018-02-20 17:45:19 -08:00
Nicolas Gallagher
619c2048be [add] support for 'transformStyle' style prop 2018-02-20 17:44:22 -08:00
Nicolas Gallagher
b9f9a4f8d7 Move some View style propTypes to InteractionPropTypes 2018-02-20 17:43:22 -08:00
Nicolas Gallagher
58bc18c2f5 Group 'transition' style propTypes with animations 2018-02-20 17:42:19 -08:00
Nicolas Gallagher
073940fc4e Group 'perspective' style propType with transforms 2018-02-20 17:40:57 -08:00
Nicolas Gallagher
5c462303de Inline some values in TextStylePropTypes 2018-02-20 17:32:45 -08:00
Nicolas Gallagher
5fb92da317 [fix] Switch layout when left/right do not flip
The I18nManager can now disable the automatic BiDi flipping of
left/right, which caused the Switch layout to break in RTL mode. Change
the styles to use start/end.
2018-02-20 16:44:46 -08:00
Nicolas Gallagher
cafe10d851 Improve View 'pointerEvents' example 2018-02-19 18:48:31 -08:00
Nicolas Gallagher
b28581f44e [fix] Touchable 'touchAction' value 2018-02-19 18:27:49 -08:00
Nicolas Gallagher
9333e7e887 0.5.0 2018-02-19 15:48:05 -08:00
Nicolas Gallagher
b28cbbb37e [fix] TextInput default font styles
Match React Native (and web) expected defaults.
2018-02-19 15:29:05 -08:00
Nicolas Gallagher
a53372ceb3 [fix] babel-plugin only rewrites paths for known modules
Don't rewrite import paths for non-existent modules or types. They will
attempt to be imported from the package's main export. This change
currently requires a module map to be generated for the babel-plugin to
use. The map is automatically regenerated for any commit that alters the
entry file of react-native-web.

Fix #822
2018-02-19 13:05:42 -08:00
Nicolas Gallagher
239a43978f Update yarn.lock 2018-02-18 17:43:22 -08:00
Nicolas Gallagher
b4e4bfbb3c Fix the event handlers with event normalization
Events are now normalized within the responder system, so those handlers
don't need to be listed anymore. Recently added events (blur,
contextmenu, focus) are now also normalized.
2018-02-18 17:42:02 -08:00
Nicolas Gallagher
893963a799 [fix] PanResponder grant firing twice on touch devices
Touch events can produce trailing mouse events, which cause unwanted
events to fire in the responder event system.  This issue is avoided in
`Touchable` by cancelling the event in the responder release callback.
To fix the issue in other areas, like the PaneResponder, this hack is
moved into `createElement` and applied to event `onResponderRelease`
callback.

Fix #802
2018-02-18 17:41:48 -08:00
Nicolas Gallagher
e5adc5a37c Add 'coveragePathIgnorePatterns' to jest config 2018-02-17 18:03:36 -08:00
Nicolas Gallagher
6d908189a7 [fix] Text support for 'fontVariant' style
Fix #824
Close #825
2018-02-17 18:03:31 -08:00
Nicolas Gallagher
31db333ba3 [fix] Image support for SVG base64 data
The previous fix to support inline SVG data in utf-8 format broke images
that were rendering base64 SVGs.
2018-02-17 15:55:45 -08:00
Nicolas Gallagher
9fe089ca21 [add] development warning about using '!important' in styles
React Native for Web may use '!important' as part of the internal
resolving of styles. But user styles should never be allowed to include
'!important' in the value. Print a warning to the console when they do.
2018-02-17 14:46:31 -08:00
Nicolas Gallagher
a314d5b2e4 [change] MIT license
Now possible to license under MIT following the change to React Native's
license.

26684cf3ad

Fix #828
2018-02-17 12:23:45 -08:00
Nicolas Gallagher
fb845ebf44 Update benchmarks dependencies 2018-02-16 19:08:19 -08:00
Nicolas Gallagher
0d0c7e6e27 Document 'onBlur', 'onFocus', and 'onContextMenu' props 2018-02-16 18:53:33 -08:00
Nicolas Gallagher
f37003a079 Add end/start to BorderPropTypes 2018-02-15 19:08:34 -08:00
Nicolas Gallagher
f1fc2a9e37 Rewrite I18nManager and i18nStyle unit tests 2018-02-15 18:46:08 -08:00
Nicolas Gallagher
92794cdc9f [add] I18nManager and StyleSheet support for RTL without left/right flip
I18nManager supports `doLeftAndRightSwapInRTL` and
`swapLeftAndRightInRTL` to query and control the BiDi-flipping of
left/right properties and values. For example, you may choose to use
`end`/`start` for positioning that flips with writing direction, and
then disable `left`/`right` swapping in RTL so that `left` will always
be `left`.

The StyleSheet resolver cache must also account for the third "direction"
variant: RTL with no swapping of left/right.
2018-02-15 18:45:45 -08:00
Nicolas Gallagher
b754776373 [add] StyleSheet support for start/end properties and values
Add support for new style properties and values that automatically
account for the writing direction (as introduced in React Native
0.51.0). The start/end variants are automatically resolved to match the
global writing direction, as defined by I18nManager.isRTL. Start/End
take precedence over Left/Right.

Adds support for the following properties:

* `borderTop{End,Start}Radius`
* `borderBottom{End,Start}Radius`
* `border{End,Start}Color`
* `border{End,Start}Style`
* `border{End,Start}Width`
* `end`
* `margin{End,Start}`
* `padding{End,Start}`
* `start`

And values:

* `clear: "end" | "start"`
* `float: "end" | "start"`
* `textAlign: "end" | "start"`
2018-02-15 18:43:09 -08:00
Nicolas Gallagher
155b34e495 Fix unit test timeouts on Travis CI
Jest recommends using 'runInBand' for Travis CI. It runs all tests
serially in the current process, rather than creating a worker pool of
child processes that run tests.
2018-02-14 14:26:03 -08:00
Nicolas Gallagher
00c9dc4236 [fix] setNativeProps can apply flex styles
Updates the 'setValueForStyle' implementation to support style values
that contain "!important". This allows the 'flex{Basis,Grow,Shrink}'
values created by the style resolver to be applied. They currently use
the important priority as a work-around for browser-inconsistencies in
the 'flex' shorthand.

Upstream fix: https://github.com/facebook/react/pull/12181

Ref #798
Close #813
2018-02-14 13:51:00 -08:00
Nicolas Gallagher
b66aba1a06 website: fix ImageBackground source code link
Close #820
2018-02-14 13:39:14 -08:00
Nicolas Gallagher
17f8a674b8 [fix] ResponderEventPlugin skips 'mouseup' when no touch is active
Prevent the responder system recording 'mouseup' events if there is no
active 'touch'.

Fix #816
2018-02-13 15:02:09 -08:00
Nicolas Gallagher
b8080ba775 [fix] Touchable press events regression in 9ee89bc
Fix a regression introduced by "ResponderEvent event filtering"
9ee89bc7f7. Touchable press events were
firing twice after the event normalization was moved up into
'extractEvents'. The reason is:

1) events were previously not normalized throughout the responder system
2) once they were normalized, the fix introduced by a535c558d8 stopped working
3) because normalized nativeEvent did not include event data like 'cancelable'.

This patch adds more of the original nativeEvent fields to the
normalized event, so that React's synthetic event can return the correct
information for 'bubbles', 'cancelable', 'isDefaultPrevented()', etc.
2018-02-13 13:34:17 -08:00
Nicolas Gallagher
7265736545 [fix] StyleSheet accepts 'space-evenly' value for 'justifyContent' 2018-02-12 10:35:30 -08:00
Bulat Kidasov
399f465e59 [fix] NativeMethodsMixin measure/measureInWindow with scroll
Account for scroll offsets when calculating measurements.

Fix #702
Fix #805
Close #806
2018-02-12 10:27:47 -08:00
Nicolas Gallagher
9ee89bc7f7 [fix] ResponderEventPlugin event filtering
Exclude middle, wheel, and right click mouse events from the responder
system. This fixes the Touchables incorrectly triggering 'onPress' in
response to these events.

Filter mousemove events in the 'extractEvents' methods, and check for
active touches rather than the length of the touch bank. This fixes the
PanResponder not functioning after the first touch in Firefox.

Fix #719
Fix #729
Close #804
2018-02-12 10:08:44 -08:00
Jakub Rimal
748b2d0f3f [fix] Image 'source' prop update when missing in initial render
Close #811
2018-02-12 08:27:48 -08:00
Nicolas Gallagher
fb4635e013 Update README's 2018-02-08 16:09:56 -08:00
Nicolas Gallagher
73b459e770 [add] TextInput onKeyPress support for arrow keys
Close #791
Close #792
2018-02-08 10:57:32 -08:00
243 changed files with 9482 additions and 4276 deletions

View File

@@ -1,20 +0,0 @@
**Do you want to request a *feature* or report a *bug*?**
**What is the current behavior?**
**If the current behavior is a bug, please provide the steps to reproduce and
if a minimal demo of the problem via Glitch or similar (template:
https://glitch.com/edit/#!/react-native-web-playground).**
1.
2.
**What is the expected behavior?**
**Environment (include versions). Did this work in previous versions?**
* OS:
* Device:
* Browser:
* React Native for Web (version):
* React (version):

32
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View File

@@ -0,0 +1,32 @@
---
name: "\U0001F41B Bug report"
about: "If something isn't working as expected \U0001F914"
---
**The problem**
A clear and concise description of the bug or problem.
**How to reproduce**
Test case: <!-- FORK THIS TEMPLATE: https://codesandbox.io/s/6lx6ql1w5r -->
Steps to reproduce:
1.
2.
3.
<!-- If applicable, add screenshots to help explain your problem. -->
**Expected behavior**
A clear and concise description of what you expected to happen.
**Environment (include versions). Did this work in previous versions?**
* OS:
* Device:
* Browser:
* React Native for Web (version):
* React (version):
**Additional context**
Add any other context about the problem here.

17
.github/ISSUE_TEMPLATE/feature.md vendored Normal file
View File

@@ -0,0 +1,17 @@
---
name: "\U0001F680 Feature request"
about: If you have a suggestion
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is, e.g., I have an issue when [...]
**Describe a solution you'd like**
A clear and concise description of what you want to happen. Add any considered drawbacks.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1 +0,0 @@
**Before submitting a pull request,** please make sure you have followed the steps the CONTRIBUTING guide.

45
LICENSE
View File

@@ -1,31 +1,22 @@
BSD License
MIT License
For React Native software
Copyright (c) 2015-present, Nicolas Gallagher.
Copyright (c) 2015-present, Facebook, Inc.
Copyright (c) 2015-present, Nicolas Gallagher. All rights reserved.
Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name Facebook nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -19,20 +19,19 @@ rewriting existing code. React Native for Web can also render to HTML and
critical CSS on the server using Node.js.
Who is using React Native for Web? [Twitter](https://mobile.twitter.com),
[Major League Soccer](https://matchcenter.mlssoccer.com), [The
[Major League Soccer](https://matchcenter.mlssoccer.com),
[Flipkart](https://www.flipkart.com/), Playstation, Uber, [The
Times](https://github.com/newsuk/times-components), [React Native's
documentation](http://facebook.github.io/react-native/).
Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
Browser support: Chrome, Firefox, Edge, Safari 7+, IE 10+.
## Quick start
The easiest way to get started with React Native for Web is to use this
[ready-to-go project on Glitch](https://glitch.com/edit/#!/react-native-web-playground).
You dont need to install anything to try it out.
If you are unfamiliar with setting up a React web project, please follow the
recommendations in the [React documentation](https://reactjs.org/).
[CodeSandbox](https://codesandbox.io/s/q4qymyp2l6) template (or
[Glitch](https://glitch.com/edit/#!/react-native)). You dont need to install
anything to try it out.
## Documentation
@@ -44,15 +43,6 @@ design details, and for 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).
### Installation
Install using `yarn` or `npm`:
```
yarn add react react-dom react-native-web
yarn add --dev babel-plugin-react-native-web
```
### Guides
* [Getting started](https://github.com/necolas/react-native-web/blob/master/website/guides/getting-started.md)
@@ -97,6 +87,17 @@ 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/website/storybook/.storybook)
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
## Contributing
The main purpose of this repository is to help evolve React web and native
@@ -126,7 +127,9 @@ relatively limited scope. This is a great place to get started.
## License
React Native for Web is [BSD licensed](./LICENSE).
React Native for Web is [MIT licensed](./LICENSE). By contributing to React
Native for Web, you agree that your contributions will be licensed under its
MIT license.
[package-badge]: https://img.shields.io/npm/v/react-native-web.svg?style=flat
[package-url]: https://yarnpkg.com/en/package/react-native-web

View File

@@ -1,10 +1,11 @@
{
"private": true,
"version": "0.4.0",
"version": "0.7.0",
"name": "react-native-web-monorepo",
"scripts": {
"clean": "del ./packages/*/dist",
"compile": "yarn clean && cd packages/react-native-web && babel src --out-dir dist --ignore \"**/__tests__\"",
"compile:commonjs": "cd packages/react-native-web && MODULES=commonjs babel src --out-dir dist/cjs --ignore \"**/__tests__\"",
"benchmarks": "cd packages/benchmarks && yarn build",
"benchmarks:release": "cd packages/benchmarks && yarn release",
"website": "cd website && yarn start",
@@ -12,19 +13,19 @@
"flow": "flow",
"fmt": "find packages scripts types website -name '*.js' | grep -v -E '(node_modules|dist|vendor)' | xargs yarn fmt:cmd",
"fmt:cmd": "prettier --write",
"jest": "jest --config ./scripts/jest/config.js",
"jest": "MODULES=commonjs jest --config ./scripts/jest/config.js",
"lint": "yarn lint:check --fix",
"lint:check": "eslint packages scripts website",
"precommit": "lint-staged",
"prerelease": "yarn test && yarn compile",
"prerelease": "yarn test && yarn compile && yarn compile:commonjs",
"release": "node ./scripts/release/publish.js",
"postrelease": "yarn website:release && yarn benchmarks:release",
"test": "yarn flow && yarn lint:check && yarn jest"
"test": "yarn flow && yarn lint:check && yarn jest --runInBand"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.3",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.2",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
@@ -37,21 +38,22 @@
"del-cli": "^1.1.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.0",
"enzyme-to-json": "^3.2.2",
"eslint": "^4.12.1",
"enzyme-to-json": "^3.3.3",
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-react": "^7.5.1",
"eslint-plugin-promise": "^3.7.0",
"eslint-plugin-react": "^7.7.0",
"flow-bin": "^0.63.1",
"glob": "^7.1.2",
"husky": "^0.14.3",
"jest": "^21.2.1",
"lint-staged": "^6.0.0",
"prettier": "^1.8.2",
"raf": "^3.4.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-test-renderer": "^16.2.0"
"jest": "^22.4.3",
"jest-canvas-mock": "^1.0.2",
"lint-staged": "^7.1.0",
"prettier": "^1.12.1",
"react": "^16.3.2",
"react-art": "^16.3.2",
"react-dom": "^16.3.2",
"react-test-renderer": "^16.3.2"
},
"workspaces": [
"packages/*",
@@ -59,9 +61,12 @@
],
"lint-staged": {
"**/*.js": [
"fmt:cmd",
"prettier --write",
"git update-index --again",
"eslint"
],
"packages/react-native-web/src/index.js": [
"node ./scripts/babel/createModuleMap.js"
]
},
"prettier": {
@@ -69,5 +74,5 @@
"singleQuote": true
},
"author": "Nicolas Gallagher",
"license": "BSD-3-Clause"
"license": "MIT"
}

View File

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

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`export from "react-native" 1`] = `
exports[`Rewrite react-native to react-native-web export from "react-native": export from "react-native" 1`] = `
"
export { View } from 'react-native';
export { ColorPropType, StyleSheet, Text, createElement } from 'react-native';
@@ -15,7 +15,7 @@ export { default as createElement } from 'react-native-web/dist/exports/createEl
"
`;
exports[`export from "react-native-web" 1`] = `
exports[`Rewrite react-native to react-native-web export from "react-native-web": export from "react-native-web" 1`] = `
"
export { View } from 'react-native-web';
export { ColorPropType, StyleSheet, Text, createElement } from 'react-native-web';
@@ -30,7 +30,7 @@ export { default as createElement } from 'react-native-web/dist/exports/createEl
"
`;
exports[`import from "native-native" 1`] = `
exports[`Rewrite react-native to react-native-web import from "native-native": import from "native-native" 1`] = `
"
import ReactNative from 'react-native';
import { View } from 'react-native';
@@ -41,14 +41,14 @@ import * as ReactNativeModules from 'react-native';
import ReactNative from 'react-native-web/dist/index';
import View from 'react-native-web/dist/exports/View';
import Invalid from 'react-native-web/dist/exports/Invalid';
import { Invalid } from 'react-native-web/dist/index';
import MyView from 'react-native-web/dist/exports/View';
import ViewPropTypes from 'react-native-web/dist/exports/ViewPropTypes';
import * as ReactNativeModules from 'react-native-web/dist/index';
"
`;
exports[`import from "react-native-web" 1`] = `
exports[`Rewrite react-native to react-native-web import from "react-native-web": import from "react-native-web" 1`] = `
"
import { createElement } from 'react-native-web';
import { ColorPropType, StyleSheet, View, TouchableOpacity, processColor } from 'react-native-web';
@@ -66,7 +66,7 @@ import * as ReactNativeModules from 'react-native-web/dist/index';
"
`;
exports[`require "react-native" 1`] = `
exports[`Rewrite react-native to react-native-web require "react-native": require "react-native" 1`] = `
"
const ReactNative = require('react-native');
const { View } = require('react-native');
@@ -84,7 +84,7 @@ const TouchableOpacity = require('react-native-web/dist/exports/TouchableOpacity
"
`;
exports[`require "react-native-web" 1`] = `
exports[`Rewrite react-native to react-native-web require "react-native-web": require "react-native-web" 1`] = `
"
const ReactNative = require('react-native-web');
const { createElement } = require('react-native-web');

View File

@@ -1,5 +1,7 @@
const moduleMap = require('./moduleMap');
const getDistLocation = importName =>
importName ? `react-native-web/dist/exports/${importName}` : undefined;
importName && moduleMap[importName] ? `react-native-web/dist/exports/${importName}` : undefined;
const isReactNativeRequire = (t, node) => {
const { declarations } = node;

View File

@@ -0,0 +1,61 @@
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
module.exports = {
ART: true,
ActivityIndicator: true,
Animated: true,
AppRegistry: true,
AppState: true,
AsyncStorage: true,
BackHandler: true,
Button: true,
CheckBox: true,
Clipboard: true,
ColorPropType: true,
Dimensions: true,
Easing: true,
EdgeInsetsPropType: true,
FlatList: true,
I18nManager: true,
Image: true,
ImageBackground: true,
InteractionManager: true,
Keyboard: true,
KeyboardAvoidingView: true,
Linking: true,
ListView: true,
Modal: true,
NativeModules: true,
NetInfo: true,
PanResponder: true,
Picker: true,
PixelRatio: true,
Platform: true,
PointPropType: true,
ProgressBar: true,
RefreshControl: true,
SafeAreaView: true,
ScrollView: true,
SectionList: true,
Slider: true,
StatusBar: true,
StyleSheet: true,
Switch: true,
Text: true,
TextInput: true,
TextPropTypes: true,
Touchable: true,
TouchableHighlight: true,
TouchableNativeFeedback: true,
TouchableOpacity: true,
TouchableWithoutFeedback: true,
UIManager: true,
Vibration: true,
View: true,
ViewPropTypes: true,
VirtualizedList: true,
createElement: true,
findNodeHandle: true,
processColor: true,
render: true,
unmountComponentAtNode: true
};

View File

@@ -19,12 +19,9 @@ yarn benchmarks --watch
## Notes
These benchmarks are approximations of extreme cases that libraries may
encounter. The deep and wide tree cases look at the performance of mounting and
rendering large trees of styled elements. The dynamic case looks at the
performance of repeated style updates to a large mounted tree. Some libraries
must inject new styles for each "dynamic style", whereas others may not.
Libraries without support for dynamic styles (i.e., they rely on user-authored
inline styles) do not include a corresponding benchmark.
encounter. Their purpose is to provide an early-warning signal for performance
regressions. Each test report includes the mean and standard deviation of the
timings, and approximations of the time spent in scripting (S) and layout (L).
The components used in the render benchmarks are simple enough to be
implemented by multiple UI or style libraries. The benchmark implementations
@@ -33,6 +30,19 @@ functionality_.
No benchmark will run for more than 20 seconds.
### Mount deep/wide tree
These cases look at the performance of mounting and rendering large trees of
elements that use static styles.
### Update dynamic styles
This case looks at the performance of repeated style updates to a large mounted
tree. Some libraries choose to inject new styles for each "dynamic style",
whereas others choose to use inline styles. Libraries without built-in support
for dynamic styles (i.e., they rely on user-authored inline styles) are not
included.
## Example results
### MacBook Pro (2011)
@@ -41,52 +51,20 @@ MacBook Pro (13-inch, Early 2011); 2.3 GHz Intel Core i5; 8 GB 1333 MHz DDR3 RAM
Typical render timings: mean ± standard deviations.
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Dynamic update (ms) |
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Dynamic update (ms) |
| :--- | ---: | ---: | ---: |
| `css-modules` | `15.23` `±04.31` | `21.27` `±07.03` | - |
| `react-native-web@0.3.2` | `17.52` `±04.44` | `24.14` `±04.39` | `15.03` `±02.22` |
| `inline-styles` | `50.06` `±06.70` | `76.38` `±09.58` | `06.43` `±02.02` |
Other libraries
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Dynamic update (ms) |
| :--- | ---: | ---: | ---: |
| `aphrodite@1.2.5` | `17.27` `±05.96` | `24.89` `±08.36` | - |
| `glamor@2.20.40` | `21.59` `±05.38` | `27.93` `±07.56` | ‡ |
| `emotion@8.0.12` | `21.07` `±04.16` | `31.40` `±09.40` | ‡ `19.80` `±13.56` |
| `styletron-react@3.0.3` | `23.55` `±05.14` | `34.26` `±07.58` | `10.39` `±02.94` |
| `react-fela@5.0.0` | `27.58` `±04.26` | `39.54` `±05.46` | `10.93` `±01.69` |
| `react-jss@8.2.1` | `27.31` `±07.87` | `40.74` `±10.67` | - |
| `styled-jsx@2.2.1` | `27.46` `±07.85` | `41.47` `±11.53` | `29.16` `±09.98` |
| `styled-components@2.4.0` | `43.89` `±06.99` | `63.26` `±09.02` | `16.17` `±03.71` |
| `reactxp@0.51.0-alpha.9` | `51.86` `±07.21` | `78.80` `±11.85` | `15.04` `±03.92` |
| `radium@0.21.0` | `101.06` `±13.00` | `144.46` `±16.94` | `17.44` `±03.59` |
| `css-modules` | `30.19` `±04.84` | `38.25` `±04.85` | - |
| `react-native-web@0.4.0` | `36.40` `±04.98` | `51.28` `±05.58` | `19.36` `±02.56` |
| `inline-styles` | `64.12` `±07.69` | `94.49` `±11.34` | `09.84` `±02.36` |
### Moto G4
Moto G4 (Android 7); Octa-core (4x1.5 GHz & 4x1.2 Ghz); 2 GB RAM. Google Chrome 63
Moto G4 (Android 7); Octa-core (4x1.5 GHz & 4x1.2 Ghz); 2 GB RAM. Google Chrome 63.
Typical render timings: mean ± standard deviations.
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Dynamic update (ms) |
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Dynamic update (ms) |
| :--- | ---: | ---: | ---: |
| `css-modules` | `56.18` 19.54` | `75.95` `±23.55` | - |
| `react-native-web@0.3.2` | `68.53` 21.00` | `101.03` 25.32` | `60.57` `±09.07` |
| `inline-styles` | `140.32` `±23.91` | `208.55` 35.25` | `20.36` `±04.92` |
Other libraries
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Dynamic update (ms) |
| :--- | ---: | ---: | ---: |
| `aphrodite@1.2.5` | `58.77` `±19.73` | `85.83` `±24.64` | - |
| `glamor@2.20.40` | `81.05` `±15.87` | `104.02` `±20.92` | ‡ |
| `emotion@8.0.12` | `77.12` `±19.61` | `112.04` `±24.43` | ‡ `80.40` `±40.56` |
| `styletron-react@3.0.3` | `91.00` `±17.95` | `130.49` `±20.06` | `39.70` `±06.85` |
| `react-fela@5.0.0` | `101.36` `±19.55` | `142.18` `±21.87` | `43.64` `±12.24` |
| `styled-jsx@2.2.1` | `101.60` `±25.26` | `144.12` `±30.79` | `115.63` `±32.77` |
| `react-jss@8.2.1` | `112.46` `±32.07` | `165.96` `±42.54` | - |
| `styled-components@2.4.0` | `159.85` `±24.30` | `231.00` `±31.34` | `53.86` `±13.40` |
| `reactxp@0.51.0-alpha.9` | `182.05` `±30.72` | `261.25` `±35.54` | `58.20` `±08.62` |
| `radium@0.21.0` | `323.93` `±41.46` | `464.70` `±53.93` | `59.13` `±09.76` |
‡Glamor essentially crashes the browser tab. Emotion gets slower every iteration.
| `css-modules` | `98.24` 20.26` | `143.75` `±25.50` | - |
| `react-native-web@0.4.0` | `131.46` 18.96` | `174.70` 14.88` | `60.87` `±06.32` |
| `inline-styles` | `184.58` `±26.23` | `273.86` 26.23` | `30.28` `±07.44` |

View File

@@ -1,37 +1,37 @@
{
"private": true,
"name": "benchmarks",
"version": "0.4.0",
"version": "0.7.0",
"scripts": {
"build": "mkdir -p dist && cp -f index.html dist/index.html && webpack --config ./webpack.config.js",
"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 -"
},
"dependencies": {
"aphrodite": "1.2.5",
"aphrodite": "^2.2.0",
"classnames": "^2.2.5",
"d3-scale-chromatic": "^1.1.1",
"emotion": "8.0.12",
"fela": "6.1.3",
"d3-scale-chromatic": "^1.2.0",
"emotion": "^9.1.3",
"fela": "^6.1.7",
"glamor": "2.20.40",
"radium": "0.21.2",
"react": "^16.2.0",
"react-component-benchmark": "^0.0.4",
"react-dom": "^16.2.0",
"react-fela": "6.2.4",
"react-jss": "8.2.1",
"react-native-web": "0.4.0",
"reactxp": "0.51.2",
"style-loader": "0.20.1",
"styled-components": "3.1.2",
"styled-jsx": "2.2.2",
"styletron-client": "3.0.4",
"styletron-react": "3.0.4"
"radium": "^0.24.0",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-fela": "^7.2.0",
"react-jss": "^8.4.0",
"react-native-web": "0.7.0",
"reactxp": "^1.1.1",
"styled-components": "^3.2.6",
"styled-jsx": "^2.2.6",
"styletron-engine-atomic": "^1.0.5",
"styletron-react": "^4.2.1"
},
"devDependencies": {
"babel-plugin-react-native-web": "0.4.0",
"css-loader": "^0.28.9",
"style-loader": "^0.19.1",
"webpack": "^3.10.0",
"webpack-bundle-analyzer": "^2.9.2"
"babel-plugin-react-native-web": "0.7.0",
"css-loader": "^0.28.11",
"style-loader": "^0.21.0",
"url-loader": "^1.0.1",
"webpack": "^4.8.1",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-cli": "^2.1.3"
}
}

View File

@@ -292,7 +292,6 @@ const styles = StyleSheet.create({
},
button: {
borderRadius: 0,
fontSize: 32,
flex: 1
}
});

View File

@@ -1,3 +1,9 @@
/**
* The MIT License (MIT)
* Copyright (c) 2017 Paul Armstrong
* https://github.com/paularmstrong/react-component-benchmark
*/
/* global $Values */
/**
* @flow

View File

@@ -56,6 +56,7 @@ const styles = StyleSheet.create({
},
text: {
color: '#fff',
fontSize: 20,
fontWeight: '500',
padding: 8,
textAlign: 'center',

View File

@@ -40,7 +40,7 @@ class ReportCard extends React.PureComponent {
{fmt(mean)} ±{fmt(stdDev)} ms
</Text>
<Text style={[styles.smallText, styles.monoFont]}>
(S/L) {fmt(meanScripting)} / {fmt(meanLayout)} ms
(S/L) {fmt(meanScripting)}/{fmt(meanLayout)} ms
</Text>
</Fragment>
) : (

View File

@@ -1,4 +1,4 @@
import { BenchmarkType } from 'react-component-benchmark';
import { BenchmarkType } from '../app/Benchmark';
import { number, object } from 'prop-types';
import React from 'react';
import { interpolatePurples, interpolateBuPu, interpolateRdPu } from 'd3-scale-chromatic';

View File

@@ -1,4 +1,4 @@
import { BenchmarkType } from 'react-component-benchmark';
import { BenchmarkType } from '../app/Benchmark';
import { number, object } from 'prop-types';
import React, { Component } from 'react';

View File

@@ -25,7 +25,7 @@ const Box = styled(View)`
flex-direction: ${props => (props.layout === 'column' ? 'column' : 'row')};
padding: ${props => (props.outer ? '4px' : '0')};
${props => props.fixed && 'height:6px;'} ${props =>
props.fixed && 'width:6px;'} background-color: ${props => getColor(props.color)};
props.fixed && 'width:6px;'} background-color: ${props => getColor(props.color)};
`;
export default Box;

View File

@@ -1,8 +1,8 @@
/* eslint-disable react/prop-types */
import { styled } from 'styletron-react';
import { withStyle } from 'styletron-react';
import View from './View';
const Box = styled(
const Box = withStyle(
View,
({ color, fixed = false, layout = 'column', outer = false, ...other }) => ({
...styles[`color${color}`],

View File

@@ -1,7 +1,7 @@
/* eslint-disable react/prop-types */
import React from 'react';
import Styletron from 'styletron-client';
import { StyletronProvider } from 'styletron-react';
import { Client as Styletron } from 'styletron-engine-atomic';
import { Provider as StyletronProvider } from 'styletron-react';
import View from './View';
const styletron = new Styletron();
@@ -9,7 +9,7 @@ const styletron = new Styletron();
class Provider extends React.Component {
render() {
return (
<StyletronProvider styletron={styletron}>
<StyletronProvider value={styletron}>
<View>{this.props.children}</View>
</StyletronProvider>
);

View File

@@ -1,11 +1,11 @@
const babelPreset = require('../../scripts/babel/preset');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const path = require('path');
const webpack = require('webpack');
const appDirectory = path.resolve(__dirname);
module.exports = {
mode: 'production',
context: __dirname,
entry: './src/index',
output: {
@@ -32,7 +32,7 @@ module.exports = {
options: {
cacheDirectory: false,
presets: babelPreset,
plugins: ['react-native-web', 'styled-jsx/babel']
plugins: ['styled-jsx/babel']
}
}
}
@@ -42,17 +42,11 @@ module.exports = {
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
dead_code: true,
drop_console: false,
screw_ie8: true,
warnings: false
}
})
]
],
resolve: {
alias: {
'react-native': 'react-native-web'
}
}
};

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`enzyme.mount complex 1`] = `
exports[`enzyme complex: enzyme.mount complex 1`] = `
<Box
element={
<View>
@@ -26,7 +26,7 @@ exports[`enzyme.mount complex 1`] = `
}
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<Title>
<Text
@@ -39,7 +39,7 @@ exports[`enzyme.mount complex 1`] = `
}
>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-ubezar rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-ubezar rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
@@ -48,7 +48,7 @@ exports[`enzyme.mount complex 1`] = `
</Title>
<View>
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
>
<View
style={
@@ -58,12 +58,12 @@ exports[`enzyme.mount complex 1`] = `
}
>
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-1knelpx rn-paddingRight-1ah4tor rn-paddingBottom-k8qxaj rn-paddingLeft-b5h31w rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-1knelpx rn-paddingRight-1ah4tor rn-paddingBottom-k8qxaj rn-paddingLeft-b5h31w rn-position-bnwqim rn-zIndex-1lgpqti"
/>
</View>
<Text>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-1b43r93 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-1b43r93 rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Nested
@@ -76,85 +76,24 @@ exports[`enzyme.mount complex 1`] = `
</Box>
`;
exports[`enzyme.mount composite 1`] = `
<Box>
<View
style={
Object {
"backgroundColor": "red",
"padding": 10,
}
}
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
/>
</View>
</Box>
`;
exports[`enzyme.mount nested 1`] = `
<Box>
<View
style={
Object {
"backgroundColor": "red",
"padding": 10,
}
}
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<Title>
<Text
style={
Object {
"color": "black",
"fontSize": 16,
"textAlignVertical": "center",
}
}
>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-ubezar rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
</div>
</Text>
</Title>
</div>
</View>
</Box>
`;
exports[`enzyme.mount noop 1`] = `
<View>
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
</View>
`;
exports[`enzyme.render complex 1`] = `
exports[`enzyme complex: enzyme.render complex 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
class="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
class="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-ubezar rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
class="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-ubezar rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
</div>
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-1knelpx rn-paddingRight-1ah4tor rn-paddingBottom-k8qxaj rn-paddingLeft-b5h31w rn-position-bnwqim rn-zIndex-1lgpqti"
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-1knelpx rn-paddingRight-1ah4tor rn-paddingBottom-k8qxaj rn-paddingLeft-b5h31w rn-position-bnwqim rn-zIndex-1lgpqti"
/>
<div
class="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-1b43r93 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
class="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-1b43r93 rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Nested
@@ -163,32 +102,7 @@ exports[`enzyme.render complex 1`] = `
</div>
`;
exports[`enzyme.render composite 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`enzyme.render nested 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
class="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-ubezar rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
</div>
</div>
`;
exports[`enzyme.render noop 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`enzyme.shallow complex 1`] = `
exports[`enzyme complex: enzyme.shallow complex 1`] = `
<View
style={
Object {
@@ -215,7 +129,30 @@ exports[`enzyme.shallow complex 1`] = `
</View>
`;
exports[`enzyme.shallow composite 1`] = `
exports[`enzyme composite: enzyme.mount composite 1`] = `
<Box>
<View
style={
Object {
"backgroundColor": "red",
"padding": 10,
}
}
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
/>
</View>
</Box>
`;
exports[`enzyme composite: enzyme.render composite 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`enzyme composite: enzyme.shallow composite 1`] = `
<View
style={
Object {
@@ -226,7 +163,56 @@ exports[`enzyme.shallow composite 1`] = `
/>
`;
exports[`enzyme.shallow nested 1`] = `
exports[`enzyme nested: enzyme.mount nested 1`] = `
<Box>
<View
style={
Object {
"backgroundColor": "red",
"padding": 10,
}
}
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<Title>
<Text
style={
Object {
"color": "black",
"fontSize": 16,
"textAlignVertical": "center",
}
}
>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-ubezar rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
</div>
</Text>
</Title>
</div>
</View>
</Box>
`;
exports[`enzyme nested: enzyme.render nested 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
class="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-ubezar rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
</div>
</div>
`;
exports[`enzyme nested: enzyme.shallow nested 1`] = `
<View
style={
Object {
@@ -241,30 +227,44 @@ exports[`enzyme.shallow nested 1`] = `
</View>
`;
exports[`enzyme.shallow noop 1`] = `
exports[`enzyme noop: enzyme.mount noop 1`] = `
<View>
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
</View>
`;
exports[`enzyme noop: enzyme.render noop 1`] = `
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`enzyme noop: enzyme.shallow noop 1`] = `
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`react-test-renderer complex 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-ubezar rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-ubezar rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
</div>
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-1knelpx rn-paddingRight-1ah4tor rn-paddingBottom-k8qxaj rn-paddingLeft-b5h31w rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-1knelpx rn-paddingRight-1ah4tor rn-paddingBottom-k8qxaj rn-paddingLeft-b5h31w rn-position-bnwqim rn-zIndex-1lgpqti"
/>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-1b43r93 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-1b43r93 rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Nested
@@ -275,16 +275,16 @@ exports[`react-test-renderer complex 1`] = `
exports[`react-test-renderer composite 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`react-test-renderer nested 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-backgroundColor-1mjtqww rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-m611by rn-paddingRight-1qfoi16 rn-paddingBottom-1mi0q7o rn-paddingLeft-1hfyk0a rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-font-1lw9tu2 rn-fontFamily-10u92zi rn-fontSize-ubezar rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-1bodaif rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-ubezar rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-verticalAlign-9iso6 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
>
Hello World
@@ -294,6 +294,6 @@ exports[`react-test-renderer nested 1`] = `
exports[`react-test-renderer noop 1`] = `
<div
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1pxmb3b rn-flexBasis-7vfszb rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
className="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;

View File

@@ -1,8 +1,10 @@
{
"name": "react-native-web",
"version": "0.4.0",
"version": "0.7.0",
"description": "React Native for Web",
"main": "dist/index.js",
"module": "dist/index.js",
"main": "dist/cjs/index.js",
"sideEffects": false,
"files": [
"dist",
"jest",
@@ -16,18 +18,18 @@
"deep-assign": "^2.0.0",
"fbjs": "^0.8.16",
"hyphenate-style-name": "^1.0.2",
"inline-style-prefixer": "^4.0.0",
"inline-style-prefixer": "^4.0.2",
"normalize-css-color": "^1.0.2",
"prop-types": "^15.6.0",
"react-art": "^16.2.0",
"react-timer-mixin": "^0.13.3"
},
"peerDependencies": {
"react": "16.x.x",
"react-art": "16.x.x",
"react-dom": "16.x.x"
},
"author": "Nicolas Gallagher",
"license": "BSD-3-Clause",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/necolas/react-native-web.git"

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ActivityIndicator
* @flow
*/

View File

@@ -1,12 +1,9 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Animated
* @flow
*/

View File

@@ -1,9 +1,8 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
@@ -12,13 +11,14 @@
import StyleSheet from '../StyleSheet';
import View from '../View';
import { any, node } from 'prop-types';
import React, { Component } from 'react';
import React, { Component, type ComponentType } from 'react';
type Context = {
rootTag: any
};
type Props = {
WrapperComponent?: ?ComponentType<*>,
// $FlowFixMe
children?: React.Children,
rootTag: any
@@ -36,6 +36,7 @@ export default class AppContainer extends Component<Props, State> {
};
static propTypes = {
WrapperComponent: any,
children: node,
rootTag: any.isRequired
};
@@ -47,23 +48,29 @@ export default class AppContainer extends Component<Props, State> {
}
render() {
const { children, WrapperComponent } = this.props;
let innerView = (
<View
children={children}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer}
/>
);
if (WrapperComponent) {
innerView = <WrapperComponent>{innerView}</WrapperComponent>;
}
return (
<View pointerEvents="box-none" style={[styles.appContainer, StyleSheet.absoluteFill]}>
<View
children={this.props.children}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer}
/>
<View pointerEvents="box-none" style={styles.appContainer}>
{innerView}
</View>
);
}
}
const styles = StyleSheet.create({
/**
* Ensure that the application covers the whole screen.
*/
appContainer: {
flex: 1
}

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Additional CSS for styled app 1`] = `
exports[`AppRegistry getApplication "getStyleElement" produces styles that are a function of rendering "element": Additional CSS for styled app 1`] = `
"
.rn-backgroundColor-1e4kli0{background-color:purple}
.rn-borderTopWidth-10pzpfo{border-top-width:1234px}
@@ -9,24 +9,7 @@ exports[`Additional CSS for styled app 1`] = `
.rn-borderLeftWidth-150mub4{border-left-width:1234px}"
`;
exports[`AppRegistry/renderApplication getApplication returns "element" and "getStyleElement" 1`] = `
<AppContainer
rootTag={Object {}}
>
<RootComponent />
</AppContainer>
`;
exports[`AppRegistry/renderApplication getApplication returns "element" and "getStyleElement" 2`] = `
"<style id=\\"react-native-stylesheet\\">@media all{
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-webkit-search-results-button,input::-webkit-search-results-decoration{display:none;}
}</style>"
`;
exports[`CSS for an unstyled app 1`] = `
exports[`AppRegistry getApplication "getStyleElement" produces styles that are a function of rendering "element": CSS for an unstyled app 1`] = `
"@media all{
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
@@ -46,8 +29,8 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-borderLeftWidth-gxnn5r{border-left-width:0px}
.rn-boxSizing-deolkf{box-sizing:border-box}
.rn-display-6koalj{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
.rn-flexShrink-1pxmb3b{-ms-flex-negative:0 !important;-webkit-flex-shrink:0 !important;flex-shrink:0 !important}
.rn-flexBasis-7vfszb{-ms-flex-preferred-size:auto !important;-webkit-flex-basis:auto !important;flex-basis:auto !important}
.rn-flexShrink-1qe8dj5{-ms-flex-negative:0;-webkit-flex-shrink:0;flex-shrink:0}
.rn-flexBasis-1mlwlqe{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}
.rn-flexDirection-eqz5dr{-ms-flex-direction:column;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
.rn-marginTop-1mnahxq{margin-top:0px}
.rn-marginRight-61z16t{margin-right:0px}
@@ -61,12 +44,25 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-paddingLeft-gy4na3{padding-left:0px}
.rn-position-bnwqim{position:relative}
.rn-zIndex-1lgpqti{z-index:0}
.rn-flex-13awgt0{-ms-flex:1;-webkit-flex:1;flex:1}
.rn-flexGrow-1m1wadx{-ms-flex-positive:1 !important;-webkit-flex-grow:1 !important;flex-grow:1 !important}
.rn-flexShrink-1awmn5t{-ms-flex-negative:1 !important;-webkit-flex-shrink:1 !important;flex-shrink:1 !important}
.rn-bottom-1p0dtai{bottom:0px}
.rn-left-1d2f490{left:0px}
.rn-position-u8s1d{position:absolute}
.rn-right-zchlnj{right:0px}
.rn-top-ipm5af{top:0px}"
.rn-flexGrow-16y2uox{-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1}
.rn-flexShrink-1wbh5a2{-ms-flex-negative:1;-webkit-flex-shrink:1;flex-shrink:1}
.rn-flexBasis-1ro0kt6{-ms-flex-preferred-size:0%;-webkit-flex-basis:0%;flex-basis:0%}"
`;
exports[`AppRegistry getApplication returns "element" and "getStyleElement" 1`] = `
<AppContainer
WrapperComponent={undefined}
rootTag={Object {}}
>
<RootComponent />
</AppContainer>
`;
exports[`AppRegistry getApplication returns "element" and "getStyleElement" 2`] = `
"<style id=\\"react-native-stylesheet\\">@media all{
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-webkit-search-results-button,input::-webkit-search-results-decoration{display:none;}
}</style>"
`;

View File

@@ -0,0 +1,91 @@
/* eslint-env jasmine, jest */
import AppRegistry from '..';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { render } from 'enzyme';
import StyleSheet from '../../StyleSheet';
import View from '../../View';
const RootComponent = () => <div />;
const styles = StyleSheet.create({ root: { borderWidth: 1234, backgroundColor: 'purple' } });
const AlternativeComponent = () => <View style={styles.root} />;
describe('AppRegistry', () => {
describe('getApplication', () => {
const canUseDOM = ExecutionEnvironment.canUseDOM;
beforeEach(() => {
ExecutionEnvironment.canUseDOM = false;
});
afterEach(() => {
ExecutionEnvironment.canUseDOM = canUseDOM;
});
test('does not throw when missing appParameters', () => {
AppRegistry.registerComponent('App', () => RootComponent);
expect(() => AppRegistry.getApplication('App')).not.toThrow();
});
test('returns "element" and "getStyleElement"', () => {
AppRegistry.registerComponent('App', () => RootComponent);
const { element, getStyleElement } = AppRegistry.getApplication('App', {});
const styleElement = ReactDOMServer.renderToStaticMarkup(getStyleElement());
expect(element).toMatchSnapshot();
expect(styleElement).toMatchSnapshot();
});
test('"getStyleElement" adds props to <style>', () => {
const nonce = '2Bz9RM/UHvBbmo3jK/PbYZ==';
AppRegistry.registerComponent('App', () => RootComponent);
const { getStyleElement } = AppRegistry.getApplication('App', {});
const styleElement = getStyleElement({ nonce });
expect(styleElement.props.nonce).toBe(nonce);
});
test('"getStyleElement" produces styles that are a function of rendering "element"', () => {
const getApplicationStyles = appName => {
const { element, getStyleElement } = AppRegistry.getApplication(appName, {});
render(element);
return getStyleElement().props.dangerouslySetInnerHTML.__html;
};
// First render "RootComponent"
AppRegistry.registerComponent('App', () => RootComponent);
const first = getApplicationStyles('App');
expect(first).toMatchSnapshot('CSS for an unstyled app');
// Second render "AlternativeComponent"
AppRegistry.registerComponent('AlternativeApp', () => AlternativeComponent);
const second = getApplicationStyles('AlternativeApp');
const diff = second.split(first)[1];
expect(first).not.toEqual(second);
expect(diff).toMatchSnapshot('Additional CSS for styled app');
// Third render "RootComponent" again
const third = getApplicationStyles('App');
expect(first).toEqual(third);
});
});
describe('runApplication', () => {
test('callback after render', () => {
// setup
const rootTag = document.createElement('div');
rootTag.id = 'react-root';
document.body.appendChild(rootTag);
const callback = jest.fn();
AppRegistry.registerComponent('App', () => RootComponent);
AppRegistry.runApplication('App', { initialProps: {}, rootTag, callback });
expect(callback).toHaveBeenCalledTimes(1);
// cleanup
document.body.removeChild(rootTag);
});
});
});

View File

@@ -1,61 +0,0 @@
/* eslint-env jasmine, jest */
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import { getApplication } from '../renderApplication';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { render } from 'enzyme';
import StyleSheet from '../../StyleSheet';
import View from '../../View';
const RootComponent = () => <div />;
describe('AppRegistry/renderApplication', () => {
describe('getApplication', () => {
const canUseDOM = ExecutionEnvironment.canUseDOM;
beforeEach(() => {
ExecutionEnvironment.canUseDOM = false;
});
afterEach(() => {
ExecutionEnvironment.canUseDOM = canUseDOM;
});
test('returns "element" and "getStyleElement"', () => {
const { element, getStyleElement } = getApplication(RootComponent, {});
expect(element).toMatchSnapshot();
expect(ReactDOMServer.renderToStaticMarkup(getStyleElement())).toMatchSnapshot();
});
test('"getStyleElement" produces styles that are a function of rendering "element"', () => {
const getTextContent = getStyleElement =>
getStyleElement().props.dangerouslySetInnerHTML.__html;
// First "RootComponent" render
let app = getApplication(RootComponent, {});
render(app.element);
const first = getTextContent(app.getStyleElement);
// Next render is a different tree; the style sheet should be different
const styles = StyleSheet.create({ root: { borderWidth: 1234, backgroundColor: 'purple' } });
app = getApplication(() => <View style={styles.root} />, {});
render(app.element);
const second = getTextContent(app.getStyleElement);
const diff = second.split(first)[1];
expect(first).toMatchSnapshot('CSS for an unstyled app');
expect(diff).toMatchSnapshot('Additional CSS for styled app');
expect(first).not.toEqual(second);
// Final render is once again "RootComponent"; the style sheet should not
// be polluted by earlier rendering of a different tree
app = getApplication(RootComponent, {});
render(app.element);
const third = getTextContent(app.getStyleElement);
expect(first).toEqual(third);
});
});
});

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule AppRegistry
* @flow
*/
@@ -19,6 +17,15 @@ const emptyObject = {};
const runnables = {};
export type ComponentProvider = () => ComponentType<any>;
export type ComponentProviderInstrumentationHook = (
component: ComponentProvider
) => ComponentType<any>;
export type WrapperComponentProvider = any => ComponentType<*>;
let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = (
component: ComponentProvider
) => component();
let wrapperComponentProvider: ?WrapperComponentProvider;
export type AppConfig = {
appKey: string,
@@ -45,12 +52,22 @@ export default class AppRegistry {
return runnables[appKey].getApplication(appParameters);
}
static registerComponent(appKey: string, getComponentFunc: ComponentProvider): string {
static registerComponent(appKey: string, componentProvider: ComponentProvider): string {
runnables[appKey] = {
getApplication: ({ initialProps } = emptyObject) =>
getApplication(getComponentFunc(), initialProps),
run: ({ initialProps = emptyObject, rootTag }) =>
renderApplication(getComponentFunc(), initialProps, rootTag)
getApplication: appParameters =>
getApplication(
componentProviderInstrumentationHook(componentProvider),
appParameters ? appParameters.initialProps : emptyObject,
wrapperComponentProvider && wrapperComponentProvider(appParameters)
),
run: appParameters =>
renderApplication(
componentProviderInstrumentationHook(componentProvider),
appParameters.initialProps || emptyObject,
appParameters.rootTag,
wrapperComponentProvider && wrapperComponentProvider(appParameters),
appParameters.callback
)
};
return appKey;
}
@@ -72,15 +89,15 @@ export default class AppRegistry {
return appKey;
}
static runApplication(appKey: string, appParameters?: Object): void {
static runApplication(appKey: string, appParameters: Object): void {
const isDevelopment = process.env.NODE_ENV !== 'production';
const params = { ...appParameters };
params.rootTag = `#${params.rootTag.id}`;
console.log(
`Running application "${appKey}" with appParams: ${JSON.stringify(params)}. ` +
`development-level warnings are ${isDevelopment ? 'ON' : 'OFF'}, ` +
`performance optimizations are ${isDevelopment ? 'OFF' : 'ON'}`
`Running application "${appKey}" with appParams: ${JSON.stringify(params)}.\n` +
`Development-level warnings: ${isDevelopment ? 'ON' : 'OFF'}.\n` +
`Performance optimizations: ${isDevelopment ? 'OFF' : 'ON'}.`
);
invariant(
@@ -92,6 +109,14 @@ export default class AppRegistry {
runnables[appKey].run(appParameters);
}
static setComponentProviderInstrumentationHook(hook: ComponentProviderInstrumentationHook) {
componentProviderInstrumentationHook = hook;
}
static setWrapperComponentProvider(provider: WrapperComponentProvider) {
wrapperComponentProvider = provider;
}
static unmountApplicationComponentAtRootTag(rootTag: Object) {
unmountComponentAtNode(rootTag);
}

View File

@@ -1,9 +1,8 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
@@ -21,28 +20,37 @@ const renderFn = process.env.NODE_ENV !== 'production' ? render : hydrate;
export default function renderApplication<Props: Object>(
RootComponent: ComponentType<Props>,
initialProps: Props,
rootTag: any
rootTag: any,
WrapperComponent?: ?ComponentType<*>,
callback?: () => void
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
renderFn(
<AppContainer rootTag={rootTag}>
<AppContainer WrapperComponent={WrapperComponent} rootTag={rootTag}>
<RootComponent {...initialProps} />
</AppContainer>,
rootTag
rootTag,
callback
);
}
export function getApplication(RootComponent: ComponentType<Object>, initialProps: Object): Object {
export function getApplication(
RootComponent: ComponentType<Object>,
initialProps: Object,
WrapperComponent?: ?ComponentType<*>
): Object {
const element = (
<AppContainer rootTag={{}}>
<AppContainer WrapperComponent={WrapperComponent} rootTag={{}}>
<RootComponent {...initialProps} />
</AppContainer>
);
// Don't escape CSS text
const getStyleElement = () => {
const getStyleElement = props => {
const sheet = styleResolver.getStyleSheet();
return <style dangerouslySetInnerHTML={{ __html: sheet.textContent }} id={sheet.id} />;
return (
<style {...props} dangerouslySetInnerHTML={{ __html: sheet.textContent }} id={sheet.id} />
);
};
return { element, getStyleElement };
}

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule AppState
* @noflow
*/

View File

@@ -159,7 +159,7 @@ describe('apis/AsyncStorage', () => {
});
describe('multiSet', () => {
const assertResult = result => {
const assertResult = () => {
expect(mockLocalStorage.getItem('UID123')).toEqual(JSON.stringify(uid123Object));
expect(mockLocalStorage.getItem('UID124')).toEqual(JSON.stringify(uid124Object));
};
@@ -206,7 +206,7 @@ describe('apis/AsyncStorage', () => {
});
describe('multiMerge', () => {
const assertResult = result => {
const assertResult = () => {
expect(JSON.parse(mockLocalStorage.getItem('UID123'))).toMatchSnapshot();
expect(JSON.parse(mockLocalStorage.getItem('UID124'))).toMatchSnapshot();
};
@@ -253,7 +253,7 @@ describe('apis/AsyncStorage', () => {
});
describe('multiRemove', () => {
const assertResult = result => {
const assertResult = () => {
expect(mockLocalStorage.getItem('UID123')).toBeUndefined();
expect(mockLocalStorage.getItem('UID124')).toBeUndefined();
};

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule AsyncStorage
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule BackHandler
* @flow
*/

View File

@@ -1,31 +1,32 @@
/* eslint-env jasmine, jest */
/* eslint-disable react/jsx-no-bind */
import React from 'react';
import Button from '..';
import { mount, shallow } from 'enzyme';
const findNativeButton = wrapper => wrapper.getDOMNode();
import React from 'react';
import StyleSheet from '../../StyleSheet';
import TouchableOpacity from '../../TouchableOpacity';
import { render, shallow } from 'enzyme';
describe('components/Button', () => {
test('prop "color"', () => {
const onPress = () => {};
const color = 'blue';
const button = findNativeButton(mount(<Button color={color} onPress={onPress} title="" />));
expect(button.style.backgroundColor).toEqual(color);
const button = shallow(<Button color={color} onPress={onPress} title="" />);
const style = StyleSheet.flatten(button.prop('style'));
expect(style.backgroundColor).toEqual(color);
});
test('prop "onPress"', () => {
const onPress = jest.fn();
const component = shallow(<Button onPress={onPress} title="" />);
component.simulate('press');
component.find(TouchableOpacity).simulate('press');
expect(onPress).toHaveBeenCalled();
});
test('prop "title"', () => {
const onPress = () => {};
const text = 'Click me';
const component = mount(<Button onPress={onPress} title={text} />);
const component = render(<Button onPress={onPress} title={text} />);
expect(component.text()).toEqual(text);
});
});

View File

@@ -1,12 +1,9 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Button
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule CheckBox
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Clipboard
* @flow
*/

View File

@@ -1,12 +1,9 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ColorPropType
* @noflow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Dimensions
* @flow
*/

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow

View File

@@ -1,12 +1,9 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EdgeInsetsPropType
* @flow
*/

View File

@@ -2,44 +2,117 @@
import I18nManager from '..';
const getDocumentDir = () => document.documentElement.getAttribute('dir');
describe('apis/I18nManager', () => {
describe('when RTL not enabled', () => {
describe('preferred language is LTR', () => {
beforeEach(() => {
I18nManager.setPreferredLanguageRTL(false);
});
test('is "false" by default', () => {
expect(I18nManager.isRTL).toEqual(false);
expect(document.documentElement.getAttribute('dir')).toEqual('ltr');
describe('isRTL', () => {
test('is false', () => {
expect(I18nManager.isRTL).toBe(false);
expect(getDocumentDir()).toEqual('ltr');
});
});
test('is "true" when forced', () => {
I18nManager.forceRTL(true);
expect(I18nManager.isRTL).toEqual(true);
expect(document.documentElement.getAttribute('dir')).toEqual('rtl');
I18nManager.forceRTL(false);
describe('forceRTL', () => {
afterEach(() => {
I18nManager.forceRTL(false);
});
test('when set to false, "isRTL" is false', () => {
I18nManager.forceRTL(false);
expect(I18nManager.isRTL).toBe(false);
expect(getDocumentDir()).toEqual('ltr');
});
test('when set to true, "isRTL" is true', () => {
I18nManager.forceRTL(true);
expect(I18nManager.isRTL).toBe(true);
expect(getDocumentDir()).toEqual('rtl');
});
});
describe('swapLeftAndRightInRTL', () => {
afterEach(() => {
I18nManager.swapLeftAndRightInRTL(true);
});
test('when set to false, "doLeftAndRightSwapInRTL" is false', () => {
I18nManager.swapLeftAndRightInRTL(false);
expect(I18nManager.doLeftAndRightSwapInRTL).toBe(false);
});
test('when set to true, "doLeftAndRightSwapInRTL" is true', () => {
I18nManager.swapLeftAndRightInRTL(true);
expect(I18nManager.doLeftAndRightSwapInRTL).toBe(true);
});
});
});
describe('when RTL is enabled', () => {
describe('preferred language is RTL', () => {
beforeEach(() => {
I18nManager.setPreferredLanguageRTL(true);
});
afterEach(() => {
afterAll(() => {
I18nManager.setPreferredLanguageRTL(false);
});
test('is "true" by default', () => {
expect(I18nManager.isRTL).toEqual(true);
expect(document.documentElement.getAttribute('dir')).toEqual('rtl');
describe('isRTL', () => {
test('is true', () => {
expect(I18nManager.isRTL).toBe(true);
expect(getDocumentDir()).toEqual('rtl');
});
});
test('is "false" when not allowed', () => {
I18nManager.allowRTL(false);
expect(I18nManager.isRTL).toEqual(false);
expect(document.documentElement.getAttribute('dir')).toEqual('ltr');
I18nManager.allowRTL(true);
describe('allowRTL', () => {
afterEach(() => {
I18nManager.allowRTL(true);
});
test('when set to false, "isRTL" is false', () => {
I18nManager.allowRTL(false);
expect(I18nManager.isRTL).toBe(false);
expect(getDocumentDir()).toEqual('ltr');
});
test('when set to true, "isRTL" is true', () => {
I18nManager.allowRTL(true);
expect(I18nManager.isRTL).toBe(true);
expect(getDocumentDir()).toEqual('rtl');
});
});
describe('forceRTL', () => {
afterEach(() => {
I18nManager.forceRTL(false);
});
test('when set to false, "isRTL" is true', () => {
I18nManager.forceRTL(false);
expect(I18nManager.isRTL).toBe(true);
expect(getDocumentDir()).toEqual('rtl');
});
test('when set to true, "isRTL" is true', () => {
I18nManager.forceRTL(true);
expect(I18nManager.isRTL).toBe(true);
expect(getDocumentDir()).toEqual('rtl');
});
});
describe('swapLeftAndRightInRTL', () => {
afterEach(() => {
I18nManager.swapLeftAndRightInRTL(true);
});
test('when set to false, "doLeftAndRightSwapInRTL" is false', () => {
I18nManager.swapLeftAndRightInRTL(false);
expect(I18nManager.doLeftAndRightSwapInRTL).toBe(false);
});
test('when set to true, "doLeftAndRightSwapInRTL" is true', () => {
I18nManager.swapLeftAndRightInRTL(true);
expect(I18nManager.doLeftAndRightSwapInRTL).toBe(true);
});
});
});
});

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule I18nManager
* @flow
*/
@@ -14,11 +12,14 @@ import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
type I18nManagerStatus = {
allowRTL: (allowRTL: boolean) => void,
doLeftAndRightSwapInRTL: boolean,
forceRTL: (forceRTL: boolean) => void,
isRTL: boolean,
setPreferredLanguageRTL: (setRTL: boolean) => void,
isRTL: boolean
swapLeftAndRightInRTL: (flipStyles: boolean) => void
};
let doLeftAndRightSwapInRTL = true;
let isPreferredLanguageRTL = false;
let isRTLAllowed = true;
let isRTLForced = false;
@@ -30,7 +31,7 @@ const isRTL = () => {
return isRTLAllowed && isPreferredLanguageRTL;
};
const onChange = () => {
const onDirectionChange = () => {
if (ExecutionEnvironment.canUseDOM) {
if (document.documentElement && document.documentElement.setAttribute) {
document.documentElement.setAttribute('dir', isRTL() ? 'rtl' : 'ltr');
@@ -41,15 +42,21 @@ const onChange = () => {
const I18nManager: I18nManagerStatus = {
allowRTL(bool) {
isRTLAllowed = bool;
onChange();
onDirectionChange();
},
forceRTL(bool) {
isRTLForced = bool;
onChange();
onDirectionChange();
},
setPreferredLanguageRTL(bool) {
isPreferredLanguageRTL = bool;
onChange();
onDirectionChange();
},
swapLeftAndRightInRTL(bool) {
doLeftAndRightSwapInRTL = bool;
},
get doLeftAndRightSwapInRTL() {
return doLeftAndRightSwapInRTL;
},
get isRTL() {
return isRTL();

View File

@@ -2,16 +2,20 @@
* @flow
*/
import AnimationPropTypes from '../../modules/AnimationPropTypes';
import BorderPropTypes from '../../modules/BorderPropTypes';
import ColorPropType from '../ColorPropType';
import ImageResizeMode from './ImageResizeMode';
import InteractionPropTypes from '../../modules/InteractionPropTypes';
import LayoutPropTypes from '../../modules/LayoutPropTypes';
import ShadowPropTypes from '../../modules/ShadowPropTypes';
import TransformPropTypes from '../../modules/TransformPropTypes';
import { number, oneOf, string } from 'prop-types';
const ImageStylePropTypes = {
...AnimationPropTypes,
...BorderPropTypes,
...InteractionPropTypes,
...LayoutPropTypes,
...ShadowPropTypes,
...TransformPropTypes,
@@ -26,7 +30,8 @@ const ImageStylePropTypes = {
/**
* @platform web
*/
boxShadow: string
boxShadow: string,
filter: string
};
export default ImageStylePropTypes;

View File

@@ -180,6 +180,20 @@ describe('components/Image', () => {
.attr('src')
).toBe(uriTwo);
});
test('is correctly updated when missing in initial render', () => {
jest.useFakeTimers();
const uri = 'https://testing.com/img.jpg';
const component = mount(<Image />);
component.setProps({ source: { uri } });
jest.runOnlyPendingTimers();
expect(
component
.render()
.find('img')
.attr('src')
).toBe(uri);
});
});
describe('prop "style"', () => {

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Image
* @flow
*/
@@ -57,7 +55,7 @@ const resolveAssetDimensions = source => {
}
};
const svgDataUriPattern = /^data:image\/svg\+xml;/;
const svgDataUriPattern = /^(data:image\/svg\+xml;utf8,)(.*)/;
const resolveAssetSource = source => {
let uri;
if (typeof source === 'number') {
@@ -72,12 +70,12 @@ const resolveAssetSource = source => {
uri = source || '';
}
// SVG data may contain characters (e.g., #, ") that need to be escaped
if (svgDataUriPattern.test(uri)) {
const parts = uri.split('<svg');
const [prefix, ...svgFragment] = parts;
const svg = encodeURIComponent(`<svg${svgFragment.join('<svg')}`);
return `${prefix}${svg}`;
const match = uri.match(svgDataUriPattern);
// inline SVG markup may contain characters (e.g., #, ") that need to be escaped
if (match) {
const [, prefix, svg] = match;
const encodedSvg = encodeURIComponent(svg);
return `${prefix}${encodedSvg}`;
}
return uri;
@@ -168,8 +166,8 @@ class Image extends Component<*, State> {
if (uri !== nextUri) {
ImageUriCache.remove(uri);
const isPreviouslyLoaded = ImageUriCache.has(nextUri);
isPreviouslyLoaded && ImageUriCache.add(uri);
this._updateImageState(getImageState(uri, isPreviouslyLoaded));
isPreviouslyLoaded && ImageUriCache.add(nextUri);
this._updateImageState(getImageState(nextUri, isPreviouslyLoaded));
}
}

View File

@@ -1,10 +1,8 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule InteractionManager
* @flow
*/
@@ -21,9 +19,18 @@ const InteractionManager = {
/**
* Schedule a function to run after all interactions have completed.
*/
runAfterInteractions(callback: Function) {
invariant(typeof callback === 'function', 'Must specify a function to schedule.');
callback();
runAfterInteractions(task: ?Function): { then: Function, done: Function, cancel: Function } {
console.warn('InteractionManager is not supported on web');
const promise = new Promise(resolve => {
if (task) {
resolve(task());
}
});
return {
then: promise.then.bind(promise),
done: () => {},
cancel: () => {}
};
},
/**

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Keyboard
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule KeyboardAvoidingView
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Linking
* @flow
*/
@@ -25,7 +23,7 @@ const Linking = {
},
openURL(url: string): Promise<Object | void> {
try {
iframeOpen(url);
open(url);
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
@@ -33,36 +31,16 @@ const Linking = {
}
};
/**
* Tabs opened using JavaScript may redirect the parent tab using
* `window.opener.location`, ignoring cross-origin restrictions and enabling
* phishing attacks.
*
* Safari requires that we open the url by injecting a hidden iframe that calls
* window.open(), then removes the iframe from the DOM.
*
* https://mathiasbynens.github.io/rel-noopener/
*/
const iframeOpen = url => {
const noOpener = url.indexOf('mailto:') !== 0;
const open = url => {
const anchor = document.createElement('a');
anchor.target = '_blank'; // :(
anchor.rel = 'noopener';
anchor.href = url;
const body = document.body;
if (body) {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
body.appendChild(iframe);
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const iframeBody = iframeDoc.body;
if (iframeBody) {
const script = iframeDoc.createElement('script');
const openerExpression = noOpener ? 'child.opener = null' : '';
script.text = `
window.parent = null; window.top = null; window.frameElement = null;
var child = window.open("${url}"); ${openerExpression};
`;
iframeBody.appendChild(script);
}
body.removeChild(iframe);
body.appendChild(anchor);
anchor.click();
body.removeChild(anchor);
}
};

View File

@@ -23,7 +23,6 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @providesModule ListViewDataSource
* @typechecks
* @flow
*/

View File

@@ -1,5 +0,0 @@
/* eslint-env jasmine, jest */
describe('components/ListView', () => {
test('NO TEST COVERAGE');
});

View File

@@ -37,6 +37,15 @@ describe('apis/NetInfo', () => {
} catch (e) {}
});
describe('fetch', () => {
test('returns a boolean', done => {
NetInfo.isConnected.fetch().then(isConnected => {
expect(isConnected).toBe(true);
done();
});
});
});
describe('addEventListener', () => {
test('throws if the provided "eventType" is not supported', () => {
expect(() => NetInfo.isConnected.addEventListener('foo', handler)).toThrow();

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule NetInfo
* @flow
*/
@@ -157,11 +155,6 @@ const NetInfo = {
},
fetch(): Promise<boolean> {
console.warn('`fetch` is deprecated. Use `getConnectionInfo` instead.');
return NetInfo.isConnected.getConnectionInfo();
},
getConnectionInfo(): Promise<boolean> {
return new Promise((resolve, reject) => {
try {
resolve(window.navigator.onLine);

View File

@@ -19,7 +19,8 @@ export default class PickerItem extends Component<Props> {
};
render() {
const { label, testID, value } = this.props;
return createElement('option', { testID, value }, label);
const { color, label, testID, value } = this.props;
const style = { color };
return createElement('option', { style, testID, value }, label);
}
}

View File

@@ -1,9 +1,8 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow

View File

@@ -1,9 +1,8 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow

View File

@@ -10,7 +10,8 @@ exports[`components/Picker prop "children" items 1`] = `
exports[`components/Picker prop "children" renders items 1`] = `
<select
className="rn-fontFamily-poiln3 rn-fontSize-7cikom rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw"
className="rn-fontFamily-14xgk7a rn-fontSize-7cikom rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw"
data-focusable={true}
onChange={[Function]}
>
<PickerItem

View File

@@ -33,7 +33,7 @@ describe('components/Picker', () => {
</Picker>
);
const component = shallow(picker);
expect(component.find('select').props().disabled).toBe(true);
expect(component.find('select').prop('disabled')).toBe(true);
});
});

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Picker
* @flow
*/
@@ -24,7 +22,7 @@ import { arrayOf, bool, func, number, oneOfType, string } from 'prop-types';
const pickerStyleType = StyleSheetPropType(PickerStylePropTypes);
type Props = {
children?: Array<typeof PickerItem>,
children?: PickerItem | Array<typeof PickerItem>,
enabled?: boolean,
onValueChange?: Function,
selectedValue?: number | string,
@@ -38,7 +36,7 @@ type Props = {
class Picker extends Component<Props> {
static propTypes = {
children: arrayOf(PickerItemPropType),
children: oneOfType([PickerItemPropType, arrayOf(PickerItemPropType)]),
enabled: bool,
onValueChange: func,
selectedValue: oneOfType([number, string]),
@@ -83,7 +81,7 @@ class Picker extends Component<Props> {
const styles = StyleSheet.create({
initial: {
fontFamily: 'inherit',
fontFamily: 'System',
fontSize: 'inherit',
margin: 0
}

View File

@@ -1,5 +0,0 @@
/* eslint-env jasmine, jest */
describe('apis/PixelRatio', () => {
test.skip('NO TEST COVERAGE', () => {});
});

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule PixelRatio
* @flow
*/

View File

@@ -0,0 +1,17 @@
/* eslint-env jasmine, jest */
import Platform from '../';
describe('apis/Platform', () => {
describe('select', () => {
test('supports "default"', () => {
expect(Platform.select({ default: 'default' })).toEqual('default');
});
test('chooses "web"', () => {
expect(
Platform.select({ android: 'android', ios: 'ios', web: 'web', default: 'default' })
).toEqual('web');
});
});
});

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Platform
* @flow
*/

View File

@@ -1,12 +1,9 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule PointPropType
* @flow
*/

View File

@@ -1,11 +1,9 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ProgressBar
* @flow
*/

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule RefreshControl
* @flow
*/

View File

@@ -1,14 +1,37 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule SafeAreaView
* @flow
*/
import React from 'react';
import StyleSheet from '../StyleSheet';
import View from '../View';
export default View;
import ViewPropTypes, { type ViewProps } from '../ViewPropTypes';
class SafeAreaView extends React.Component<ViewProps> {
static displayName = 'SafeAreaView';
static propTypes = {
...ViewPropTypes
};
render() {
const { style, ...rest } = this.props;
return <View {...rest} style={StyleSheet.compose(styles.root, style)} />;
}
}
const styles = StyleSheet.create({
root: {
paddingTop: 'env(safe-area-inset-top)',
paddingRight: 'env(safe-area-inset-right)',
paddingBottom: 'env(safe-area-inset-bottom)',
paddingLeft: 'env(safe-area-inset-left)'
}
});
export default SafeAreaView;

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ScrollView
* @noflow
*/

View File

@@ -1,11 +1,9 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule StatusBar
* @flow
*/

View File

@@ -1,14 +1,15 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
*/
/**
* WARNING: changes to this file in particular can cause significant changes to
* the results of render performance benchmarks.
*
* @noflow
*/
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
@@ -24,8 +25,8 @@ const emptyObject = {};
export default class ReactNativeStyleResolver {
_init() {
this.cache = { ltr: {}, rtl: {} };
this.injectedCache = { ltr: {}, rtl: {} };
this.cache = { ltr: {}, rtl: {}, rtlNoSwap: {} };
this.injectedCache = { ltr: {}, rtl: {}, rtlNoSwap: {} };
this.styleSheetManager = new StyleSheetManager();
}
@@ -43,7 +44,8 @@ export default class ReactNativeStyleResolver {
}
_injectRegisteredStyle(id) {
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
const { doLeftAndRightSwapInRTL, isRTL } = I18nManager;
const dir = isRTL ? (doLeftAndRightSwapInRTL ? 'rtl' : 'rtlNoSwap') : 'ltr';
if (!this.injectedCache[dir][id]) {
const style = flattenStyle(id);
const domStyle = createReactDOMStyle(i18nStyle(style));
@@ -120,7 +122,7 @@ export default class ReactNativeStyleResolver {
// Create next DOM style props from current and next RN styles
const { classList: rdomClassListNext, style: rdomStyleNext } = this.resolve([
I18nManager.isRTL ? i18nStyle(rnStyle) : rnStyle,
i18nStyle(rnStyle),
rnStyleNext
]);
@@ -196,7 +198,8 @@ export default class ReactNativeStyleResolver {
*/
_resolveStyleIfNeeded(style, key) {
if (key) {
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
const { doLeftAndRightSwapInRTL, isRTL } = I18nManager;
const dir = isRTL ? (doLeftAndRightSwapInRTL ? 'rtl' : 'rtlNoSwap') : 'ltr';
if (!this.cache[dir][key]) {
// slow: convert style object to props and cache
this.cache[dir][key] = this._resolveStyle(style);

View File

@@ -1,11 +1,9 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule StyleSheet
* @noflow
*/

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
@@ -70,10 +69,6 @@ export default class StyleSheetManager {
return className;
}
injectKeyframe(): string {
// return identifier;
}
_addToCache(className, prop, value) {
const cache = this._cache;
if (!cache.byProp[prop]) {

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule StyleSheetValidation
* @flow
*/
@@ -26,6 +24,8 @@ const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
export default class StyleSheetValidation {
static validateStyleProp(prop: string, style: Object, caller: string) {
if (process.env.NODE_ENV !== 'production') {
const value = style[prop];
const isCustomProperty = prop.indexOf('--') === 0;
if (isCustomProperty) return;
@@ -35,6 +35,12 @@ export default class StyleSheetValidation {
'\nValid style props: ' +
JSON.stringify(Object.keys(allStylePropTypes).sort(), null, ' ');
styleError(message1, style, caller, message2);
} else if (typeof value === 'string' && value.indexOf('!important') > -1) {
styleError(
`Invalid value of "${value}" set on prop "${prop}". Values cannot include "!important"`,
style,
caller
);
} else {
const error = allStylePropTypes[prop](
style,
@@ -92,11 +98,11 @@ StyleSheetValidation.addValidStylePropTypes({
clear: string,
cursor: string,
fill: string,
float: oneOf(['left', 'none', 'right']),
float: oneOf(['end', 'left', 'none', 'right', 'start']),
listStyle: string,
pointerEvents: string,
tableLayout: string,
/* @private */
MozAppearance: string,
font: string
WebkitAppearance: string
});

View File

@@ -1,14 +1,14 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import modality from './modality';
export default class WebStyleSheet {
_cssRules = [];
@@ -30,6 +30,7 @@ export default class WebStyleSheet {
}
if (domStyleElement) {
modality(domStyleElement);
// $FlowFixMe
this._sheet = domStyleElement.sheet;
this._textContent = domStyleElement.textContent;

View File

@@ -42,14 +42,22 @@ describe('StyleSheet/ReactNativeStyleResolver', () => {
testResolve(a, b, c);
});
test('with register before RTL, resolves to className', () => {
test('with register before RTL, resolves to correct className', () => {
const a = ReactNativePropRegistry.register({ left: '12.34%' });
const b = ReactNativePropRegistry.register({ textAlign: 'left' });
const c = ReactNativePropRegistry.register({ marginLeft: 10 });
I18nManager.forceRTL(true);
const resolved = styleResolver.resolve([a, b, c]);
const resolved1 = styleResolver.resolve([a, b, c]);
expect(resolved1).toMatchSnapshot();
I18nManager.swapLeftAndRightInRTL(false);
const resolved2 = styleResolver.resolve([a, b, c]);
expect(resolved2).toMatchSnapshot();
I18nManager.swapLeftAndRightInRTL(true);
I18nManager.forceRTL(false);
expect(resolved).toMatchSnapshot();
});
test('with register, resolves to mixed', () => {
@@ -102,7 +110,7 @@ describe('StyleSheet/ReactNativeStyleResolver', () => {
expect(resolved).toMatchSnapshot();
});
test('when RTL=true, resolves to flipped inline styles', () => {
test('when isRTL=true, resolves to flipped inline styles', () => {
// note: DOM state resolved from { marginLeft: 5, left: 5 } in RTL mode
node.style.cssText = 'margin-right: 5px; right: 5px;';
I18nManager.forceRTL(true);
@@ -111,8 +119,8 @@ describe('StyleSheet/ReactNativeStyleResolver', () => {
expect(resolved).toMatchSnapshot();
});
test('when RTL=true, resolves to flipped classNames', () => {
// note: DOM state resolved from { marginLeft: 5, left: 5 } in RTL mode
test('when isRTL=true, resolves to flipped classNames', () => {
// note: DOM state resolved from { marginLeft: 5, left: 5 }
node.style.cssText = 'margin-right: 5px; right: 5px;';
const nextStyle = ReactNativePropRegistry.register({ marginLeft: 10, right: 1 });
@@ -121,5 +129,19 @@ describe('StyleSheet/ReactNativeStyleResolver', () => {
I18nManager.forceRTL(false);
expect(resolved).toMatchSnapshot();
});
test('when isRTL=true & doLeftAndRightSwapInRTL=false, resolves to non-flipped inline styles', () => {
// note: DOM state resolved from { marginRight 5, right: 5, paddingEnd: 5 }
node.style.cssText = 'margin-right: 5px; right: 5px; padding-left: 5px';
I18nManager.forceRTL(true);
I18nManager.swapLeftAndRightInRTL(false);
const resolved = styleResolver.resolveWithNode(
{ marginRight: 10, right: 10, paddingEnd: 10 },
node
);
I18nManager.forceRTL(false);
I18nManager.swapLeftAndRightInRTL(true);
expect(resolved).toMatchSnapshot();
});
});
});

View File

@@ -9,7 +9,7 @@ Object {
}
`;
exports[`StyleSheet/ReactNativeStyleResolver resolve with register before RTL, resolves to className 1`] = `
exports[`StyleSheet/ReactNativeStyleResolver resolve with register before RTL, resolves to correct className 1`] = `
Object {
"classList": Array [
"rn-marginRight-zso239",
@@ -20,6 +20,17 @@ Object {
}
`;
exports[`StyleSheet/ReactNativeStyleResolver resolve with register before RTL, resolves to correct className 2`] = `
Object {
"classList": Array [
"rn-left-2s0hu9",
"rn-marginLeft-1n0xq6e",
"rn-textAlign-fdjqy7",
],
"className": "rn-left-2s0hu9 rn-marginLeft-1n0xq6e rn-textAlign-fdjqy7",
}
`;
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to className 1`] = `
Object {
"classList": Array [
@@ -246,7 +257,18 @@ Object {
}
`;
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode when RTL=true, resolves to flipped classNames 1`] = `
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode when isRTL=true & doLeftAndRightSwapInRTL=false, resolves to non-flipped inline styles 1`] = `
Object {
"className": "",
"style": Object {
"marginRight": "10px",
"paddingLeft": "10px",
"right": "10px",
},
}
`;
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode when isRTL=true, resolves to flipped classNames 1`] = `
Object {
"className": "rn-left-1u10d71 rn-marginRight-zso239",
"style": Object {
@@ -256,7 +278,7 @@ Object {
}
`;
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode when RTL=true, resolves to flipped inline styles 1`] = `
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode when isRTL=true, resolves to flipped inline styles 1`] = `
Object {
"className": "",
"style": Object {

View File

@@ -1,12 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`StyleSheet/createReactDOMStyle fontFamily fontFamily: "System" 1`] = `
exports[`StyleSheet/createReactDOMStyle fontFamily "Noto, System" 1`] = `
Object {
"fontFamily": "-apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Ubuntu, \\"Helvetica Neue\\", sans-serif",
"fontFamily": "Noto, system-ui, -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Ubuntu, \\"Helvetica Neue\\", sans-serif",
}
`;
exports[`StyleSheet/createReactDOMStyle fontFamily fontFamily: "monospace" 1`] = `
exports[`StyleSheet/createReactDOMStyle fontFamily "System" 1`] = `
Object {
"fontFamily": "system-ui, -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Ubuntu, \\"Helvetica Neue\\", sans-serif",
}
`;
exports[`StyleSheet/createReactDOMStyle fontFamily "monospace" 1`] = `
Object {
"fontFamily": "monospace, monospace",
}

View File

@@ -1,53 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`StyleSheet/i18nStyle LTR mode does not auto-flip 1`] = `
Object {
"borderBottomLeftRadius": 20,
"borderBottomRightRadius": "2rem",
"borderLeftColor": "red",
"borderLeftStyle": "solid",
"borderLeftWidth": 5,
"borderRightColor": "blue",
"borderRightStyle": "dotted",
"borderRightWidth": 6,
"borderTopLeftRadius": 10,
"borderTopRightRadius": "1rem",
"left": 1,
"marginLeft": 7,
"marginRight": 8,
"paddingLeft": 9,
"paddingRight": 10,
"right": 2,
"textAlign": "left",
"textShadowOffset": Object {
"height": 10,
"width": "1rem",
},
}
`;
exports[`StyleSheet/i18nStyle RTL mode does auto-flip 1`] = `
Object {
"borderBottomLeftRadius": "2rem",
"borderBottomRightRadius": 20,
"borderLeftColor": "blue",
"borderLeftStyle": "dotted",
"borderLeftWidth": 6,
"borderRightColor": "red",
"borderRightStyle": "solid",
"borderRightWidth": 5,
"borderTopLeftRadius": "1rem",
"borderTopRightRadius": 10,
"left": 2,
"marginLeft": 8,
"marginRight": 7,
"paddingLeft": 10,
"paddingRight": 9,
"right": 1,
"textAlign": "right",
"textShadowOffset": Object {
"height": 10,
"width": "-1rem",
},
}
`;

View File

@@ -22,6 +22,23 @@ describe('StyleSheet/createReactDOMStyle', () => {
expect(firstStyle).toEqual(secondStyle);
});
test('shortform -> longform', () => {
const style = {
borderStyle: 'solid',
boxSizing: 'border-box',
borderBottomColor: 'white',
borderBottomWidth: 1,
borderWidth: 0,
marginTop: 50,
marginVertical: 25,
margin: 10,
overflow: 'hidden',
overscrollBehavior: 'contain'
};
expect(createReactDOMStyle(style)).toMatchSnapshot();
});
describe('borderWidth styles', () => {
test('defaults to 0 when "null"', () => {
expect(createReactDOMStyle({ borderWidth: null })).toEqual({
@@ -43,44 +60,44 @@ describe('StyleSheet/createReactDOMStyle', () => {
test('flex defaults', () => {
expect(createReactDOMStyle({ display: 'flex' })).toEqual({
display: 'flex',
flexShrink: '0 !important',
flexBasis: 'auto !important'
flexShrink: 0,
flexBasis: 'auto'
});
});
test('flex: -1', () => {
expect(createReactDOMStyle({ display: 'flex', flex: -1 })).toEqual({
display: 'flex',
flexGrow: '0 !important',
flexShrink: '1 !important',
flexBasis: 'auto !important'
flexGrow: 0,
flexShrink: 1,
flexBasis: 'auto'
});
});
test('flex: 0', () => {
expect(createReactDOMStyle({ display: 'flex', flex: 0 })).toEqual({
display: 'flex',
flexGrow: '0 !important',
flexShrink: '0 !important',
flexBasis: 'auto !important'
flexGrow: 0,
flexShrink: 0,
flexBasis: '0%'
});
});
test('flex: 1', () => {
expect(createReactDOMStyle({ display: 'flex', flex: 1 })).toEqual({
display: 'flex',
flex: 1,
flexGrow: '1 !important',
flexShrink: '1 !important'
flexGrow: 1,
flexShrink: 1,
flexBasis: '0%'
});
});
test('flex: 10', () => {
expect(createReactDOMStyle({ display: 'flex', flex: 10 })).toEqual({
display: 'flex',
flex: 10,
flexGrow: '10 !important',
flexShrink: '1 !important'
flexGrow: 10,
flexShrink: 1,
flexBasis: '0%'
});
});
@@ -88,17 +105,16 @@ describe('StyleSheet/createReactDOMStyle', () => {
// is flex-basis applied?
expect(createReactDOMStyle({ display: 'flex', flexBasis: '25%' })).toEqual({
display: 'flex',
flexShrink: '0 !important',
flexBasis: '25% !important'
flexShrink: 0,
flexBasis: '25%'
});
// can flex-basis override the 'flex' expansion?
expect(createReactDOMStyle({ display: 'flex', flex: 1, flexBasis: '25%' })).toEqual({
display: 'flex',
flex: 1,
flexGrow: '1 !important',
flexShrink: '1 !important',
flexBasis: '25% !important'
flexGrow: 1,
flexShrink: 1,
flexBasis: '25%'
});
});
@@ -106,16 +122,16 @@ describe('StyleSheet/createReactDOMStyle', () => {
// is flex-shrink applied?
expect(createReactDOMStyle({ display: 'flex', flexShrink: 1 })).toEqual({
display: 'flex',
flexShrink: '1 !important',
flexBasis: 'auto !important'
flexShrink: 1,
flexBasis: 'auto'
});
// can flex-shrink override the 'flex' expansion?
expect(createReactDOMStyle({ display: 'flex', flex: 1, flexShrink: 2 })).toEqual({
display: 'flex',
flex: 1,
flexGrow: '1 !important',
flexShrink: '2 !important'
flexGrow: 1,
flexShrink: 2,
flexBasis: '0%'
});
});
});
@@ -125,30 +141,23 @@ describe('StyleSheet/createReactDOMStyle', () => {
expect(createReactDOMStyle({ fontFamily: 'Georgia, Times, serif' })).toMatchSnapshot();
});
test('fontFamily: "monospace"', () => {
test('"monospace"', () => {
expect(createReactDOMStyle({ fontFamily: 'monospace' })).toMatchSnapshot();
});
test('fontFamily: "System"', () => {
test('"System"', () => {
expect(createReactDOMStyle({ fontFamily: 'System' })).toMatchSnapshot();
});
test('"Noto, System"', () => {
expect(createReactDOMStyle({ fontFamily: 'Noto, System' })).toMatchSnapshot();
});
});
test('shortform -> longform', () => {
const style = {
borderStyle: 'solid',
boxSizing: 'border-box',
borderBottomColor: 'white',
borderBottomWidth: 1,
borderWidth: 0,
marginTop: 50,
marginVertical: 25,
margin: 10,
overflow: 'hidden',
overscrollBehavior: 'contain'
};
expect(createReactDOMStyle(style)).toMatchSnapshot();
test('fontVariant', () => {
expect(createReactDOMStyle({ fontVariant: ['common-ligatures', 'small-caps'] })).toEqual({
fontVariant: 'common-ligatures small-caps'
});
});
describe('shadow styles', () => {

View File

@@ -2,11 +2,9 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import flattenStyle from '../flattenStyle';

View File

@@ -3,29 +3,8 @@
import I18nManager from '../../I18nManager';
import i18nStyle from '../i18nStyle';
const style = {
borderLeftColor: 'red',
borderRightColor: 'blue',
borderTopLeftRadius: 10,
borderTopRightRadius: '1rem',
borderBottomLeftRadius: 20,
borderBottomRightRadius: '2rem',
borderLeftStyle: 'solid',
borderRightStyle: 'dotted',
borderLeftWidth: 5,
borderRightWidth: 6,
left: 1,
marginLeft: 7,
marginRight: 8,
paddingLeft: 9,
paddingRight: 10,
right: 2,
textAlign: 'left',
textShadowOffset: { width: '1rem', height: 10 }
};
describe('StyleSheet/i18nStyle', () => {
describe('LTR mode', () => {
describe('isRTL is false', () => {
beforeEach(() => {
I18nManager.allowRTL(false);
});
@@ -34,12 +13,73 @@ describe('StyleSheet/i18nStyle', () => {
I18nManager.allowRTL(true);
});
test('does not auto-flip', () => {
expect(i18nStyle(style)).toMatchSnapshot();
test('converts end/start properties', () => {
const initial = {
borderStartColor: 'red',
start: 1,
marginStart: 5,
paddingEnd: 10
};
const expected = {
borderLeftColor: 'red',
left: 1,
marginLeft: 5,
paddingRight: 10
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('converts end/start values', () => {
const initial = {
float: 'start',
textAlign: 'end'
};
const expected = {
float: 'left',
textAlign: 'right'
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('noop on left/right properties', () => {
const initial = {
paddingLeft: 0,
left: 0,
marginRight: 0,
paddingRight: 10
};
expect(i18nStyle(initial)).toEqual(initial);
});
test('noop on left/right values', () => {
const initial = {
clear: 'left',
float: 'left',
textAlign: 'right',
textShadowOffset: { width: '1rem', height: 10 }
};
expect(i18nStyle(initial)).toEqual(initial);
});
test('end/start properties take precedence', () => {
const initial = {
borderStartWidth: 10,
borderLeftWidth: 0,
end: 10,
right: 0,
marginStart: 10,
marginLeft: 0
};
const expected = {
borderLeftWidth: 10,
marginLeft: 10,
right: 10
};
expect(i18nStyle(initial)).toEqual(expected);
});
});
describe('RTL mode', () => {
describe('isRTL is true', () => {
beforeEach(() => {
I18nManager.forceRTL(true);
});
@@ -48,8 +88,156 @@ describe('StyleSheet/i18nStyle', () => {
I18nManager.forceRTL(false);
});
test('does auto-flip', () => {
expect(i18nStyle(style)).toMatchSnapshot();
describe('doLeftAndRightSwapInRTL is false', () => {
beforeEach(() => {
I18nManager.swapLeftAndRightInRTL(false);
});
afterEach(() => {
I18nManager.swapLeftAndRightInRTL(true);
});
test('converts end/start properties', () => {
const initial = {
borderStartColor: 'red',
start: 1,
marginStart: 5,
paddingEnd: 10
};
const expected = {
borderRightColor: 'red',
right: 1,
marginRight: 5,
paddingLeft: 10
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('converts end/start values', () => {
const initial = {
float: 'start',
textAlign: 'end'
};
const expected = {
float: 'right',
textAlign: 'left'
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('noop on left/right properties', () => {
const initial = {
paddingLeft: 0,
left: 0,
marginRight: 0,
paddingRight: 10
};
expect(i18nStyle(initial)).toEqual(initial);
});
test('noop on left/right values', () => {
const initial = {
clear: 'left',
float: 'left',
textAlign: 'right',
textShadowOffset: { width: '1rem', height: 10 }
};
expect(i18nStyle(initial)).toEqual(initial);
});
test('end/start properties take precedence', () => {
const style = {
borderStartWidth: 10,
borderRightWidth: 0,
end: 10,
left: 0,
marginStart: 10,
marginRight: 0
};
const expected = {
borderRightWidth: 10,
marginRight: 10,
left: 10
};
expect(i18nStyle(style)).toEqual(expected);
});
});
describe('doLeftAndRightSwapInRTL is true', () => {
test('converts end/start properties', () => {
const initial = {
borderStartColor: 'red',
start: 1,
marginStart: 5,
paddingEnd: 10
};
const expected = {
borderRightColor: 'red',
right: 1,
marginRight: 5,
paddingLeft: 10
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('converts end/start values', () => {
const initial = {
float: 'start',
textAlign: 'end'
};
const expected = {
float: 'right',
textAlign: 'left'
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('converts left/right properties', () => {
const initial = {
borderLeftColor: 'red',
left: 1,
marginLeft: 5,
paddingRight: 10
};
const expected = {
borderRightColor: 'red',
right: 1,
marginRight: 5,
paddingLeft: 10
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('converts left/right values', () => {
const initial = {
float: 'left',
textAlign: 'right',
textShadowOffset: { width: '1rem', height: 10 }
};
const expected = {
float: 'right',
textAlign: 'left',
textShadowOffset: { width: '-1rem', height: 10 }
};
expect(i18nStyle(initial)).toEqual(expected);
});
test('end/start properties take precedence', () => {
const style = {
borderStartWidth: 10,
borderLeftWidth: 0,
end: 10,
right: 0,
marginStart: 10,
marginLeft: 0
};
const expected = {
borderRightWidth: 10,
marginRight: 10,
left: 10
};
expect(i18nStyle(style)).toEqual(expected);
});
});
});
});

View File

@@ -1,10 +1,16 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
*/
import normalizeValue from './normalizeValue';
import processColor from '../processColor';
/**
* The browser implements the CSS cascade, where the order of properties is a
* factor in determining which styles to paint. React Native is different. It
* gives giving precedence to the more specific style property. For example,
@@ -13,13 +19,8 @@
* This module creates mutally exclusive style declarations by expanding all of
* React Native's supported shortform properties (e.g. `padding`) to their
* longfrom equivalents.
*
* @noflow
*/
import normalizeValue from './normalizeValue';
import processColor from '../processColor';
const emptyObject = {};
const styleShortFormProperties = {
borderColor: ['borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor'],
@@ -63,7 +64,7 @@ const borderWidthProps = {
const monospaceFontStack = 'monospace, monospace';
const systemFontStack =
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif';
'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif';
const alphaSortProps = propsArray =>
propsArray.sort((a, b) => {
@@ -185,10 +186,10 @@ const createReducer = (style, styleProps) => {
// set only if there is no otherwise supplied flex style.
if (style.display === 'flex' && style.flex == null) {
if (style.flexShrink == null) {
resolvedStyle.flexShrink = '0 !important';
resolvedStyle.flexShrink = 0;
}
if (style.flexBasis == null) {
resolvedStyle.flexBasis = 'auto !important';
resolvedStyle.flexBasis = 'auto';
}
}
break;
@@ -196,48 +197,28 @@ const createReducer = (style, styleProps) => {
// The 'flex' property value in React Native must be a positive integer,
// 0, or -1.
//
// On the web, a positive integer value for 'flex' is complicated by
// browser differences. Although browsers render styles like 'flex:2'
// consistently, they don't all set the same value for the resulting
// 'flexBasis' (See #616). Expanding 'flex' in 'StyleSheet' would mean
// setting different values for different browsers.
//
// This fix instead relies on the browser expanding 'flex' itself. And
// because the 'flex' style is not being expanded the generated CSS is
// likely to contain source order "conflicts". To avoid the browser
// relying on source order to resolve the styles, all the longhand flex
// property values must use '!important'.
case 'flex': {
if (value > 0) {
resolvedStyle.flex = value;
resolvedStyle.flexGrow = `${value} !important`;
resolvedStyle.flexShrink = '1 !important';
resolvedStyle.flexGrow = value;
resolvedStyle.flexShrink = 1;
resolvedStyle.flexBasis = '0%';
} else if (value === 0) {
resolvedStyle.flexGrow = '0 !important';
resolvedStyle.flexShrink = '0 !important';
resolvedStyle.flexBasis = 'auto !important';
resolvedStyle.flexGrow = 0;
resolvedStyle.flexShrink = 0;
resolvedStyle.flexBasis = '0%';
} else if (value === -1) {
resolvedStyle.flexGrow = '0 !important';
resolvedStyle.flexShrink = '1 !important';
resolvedStyle.flexBasis = 'auto !important';
}
break;
}
case 'flexGrow':
case 'flexShrink':
case 'flexBasis': {
if (value != null) {
const hasImportant = `${value}`.indexOf('!important') > -1;
resolvedStyle[prop] = hasImportant ? value : `${value} !important`;
resolvedStyle.flexGrow = 0;
resolvedStyle.flexShrink = 1;
resolvedStyle.flexBasis = 'auto';
}
break;
}
case 'fontFamily': {
if (value === 'System') {
resolvedStyle.fontFamily = systemFontStack;
if (value.indexOf('System') > -1) {
const stack = value.split(/\s*,\s*/);
stack[stack.indexOf('System')] = systemFontStack;
resolvedStyle.fontFamily = stack.join(', ');
} else if (value === 'monospace') {
resolvedStyle.fontFamily = monospaceFontStack;
} else {
@@ -246,6 +227,13 @@ const createReducer = (style, styleProps) => {
break;
}
case 'fontVariant': {
if (Array.isArray(value) && value.length > 0) {
resolvedStyle.fontVariant = value.join(' ');
}
break;
}
case 'shadowColor':
case 'shadowOffset':
case 'shadowOpacity':

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule flattenStyle
* @flow
*/

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
@@ -13,75 +12,119 @@ import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue';
const emptyObject = {};
/**
* Map of property names to their BiDi equivalent.
*/
const PROPERTIES_TO_SWAP = {
borderTopLeftRadius: 'borderTopRightRadius',
borderTopRightRadius: 'borderTopLeftRadius',
borderBottomLeftRadius: 'borderBottomRightRadius',
borderBottomRightRadius: 'borderBottomLeftRadius',
borderLeftColor: 'borderRightColor',
borderLeftStyle: 'borderRightStyle',
borderLeftWidth: 'borderRightWidth',
borderRightColor: 'borderLeftColor',
borderRightWidth: 'borderLeftWidth',
borderRightStyle: 'borderLeftStyle',
left: 'right',
marginLeft: 'marginRight',
marginRight: 'marginLeft',
paddingLeft: 'paddingRight',
paddingRight: 'paddingLeft',
right: 'left'
const borderTopLeftRadius = 'borderTopLeftRadius';
const borderTopRightRadius = 'borderTopRightRadius';
const borderBottomLeftRadius = 'borderBottomLeftRadius';
const borderBottomRightRadius = 'borderBottomRightRadius';
const borderLeftColor = 'borderLeftColor';
const borderLeftStyle = 'borderLeftStyle';
const borderLeftWidth = 'borderLeftWidth';
const borderRightColor = 'borderRightColor';
const borderRightStyle = 'borderRightStyle';
const borderRightWidth = 'borderRightWidth';
const right = 'right';
const marginLeft = 'marginLeft';
const marginRight = 'marginRight';
const paddingLeft = 'paddingLeft';
const paddingRight = 'paddingRight';
const left = 'left';
// Map of LTR property names to their BiDi equivalent.
const PROPERTIES_FLIP = {
borderTopLeftRadius: borderTopRightRadius,
borderTopRightRadius: borderTopLeftRadius,
borderBottomLeftRadius: borderBottomRightRadius,
borderBottomRightRadius: borderBottomLeftRadius,
borderLeftColor: borderRightColor,
borderLeftStyle: borderRightStyle,
borderLeftWidth: borderRightWidth,
borderRightColor: borderLeftColor,
borderRightStyle: borderLeftStyle,
borderRightWidth: borderLeftWidth,
left: right,
marginLeft: marginRight,
marginRight: marginLeft,
paddingLeft: paddingRight,
paddingRight: paddingLeft,
right: left
};
const PROPERTIES_SWAP_LEFT_RIGHT = {
// Map of I18N property names to their LTR equivalent.
const PROPERTIES_I18N = {
borderTopStartRadius: borderTopLeftRadius,
borderTopEndRadius: borderTopRightRadius,
borderBottomStartRadius: borderBottomLeftRadius,
borderBottomEndRadius: borderBottomRightRadius,
borderStartColor: borderLeftColor,
borderStartStyle: borderLeftStyle,
borderStartWidth: borderLeftWidth,
borderEndColor: borderRightColor,
borderEndStyle: borderRightStyle,
borderEndWidth: borderRightWidth,
end: right,
marginStart: marginLeft,
marginEnd: marginRight,
paddingStart: paddingLeft,
paddingEnd: paddingRight,
start: left
};
const PROPERTIES_VALUE = {
clear: true,
float: true,
textAlign: true
};
/**
* Invert the sign of a numeric-like value
*/
// Invert the sign of a numeric-like value
const additiveInverse = (value: String | Number) => multiplyStyleLengthValue(value, -1);
/**
* BiDi flip the given property.
*/
const flipProperty = (prop: String): String => {
return PROPERTIES_TO_SWAP.hasOwnProperty(prop) ? PROPERTIES_TO_SWAP[prop] : prop;
};
const swapLeftRight = (value: String): String => {
return value === 'left' ? 'right' : value === 'right' ? 'left' : value;
};
const i18nStyle = originalStyle => {
if (!I18nManager.isRTL) {
return originalStyle;
}
const { doLeftAndRightSwapInRTL, isRTL } = I18nManager;
const style = originalStyle || emptyObject;
const frozenProps = {};
const nextStyle = {};
for (const prop in style) {
if (!Object.prototype.hasOwnProperty.call(style, prop)) {
for (const originalProp in style) {
if (!Object.prototype.hasOwnProperty.call(style, originalProp)) {
continue;
}
const originalValue = style[originalProp];
let prop = originalProp;
let value = originalValue;
const value = style[prop];
// BiDi flip properties
if (PROPERTIES_I18N.hasOwnProperty(originalProp)) {
// convert start/end
const convertedProp = PROPERTIES_I18N[originalProp];
prop = isRTL ? PROPERTIES_FLIP[convertedProp] : convertedProp;
} else if (isRTL && doLeftAndRightSwapInRTL && PROPERTIES_FLIP[originalProp]) {
prop = PROPERTIES_FLIP[originalProp];
}
if (PROPERTIES_TO_SWAP[prop]) {
const newProp = flipProperty(prop);
nextStyle[newProp] = value;
} else if (PROPERTIES_SWAP_LEFT_RIGHT[prop]) {
nextStyle[prop] = swapLeftRight(value);
} else if (prop === 'textShadowOffset') {
// BiDi flip values
if (PROPERTIES_VALUE.hasOwnProperty(originalProp)) {
if (originalValue === 'start') {
value = isRTL ? 'right' : 'left';
} else if (originalValue === 'end') {
value = isRTL ? 'left' : 'right';
} else if (isRTL && doLeftAndRightSwapInRTL) {
if (originalValue === 'left') {
value = 'right';
} else if (originalValue === 'right') {
value = 'left';
}
}
}
if (isRTL && prop === 'textShadowOffset') {
nextStyle[prop] = value;
nextStyle[prop].width = additiveInverse(value.width);
} else {
nextStyle[prop] = style[prop];
} else if (!frozenProps[prop]) {
nextStyle[prop] = value;
}
if (PROPERTIES_I18N[originalProp]) {
frozenProps[prop] = true;
}
}

View File

@@ -1,9 +1,5 @@
import modality from '../../modules/modality';
import StyleSheet from './StyleSheet';
// initialize focus-ring fix
modality();
// allow component styles to be editable in React Dev Tools
if (process.env.NODE_ENV !== 'production') {
const { canUseDOM } = require('fbjs/lib/ExecutionEnvironment');

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow

View File

@@ -18,12 +18,14 @@
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
const modality = () => {
const rule = ':focus { outline: none; }';
let ruleExists = false;
const modality = styleElement => {
if (!canUseDOM) {
return;
}
let styleElement;
let hadKeyboardEvent = false;
let keyboardThrottleTimeoutID = 0;
@@ -55,21 +57,6 @@ const modality = () => {
'[role=textbox]'
].join(',');
/**
* Disable the focus ring by default
*/
const initialize = () => {
// check if the style sheet needs to be created
const id = 'react-native-modality';
styleElement = document.getElementById(id);
if (!styleElement) {
// removes focus styles by default
const style = `<style id="${id}">:focus { outline: none; }</style>`;
document.head.insertAdjacentHTML('afterbegin', style);
styleElement = document.getElementById(id);
}
};
/**
* Computes whether the given element should automatically trigger the
* `focus-ring`.
@@ -83,20 +70,22 @@ const modality = () => {
};
/**
* Add the focus ring to the focused element
* Add the focus ring style
*/
const addFocusRing = () => {
if (styleElement) {
styleElement.disabled = true;
if (styleElement && ruleExists) {
styleElement.sheet.deleteRule(0);
ruleExists = false;
}
};
/**
* Remove the focus ring
* Remove the focus ring style
*/
const removeFocusRing = () => {
if (styleElement) {
styleElement.disabled = false;
if (styleElement && !ruleExists) {
styleElement.sheet.insertRule(rule, 0);
ruleExists = true;
}
};
@@ -136,7 +125,7 @@ const modality = () => {
};
if (document.body && document.body.addEventListener) {
initialize();
removeFocusRing();
document.body.addEventListener('keydown', handleKeyDown, true);
document.body.addEventListener('focus', handleFocus, true);
document.body.addEventListener('blur', handleBlur, true);

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow

View File

@@ -1,11 +1,9 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Switch
* @flow
*/
@@ -136,7 +134,7 @@ class Switch extends Component<*> {
thumbStyle,
value && styles.thumbOn,
{
marginLeft: value ? multiplyStyleLengthValue(thumbWidth, -1) : 0
marginStart: value ? multiplyStyleLengthValue(thumbWidth, -1) : 0
}
]}
/>
@@ -192,12 +190,12 @@ const styles = StyleSheet.create({
alignSelf: 'flex-start',
borderRadius: '100%',
boxShadow: thumbDefaultBoxShadow,
left: '0%',
start: '0%',
transform: [{ translateZ: 0 }],
transitionDuration: '0.1s'
},
thumbOn: {
left: '100%'
start: '100%'
},
disabledThumb: {
backgroundColor: '#BDBDBD'

View File

@@ -1,12 +1,10 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule TextPropTypes
* @flow
*/
@@ -24,6 +22,9 @@ const TextPropTypes = {
children: any,
importantForAccessibility: oneOf(['auto', 'no', 'no-hide-descendants', 'yes']),
numberOfLines: number,
onBlur: func,
onContextMenu: func,
onFocus: func,
onLayout: func,
onPress: func,
selectable: bool,

View File

@@ -1,9 +1,8 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
@@ -11,14 +10,10 @@
import ColorPropType from '../ColorPropType';
import ViewStylePropTypes from '../View/ViewStylePropTypes';
import { number, oneOf, oneOfType, shape, string } from 'prop-types';
import { array, number, oneOf, oneOfType, shape, string } from 'prop-types';
const numberOrString = oneOfType([number, string]);
const ShadowOffsetPropType = shape({ width: number, height: number });
const TextAlignPropType = oneOf(['center', 'inherit', 'justify', 'justify-all', 'left', 'right']);
const WritingDirectionPropType = oneOf(['auto', 'ltr', 'rtl']);
const TextStylePropTypes = {
...ViewStylePropTypes,
color: ColorPropType,
@@ -27,17 +22,27 @@ const TextStylePropTypes = {
fontSize: numberOrString,
fontStyle: string,
fontWeight: string,
fontVariant: array,
letterSpacing: numberOrString,
lineHeight: numberOrString,
textAlign: TextAlignPropType,
textAlign: oneOf([
'center',
'end',
'inherit',
'justify',
'justify-all',
'left',
'right',
'start'
]),
textAlignVertical: string,
textDecorationColor: ColorPropType,
textDecorationLine: string,
textDecorationStyle: string,
textShadowColor: ColorPropType,
textShadowOffset: ShadowOffsetPropType,
textShadowOffset: shape({ width: number, height: number }),
textShadowRadius: number,
writingDirection: WritingDirectionPropType,
writingDirection: oneOf(['auto', 'ltr', 'rtl']),
/* @platform web */
textIndent: numberOrString,
textOverflow: string,

Some files were not shown because too many files have changed in this diff Show More