Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@faceyspacey
Last active November 26, 2016 04:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save faceyspacey/453e6ee26d6dae319b48679ea56e9432 to your computer and use it in GitHub Desktop.
Save faceyspacey/453e6ee26d6dae319b48679ea56e9432 to your computer and use it in GitHub Desktop.
RNW className transform concept
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
}
};
@jtag05
Copy link

jtag05 commented Nov 26, 2016

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 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment