mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-24 23:25:40 +00:00
[fix] unitless values for vendor prefixed properties
Problem: Numeric values are suffixed with 'px', unless the property supports unitless values. However, vendor prefixed properties were ignored resulting in invalid CSS values for properties like '-webkit-flex-shrink'. Solution: Apply the upstream solution from React, which includes vendor prefixed properties in the "unitless number" map. Also build a custom vendor prefixer to ensure adequate browser support (i.e., Safari 7 and older Chrome).
This commit is contained in:
@@ -74,6 +74,7 @@
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.6",
|
||||
"babel-preset-react-native": "^2.1.0",
|
||||
"caniuse-api": "^2.0.0",
|
||||
"del-cli": "^1.1.0",
|
||||
"enzyme": "^2.9.1",
|
||||
"enzyme-to-json": "^1.5.1",
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const generateData = require('inline-style-prefixer/generator');
|
||||
const path = require('path');
|
||||
|
||||
const browserList = {
|
||||
chrome: 38,
|
||||
android: 4,
|
||||
firefox: 40,
|
||||
ios_saf: 7,
|
||||
safari: 7,
|
||||
ie: 11,
|
||||
ie_mob: 11,
|
||||
edge: 12,
|
||||
opera: 16,
|
||||
op_mini: 12,
|
||||
and_uc: 9,
|
||||
and_chr: 38
|
||||
};
|
||||
|
||||
generateData(browserList, {
|
||||
staticPath: path.join(__dirname, '../src/modules/prefixStyles/static.js'),
|
||||
});
|
||||
@@ -113,7 +113,8 @@ export default class StyleManager {
|
||||
if (prop !== 'pointerEvents') {
|
||||
Object.keys(cache[prop]).forEach(value => {
|
||||
const className = this.getClassName(prop, value);
|
||||
rules.push(createCssRule(className, prop, value));
|
||||
const rule = createCssRule(className, prop, value);
|
||||
rules.push(rule);
|
||||
});
|
||||
}
|
||||
return rules;
|
||||
|
||||
@@ -28,4 +28,12 @@ describe('apis/StyleSheet/StyleManager', () => {
|
||||
styleManager.setDeclaration('width', '100px');
|
||||
expect(styleManager.getStyleSheetHtml()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('setDeclaration', () => {
|
||||
styleManager.mainSheet.sheet.insertRule = (rule, position) => {
|
||||
// check for regressions in CSS write path (e.g., 0 => 0px)
|
||||
expect(rule.indexOf('-webkit-flex-shrink:0;')).not.toEqual(-1);
|
||||
};
|
||||
styleManager.setDeclaration('flexShrink', 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -103,8 +103,8 @@ function normalizeMouseEvent(nativeEvent) {
|
||||
identifier: touches[0].identifier,
|
||||
locationX: nativeEvent.offsetX,
|
||||
locationY: nativeEvent.offsetY,
|
||||
offsetX: nativeEvent.offsetX,
|
||||
offsetY: nativeEvent.offsetY,
|
||||
offsetX: nativeEvent.offsetX,
|
||||
offsetY: nativeEvent.offsetY,
|
||||
pageX: nativeEvent.pageX,
|
||||
pageY: nativeEvent.pageY,
|
||||
preventDefault: nativeEvent.preventDefault.bind(nativeEvent),
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import prefixAll from 'inline-style-prefixer/static';
|
||||
import createPrefixer from 'inline-style-prefixer/static/createPrefixer';
|
||||
import staticData from './static';
|
||||
|
||||
const prefixAll = createPrefixer(staticData);
|
||||
|
||||
export default prefixAll;
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import crossFade from 'inline-style-prefixer/static/plugins/crossFade';
|
||||
import cursor from 'inline-style-prefixer/static/plugins/cursor';
|
||||
import filter from 'inline-style-prefixer/static/plugins/filter';
|
||||
import flex from 'inline-style-prefixer/static/plugins/flex';
|
||||
import flexboxOld from 'inline-style-prefixer/static/plugins/flexboxOld';
|
||||
import gradient from 'inline-style-prefixer/static/plugins/gradient';
|
||||
import imageSet from 'inline-style-prefixer/static/plugins/imageSet';
|
||||
import position from 'inline-style-prefixer/static/plugins/position';
|
||||
import sizing from 'inline-style-prefixer/static/plugins/sizing';
|
||||
import transition from 'inline-style-prefixer/static/plugins/transition';
|
||||
const w = ['Webkit'];
|
||||
const m = ['Moz'];
|
||||
const ms = ['ms'];
|
||||
const wm = ['Webkit', 'Moz'];
|
||||
const wms = ['Webkit', 'ms'];
|
||||
const wmms = ['Webkit', 'Moz', 'ms'];
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
crossFade,
|
||||
cursor,
|
||||
filter,
|
||||
flex,
|
||||
flexboxOld,
|
||||
gradient,
|
||||
imageSet,
|
||||
position,
|
||||
sizing,
|
||||
transition
|
||||
],
|
||||
prefixMap: {
|
||||
animation: w,
|
||||
animationDelay: w,
|
||||
animationDirection: w,
|
||||
animationFillMode: w,
|
||||
animationDuration: w,
|
||||
animationIterationCount: w,
|
||||
animationName: w,
|
||||
animationPlayState: w,
|
||||
animationTimingFunction: w,
|
||||
appearance: wm,
|
||||
userSelect: wmms,
|
||||
textEmphasisPosition: w,
|
||||
textEmphasis: w,
|
||||
textEmphasisStyle: w,
|
||||
textEmphasisColor: w,
|
||||
boxDecorationBreak: w,
|
||||
clipPath: w,
|
||||
maskImage: w,
|
||||
maskMode: w,
|
||||
maskRepeat: w,
|
||||
maskPosition: w,
|
||||
maskClip: w,
|
||||
maskOrigin: w,
|
||||
maskSize: w,
|
||||
maskComposite: w,
|
||||
mask: w,
|
||||
maskBorderSource: w,
|
||||
maskBorderMode: w,
|
||||
maskBorderSlice: w,
|
||||
maskBorderWidth: w,
|
||||
maskBorderOutset: w,
|
||||
maskBorderRepeat: w,
|
||||
maskBorder: w,
|
||||
maskType: w,
|
||||
textDecorationStyle: w,
|
||||
textDecorationSkip: w,
|
||||
textDecorationLine: w,
|
||||
textDecorationColor: w,
|
||||
filter: w,
|
||||
fontFeatureSettings: w,
|
||||
breakAfter: wmms,
|
||||
breakBefore: wmms,
|
||||
breakInside: wmms,
|
||||
columnCount: wm,
|
||||
columnFill: wm,
|
||||
columnGap: wm,
|
||||
columnRule: wm,
|
||||
columnRuleColor: wm,
|
||||
columnRuleStyle: wm,
|
||||
columnRuleWidth: wm,
|
||||
columns: wm,
|
||||
columnSpan: wm,
|
||||
columnWidth: wm,
|
||||
flex: w,
|
||||
flexBasis: w,
|
||||
flexDirection: w,
|
||||
flexGrow: w,
|
||||
flexFlow: w,
|
||||
flexShrink: w,
|
||||
flexWrap: w,
|
||||
alignContent: w,
|
||||
alignItems: w,
|
||||
alignSelf: w,
|
||||
justifyContent: w,
|
||||
order: w,
|
||||
transform: w,
|
||||
transformOrigin: w,
|
||||
transformOriginX: w,
|
||||
transformOriginY: w,
|
||||
backfaceVisibility: w,
|
||||
perspective: w,
|
||||
perspectiveOrigin: w,
|
||||
transformStyle: w,
|
||||
transformOriginZ: w,
|
||||
backdropFilter: w,
|
||||
fontKerning: w,
|
||||
scrollSnapType: wms,
|
||||
scrollSnapPointsX: wms,
|
||||
scrollSnapPointsY: wms,
|
||||
scrollSnapDestination: wms,
|
||||
scrollSnapCoordinate: wms,
|
||||
shapeImageThreshold: w,
|
||||
shapeImageMargin: w,
|
||||
shapeImageOutside: w,
|
||||
hyphens: wmms,
|
||||
flowInto: wms,
|
||||
flowFrom: wms,
|
||||
regionFragment: wms,
|
||||
textAlignLast: m,
|
||||
tabSize: m,
|
||||
wrapFlow: ms,
|
||||
wrapThrough: ms,
|
||||
wrapMargin: ms,
|
||||
gridTemplateColumns: ms,
|
||||
gridTemplateRows: ms,
|
||||
gridTemplateAreas: ms,
|
||||
gridTemplate: ms,
|
||||
gridAutoColumns: ms,
|
||||
gridAutoRows: ms,
|
||||
gridAutoFlow: ms,
|
||||
grid: ms,
|
||||
gridRowStart: ms,
|
||||
gridColumnStart: ms,
|
||||
gridRowEnd: ms,
|
||||
gridRow: ms,
|
||||
gridColumn: ms,
|
||||
gridColumnEnd: ms,
|
||||
gridColumnGap: ms,
|
||||
gridRowGap: ms,
|
||||
gridArea: ms,
|
||||
gridGap: ms,
|
||||
textSizeAdjust: wms,
|
||||
borderImage: w,
|
||||
borderImageOutset: w,
|
||||
borderImageRepeat: w,
|
||||
borderImageSlice: w,
|
||||
borderImageSource: w,
|
||||
borderImageWidth: w,
|
||||
transitionDelay: w,
|
||||
transitionDuration: w,
|
||||
transitionProperty: w,
|
||||
transitionTimingFunction: w
|
||||
}
|
||||
};
|
||||
@@ -46,4 +46,18 @@ const unitlessNumbers = {
|
||||
shadowOpacity: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Support style names that may come passed in prefixed by adding permutations
|
||||
* of vendor prefixes.
|
||||
*/
|
||||
const prefixes = ['ms', 'Moz', 'O', 'Webkit'];
|
||||
const prefixKey = (prefix: string, key: string) => {
|
||||
return prefix + key.charAt(0).toUpperCase() + key.substring(1);
|
||||
};
|
||||
Object.keys(unitlessNumbers).forEach(prop => {
|
||||
prefixes.forEach(prefix => {
|
||||
unitlessNumbers[prefixKey(prefix, prop)] = unitlessNumbers[prop];
|
||||
});
|
||||
});
|
||||
|
||||
export default unitlessNumbers;
|
||||
|
||||
@@ -894,6 +894,13 @@ browserify-zlib@^0.1.4:
|
||||
dependencies:
|
||||
pako "~0.2.0"
|
||||
|
||||
browserslist@^2.0.0:
|
||||
version "2.2.2"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/browserslist/-/browserslist-2.2.2.tgz#e9b4618b8a01c193f9786beea09f6fd10dbe31c3"
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30000704"
|
||||
electron-to-chromium "^1.3.16"
|
||||
|
||||
bser@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169"
|
||||
@@ -967,6 +974,19 @@ camelcase@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||
|
||||
caniuse-api@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/caniuse-api/-/caniuse-api-2.0.0.tgz#b1ddb5a5966b16f48dc4998444d4bbc6c7d9d834"
|
||||
dependencies:
|
||||
browserslist "^2.0.0"
|
||||
caniuse-lite "^1.0.0"
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000704:
|
||||
version "1.0.30000706"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/caniuse-lite/-/caniuse-lite-1.0.30000706.tgz#bc59abc41ba7d4a3634dda95befded6114e1f24e"
|
||||
|
||||
capture-stack-trace@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d"
|
||||
@@ -1553,6 +1573,10 @@ ejs@^2.5.6:
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.6.tgz#479636bfa3fe3b1debd52087f0acb204b4f19c88"
|
||||
|
||||
electron-to-chromium@^1.3.16:
|
||||
version "1.3.16"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/electron-to-chromium/-/electron-to-chromium-1.3.16.tgz#d0e026735754770901ae301a21664cba45d92f7d"
|
||||
|
||||
elegant-spinner@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
|
||||
@@ -3291,6 +3315,10 @@ lodash.map@^4.4.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
|
||||
lodash.merge@^4.4.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
|
||||
@@ -3319,6 +3347,10 @@ lodash.some@^4.4.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
|
||||
|
||||
lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://artifactory.twitter.biz:443/api/npm/js-virtual/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||
|
||||
Reference in New Issue
Block a user