mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-27 08:13:46 +00:00
Minor StyleSheet/injector refactor; small fixes
This commit is contained in:
@@ -113,7 +113,7 @@ var Cell = React.createClass({
|
||||
case 2:
|
||||
return styles.cellTextO;
|
||||
default:
|
||||
return {};
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ 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}
|
||||
@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\\:auto,.rn_pointerEvents\\:box-only,.rn_pointerEvents\\:box-none *{pointer-events:auto}.rn_pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn_pointerEvents\\:box-none{pointer-events:none}
|
||||
.rn-pointerEvents\\:auto,.rn_pointerEvents\\:box-only,.rn-pointerEvents\\:box-none *{pointer-events:auto}.rn-pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn-pointerEvents\\:box-none{pointer-events:none}
|
||||
.rn-bottom\\:0px{bottom:0px}
|
||||
.rn-left\\:0px{left:0px}
|
||||
.rn-position\\:absolute{position:absolute}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to className 1`] = `
|
||||
exports[`apis/StyleSheet/registry resolve with register, resolves to className 1`] = `
|
||||
Object {
|
||||
"className": "
|
||||
rn-borderTopColor:red
|
||||
@@ -17,7 +17,7 @@ rn-width:100px",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to className 2`] = `
|
||||
exports[`apis/StyleSheet/registry resolve with register, resolves to className 2`] = `
|
||||
Object {
|
||||
"className": "
|
||||
rn-borderTopColor:red
|
||||
@@ -36,7 +36,7 @@ rn-width:200px",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to className 3`] = `
|
||||
exports[`apis/StyleSheet/registry resolve with register, resolves to className 3`] = `
|
||||
Object {
|
||||
"className": "
|
||||
rn-borderTopColor:red
|
||||
@@ -55,7 +55,7 @@ rn-width:100px",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to mixed 1`] = `
|
||||
exports[`apis/StyleSheet/registry resolve with register, resolves to mixed 1`] = `
|
||||
Object {
|
||||
"className": "
|
||||
rn-left:50px
|
||||
@@ -75,7 +75,7 @@ rn-position:absolute",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to mixed 2`] = `
|
||||
exports[`apis/StyleSheet/registry resolve with register, resolves to mixed 2`] = `
|
||||
Object {
|
||||
"className": "
|
||||
rn-left:50px
|
||||
@@ -95,7 +95,7 @@ rn-width:200px",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to mixed 3`] = `
|
||||
exports[`apis/StyleSheet/registry resolve with register, resolves to mixed 3`] = `
|
||||
Object {
|
||||
"className": "
|
||||
rn-left:50px
|
||||
@@ -115,7 +115,7 @@ rn-position:absolute",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve without stylesheet, resolves to inline styles 1`] = `
|
||||
exports[`apis/StyleSheet/registry resolve without register, resolves to inline styles 1`] = `
|
||||
Object {
|
||||
"className": "
|
||||
",
|
||||
@@ -136,7 +136,7 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve without stylesheet, resolves to inline styles 2`] = `
|
||||
exports[`apis/StyleSheet/registry resolve without register, resolves to inline styles 2`] = `
|
||||
Object {
|
||||
"className": "
|
||||
",
|
||||
@@ -157,7 +157,7 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`apis/StyleSheet/registry resolve without stylesheet, resolves to inline styles 3`] = `
|
||||
exports[`apis/StyleSheet/registry resolve without register, resolves to inline styles 3`] = `
|
||||
Object {
|
||||
"className": "
|
||||
",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import injector from '../injector';
|
||||
|
||||
describe('apis/StyleSheet', () => {
|
||||
describe('apis/StyleSheet/injector', () => {
|
||||
beforeEach(() => {
|
||||
document.head.insertAdjacentHTML('afterbegin', `
|
||||
<style id="react-native-stylesheet">
|
||||
@@ -13,10 +13,10 @@ describe('apis/StyleSheet', () => {
|
||||
});
|
||||
|
||||
test('hydrates from SSR', () => {
|
||||
const classList = injector.getAvailableClassNames();
|
||||
expect(classList).toEqual([
|
||||
'rn-alignItems\\:stretch',
|
||||
'rn-position\\:top'
|
||||
]);
|
||||
const classList = injector.getClassNames();
|
||||
expect(classList).toEqual({
|
||||
'rn-alignItems\\:stretch': true,
|
||||
'rn-position\\:top': true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,21 +33,21 @@ describe('apis/StyleSheet/registry', () => {
|
||||
expect(resolve3).not.toEqual(resolve4);
|
||||
};
|
||||
|
||||
test('with stylesheet, resolves to className', () => {
|
||||
test('with register, resolves to className', () => {
|
||||
const a = StyleRegistry.register(styleA);
|
||||
const b = StyleRegistry.register(styleB);
|
||||
const c = StyleRegistry.register(styleC);
|
||||
testResolve(a, b, c);
|
||||
});
|
||||
|
||||
test('with stylesheet, resolves to mixed', () => {
|
||||
test('with register, resolves to mixed', () => {
|
||||
const a = styleA;
|
||||
const b = StyleRegistry.register(styleB);
|
||||
const c = StyleRegistry.register(styleC);
|
||||
testResolve(a, b, c);
|
||||
});
|
||||
|
||||
test('without stylesheet, resolves to inline styles', () => {
|
||||
test('without register, resolves to inline styles', () => {
|
||||
testResolve(styleA, styleB, styleC);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,11 +28,12 @@ const initialize = () => {
|
||||
);
|
||||
injector.addRule(
|
||||
'pointer-events',
|
||||
'.rn_pointerEvents\\:auto,.rn_pointerEvents\\:box-only,.rn_pointerEvents\\:box-none *{pointer-events:auto}' +
|
||||
'.rn_pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn_pointerEvents\\:box-none{pointer-events:none}'
|
||||
'.rn-pointerEvents\\:auto,.rn_pointerEvents\\:box-only,.rn-pointerEvents\\:box-none *{pointer-events:auto}' +
|
||||
'.rn-pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn-pointerEvents\\:box-none{pointer-events:none}'
|
||||
);
|
||||
|
||||
StyleRegistry.initialize();
|
||||
const classNames = injector.getClassNames();
|
||||
StyleRegistry.initialize(classNames);
|
||||
};
|
||||
|
||||
export default initialize;
|
||||
|
||||
@@ -5,14 +5,31 @@
|
||||
|
||||
import asap from 'asap';
|
||||
|
||||
const emptyObject = {};
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
const CLASSNAME_REXEP = /\.rn-([^{;\s]+)/g;
|
||||
const STYLE_ELEMENT_ID = 'react-native-stylesheet';
|
||||
|
||||
let registry = {};
|
||||
let isDirty = false;
|
||||
let styleNode = null;
|
||||
|
||||
/**
|
||||
* Registers a rule and requests an update to the style sheet
|
||||
*/
|
||||
const addRule = (key, rule) => {
|
||||
if (!registry[key]) {
|
||||
registry[key] = rule;
|
||||
isDirty = true;
|
||||
if (global.document) {
|
||||
asap(frame);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string of the registered rules
|
||||
*/
|
||||
const getStyleText = () => {
|
||||
/* eslint prefer-template:0 */
|
||||
let result = '\n';
|
||||
@@ -24,66 +41,66 @@ const getStyleText = () => {
|
||||
return result;
|
||||
};
|
||||
|
||||
// TODO: SSR support
|
||||
const getAvailableClassNames = () => {
|
||||
/**
|
||||
* Returns an HTML string for server rendering
|
||||
*/
|
||||
const getStyleSheetHtml = () => `<style id="${STYLE_ELEMENT_ID}">${getStyleText()}</style>`;
|
||||
|
||||
const reset = () => { registry = {}; };
|
||||
|
||||
/**
|
||||
* Finds or injects the style sheet when in a browser environment
|
||||
*/
|
||||
let styleNode = null;
|
||||
const getStyleNode = () => {
|
||||
if (global.document) {
|
||||
if (!styleNode) {
|
||||
// look for existing style sheet (could also be server-rendered)
|
||||
styleNode = document.getElementById(STYLE_ELEMENT_ID);
|
||||
if (!styleNode) {
|
||||
// if there is no existing stylesheet, inject it style sheet
|
||||
document.head.insertAdjacentHTML('afterbegin', getStyleSheetHtml());
|
||||
styleNode = document.getElementById(STYLE_ELEMENT_ID);
|
||||
}
|
||||
}
|
||||
if (styleNode) {
|
||||
const text = styleNode.textContent;
|
||||
return text.match(CLASSNAME_REXEP).map((name) => name.slice(1));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
return styleNode;
|
||||
}
|
||||
};
|
||||
|
||||
const createStyleHTML = (text) => `<style id="${STYLE_ELEMENT_ID}">${text}</style>`;
|
||||
/**
|
||||
* Determines which classes are available in the existing document. Doesn't
|
||||
* rely on the registry so it can be used to read class names from a SSR style
|
||||
* sheet.
|
||||
*/
|
||||
const getClassNames = () => {
|
||||
const styleNode = getStyleNode();
|
||||
if (styleNode) {
|
||||
const text = styleNode.textContent;
|
||||
const matches = text.match(CLASSNAME_REXEP);
|
||||
if (matches) {
|
||||
return matches.map((name) => name.slice(1)).reduce((classMap, className) => {
|
||||
classMap[className] = true;
|
||||
return classMap;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
return emptyObject;
|
||||
};
|
||||
|
||||
const frame = () => {
|
||||
if (!isDirty || !global.document) { return; }
|
||||
isDirty = false;
|
||||
styleNode = styleNode || document.getElementById(STYLE_ELEMENT_ID);
|
||||
|
||||
if (!styleNode) {
|
||||
document.head.insertAdjacentHTML('afterbegin', createStyleHTML());
|
||||
styleNode = document.getElementById(STYLE_ELEMENT_ID);
|
||||
}
|
||||
|
||||
const css = getStyleText();
|
||||
|
||||
if (styleNode.styleSheet) {
|
||||
styleNode.styleSheet.cssText = css;
|
||||
} else {
|
||||
/* eslint no-cond-assign:0 */
|
||||
let last;
|
||||
while (last = styleNode.lastChild) {
|
||||
styleNode.removeChild(last);
|
||||
}
|
||||
styleNode.appendChild(document.createTextNode(css));
|
||||
const styleNode = getStyleNode();
|
||||
if (styleNode) {
|
||||
const css = getStyleText();
|
||||
styleNode.textContent = css;
|
||||
}
|
||||
};
|
||||
|
||||
const addRule = (key, rule) => {
|
||||
if (!registry[key]) {
|
||||
registry[key] = rule;
|
||||
if (!isDirty) {
|
||||
isDirty = true;
|
||||
if (global.document) {
|
||||
asap(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getStyleSheetHtml = () => createStyleHTML(getStyleText());
|
||||
|
||||
module.exports = {
|
||||
addRule,
|
||||
getAvailableClassNames,
|
||||
getClassNames,
|
||||
getStyleSheetHtml,
|
||||
reset: () => { registry = {}; }
|
||||
reset
|
||||
};
|
||||
|
||||
@@ -67,7 +67,6 @@ const registerStyle = (id, flatStyle) => {
|
||||
*/
|
||||
const resolveProps = (reactNativeStyle) => {
|
||||
const flatStyle = flattenStyle(reactNativeStyle);
|
||||
|
||||
const domStyle = createReactDOMStyle(flatStyle);
|
||||
const style = {};
|
||||
|
||||
@@ -122,9 +121,8 @@ const resolvePropsIfNeeded = (key, style) => {
|
||||
* Web style registry
|
||||
*/
|
||||
const StyleRegistry = {
|
||||
initialize() {
|
||||
const classNames = injector.getAvailableClassNames();
|
||||
classNames.forEach((className) => { injectedClassNames[className] = true; });
|
||||
initialize(classNames) {
|
||||
injectedClassNames = classNames;
|
||||
},
|
||||
|
||||
reset() {
|
||||
|
||||
Reference in New Issue
Block a user