mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-01 17:29:34 +08:00
Compare commits
1 Commits
0.9.13
...
react-nati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc46c1d1a8 |
@@ -15,35 +15,11 @@ html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlig
|
||||
body{margin:0;}
|
||||
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;}
|
||||
.rn-reset{background-color:transparent;color:inherit;font:inherit;list-style:none;margin:0;text-align:inherit;text-decoration:none;}
|
||||
.rn-pointer{cursor:pointer;}
|
||||
}
|
||||
.rn-pointerEvents-12vffkv > *{pointer-events:auto}
|
||||
.rn-pointerEvents-12vffkv{pointer-events:none !important}
|
||||
.rn-alignItems-1oszu61{-ms-flex-align:stretch;-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
|
||||
.rn-borderTopStyle-1efd50x{border-top-style:solid}
|
||||
.rn-borderRightStyle-14skgim{border-right-style:solid}
|
||||
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
|
||||
.rn-borderLeftStyle-mm0ijv{border-left-style:solid}
|
||||
.rn-borderTopWidth-13yce4e{border-top-width:0px}
|
||||
.rn-borderRightWidth-fnigne{border-right-width:0px}
|
||||
.rn-borderBottomWidth-ndvcnb{border-bottom-width:0px}
|
||||
.rn-borderLeftWidth-gxnn5r{border-left-width:0px}
|
||||
.rn-boxSizing-deolkf{box-sizing:border-box}
|
||||
.rn-display-6koalj{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
|
||||
.rn-flexShrink-1qe8dj5{-ms-flex-negative:0;-webkit-flex-shrink:0;flex-shrink:0}
|
||||
.rn-flexBasis-1mlwlqe{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}
|
||||
.rn-flexDirection-eqz5dr{-ms-flex-direction:column;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
|
||||
.rn-marginTop-1mnahxq{margin-top:0px}
|
||||
.rn-marginRight-61z16t{margin-right:0px}
|
||||
.rn-marginBottom-p1pxzi{margin-bottom:0px}
|
||||
.rn-marginLeft-11wrixw{margin-left:0px}
|
||||
.rn-minHeight-ifefl9{min-height:0px}
|
||||
.rn-minWidth-bcqeeo{min-width:0px}
|
||||
.rn-paddingTop-wk8lta{padding-top:0px}
|
||||
.rn-paddingRight-9aemit{padding-right:0px}
|
||||
.rn-paddingBottom-1mdbw0j{padding-bottom:0px}
|
||||
.rn-paddingLeft-gy4na3{padding-left:0px}
|
||||
.rn-position-bnwqim{position:relative}
|
||||
.rn-zIndex-1lgpqti{z-index:0}
|
||||
.rn-flexGrow-16y2uox{-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1}
|
||||
.rn-flexShrink-1wbh5a2{-ms-flex-negative:1;-webkit-flex-shrink:1;flex-shrink:1}
|
||||
.rn-flexBasis-1ro0kt6{-ms-flex-preferred-size:0%;-webkit-flex-basis:0%;flex-basis:0%}"
|
||||
@@ -64,5 +40,11 @@ html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlig
|
||||
body{margin:0;}
|
||||
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;}
|
||||
}</style>"
|
||||
.rn-reset{background-color:transparent;color:inherit;font:inherit;list-style:none;margin:0;text-align:inherit;text-decoration:none;}
|
||||
.rn-pointer{cursor:pointer;}
|
||||
}
|
||||
.rn-view-1d2if7t{-ms-flex-align:stretch;-ms-flex-direction:column;-ms-flex-negative:0;-ms-flex-preferred-size:auto;-webkit-align-items:stretch;-webkit-box-align:stretch;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-basis:auto;-webkit-flex-direction:column;-webkit-flex-shrink:0;align-items:stretch;background-color:transparent;border:0 solid black;box-sizing:border-box;color:inherit;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;flex-basis:auto;flex-direction:column;flex-shrink:0;font:inherit;list-style:none;margin:0px;min-height:0px;min-width:0px;padding:0px;position:relative;text-align:inherit;text-decoration:none;z-index:0}
|
||||
.rn-hitSlop-1be6dej{bottom:0px;left:0px;position:absolute;right:0px;top:0px;z-index:-1}
|
||||
.rn-text-1ogs4z5{background-color:transparent;border-width:0px;box-sizing:border-box;color:inherit;display:inline;font:14px system-ui, -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Ubuntu, \\"Helvetica Neue\\", sans-serif;margin:0px;padding:0px;text-align:inherit;text-decoration:none;white-space:pre-wrap;word-wrap:break-word}
|
||||
.rn-textinput-wwmj4d{-moz-appearance:textfield;-webkit-appearance:none;background-color:transparent;border-radius:0px;border:0 solid black;box-sizing:border-box;font-family:14px System;padding:0px;resize:none}</style>"
|
||||
`;
|
||||
|
||||
@@ -15,9 +15,9 @@ import WebStyleSheet from './WebStyleSheet';
|
||||
const emptyObject = {};
|
||||
const STYLE_ELEMENT_ID = 'react-native-stylesheet';
|
||||
|
||||
const createClassName = (prop, value) => {
|
||||
const hashed = hash(prop + normalizeValue(value));
|
||||
return process.env.NODE_ENV !== 'production' ? `rn-${prop}-${hashed}` : `rn-${hashed}`;
|
||||
const createClassName = (name, value) => {
|
||||
const hashed = hash(name + normalizeValue(value));
|
||||
return process.env.NODE_ENV !== 'production' ? `rn-${name}-${hashed}` : `rn-${hashed}`;
|
||||
};
|
||||
|
||||
const normalizeValue = value => (typeof value === 'object' ? JSON.stringify(value) : value);
|
||||
@@ -69,6 +69,13 @@ export default class StyleSheetManager {
|
||||
return className;
|
||||
}
|
||||
|
||||
injectRule(name, body: string): void {
|
||||
const className = createClassName(name, body);
|
||||
const rule = `.${className}{${body}}`;
|
||||
this._sheet.insertRuleOnce(rule);
|
||||
return className;
|
||||
}
|
||||
|
||||
_addToCache(className, prop, value) {
|
||||
const cache = this._cache;
|
||||
if (!cache.byProp[prop]) {
|
||||
|
||||
@@ -103,10 +103,7 @@ StyleSheetValidation.addValidStylePropTypes({
|
||||
objectFit: oneOf(['fill', 'contain', 'cover', 'none', 'scale-down']),
|
||||
objectPosition: string,
|
||||
pointerEvents: string,
|
||||
tableLayout: string,
|
||||
/* @private */
|
||||
MozAppearance: string,
|
||||
WebkitAppearance: string
|
||||
tableLayout: string
|
||||
});
|
||||
|
||||
export default StyleSheetValidation;
|
||||
|
||||
@@ -10,6 +10,8 @@ html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlig
|
||||
body{margin:0;}
|
||||
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;}
|
||||
.rn-reset{background-color:transparent;color:inherit;font:inherit;list-style:none;margin:0;text-align:inherit;text-decoration:none;}
|
||||
.rn-pointer{cursor:pointer;}
|
||||
}
|
||||
.rn---test-property-ax3bxi{--test-property:test-value}",
|
||||
}
|
||||
|
||||
@@ -39,44 +39,17 @@ describe('StyleSheet/createReactDOMStyle', () => {
|
||||
expect(createReactDOMStyle(style)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('borderWidth styles', () => {
|
||||
test('defaults to 0 when "null"', () => {
|
||||
expect(createReactDOMStyle({ borderWidth: null })).toEqual({
|
||||
borderTopWidth: '0px',
|
||||
borderRightWidth: '0px',
|
||||
borderBottomWidth: '0px',
|
||||
borderLeftWidth: '0px'
|
||||
});
|
||||
expect(createReactDOMStyle({ borderWidth: 2, borderRightWidth: null })).toEqual({
|
||||
borderTopWidth: '2px',
|
||||
borderRightWidth: '0px',
|
||||
borderBottomWidth: '2px',
|
||||
borderLeftWidth: '2px'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('flexbox styles', () => {
|
||||
test('flex defaults', () => {
|
||||
expect(createReactDOMStyle({ display: 'flex' })).toEqual({
|
||||
display: 'flex',
|
||||
flexShrink: 0,
|
||||
flexBasis: 'auto'
|
||||
});
|
||||
});
|
||||
|
||||
test('flex: -1', () => {
|
||||
expect(createReactDOMStyle({ display: 'flex', flex: -1 })).toEqual({
|
||||
display: 'flex',
|
||||
expect(createReactDOMStyle({ flex: -1 })).toEqual({
|
||||
flexBasis: 'auto',
|
||||
flexGrow: 0,
|
||||
flexShrink: 1,
|
||||
flexBasis: 'auto'
|
||||
flexShrink: 1
|
||||
});
|
||||
});
|
||||
|
||||
test('flex: 0', () => {
|
||||
expect(createReactDOMStyle({ display: 'flex', flex: 0 })).toEqual({
|
||||
display: 'flex',
|
||||
expect(createReactDOMStyle({ flex: 0 })).toEqual({
|
||||
flexGrow: 0,
|
||||
flexShrink: 0,
|
||||
flexBasis: '0%'
|
||||
@@ -84,8 +57,7 @@ describe('StyleSheet/createReactDOMStyle', () => {
|
||||
});
|
||||
|
||||
test('flex: 1', () => {
|
||||
expect(createReactDOMStyle({ display: 'flex', flex: 1 })).toEqual({
|
||||
display: 'flex',
|
||||
expect(createReactDOMStyle({ flex: 1 })).toEqual({
|
||||
flexGrow: 1,
|
||||
flexShrink: 1,
|
||||
flexBasis: '0%'
|
||||
@@ -93,8 +65,7 @@ describe('StyleSheet/createReactDOMStyle', () => {
|
||||
});
|
||||
|
||||
test('flex: 10', () => {
|
||||
expect(createReactDOMStyle({ display: 'flex', flex: 10 })).toEqual({
|
||||
display: 'flex',
|
||||
expect(createReactDOMStyle({ flex: 10 })).toEqual({
|
||||
flexGrow: 10,
|
||||
flexShrink: 1,
|
||||
flexBasis: '0%'
|
||||
@@ -103,15 +74,12 @@ describe('StyleSheet/createReactDOMStyle', () => {
|
||||
|
||||
test('flexBasis overrides', () => {
|
||||
// is flex-basis applied?
|
||||
expect(createReactDOMStyle({ display: 'flex', flexBasis: '25%' })).toEqual({
|
||||
display: 'flex',
|
||||
flexShrink: 0,
|
||||
expect(createReactDOMStyle({ flexBasis: '25%' })).toEqual({
|
||||
flexBasis: '25%'
|
||||
});
|
||||
|
||||
// can flex-basis override the 'flex' expansion?
|
||||
expect(createReactDOMStyle({ display: 'flex', flex: 1, flexBasis: '25%' })).toEqual({
|
||||
display: 'flex',
|
||||
expect(createReactDOMStyle({ flex: 1, flexBasis: '25%' })).toEqual({
|
||||
flexGrow: 1,
|
||||
flexShrink: 1,
|
||||
flexBasis: '25%'
|
||||
@@ -120,15 +88,12 @@ describe('StyleSheet/createReactDOMStyle', () => {
|
||||
|
||||
test('flexShrink overrides', () => {
|
||||
// is flex-shrink applied?
|
||||
expect(createReactDOMStyle({ display: 'flex', flexShrink: 1 })).toEqual({
|
||||
display: 'flex',
|
||||
flexShrink: 1,
|
||||
flexBasis: 'auto'
|
||||
expect(createReactDOMStyle({ flexShrink: 1 })).toEqual({
|
||||
flexShrink: 1
|
||||
});
|
||||
|
||||
// can flex-shrink override the 'flex' expansion?
|
||||
expect(createReactDOMStyle({ display: 'flex', flex: 1, flexShrink: 2 })).toEqual({
|
||||
display: 'flex',
|
||||
expect(createReactDOMStyle({ flex: 1, flexShrink: 2 })).toEqual({
|
||||
flexGrow: 1,
|
||||
flexShrink: 2,
|
||||
flexBasis: '0%'
|
||||
|
||||
13
packages/react-native-web/src/exports/StyleSheet/constants.js
vendored
Normal file
13
packages/react-native-web/src/exports/StyleSheet/constants.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Nicolas Gallagher.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
export const monospaceFontStack = 'monospace, monospace';
|
||||
|
||||
export const systemFontStack =
|
||||
'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif';
|
||||
@@ -7,6 +7,7 @@
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
import { monospaceFontStack, systemFontStack } from './constants';
|
||||
import normalizeColor from '../../modules/normalizeColor';
|
||||
import normalizeValue from './normalizeValue';
|
||||
import resolveShadowValue from './resolveShadowValue';
|
||||
@@ -54,18 +55,6 @@ const colorProps = {
|
||||
color: true
|
||||
};
|
||||
|
||||
const borderWidthProps = {
|
||||
borderWidth: true,
|
||||
borderTopWidth: true,
|
||||
borderRightWidth: true,
|
||||
borderBottomWidth: true,
|
||||
borderLeftWidth: true
|
||||
};
|
||||
|
||||
const monospaceFontStack = 'monospace, monospace';
|
||||
const systemFontStack =
|
||||
'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif';
|
||||
|
||||
const alphaSortProps = propsArray =>
|
||||
propsArray.sort((a, b) => {
|
||||
if (a < b) {
|
||||
@@ -167,12 +156,6 @@ const createReducer = (style, styleProps) => {
|
||||
return (resolvedStyle, prop) => {
|
||||
let value = normalizeValue(prop, style[prop]);
|
||||
|
||||
// Make sure the default border width is explicitly set to '0' to avoid
|
||||
// falling back to any unwanted user-agent styles.
|
||||
if (borderWidthProps[prop]) {
|
||||
value = value == null ? normalizeValue(null, 0) : value;
|
||||
}
|
||||
|
||||
// Normalize color values
|
||||
if (colorProps[prop]) {
|
||||
value = normalizeColor(value);
|
||||
@@ -203,21 +186,6 @@ const createReducer = (style, styleProps) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'display': {
|
||||
resolvedStyle.display = value;
|
||||
// A flex container in React Native has these defaults which should be
|
||||
// set only if there is no otherwise supplied flex style.
|
||||
if (style.display === 'flex' && style.flex == null) {
|
||||
if (style.flexShrink == null) {
|
||||
resolvedStyle.flexShrink = 0;
|
||||
}
|
||||
if (style.flexBasis == null) {
|
||||
resolvedStyle.flexBasis = 'auto';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The 'flex' property value in React Native must be a positive integer,
|
||||
// 0, or -1.
|
||||
case 'flex': {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
|
||||
import hyphenateStyleName from 'hyphenate-style-name';
|
||||
import mapKeyValue from '../../modules/mapKeyValue';
|
||||
import normalizeValue from './normalizeValue';
|
||||
import prefixStyles from '../../modules/prefixStyles';
|
||||
|
||||
@@ -27,9 +26,15 @@ const createDeclarationString = (prop, val) => {
|
||||
* createRuleBlock({ width: 20, color: 'blue' });
|
||||
* // => 'color:blue;width:20px'
|
||||
*/
|
||||
const createRuleBlock = style =>
|
||||
mapKeyValue(prefixStyles(style), createDeclarationString)
|
||||
.sort()
|
||||
.join(';');
|
||||
const createRuleBlock = style => {
|
||||
const prefixedStyle = prefixStyles(style);
|
||||
return (
|
||||
Object.keys(prefixedStyle)
|
||||
.map(prop => createDeclarationString(prop, prefixedStyle[prop]))
|
||||
// put short-form and vendor prefixed properties first
|
||||
.sort()
|
||||
.join(';')
|
||||
);
|
||||
};
|
||||
|
||||
export default createRuleBlock;
|
||||
|
||||
33
packages/react-native-web/src/exports/StyleSheet/css.js
vendored
Normal file
33
packages/react-native-web/src/exports/StyleSheet/css.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Nicolas Gallagher.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
import createRuleBlock from './createRuleBlock';
|
||||
import styleResolver from './styleResolver';
|
||||
import { systemFontStack } from './constants';
|
||||
|
||||
const css = {
|
||||
create(rules) {
|
||||
const result = {};
|
||||
Object.keys(rules).forEach(key => {
|
||||
const rule = rules[key];
|
||||
if (rule.font && rule.font.indexOf('System') > -1) {
|
||||
rule.font = rule.font.replace('System', systemFontStack);
|
||||
}
|
||||
if (rule.fontFamily === 'System') {
|
||||
rule.fontFamily = systemFontStack;
|
||||
}
|
||||
const cssRule = createRuleBlock(rule);
|
||||
const className = styleResolver.styleSheetManager.injectRule(key, cssRule);
|
||||
result[key] = className;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
export default css;
|
||||
@@ -12,13 +12,34 @@ const safeRule = rule => `@media all{\n${rule}\n}`;
|
||||
|
||||
const resets = [
|
||||
// minimal top-level reset
|
||||
'html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}',
|
||||
'html{' +
|
||||
'-ms-text-size-adjust:100%;' +
|
||||
'-webkit-text-size-adjust:100%;' +
|
||||
'-webkit-tap-highlight-color:rgba(0,0,0,0);' +
|
||||
'}',
|
||||
'body{margin:0;}',
|
||||
// minimal form pseudo-element reset
|
||||
'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;}'
|
||||
'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;' +
|
||||
'}',
|
||||
// Reset styles for heading, link, and list DOM elements
|
||||
'.rn-reset{' +
|
||||
'background-color:transparent;' +
|
||||
'color:inherit;' +
|
||||
'font:inherit;' +
|
||||
'list-style:none;' +
|
||||
'margin:0;' +
|
||||
'text-align:inherit;' +
|
||||
'text-decoration:none;' +
|
||||
'}',
|
||||
// For pressable elements
|
||||
'.rn-pointer{cursor:pointer;}'
|
||||
];
|
||||
|
||||
const reset = [safeRule(resets.join('\n'))];
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`components/Text prop "onPress" 1`] = `
|
||||
<div
|
||||
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-cursor-1loqt21 rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-1b43r93 rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
|
||||
className="rn-text-1ogs4z5 rn-cursor-1loqt21"
|
||||
data-focusable={true}
|
||||
dir="auto"
|
||||
onClick={[Function]}
|
||||
@@ -13,14 +13,14 @@ exports[`components/Text prop "onPress" 1`] = `
|
||||
|
||||
exports[`components/Text prop "selectable" 1`] = `
|
||||
<div
|
||||
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-1b43r93 rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
|
||||
className="rn-text-1ogs4z5"
|
||||
dir="auto"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`components/Text prop "selectable" 2`] = `
|
||||
<div
|
||||
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-color-homxoj rn-display-1471scf rn-fontFamily-14xgk7a rn-fontSize-1b43r93 rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-userSelect-lrvibr rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
|
||||
className="rn-text-1ogs4z5 rn-userSelect-lrvibr"
|
||||
dir="auto"
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -13,6 +13,7 @@ import applyNativeMethods from '../../modules/applyNativeMethods';
|
||||
import { bool } from 'prop-types';
|
||||
import { Component } from 'react';
|
||||
import createElement from '../createElement';
|
||||
import css from '../StyleSheet/css';
|
||||
import StyleSheet from '../StyleSheet';
|
||||
import TextPropTypes from './TextPropTypes';
|
||||
|
||||
@@ -65,10 +66,10 @@ class Text extends Component<*> {
|
||||
otherProps.onKeyDown = this._createEnterHandler(onPress);
|
||||
}
|
||||
|
||||
otherProps.className = classes.text;
|
||||
// allow browsers to automatically infer the language writing direction
|
||||
otherProps.dir = dir !== undefined ? dir : 'auto';
|
||||
otherProps.style = [
|
||||
styles.initial,
|
||||
this.context.isInAParentText === true && styles.isInAParentText,
|
||||
style,
|
||||
selectable === false && styles.notSelectable,
|
||||
@@ -97,24 +98,24 @@ class Text extends Component<*> {
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
initial: {
|
||||
const classes = css.create({
|
||||
text: {
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
boxSizing: 'border-box',
|
||||
color: 'inherit',
|
||||
display: 'inline',
|
||||
fontFamily: 'System',
|
||||
fontSize: 14,
|
||||
fontStyle: 'inherit',
|
||||
fontVariant: ['inherit'],
|
||||
fontWeight: 'inherit',
|
||||
lineHeight: 'inherit',
|
||||
font: '14px System',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
textDecorationLine: 'none',
|
||||
textAlign: 'inherit',
|
||||
textDecoration: 'none',
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordWrap: 'break-word'
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
isInAParentText: {
|
||||
// inherit parent font styles
|
||||
fontFamily: 'inherit',
|
||||
|
||||
@@ -14,8 +14,8 @@ import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
import { Component } from 'react';
|
||||
import ColorPropType from '../ColorPropType';
|
||||
import createElement from '../createElement';
|
||||
import css from '../StyleSheet/css';
|
||||
import findNodeHandle from '../findNodeHandle';
|
||||
import StyleSheet from '../StyleSheet';
|
||||
import StyleSheetPropType from '../../modules/StyleSheetPropType';
|
||||
import TextInputStylePropTypes from './TextInputStylePropTypes';
|
||||
import TextInputState from '../../modules/TextInputState';
|
||||
@@ -256,6 +256,7 @@ class TextInput extends Component<*> {
|
||||
|
||||
Object.assign(otherProps, {
|
||||
autoCorrect: autoCorrect ? 'on' : 'off',
|
||||
className: classes.textinput,
|
||||
dir: 'auto',
|
||||
onBlur: normalizeEventHandler(this._handleBlur),
|
||||
onChange: normalizeEventHandler(this._handleChange),
|
||||
@@ -266,7 +267,7 @@ class TextInput extends Component<*> {
|
||||
readOnly: !editable,
|
||||
ref: this._setNode,
|
||||
spellCheck: spellCheck != null ? spellCheck : autoCorrect,
|
||||
style: [styles.initial, style]
|
||||
style
|
||||
});
|
||||
|
||||
if (multiline) {
|
||||
@@ -428,18 +429,15 @@ class TextInput extends Component<*> {
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
initial: {
|
||||
const classes = css.create({
|
||||
textinput: {
|
||||
MozAppearance: 'textfield',
|
||||
WebkitAppearance: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: 'black',
|
||||
border: '0 solid black',
|
||||
borderRadius: 0,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: 0,
|
||||
boxSizing: 'border-box',
|
||||
fontFamily: 'System',
|
||||
fontSize: 14,
|
||||
fontFamily: '14px System',
|
||||
padding: 0,
|
||||
resize: 'none'
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import applyLayout from '../../modules/applyLayout';
|
||||
import applyNativeMethods from '../../modules/applyNativeMethods';
|
||||
import { bool } from 'prop-types';
|
||||
import createElement from '../createElement';
|
||||
import css from '../StyleSheet/css';
|
||||
import filterSupportedProps from './filterSupportedProps';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import StyleSheet from '../StyleSheet';
|
||||
@@ -51,14 +52,18 @@ class View extends Component<ViewProps> {
|
||||
|
||||
const { isInAParentText } = this.context;
|
||||
|
||||
supportedProps.className = classes.view;
|
||||
supportedProps.style = StyleSheet.compose(
|
||||
styles.initial,
|
||||
StyleSheet.compose(isInAParentText && styles.inline, this.props.style)
|
||||
isInAParentText && styles.inline,
|
||||
this.props.style
|
||||
);
|
||||
|
||||
if (hitSlop) {
|
||||
const hitSlopStyle = calculateHitSlopStyle(hitSlop);
|
||||
const hitSlopChild = createElement('span', { style: [styles.hitSlop, hitSlopStyle] });
|
||||
const hitSlopChild = createElement('span', {
|
||||
className: classes.hitslop,
|
||||
style: hitSlopStyle
|
||||
});
|
||||
supportedProps.children = React.Children.toArray([hitSlopChild, supportedProps.children]);
|
||||
}
|
||||
|
||||
@@ -66,32 +71,45 @@ class View extends Component<ViewProps> {
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
// https://github.com/facebook/css-layout#default-values
|
||||
initial: {
|
||||
const classes = css.create({
|
||||
view: {
|
||||
alignItems: 'stretch',
|
||||
borderWidth: 0,
|
||||
borderStyle: 'solid',
|
||||
border: '0 solid black',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexBasis: 'auto',
|
||||
flexDirection: 'column',
|
||||
flexShrink: 0,
|
||||
margin: 0,
|
||||
minHeight: 0,
|
||||
minWidth: 0,
|
||||
padding: 0,
|
||||
position: 'relative',
|
||||
zIndex: 0,
|
||||
// fix flexbox bugs
|
||||
minHeight: 0,
|
||||
minWidth: 0
|
||||
},
|
||||
inline: {
|
||||
display: 'inline-flex'
|
||||
// resets for if View is rendered as a link or list DOM element
|
||||
backgroundColor: 'transparent',
|
||||
color: 'inherit',
|
||||
font: 'inherit',
|
||||
listStyle: 'none',
|
||||
textAlign: 'inherit',
|
||||
textDecoration: 'none'
|
||||
},
|
||||
// this zIndex-ordering positions the hitSlop above the View but behind
|
||||
// its children
|
||||
hitSlop: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
zIndex: -1
|
||||
}
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
inline: {
|
||||
display: 'inline-flex'
|
||||
}
|
||||
});
|
||||
|
||||
export default applyLayout(applyNativeMethods(View));
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
|
||||
exports[`modules/createDOMProps includes "rel" values for "a" elements (to securely open external links) 1`] = `" noopener noreferrer"`;
|
||||
|
||||
exports[`modules/createDOMProps includes cursor style for "button" role 1`] = `"rn-cursor-1loqt21"`;
|
||||
exports[`modules/createDOMProps includes base reset style for browser-styled elements 1`] = `"rn-reset"`;
|
||||
|
||||
exports[`modules/createDOMProps includes reset styles for "a" elements 1`] = `"rn-backgroundColor-1niwhzg rn-color-homxoj rn-textDecoration-bauka4"`;
|
||||
exports[`modules/createDOMProps includes base reset style for browser-styled elements 2`] = `"rn-reset"`;
|
||||
|
||||
exports[`modules/createDOMProps includes reset styles for "button" elements 1`] = `"rn-appearance-30o5oe rn-backgroundColor-1niwhzg rn-color-homxoj rn-fontFamily-poiln3 rn-fontSize-7cikom rn-fontStyle-o11vmf rn-fontVariant-ebii48 rn-fontWeight-gul640 rn-lineHeight-t9a87b rn-textAlign-1ttztb7"`;
|
||||
exports[`modules/createDOMProps includes base reset style for browser-styled elements 3`] = `"rn-reset"`;
|
||||
|
||||
exports[`modules/createDOMProps includes reset styles for "ul" elements 1`] = `"rn-listStyle-1ebb2ja"`;
|
||||
exports[`modules/createDOMProps includes base reset style for browser-styled elements 4`] = `"rn-reset"`;
|
||||
|
||||
exports[`modules/createDOMProps includes cursor style for pressable roles 1`] = `"rn-pointer"`;
|
||||
|
||||
exports[`modules/createDOMProps includes cursor style for pressable roles 2`] = `"rn-pointer"`;
|
||||
|
||||
@@ -200,23 +200,15 @@ describe('modules/createDOMProps', () => {
|
||||
expect(props.rel).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('includes reset styles for "a" elements', () => {
|
||||
const props = createDOMProps('a');
|
||||
expect(props.className).toMatchSnapshot();
|
||||
test('includes cursor style for pressable roles', () => {
|
||||
expect(createDOMProps('span', { accessibilityRole: 'link' }).className).toMatchSnapshot();
|
||||
expect(createDOMProps('span', { accessibilityRole: 'button' }).className).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('includes reset styles for "button" elements', () => {
|
||||
const props = createDOMProps('button');
|
||||
expect(props.className).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('includes cursor style for "button" role', () => {
|
||||
const props = createDOMProps('span', { accessibilityRole: 'button' });
|
||||
expect(props.className).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('includes reset styles for "ul" elements', () => {
|
||||
const props = createDOMProps('ul');
|
||||
expect(props.className).toMatchSnapshot();
|
||||
test('includes base reset style for browser-styled elements', () => {
|
||||
expect(createDOMProps('a').className).toMatchSnapshot();
|
||||
expect(createDOMProps('button').className).toMatchSnapshot();
|
||||
expect(createDOMProps('li').className).toMatchSnapshot();
|
||||
expect(createDOMProps('ul').className).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,40 +13,6 @@ import styleResolver from '../../exports/StyleSheet/styleResolver';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const resetStyles = StyleSheet.create({
|
||||
ariaButton: {
|
||||
cursor: 'pointer'
|
||||
},
|
||||
button: {
|
||||
appearance: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
color: 'inherit',
|
||||
fontFamily: 'inherit',
|
||||
fontSize: 'inherit',
|
||||
fontStyle: 'inherit',
|
||||
fontVariant: ['inherit'],
|
||||
fontWeight: 'inherit',
|
||||
lineHeight: 'inherit',
|
||||
textAlign: 'inherit'
|
||||
},
|
||||
heading: {
|
||||
fontFamily: 'inherit',
|
||||
fontSize: 'inherit',
|
||||
fontStyle: 'inherit',
|
||||
fontVariant: ['inherit'],
|
||||
fontWeight: 'inherit',
|
||||
lineHeight: 'inherit'
|
||||
},
|
||||
link: {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'inherit',
|
||||
textDecorationLine: 'none'
|
||||
},
|
||||
list: {
|
||||
listStyle: 'none'
|
||||
}
|
||||
});
|
||||
|
||||
const pointerEventsStyles = StyleSheet.create({
|
||||
auto: {
|
||||
pointerEvents: 'auto'
|
||||
@@ -123,6 +89,8 @@ const createDOMProps = (component, props, styleResolver) => {
|
||||
importantForAccessibility !== 'no-hide-descendants';
|
||||
if (
|
||||
role === 'link' ||
|
||||
component === 'a' ||
|
||||
component === 'button' ||
|
||||
component === 'input' ||
|
||||
component === 'select' ||
|
||||
component === 'textarea'
|
||||
@@ -146,30 +114,53 @@ const createDOMProps = (component, props, styleResolver) => {
|
||||
|
||||
// STYLE
|
||||
// Resolve React Native styles to optimized browser equivalent
|
||||
const reactNativeStyle = [
|
||||
component === 'a' && resetStyles.link,
|
||||
component === 'button' && resetStyles.button,
|
||||
role === 'heading' && resetStyles.heading,
|
||||
component === 'ul' && resetStyles.list,
|
||||
role === 'button' && !disabled && resetStyles.ariaButton,
|
||||
const reactNativeStyle = StyleSheet.compose(
|
||||
pointerEvents && pointerEventsStyles[pointerEvents],
|
||||
providedStyle,
|
||||
placeholderTextColor && { placeholderTextColor }
|
||||
];
|
||||
StyleSheet.compose(
|
||||
providedStyle,
|
||||
placeholderTextColor && { placeholderTextColor }
|
||||
)
|
||||
);
|
||||
const { className, style } = styleResolver(reactNativeStyle);
|
||||
if (className && className.constructor === String) {
|
||||
domProps.className = props.className ? `${props.className} ${className}` : className;
|
||||
}
|
||||
if (style) {
|
||||
domProps.style = style;
|
||||
}
|
||||
|
||||
// CLASSNAME
|
||||
// Apply static style resets
|
||||
let c;
|
||||
// style interactive elements for mouse and mobile browsers
|
||||
if ((role === 'button' || role === 'link') && !disabled) {
|
||||
c = 'rn-pointer';
|
||||
}
|
||||
// style reset various elements (not all are used internally)
|
||||
if (
|
||||
component === 'a' ||
|
||||
component === 'button' ||
|
||||
component === 'li' ||
|
||||
component === 'ul' ||
|
||||
role === 'heading'
|
||||
) {
|
||||
c = 'rn-reset' + (c != null ? ' ' + c : '');
|
||||
}
|
||||
// style from createElement use
|
||||
if (props.className != null) {
|
||||
c = props.className + (c != null ? ' ' + c : '');
|
||||
}
|
||||
// style from React Native StyleSheets
|
||||
if (className != null && className !== '') {
|
||||
c = (c != null ? c + ' ' : '') + className;
|
||||
}
|
||||
if (c != null) {
|
||||
domProps.className = c;
|
||||
}
|
||||
|
||||
// OTHER
|
||||
// Native element ID
|
||||
if (nativeID && nativeID.constructor === String) {
|
||||
domProps.id = nativeID;
|
||||
}
|
||||
// Link security and automation test ids
|
||||
// Link security
|
||||
if (component === 'a' && domProps.target === '_blank') {
|
||||
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
const mapKeyValue = (obj, fn) => {
|
||||
const result = [];
|
||||
for (const key in obj) {
|
||||
if (hasOwnProperty.call(obj, key)) {
|
||||
const r = fn(key, obj[key]);
|
||||
r && result.push(r);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default mapKeyValue;
|
||||
Reference in New Issue
Block a user