diff --git a/package.json b/package.json
index fbe9a030..9bf5dd18 100644
--- a/package.json
+++ b/package.json
@@ -11,9 +11,9 @@
"build:examples": "build-storybook -o dist-examples -c ./examples/.storybook",
"build:umd": "webpack --config webpack.config.js --sort-assets-by --progress",
"deploy:examples": "git checkout gh-pages && rm -rf ./storybook && mv dist-examples storybook && git add -A && git commit -m \"Storybook deploy\" && git push origin gh-pages && git checkout -",
+ "examples": "start-storybook -p 9001 -c ./examples/.storybook",
"lint": "eslint src",
"prepublish": "npm run build && npm run build:umd",
- "storybook": "start-storybook -p 9001 -c ./examples/.storybook",
"test": "karma start karma.config.js",
"test:watch": "npm run test -- --no-single-run"
},
diff --git a/src/apis/StyleSheet/StyleSheetValidation.js b/src/apis/StyleSheet/StyleSheetValidation.js
index efe0b588..307ad574 100644
--- a/src/apis/StyleSheet/StyleSheetValidation.js
+++ b/src/apis/StyleSheet/StyleSheetValidation.js
@@ -12,11 +12,13 @@ import TextStylePropTypes from '../../components/Text/TextStylePropTypes'
import ViewStylePropTypes from '../../components/View/ViewStylePropTypes'
import warning from 'fbjs/lib/warning'
+const allStylePropTypes = {}
+
class StyleSheetValidation {
static validateStyleProp(prop, style, caller) {
if (process.env.NODE_ENV !== 'production') {
if (allStylePropTypes[prop] === undefined) {
- const message1 = `"${prop}" is not a valid style property.`
+ const message1 = `"${prop}" is not a valid style property on Web.`
const message2 = '\nValid style props: ' + JSON.stringify(Object.keys(allStylePropTypes).sort(), null, ' ')
styleError(message1, style, caller, message2)
} else {
@@ -51,8 +53,6 @@ const styleError = (message1, style, caller, message2) => {
)
}
-const allStylePropTypes = {}
-
StyleSheetValidation.addValidStylePropTypes(ImageStylePropTypes)
StyleSheetValidation.addValidStylePropTypes(TextStylePropTypes)
StyleSheetValidation.addValidStylePropTypes(ViewStylePropTypes)
diff --git a/src/apis/StyleSheet/__tests__/index-test.js b/src/apis/StyleSheet/__tests__/index-test.js
index f3601cf5..b72e6419 100644
--- a/src/apis/StyleSheet/__tests__/index-test.js
+++ b/src/apis/StyleSheet/__tests__/index-test.js
@@ -1,7 +1,7 @@
/* eslint-env mocha */
import assert from 'assert'
-import { defaultStyles } from '../predefs'
+import { getDefaultStyleSheet } from '../css'
import isPlainObject from 'lodash/isPlainObject'
import StyleSheet from '..'
@@ -28,7 +28,7 @@ suite('apis/StyleSheet', () => {
StyleSheet.create({ root: { color: 'red' } })
assert.equal(
document.getElementById('__react-native-style').textContent,
- defaultStyles
+ getDefaultStyleSheet()
)
})
})
@@ -44,7 +44,7 @@ suite('apis/StyleSheet', () => {
test('render', () => {
assert.equal(
StyleSheet.render().props.dangerouslySetInnerHTML.__html,
- defaultStyles
+ getDefaultStyleSheet()
)
})
@@ -61,9 +61,9 @@ suite('apis/StyleSheet', () => {
{
className: 'test __style_df __style_pebn',
style: {
- display: 'flex',
+ display: null,
opacity: 1,
- pointerEvents: 'box-none'
+ pointerEvents: null
}
}
)
diff --git a/src/apis/StyleSheet/predefs.js b/src/apis/StyleSheet/css.js
similarity index 87%
rename from src/apis/StyleSheet/predefs.js
rename to src/apis/StyleSheet/css.js
index 4fa67ddf..635d2a1e 100644
--- a/src/apis/StyleSheet/predefs.js
+++ b/src/apis/StyleSheet/css.js
@@ -4,6 +4,21 @@ const POINTER_EVENTS_BOX_NONE_CLASSNAME = '__style_pebn'
const POINTER_EVENTS_BOX_ONLY_CLASSNAME = '__style_pebo'
const POINTER_EVENTS_NONE_CLASSNAME = '__style_pen'
+const CSS_RESET =
+// reset unwanted styles
+'/* React Native */\n' +
+'html {font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}\n' +
+'body {margin:0}\n' +
+'button::-moz-focus-inner, input::-moz-focus-inner {border:0;padding:0}\n' +
+'input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {display:none}'
+
+const CSS_HELPERS =
+// vendor prefix 'display:flex' until React supports fallback values for inline styles
+`.${DISPLAY_FLEX_CLASSNAME} {display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}\n` +
+// implement React Native's pointer event values
+`.${POINTER_EVENTS_AUTO_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME}, .${POINTER_EVENTS_BOX_NONE_CLASSNAME} * {pointer-events:auto}\n` +
+`.${POINTER_EVENTS_NONE_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME} *, .${POINTER_EVENTS_NONE_CLASSNAME} {pointer-events:none}`
+
const styleAsClassName = {
display: {
'flex': DISPLAY_FLEX_CLASSNAME
@@ -16,23 +31,8 @@ const styleAsClassName = {
}
}
-export const mapStyleToClassName = (prop, value) => {
+export const getDefaultStyleSheet = () => `${CSS_RESET}\n${CSS_HELPERS}`
+
+export const getStyleAsHelperClassName = (prop, value) => {
return styleAsClassName[prop] && styleAsClassName[prop][value]
}
-
-// reset unwanted styles beyond the control of React inline styles
-const resetCSS =
-'/* React Native */\n' +
-'html {font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}\n' +
-'body {margin:0}\n' +
-'button::-moz-focus-inner, input::-moz-focus-inner {border:0;padding:0}\n' +
-'input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {display:none}'
-
-const helperCSS =
-// vendor prefix 'display:flex' until React supports fallback values for inline styles
-`.${DISPLAY_FLEX_CLASSNAME} {display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}\n` +
-// implement React Native's pointer event values
-`.${POINTER_EVENTS_AUTO_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME}, .${POINTER_EVENTS_BOX_NONE_CLASSNAME} * {pointer-events:auto}\n` +
-`.${POINTER_EVENTS_NONE_CLASSNAME}, .${POINTER_EVENTS_BOX_ONLY_CLASSNAME} *, .${POINTER_EVENTS_NONE_CLASSNAME} {pointer-events:none}`
-
-export const defaultStyles = `${resetCSS}\n${helperCSS}`
diff --git a/src/apis/StyleSheet/index.js b/src/apis/StyleSheet/index.js
index 9f81e6a9..1cfffc43 100644
--- a/src/apis/StyleSheet/index.js
+++ b/src/apis/StyleSheet/index.js
@@ -1,76 +1,88 @@
+import * as css from './css'
import createReactStyleObject from './createReactStyleObject'
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'
import flattenStyle from '../../modules/flattenStyle'
import React from 'react'
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry'
import StyleSheetValidation from './StyleSheetValidation'
-import { defaultStyles, mapStyleToClassName } from './predefs'
-let isRendered = false
let styleElement
+let shouldInsertStyleSheet = ExecutionEnvironment.canUseDOM
+
const STYLE_SHEET_ID = '__react-native-style'
-const _injectStyleSheet = () => {
+const absoluteFillObject = { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }
+
+const defaultStyleSheet = css.getDefaultStyleSheet()
+
+const insertStyleSheet = () => {
// check if the server rendered the style sheet
styleElement = document.getElementById(STYLE_SHEET_ID)
// if not, inject the style sheet
- if (!styleElement) { document.head.insertAdjacentHTML('afterbegin', renderToString()) }
- isRendered = true
-}
-
-const _reset = () => {
- if (styleElement) { document.head.removeChild(styleElement) }
- styleElement = null
- isRendered = false
-}
-
-const absoluteFillObject = { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }
-const absoluteFill = ReactNativePropRegistry.register(absoluteFillObject)
-
-const create = (styles: Object): Object => {
- if (!isRendered && ExecutionEnvironment.canUseDOM) {
- _injectStyleSheet()
+ if (!styleElement) {
+ document.head.insertAdjacentHTML(
+ 'afterbegin',
+ ``
+ )
+ shouldInsertStyleSheet = false
}
-
- const result = {}
- for (let key in styles) {
- StyleSheetValidation.validateStyle(key, styles)
- result[key] = ReactNativePropRegistry.register(styles[key])
- }
- return result
-}
-
-const render = () =>
-
-const renderToString = () => ``
-
-/**
- * Accepts React props and converts style declarations to classNames when necessary
- */
-const resolve = (props) => {
- let className = props.className || ''
- let style = createReactStyleObject(props.style)
- for (const prop in style) {
- const value = style[prop]
- const replacementClassName = mapStyleToClassName(prop, value)
- if (replacementClassName) {
- className += ` ${replacementClassName}`
- // delete style[prop]
- }
- }
-
- return { className, style }
}
module.exports = {
- _reset,
- absoluteFill,
+ /**
+ * For testing
+ * @private
+ */
+ _reset() {
+ if (styleElement) {
+ document.head.removeChild(styleElement)
+ styleElement = null
+ shouldInsertStyleSheet = true
+ }
+ },
+
+ absoluteFill: ReactNativePropRegistry.register(absoluteFillObject),
+
absoluteFillObject,
- create,
+
+ create(styles) {
+ if (shouldInsertStyleSheet) {
+ insertStyleSheet()
+ }
+
+ const result = {}
+ for (const key in styles) {
+ StyleSheetValidation.validateStyle(key, styles)
+ result[key] = ReactNativePropRegistry.register(styles[key])
+ }
+ return result
+ },
+
hairlineWidth: 1,
+
flatten: flattenStyle,
+
/* @platform web */
- render,
- /* @platform web */
- resolve
+ render() {
+ return
+ },
+
+ /**
+ * Accepts React props and converts style declarations to classNames when necessary
+ * @platform web
+ */
+ resolve(props) {
+ let className = props.className || ''
+ let style = createReactStyleObject(props.style)
+ for (const prop in style) {
+ const value = style[prop]
+ const replacementClassName = css.getStyleAsHelperClassName(prop, value)
+ if (replacementClassName) {
+ className += ` ${replacementClassName}`
+ style[prop] = null
+ }
+ }
+
+ return { className, style }
+ }
}