[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, height: CIRCLE_SIZE,
borderRadius: CIRCLE_SIZE / 2, borderRadius: CIRCLE_SIZE / 2,
position: 'absolute', position: 'absolute',
left: 0,
top: 0, top: 0,
}, },
container: { container: {
+34 -22
View File
@@ -7,13 +7,14 @@ import flattenArray from '../../modules/flattenArray';
import flattenStyle from './flattenStyle'; import flattenStyle from './flattenStyle';
import I18nManager from '../I18nManager'; import I18nManager from '../I18nManager';
import i18nStyle from './i18nStyle'; import i18nStyle from './i18nStyle';
import mapKeyValue from '../../modules/mapKeyValue';
import { prefixInlineStyles } from '../../modules/prefixStyles'; import { prefixInlineStyles } from '../../modules/prefixStyles';
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry'; import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
import StyleManager from './StyleManager'; import StyleManager from './StyleManager';
const emptyObject = {};
const createCacheKey = id => { const createCacheKey = id => {
const prefix = I18nManager.isRTL ? 'rtl' : 'ltr'; const prefix = 'rn';
return `${prefix}-${id}`; return `${prefix}-${id}`;
}; };
@@ -21,7 +22,7 @@ const classListToString = list => list.join(' ').trim();
class StyleRegistry { class StyleRegistry {
constructor() { constructor() {
this.cache = {}; this.cache = { ltr: {}, rtl: {} };
this.styleManager = new StyleManager(); this.styleManager = new StyleManager();
} }
@@ -34,30 +35,38 @@ class StyleRegistry {
*/ */
register(flatStyle) { register(flatStyle) {
const id = ReactNativePropRegistry.register(flatStyle); const id = ReactNativePropRegistry.register(flatStyle);
const key = createCacheKey(id); this._registerById(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 };
return 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 * Resolves a React Native style object to DOM attributes
*/ */
resolve(reactNativeStyle, options) { resolve(reactNativeStyle, options = emptyObject) {
if (!reactNativeStyle) { if (!reactNativeStyle) {
return undefined; return undefined;
} }
// fast and cachable // fast and cachable
if (typeof reactNativeStyle === 'number') { if (typeof reactNativeStyle === 'number') {
this._registerById(reactNativeStyle);
const key = createCacheKey(reactNativeStyle); const key = createCacheKey(reactNativeStyle);
return this._resolveStyleIfNeeded(reactNativeStyle, { key, ...options }); return this._resolveStyleIfNeeded(reactNativeStyle, options, key);
} }
// resolve a plain RN style object // resolve a plain RN style object
@@ -71,13 +80,15 @@ class StyleRegistry {
const flatArray = flattenArray(reactNativeStyle); const flatArray = flattenArray(reactNativeStyle);
let isArrayOfNumbers = true; let isArrayOfNumbers = true;
for (let i = 0; i < flatArray.length; i++) { for (let i = 0; i < flatArray.length; i++) {
if (typeof flatArray[i] !== 'number') { const id = flatArray[i];
if (typeof id !== 'number') {
isArrayOfNumbers = false; isArrayOfNumbers = false;
break; } else {
this._registerById(id);
} }
} }
const key = isArrayOfNumbers ? createCacheKey(flatArray.join('-')) : null; 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' * Caching layer over 'resolveStyle'
*/ */
_resolveStyleIfNeeded(style, { key, ...rest }) { _resolveStyleIfNeeded(style, options, key) {
const dir = I18nManager.isRTL ? 'rtl' : 'ltr';
if (key) { if (key) {
if (!this.cache[key]) { if (!this.cache[dir][key]) {
// slow: convert style object to props and cache // 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`] = ` exports[`apis/StyleSheet/StyleRegistry resolve with register before RTL, resolves to className 1`] = `
Object { Object {
"classList": Array [], "classList": Array [
"className": "", "rn-marginRight-zso239",
"style": Object { "rn-right-1bnbe1j",
"marginRight": "10px", "rn-textAlign-1ff274t",
"right": "12.34%", ],
"textAlign": "right", "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; 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 => { const swapLeftRight = (value: String): String => {
return value === 'left' ? 'right' : value === 'right' ? 'left' : value; return value === 'left' ? 'right' : value === 'right' ? 'left' : value;
}; };
@@ -81,8 +70,6 @@ const i18nStyle = originalStyle => {
} else if (prop === 'textShadowOffset') { } else if (prop === 'textShadowOffset') {
nextStyle[prop] = value; nextStyle[prop] = value;
nextStyle[prop].width = additiveInverse(value.width); nextStyle[prop].width = additiveInverse(value.width);
} else if (prop === 'transform' && Array.isArray(value)) {
nextStyle[prop] = style[prop].map(flipTransform);
} else { } else {
nextStyle[prop] = style[prop]; nextStyle[prop] = style[prop];
} }