mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-03-30 23:23:35 +08:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83a8758f68 | ||
|
|
e022d166dd | ||
|
|
1a225bc449 | ||
|
|
cf2612663b | ||
|
|
1aec803086 | ||
|
|
2050730b77 | ||
|
|
a67bf0f490 | ||
|
|
4529a4ac0a | ||
|
|
5a04d07a35 | ||
|
|
9427eea293 | ||
|
|
b9803e1e07 | ||
|
|
7a3a9a5c3f | ||
|
|
4c59343fd3 | ||
|
|
ce89b7e3ec | ||
|
|
23fa663a6e | ||
|
|
b96dd668d3 | ||
|
|
a9cacb2ef5 | ||
|
|
c122814591 | ||
|
|
efe18f1b7e | ||
|
|
e1b576e427 | ||
|
|
5d77d6e30f | ||
|
|
8fb9a88ee6 | ||
|
|
a7cda988ef | ||
|
|
b239cfb04d | ||
|
|
8e94d858b2 | ||
|
|
aa22b06359 | ||
|
|
2aa565c7c3 | ||
|
|
7b9b57960d | ||
|
|
eae3ee9dca | ||
|
|
74e1a196b6 | ||
|
|
48da9814e7 | ||
|
|
4d391ef57c | ||
|
|
780df69a80 | ||
|
|
6c229da01f | ||
|
|
ae7aa818fb | ||
|
|
306cf67932 | ||
|
|
619c2048be | ||
|
|
b9f9a4f8d7 | ||
|
|
58bc18c2f5 | ||
|
|
073940fc4e | ||
|
|
5c462303de | ||
|
|
5fb92da317 | ||
|
|
cafe10d851 | ||
|
|
b28581f44e | ||
|
|
9333e7e887 | ||
|
|
b28cbbb37e | ||
|
|
a53372ceb3 | ||
|
|
239a43978f | ||
|
|
b4e4bfbb3c | ||
|
|
893963a799 | ||
|
|
e5adc5a37c | ||
|
|
6d908189a7 | ||
|
|
31db333ba3 | ||
|
|
9fe089ca21 | ||
|
|
a314d5b2e4 | ||
|
|
fb845ebf44 | ||
|
|
0d0c7e6e27 | ||
|
|
f37003a079 | ||
|
|
f1fc2a9e37 | ||
|
|
92794cdc9f | ||
|
|
b754776373 | ||
|
|
155b34e495 | ||
|
|
00c9dc4236 | ||
|
|
b66aba1a06 | ||
|
|
17f8a674b8 | ||
|
|
b8080ba775 | ||
|
|
7265736545 | ||
|
|
399f465e59 | ||
|
|
9ee89bc7f7 | ||
|
|
748b2d0f3f | ||
|
|
fb4635e013 | ||
|
|
73b459e770 | ||
|
|
a41af0f65f | ||
|
|
96eecc0da3 | ||
|
|
69d5373222 | ||
|
|
538ab88eda | ||
|
|
21b3f39c0b | ||
|
|
998e275e65 | ||
|
|
31d428a649 | ||
|
|
240cf7e05f | ||
|
|
2ad710d83a | ||
|
|
dcce72b66e | ||
|
|
083769d642 | ||
|
|
a53dba8c62 | ||
|
|
670d43ba04 | ||
|
|
73a731f2da | ||
|
|
1542f1f369 | ||
|
|
6f58d7abe7 | ||
|
|
7e0fbf9691 | ||
|
|
865034e8f7 | ||
|
|
6e96ee4f3c | ||
|
|
16d98b49f0 | ||
|
|
d04721c75a | ||
|
|
8512709251 | ||
|
|
efeaea70a9 | ||
|
|
a403244e67 | ||
|
|
985c1d63b6 | ||
|
|
9d8d4057f6 | ||
|
|
ec8843fe90 | ||
|
|
935970156c |
@@ -3,7 +3,6 @@
|
||||
|
||||
[ignore]
|
||||
<PROJECT_ROOT>/.*/__tests__/.*
|
||||
<PROJECT_ROOT>/packages/benchmarks/.*
|
||||
<PROJECT_ROOT>/packages/.*/dist/.*
|
||||
<PROJECT_ROOT>/website/.*
|
||||
.*/node_modules/babel-plugin-transform-react-remove-prop-types/*
|
||||
|
||||
10
.github/CONTRIBUTING.md
vendored
10
.github/CONTRIBUTING.md
vendored
@@ -85,10 +85,18 @@ yarn compile --watch
|
||||
|
||||
## Benchmarks
|
||||
|
||||
To run the performance benchmarks in a browser (opening `./packages/benchmarks/index.html`):
|
||||
To run the benchmarks locally:
|
||||
|
||||
```
|
||||
yarn benchmarks
|
||||
open ./packages/benchmarks/dist/index.html
|
||||
```
|
||||
|
||||
To develop against these benchmarks:
|
||||
|
||||
```
|
||||
yarn compile --watch
|
||||
yarn benchmarks --watch
|
||||
```
|
||||
|
||||
### New Features
|
||||
|
||||
45
LICENSE
45
LICENSE
@@ -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.
|
||||
|
||||
30
README.md
30
README.md
@@ -19,21 +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).
|
||||
[ready-to-go project on Glitch](https://glitch.com/edit/#!/react-native).
|
||||
You don’t 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/).
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find the React Native for Web API documentation [on the
|
||||
@@ -53,6 +51,12 @@ yarn add react react-dom react-native-web
|
||||
yarn add --dev babel-plugin-react-native-web
|
||||
```
|
||||
|
||||
And if you need to use `ART`:
|
||||
|
||||
```
|
||||
yarn add react-art
|
||||
```
|
||||
|
||||
### Guides
|
||||
|
||||
* [Getting started](https://github.com/necolas/react-native-web/blob/master/website/guides/getting-started.md)
|
||||
@@ -97,6 +101,16 @@ 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:
|
||||
|
||||
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web)
|
||||
* [Storybook](https://github.com/necolas/react-native-web/tree/0.5.1/website/storybook/.storybook)
|
||||
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
|
||||
* [Phenomic](https://github.com/phenomic/phenomic/tree/master/examples/react-native-web-app)
|
||||
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/v6.2.6/examples/react-native)
|
||||
|
||||
## Contributing
|
||||
|
||||
The main purpose of this repository is to help evolve React web and native
|
||||
@@ -126,7 +140,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
|
||||
|
||||
10
lerna.json
10
lerna.json
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"lerna": "2.5.1",
|
||||
"version": "0.3.3",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"website"
|
||||
]
|
||||
}
|
||||
11
package.json
11
package.json
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "0.6.0",
|
||||
"name": "react-native-web-monorepo",
|
||||
"scripts": {
|
||||
"clean": "del ./packages/*/dist",
|
||||
@@ -18,7 +19,7 @@
|
||||
"prerelease": "yarn test && yarn compile",
|
||||
"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",
|
||||
@@ -42,13 +43,14 @@
|
||||
"eslint-plugin-promise": "^3.6.0",
|
||||
"eslint-plugin-react": "^7.5.1",
|
||||
"flow-bin": "^0.63.1",
|
||||
"glob": "^7.1.2",
|
||||
"husky": "^0.14.3",
|
||||
"jest": "^21.2.1",
|
||||
"lerna": "^2.6.0",
|
||||
"lint-staged": "^6.0.0",
|
||||
"prettier": "^1.8.2",
|
||||
"raf": "^3.4.0",
|
||||
"react": "^16.2.0",
|
||||
"react-art": "^16.3.0",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-test-renderer": "^16.2.0"
|
||||
},
|
||||
@@ -61,6 +63,9 @@
|
||||
"fmt:cmd",
|
||||
"git update-index --again",
|
||||
"eslint"
|
||||
],
|
||||
"packages/react-native-web/src/index.js": [
|
||||
"node ./scripts/babel/createModuleMap.js"
|
||||
]
|
||||
},
|
||||
"prettier": {
|
||||
@@ -68,5 +73,5 @@
|
||||
"singleQuote": true
|
||||
},
|
||||
"author": "Nicolas Gallagher",
|
||||
"license": "BSD-3-Clause"
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "babel-plugin-react-native-web",
|
||||
"version": "0.3.3",
|
||||
"version": "0.6.0",
|
||||
"description": "Babel plugin for React Native for Web",
|
||||
"main": "index.js",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -41,7 +41,7 @@ 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';
|
||||
@@ -74,13 +74,13 @@ const { StyleSheet, TouchableOpacity } = require('react-native');
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
const ReactNative = require('react-native-web/dist/index');
|
||||
const ReactNative = require('react-native-web/dist/index').default;
|
||||
|
||||
const View = require('react-native-web/dist/exports/View');
|
||||
const View = require('react-native-web/dist/exports/View').default;
|
||||
|
||||
const StyleSheet = require('react-native-web/dist/exports/StyleSheet');
|
||||
const StyleSheet = require('react-native-web/dist/exports/StyleSheet').default;
|
||||
|
||||
const TouchableOpacity = require('react-native-web/dist/exports/TouchableOpacity');
|
||||
const TouchableOpacity = require('react-native-web/dist/exports/TouchableOpacity').default;
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -92,18 +92,18 @@ const { ColorPropType, StyleSheet, View, TouchableOpacity, processColor } = requ
|
||||
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
|
||||
const ReactNative = require('react-native-web/dist/index');
|
||||
const ReactNative = require('react-native-web/dist/index').default;
|
||||
|
||||
const createElement = require('react-native-web/dist/exports/createElement');
|
||||
const createElement = require('react-native-web/dist/exports/createElement').default;
|
||||
|
||||
const ColorPropType = require('react-native-web/dist/exports/ColorPropType');
|
||||
const ColorPropType = require('react-native-web/dist/exports/ColorPropType').default;
|
||||
|
||||
const StyleSheet = require('react-native-web/dist/exports/StyleSheet');
|
||||
const StyleSheet = require('react-native-web/dist/exports/StyleSheet').default;
|
||||
|
||||
const View = require('react-native-web/dist/exports/View');
|
||||
const View = require('react-native-web/dist/exports/View').default;
|
||||
|
||||
const TouchableOpacity = require('react-native-web/dist/exports/TouchableOpacity');
|
||||
const TouchableOpacity = require('react-native-web/dist/exports/TouchableOpacity').default;
|
||||
|
||||
const processColor = require('react-native-web/dist/exports/processColor');
|
||||
const processColor = require('react-native-web/dist/exports/processColor').default;
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -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;
|
||||
@@ -92,7 +94,10 @@ module.exports = function({ types: t }) {
|
||||
return t.variableDeclaration(path.node.kind, [
|
||||
t.variableDeclarator(
|
||||
t.identifier(identifier.value.name),
|
||||
t.callExpression(t.identifier('require'), [t.stringLiteral(distLocation)])
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [t.stringLiteral(distLocation)]),
|
||||
t.identifier('default')
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
@@ -105,9 +110,12 @@ module.exports = function({ types: t }) {
|
||||
const importIndex = t.variableDeclaration(path.node.kind, [
|
||||
t.variableDeclarator(
|
||||
t.identifier(name),
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral('react-native-web/dist/index')
|
||||
])
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral('react-native-web/dist/index')
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
)
|
||||
]);
|
||||
|
||||
|
||||
61
packages/babel-plugin-react-native-web/src/moduleMap.js
Normal file
61
packages/babel-plugin-react-native-web/src/moduleMap.js
Normal 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
|
||||
};
|
||||
@@ -5,7 +5,7 @@ Try the [benchmarks app](https://necolas.github.io/react-native-web/benchmarks)
|
||||
To run the benchmarks locally:
|
||||
|
||||
```
|
||||
yarn benchmark
|
||||
yarn benchmarks
|
||||
open ./packages/benchmarks/dist/index.html
|
||||
```
|
||||
|
||||
@@ -13,18 +13,15 @@ Develop against these benchmarks:
|
||||
|
||||
```
|
||||
yarn compile --watch
|
||||
yarn benchmark --watch
|
||||
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,60 +30,41 @@ 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)
|
||||
|
||||
MacBook Pro (13-inch, Early 2011); 2.3 GHz Intel Core i5; 8 GB 1333 MHz DDR3 RAM. Google Chrome 63.
|
||||
|
||||
Typical render timings*: mean ± standard deviations.
|
||||
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.
|
||||
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` |
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "benchmarks",
|
||||
"version": "0.3.3",
|
||||
"version": "0.6.0",
|
||||
"scripts": {
|
||||
"build": "mkdir -p dist && cp -f index.html dist/index.html && webpack --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.1.0",
|
||||
"classnames": "^2.2.5",
|
||||
"d3-scale-chromatic": "^1.1.1",
|
||||
"emotion": "8.0.12",
|
||||
"fela": "5.0.0",
|
||||
"d3-scale-chromatic": "^1.2.0",
|
||||
"emotion": "^9.1.1",
|
||||
"fela": "^6.1.7",
|
||||
"glamor": "2.20.40",
|
||||
"radium": "0.21.0",
|
||||
"radium": "^0.24.0",
|
||||
"react": "^16.2.0",
|
||||
"react-component-benchmark": "^0.0.4",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-fela": "5.0.0",
|
||||
"react-jss": "8.2.1",
|
||||
"react-native-web": "^0.3.2",
|
||||
"reactxp": "0.51.0-alpha.9",
|
||||
"styled-components": "2.4.0",
|
||||
"styled-jsx": "2.2.1",
|
||||
"styletron-client": "3.0.2",
|
||||
"styletron-react": "3.0.3"
|
||||
"react-fela": "^7.2.0",
|
||||
"react-jss": "^8.4.0",
|
||||
"react-native-web": "0.6.0",
|
||||
"reactxp": "^1.1.0",
|
||||
"styled-components": "^3.2.5",
|
||||
"styled-jsx": "^2.2.6",
|
||||
"styletron-engine-atomic": "^1.0.4",
|
||||
"styletron-react": "^4.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-react-native-web": "^0.3.3",
|
||||
"css-loader": "^0.28.9",
|
||||
"style-loader": "^0.19.1",
|
||||
"babel-plugin-react-native-web": "0.6.0",
|
||||
"css-loader": "^0.28.11",
|
||||
"style-loader": "^0.20.3",
|
||||
"url-loader": "^1.0.1",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-bundle-analyzer": "^2.9.2"
|
||||
}
|
||||
|
||||
@@ -100,6 +100,9 @@ export default class App extends Component {
|
||||
libraryName={r.libraryName}
|
||||
libraryVersion={r.libraryVersion}
|
||||
mean={r.mean}
|
||||
meanLayout={r.meanLayout}
|
||||
meanScripting={r.meanScripting}
|
||||
runTime={r.runTime}
|
||||
sampleCount={r.sampleCount}
|
||||
stdDev={r.stdDev}
|
||||
/>
|
||||
@@ -129,6 +132,7 @@ export default class App extends Component {
|
||||
<View ref={this._setBenchWrapperRef}>
|
||||
<Benchmark
|
||||
component={Component}
|
||||
forceLayout={true}
|
||||
getComponentProps={getComponentProps}
|
||||
onComplete={this._createHandleComplete({
|
||||
sampleCount,
|
||||
@@ -282,6 +286,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
picker: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
appearance: 'none',
|
||||
opacity: 0,
|
||||
width: '100%'
|
||||
},
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// @flow
|
||||
/* global $Values */
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
import * as Timing from './timing';
|
||||
import React, { Component } from 'react';
|
||||
import { getMean, getMedian, getStdDev } from './math';
|
||||
@@ -12,8 +14,6 @@ export const BenchmarkType = {
|
||||
UNMOUNT: 'unmount'
|
||||
};
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const shouldRender = (cycle: number, type: $Values<typeof BenchmarkType>): boolean => {
|
||||
switch (type) {
|
||||
// Render every odd iteration (first, third, etc)
|
||||
@@ -66,7 +66,8 @@ const sortNumbers = (a: number, b: number): number => a - b;
|
||||
|
||||
type BenchmarkPropsType = {
|
||||
component: typeof React.Component,
|
||||
getComponentProps?: Function,
|
||||
forceLayout?: boolean,
|
||||
getComponentProps: Function,
|
||||
onComplete: (x: BenchResultsType) => void,
|
||||
sampleCount: number,
|
||||
timeout: number,
|
||||
@@ -74,7 +75,7 @@ type BenchmarkPropsType = {
|
||||
};
|
||||
|
||||
type BenchmarkStateType = {
|
||||
getComponentProps: Function,
|
||||
componentProps: Object,
|
||||
cycle: number,
|
||||
running: boolean
|
||||
};
|
||||
@@ -84,13 +85,13 @@ type BenchmarkStateType = {
|
||||
* TODO: documentation
|
||||
*/
|
||||
export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkStateType> {
|
||||
_raf: ?Function;
|
||||
_startTime: number;
|
||||
_samples: Array<SampleTimingType>;
|
||||
|
||||
static displayName = 'Benchmark';
|
||||
|
||||
static defaultProps = {
|
||||
getComponentProps: () => emptyObject,
|
||||
sampleCount: 50,
|
||||
timeout: 10000, // 10 seconds
|
||||
type: BenchmarkType.MOUNT
|
||||
@@ -100,9 +101,11 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
|
||||
constructor(props: BenchmarkPropsType, context?: {}) {
|
||||
super(props, context);
|
||||
const cycle = 0;
|
||||
const componentProps = props.getComponentProps({ cycle });
|
||||
this.state = {
|
||||
getComponentProps: props.getComponentProps,
|
||||
cycle: 0,
|
||||
componentProps,
|
||||
cycle,
|
||||
running: false
|
||||
};
|
||||
this._startTime = 0;
|
||||
@@ -110,7 +113,9 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: BenchmarkPropsType) {
|
||||
this.setState(state => ({ getComponentProps: nextProps.getComponentProps }));
|
||||
if (nextProps) {
|
||||
this.setState(state => ({ componentProps: nextProps.getComponentProps(state.cycle) }));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps: BenchmarkPropsType, nextState: BenchmarkStateType) {
|
||||
@@ -120,11 +125,20 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { sampleCount, timeout, type } = this.props;
|
||||
const { forceLayout, sampleCount, timeout, type } = this.props;
|
||||
const { cycle, running } = this.state;
|
||||
|
||||
if (running && shouldRecord(cycle, type)) {
|
||||
this._samples[cycle].end = Timing.now();
|
||||
this._samples[cycle].scriptingEnd = Timing.now();
|
||||
|
||||
// force style recalc that would otherwise happen before the next frame
|
||||
if (forceLayout) {
|
||||
this._samples[cycle].layoutStart = Timing.now();
|
||||
if (document.body) {
|
||||
document.body.offsetWidth;
|
||||
}
|
||||
this._samples[cycle].layoutEnd = Timing.now();
|
||||
}
|
||||
}
|
||||
|
||||
if (running) {
|
||||
@@ -138,20 +152,18 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.raf) {
|
||||
window.cancelAnimationFrame(this.raf);
|
||||
if (this._raf) {
|
||||
window.cancelAnimationFrame(this._raf);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { component: Component, type } = this.props;
|
||||
const { getComponentProps, cycle, running } = this.state;
|
||||
const { componentProps, cycle, running } = this.state;
|
||||
if (running && shouldRecord(cycle, type)) {
|
||||
this._samples[cycle] = { start: Timing.now() };
|
||||
this._samples[cycle] = { scriptingStart: Timing.now() };
|
||||
}
|
||||
return running && shouldRender(cycle, type) ? (
|
||||
<Component {...getComponentProps({ cycle })} />
|
||||
) : null;
|
||||
return running && shouldRender(cycle, type) ? <Component {...componentProps} /> : null;
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -163,17 +175,21 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
const { getComponentProps, type } = this.props;
|
||||
const { cycle } = this.state;
|
||||
|
||||
// Calculate the component props outside of the time recording (render)
|
||||
// so that it doesn't skew results
|
||||
const getNextProps =
|
||||
type === BenchmarkType.UPDATE
|
||||
? obj => ({ ...getComponentProps(obj), 'data-test': cycle })
|
||||
: getComponentProps;
|
||||
let componentProps;
|
||||
if (getComponentProps) {
|
||||
// Calculate the component props outside of the time recording (render)
|
||||
// so that it doesn't skew results
|
||||
componentProps = getComponentProps({ cycle });
|
||||
// make sure props always change for update tests
|
||||
if (type === BenchmarkType.UPDATE) {
|
||||
componentProps['data-test'] = cycle;
|
||||
}
|
||||
}
|
||||
|
||||
this.raf = window.requestAnimationFrame(() => {
|
||||
this._raf = window.requestAnimationFrame(() => {
|
||||
this.setState((state: BenchmarkStateType) => ({
|
||||
getComponentProps: getNextProps,
|
||||
cycle: state.cycle + 1
|
||||
cycle: state.cycle + 1,
|
||||
componentProps
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -182,10 +198,16 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
return this._samples.reduce(
|
||||
(
|
||||
memo: Array<FullSampleTimingType>,
|
||||
{ start, end: endTime }: SampleTimingType
|
||||
{ scriptingStart, scriptingEnd, layoutStart, layoutEnd }: SampleTimingType
|
||||
): Array<FullSampleTimingType> => {
|
||||
const end = endTime || 0;
|
||||
memo.push({ start, end, elapsed: end - start });
|
||||
memo.push({
|
||||
start: scriptingStart,
|
||||
end: layoutEnd || scriptingEnd || 0,
|
||||
scriptingStart,
|
||||
scriptingEnd: scriptingEnd || 0,
|
||||
layoutStart,
|
||||
layoutEnd
|
||||
});
|
||||
return memo;
|
||||
},
|
||||
[]
|
||||
@@ -199,11 +221,13 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
this.setState(() => ({ running: false, cycle: 0 }));
|
||||
|
||||
const runTime = endTime - this._startTime;
|
||||
const sortedElapsedTimes = samples
|
||||
.map(({ elapsed }: { elapsed: number }): number => elapsed)
|
||||
const sortedElapsedTimes = samples.map(({ start, end }) => end - start).sort(sortNumbers);
|
||||
const sortedScriptingElapsedTimes = samples
|
||||
.map(({ scriptingStart, scriptingEnd }) => scriptingEnd - scriptingStart)
|
||||
.sort(sortNumbers);
|
||||
const sortedLayoutElapsedTimes = samples
|
||||
.map(({ layoutStart, layoutEnd }) => (layoutEnd || 0) - (layoutStart || 0))
|
||||
.sort(sortNumbers);
|
||||
const mean = getMean(sortedElapsedTimes);
|
||||
const stdDev = getStdDev(sortedElapsedTimes);
|
||||
|
||||
onComplete({
|
||||
startTime: this._startTime,
|
||||
@@ -214,8 +238,10 @@ export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkSt
|
||||
max: sortedElapsedTimes[sortedElapsedTimes.length - 1],
|
||||
min: sortedElapsedTimes[0],
|
||||
median: getMedian(sortedElapsedTimes),
|
||||
mean,
|
||||
stdDev
|
||||
mean: getMean(sortedElapsedTimes),
|
||||
stdDev: getStdDev(sortedElapsedTimes),
|
||||
meanLayout: getMean(sortedLayoutElapsedTimes),
|
||||
meanScripting: getMean(sortedScriptingElapsedTimes)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// @flow
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
export type BenchResultsType = {
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
@@ -9,20 +11,21 @@ export type BenchResultsType = {
|
||||
min: number,
|
||||
median: number,
|
||||
mean: number,
|
||||
stdDev: number,
|
||||
p70: number,
|
||||
p95: number,
|
||||
p99: number
|
||||
stdDev: number
|
||||
};
|
||||
|
||||
export type SampleTimingType = {
|
||||
start: number,
|
||||
end?: number,
|
||||
elapsed?: number
|
||||
scriptingStart: number,
|
||||
scriptingEnd?: number,
|
||||
layoutStart?: number,
|
||||
layoutEnd?: number
|
||||
};
|
||||
|
||||
export type FullSampleTimingType = {
|
||||
start: number,
|
||||
end: number,
|
||||
elapsed: number
|
||||
scriptingStart: number,
|
||||
scriptingEnd: number,
|
||||
layoutStart?: number,
|
||||
layoutEnd?: number
|
||||
};
|
||||
|
||||
@@ -19,11 +19,13 @@ export default class Layout extends Component {
|
||||
const { widescreen } = this.state;
|
||||
return (
|
||||
<View onLayout={this._handleLayout} style={[styles.root, widescreen && styles.row]}>
|
||||
<View style={widescreen ? styles.grow : styles.stackPanel}>{viewPanel}</View>
|
||||
<View style={[widescreen ? styles.grow : styles.stackPanel, styles.layer]}>
|
||||
{viewPanel}
|
||||
</View>
|
||||
<View style={styles.grow}>
|
||||
<View style={styles.grow}>{listPanel}</View>
|
||||
<View style={[styles.grow, styles.layer]}>{listPanel}</View>
|
||||
<View style={styles.divider} />
|
||||
<View>{actionPanel}</View>
|
||||
<View style={styles.layer}>{actionPanel}</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -59,5 +61,8 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
stackPanel: {
|
||||
height: '33.33%'
|
||||
},
|
||||
layer: {
|
||||
transform: [{ translateZ: '0' }]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,37 +8,49 @@ const fmt = (time: number) => {
|
||||
return 10 / i > 1 ? `0${i}` : i;
|
||||
};
|
||||
|
||||
const ReportCard = ({ benchmarkName, libraryName, sampleCount, mean, stdDev, libraryVersion }) => {
|
||||
const sampleCountText = sampleCount != null ? `(${sampleCount})` : '';
|
||||
class ReportCard extends React.PureComponent {
|
||||
render() {
|
||||
const {
|
||||
benchmarkName,
|
||||
libraryName,
|
||||
sampleCount,
|
||||
mean,
|
||||
meanLayout,
|
||||
meanScripting,
|
||||
stdDev,
|
||||
libraryVersion
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<View style={styles.left}>
|
||||
<Text numberOfLines={1} style={styles.bold}>
|
||||
{`${libraryName}${libraryVersion ? '@' + libraryVersion : ''}`}
|
||||
</Text>
|
||||
<Text numberOfLines={1}>
|
||||
{benchmarkName} {sampleCountText}
|
||||
</Text>
|
||||
const sampleCountText = sampleCount != null ? `(${sampleCount})` : '';
|
||||
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<View style={styles.left}>
|
||||
<Text numberOfLines={1} style={styles.bold}>
|
||||
{`${libraryName}${libraryVersion ? '@' + libraryVersion : ''}`}
|
||||
</Text>
|
||||
<Text numberOfLines={1}>
|
||||
{benchmarkName} {sampleCountText}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.right}>
|
||||
{mean ? (
|
||||
<Fragment>
|
||||
<Text style={[styles.bold, styles.monoFont]}>
|
||||
{fmt(mean)} ±{fmt(stdDev)} ms
|
||||
</Text>
|
||||
<Text style={[styles.smallText, styles.monoFont]}>
|
||||
(S/L) {fmt(meanScripting)}/{fmt(meanLayout)} ms
|
||||
</Text>
|
||||
</Fragment>
|
||||
) : (
|
||||
<Text style={styles.bold}>In progress…</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.right}>
|
||||
{mean ? (
|
||||
<Fragment>
|
||||
<Text style={[styles.bold, styles.monoFont]}>
|
||||
{fmt(mean)} ±{fmt(stdDev)} ms
|
||||
</Text>
|
||||
<Text style={[styles.monoFont, styles.centerText]}>
|
||||
<Text style={styles.smallText}>Σ = </Text>
|
||||
<Text>{Math.round(mean * sampleCount)} ms</Text>
|
||||
</Text>
|
||||
</Fragment>
|
||||
) : (
|
||||
<Text style={styles.bold}>In progress…</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { bool } from 'prop-types';
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text } from 'react-native';
|
||||
|
||||
@@ -53,35 +53,34 @@ class SierpinskiTriangle extends React.Component {
|
||||
|
||||
s /= 2;
|
||||
|
||||
return [
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={1}
|
||||
key={1}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x}
|
||||
y={y - s / 2}
|
||||
/>,
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={2}
|
||||
key={2}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x - s}
|
||||
y={y + s / 2}
|
||||
/>,
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={3}
|
||||
key={3}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x + s}
|
||||
y={y + s / 2}
|
||||
/>
|
||||
];
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={1}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x}
|
||||
y={y - s / 2}
|
||||
/>
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={2}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x - s}
|
||||
y={y + s / 2}
|
||||
/>
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={3}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x + s}
|
||||
y={y + s / 2}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
} else {
|
||||
return <span style={{ color: 'white' }}>No implementation available</span>;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import { type Component } from 'react';
|
||||
import packageJson from '../package.json';
|
||||
|
||||
|
||||
26
packages/benchmarks/src/implementations/react-jss/Dot.js
vendored
Normal file
26
packages/benchmarks/src/implementations/react-jss/Dot.js
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import injectSheet from 'react-jss';
|
||||
import React from 'react';
|
||||
|
||||
const Dot = ({ classes, children }) => <div className={classes.root}>{children}</div>;
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
position: 'absolute',
|
||||
cursor: 'pointer',
|
||||
width: 0,
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)',
|
||||
borderBottomColor: ({ color }) => color,
|
||||
borderRightWidth: ({ size }) => size / 2,
|
||||
borderBottomWidth: ({ size }) => size / 2,
|
||||
borderLeftWidth: ({ size }) => size / 2,
|
||||
marginLeft: ({ x }) => x,
|
||||
marginTop: ({ y }) => y
|
||||
}
|
||||
};
|
||||
|
||||
export default injectSheet(styles)(Dot);
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -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}`],
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -49,7 +49,7 @@ module.exports = {
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
dead_code: true,
|
||||
drop_console: true,
|
||||
drop_console: false,
|
||||
screw_ie8: true,
|
||||
warnings: false
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -63,7 +63,7 @@ exports[`enzyme.mount complex 1`] = `
|
||||
</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
|
||||
@@ -117,7 +117,7 @@ exports[`enzyme.mount nested 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
|
||||
@@ -142,7 +142,7 @@ exports[`enzyme.render complex 1`] = `
|
||||
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"
|
||||
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
|
||||
@@ -154,7 +154,7 @@ exports[`enzyme.render complex 1`] = `
|
||||
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"
|
||||
/>
|
||||
<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
|
||||
@@ -174,7 +174,7 @@ exports[`enzyme.render nested 1`] = `
|
||||
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"
|
||||
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
|
||||
@@ -252,7 +252,7 @@ exports[`react-test-renderer complex 1`] = `
|
||||
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"
|
||||
>
|
||||
<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
|
||||
@@ -264,7 +264,7 @@ exports[`react-test-renderer complex 1`] = `
|
||||
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"
|
||||
/>
|
||||
<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
|
||||
@@ -284,7 +284,7 @@ exports[`react-test-renderer nested 1`] = `
|
||||
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"
|
||||
>
|
||||
<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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-web",
|
||||
"version": "0.3.2",
|
||||
"version": "0.6.0",
|
||||
"description": "React Native for Web",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
@@ -19,15 +19,15 @@
|
||||
"inline-style-prefixer": "^4.0.0",
|
||||
"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"
|
||||
|
||||
@@ -17,7 +17,24 @@ exports[`components/ActivityIndicator prop "animating" is "false" 1`] = `
|
||||
Object {
|
||||
"animationDuration": "0.75s",
|
||||
"animationIterationCount": "infinite",
|
||||
"animationName": "rn-ActivityIndicator-animation",
|
||||
"animationName": Array [
|
||||
Object {
|
||||
"0%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
"100%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "360deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"animationPlayState": "paused",
|
||||
"animationTimingFunction": "linear",
|
||||
"height": 20,
|
||||
@@ -80,7 +97,24 @@ exports[`components/ActivityIndicator prop "animating" is "true" 1`] = `
|
||||
Object {
|
||||
"animationDuration": "0.75s",
|
||||
"animationIterationCount": "infinite",
|
||||
"animationName": "rn-ActivityIndicator-animation",
|
||||
"animationName": Array [
|
||||
Object {
|
||||
"0%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
"100%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "360deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"animationTimingFunction": "linear",
|
||||
"height": 20,
|
||||
"width": 20,
|
||||
@@ -177,7 +211,24 @@ exports[`components/ActivityIndicator prop "hidesWhenStopped" is "false" 1`] = `
|
||||
Object {
|
||||
"animationDuration": "0.75s",
|
||||
"animationIterationCount": "infinite",
|
||||
"animationName": "rn-ActivityIndicator-animation",
|
||||
"animationName": Array [
|
||||
Object {
|
||||
"0%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
"100%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "360deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"animationPlayState": "paused",
|
||||
"animationTimingFunction": "linear",
|
||||
"height": 20,
|
||||
@@ -239,7 +290,24 @@ exports[`components/ActivityIndicator prop "hidesWhenStopped" is "true" 1`] = `
|
||||
Object {
|
||||
"animationDuration": "0.75s",
|
||||
"animationIterationCount": "infinite",
|
||||
"animationName": "rn-ActivityIndicator-animation",
|
||||
"animationName": Array [
|
||||
Object {
|
||||
"0%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
"100%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "360deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"animationPlayState": "paused",
|
||||
"animationTimingFunction": "linear",
|
||||
"height": 20,
|
||||
@@ -302,7 +370,24 @@ exports[`components/ActivityIndicator prop "size" is "large" 1`] = `
|
||||
Object {
|
||||
"animationDuration": "0.75s",
|
||||
"animationIterationCount": "infinite",
|
||||
"animationName": "rn-ActivityIndicator-animation",
|
||||
"animationName": Array [
|
||||
Object {
|
||||
"0%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
"100%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "360deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"animationTimingFunction": "linear",
|
||||
"height": 36,
|
||||
"width": 36,
|
||||
@@ -363,7 +448,24 @@ exports[`components/ActivityIndicator prop "size" is a number 1`] = `
|
||||
Object {
|
||||
"animationDuration": "0.75s",
|
||||
"animationIterationCount": "infinite",
|
||||
"animationName": "rn-ActivityIndicator-animation",
|
||||
"animationName": Array [
|
||||
Object {
|
||||
"0%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "0deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
"100%": Object {
|
||||
"transform": Array [
|
||||
Object {
|
||||
"rotate": "360deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"animationTimingFunction": "linear",
|
||||
"height": 30,
|
||||
"width": 30,
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule ActivityIndicator
|
||||
@@ -88,7 +87,12 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
animation: {
|
||||
animationDuration: '0.75s',
|
||||
animationName: 'rn-ActivityIndicator-animation',
|
||||
animationName: [
|
||||
{
|
||||
'0%': { transform: [{ rotate: '0deg' }] },
|
||||
'100%': { transform: [{ rotate: '360deg' }] }
|
||||
}
|
||||
],
|
||||
animationTimingFunction: 'linear',
|
||||
animationIterationCount: 'infinite'
|
||||
},
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Additional CSS for styled app 1`] = `
|
||||
"
|
||||
.rn-backgroundColor-1e4kli0{background-color:purple}
|
||||
.rn-borderTopWidth-10pzpfo{border-top-width:1234px}
|
||||
.rn-borderRightWidth-1y24uml{border-right-width:1234px}
|
||||
.rn-borderBottomWidth-98wxn4{border-bottom-width:1234px}
|
||||
.rn-borderLeftWidth-150mub4{border-left-width:1234px}"
|
||||
`;
|
||||
|
||||
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>"
|
||||
`;
|
||||
|
||||
exports[`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;}
|
||||
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;}
|
||||
}
|
||||
.rn-pointerEvents-12vffkv > *{pointer-events:auto}
|
||||
.rn-pointerEvents-12vffkv{pointer-events:none !important}
|
||||
.rn-alignItems-1oszu61{-ms-flex-align:stretch;-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
|
||||
.rn-borderTopStyle-1efd50x{border-top-style:solid}
|
||||
.rn-borderRightStyle-14skgim{border-right-style:solid}
|
||||
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
|
||||
.rn-borderLeftStyle-mm0ijv{border-left-style:solid}
|
||||
.rn-borderTopWidth-13yce4e{border-top-width:0px}
|
||||
.rn-borderRightWidth-fnigne{border-right-width:0px}
|
||||
.rn-borderBottomWidth-ndvcnb{border-bottom-width:0px}
|
||||
.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-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}
|
||||
.rn-marginBottom-p1pxzi{margin-bottom:0px}
|
||||
.rn-marginLeft-11wrixw{margin-left:0px}
|
||||
.rn-minHeight-ifefl9{min-height:0px}
|
||||
.rn-minWidth-bcqeeo{min-width:0px}
|
||||
.rn-paddingTop-wk8lta{padding-top:0px}
|
||||
.rn-paddingRight-9aemit{padding-right:0px}
|
||||
.rn-paddingBottom-1mdbw0j{padding-bottom:0px}
|
||||
.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}"
|
||||
`;
|
||||
@@ -1,188 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/AppRegistry/renderApplication getApplication 1`] = `
|
||||
<AppContainer
|
||||
rootTag={Object {}}
|
||||
>
|
||||
<RootComponent />
|
||||
</AppContainer>
|
||||
`;
|
||||
|
||||
exports[`apis/AppRegistry/renderApplication getApplication 2`] = `
|
||||
"<style id=\\"react-native-stylesheet-static\\">html{font-family:sans-serif;-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;}
|
||||
@keyframes rn-ActivityIndicator-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg);}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg);}}
|
||||
@keyframes rn-ProgressBar-animation{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);}100%{-webkit-transform:translateX(400%);transform:translateX(400%);}}
|
||||
.rn-pointerEvents-105ug2t{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-ah5dr5{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-633pao{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv > *{pointer-events:auto;}
|
||||
.rn-pointerEvents-ah5dr5 > *{pointer-events:none;}</style>"
|
||||
`;
|
||||
|
||||
exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
|
||||
"<style id=\\"react-native-stylesheet\\">.rn-bottom-1p0dtai{bottom:0px}
|
||||
.rn-left-1d2f490{left:0px}
|
||||
.rn-left-1fe0xdi{left:0%}
|
||||
.rn-left-7b7h2f{left:100%}
|
||||
.rn-position-u8s1d{position:absolute}
|
||||
.rn-position-bnwqim{position:relative}
|
||||
.rn-right-zchlnj{right:0px}
|
||||
.rn-top-ipm5af{top:0px}
|
||||
.rn-cursor-1loqt21{cursor:pointer}
|
||||
.rn-cursor-7q8q6z{cursor:default}
|
||||
.rn-cursor-1ei5mc7{cursor:inherit}
|
||||
.rn-appearance-30o5oe{-moz-appearance:none;-webkit-appearance:none;appearance:none}
|
||||
.rn-backgroundColor-wib322{background-color:transparent}
|
||||
.rn-backgroundColor-8ndhhv{background-color:rgba(33,150,243,1)}
|
||||
.rn-backgroundColor-15al3ab{background-color:rgba(223,223,223,1)}
|
||||
.rn-backgroundColor-44z8sh{background-color:rgba(255,255,255,1)}
|
||||
.rn-backgroundColor-5itogg{background-color:rgba(0,150,136,1)}
|
||||
.rn-backgroundColor-1v82r4u{background-color:rgba(170,184,194,1)}
|
||||
.rn-backgroundColor-1hj8efq{background-color:rgba(213,213,213,1)}
|
||||
.rn-backgroundColor-1bgzomc{background-color:rgba(189,189,189,1)}
|
||||
.rn-color-homxoj{color:inherit}
|
||||
.rn-color-1qtguxu{color:rgba(255,255,255,1)}
|
||||
.rn-color-istcb5{color:rgba(161,161,161,1)}
|
||||
.rn-font-1lw9tu2{font:inherit}
|
||||
.rn-textAlign-1ttztb7{text-align:inherit}
|
||||
.rn-textAlign-q4m81j{text-align:center}
|
||||
.rn-textDecoration-bauka4{text-decoration:none}
|
||||
.rn-listStyle-1ebb2ja{list-style:none}
|
||||
.rn-alignItems-1oszu61{-ms-flex-align:stretch;-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
|
||||
.rn-alignItems-1awozwy{-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center}
|
||||
.rn-borderTopStyle-1efd50x{border-top-style:solid}
|
||||
.rn-borderRightStyle-14skgim{border-right-style:solid}
|
||||
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
|
||||
.rn-borderLeftStyle-mm0ijv{border-left-style:solid}
|
||||
.rn-borderTopWidth-13yce4e{border-top-width:0px}
|
||||
.rn-borderTopWidth-1jxfwug{border-top-width:2px}
|
||||
.rn-borderRightWidth-fnigne{border-right-width:0px}
|
||||
.rn-borderRightWidth-18p6if4{border-right-width:2px}
|
||||
.rn-borderBottomWidth-ndvcnb{border-bottom-width:0px}
|
||||
.rn-borderBottomWidth-wgabs5{border-bottom-width:2px}
|
||||
.rn-borderLeftWidth-gxnn5r{border-left-width:0px}
|
||||
.rn-borderLeftWidth-dwliz8{border-left-width:2px}
|
||||
.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-display-xoduu5{display:-webkit-inline-box;display:-moz-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}
|
||||
.rn-display-1471scf{display:inline}
|
||||
.rn-flexShrink-1pxmb3b{-ms-flex-negative:0 !important;-webkit-flex-shrink:0 !important;flex-shrink:0 !important}
|
||||
.rn-flexShrink-1awmn5t{-ms-flex-negative:1 !important;-webkit-flex-shrink:1 !important;flex-shrink:1 !important}
|
||||
.rn-flexBasis-7vfszb{-ms-flex-preferred-size:auto !important;-webkit-flex-basis:auto !important;flex-basis:auto !important}
|
||||
.rn-flexDirection-eqz5dr{-ms-flex-direction:column;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
|
||||
.rn-flexDirection-18u37iz{-ms-flex-direction:row;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;flex-direction:row}
|
||||
.rn-marginTop-1mnahxq{margin-top:0px}
|
||||
.rn-marginTop-1t01tom{margin-top:auto}
|
||||
.rn-marginRight-61z16t{margin-right:0px}
|
||||
.rn-marginRight-lchren{margin-right:auto}
|
||||
.rn-marginBottom-p1pxzi{margin-bottom:0px}
|
||||
.rn-marginBottom-1qahzrx{margin-bottom:auto}
|
||||
.rn-marginLeft-11wrixw{margin-left:0px}
|
||||
.rn-marginLeft-1jj8364{margin-left:auto}
|
||||
.rn-minHeight-ifefl9{min-height:0px}
|
||||
.rn-minWidth-bcqeeo{min-width:0px}
|
||||
.rn-paddingTop-wk8lta{padding-top:0px}
|
||||
.rn-paddingTop-tskmnb{padding-top:8px}
|
||||
.rn-paddingRight-9aemit{padding-right:0px}
|
||||
.rn-paddingRight-1pyaxff{padding-right:8px}
|
||||
.rn-paddingBottom-1mdbw0j{padding-bottom:0px}
|
||||
.rn-paddingBottom-xd6kpl{padding-bottom:8px}
|
||||
.rn-paddingLeft-gy4na3{padding-left:0px}
|
||||
.rn-paddingLeft-1m04atk{padding-left:8px}
|
||||
.rn-zIndex-1lgpqti{z-index:0}
|
||||
.rn-zIndex-1wyyakw{z-index:-1}
|
||||
.rn-backgroundPosition-vvn4in{background-position:center}
|
||||
.rn-backgroundRepeat-u6sd8q{background-repeat:no-repeat}
|
||||
.rn-backgroundRepeat-17leim2{background-repeat:repeat}
|
||||
.rn-backgroundSize-4gszlv{background-size:cover}
|
||||
.rn-backgroundSize-1sxrcry{background-size:auto}
|
||||
.rn-backgroundSize-ehq7j7{background-size:contain}
|
||||
.rn-backgroundSize-x3cy2q{background-size:100% 100%}
|
||||
.rn-height-1pi2tsx{height:100%}
|
||||
.rn-height-z80fyv{height:20px}
|
||||
.rn-height-1r8g8re{height:36px}
|
||||
.rn-height-10ptun7{height:16px}
|
||||
.rn-height-4v7adb{height:5px}
|
||||
.rn-height-1dernwh{height:70%}
|
||||
.rn-opacity-1272l3b{opacity:0}
|
||||
.rn-opacity-6dt33c{opacity:1}
|
||||
.rn-width-13qz1uu{width:100%}
|
||||
.rn-width-19wmn03{width:20px}
|
||||
.rn-width-1acpoxo{width:36px}
|
||||
.rn-width-1janqcz{width:16px}
|
||||
.rn-touchAction-19z077z{-ms-touch-action:none;touch-action:none}
|
||||
.rn-touchAction-1gvxusu{-ms-touch-action:manipulate;touch-action:manipulate}
|
||||
.rn-WebkitOverflowScrolling-150rngu{-webkit-overflow-scrolling:touch}
|
||||
.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-overflowX-11yh6sk{overflow-x:hidden}
|
||||
.rn-overflowX-lltvgl{overflow-x:auto}
|
||||
.rn-overflowY-1rnoaur{overflow-y:auto}
|
||||
.rn-overflowY-buy8e9{overflow-y:hidden}
|
||||
.rn-transform-emqnss{-webkit-transform:translateZ(0px);transform:translateZ(0px)}
|
||||
.rn-fontFamily-10u92zi{font-family:-apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Ubuntu, \\"Helvetica Neue\\", sans-serif}
|
||||
.rn-fontFamily-poiln3{font-family:inherit}
|
||||
.rn-fontSize-1b43r93{font-size:14px}
|
||||
.rn-fontSize-7cikom{font-size:inherit}
|
||||
.rn-whiteSpace-q42fyq{white-space:pre-wrap}
|
||||
.rn-whiteSpace-irrty{white-space:inherit}
|
||||
.rn-whiteSpace-3s2u2q{white-space:nowrap}
|
||||
.rn-wordWrap-qvutc0{word-wrap:break-word}
|
||||
.rn-userSelect-lrvibr{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}
|
||||
.rn-maxWidth-dnmrzs{max-width:100%}
|
||||
.rn-textOverflow-1udbk01{text-overflow:ellipsis}
|
||||
.rn-justifyContent-1777fci{-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}
|
||||
.rn-visibility-11j9u27{visibility:hidden}
|
||||
.rn-animationDuration-17bb2tj{-webkit-animation-duration:0.75s;animation-duration:0.75s}
|
||||
.rn-animationDuration-1ay1djp{-webkit-animation-duration:1s;animation-duration:1s}
|
||||
.rn-animationIterationCount-1muvv40{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}
|
||||
.rn-animationName-dozj4v{-webkit-animation-name:rn-ActivityIndicator-animation;animation-name:rn-ActivityIndicator-animation}
|
||||
.rn-animationName-141g9a{-webkit-animation-name:rn-ProgressBar-animation;animation-name:rn-ProgressBar-animation}
|
||||
.rn-animationTimingFunction-1ldzwu0{-webkit-animation-timing-function:linear;animation-timing-function:linear}
|
||||
.rn-animationPlayState-1abnn5w{-webkit-animation-play-state:paused;animation-play-state:paused}
|
||||
.rn-transitionDuration-eafdt9{-webkit-transition-duration:0.15s;transition-duration:0.15s}
|
||||
.rn-transitionDuration-13tjlyg{-webkit-transition-duration:0.1s;transition-duration:0.1s}
|
||||
.rn-transitionProperty-1i6wzkk{-moz-transition-property:opacity;-webkit-transition-property:opacity;transition-property:opacity}
|
||||
.rn-borderTopLeftRadius-1iymjk7{border-top-left-radius:2px}
|
||||
.rn-borderTopLeftRadius-jt3ufn{border-top-left-radius:100%}
|
||||
.rn-borderTopLeftRadius-ou6ah9{border-top-left-radius:0px}
|
||||
.rn-borderTopRightRadius-s2skl2{border-top-right-radius:2px}
|
||||
.rn-borderTopRightRadius-1e868j9{border-top-right-radius:100%}
|
||||
.rn-borderTopRightRadius-t12b5v{border-top-right-radius:0px}
|
||||
.rn-borderBottomRightRadius-l5bh9y{border-bottom-right-radius:2px}
|
||||
.rn-borderBottomRightRadius-ujv9e3{border-bottom-right-radius:100%}
|
||||
.rn-borderBottomRightRadius-zmljjp{border-bottom-right-radius:0px}
|
||||
.rn-borderBottomLeftRadius-101sy47{border-bottom-left-radius:2px}
|
||||
.rn-borderBottomLeftRadius-1hakmuk{border-bottom-left-radius:100%}
|
||||
.rn-borderBottomLeftRadius-pm2fo{border-bottom-left-radius:0px}
|
||||
.rn-fontWeight-majxgm{font-weight:500}
|
||||
.rn-textTransform-tsynxw{text-transform:uppercase}
|
||||
.rn-borderTopColor-j4x2lb{border-top-color:rgba(101,119,134,1)}
|
||||
.rn-borderTopColor-gj2eto{border-top-color:rgba(0,150,136,1)}
|
||||
.rn-borderTopColor-1j7vz2b{border-top-color:rgba(204,214,221,1)}
|
||||
.rn-borderTopColor-2dclza{border-top-color:rgba(170,184,194,1)}
|
||||
.rn-borderTopColor-kqr9px{border-top-color:black}
|
||||
.rn-borderRightColor-12i18q1{border-right-color:rgba(101,119,134,1)}
|
||||
.rn-borderRightColor-31ud7z{border-right-color:rgba(0,150,136,1)}
|
||||
.rn-borderRightColor-10fg1ub{border-right-color:rgba(204,214,221,1)}
|
||||
.rn-borderRightColor-8jf312{border-right-color:rgba(170,184,194,1)}
|
||||
.rn-borderRightColor-q0dj5p{border-right-color:black}
|
||||
.rn-borderBottomColor-mg3rfb{border-bottom-color:rgba(101,119,134,1)}
|
||||
.rn-borderBottomColor-1bgnb8i{border-bottom-color:rgba(0,150,136,1)}
|
||||
.rn-borderBottomColor-zxuuv6{border-bottom-color:rgba(204,214,221,1)}
|
||||
.rn-borderBottomColor-1yeakrt{border-bottom-color:rgba(170,184,194,1)}
|
||||
.rn-borderBottomColor-1ah7hsa{border-bottom-color:black}
|
||||
.rn-borderLeftColor-vnhemr{border-left-color:rgba(101,119,134,1)}
|
||||
.rn-borderLeftColor-tbzcuz{border-left-color:rgba(0,150,136,1)}
|
||||
.rn-borderLeftColor-1p34dw6{border-left-color:rgba(204,214,221,1)}
|
||||
.rn-borderLeftColor-bluj2i{border-left-color:rgba(170,184,194,1)}
|
||||
.rn-borderLeftColor-137uh4u{border-left-color:black}
|
||||
.rn-backgroundImage-rs94m5{background-image:url(\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMSAxIgogICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0Ij4KICA8cGF0aAogICAgIGQ9Ik0gMC4wNDAzODA1OSwwLjYyNjc3NjcgMC4xNDY0NDY2MSwwLjUyMDcxMDY4IDAuNDI5Mjg5MzIsMC44MDM1NTMzOSAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IE0gMC4yMTcxNTcyOSwwLjgwMzU1MzM5IDAuODUzNTUzMzksMC4xNjcxNTcyOSAwLjk1OTYxOTQxLDAuMjczMjIzMyAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IgogICAgIGlkPSJyZWN0Mzc4MCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L3N2Zz4K\\")}
|
||||
.rn-alignSelf-k200y{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}
|
||||
.rn-boxShadow-1ewcgjf{box-shadow:0px 1px 3px rgba(0,0,0,0.5)}
|
||||
.rn-resize-1dz5y72{resize:none}</style>"
|
||||
`;
|
||||
80
packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.js
vendored
Normal file
80
packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.js
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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 />;
|
||||
|
||||
describe('AppRegistry', () => {
|
||||
describe('getApplication', () => {
|
||||
const canUseDOM = ExecutionEnvironment.canUseDOM;
|
||||
|
||||
beforeEach(() => {
|
||||
ExecutionEnvironment.canUseDOM = false;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
ExecutionEnvironment.canUseDOM = canUseDOM;
|
||||
});
|
||||
|
||||
test('returns "element" and "getStyleElement"', () => {
|
||||
AppRegistry.registerComponent('App', () => RootComponent);
|
||||
|
||||
const { element, getStyleElement } = AppRegistry.getApplication('App', {});
|
||||
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
|
||||
AppRegistry.registerComponent('App1', () => RootComponent);
|
||||
let app = AppRegistry.getApplication('App1', {});
|
||||
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' } });
|
||||
const Component = () => <View style={styles.root} />;
|
||||
AppRegistry.registerComponent('App2', () => Component);
|
||||
app = AppRegistry.getApplication('App2', {});
|
||||
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 = AppRegistry.getApplication('App1', {});
|
||||
render(app.element);
|
||||
const third = getTextContent(app.getStyleElement);
|
||||
|
||||
expect(first).toEqual(third);
|
||||
});
|
||||
});
|
||||
|
||||
describe('runApplication', () => {
|
||||
test('callback after render', () => {
|
||||
AppRegistry.registerComponent('App', () => RootComponent);
|
||||
|
||||
const callback = jest.fn();
|
||||
const rootTag = document.createElement('div');
|
||||
rootTag.id = 'react-root';
|
||||
document.body.appendChild(rootTag);
|
||||
AppRegistry.runApplication('App', { initialProps: {}, rootTag, callback });
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
document.body.removeChild(rootTag);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import { getApplication } from '../renderApplication';
|
||||
import React from 'react';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
|
||||
const RootComponent = () => <div />;
|
||||
|
||||
describe('apis/AppRegistry/renderApplication', () => {
|
||||
test('getApplication', () => {
|
||||
const { element, stylesheets } = getApplication(RootComponent, {});
|
||||
|
||||
expect(element).toMatchSnapshot();
|
||||
stylesheets.forEach(sheet => {
|
||||
const result = ReactDOMServer.renderToStaticMarkup(sheet);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule AppRegistry
|
||||
@@ -19,6 +18,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 +53,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.initialProps || emptyObject,
|
||||
wrapperComponentProvider && wrapperComponentProvider(appParameters)
|
||||
),
|
||||
run: appParameters =>
|
||||
renderApplication(
|
||||
componentProviderInstrumentationHook(componentProvider),
|
||||
appParameters.initialProps || emptyObject,
|
||||
appParameters.rootTag,
|
||||
wrapperComponentProvider && wrapperComponentProvider(appParameters),
|
||||
appParameters.callback
|
||||
)
|
||||
};
|
||||
return appKey;
|
||||
}
|
||||
@@ -78,9 +96,9 @@ export default class AppRegistry {
|
||||
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 +110,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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -13,7 +12,7 @@ import AppContainer from './AppContainer';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import hydrate from '../../modules/hydrate';
|
||||
import render from '../render';
|
||||
import StyleSheet from '../StyleSheet';
|
||||
import styleResolver from '../StyleSheet/styleResolver';
|
||||
import React, { type ComponentType } from 'react';
|
||||
|
||||
const renderFn = process.env.NODE_ENV !== 'production' ? render : hydrate;
|
||||
@@ -21,27 +20,35 @@ 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>
|
||||
);
|
||||
const stylesheets = StyleSheet.getStyleSheets().map(sheet => (
|
||||
// ensure that CSS text is not escaped
|
||||
<style dangerouslySetInnerHTML={{ __html: sheet.textContent }} id={sheet.id} key={sheet.id} />
|
||||
));
|
||||
return { element, stylesheets };
|
||||
// Don't escape CSS text
|
||||
const getStyleElement = () => {
|
||||
const sheet = styleResolver.getStyleSheet();
|
||||
return <style dangerouslySetInnerHTML={{ __html: sheet.textContent }} id={sheet.id} />;
|
||||
};
|
||||
return { element, getStyleElement };
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule AppState
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule AsyncStorage
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule BackHandler
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Clipboard
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule ColorPropType
|
||||
* @noflow
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Dimensions
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule EdgeInsetsPropType
|
||||
* @flow
|
||||
|
||||
@@ -2,44 +2,100 @@
|
||||
|
||||
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', () => {
|
||||
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');
|
||||
I18nManager.forceRTL(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('swapLeftAndRightInRTL', () => {
|
||||
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', () => {
|
||||
test('when set to false, "isRTL" is false', () => {
|
||||
I18nManager.allowRTL(false);
|
||||
expect(I18nManager.isRTL).toBe(false);
|
||||
expect(getDocumentDir()).toEqual('ltr');
|
||||
I18nManager.allowRTL(true);
|
||||
});
|
||||
test('when set to true, "isRTL" is true', () => {
|
||||
I18nManager.allowRTL(true);
|
||||
expect(I18nManager.isRTL).toBe(true);
|
||||
expect(getDocumentDir()).toEqual('rtl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('forceRTL', () => {
|
||||
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');
|
||||
I18nManager.forceRTL(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('swapLeftAndRightInRTL', () => {
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule I18nManager
|
||||
@@ -14,11 +13,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 +32,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 +43,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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"', () => {
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Image
|
||||
@@ -57,7 +56,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 +71,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;
|
||||
@@ -108,7 +107,13 @@ class Image extends Component<*, State> {
|
||||
onLoadStart: func,
|
||||
resizeMode: oneOf(Object.keys(ImageResizeMode)),
|
||||
source: ImageSourcePropType,
|
||||
style: StyleSheetPropType(ImageStylePropTypes)
|
||||
style: StyleSheetPropType(ImageStylePropTypes),
|
||||
// compatibility with React Native
|
||||
/* eslint-disable react/sort-prop-types */
|
||||
blurRadius: number,
|
||||
capInsets: shape({ top: number, left: number, bottom: number, right: number }),
|
||||
resizeMethod: oneOf(['auto', 'resize', 'scale'])
|
||||
/* eslint-enable react/sort-prop-types */
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@@ -162,8 +167,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,10 +189,13 @@ class Image extends Component<*, State> {
|
||||
source,
|
||||
testID,
|
||||
/* eslint-disable */
|
||||
blurRadius,
|
||||
capInsets,
|
||||
onError,
|
||||
onLoad,
|
||||
onLoadEnd,
|
||||
onLoadStart,
|
||||
resizeMethod,
|
||||
resizeMode,
|
||||
/* eslint-enable */
|
||||
...other
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule InteractionManager
|
||||
@@ -21,9 +20,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: () => {}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Keyboard
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule KeyboardAvoidingView
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Linking
|
||||
@@ -25,7 +24,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 +32,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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule NetInfo
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,7 +10,7 @@ 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"
|
||||
onChange={[Function]}
|
||||
>
|
||||
<PickerItem
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Picker
|
||||
@@ -24,7 +23,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 +37,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 +82,7 @@ class Picker extends Component<Props> {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
initial: {
|
||||
fontFamily: 'inherit',
|
||||
fontFamily: 'System',
|
||||
fontSize: 'inherit',
|
||||
margin: 0
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule PixelRatio
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule Platform
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule PointPropType
|
||||
* @flow
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule ProgressBar
|
||||
@@ -96,7 +95,12 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
animation: {
|
||||
animationDuration: '1s',
|
||||
animationName: 'rn-ProgressBar-animation',
|
||||
animationName: [
|
||||
{
|
||||
'0%': { transform: [{ translateX: '-100%' }] },
|
||||
'100%': { transform: [{ translateX: '400%' }] }
|
||||
}
|
||||
],
|
||||
animationTimingFunction: 'linear',
|
||||
animationIterationCount: 'infinite'
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule RefreshControl
|
||||
|
||||
@@ -1,14 +1,38 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule ScrollView
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule StatusBar
|
||||
|
||||
244
packages/react-native-web/src/exports/StyleSheet/ReactNativeStyleResolver.js
vendored
Normal file
244
packages/react-native-web/src/exports/StyleSheet/ReactNativeStyleResolver.js
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Nicolas Gallagher.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
/**
|
||||
* WARNING: changes to this file in particular can cause significant changes to
|
||||
* the results of render performance benchmarks.
|
||||
*/
|
||||
|
||||
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
import createReactDOMStyle from './createReactDOMStyle';
|
||||
import flattenArray from '../../modules/flattenArray';
|
||||
import flattenStyle from './flattenStyle';
|
||||
import I18nManager from '../I18nManager';
|
||||
import i18nStyle from './i18nStyle';
|
||||
import { prefixInlineStyles } from '../../modules/prefixStyles';
|
||||
import StyleSheetManager from './StyleSheetManager';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
export default class ReactNativeStyleResolver {
|
||||
_init() {
|
||||
this.cache = { ltr: {}, rtl: {}, rtlNoSwap: {} };
|
||||
this.injectedCache = { ltr: {}, rtl: {}, rtlNoSwap: {} };
|
||||
this.styleSheetManager = new StyleSheetManager();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
getStyleSheet() {
|
||||
// reset state on the server so critical css is always the result
|
||||
const sheet = this.styleSheetManager.getStyleSheet();
|
||||
if (!canUseDOM) {
|
||||
this._init();
|
||||
}
|
||||
return sheet;
|
||||
}
|
||||
|
||||
_injectRegisteredStyle(id) {
|
||||
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));
|
||||
Object.keys(domStyle).forEach(styleProp => {
|
||||
const value = domStyle[styleProp];
|
||||
if (value != null) {
|
||||
this.styleSheetManager.injectDeclaration(styleProp, value);
|
||||
}
|
||||
});
|
||||
this.injectedCache[dir][id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a React Native style object to DOM attributes
|
||||
*/
|
||||
resolve(style) {
|
||||
if (!style) {
|
||||
return emptyObject;
|
||||
}
|
||||
|
||||
// fast and cachable
|
||||
if (typeof style === 'number') {
|
||||
this._injectRegisteredStyle(style);
|
||||
const key = createCacheKey(style);
|
||||
return this._resolveStyleIfNeeded(style, key);
|
||||
}
|
||||
|
||||
// resolve a plain RN style object
|
||||
if (!Array.isArray(style)) {
|
||||
return this._resolveStyleIfNeeded(style);
|
||||
}
|
||||
|
||||
// flatten the style array
|
||||
// cache resolved props when all styles are registered
|
||||
// otherwise fallback to resolving
|
||||
const flatArray = flattenArray(style);
|
||||
let isArrayOfNumbers = true;
|
||||
for (let i = 0; i < flatArray.length; i++) {
|
||||
const id = flatArray[i];
|
||||
if (typeof id !== 'number') {
|
||||
isArrayOfNumbers = false;
|
||||
} else {
|
||||
this._injectRegisteredStyle(id);
|
||||
}
|
||||
}
|
||||
const key = isArrayOfNumbers ? createCacheKey(flatArray.join('-')) : null;
|
||||
return this._resolveStyleIfNeeded(flatArray, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a React Native style object to DOM attributes, accounting for
|
||||
* the existing styles applied to the DOM node.
|
||||
*
|
||||
* To determine the next style, some of the existing DOM state must be
|
||||
* converted back into React Native styles.
|
||||
*/
|
||||
resolveWithNode(rnStyleNext, node) {
|
||||
const { classList: rdomClassList, style: rdomStyle } = getDOMStyleInfo(node);
|
||||
// Convert the DOM classList back into a React Native form
|
||||
// Preserves unrecognized class names.
|
||||
const { classList: rnClassList, style: rnStyle } = rdomClassList.reduce(
|
||||
(styleProps, className) => {
|
||||
const { prop, value } = this.styleSheetManager.getDeclaration(className);
|
||||
if (prop) {
|
||||
styleProps.style[prop] = value;
|
||||
} else {
|
||||
styleProps.classList.push(className);
|
||||
}
|
||||
return styleProps;
|
||||
},
|
||||
{ classList: [], style: {} }
|
||||
);
|
||||
|
||||
// Create next DOM style props from current and next RN styles
|
||||
const { classList: rdomClassListNext, style: rdomStyleNext } = this.resolve([
|
||||
i18nStyle(rnStyle),
|
||||
rnStyleNext
|
||||
]);
|
||||
|
||||
// Final className
|
||||
// Add the current class names not managed by React Native
|
||||
const className = classListToString(rdomClassListNext.concat(rnClassList));
|
||||
|
||||
// Final style
|
||||
// Next class names take priority over current inline styles
|
||||
const style = { ...rdomStyle };
|
||||
rdomClassListNext.forEach(className => {
|
||||
const { prop } = this.styleSheetManager.getDeclaration(className);
|
||||
if (style[prop]) {
|
||||
style[prop] = '';
|
||||
}
|
||||
});
|
||||
// Next inline styles take priority over current inline styles
|
||||
Object.assign(style, rdomStyleNext);
|
||||
|
||||
return { className, style };
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a React Native style object
|
||||
*/
|
||||
_resolveStyle(style) {
|
||||
const flatStyle = flattenStyle(style);
|
||||
const domStyle = createReactDOMStyle(i18nStyle(flatStyle));
|
||||
|
||||
const props = Object.keys(domStyle).reduce(
|
||||
(props, styleProp) => {
|
||||
const value = domStyle[styleProp];
|
||||
if (value != null) {
|
||||
const className = this.styleSheetManager.getClassName(styleProp, value);
|
||||
if (className) {
|
||||
props.classList.push(className);
|
||||
} else {
|
||||
// Certain properties and values are not transformed by 'createReactDOMStyle' as they
|
||||
// require more complex transforms into multiple CSS rules. Here we assume that StyleManager
|
||||
// can bind these styles to a className, and prevent them becoming invalid inline-styles.
|
||||
if (
|
||||
styleProp === 'pointerEvents' ||
|
||||
styleProp === 'placeholderTextColor' ||
|
||||
styleProp === 'animationName'
|
||||
) {
|
||||
const className = this.styleSheetManager.injectDeclaration(styleProp, value);
|
||||
if (className) {
|
||||
props.classList.push(className);
|
||||
}
|
||||
} else {
|
||||
if (!props.style) {
|
||||
props.style = {};
|
||||
}
|
||||
// 4x slower render
|
||||
props.style[styleProp] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return props;
|
||||
},
|
||||
{ classList: [] }
|
||||
);
|
||||
|
||||
props.className = classListToString(props.classList);
|
||||
if (props.style) {
|
||||
props.style = prefixInlineStyles(props.style);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caching layer over 'resolveStyle'
|
||||
*/
|
||||
_resolveStyleIfNeeded(style, key) {
|
||||
if (key) {
|
||||
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);
|
||||
}
|
||||
return this.cache[dir][key];
|
||||
}
|
||||
return this._resolveStyle(style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Misc helpers
|
||||
*/
|
||||
const createCacheKey = id => {
|
||||
const prefix = 'rn';
|
||||
return `${prefix}-${id}`;
|
||||
};
|
||||
|
||||
const classListToString = list => list.join(' ').trim();
|
||||
|
||||
/**
|
||||
* Copies classList and style data from a DOM node
|
||||
*/
|
||||
const hyphenPattern = /-([a-z])/g;
|
||||
const toCamelCase = str => str.replace(hyphenPattern, m => m[1].toUpperCase());
|
||||
|
||||
const getDOMStyleInfo = node => {
|
||||
const nodeStyle = node.style;
|
||||
const classList = Array.prototype.slice.call(node.classList);
|
||||
const style = {};
|
||||
// DOM style is a CSSStyleDeclaration
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration
|
||||
for (let i = 0; i < nodeStyle.length; i += 1) {
|
||||
const property = nodeStyle.item(i);
|
||||
if (property) {
|
||||
// DOM style uses hyphenated prop names and may include vendor prefixes
|
||||
// Transform back into React DOM style.
|
||||
style[toCamelCase(property)] = nodeStyle.getPropertyValue(property);
|
||||
}
|
||||
}
|
||||
return { classList, style };
|
||||
};
|
||||
@@ -1,161 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
import generateCss from './generateCss';
|
||||
import hash from '../../vendor/hash';
|
||||
import staticCss from './staticCss';
|
||||
|
||||
const emptyObject = {};
|
||||
const STYLE_ELEMENT_ID = 'react-native-stylesheet';
|
||||
|
||||
const createClassName = (prop, value) => {
|
||||
const hashed = hash(prop + value);
|
||||
return process.env.NODE_ENV !== 'production' ? `rn-${prop}-${hashed}` : `rn-${hashed}`;
|
||||
};
|
||||
|
||||
const createCssRule = (className, prop, value) => {
|
||||
const css = generateCss({ [prop]: value });
|
||||
const selector = `.${className}`;
|
||||
return `${selector}{${css}}`;
|
||||
};
|
||||
|
||||
const pointerEvents = {
|
||||
auto: createClassName('pointerEvents', 'auto'),
|
||||
boxNone: createClassName('pointerEvents', 'box-none'),
|
||||
boxOnly: createClassName('pointerEvents', 'box-only'),
|
||||
none: createClassName('pointerEvents', 'none')
|
||||
};
|
||||
|
||||
// See #513
|
||||
const pointerEventsCss =
|
||||
`.${pointerEvents.auto}{pointer-events:auto !important;}\n` +
|
||||
`.${pointerEvents.boxOnly}{pointer-events:auto !important;}\n` +
|
||||
`.${pointerEvents.none}{pointer-events:none !important;}\n` +
|
||||
`.${pointerEvents.boxNone}{pointer-events:none !important;}\n` +
|
||||
`.${pointerEvents.boxNone} > *{pointer-events:auto;}\n` +
|
||||
`.${pointerEvents.boxOnly} > *{pointer-events:none;}`;
|
||||
|
||||
export default class StyleManager {
|
||||
cache = null;
|
||||
mainSheet = null;
|
||||
|
||||
constructor() {
|
||||
// custom pointer event values are implemented using descendent selectors,
|
||||
// so we manually create the CSS and pre-register the declarations
|
||||
const pointerEventsPropName = 'pointerEvents';
|
||||
this.cache = {
|
||||
byClassName: {
|
||||
[pointerEvents.auto]: { prop: pointerEventsPropName, value: 'auto' },
|
||||
[pointerEvents.boxNone]: {
|
||||
prop: pointerEventsPropName,
|
||||
value: 'box-none'
|
||||
},
|
||||
[pointerEvents.boxOnly]: {
|
||||
prop: pointerEventsPropName,
|
||||
value: 'box-only'
|
||||
},
|
||||
[pointerEvents.none]: { prop: pointerEventsPropName, value: 'none' }
|
||||
},
|
||||
byProp: {
|
||||
pointerEvents: {
|
||||
auto: pointerEvents.auto,
|
||||
'box-none': pointerEvents.boxNone,
|
||||
'box-only': pointerEvents.boxOnly,
|
||||
none: pointerEvents.none
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// on the client we check for an existing style sheet before injecting style sheets
|
||||
if (canUseDOM) {
|
||||
const prerenderedStyleSheet = document.getElementById(STYLE_ELEMENT_ID);
|
||||
if (prerenderedStyleSheet) {
|
||||
this.mainSheet = prerenderedStyleSheet;
|
||||
} else {
|
||||
document.head.insertAdjacentHTML('afterbegin', this.getStyleSheetHtml());
|
||||
this.mainSheet = document.getElementById(STYLE_ELEMENT_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getClassName(prop, value) {
|
||||
const cache = this.cache.byProp;
|
||||
return cache[prop] && cache[prop].hasOwnProperty(value) && cache[prop][value];
|
||||
}
|
||||
|
||||
getDeclaration(className) {
|
||||
const cache = this.cache.byClassName;
|
||||
return cache[className] || emptyObject;
|
||||
}
|
||||
|
||||
getStyleSheetHtml() {
|
||||
const styleSheets = this.getStyleSheets();
|
||||
return styleSheets
|
||||
.map(sheet => {
|
||||
return `<style id="${sheet.id}">\n${sheet.textContent}\n</style>`;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
getStyleSheets() {
|
||||
const cache = this.cache.byProp;
|
||||
|
||||
const mainSheetTextContext = Object.keys(cache)
|
||||
.reduce((rules, prop) => {
|
||||
if (prop !== 'pointerEvents') {
|
||||
Object.keys(cache[prop]).forEach(value => {
|
||||
const className = this.getClassName(prop, value);
|
||||
const rule = createCssRule(className, prop, value);
|
||||
rules.push(rule);
|
||||
});
|
||||
}
|
||||
return rules;
|
||||
}, [])
|
||||
.join('\n');
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'react-native-stylesheet-static',
|
||||
textContent: `${staticCss}\n${pointerEventsCss}`
|
||||
},
|
||||
{
|
||||
id: STYLE_ELEMENT_ID,
|
||||
textContent: `${mainSheetTextContext}`
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
setDeclaration(prop, value) {
|
||||
let className = this.getClassName(prop, value);
|
||||
if (!className) {
|
||||
className = createClassName(prop, value);
|
||||
this._addToCache(className, prop, value);
|
||||
if (canUseDOM) {
|
||||
const sheet = this.mainSheet.sheet;
|
||||
// avoid injecting if the rule already exists (e.g., server rendered, hot reload)
|
||||
if (this.mainSheet.textContent.indexOf(className) === -1) {
|
||||
const rule = createCssRule(className, prop, value);
|
||||
sheet.insertRule(rule, sheet.cssRules.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
_addToCache(className, prop, value) {
|
||||
const cache = this.cache;
|
||||
if (!cache.byProp[prop]) {
|
||||
cache.byProp[prop] = {};
|
||||
}
|
||||
cache.byProp[prop][value] = className;
|
||||
cache.byClassName[className] = { prop, value };
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* WARNING: changes to this file in particular can cause significant changes to
|
||||
* the results of render performance benchmarks.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
import createReactDOMStyle from './createReactDOMStyle';
|
||||
import flattenArray from '../../modules/flattenArray';
|
||||
import flattenStyle from './flattenStyle';
|
||||
import I18nManager from '../I18nManager';
|
||||
import i18nStyle from './i18nStyle';
|
||||
import { prefixInlineStyles } from '../../modules/prefixStyles';
|
||||
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
|
||||
import StyleManager from './StyleManager';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const createCacheKey = id => {
|
||||
const prefix = 'rn';
|
||||
return `${prefix}-${id}`;
|
||||
};
|
||||
|
||||
const classListToString = list => list.join(' ').trim();
|
||||
|
||||
export default class StyleRegistry {
|
||||
cache = { ltr: {}, rtl: {} };
|
||||
styleManager = new StyleManager();
|
||||
|
||||
getStyleSheets() {
|
||||
return this.styleManager.getStyleSheets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers and precaches a React Native style object to HTML class names
|
||||
*/
|
||||
register(flatStyle) {
|
||||
const id = ReactNativePropRegistry.register(flatStyle);
|
||||
this._registerById(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
_registerById(id) {
|
||||
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
|
||||
if (!this.cache[dir][id]) {
|
||||
const style = flattenStyle(id);
|
||||
const domStyle = createReactDOMStyle(i18nStyle(style));
|
||||
Object.keys(domStyle).forEach(styleProp => {
|
||||
const value = domStyle[styleProp];
|
||||
if (value != null) {
|
||||
this.styleManager.setDeclaration(styleProp, value);
|
||||
}
|
||||
});
|
||||
this.cache[dir][id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a React Native style object to DOM attributes
|
||||
*/
|
||||
resolve(reactNativeStyle, options = emptyObject) {
|
||||
if (!reactNativeStyle) {
|
||||
return emptyObject;
|
||||
}
|
||||
|
||||
// fast and cachable
|
||||
if (typeof reactNativeStyle === 'number') {
|
||||
this._registerById(reactNativeStyle);
|
||||
const key = createCacheKey(reactNativeStyle);
|
||||
return this._resolveStyleIfNeeded(reactNativeStyle, options, key);
|
||||
}
|
||||
|
||||
// resolve a plain RN style object
|
||||
if (!Array.isArray(reactNativeStyle)) {
|
||||
return this._resolveStyle(reactNativeStyle, options);
|
||||
}
|
||||
|
||||
// flatten the style array
|
||||
// cache resolved props when all styles are registered
|
||||
// otherwise fallback to resolving
|
||||
const flatArray = flattenArray(reactNativeStyle);
|
||||
let isArrayOfNumbers = true;
|
||||
for (let i = 0; i < flatArray.length; i++) {
|
||||
const id = flatArray[i];
|
||||
if (typeof id !== 'number') {
|
||||
isArrayOfNumbers = false;
|
||||
} else {
|
||||
this._registerById(id);
|
||||
}
|
||||
}
|
||||
const key = isArrayOfNumbers ? createCacheKey(flatArray.join('-')) : null;
|
||||
return this._resolveStyleIfNeeded(flatArray, options, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a React Native style object to DOM attributes, accounting for
|
||||
* the existing styles applied to the DOM node.
|
||||
*
|
||||
* To determine the next style, some of the existing DOM state must be
|
||||
* converted back into React Native styles.
|
||||
*/
|
||||
resolveStateful(rnStyleNext, domStyleProps, options) {
|
||||
const { classList: rdomClassList, style: rdomStyle } = domStyleProps;
|
||||
|
||||
// Convert the DOM classList back into a React Native form
|
||||
// Preserves unrecognized class names.
|
||||
const { classList: rnClassList, style: rnStyle } = rdomClassList.reduce(
|
||||
(styleProps, className) => {
|
||||
const { prop, value } = this.styleManager.getDeclaration(className);
|
||||
if (prop) {
|
||||
styleProps.style[prop] = value;
|
||||
} else {
|
||||
styleProps.classList.push(className);
|
||||
}
|
||||
return styleProps;
|
||||
},
|
||||
{ classList: [], style: {} }
|
||||
);
|
||||
|
||||
// Create next DOM style props from current and next RN styles
|
||||
const { classList: rdomClassListNext, style: rdomStyleNext } = this.resolve(
|
||||
[rnStyle, rnStyleNext],
|
||||
options
|
||||
);
|
||||
|
||||
// Next class names take priority over current inline styles
|
||||
const style = { ...rdomStyle };
|
||||
rdomClassListNext.forEach(className => {
|
||||
const { prop } = this.styleManager.getDeclaration(className);
|
||||
if (style[prop]) {
|
||||
style[prop] = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Next inline styles take priority over current inline styles
|
||||
Object.assign(style, rdomStyleNext);
|
||||
|
||||
// Add the current class names not managed by React Native
|
||||
const className = classListToString(rdomClassListNext.concat(rnClassList));
|
||||
|
||||
return { className, style };
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a React Native style object
|
||||
*/
|
||||
_resolveStyle(reactNativeStyle, options) {
|
||||
const flatStyle = flattenStyle(reactNativeStyle);
|
||||
const domStyle = createReactDOMStyle(options.i18n === false ? flatStyle : i18nStyle(flatStyle));
|
||||
|
||||
const props = Object.keys(domStyle).reduce(
|
||||
(props, styleProp) => {
|
||||
const value = domStyle[styleProp];
|
||||
if (value != null) {
|
||||
const className = this.styleManager.getClassName(styleProp, value);
|
||||
if (className) {
|
||||
props.classList.push(className);
|
||||
} else {
|
||||
if (!props.style) {
|
||||
props.style = {};
|
||||
}
|
||||
// 4x slower render
|
||||
props.style[styleProp] = value;
|
||||
}
|
||||
}
|
||||
return props;
|
||||
},
|
||||
{ classList: [] }
|
||||
);
|
||||
|
||||
props.className = classListToString(props.classList);
|
||||
if (props.style) {
|
||||
props.style = prefixInlineStyles(props.style);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caching layer over 'resolveStyle'
|
||||
*/
|
||||
_resolveStyleIfNeeded(style, options, key) {
|
||||
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
|
||||
if (key) {
|
||||
if (!this.cache[dir][key]) {
|
||||
// slow: convert style object to props and cache
|
||||
this.cache[dir][key] = this._resolveStyle(style, options);
|
||||
}
|
||||
return this.cache[dir][key];
|
||||
}
|
||||
return this._resolveStyle(style, options);
|
||||
}
|
||||
}
|
||||
50
packages/react-native-web/src/exports/StyleSheet/StyleSheet.js
vendored
Normal file
50
packages/react-native-web/src/exports/StyleSheet/StyleSheet.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Nicolas Gallagher.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule StyleSheet
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
import flattenStyle from './flattenStyle';
|
||||
import getHairlineWidth from './getHairlineWidth';
|
||||
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
|
||||
|
||||
const absoluteFillObject = {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0
|
||||
};
|
||||
const absoluteFill = ReactNativePropRegistry.register(absoluteFillObject);
|
||||
|
||||
const StyleSheet = {
|
||||
absoluteFill,
|
||||
absoluteFillObject,
|
||||
compose(style1, style2) {
|
||||
if (style1 && style2) {
|
||||
return [style1, style2];
|
||||
} else {
|
||||
return style1 || style2;
|
||||
}
|
||||
},
|
||||
create(styles) {
|
||||
const result = {};
|
||||
Object.keys(styles).forEach(key => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const StyleSheetValidation = require('./StyleSheetValidation').default;
|
||||
StyleSheetValidation.validateStyle(key, styles);
|
||||
}
|
||||
const id = styles[key] && ReactNativePropRegistry.register(styles[key]);
|
||||
result[key] = id;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
flatten: flattenStyle,
|
||||
hairlineWidth: getHairlineWidth()
|
||||
};
|
||||
|
||||
export default StyleSheet;
|
||||
84
packages/react-native-web/src/exports/StyleSheet/StyleSheetManager.js
vendored
Normal file
84
packages/react-native-web/src/exports/StyleSheet/StyleSheetManager.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Nicolas Gallagher.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
import createAtomicRules from './createAtomicRules';
|
||||
import hash from '../../vendor/hash';
|
||||
import initialRules from './initialRules';
|
||||
import WebStyleSheet from './WebStyleSheet';
|
||||
|
||||
const emptyObject = {};
|
||||
const STYLE_ELEMENT_ID = 'react-native-stylesheet';
|
||||
|
||||
const createClassName = (prop, value) => {
|
||||
const hashed = hash(prop + normalizeValue(value));
|
||||
return process.env.NODE_ENV !== 'production' ? `rn-${prop}-${hashed}` : `rn-${hashed}`;
|
||||
};
|
||||
|
||||
const normalizeValue = value => (typeof value === 'object' ? JSON.stringify(value) : value);
|
||||
|
||||
export default class StyleSheetManager {
|
||||
_cache = {
|
||||
byClassName: {},
|
||||
byProp: {}
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this._sheet = new WebStyleSheet(STYLE_ELEMENT_ID);
|
||||
initialRules.forEach(rule => {
|
||||
this._sheet.insertRuleOnce(rule);
|
||||
});
|
||||
}
|
||||
|
||||
getClassName(prop, value) {
|
||||
const val = normalizeValue(value);
|
||||
const cache = this._cache.byProp;
|
||||
return cache[prop] && cache[prop].hasOwnProperty(val) && cache[prop][val];
|
||||
}
|
||||
|
||||
getDeclaration(className) {
|
||||
const cache = this._cache.byClassName;
|
||||
return cache[className] || emptyObject;
|
||||
}
|
||||
|
||||
getStyleSheet() {
|
||||
const { cssText } = this._sheet;
|
||||
|
||||
return {
|
||||
id: STYLE_ELEMENT_ID,
|
||||
textContent: cssText
|
||||
};
|
||||
}
|
||||
|
||||
injectDeclaration(prop, value): string {
|
||||
const val = normalizeValue(value);
|
||||
let className = this.getClassName(prop, val);
|
||||
if (!className) {
|
||||
className = createClassName(prop, val);
|
||||
this._addToCache(className, prop, val);
|
||||
const rules = createAtomicRules(`.${className}`, prop, value);
|
||||
rules.forEach(rule => {
|
||||
this._sheet.insertRuleOnce(rule);
|
||||
});
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
injectKeyframe(): string {
|
||||
// return identifier;
|
||||
}
|
||||
|
||||
_addToCache(className, prop, value) {
|
||||
const cache = this._cache;
|
||||
if (!cache.byProp[prop]) {
|
||||
cache.byProp[prop] = {};
|
||||
}
|
||||
cache.byProp[prop][value] = className;
|
||||
cache.byClassName[className] = { prop, value };
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
* @providesModule StyleSheetValidation
|
||||
@@ -26,6 +25,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 +36,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,9 +99,10 @@ StyleSheetValidation.addValidStylePropTypes({
|
||||
clear: string,
|
||||
cursor: string,
|
||||
fill: string,
|
||||
float: oneOf(['left', 'none', 'right']),
|
||||
font: string /* @private */,
|
||||
float: oneOf(['end', 'left', 'none', 'right', 'start']),
|
||||
listStyle: string,
|
||||
pointerEvents: string,
|
||||
tableLayout: string
|
||||
tableLayout: string,
|
||||
/* @private */
|
||||
MozAppearance: string
|
||||
});
|
||||
|
||||
60
packages/react-native-web/src/exports/StyleSheet/WebStyleSheet.js
vendored
Normal file
60
packages/react-native-web/src/exports/StyleSheet/WebStyleSheet.js
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Nicolas Gallagher.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
|
||||
export default class WebStyleSheet {
|
||||
_cssRules = [];
|
||||
_sheet = null;
|
||||
_textContent = '';
|
||||
|
||||
constructor(id: string) {
|
||||
let domStyleElement;
|
||||
|
||||
// on the client we check for an existing style sheet before injecting
|
||||
if (canUseDOM) {
|
||||
domStyleElement = document.getElementById(id);
|
||||
if (!domStyleElement) {
|
||||
const html = `<style id="${id}"></style>`;
|
||||
if (document.head) {
|
||||
document.head.insertAdjacentHTML('afterbegin', html);
|
||||
domStyleElement = document.getElementById(id);
|
||||
}
|
||||
}
|
||||
|
||||
if (domStyleElement) {
|
||||
// $FlowFixMe
|
||||
this._sheet = domStyleElement.sheet;
|
||||
this._textContent = domStyleElement.textContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
containsRule(rule: string): boolean {
|
||||
return this._cssRules.indexOf(rule) > -1;
|
||||
}
|
||||
|
||||
get cssText(): string {
|
||||
return this._cssRules.join('\n');
|
||||
}
|
||||
|
||||
insertRuleOnce(rule: string, position: ?number) {
|
||||
// Reduce chance of duplicate rules
|
||||
if (!this.containsRule(rule)) {
|
||||
this._cssRules.push(rule);
|
||||
|
||||
// Check whether a rule was part of any prerendered styles (textContent
|
||||
// doesn't include styles injected via 'insertRule')
|
||||
if (this._textContent.indexOf(rule) === -1 && this._sheet) {
|
||||
const pos = position || this._sheet.cssRules.length;
|
||||
this._sheet.insertRule(rule, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
147
packages/react-native-web/src/exports/StyleSheet/__tests__/ReactNativeStyleResolver-test.js
vendored
Normal file
147
packages/react-native-web/src/exports/StyleSheet/__tests__/ReactNativeStyleResolver-test.js
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import I18nManager from '../../I18nManager';
|
||||
import ReactNativePropRegistry from '../../../modules/ReactNativePropRegistry';
|
||||
import ReactNativeStyleResolver from '../ReactNativeStyleResolver';
|
||||
|
||||
let styleResolver;
|
||||
|
||||
describe('StyleSheet/ReactNativeStyleResolver', () => {
|
||||
beforeEach(() => {
|
||||
styleResolver = new ReactNativeStyleResolver();
|
||||
});
|
||||
|
||||
describe('resolve', () => {
|
||||
const styleA = { borderWidth: 0, borderColor: 'red', width: 100 };
|
||||
const styleB = {
|
||||
position: 'absolute',
|
||||
left: 50,
|
||||
opacity: 0.5
|
||||
};
|
||||
const styleC = { width: 200 };
|
||||
|
||||
const testResolve = (a, b, c) => {
|
||||
// no common properties, different resolving order, same result
|
||||
const resolve1 = styleResolver.resolve([a, b]);
|
||||
expect(resolve1).toMatchSnapshot();
|
||||
const resolve2 = styleResolver.resolve([b, a]);
|
||||
expect(resolve1).toEqual(resolve2);
|
||||
|
||||
// common properties, different resolving order, different result
|
||||
const resolve3 = styleResolver.resolve([a, b, c]);
|
||||
expect(resolve3).toMatchSnapshot();
|
||||
const resolve4 = styleResolver.resolve([c, a, b]);
|
||||
expect(resolve4).toMatchSnapshot();
|
||||
expect(resolve3).not.toEqual(resolve4);
|
||||
};
|
||||
|
||||
test('with register, resolves to className', () => {
|
||||
const a = ReactNativePropRegistry.register(styleA);
|
||||
const b = ReactNativePropRegistry.register(styleB);
|
||||
const c = ReactNativePropRegistry.register(styleC);
|
||||
testResolve(a, b, c);
|
||||
});
|
||||
|
||||
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 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);
|
||||
});
|
||||
|
||||
test('with register, resolves to mixed', () => {
|
||||
const a = styleA;
|
||||
const b = ReactNativePropRegistry.register(styleB);
|
||||
const c = ReactNativePropRegistry.register(styleC);
|
||||
testResolve(a, b, c);
|
||||
});
|
||||
|
||||
test('without register, resolves to inline styles', () => {
|
||||
testResolve(styleA, styleB, styleC);
|
||||
});
|
||||
|
||||
test('resolves inline-style pointerEvents to classname', () => {
|
||||
expect(styleResolver.resolve({ pointerEvents: 'box-none' })).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveWithNode', () => {
|
||||
let node;
|
||||
|
||||
beforeEach(() => {
|
||||
node = document.createElement('div');
|
||||
});
|
||||
|
||||
test('preserves unrelated class names', () => {
|
||||
node.classList.add('unknown-class-1', 'unknown-class-2');
|
||||
const resolved = styleResolver.resolveWithNode({}, node);
|
||||
expect(resolved).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('preserves unrelated inline styles', () => {
|
||||
node.style.cssText = 'font-size: 20px;';
|
||||
const resolved = styleResolver.resolveWithNode({ opacity: 1 }, node);
|
||||
expect(resolved).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('next class names have priority over current inline styles', () => {
|
||||
node.style.cssText = 'opacity: 0.5;';
|
||||
const nextStyle = ReactNativePropRegistry.register({ opacity: 1 });
|
||||
const resolved = styleResolver.resolveWithNode(nextStyle, node);
|
||||
expect(resolved).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('next inline styles have priority over current inline styles', () => {
|
||||
// note: this also checks for correctly uppercasing the first letter of DOM vendor prefixes
|
||||
node.style.cssText = 'opacity: 0.5; transform: scale(1);';
|
||||
const style = { opacity: 1, transform: [{ scale: 2 }] };
|
||||
const resolved = styleResolver.resolveWithNode(style, node);
|
||||
expect(resolved).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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);
|
||||
const resolved = styleResolver.resolveWithNode({ marginLeft: 10, right: 10 }, node);
|
||||
I18nManager.forceRTL(false);
|
||||
expect(resolved).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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 });
|
||||
|
||||
I18nManager.forceRTL(true);
|
||||
const resolved = styleResolver.resolveWithNode(nextStyle, node);
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,39 +0,0 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import StyleManager from '../StyleManager';
|
||||
|
||||
let styleManager;
|
||||
|
||||
describe('apis/StyleSheet/StyleManager', () => {
|
||||
beforeEach(() => {
|
||||
styleManager = new StyleManager();
|
||||
});
|
||||
|
||||
test('getClassName', () => {
|
||||
expect(styleManager.getClassName('pointerEvents', 'box-only')).toMatchSnapshot();
|
||||
const className = styleManager.setDeclaration('width', '100px');
|
||||
expect(styleManager.getClassName('width', '100px')).toEqual(className);
|
||||
});
|
||||
|
||||
test('getDeclaration', () => {
|
||||
const className = styleManager.setDeclaration('width', '100px');
|
||||
expect(styleManager.getDeclaration(className)).toEqual({
|
||||
prop: 'width',
|
||||
value: '100px'
|
||||
});
|
||||
});
|
||||
|
||||
test('getStyleSheetHtml', () => {
|
||||
expect(styleManager.getStyleSheetHtml()).toMatchSnapshot();
|
||||
styleManager.setDeclaration('width', '100px');
|
||||
expect(styleManager.getStyleSheetHtml()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('setDeclaration', () => {
|
||||
styleManager.mainSheet.sheet.insertRule = (rule, position) => {
|
||||
// check for regressions in CSS write path (e.g., 0 => 0px)
|
||||
expect(rule.indexOf('-webkit-flex-shrink:0;')).not.toEqual(-1);
|
||||
};
|
||||
styleManager.setDeclaration('flexShrink', 0);
|
||||
});
|
||||
});
|
||||
@@ -1,105 +0,0 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import I18nManager from '../../I18nManager';
|
||||
import StyleRegistry from '../StyleRegistry';
|
||||
|
||||
let styleRegistry;
|
||||
|
||||
describe('apis/StyleSheet/StyleRegistry', () => {
|
||||
beforeEach(() => {
|
||||
styleRegistry = new StyleRegistry();
|
||||
});
|
||||
|
||||
test('register', () => {
|
||||
const style = { opacity: 0 };
|
||||
const id = styleRegistry.register(style);
|
||||
expect(typeof id === 'number').toBe(true);
|
||||
});
|
||||
|
||||
describe('resolve', () => {
|
||||
const styleA = { borderWidth: 0, borderColor: 'red', width: 100 };
|
||||
const styleB = {
|
||||
position: 'absolute',
|
||||
left: 50,
|
||||
pointerEvents: 'box-only'
|
||||
};
|
||||
const styleC = { width: 200 };
|
||||
|
||||
const testResolve = (a, b, c) => {
|
||||
// no common properties, different resolving order, same result
|
||||
const resolve1 = styleRegistry.resolve([a, b]);
|
||||
expect(resolve1).toMatchSnapshot();
|
||||
const resolve2 = styleRegistry.resolve([b, a]);
|
||||
expect(resolve1).toEqual(resolve2);
|
||||
|
||||
// common properties, different resolving order, different result
|
||||
const resolve3 = styleRegistry.resolve([a, b, c]);
|
||||
expect(resolve3).toMatchSnapshot();
|
||||
const resolve4 = styleRegistry.resolve([c, a, b]);
|
||||
expect(resolve4).toMatchSnapshot();
|
||||
expect(resolve3).not.toEqual(resolve4);
|
||||
};
|
||||
|
||||
test('with register, resolves to className', () => {
|
||||
const a = styleRegistry.register(styleA);
|
||||
const b = styleRegistry.register(styleB);
|
||||
const c = styleRegistry.register(styleC);
|
||||
testResolve(a, b, c);
|
||||
});
|
||||
|
||||
test('with register before RTL, resolves to className', () => {
|
||||
const a = styleRegistry.register({ left: '12.34%' });
|
||||
const b = styleRegistry.register({ textAlign: 'left' });
|
||||
const c = styleRegistry.register({ marginLeft: 10 });
|
||||
I18nManager.forceRTL(true);
|
||||
const resolved = styleRegistry.resolve([a, b, c]);
|
||||
I18nManager.forceRTL(false);
|
||||
expect(resolved).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('with register, resolves to mixed', () => {
|
||||
const a = styleA;
|
||||
const b = styleRegistry.register(styleB);
|
||||
const c = styleRegistry.register(styleC);
|
||||
testResolve(a, b, c);
|
||||
});
|
||||
|
||||
test('without register, resolves to inline styles', () => {
|
||||
testResolve(styleA, styleB, styleC);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveStateful', () => {
|
||||
test('preserves unrelated class names', () => {
|
||||
const domStyleProps = { classList: ['unknown-class-1', 'unknown-class-2'], style: {} };
|
||||
const domStyleNextProps = styleRegistry.resolveStateful({}, domStyleProps);
|
||||
expect(domStyleNextProps).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('preserves unrelated inline styles', () => {
|
||||
const domStyleProps = { classList: [], style: { fontSize: '20px' } };
|
||||
const domStyleNextProps = styleRegistry.resolveStateful({ opacity: 1 }, domStyleProps);
|
||||
expect(domStyleNextProps).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('next class names have priority over current inline styles', () => {
|
||||
const domStyleProps = { classList: [], style: { opacity: 0.5 } };
|
||||
const nextStyle = styleRegistry.register({ opacity: 1 });
|
||||
const domStyleNextProps = styleRegistry.resolveStateful(nextStyle, domStyleProps);
|
||||
expect(domStyleNextProps).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('next inline styles have priority over current inline styles', () => {
|
||||
// note: this also checks for correctly uppercasing the first letter of DOM vendor prefixes
|
||||
const domStyleProps = {
|
||||
classList: [],
|
||||
style: { opacity: 0.5, WebkitTransform: 'scale(1)', transform: 'scale(1)' }
|
||||
};
|
||||
const domStyleNextProps = styleRegistry.resolveStateful(
|
||||
{ opacity: 1, transform: [{ scale: 2 }] },
|
||||
domStyleProps
|
||||
);
|
||||
expect(domStyleNextProps).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
38
packages/react-native-web/src/exports/StyleSheet/__tests__/StyleSheetManager-test.js
vendored
Normal file
38
packages/react-native-web/src/exports/StyleSheet/__tests__/StyleSheetManager-test.js
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import StyleSheetManager from '../StyleSheetManager';
|
||||
|
||||
let styleSheetManager;
|
||||
|
||||
describe('StyleSheet/StyleSheetManager', () => {
|
||||
beforeEach(() => {
|
||||
styleSheetManager = new StyleSheetManager();
|
||||
});
|
||||
|
||||
test('getClassName', () => {
|
||||
expect(styleSheetManager.getClassName('pointerEvents', 'box-only')).toMatchSnapshot();
|
||||
const className = styleSheetManager.injectDeclaration('width', '100px');
|
||||
expect(styleSheetManager.getClassName('width', '100px')).toEqual(className);
|
||||
});
|
||||
|
||||
test('getDeclaration', () => {
|
||||
const className = styleSheetManager.injectDeclaration('width', '100px');
|
||||
expect(styleSheetManager.getDeclaration(className)).toEqual({
|
||||
prop: 'width',
|
||||
value: '100px'
|
||||
});
|
||||
});
|
||||
|
||||
test('getStyleSheet', () => {
|
||||
styleSheetManager.injectDeclaration('--test-property', 'test-value');
|
||||
expect(styleSheetManager.getStyleSheet()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('injectDeclaration', () => {
|
||||
styleSheetManager._sheet.insertRuleOnce = (rule, position) => {
|
||||
// check for regressions in CSS write path (e.g., 0 => 0px)
|
||||
expect(rule.indexOf('-webkit-flex-shrink:0;')).not.toEqual(-1);
|
||||
};
|
||||
styleSheetManager.injectDeclaration('flexShrink', 0);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,15 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register before RTL, resolves to className 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve resolves inline-style pointerEvents to classname 1`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-pointerEvents-12vffkv",
|
||||
],
|
||||
"className": "rn-pointerEvents-12vffkv",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register before RTL, resolves to correct className 1`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-marginRight-zso239",
|
||||
@@ -11,27 +20,18 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to className 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register before RTL, resolves to correct className 2`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-borderTopColor-1gxhl28",
|
||||
"rn-borderRightColor-knoah9",
|
||||
"rn-borderBottomColor-1ani3fp",
|
||||
"rn-borderLeftColor-ribj9x",
|
||||
"rn-borderTopWidth-13yce4e",
|
||||
"rn-borderRightWidth-fnigne",
|
||||
"rn-borderBottomWidth-ndvcnb",
|
||||
"rn-borderLeftWidth-gxnn5r",
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
"rn-position-u8s1d",
|
||||
"rn-width-b8lwoo",
|
||||
"rn-left-2s0hu9",
|
||||
"rn-marginLeft-1n0xq6e",
|
||||
"rn-textAlign-fdjqy7",
|
||||
],
|
||||
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-b8lwoo",
|
||||
"className": "rn-left-2s0hu9 rn-marginLeft-1n0xq6e rn-textAlign-fdjqy7",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to className 2`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to className 1`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-borderTopColor-1gxhl28",
|
||||
@@ -43,15 +43,35 @@ Object {
|
||||
"rn-borderBottomWidth-ndvcnb",
|
||||
"rn-borderLeftWidth-gxnn5r",
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
"rn-opacity-icoktb",
|
||||
"rn-position-u8s1d",
|
||||
"rn-width-b8lwoo",
|
||||
],
|
||||
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-opacity-icoktb rn-position-u8s1d rn-width-b8lwoo",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to className 2`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-borderTopColor-1gxhl28",
|
||||
"rn-borderRightColor-knoah9",
|
||||
"rn-borderBottomColor-1ani3fp",
|
||||
"rn-borderLeftColor-ribj9x",
|
||||
"rn-borderTopWidth-13yce4e",
|
||||
"rn-borderRightWidth-fnigne",
|
||||
"rn-borderBottomWidth-ndvcnb",
|
||||
"rn-borderLeftWidth-gxnn5r",
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-opacity-icoktb",
|
||||
"rn-position-u8s1d",
|
||||
"rn-width-l0gwng",
|
||||
],
|
||||
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-l0gwng",
|
||||
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-opacity-icoktb rn-position-u8s1d rn-width-l0gwng",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to className 3`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to className 3`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-borderTopColor-1gxhl28",
|
||||
@@ -63,22 +83,22 @@ Object {
|
||||
"rn-borderBottomWidth-ndvcnb",
|
||||
"rn-borderLeftWidth-gxnn5r",
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
"rn-opacity-icoktb",
|
||||
"rn-position-u8s1d",
|
||||
"rn-width-b8lwoo",
|
||||
],
|
||||
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-b8lwoo",
|
||||
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-opacity-icoktb rn-position-u8s1d rn-width-b8lwoo",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to mixed 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to mixed 1`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
"rn-opacity-icoktb",
|
||||
"rn-position-u8s1d",
|
||||
],
|
||||
"className": "rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d",
|
||||
"className": "rn-left-1tsx3h3 rn-opacity-icoktb rn-position-u8s1d",
|
||||
"style": Object {
|
||||
"borderBottomColor": "red",
|
||||
"borderBottomWidth": "0px",
|
||||
@@ -93,15 +113,15 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to mixed 2`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to mixed 2`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
"rn-opacity-icoktb",
|
||||
"rn-position-u8s1d",
|
||||
"rn-width-l0gwng",
|
||||
],
|
||||
"className": "rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-l0gwng",
|
||||
"className": "rn-left-1tsx3h3 rn-opacity-icoktb rn-position-u8s1d rn-width-l0gwng",
|
||||
"style": Object {
|
||||
"borderBottomColor": "red",
|
||||
"borderBottomWidth": "0px",
|
||||
@@ -115,14 +135,14 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to mixed 3`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve with register, resolves to mixed 3`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-left-1tsx3h3",
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
"rn-opacity-icoktb",
|
||||
"rn-position-u8s1d",
|
||||
],
|
||||
"className": "rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d",
|
||||
"className": "rn-left-1tsx3h3 rn-opacity-icoktb rn-position-u8s1d",
|
||||
"style": Object {
|
||||
"borderBottomColor": "red",
|
||||
"borderBottomWidth": "0px",
|
||||
@@ -137,12 +157,10 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve without register, resolves to inline styles 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve without register, resolves to inline styles 1`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
],
|
||||
"className": "rn-pointerEvents-ah5dr5",
|
||||
"classList": Array [],
|
||||
"className": "",
|
||||
"style": Object {
|
||||
"borderBottomColor": "red",
|
||||
"borderBottomWidth": "0px",
|
||||
@@ -153,18 +171,17 @@ Object {
|
||||
"borderTopColor": "red",
|
||||
"borderTopWidth": "0px",
|
||||
"left": "50px",
|
||||
"opacity": 0.5,
|
||||
"position": "absolute",
|
||||
"width": "100px",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve without register, resolves to inline styles 2`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve without register, resolves to inline styles 2`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
],
|
||||
"className": "rn-pointerEvents-ah5dr5",
|
||||
"classList": Array [],
|
||||
"className": "",
|
||||
"style": Object {
|
||||
"borderBottomColor": "red",
|
||||
"borderBottomWidth": "0px",
|
||||
@@ -175,18 +192,17 @@ Object {
|
||||
"borderTopColor": "red",
|
||||
"borderTopWidth": "0px",
|
||||
"left": "50px",
|
||||
"opacity": 0.5,
|
||||
"position": "absolute",
|
||||
"width": "200px",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolve without register, resolves to inline styles 3`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolve without register, resolves to inline styles 3`] = `
|
||||
Object {
|
||||
"classList": Array [
|
||||
"rn-pointerEvents-ah5dr5",
|
||||
],
|
||||
"className": "rn-pointerEvents-ah5dr5",
|
||||
"classList": Array [],
|
||||
"className": "",
|
||||
"style": Object {
|
||||
"borderBottomColor": "red",
|
||||
"borderBottomWidth": "0px",
|
||||
@@ -197,13 +213,14 @@ Object {
|
||||
"borderTopColor": "red",
|
||||
"borderTopWidth": "0px",
|
||||
"left": "50px",
|
||||
"opacity": 0.5,
|
||||
"position": "absolute",
|
||||
"width": "100px",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolveStateful next class names have priority over current inline styles 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode next class names have priority over current inline styles 1`] = `
|
||||
Object {
|
||||
"className": "rn-opacity-6dt33c",
|
||||
"style": Object {
|
||||
@@ -212,7 +229,7 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolveStateful next inline styles have priority over current inline styles 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode next inline styles have priority over current inline styles 1`] = `
|
||||
Object {
|
||||
"className": "",
|
||||
"style": Object {
|
||||
@@ -223,14 +240,14 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolveStateful preserves unrelated class names 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode preserves unrelated class names 1`] = `
|
||||
Object {
|
||||
"className": "unknown-class-1 unknown-class-2",
|
||||
"style": Object {},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleRegistry resolveStateful preserves unrelated inline styles 1`] = `
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode preserves unrelated inline styles 1`] = `
|
||||
Object {
|
||||
"className": "",
|
||||
"style": Object {
|
||||
@@ -239,3 +256,35 @@ Object {
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
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 {
|
||||
"marginRight": "",
|
||||
"right": "5px",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`StyleSheet/ReactNativeStyleResolver resolveWithNode when isRTL=true, resolves to flipped inline styles 1`] = `
|
||||
Object {
|
||||
"className": "",
|
||||
"style": Object {
|
||||
"left": "10px",
|
||||
"marginRight": "10px",
|
||||
"right": "5px",
|
||||
},
|
||||
}
|
||||
`;
|
||||
@@ -1,43 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/StyleSheet/StyleManager getClassName 1`] = `"rn-pointerEvents-ah5dr5"`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleManager getStyleSheetHtml 1`] = `
|
||||
"<style id=\\"react-native-stylesheet-static\\">
|
||||
html{font-family:sans-serif;-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;}
|
||||
@keyframes rn-ActivityIndicator-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg);}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg);}}
|
||||
@keyframes rn-ProgressBar-animation{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);}100%{-webkit-transform:translateX(400%);transform:translateX(400%);}}
|
||||
.rn-pointerEvents-105ug2t{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-ah5dr5{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-633pao{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv > *{pointer-events:auto;}
|
||||
.rn-pointerEvents-ah5dr5 > *{pointer-events:none;}
|
||||
</style>
|
||||
<style id=\\"react-native-stylesheet\\">
|
||||
|
||||
</style>"
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/StyleManager getStyleSheetHtml 2`] = `
|
||||
"<style id=\\"react-native-stylesheet-static\\">
|
||||
html{font-family:sans-serif;-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;}
|
||||
@keyframes rn-ActivityIndicator-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg);}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg);}}
|
||||
@keyframes rn-ProgressBar-animation{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);}100%{-webkit-transform:translateX(400%);transform:translateX(400%);}}
|
||||
.rn-pointerEvents-105ug2t{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-ah5dr5{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-633pao{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv > *{pointer-events:auto;}
|
||||
.rn-pointerEvents-ah5dr5 > *{pointer-events:none;}
|
||||
</style>
|
||||
<style id=\\"react-native-stylesheet\\">
|
||||
.rn-width-b8lwoo{width:100px}
|
||||
</style>"
|
||||
`;
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`StyleSheet/StyleSheetManager getClassName 1`] = `undefined`;
|
||||
|
||||
exports[`StyleSheet/StyleSheetManager getStyleSheet 1`] = `
|
||||
Object {
|
||||
"id": "react-native-stylesheet",
|
||||
"textContent": "@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;}
|
||||
}
|
||||
.rn---test-property-ax3bxi{--test-property:test-value}",
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,30 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`StyleSheet/createAtomicRules transforms custom "animationName" declaration 1`] = `
|
||||
Array [
|
||||
"@media all {@-webkit-keyframes rn-anim-2k74q5{0%{top:0px}50%{top:5px}100%{top:10px}}}",
|
||||
"@media all {@keyframes rn-anim-2k74q5{0%{top:0px}50%{top:5px}100%{top:10px}}}",
|
||||
"@media all {@-webkit-keyframes rn-anim-zc91cv{from{left:0px}to{left:10px}}}",
|
||||
"@media all {@keyframes rn-anim-zc91cv{from{left:0px}to{left:10px}}}",
|
||||
".test{-webkit-animation-name:rn-anim-2k74q5,rn-anim-zc91cv;animation-name:rn-anim-2k74q5,rn-anim-zc91cv}",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`StyleSheet/createAtomicRules transforms custom "placeholderTextColor" declaration 1`] = `
|
||||
Array [
|
||||
"@media all {.test::-webkit-input-placeholder{color:gray;opacity:1}.test::-moz-placeholder{color:gray;opacity:1}.test:-ms-input-placeholder{color:gray;opacity:1}.test::placeholder{color:gray;opacity:1}}",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`StyleSheet/createAtomicRules transforms custom "pointerEvents" declaration 1`] = `
|
||||
Array [
|
||||
".test > *{pointer-events:none}",
|
||||
".test{pointer-events:auto !important}",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`StyleSheet/createAtomicRules transforms standard declarations to a single rule 1`] = `
|
||||
Array [
|
||||
".test{margin:0px}",
|
||||
]
|
||||
`;
|
||||
@@ -1,24 +1,30 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/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[`apis/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",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/createReactDOMStyle fontFamily general case 1`] = `
|
||||
exports[`StyleSheet/createReactDOMStyle fontFamily general case 1`] = `
|
||||
Object {
|
||||
"fontFamily": "Georgia, Times, serif",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/createReactDOMStyle shortform -> longform 1`] = `
|
||||
exports[`StyleSheet/createReactDOMStyle shortform -> longform 1`] = `
|
||||
Object {
|
||||
"borderBottomColor": "white",
|
||||
"borderBottomStyle": "solid",
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`StyleSheet/createRuleBlock generates correct css 1`] = `"-webkit-transition-duration:0.1s;border-width-left:2px;border-width-right:3px;box-shadow:1px 1px 1px 1px #000;position:absolute;transition-duration:0.1s"`;
|
||||
@@ -1,26 +1,26 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/StyleSheet/flattenStyle should merge style objects 1`] = `
|
||||
exports[`StyleSheet/flattenStyle should merge style objects 1`] = `
|
||||
Object {
|
||||
"opacity": 1,
|
||||
"order": 2,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/flattenStyle should override style properties 1`] = `
|
||||
exports[`StyleSheet/flattenStyle should override style properties 1`] = `
|
||||
Object {
|
||||
"backgroundColor": "#023c69",
|
||||
"order": null,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/flattenStyle should overwrite properties with \`undefined\` 1`] = `
|
||||
exports[`StyleSheet/flattenStyle should overwrite properties with \`undefined\` 1`] = `
|
||||
Object {
|
||||
"backgroundColor": undefined,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/flattenStyle should recursively flatten arrays 1`] = `
|
||||
exports[`StyleSheet/flattenStyle should recursively flatten arrays 1`] = `
|
||||
Object {
|
||||
"opacity": 1,
|
||||
"order": 3,
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/StyleSheet/generateCss generates correct css 1`] = `"-webkit-transition-duration:0.1s;border-width-left:2px;border-width-right:3px;box-shadow:1px 1px 1px 1px #000;position:absolute;transition-duration:0.1s"`;
|
||||
@@ -1,53 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/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[`apis/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",
|
||||
},
|
||||
}
|
||||
`;
|
||||
@@ -1,185 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`apis/StyleSheet getStyleSheets 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"id": "react-native-stylesheet-static",
|
||||
"textContent": "html{font-family:sans-serif;-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;}
|
||||
@keyframes rn-ActivityIndicator-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg);}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg);}}
|
||||
@keyframes rn-ProgressBar-animation{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);}100%{-webkit-transform:translateX(400%);transform:translateX(400%);}}
|
||||
.rn-pointerEvents-105ug2t{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-ah5dr5{pointer-events:auto !important;}
|
||||
.rn-pointerEvents-633pao{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv{pointer-events:none !important;}
|
||||
.rn-pointerEvents-12vffkv > *{pointer-events:auto;}
|
||||
.rn-pointerEvents-ah5dr5 > *{pointer-events:none;}",
|
||||
},
|
||||
Object {
|
||||
"id": "react-native-stylesheet",
|
||||
"textContent": ".rn-bottom-1p0dtai{bottom:0px}
|
||||
.rn-left-1d2f490{left:0px}
|
||||
.rn-left-1fe0xdi{left:0%}
|
||||
.rn-left-7b7h2f{left:100%}
|
||||
.rn-position-u8s1d{position:absolute}
|
||||
.rn-position-bnwqim{position:relative}
|
||||
.rn-right-zchlnj{right:0px}
|
||||
.rn-top-ipm5af{top:0px}
|
||||
.rn-cursor-1loqt21{cursor:pointer}
|
||||
.rn-cursor-7q8q6z{cursor:default}
|
||||
.rn-cursor-1ei5mc7{cursor:inherit}
|
||||
.rn-appearance-30o5oe{-moz-appearance:none;-webkit-appearance:none;appearance:none}
|
||||
.rn-backgroundColor-wib322{background-color:transparent}
|
||||
.rn-backgroundColor-8ndhhv{background-color:rgba(33,150,243,1)}
|
||||
.rn-backgroundColor-15al3ab{background-color:rgba(223,223,223,1)}
|
||||
.rn-backgroundColor-44z8sh{background-color:rgba(255,255,255,1)}
|
||||
.rn-backgroundColor-5itogg{background-color:rgba(0,150,136,1)}
|
||||
.rn-backgroundColor-1v82r4u{background-color:rgba(170,184,194,1)}
|
||||
.rn-backgroundColor-1hj8efq{background-color:rgba(213,213,213,1)}
|
||||
.rn-backgroundColor-1bgzomc{background-color:rgba(189,189,189,1)}
|
||||
.rn-color-homxoj{color:inherit}
|
||||
.rn-color-1qtguxu{color:rgba(255,255,255,1)}
|
||||
.rn-color-istcb5{color:rgba(161,161,161,1)}
|
||||
.rn-font-1lw9tu2{font:inherit}
|
||||
.rn-textAlign-1ttztb7{text-align:inherit}
|
||||
.rn-textAlign-q4m81j{text-align:center}
|
||||
.rn-textDecoration-bauka4{text-decoration:none}
|
||||
.rn-listStyle-1ebb2ja{list-style:none}
|
||||
.rn-alignItems-1oszu61{-ms-flex-align:stretch;-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
|
||||
.rn-alignItems-1awozwy{-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center}
|
||||
.rn-borderTopStyle-1efd50x{border-top-style:solid}
|
||||
.rn-borderRightStyle-14skgim{border-right-style:solid}
|
||||
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
|
||||
.rn-borderLeftStyle-mm0ijv{border-left-style:solid}
|
||||
.rn-borderTopWidth-13yce4e{border-top-width:0px}
|
||||
.rn-borderTopWidth-1jxfwug{border-top-width:2px}
|
||||
.rn-borderRightWidth-fnigne{border-right-width:0px}
|
||||
.rn-borderRightWidth-18p6if4{border-right-width:2px}
|
||||
.rn-borderBottomWidth-ndvcnb{border-bottom-width:0px}
|
||||
.rn-borderBottomWidth-wgabs5{border-bottom-width:2px}
|
||||
.rn-borderLeftWidth-gxnn5r{border-left-width:0px}
|
||||
.rn-borderLeftWidth-dwliz8{border-left-width:2px}
|
||||
.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-display-xoduu5{display:-webkit-inline-box;display:-moz-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}
|
||||
.rn-display-1471scf{display:inline}
|
||||
.rn-flexShrink-1pxmb3b{-ms-flex-negative:0 !important;-webkit-flex-shrink:0 !important;flex-shrink:0 !important}
|
||||
.rn-flexShrink-1awmn5t{-ms-flex-negative:1 !important;-webkit-flex-shrink:1 !important;flex-shrink:1 !important}
|
||||
.rn-flexBasis-7vfszb{-ms-flex-preferred-size:auto !important;-webkit-flex-basis:auto !important;flex-basis:auto !important}
|
||||
.rn-flexDirection-eqz5dr{-ms-flex-direction:column;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
|
||||
.rn-flexDirection-18u37iz{-ms-flex-direction:row;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;flex-direction:row}
|
||||
.rn-marginTop-1mnahxq{margin-top:0px}
|
||||
.rn-marginTop-1t01tom{margin-top:auto}
|
||||
.rn-marginRight-61z16t{margin-right:0px}
|
||||
.rn-marginRight-lchren{margin-right:auto}
|
||||
.rn-marginBottom-p1pxzi{margin-bottom:0px}
|
||||
.rn-marginBottom-1qahzrx{margin-bottom:auto}
|
||||
.rn-marginLeft-11wrixw{margin-left:0px}
|
||||
.rn-marginLeft-1jj8364{margin-left:auto}
|
||||
.rn-minHeight-ifefl9{min-height:0px}
|
||||
.rn-minWidth-bcqeeo{min-width:0px}
|
||||
.rn-paddingTop-wk8lta{padding-top:0px}
|
||||
.rn-paddingTop-tskmnb{padding-top:8px}
|
||||
.rn-paddingRight-9aemit{padding-right:0px}
|
||||
.rn-paddingRight-1pyaxff{padding-right:8px}
|
||||
.rn-paddingBottom-1mdbw0j{padding-bottom:0px}
|
||||
.rn-paddingBottom-xd6kpl{padding-bottom:8px}
|
||||
.rn-paddingLeft-gy4na3{padding-left:0px}
|
||||
.rn-paddingLeft-1m04atk{padding-left:8px}
|
||||
.rn-zIndex-1lgpqti{z-index:0}
|
||||
.rn-zIndex-1wyyakw{z-index:-1}
|
||||
.rn-backgroundPosition-vvn4in{background-position:center}
|
||||
.rn-backgroundRepeat-u6sd8q{background-repeat:no-repeat}
|
||||
.rn-backgroundRepeat-17leim2{background-repeat:repeat}
|
||||
.rn-backgroundSize-4gszlv{background-size:cover}
|
||||
.rn-backgroundSize-1sxrcry{background-size:auto}
|
||||
.rn-backgroundSize-ehq7j7{background-size:contain}
|
||||
.rn-backgroundSize-x3cy2q{background-size:100% 100%}
|
||||
.rn-height-1pi2tsx{height:100%}
|
||||
.rn-height-z80fyv{height:20px}
|
||||
.rn-height-1r8g8re{height:36px}
|
||||
.rn-height-10ptun7{height:16px}
|
||||
.rn-height-4v7adb{height:5px}
|
||||
.rn-height-1dernwh{height:70%}
|
||||
.rn-opacity-1272l3b{opacity:0}
|
||||
.rn-opacity-6dt33c{opacity:1}
|
||||
.rn-width-13qz1uu{width:100%}
|
||||
.rn-width-19wmn03{width:20px}
|
||||
.rn-width-1acpoxo{width:36px}
|
||||
.rn-width-1janqcz{width:16px}
|
||||
.rn-touchAction-19z077z{-ms-touch-action:none;touch-action:none}
|
||||
.rn-touchAction-1gvxusu{-ms-touch-action:manipulate;touch-action:manipulate}
|
||||
.rn-WebkitOverflowScrolling-150rngu{-webkit-overflow-scrolling:touch}
|
||||
.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-overflowX-11yh6sk{overflow-x:hidden}
|
||||
.rn-overflowX-lltvgl{overflow-x:auto}
|
||||
.rn-overflowY-1rnoaur{overflow-y:auto}
|
||||
.rn-overflowY-buy8e9{overflow-y:hidden}
|
||||
.rn-transform-emqnss{-webkit-transform:translateZ(0px);transform:translateZ(0px)}
|
||||
.rn-fontFamily-10u92zi{font-family:-apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Ubuntu, \\"Helvetica Neue\\", sans-serif}
|
||||
.rn-fontFamily-poiln3{font-family:inherit}
|
||||
.rn-fontSize-1b43r93{font-size:14px}
|
||||
.rn-fontSize-7cikom{font-size:inherit}
|
||||
.rn-whiteSpace-q42fyq{white-space:pre-wrap}
|
||||
.rn-whiteSpace-irrty{white-space:inherit}
|
||||
.rn-whiteSpace-3s2u2q{white-space:nowrap}
|
||||
.rn-wordWrap-qvutc0{word-wrap:break-word}
|
||||
.rn-userSelect-lrvibr{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}
|
||||
.rn-maxWidth-dnmrzs{max-width:100%}
|
||||
.rn-textOverflow-1udbk01{text-overflow:ellipsis}
|
||||
.rn-justifyContent-1777fci{-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}
|
||||
.rn-visibility-11j9u27{visibility:hidden}
|
||||
.rn-animationDuration-17bb2tj{-webkit-animation-duration:0.75s;animation-duration:0.75s}
|
||||
.rn-animationDuration-1ay1djp{-webkit-animation-duration:1s;animation-duration:1s}
|
||||
.rn-animationIterationCount-1muvv40{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}
|
||||
.rn-animationName-dozj4v{-webkit-animation-name:rn-ActivityIndicator-animation;animation-name:rn-ActivityIndicator-animation}
|
||||
.rn-animationName-141g9a{-webkit-animation-name:rn-ProgressBar-animation;animation-name:rn-ProgressBar-animation}
|
||||
.rn-animationTimingFunction-1ldzwu0{-webkit-animation-timing-function:linear;animation-timing-function:linear}
|
||||
.rn-animationPlayState-1abnn5w{-webkit-animation-play-state:paused;animation-play-state:paused}
|
||||
.rn-transitionDuration-eafdt9{-webkit-transition-duration:0.15s;transition-duration:0.15s}
|
||||
.rn-transitionDuration-13tjlyg{-webkit-transition-duration:0.1s;transition-duration:0.1s}
|
||||
.rn-transitionProperty-1i6wzkk{-moz-transition-property:opacity;-webkit-transition-property:opacity;transition-property:opacity}
|
||||
.rn-borderTopLeftRadius-1iymjk7{border-top-left-radius:2px}
|
||||
.rn-borderTopLeftRadius-jt3ufn{border-top-left-radius:100%}
|
||||
.rn-borderTopLeftRadius-ou6ah9{border-top-left-radius:0px}
|
||||
.rn-borderTopRightRadius-s2skl2{border-top-right-radius:2px}
|
||||
.rn-borderTopRightRadius-1e868j9{border-top-right-radius:100%}
|
||||
.rn-borderTopRightRadius-t12b5v{border-top-right-radius:0px}
|
||||
.rn-borderBottomRightRadius-l5bh9y{border-bottom-right-radius:2px}
|
||||
.rn-borderBottomRightRadius-ujv9e3{border-bottom-right-radius:100%}
|
||||
.rn-borderBottomRightRadius-zmljjp{border-bottom-right-radius:0px}
|
||||
.rn-borderBottomLeftRadius-101sy47{border-bottom-left-radius:2px}
|
||||
.rn-borderBottomLeftRadius-1hakmuk{border-bottom-left-radius:100%}
|
||||
.rn-borderBottomLeftRadius-pm2fo{border-bottom-left-radius:0px}
|
||||
.rn-fontWeight-majxgm{font-weight:500}
|
||||
.rn-textTransform-tsynxw{text-transform:uppercase}
|
||||
.rn-borderTopColor-j4x2lb{border-top-color:rgba(101,119,134,1)}
|
||||
.rn-borderTopColor-gj2eto{border-top-color:rgba(0,150,136,1)}
|
||||
.rn-borderTopColor-1j7vz2b{border-top-color:rgba(204,214,221,1)}
|
||||
.rn-borderTopColor-2dclza{border-top-color:rgba(170,184,194,1)}
|
||||
.rn-borderTopColor-kqr9px{border-top-color:black}
|
||||
.rn-borderRightColor-12i18q1{border-right-color:rgba(101,119,134,1)}
|
||||
.rn-borderRightColor-31ud7z{border-right-color:rgba(0,150,136,1)}
|
||||
.rn-borderRightColor-10fg1ub{border-right-color:rgba(204,214,221,1)}
|
||||
.rn-borderRightColor-8jf312{border-right-color:rgba(170,184,194,1)}
|
||||
.rn-borderRightColor-q0dj5p{border-right-color:black}
|
||||
.rn-borderBottomColor-mg3rfb{border-bottom-color:rgba(101,119,134,1)}
|
||||
.rn-borderBottomColor-1bgnb8i{border-bottom-color:rgba(0,150,136,1)}
|
||||
.rn-borderBottomColor-zxuuv6{border-bottom-color:rgba(204,214,221,1)}
|
||||
.rn-borderBottomColor-1yeakrt{border-bottom-color:rgba(170,184,194,1)}
|
||||
.rn-borderBottomColor-1ah7hsa{border-bottom-color:black}
|
||||
.rn-borderLeftColor-vnhemr{border-left-color:rgba(101,119,134,1)}
|
||||
.rn-borderLeftColor-tbzcuz{border-left-color:rgba(0,150,136,1)}
|
||||
.rn-borderLeftColor-1p34dw6{border-left-color:rgba(204,214,221,1)}
|
||||
.rn-borderLeftColor-bluj2i{border-left-color:rgba(170,184,194,1)}
|
||||
.rn-borderLeftColor-137uh4u{border-left-color:black}
|
||||
.rn-backgroundImage-rs94m5{background-image:url(\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMSAxIgogICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0Ij4KICA8cGF0aAogICAgIGQ9Ik0gMC4wNDAzODA1OSwwLjYyNjc3NjcgMC4xNDY0NDY2MSwwLjUyMDcxMDY4IDAuNDI5Mjg5MzIsMC44MDM1NTMzOSAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IE0gMC4yMTcxNTcyOSwwLjgwMzU1MzM5IDAuODUzNTUzMzksMC4xNjcxNTcyOSAwLjk1OTYxOTQxLDAuMjczMjIzMyAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IgogICAgIGlkPSJyZWN0Mzc4MCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L3N2Zz4K\\")}
|
||||
.rn-alignSelf-k200y{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}
|
||||
.rn-boxShadow-1ewcgjf{box-shadow:0px 1px 3px rgba(0,0,0,0.5)}
|
||||
.rn-resize-1dz5y72{resize:none}",
|
||||
},
|
||||
]
|
||||
`;
|
||||
25
packages/react-native-web/src/exports/StyleSheet/__tests__/createAtomicRules.js
vendored
Normal file
25
packages/react-native-web/src/exports/StyleSheet/__tests__/createAtomicRules.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import createAtomicRules from '../createAtomicRules';
|
||||
|
||||
describe('StyleSheet/createAtomicRules', () => {
|
||||
test('transforms standard declarations to a single rule', () => {
|
||||
expect(createAtomicRules('.test', 'margin', 0)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('transforms custom "animationName" declaration', () => {
|
||||
const value = [
|
||||
{ '0%': { top: 0 }, '50%': { top: 5 }, '100%': { top: 10 } },
|
||||
{ from: { left: 0 }, to: { left: 10 } }
|
||||
];
|
||||
expect(createAtomicRules('.test', 'animationName', value)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('transforms custom "pointerEvents" declaration', () => {
|
||||
expect(createAtomicRules('.test', 'pointerEvents', 'box-only')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('transforms custom "placeholderTextColor" declaration', () => {
|
||||
expect(createAtomicRules('.test', 'placeholderTextColor', 'gray')).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -15,13 +15,30 @@ const reactNativeStyle = {
|
||||
resizeMode: 'contain'
|
||||
};
|
||||
|
||||
describe('apis/StyleSheet/createReactDOMStyle', () => {
|
||||
describe('StyleSheet/createReactDOMStyle', () => {
|
||||
test('noop on DOM styles', () => {
|
||||
const firstStyle = createReactDOMStyle(reactNativeStyle);
|
||||
const secondStyle = createReactDOMStyle(firstStyle);
|
||||
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({
|
||||
@@ -125,30 +142,23 @@ describe('apis/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', () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-env jasmine, jest */
|
||||
|
||||
import generateCss from '../generateCss';
|
||||
import createRuleBlock from '../createRuleBlock';
|
||||
|
||||
describe('apis/StyleSheet/generateCss', () => {
|
||||
describe('StyleSheet/createRuleBlock', () => {
|
||||
test('generates correct css', () => {
|
||||
const style = {
|
||||
boxShadow: '1px 1px 1px 1px #000',
|
||||
@@ -11,6 +11,6 @@ describe('apis/StyleSheet/generateCss', () => {
|
||||
position: 'absolute',
|
||||
transitionDuration: '0.1s'
|
||||
};
|
||||
expect(generateCss(style)).toMatchSnapshot();
|
||||
expect(createRuleBlock(style)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -2,16 +2,14 @@
|
||||
|
||||
/**
|
||||
* 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';
|
||||
|
||||
describe('apis/StyleSheet/flattenStyle', () => {
|
||||
describe('StyleSheet/flattenStyle', () => {
|
||||
test('should merge style objects', () => {
|
||||
const style = flattenStyle([{ opacity: 1 }, { order: 2 }]);
|
||||
expect(style).toMatchSnapshot();
|
||||
|
||||
@@ -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('apis/StyleSheet/i18nStyle', () => {
|
||||
describe('LTR mode', () => {
|
||||
describe('StyleSheet/i18nStyle', () => {
|
||||
describe('isRTL is false', () => {
|
||||
beforeEach(() => {
|
||||
I18nManager.allowRTL(false);
|
||||
});
|
||||
@@ -34,12 +13,73 @@ describe('apis/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('apis/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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ const isPlainObject = x => {
|
||||
/* eslint-enable */
|
||||
};
|
||||
|
||||
describe('apis/StyleSheet', () => {
|
||||
describe('StyleSheet', () => {
|
||||
test('absoluteFill', () => {
|
||||
expect(Number.isInteger(StyleSheet.absoluteFill) === true).toBeTruthy();
|
||||
});
|
||||
@@ -48,8 +48,4 @@ describe('apis/StyleSheet', () => {
|
||||
test('hairlineWidth', () => {
|
||||
expect(Number.isInteger(StyleSheet.hairlineWidth) === true).toBeTruthy();
|
||||
});
|
||||
|
||||
test('getStyleSheets', () => {
|
||||
expect(StyleSheet.getStyleSheets()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import normalizeValue from '../normalizeValue';
|
||||
|
||||
describe('apis/StyleSheet/normalizeValue', () => {
|
||||
describe('StyleSheet/normalizeValue', () => {
|
||||
test('normalizes property values requiring units', () => {
|
||||
expect(normalizeValue('margin', 0)).toEqual('0px');
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user