From a53dba8c62149db26cd0fb7ab027a02a86757dec Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Sat, 20 Jan 2018 16:36:04 -0800 Subject: [PATCH] [change] simplify CSS rule injection WebStyleSheet handles injecting CSS rules and returning the style sheet's text content. All CSS, including the reset, is now added using WebStyleSheet and the DOM API 'insertRule'. Browsers will throw a parse error on unrecognized vendor-prefixes in selectors, so rules with unsafe selectors are wrapped in '@media all {}' before being passed to 'insertRule'. (This will be relevant when attempting to support 'placeholderTextColor'. And it is a way to batch-insert rules with a single call to 'insertRule'.) The html tag 'font-family' CSS reset is removed as it's not needed. --- .../renderApplication-test.js.snap | 183 +++++++++-------- .../exports/StyleSheet/StyleSheetManager.js | 66 ++----- .../src/exports/StyleSheet/WebStyleSheet.js | 58 ++++++ .../__tests__/StyleSheetManager-test.js | 9 +- .../StyleSheetManager-test.js.snap | 51 ++--- .../__snapshots__/index-test.js.snap | 185 +++++++++--------- .../src/exports/StyleSheet/flattenStyle.js | 3 +- .../src/exports/StyleSheet/initialRules.js | 36 ++++ .../src/exports/StyleSheet/staticCss.js | 27 --- 9 files changed, 313 insertions(+), 305 deletions(-) create mode 100644 packages/react-native-web/src/exports/StyleSheet/WebStyleSheet.js create mode 100644 packages/react-native-web/src/exports/StyleSheet/initialRules.js delete mode 100644 packages/react-native-web/src/exports/StyleSheet/staticCss.js diff --git a/packages/react-native-web/src/exports/AppRegistry/__tests__/__snapshots__/renderApplication-test.js.snap b/packages/react-native-web/src/exports/AppRegistry/__tests__/__snapshots__/renderApplication-test.js.snap index b8d66b98..fceaa48c 100644 --- a/packages/react-native-web/src/exports/AppRegistry/__tests__/__snapshots__/renderApplication-test.js.snap +++ b/packages/react-native-web/src/exports/AppRegistry/__tests__/__snapshots__/renderApplication-test.js.snap @@ -9,180 +9,177 @@ exports[`apis/AppRegistry/renderApplication getApplication 1`] = ` `; exports[`apis/AppRegistry/renderApplication getApplication 2`] = ` -"" -`; - -exports[`apis/AppRegistry/renderApplication getApplication 3`] = ` -"" +.rn-left-1fe0xdi{left:0%} +.rn-left-7b7h2f{left:100%} +.rn-backgroundColor-1bgzomc{background-color:rgba(189,189,189,1)} +.rn-borderTopColor-kqr9px{border-top-color:black} +.rn-borderRightColor-q0dj5p{border-right-color:black} +.rn-borderBottomColor-1ah7hsa{border-bottom-color:black} +.rn-borderLeftColor-137uh4u{border-left-color:black} +.rn-borderTopLeftRadius-ou6ah9{border-top-left-radius:0px} +.rn-borderTopRightRadius-t12b5v{border-top-right-radius:0px} +.rn-borderBottomRightRadius-zmljjp{border-bottom-right-radius:0px} +.rn-borderBottomLeftRadius-pm2fo{border-bottom-left-radius:0px} +.rn-resize-1dz5y72{resize:none} +.rn-opacity-6dt33c{opacity:1}" `; diff --git a/packages/react-native-web/src/exports/StyleSheet/StyleSheetManager.js b/packages/react-native-web/src/exports/StyleSheet/StyleSheetManager.js index 360fe42a..e5569b4b 100644 --- a/packages/react-native-web/src/exports/StyleSheet/StyleSheetManager.js +++ b/packages/react-native-web/src/exports/StyleSheet/StyleSheetManager.js @@ -8,10 +8,10 @@ * @noflow */ -import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment'; import generateCss from './generateCss'; import hash from '../../vendor/hash'; -import staticCss from './staticCss'; +import initialRules from './initialRules'; +import WebStyleSheet from './WebStyleSheet'; const emptyObject = {}; const STYLE_ELEMENT_ID = 'react-native-stylesheet'; @@ -26,6 +26,7 @@ const createCssRules = (selector, prop, value) => { let v = value; // pointerEvents is a special case that requires custom values and additional css rules + // See #513 if (prop === 'pointerEvents') { if (value === 'auto' || value === 'box-only') { v = 'auto !important'; @@ -48,11 +49,9 @@ const createCssRules = (selector, prop, value) => { return rules; }; -// See #513 - export default class StyleSheetManager { cache = null; - mainSheet = null; + _webStyleSheet = null; constructor() { this.cache = { @@ -60,18 +59,14 @@ export default class StyleSheetManager { byProp: {} }; - // 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); - } - } + this._webStyleSheet = new WebStyleSheet(STYLE_ELEMENT_ID); + initialRules.forEach(rule => { + this._webStyleSheet.insertRuleOnce(rule); + }); // need to pre-register pointerEvents as they have no inline-style equivalent + // TODO: make it so inline style can register pointerEvents when needed. might need + // this for placeholder text color implementation, and keyframes too ['box-only', 'box-none', 'auto', 'none'].forEach(v => { this.setDeclaration('pointerEvents', v); }); @@ -87,38 +82,13 @@ export default class StyleSheetManager { return cache[className] || emptyObject; } - getStyleSheetHtml() { - const styleSheets = this.getStyleSheets(); - return styleSheets - .map(sheet => { - return ``; - }) - .join('\n'); - } - getStyleSheets() { - const cache = this.cache.byProp; - - const mainSheetTextContext = Object.keys(cache) - .reduce((rules, prop) => { - Object.keys(cache[prop]).forEach(value => { - const className = this.getClassName(prop, value); - const moreRules = createCssRules(`.${className}`, prop, value); - rules.push(...moreRules); - }); - - return rules; - }, []) - .join('\n'); + const { cssText } = this._webStyleSheet; return [ - { - id: 'react-native-stylesheet-static', - textContent: `${staticCss}` - }, { id: STYLE_ELEMENT_ID, - textContent: `${mainSheetTextContext}` + textContent: cssText } ]; } @@ -128,14 +98,10 @@ export default class StyleSheetManager { 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 rules = createCssRules(`.${className}`, prop, value); - rules.forEach(rule => sheet.insertRule(rule, sheet.cssRules.length)); - } - } + const rules = createCssRules(`.${className}`, prop, value); + rules.forEach(rule => { + this._webStyleSheet.insertRuleOnce(rule); + }); } return className; } diff --git a/packages/react-native-web/src/exports/StyleSheet/WebStyleSheet.js b/packages/react-native-web/src/exports/StyleSheet/WebStyleSheet.js new file mode 100644 index 00000000..fb7958ef --- /dev/null +++ b/packages/react-native-web/src/exports/StyleSheet/WebStyleSheet.js @@ -0,0 +1,58 @@ +/** + * 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. + * + * @flow + */ + +import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment'; + +export default class WebStyleSheet { + 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 = ``; + if (document.head) { + document.head.insertAdjacentHTML('afterbegin', html); + _domStyleElement = document.getElementById(id); + } + } + } + + this._domStyleElement = _domStyleElement; + } + + _cssRules = []; + _domStyleElement = null; + + containsRule(rule: string): boolean { + return this._cssRules.indexOf(rule) > -1; + } + + get cssText(): string { + return this._cssRules.join('\n'); + } + + insertRuleOnce(rule: string) { + // prevent duplicate rules + if (!this.containsRule(rule)) { + this._cssRules.push(rule); + // update the native stylesheet (i.e., browser) + if (this._domStyleElement) { + // Check whether a rule was part of any prerendered styles (textContent + // doesn't include styles injected via 'insertRule') + if (this._domStyleElement.textContent.indexOf(rule) === -1) { + // $FlowFixMe + this._domStyleElement.sheet.insertRule(rule, this._domStyleElement.sheet.cssRules.length); + } + } + } + } +} diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/StyleSheetManager-test.js b/packages/react-native-web/src/exports/StyleSheet/__tests__/StyleSheetManager-test.js index 0cb99230..d07eaba7 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/StyleSheetManager-test.js +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/StyleSheetManager-test.js @@ -23,14 +23,13 @@ describe('apis/StyleSheet/StyleSheetManager', () => { }); }); - test('getStyleSheetHtml', () => { - expect(styleSheetManager.getStyleSheetHtml()).toMatchSnapshot(); - styleSheetManager.setDeclaration('width', '100px'); - expect(styleSheetManager.getStyleSheetHtml()).toMatchSnapshot(); + test('getStyleSheets', () => { + styleSheetManager.setDeclaration('--test-property', 'test-value'); + expect(styleSheetManager.getStyleSheets()).toMatchSnapshot(); }); test('setDeclaration', () => { - styleSheetManager.mainSheet.sheet.insertRule = (rule, position) => { + styleSheetManager._webStyleSheet.insertRuleOnce = (rule, position) => { // check for regressions in CSS write path (e.g., 0 => 0px) expect(rule.indexOf('-webkit-flex-shrink:0;')).not.toEqual(-1); }; diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/StyleSheetManager-test.js.snap b/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/StyleSheetManager-test.js.snap index 030ac00b..77ee7277 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/StyleSheetManager-test.js.snap +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/StyleSheetManager-test.js.snap @@ -2,42 +2,23 @@ exports[`apis/StyleSheet/StyleSheetManager getClassName 1`] = `"rn-pointerEvents-ah5dr5"`; -exports[`apis/StyleSheet/StyleSheetManager getStyleSheetHtml 1`] = ` -" -" -`; - -exports[`apis/StyleSheet/StyleSheetManager getStyleSheetHtml 2`] = ` -" -" +.rn-pointerEvents-ah5dr5 > *{pointer-events:none} +.rn-pointerEvents-ah5dr5{pointer-events:auto !important} +.rn-pointerEvents-12vffkv > *{pointer-events:auto} +.rn-pointerEvents-12vffkv{pointer-events:none !important} +.rn-pointerEvents-105ug2t{pointer-events:auto !important} +.rn-pointerEvents-633pao{pointer-events:none !important} +.rn---test-property-ax3bxi{--test-property:test-value}", + }, +] `; diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/index-test.js.snap b/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/index-test.js.snap index acc3f418..5b37efdb 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/index-test.js.snap +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/__snapshots__/index-test.js.snap @@ -3,183 +3,180 @@ 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);} + "id": "react-native-stylesheet", + "textContent": "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;} +@media all{button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}} +@media all{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-pointerEvents-ah5dr5 > *{pointer-events:none} +.rn-pointerEvents-ah5dr5{pointer-events:auto !important} +.rn-pointerEvents-12vffkv > *{pointer-events:auto} +.rn-pointerEvents-12vffkv{pointer-events:none !important} +.rn-pointerEvents-105ug2t{pointer-events:auto !important} +.rn-pointerEvents-633pao{pointer-events:none !important} +.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-position-bnwqim{position:relative} .rn-zIndex-1lgpqti{z-index:0} +.rn-display-xoduu5{display:-webkit-inline-box;display:-moz-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex} .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-height-1pi2tsx{height:100%} +.rn-opacity-1272l3b{opacity:0} +.rn-width-13qz1uu{width:100%} .rn-backgroundSize-1sxrcry{background-size:auto} .rn-backgroundSize-ehq7j7{background-size:contain} +.rn-backgroundRepeat-17leim2{background-repeat:repeat} .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-flexShrink-1awmn5t{-ms-flex-negative:1 !important;-webkit-flex-shrink:1 !important;flex-shrink: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-flexDirection-18u37iz{-ms-flex-direction:row;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;flex-direction:row} +.rn-overflowX-lltvgl{overflow-x:auto} +.rn-overflowY-buy8e9{overflow-y:hidden} +.rn-display-1471scf{display:inline} .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-fontFamily-poiln3{font-family:inherit} +.rn-fontSize-7cikom{font-size:inherit} +.rn-whiteSpace-irrty{white-space:inherit} .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-whiteSpace-3s2u2q{white-space:nowrap} +.rn-alignItems-1awozwy{-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center} .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-height-z80fyv{height:20px} +.rn-width-19wmn03{width:20px} +.rn-height-1r8g8re{height:36px} +.rn-width-1acpoxo{width:36px} +.rn-touchAction-1gvxusu{-ms-touch-action:manipulate;touch-action:manipulate} .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-backgroundColor-8ndhhv{background-color:rgba(33,150,243,1)} .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-color-1qtguxu{color:rgba(255,255,255,1)} .rn-fontWeight-majxgm{font-weight:500} +.rn-paddingTop-tskmnb{padding-top:8px} +.rn-paddingRight-1pyaxff{padding-right:8px} +.rn-paddingBottom-xd6kpl{padding-bottom:8px} +.rn-paddingLeft-1m04atk{padding-left:8px} +.rn-textAlign-q4m81j{text-align:center} .rn-textTransform-tsynxw{text-transform:uppercase} +.rn-backgroundColor-15al3ab{background-color:rgba(223,223,223,1)} +.rn-color-istcb5{color:rgba(161,161,161,1)} +.rn-height-10ptun7{height:16px} +.rn-width-1janqcz{width:16px} +.rn-cursor-7q8q6z{cursor:default} +.rn-cursor-1ei5mc7{cursor:inherit} +.rn-backgroundColor-44z8sh{background-color:rgba(255,255,255,1)} .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-borderTopWidth-1jxfwug{border-top-width:2px} +.rn-borderRightWidth-18p6if4{border-right-width:2px} +.rn-borderBottomWidth-wgabs5{border-bottom-width:2px} +.rn-borderLeftWidth-dwliz8{border-left-width:2px} +.rn-backgroundColor-5itogg{background-color:rgba(0,150,136,1)} .rn-backgroundImage-rs94m5{background-image:url(\\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMSAxIgogICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0Ij4KICA8cGF0aAogICAgIGQ9Ik0gMC4wNDAzODA1OSwwLjYyNjc3NjcgMC4xNDY0NDY2MSwwLjUyMDcxMDY4IDAuNDI5Mjg5MzIsMC44MDM1NTMzOSAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IE0gMC4yMTcxNTcyOSwwLjgwMzU1MzM5IDAuODUzNTUzMzksMC4xNjcxNTcyOSAwLjk1OTYxOTQxLDAuMjczMjIzMyAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IgogICAgIGlkPSJyZWN0Mzc4MCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L3N2Zz4K\\")} +.rn-borderTopColor-gj2eto{border-top-color:rgba(0,150,136,1)} +.rn-borderRightColor-31ud7z{border-right-color:rgba(0,150,136,1)} +.rn-borderBottomColor-1bgnb8i{border-bottom-color:rgba(0,150,136,1)} +.rn-borderLeftColor-tbzcuz{border-left-color:rgba(0,150,136,1)} +.rn-borderTopColor-1j7vz2b{border-top-color:rgba(204,214,221,1)} +.rn-borderRightColor-10fg1ub{border-right-color:rgba(204,214,221,1)} +.rn-borderBottomColor-zxuuv6{border-bottom-color:rgba(204,214,221,1)} +.rn-borderLeftColor-1p34dw6{border-left-color:rgba(204,214,221,1)} +.rn-backgroundColor-1v82r4u{background-color:rgba(170,184,194,1)} +.rn-borderTopColor-2dclza{border-top-color:rgba(170,184,194,1)} +.rn-borderRightColor-8jf312{border-right-color:rgba(170,184,194,1)} +.rn-borderBottomColor-1yeakrt{border-bottom-color:rgba(170,184,194,1)} +.rn-borderLeftColor-bluj2i{border-left-color:rgba(170,184,194,1)} +.rn-height-4v7adb{height:5px} +.rn-animationDuration-1ay1djp{-webkit-animation-duration:1s;animation-duration:1s} +.rn-animationName-141g9a{-webkit-animation-name:rn-ProgressBar-animation;animation-name:rn-ProgressBar-animation} +.rn-height-1dernwh{height:70%} +.rn-marginTop-1t01tom{margin-top:auto} +.rn-marginRight-lchren{margin-right:auto} +.rn-marginBottom-1qahzrx{margin-bottom:auto} +.rn-marginLeft-1jj8364{margin-left:auto} +.rn-transitionDuration-13tjlyg{-webkit-transition-duration:0.1s;transition-duration:0.1s} +.rn-backgroundColor-1hj8efq{background-color:rgba(213,213,213,1)} .rn-alignSelf-k200y{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start} +.rn-borderTopLeftRadius-jt3ufn{border-top-left-radius:100%} +.rn-borderTopRightRadius-1e868j9{border-top-right-radius:100%} +.rn-borderBottomRightRadius-ujv9e3{border-bottom-right-radius:100%} +.rn-borderBottomLeftRadius-1hakmuk{border-bottom-left-radius:100%} .rn-boxShadow-1ewcgjf{box-shadow:0px 1px 3px rgba(0,0,0,0.5)} -.rn-resize-1dz5y72{resize:none}", +.rn-left-1fe0xdi{left:0%} +.rn-left-7b7h2f{left:100%} +.rn-backgroundColor-1bgzomc{background-color:rgba(189,189,189,1)} +.rn-borderTopColor-kqr9px{border-top-color:black} +.rn-borderRightColor-q0dj5p{border-right-color:black} +.rn-borderBottomColor-1ah7hsa{border-bottom-color:black} +.rn-borderLeftColor-137uh4u{border-left-color:black} +.rn-borderTopLeftRadius-ou6ah9{border-top-left-radius:0px} +.rn-borderTopRightRadius-t12b5v{border-top-right-radius:0px} +.rn-borderBottomRightRadius-zmljjp{border-bottom-right-radius:0px} +.rn-borderBottomLeftRadius-pm2fo{border-bottom-left-radius:0px} +.rn-resize-1dz5y72{resize:none} +.rn-opacity-6dt33c{opacity:1}", }, ] `; diff --git a/packages/react-native-web/src/exports/StyleSheet/flattenStyle.js b/packages/react-native-web/src/exports/StyleSheet/flattenStyle.js index d8caa9d7..518b64b1 100644 --- a/packages/react-native-web/src/exports/StyleSheet/flattenStyle.js +++ b/packages/react-native-web/src/exports/StyleSheet/flattenStyle.js @@ -24,7 +24,7 @@ function getStyle(style) { } function flattenStyle(style: ?StyleObj): ?Object { - if (style == null || typeof style === 'boolean') { + if (!style) { return undefined; } @@ -33,6 +33,7 @@ function flattenStyle(style: ?StyleObj): ?Object { } if (!Array.isArray(style)) { + // $FlowFixMe return getStyle(style); } diff --git a/packages/react-native-web/src/exports/StyleSheet/initialRules.js b/packages/react-native-web/src/exports/StyleSheet/initialRules.js new file mode 100644 index 00000000..d0b74c8c --- /dev/null +++ b/packages/react-native-web/src/exports/StyleSheet/initialRules.js @@ -0,0 +1,36 @@ +/** + * 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. + * + * @flow + */ + +// "media all" wrapper stops browsers throwing errors on each others vendor-prefixed pseudo-elements in selectors +const safeRule = rule => `@media all{${rule}}`; + +const initialRules = [ + // minimal top-level reset + 'html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}', + 'body{margin:0;}', + // minimal form pseudo-element reset + safeRule('button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}'), + safeRule( + '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;}' + ), + // temporary keyframes + '@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%);}' + + '}' +]; + +export default initialRules; diff --git a/packages/react-native-web/src/exports/StyleSheet/staticCss.js b/packages/react-native-web/src/exports/StyleSheet/staticCss.js deleted file mode 100644 index ba624078..00000000 --- a/packages/react-native-web/src/exports/StyleSheet/staticCss.js +++ /dev/null @@ -1,27 +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. - * - * @flow - */ - -export default 'html{' + // css reset - '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::-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;}\n' + - '@keyframes rn-ActivityIndicator-animation{' + - '0%{-webkit-transform:rotate(0deg);transform:rotate(0deg);}' + - '100%{-webkit-transform:rotate(360deg);transform:rotate(360deg);}' + - '}\n' + - '@keyframes rn-ProgressBar-animation{' + - '0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);}' + - '100%{-webkit-transform:translateX(400%);transform:translateX(400%);}' + - '}';