[fix] RTL style registration and resolution

* Lazy-register RTL variants to generate class names
* Don't RTL-flip translateX
This commit is contained in:
Nicolas Gallagher
2017-04-30 13:35:06 -07:00
parent 03769f7d45
commit c38369ac0f
4 changed files with 40 additions and 43 deletions
@@ -104,7 +104,6 @@ var styles = StyleSheet.create({
height: CIRCLE_SIZE,
borderRadius: CIRCLE_SIZE / 2,
position: 'absolute',
left: 0,
top: 0,
},
container: {
+34 -22
View File
@@ -7,13 +7,14 @@ import flattenArray from '../../modules/flattenArray';
import flattenStyle from './flattenStyle';
import I18nManager from '../I18nManager';
import i18nStyle from './i18nStyle';
import mapKeyValue from '../../modules/mapKeyValue';
import { prefixInlineStyles } from '../../modules/prefixStyles';
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
import StyleManager from './StyleManager';
const emptyObject = {};
const createCacheKey = id => {
const prefix = I18nManager.isRTL ? 'rtl' : 'ltr';
const prefix = 'rn';
return `${prefix}-${id}`;
};
@@ -21,7 +22,7 @@ const classListToString = list => list.join(' ').trim();
class StyleRegistry {
constructor() {
this.cache = {};
this.cache = { ltr: {}, rtl: {} };
this.styleManager = new StyleManager();
}
@@ -34,30 +35,38 @@ class StyleRegistry {
*/
register(flatStyle) {
const id = ReactNativePropRegistry.register(flatStyle);
const key = createCacheKey(id);
const style = createReactDOMStyle(i18nStyle(flatStyle));
const classList = mapKeyValue(style, (prop, value) => {
if (value != null) {
return this.styleManager.setDeclaration(prop, value);
}
});
const className = classList.join(' ').trim();
this.cache[key] = { classList, className };
this._registerById(id);
return id;
}
_registerById(id) {
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
if (!this.cache[dir][id]) {
const style = flattenStyle(id);
const domStyle = createReactDOMStyle(i18nStyle(style));
Object.keys(domStyle).forEach(styleProp => {
const value = domStyle[styleProp];
if (value != null) {
this.styleManager.setDeclaration(styleProp, value);
}
});
this.cache[dir][id] = true;
}
}
/**
* Resolves a React Native style object to DOM attributes
*/
resolve(reactNativeStyle, options) {
resolve(reactNativeStyle, options = emptyObject) {
if (!reactNativeStyle) {
return undefined;
}
// fast and cachable
if (typeof reactNativeStyle === 'number') {
this._registerById(reactNativeStyle);
const key = createCacheKey(reactNativeStyle);
return this._resolveStyleIfNeeded(reactNativeStyle, { key, ...options });
return this._resolveStyleIfNeeded(reactNativeStyle, options, key);
}
// resolve a plain RN style object
@@ -71,13 +80,15 @@ class StyleRegistry {
const flatArray = flattenArray(reactNativeStyle);
let isArrayOfNumbers = true;
for (let i = 0; i < flatArray.length; i++) {
if (typeof flatArray[i] !== 'number') {
const id = flatArray[i];
if (typeof id !== 'number') {
isArrayOfNumbers = false;
break;
} else {
this._registerById(id);
}
}
const key = isArrayOfNumbers ? createCacheKey(flatArray.join('-')) : null;
return this._resolveStyleIfNeeded(flatArray, { key, ...options });
return this._resolveStyleIfNeeded(flatArray, options, key);
}
/**
@@ -166,15 +177,16 @@ class StyleRegistry {
/**
* Caching layer over 'resolveStyle'
*/
_resolveStyleIfNeeded(style, { key, ...rest }) {
_resolveStyleIfNeeded(style, options, key) {
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
if (key) {
if (!this.cache[key]) {
if (!this.cache[dir][key]) {
// slow: convert style object to props and cache
this.cache[key] = this._resolveStyle(style, rest);
this.cache[dir][key] = this._resolveStyle(style, options);
}
return this.cache[key];
return this.cache[dir][key];
}
return this._resolveStyle(style, rest);
return this._resolveStyle(style, options);
}
}
@@ -2,13 +2,12 @@
exports[`apis/StyleSheet/StyleRegistry resolve with register before RTL, resolves to className 1`] = `
Object {
"classList": Array [],
"className": "",
"style": Object {
"marginRight": "10px",
"right": "12.34%",
"textAlign": "right",
},
"classList": Array [
"rn-marginRight-zso239",
"rn-right-1bnbe1j",
"rn-textAlign-1ff274t",
],
"className": "rn-marginRight-zso239 rn-right-1bnbe1j rn-textAlign-1ff274t",
}
`;
-13
View File
@@ -43,17 +43,6 @@ const flipProperty = (prop: String): String => {
return PROPERTIES_TO_SWAP.hasOwnProperty(prop) ? PROPERTIES_TO_SWAP[prop] : prop;
};
/**
* BiDi flip translateX
*/
const flipTransform = (transform: Object): Object => {
const translateX = transform.translateX;
if (translateX != null) {
transform.translateX = additiveInverse(translateX);
}
return transform;
};
const swapLeftRight = (value: String): String => {
return value === 'left' ? 'right' : value === 'right' ? 'left' : value;
};
@@ -81,8 +70,6 @@ const i18nStyle = originalStyle => {
} else if (prop === 'textShadowOffset') {
nextStyle[prop] = value;
nextStyle[prop].width = additiveInverse(value.width);
} else if (prop === 'transform' && Array.isArray(value)) {
nextStyle[prop] = style[prop].map(flipTransform);
} else {
nextStyle[prop] = style[prop];
}