Last active
November 26, 2016 04:28
-
-
Save faceyspacey/453e6ee26d6dae319b48679ea56e9432 to your computer and use it in GitHub Desktop.
RNW className transform concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 jss from 'jss' | |
import preset from 'jss-preset-default' | |
//I'm assuming this only needs to be setup once per app, not per file | |
let jssSetup = false; | |
if(!jssSetup) { | |
jss.setup(preset()); | |
jssSetup = true; | |
} | |
let styleElement; | |
let shouldInsertStyleSheet = ExecutionEnvironment.canUseDOM; | |
const STYLE_SHEET_ID = '__react-native-style'; | |
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', | |
`<style id="${STYLE_SHEET_ID}">${defaultStyleSheet}</style>` | |
); | |
shouldInsertStyleSheet = false; | |
} | |
}; | |
const resolveStyle = (style) => { | |
if (typeof style === 'string') { | |
return style; // className generated by `jss.createStyleSheet(styles).attach()` | |
} | |
else if (Array.isArray(style)){ | |
return style.map(s => resolveStyle(s)+' '); | |
} | |
else if (typeof style === 'object') { | |
const className = `generated-class-${Math.floor((Math.random() * 100000) + 1)}`; | |
const styles = { | |
[className]: style // inline style object NOT from `StyleSheet.create()` | |
}; | |
jss.createStyleSheet(styles).attach(); // append generated selector+style to the DOM | |
return className; | |
} | |
else { | |
return ''; | |
} | |
} | |
module.exports = { | |
/** | |
* For testing | |
* @private | |
*/ | |
_reset() { | |
if (styleElement) { | |
document.head.removeChild(styleElement); | |
styleElement = null; | |
shouldInsertStyleSheet = true; | |
} | |
}, | |
absoluteFill: ReactNativePropRegistry.register(absoluteFillObject), | |
absoluteFillObject, | |
create(styles) { | |
const sheet = jss.createStyleSheet(styles).attach(); // goodies! | |
return sheet.classes; | |
}, | |
hairlineWidth: 1, | |
flatten: flattenStyle, | |
/* @platform web */ | |
render() { | |
return <style dangerouslySetInnerHTML={{ __html: defaultStyleSheet }} id={STYLE_SHEET_ID} />; | |
}, | |
/** | |
* Accepts React props and converts style declarations to classNames when necessary | |
* @platform web | |
*/ | |
resolve(props) { | |
let className = props.className || ''; | |
className += ' ' + resolveStyle(props.style); | |
return { className }; // note: we'll deal with display and pointer events `styleAsClassName` if we go this route | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've been experimenting with react-native-web lately, and it's use of inline styles were a major drag for me. This is awesome 👍