mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-06 09:32:01 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a5f9cd7d9 | ||
|
|
aac6b796b2 | ||
|
|
c77ce19f1b | ||
|
|
25b74d30c4 | ||
|
|
4191d58694 | ||
|
|
11b861ae64 | ||
|
|
68bf08112a | ||
|
|
b277b3e509 | ||
|
|
c135dddbd1 | ||
|
|
ffc6368162 | ||
|
|
501c19fe9b | ||
|
|
e1da11fa1d | ||
|
|
b2a4d742a9 | ||
|
|
8b965fdfa0 | ||
|
|
8cfef85934 | ||
|
|
6db24e9358 |
10
.babelrc
10
.babelrc
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"optional": [
|
||||
"es7.classProperties",
|
||||
"runtime"
|
||||
],
|
||||
"stage": 1
|
||||
"presets": [
|
||||
"es2015",
|
||||
"stage-1",
|
||||
"react"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@ module.exports = function (config) {
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-mocha',
|
||||
'karma-mocha-reporter',
|
||||
'karma-sourcemap-loader',
|
||||
'karma-spec-reporter',
|
||||
'karma-webpack'
|
||||
],
|
||||
preprocessors: {
|
||||
[constants.TEST_ENTRY]: [ 'webpack', 'sourcemap' ]
|
||||
},
|
||||
reporters: process.env.TRAVIS ? [ 'dots' ] : [ 'mocha' ],
|
||||
reporters: process.env.TRAVIS ? [ 'dots' ] : [ 'spec' ],
|
||||
singleRun: true,
|
||||
webpack: {
|
||||
devtool: 'inline-source-map',
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
var webpack = require('webpack')
|
||||
|
||||
var DedupePlugin = webpack.optimize.DedupePlugin
|
||||
var EnvironmentPlugin = webpack.EnvironmentPlugin
|
||||
var DefinePlugin = webpack.DefinePlugin
|
||||
var OccurenceOrderPlugin = webpack.optimize.OccurenceOrderPlugin
|
||||
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin
|
||||
|
||||
var plugins = [
|
||||
new DedupePlugin(),
|
||||
new EnvironmentPlugin('NODE_ENV'),
|
||||
new OccurenceOrderPlugin()
|
||||
]
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
plugins.push(
|
||||
new DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
})
|
||||
)
|
||||
plugins.push(
|
||||
new UglifyJsPlugin({
|
||||
compress: {
|
||||
|
||||
@@ -64,7 +64,7 @@ Defaults:
|
||||
```js
|
||||
{
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: 'lightGray'
|
||||
backgroundColor: 'transparent'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ This function is called on press.
|
||||
|
||||
+ `backgroundColor`
|
||||
+ `color`
|
||||
+ `direction`
|
||||
+ `fontFamily`
|
||||
+ `fontSize`
|
||||
+ `fontStyle`
|
||||
@@ -69,6 +68,7 @@ This function is called on press.
|
||||
+ `textTransform`
|
||||
+ `whiteSpace`
|
||||
+ `wordWrap`
|
||||
+ `writingDirection`
|
||||
|
||||
**testID**: string
|
||||
|
||||
@@ -102,16 +102,16 @@ class PrettyText extends Component {
|
||||
...other
|
||||
style={{
|
||||
...style,
|
||||
...localStyle.color[color],
|
||||
...localStyle.size[size],
|
||||
...localStyle.weight[weight]
|
||||
...styles.color[color],
|
||||
...styles.size[size],
|
||||
...styles.weight[weight]
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const localStyle = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
color: {
|
||||
white: { color: 'white' },
|
||||
gray: { color: 'gray' },
|
||||
|
||||
@@ -213,7 +213,8 @@ export default class App extends React.Component {
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
common: {
|
||||
margin: '0 auto'
|
||||
marginVertical: 0,
|
||||
marginHorizontal: 'auto'
|
||||
},
|
||||
mqSmall: {
|
||||
maxWidth: '400px'
|
||||
@@ -230,7 +231,7 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
borderWidth: '1px'
|
||||
borderWidth: 1
|
||||
},
|
||||
horizontalBox: {
|
||||
width: '50px'
|
||||
|
||||
@@ -42,8 +42,8 @@ export default class GridView extends Component {
|
||||
|
||||
const contentContainerStyle = {
|
||||
...styles.contentContainer,
|
||||
margin: `0 calc(-0.5 * ${alley})`,
|
||||
padding: `0 ${gutter}`
|
||||
marginHorizontal: `calc(-0.5 * ${alley})`,
|
||||
paddingHorizontal: `${gutter}`
|
||||
}
|
||||
|
||||
const newChildren = React.Children.map(children, (child) => {
|
||||
@@ -51,7 +51,7 @@ export default class GridView extends Component {
|
||||
style: {
|
||||
...child.props.style,
|
||||
...styles.column,
|
||||
margin: `0 calc(0.5 * ${alley})`
|
||||
marginHorizontal: `calc(0.5 * ${alley})`
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from 'react'
|
||||
import { StyleSheet, Text } from '../../src'
|
||||
import React, { StyleSheet, Text } from '../../src'
|
||||
|
||||
const headingStyles = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
fontFamily: '"Helvetica Neue", arial, sans-serif'
|
||||
},
|
||||
size: {
|
||||
xlarge: {
|
||||
fontSize: '2rem',
|
||||
@@ -24,7 +26,7 @@ const Heading = ({ children, size = 'normal' }) => (
|
||||
<Text
|
||||
accessibilityRole='heading'
|
||||
children={children}
|
||||
style={headingStyles.size[size]}
|
||||
style={{ ...styles.root, ...styles.size[size] }}
|
||||
/>
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ const styles = StyleSheet.create({
|
||||
root: {
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
margin: '10px 0',
|
||||
marginVertical: 10,
|
||||
padding: 10,
|
||||
textAlign: 'center'
|
||||
},
|
||||
|
||||
51
package.json
51
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-web",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.11",
|
||||
"description": "React Native for Web",
|
||||
"main": "dist/react-native-web.js",
|
||||
"files": [
|
||||
@@ -10,44 +10,47 @@
|
||||
"build": "rm -rf ./dist && webpack --config config/webpack.config.publish.js --sort-assets-by --progress",
|
||||
"examples": "webpack-dev-server --config config/webpack.config.example.js --inline --hot --colors --quiet",
|
||||
"lint": "eslint config examples src",
|
||||
"prepublish": "NODE_ENV=publish npm run build",
|
||||
"prepublish": "npm run build",
|
||||
"test": "npm run lint && npm run test:unit",
|
||||
"test:unit": "karma start config/karma.config.js",
|
||||
"test:watch": "npm run test:unit -- --no-single-run"
|
||||
},
|
||||
"dependencies": {
|
||||
"inline-style-prefixer": "^0.3.3",
|
||||
"inline-style-prefixer": "^0.5.3",
|
||||
"lodash.debounce": "^3.1.1",
|
||||
"react-tappable": "^0.7.1",
|
||||
"react-textarea-autosize": "^3.0.0"
|
||||
"react-textarea-autosize": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^5.8.25",
|
||||
"babel-eslint": "^4.1.3",
|
||||
"babel-loader": "^5.3.2",
|
||||
"babel-runtime": "^5.8.25",
|
||||
"eslint": "^1.7.1",
|
||||
"babel-core": "^6.2.4",
|
||||
"babel-eslint": "^4.1.6",
|
||||
"babel-loader": "^6.2.0",
|
||||
"babel-preset-es2015": "^6.2.4",
|
||||
"babel-preset-react": "^6.2.4",
|
||||
"babel-preset-stage-1": "^6.2.4",
|
||||
"babel-runtime": "^6.2.4",
|
||||
"eslint": "^1.10.3",
|
||||
"eslint-config-standard": "^4.4.0",
|
||||
"eslint-config-standard-react": "^1.1.0",
|
||||
"eslint-plugin-react": "^3.6.0",
|
||||
"eslint-config-standard-react": "^1.2.1",
|
||||
"eslint-plugin-react": "^3.11.2",
|
||||
"eslint-plugin-standard": "^1.3.1",
|
||||
"karma": "^0.13.11",
|
||||
"karma-browserstack-launcher": "^0.1.5",
|
||||
"karma-chrome-launcher": "^0.2.1",
|
||||
"karma-firefox-launcher": "^0.1.6",
|
||||
"karma-mocha": "^0.2.0",
|
||||
"karma-mocha-reporter": "^1.1.1",
|
||||
"karma": "^0.13.15",
|
||||
"karma-browserstack-launcher": "^0.1.7",
|
||||
"karma-chrome-launcher": "^0.2.2",
|
||||
"karma-firefox-launcher": "^0.1.7",
|
||||
"karma-mocha": "^0.2.1",
|
||||
"karma-sourcemap-loader": "^0.3.6",
|
||||
"karma-spec-reporter": "0.0.23",
|
||||
"karma-webpack": "^1.7.0",
|
||||
"mocha": "^2.3.3",
|
||||
"mocha": "^2.3.4",
|
||||
"node-libs-browser": "^0.5.3",
|
||||
"object-assign": "^4.0.1",
|
||||
"react": "^0.14.0",
|
||||
"react-addons-test-utils": "^0.14.0",
|
||||
"react-dom": "^0.14.0",
|
||||
"react-media-queries": "^2.0.0",
|
||||
"webpack": "^1.12.2",
|
||||
"webpack-dev-server": "^1.12.1"
|
||||
"react": "^0.14.3",
|
||||
"react-addons-test-utils": "^0.14.3",
|
||||
"react-dom": "^0.14.3",
|
||||
"react-media-queries": "^2.0.1",
|
||||
"webpack": "^1.12.9",
|
||||
"webpack-dev-server": "^1.14.0"
|
||||
},
|
||||
"author": "Nicolas Gallagher",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -11,6 +11,8 @@ const roleComponents = {
|
||||
form: 'form',
|
||||
heading: 'h1',
|
||||
link: 'a',
|
||||
list: 'ul',
|
||||
listitem: 'li',
|
||||
main: 'main',
|
||||
navigation: 'nav',
|
||||
region: 'section'
|
||||
|
||||
@@ -17,10 +17,10 @@ const imageStyleKeys = Object.keys(ImageStylePropTypes)
|
||||
const styles = StyleSheet.create({
|
||||
initial: {
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: 'lightgray',
|
||||
backgroundColor: 'transparent',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: '100% 100%'
|
||||
backgroundSize: 'cover'
|
||||
},
|
||||
img: {
|
||||
borderWidth: 0,
|
||||
@@ -83,7 +83,7 @@ class Image extends React.Component {
|
||||
static defaultProps = {
|
||||
accessible: true,
|
||||
defaultSource: {},
|
||||
resizeMode: 'stretch',
|
||||
resizeMode: 'cover',
|
||||
source: {},
|
||||
style: styles.initial
|
||||
}
|
||||
|
||||
@@ -5,19 +5,22 @@ export default {
|
||||
...pickProps(CoreComponent.stylePropTypes, [
|
||||
'backgroundColor',
|
||||
'color',
|
||||
'direction',
|
||||
'font',
|
||||
'fontFamily',
|
||||
'fontSize',
|
||||
'fontStyle',
|
||||
'fontWeight',
|
||||
'letterSpacing',
|
||||
'lineHeight',
|
||||
'margin',
|
||||
'marginHorizontal',
|
||||
'marginVertical',
|
||||
'marginBottom',
|
||||
'marginLeft',
|
||||
'marginRight',
|
||||
'marginTop',
|
||||
'padding',
|
||||
'paddingHorizontal',
|
||||
'paddingVertical',
|
||||
'paddingBottom',
|
||||
'paddingLeft',
|
||||
'paddingRight',
|
||||
@@ -26,6 +29,7 @@ export default {
|
||||
'textDecoration',
|
||||
'textTransform',
|
||||
'whiteSpace',
|
||||
'wordWrap'
|
||||
'wordWrap',
|
||||
'writingDirection'
|
||||
])
|
||||
}
|
||||
|
||||
@@ -88,17 +88,18 @@ suite('components/TextInput', () => {
|
||||
|
||||
test('prop "maxNumberOfLines"', () => {
|
||||
const style = { borderWidth: 0, fontSize: 20, lineHeight: 1 }
|
||||
const value = (() => {
|
||||
const generateValue = () => {
|
||||
let str = ''
|
||||
while (str.length < 100) str += 'x'
|
||||
return str
|
||||
}())
|
||||
}
|
||||
|
||||
let dom = utils.renderAndInject(
|
||||
<TextInput
|
||||
maxNumberOfLines={3}
|
||||
multiline
|
||||
style={style}
|
||||
value={value}
|
||||
value={generateValue()}
|
||||
/>
|
||||
)
|
||||
const height = dom.getBoundingClientRect().height
|
||||
|
||||
@@ -54,6 +54,8 @@ export default {
|
||||
'left',
|
||||
// margin
|
||||
'margin',
|
||||
'marginHorizontal',
|
||||
'marginVertical',
|
||||
'marginBottom',
|
||||
'marginLeft',
|
||||
'marginRight',
|
||||
@@ -70,6 +72,8 @@ export default {
|
||||
'overflowY',
|
||||
// padding
|
||||
'padding',
|
||||
'paddingHorizontal',
|
||||
'paddingVertical',
|
||||
'paddingBottom',
|
||||
'paddingLeft',
|
||||
'paddingRight',
|
||||
|
||||
@@ -3,10 +3,15 @@ import { PropTypes } from 'react'
|
||||
const { number, string } = PropTypes
|
||||
const numberOrString = PropTypes.oneOfType([ number, string ])
|
||||
|
||||
/**
|
||||
* Any properties marked @private are used internally in resets or property
|
||||
* mappings.
|
||||
*/
|
||||
export default {
|
||||
alignContent: string,
|
||||
alignItems: string,
|
||||
alignSelf: string,
|
||||
appearance: string,
|
||||
backfaceVisibility: string,
|
||||
backgroundAttachment: string,
|
||||
backgroundClip: string,
|
||||
@@ -16,7 +21,6 @@ export default {
|
||||
backgroundPosition: string,
|
||||
backgroundRepeat: string,
|
||||
backgroundSize: string,
|
||||
border: string,
|
||||
borderColor: string,
|
||||
borderBottomColor: string,
|
||||
borderLeftColor: string,
|
||||
@@ -38,20 +42,21 @@ export default {
|
||||
borderRightWidth: numberOrString,
|
||||
borderTopWidth: numberOrString,
|
||||
bottom: numberOrString,
|
||||
boxShadow: string,
|
||||
boxSizing: string,
|
||||
clear: string,
|
||||
color: string,
|
||||
cursor: string,
|
||||
direction: string,
|
||||
display: string,
|
||||
flex: string,
|
||||
direction: string, /* @private */
|
||||
flex: string, /* @private */
|
||||
flexBasis: string,
|
||||
flexDirection: string,
|
||||
flexGrow: numberOrString,
|
||||
flexShrink: numberOrString,
|
||||
flexWrap: string,
|
||||
float: string,
|
||||
font: string,
|
||||
font: string, /* @private */
|
||||
fontFamily: string,
|
||||
fontSize: numberOrString,
|
||||
fontStyle: string,
|
||||
@@ -61,11 +66,14 @@ export default {
|
||||
left: numberOrString,
|
||||
letterSpacing: string,
|
||||
lineHeight: numberOrString,
|
||||
listStyle: string,
|
||||
margin: numberOrString,
|
||||
marginBottom: numberOrString,
|
||||
marginHorizontal: numberOrString,
|
||||
marginLeft: numberOrString,
|
||||
marginRight: numberOrString,
|
||||
marginTop: numberOrString,
|
||||
marginVertical: numberOrString,
|
||||
maxHeight: numberOrString,
|
||||
maxWidth: numberOrString,
|
||||
minHeight: numberOrString,
|
||||
@@ -77,19 +85,24 @@ export default {
|
||||
overflowY: string,
|
||||
padding: numberOrString,
|
||||
paddingBottom: numberOrString,
|
||||
paddingHorizontal: numberOrString,
|
||||
paddingLeft: numberOrString,
|
||||
paddingRight: numberOrString,
|
||||
paddingTop: numberOrString,
|
||||
paddingVertical: numberOrString,
|
||||
position: string,
|
||||
right: numberOrString,
|
||||
textAlign: string,
|
||||
textDecoration: string,
|
||||
textOverflow: string,
|
||||
textTransform: string,
|
||||
top: numberOrString,
|
||||
userSelect: string,
|
||||
verticalAlign: string,
|
||||
visibility: string,
|
||||
whiteSpace: string,
|
||||
width: numberOrString,
|
||||
wordWrap: string,
|
||||
writingDirection: string,
|
||||
zIndex: numberOrString
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export default class Store {
|
||||
const getCssSelector = (property, value) => {
|
||||
let className = this.get(property, value)
|
||||
if (!obfuscate && className) {
|
||||
className = className.replace(/[:?.%\\$#]/g, '\\$&')
|
||||
className = className.replace(/[,":?.%\\$#]/g, '\\$&')
|
||||
}
|
||||
return className
|
||||
}
|
||||
|
||||
@@ -82,8 +82,9 @@ suite('modules/StyleSheet/Store', () => {
|
||||
|
||||
test('replaces space characters', () => {
|
||||
const store = new Store()
|
||||
|
||||
store.set('margin', '0 auto')
|
||||
assert.deepEqual(store.get('margin', '0 auto'), 'margin:0-auto')
|
||||
assert.equal(store.get('margin', '0 auto'), 'margin\:0-auto')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -91,17 +92,17 @@ suite('modules/StyleSheet/Store', () => {
|
||||
test('human-readable style sheet', () => {
|
||||
const store = new Store()
|
||||
store.set('alignItems', 'center')
|
||||
store.set('color', '#fff')
|
||||
store.set('fontFamily', '"Helvetica Neue", Arial, sans-serif')
|
||||
store.set('marginBottom', 0)
|
||||
store.set('margin', 1)
|
||||
store.set('margin', 2)
|
||||
store.set('margin', 3)
|
||||
store.set('width', '100%')
|
||||
|
||||
const expected = '/* 5 unique declarations */\n' +
|
||||
'.alignItems\\:center{align-items:center;}\n' +
|
||||
'.margin\\:1px{margin:1px;}\n' +
|
||||
'.margin\\:2px{margin:2px;}\n' +
|
||||
'.margin\\:3px{margin:3px;}\n' +
|
||||
'.marginBottom\\:0px{margin-bottom:0px;}'
|
||||
'.color\\:\\#fff{color:#fff;}\n' +
|
||||
'.fontFamily\\:\\"Helvetica-Neue\\"\\,-Arial\\,-sans-serif{font-family:"Helvetica Neue", Arial, sans-serif;}\n' +
|
||||
'.marginBottom\\:0px{margin-bottom:0px;}\n' +
|
||||
'.width\\:100\\%{width:100%;}'
|
||||
|
||||
assert.equal(store.toString(), expected)
|
||||
})
|
||||
29
src/modules/StyleSheet/__tests__/expandStyle-test.js
Normal file
29
src/modules/StyleSheet/__tests__/expandStyle-test.js
Normal file
@@ -0,0 +1,29 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import expandStyle from '../expandStyle'
|
||||
|
||||
suite('modules/StyleSheet/expandStyle', () => {
|
||||
test('style property', () => {
|
||||
const initial = {
|
||||
borderTopWidth: 1,
|
||||
borderWidth: 2,
|
||||
marginTop: 50,
|
||||
marginVertical: 25,
|
||||
margin: 10
|
||||
}
|
||||
|
||||
const expectedStyle = {
|
||||
borderTopWidth: 1,
|
||||
borderLeftWidth: 2,
|
||||
borderRightWidth: 2,
|
||||
borderBottomWidth: 2,
|
||||
marginTop: 50,
|
||||
marginBottom: 25,
|
||||
marginLeft: 10,
|
||||
marginRight: 10
|
||||
}
|
||||
|
||||
assert.deepEqual(expandStyle(initial), expectedStyle)
|
||||
})
|
||||
})
|
||||
@@ -16,8 +16,9 @@ const fixture = {
|
||||
backgroundSize: 'contain'
|
||||
}
|
||||
},
|
||||
ignored: {
|
||||
pading: 0
|
||||
position: {
|
||||
left: { left: 0 },
|
||||
right: { right: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +28,9 @@ suite('modules/StyleSheet/getStyleObjects', () => {
|
||||
assert.deepEqual(actual, [
|
||||
{ margin: 0, padding: 0 },
|
||||
{ backgroundSize: 'auto' },
|
||||
{ backgroundSize: 'contain' }
|
||||
{ backgroundSize: 'contain' },
|
||||
{ left: 0 },
|
||||
{ right: 0 }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ import { resetCSS, predefinedCSS } from '../predefs'
|
||||
import assert from 'assert'
|
||||
import StyleSheet from '..'
|
||||
|
||||
const styles = { root: { border: 0 } }
|
||||
const styles = { root: { borderWidth: 1 } }
|
||||
|
||||
suite('modules/StyleSheet', () => {
|
||||
setup(() => {
|
||||
@@ -20,14 +20,17 @@ suite('modules/StyleSheet', () => {
|
||||
assert.equal(
|
||||
StyleSheet.renderToString(),
|
||||
`${resetCSS}\n${predefinedCSS}\n` +
|
||||
`/* 1 unique declarations */\n` +
|
||||
`.border\\:0px{border:0px;}`
|
||||
`/* 4 unique declarations */\n` +
|
||||
`.borderBottomWidth\\:1px{border-bottom-width:1px;}\n` +
|
||||
`.borderLeftWidth\\:1px{border-left-width:1px;}\n` +
|
||||
`.borderRightWidth\\:1px{border-right-width:1px;}\n` +
|
||||
`.borderTopWidth\\:1px{border-top-width:1px;}`
|
||||
)
|
||||
})
|
||||
|
||||
test('resolve', () => {
|
||||
const props = { className: 'className', style: styles.root }
|
||||
const expected = { className: 'className border:0px', style: {} }
|
||||
const expected = { className: 'className borderTopWidth:1px borderRightWidth:1px borderBottomWidth:1px borderLeftWidth:1px', style: {} }
|
||||
StyleSheet.create(styles)
|
||||
assert.deepEqual(StyleSheet.resolve(props), expected)
|
||||
})
|
||||
|
||||
@@ -3,14 +3,27 @@
|
||||
import assert from 'assert'
|
||||
import isStyleObject from '../isStyleObject'
|
||||
|
||||
const style = { margin: 0 }
|
||||
const notStyle = { root: style }
|
||||
const styles = {
|
||||
root: {
|
||||
margin: 0
|
||||
},
|
||||
align: {
|
||||
left: {
|
||||
textAlign: 'left'
|
||||
},
|
||||
right: {
|
||||
textAlign: 'right'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suite('modules/StyleSheet/isStyleObject', () => {
|
||||
test('returns "true" for style objects', () => {
|
||||
assert.ok(isStyleObject(style) === true)
|
||||
})
|
||||
test('returns "false" for non-style objects', () => {
|
||||
assert.ok(isStyleObject(notStyle) === false)
|
||||
assert.ok(isStyleObject(styles) === false)
|
||||
assert.ok(isStyleObject(styles.align) === false)
|
||||
})
|
||||
test('returns "true" for style objects', () => {
|
||||
assert.ok(isStyleObject(styles.root) === true)
|
||||
assert.ok(isStyleObject(styles.align.left) === true)
|
||||
})
|
||||
})
|
||||
|
||||
52
src/modules/StyleSheet/expandStyle.js
Normal file
52
src/modules/StyleSheet/expandStyle.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const styleShortHands = {
|
||||
borderColor: [ 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor' ],
|
||||
borderRadius: [ 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius' ],
|
||||
borderStyle: [ 'borderTopStyle', 'borderRightStyle', 'borderBottomStyle', 'borderLeftStyle' ],
|
||||
borderWidth: [ 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth' ],
|
||||
margin: [ 'marginTop', 'marginRight', 'marginBottom', 'marginLeft' ],
|
||||
marginHorizontal: [ 'marginRight', 'marginLeft' ],
|
||||
marginVertical: [ 'marginTop', 'marginBottom' ],
|
||||
padding: [ 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft' ],
|
||||
paddingHorizontal: [ 'paddingRight', 'paddingLeft' ],
|
||||
paddingVertical: [ 'paddingTop', 'paddingBottom' ],
|
||||
writingDirection: [ 'direction' ]
|
||||
}
|
||||
|
||||
/**
|
||||
* Alpha-sort properties, apart from shorthands which appear before the
|
||||
* properties they expand into. This ensures that more specific styles override
|
||||
* the shorthands, whatever the order in which they were originally declared.
|
||||
*/
|
||||
const sortProps = (propsArray) => propsArray.sort((a, b) => {
|
||||
const expandedA = styleShortHands[a]
|
||||
const expandedB = styleShortHands[b]
|
||||
if (expandedA && expandedA.indexOf(b) > -1) {
|
||||
return -1
|
||||
} else if (expandedB && expandedB.indexOf(a) > -1) {
|
||||
return 1
|
||||
}
|
||||
return a < b ? -1 : a > b ? 1 : 0
|
||||
})
|
||||
|
||||
/**
|
||||
* Expand the shorthand properties to isolate every declaration from the others.
|
||||
*/
|
||||
const expandStyle = (style) => {
|
||||
const propsArray = Object.keys(style)
|
||||
const sortedProps = sortProps(propsArray)
|
||||
|
||||
return sortedProps.reduce((resolvedStyle, key) => {
|
||||
const expandedProps = styleShortHands[key]
|
||||
const value = style[key]
|
||||
if (expandedProps) {
|
||||
expandedProps.forEach((prop, i) => {
|
||||
resolvedStyle[expandedProps[i]] = value
|
||||
})
|
||||
} else {
|
||||
resolvedStyle[key] = value
|
||||
}
|
||||
return resolvedStyle
|
||||
}, {})
|
||||
}
|
||||
|
||||
export default expandStyle
|
||||
@@ -1,7 +1,9 @@
|
||||
import { resetCSS, predefinedCSS, predefinedClassNames } from './predefs'
|
||||
import expandStyle from './expandStyle'
|
||||
import getStyleObjects from './getStyleObjects'
|
||||
import prefixer from './prefixer'
|
||||
import Store from './Store'
|
||||
import StylePropTypes from '../StylePropTypes'
|
||||
|
||||
/**
|
||||
* Initialize the store with pointer-event styles mapping to our custom pointer
|
||||
@@ -17,11 +19,18 @@ let store = createStore()
|
||||
*/
|
||||
const create = (styles: Object): Object => {
|
||||
const rules = getStyleObjects(styles)
|
||||
|
||||
rules.forEach((rule) => {
|
||||
Object.keys(rule).forEach(property => {
|
||||
const value = rule[property]
|
||||
// add each declaration to the store
|
||||
store.set(property, value)
|
||||
const style = expandStyle(rule)
|
||||
|
||||
Object.keys(style).forEach((property) => {
|
||||
if (!StylePropTypes[property]) {
|
||||
console.error(`ReactNativeWeb: the style property "${property}" is not supported`)
|
||||
} else {
|
||||
const value = style[property]
|
||||
// add each declaration to the store
|
||||
store.set(property, value)
|
||||
}
|
||||
})
|
||||
})
|
||||
return styles
|
||||
@@ -49,15 +58,19 @@ const renderToString = () => {
|
||||
const resolve = ({ className = '', style = {} }) => {
|
||||
let _className
|
||||
let _style = {}
|
||||
const expandedStyle = expandStyle(style)
|
||||
|
||||
const classList = [ className ]
|
||||
for (const prop in style) {
|
||||
let styleClass = store.get(prop, style[prop])
|
||||
for (const prop in expandedStyle) {
|
||||
if (!StylePropTypes[prop]) {
|
||||
continue
|
||||
}
|
||||
let styleClass = store.get(prop, expandedStyle[prop])
|
||||
|
||||
if (styleClass) {
|
||||
classList.push(styleClass)
|
||||
} else {
|
||||
_style[prop] = style[prop]
|
||||
_style[prop] = expandedStyle[prop]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { pickProps } from '../filterObjectProps'
|
||||
import StylePropTypes from '../StylePropTypes'
|
||||
import isObject from './isObject'
|
||||
|
||||
const isStyleObject = (obj) => {
|
||||
const declarations = pickProps(obj, Object.keys(StylePropTypes))
|
||||
return Object.keys(declarations).length > 0
|
||||
const values = Object.keys(obj).map((key) => obj[key])
|
||||
for (let i = 0; i < values.length; i += 1) {
|
||||
if (isObject(values[i])) { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export default isStyleObject
|
||||
|
||||
@@ -6,7 +6,8 @@ export const resetCSS =
|
||||
html {font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
|
||||
body {margin:0}
|
||||
button::-moz-focus-inner, input::-moz-focus-inner {border:0;padding:0}
|
||||
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {-webkit-appearance:none}`
|
||||
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {-webkit-appearance:none}
|
||||
ol,ul,li {list-style:none}`
|
||||
|
||||
/**
|
||||
* Custom pointer event styles
|
||||
|
||||
Reference in New Issue
Block a user