diff --git a/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.js b/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.js index 006c0e5d1d..60032f1c2c 100644 --- a/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.js @@ -113,7 +113,7 @@ describe.each([['concurrent'], ['legacy']])('AppRegistry', (mode) => { "[stylesheet-group=\\"2\\"] {}", ".r-display-xoduu5 {display: inline-flex;}", ".r-flex-13awgt0 {flex: 1;}", - "[stylesheet-group=\\"2.2\\"] {}", + "[stylesheet-group=\\"3\\"] {}", ".r-bottom-1p0dtai {bottom: 0px;}", ".r-left-1d2f490 {left: 0px;}", ".r-pointerEvents-105ug2t {pointer-events: auto !important;}", diff --git a/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.node.js b/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.node.js index 7dc3742099..0ea140dc0e 100644 --- a/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.node.js +++ b/packages/react-native-web/src/exports/AppRegistry/__tests__/index-test.node.js @@ -48,7 +48,7 @@ describe('AppRegistry', () => { [stylesheet-group=\\"2\\"]{} .r-display-xoduu5{display:inline-flex;} .r-flex-13awgt0{flex:1;} - [stylesheet-group=\\"2.2\\"]{} + [stylesheet-group=\\"3\\"]{} .r-bottom-1p0dtai{bottom:0px;} .r-left-1d2f490{left:0px;} .r-pointerEvents-105ug2t{pointer-events:auto!important;} @@ -92,7 +92,7 @@ describe('AppRegistry', () => { [stylesheet-group=\\"2\\"]{} .r-display-xoduu5{display:inline-flex;} .r-flex-13awgt0{flex:1;} - [stylesheet-group=\\"2.2\\"]{} + [stylesheet-group=\\"3\\"]{} .r-bottom-1p0dtai{bottom:0px;} .r-left-1d2f490{left:0px;} .r-pointerEvents-105ug2t{pointer-events:auto!important;} @@ -129,7 +129,7 @@ describe('AppRegistry', () => { .r-borderWidth-1bee2fs{border-bottom-width:1234px;border-left-width:1234px;border-right-width:1234px;border-top-width:1234px;} .r-display-xoduu5{display:inline-flex;} .r-flex-13awgt0{flex:1;} - [stylesheet-group=\\"2.2\\"]{} + [stylesheet-group=\\"3\\"]{} .r-backgroundColor-aot4c7{background-color:rgba(128,0,128,1.00);} .r-bottom-1p0dtai{bottom:0px;} .r-left-1d2f490{left:0px;} diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-createReactDOMStyle-test.js b/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-createReactDOMStyle-test.js index 3a0230930e..5d24610ce8 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-createReactDOMStyle-test.js +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-createReactDOMStyle-test.js @@ -35,12 +35,12 @@ describe('compiler/createReactDOMStyle', () => { borderBottomWidth: 1, borderWidth: 0, marginTop: 50, - marginVertical: 25, + marginBlock: 25, margin: 10, overflow: 'hidden', overscrollBehavior: 'contain', paddingLeft: 50, - paddingHorizontal: 25, + paddingInline: 25, padding: 10 }; diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-test.js b/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-test.js index 281607775f..525ff47ae2 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-test.js +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/compiler-test.js @@ -9,7 +9,7 @@ import { atomic, classic, inline } from '../compiler'; describe('StyleSheet/compile', () => { describe('atomic', () => { - test.only('converts style to atomic CSS', () => { + test('converts style to atomic CSS', () => { const result = atomic({ animationDirection: ['alternate', 'alternate-reverse'], animationKeyframes: [ @@ -17,13 +17,14 @@ describe('StyleSheet/compile', () => { { from: { left: 0 }, to: { left: 10 } } ], fontFamily: 'System', - marginHorizontal: 10, - marginStart: 1, - marginEnd: 2, + insetInlineStart: '12.34%', + marginBlockEnd: 5, + marginInline: 10, + marginInlineEnd: 2, + marginInlineStart: 1, placeholderTextColor: 'gray', scrollbarWidth: 'none', pointerEvents: 'box-only', - start: '12.34%', textAlign: 'start', transform: 'translateX(50px) scale(-1)' }); @@ -36,22 +37,23 @@ describe('StyleSheet/compile', () => { "animationDirection": "r-animationDirection-1kmv48j", "animationKeyframes": "r-animationKeyframes-zacbmr", "fontFamily": "r-fontFamily-1qd0xha", - "marginEnd": [ - "r-marginRight-a5pmau", - "r-marginLeft-9cviqr", + "insetInlineStart": [ + "r-insetInlineStart-1xn1m1p", + "r-insetInlineStart-1y2vi53", ], - "marginHorizontal": "r-marginHorizontal-vlx1xi", - "marginStart": [ - "r-marginLeft-13kc5u0", - "r-marginRight-1knfw1x", + "marginBlockEnd": "r-marginBlockEnd-1xf1q1v", + "marginInline": "r-marginInline-lcslpx", + "marginInlineEnd": [ + "r-marginInlineEnd-n2wkgt", + "r-marginInlineEnd-r7lizz", + ], + "marginInlineStart": [ + "r-marginInlineStart-hjq6k0", + "r-marginInlineStart-1iwt575", ], "placeholderTextColor": "r-placeholderTextColor-1418aci", "pointerEvents": "r-pointerEvents-ah5dr5", "scrollbarWidth": "r-scrollbarWidth-2eszeu", - "start": [ - "r-left-2s0hu9", - "r-right-1bnbe1j", - ], "textAlign": [ "r-textAlign-fdjqy7", "r-textAlign-1ff274t", @@ -63,7 +65,7 @@ describe('StyleSheet/compile', () => { [ ".r-animationDirection-1kmv48j{animation-direction:alternate,alternate-reverse;}", ], - 2.2, + 3, ], [ [ @@ -73,96 +75,102 @@ describe('StyleSheet/compile', () => { "@-webkit-keyframes r-animation-5azpl5{from{left:0px;}to{left:10px;}}", "@keyframes r-animation-5azpl5{from{left:0px;}to{left:10px;}}", ], - 2.2, + 3, ], [ [ ".r-fontFamily-1qd0xha{font-family:-apple-system,BlinkMacSystemFont,\\"Segoe UI\\",Roboto,Helvetica,Arial,sans-serif;}", ], + 3, + ], + [ + [ + ".r-insetInlineStart-1xn1m1p{left:12.34%;}", + ], 2.2, ], [ [ - ".r-marginRight-a5pmau{margin-right:2px;}", + ".r-insetInlineStart-1y2vi53{right:12.34%;}", ], 2.2, ], [ [ - ".r-marginLeft-9cviqr{margin-left:2px;}", + ".r-marginBlockEnd-1xf1q1v{margin-bottom:5px;}", ], 2.2, ], [ [ - ".r-marginHorizontal-vlx1xi{margin-left:10px;margin-right:10px;}", + ".r-marginInline-lcslpx{margin-left:10px;margin-right:10px;}", ], 2.1, ], [ [ - ".r-marginLeft-13kc5u0{margin-left:1px;}", + ".r-marginInlineEnd-n2wkgt{margin-right:2px;}", ], 2.2, ], [ [ - ".r-marginRight-1knfw1x{margin-right:1px;}", + ".r-marginInlineEnd-r7lizz{margin-left:2px;}", ], 2.2, ], [ [ - ".r-placeholderTextColor-1418aci::-webkit-input-placeholder{color:rgba(128,128,128,1.00);opacity:1;}", - ".r-placeholderTextColor-1418aci::-moz-placeholder{color:rgba(128,128,128,1.00);opacity:1;}", - ".r-placeholderTextColor-1418aci:-ms-input-placeholder{color:rgba(128,128,128,1.00);opacity:1;}", - ".r-placeholderTextColor-1418aci::placeholder{color:rgba(128,128,128,1.00);opacity:1;}", + ".r-marginInlineStart-hjq6k0{margin-left:1px;}", ], 2.2, ], [ [ - ".r-pointerEvents-ah5dr5>*{pointer-events:none;}", - ".r-pointerEvents-ah5dr5{pointer-events:auto!important;}", + ".r-marginInlineStart-1iwt575{margin-right:1px;}", ], 2.2, ], [ [ - ".r-scrollbarWidth-2eszeu::-webkit-scrollbar{display:none}", - ".r-scrollbarWidth-2eszeu{scrollbar-width:none;}", + ".r-placeholderTextColor-1418aci::-webkit-input-placeholder{color:rgba(128,128,128,1.00);opacity:1;}", + ".r-placeholderTextColor-1418aci::-moz-placeholder{color:rgba(128,128,128,1.00);opacity:1;}", + ".r-placeholderTextColor-1418aci:-ms-input-placeholder{color:rgba(128,128,128,1.00);opacity:1;}", + ".r-placeholderTextColor-1418aci::placeholder{color:rgba(128,128,128,1.00);opacity:1;}", ], - 2.2, + 3, ], [ [ - ".r-left-2s0hu9{left:12.34%;}", + ".r-pointerEvents-ah5dr5>*{pointer-events:none;}", + ".r-pointerEvents-ah5dr5{pointer-events:auto!important;}", ], - 2.2, + 3, ], [ [ - ".r-right-1bnbe1j{right:12.34%;}", + ".r-scrollbarWidth-2eszeu::-webkit-scrollbar{display:none}", + ".r-scrollbarWidth-2eszeu{scrollbar-width:none;}", ], - 2.2, + 3, ], [ [ ".r-textAlign-fdjqy7{text-align:left;}", ], - 2.2, + 3, ], [ [ ".r-textAlign-1ff274t{text-align:right;}", ], - 2.2, + 3, ], [ [ ".r-transform-d7xd9i{transform:translateX(50px) scale(-1);}", ], - 2.2, + 3, ], ], ] @@ -179,17 +187,17 @@ describe('StyleSheet/compile', () => { { '0%': { top: 0 }, '50%': { top: 5 }, '100%': { top: 10 } }, { from: { left: 0 }, to: { left: 10 } } ], - marginHorizontal: 10, + marginInline: 10, font: '14px System', transform: 'translateX(50px) scale(-1)' }, - 'text' + 'test' ); expect(result).toMatchInlineSnapshot(` [ { "$$css": true, - "css-text-1jr0ypv": "css-text-1jr0ypv", + "css-test-tbk4su": "css-test-tbk4su", }, [ [ @@ -198,7 +206,7 @@ describe('StyleSheet/compile', () => { "@keyframes r-animation-8jhqzh{0%{top:0px;}50%{top:5px;}100%{top:10px;}}", "@-webkit-keyframes r-animation-5azpl5{from{left:0px;}to{left:10px;}}", "@keyframes r-animation-5azpl5{from{left:0px;}to{left:10px;}}", - ".css-text-1jr0ypv{animation-direction:alternate,alternate-reverse;animation-name:r-animation-8jhqzh,r-animation-5azpl5;font:14px -apple-system,BlinkMacSystemFont,\\"Segoe UI\\",Roboto,Helvetica,Arial,sans-serif;margin-left:10px;margin-right:10px;transform:translateX(50px);}", + ".css-test-tbk4su{animation-direction:alternate,alternate-reverse;animation-name:r-animation-8jhqzh,r-animation-5azpl5;font:14px -apple-system,BlinkMacSystemFont,\\"Segoe UI\\",Roboto,Helvetica,Arial,sans-serif;margin-left:10px;margin-right:10px;transform:translateX(50px) scale(-1);}", ], 1, ], @@ -211,7 +219,8 @@ describe('StyleSheet/compile', () => { describe('inline', () => { test('converts style to inline styles', () => { const result = inline({ - marginHorizontal: 10, + marginBlockEnd: 5, + marginInline: 10, display: 'flex', flexShrink: 1 }); @@ -220,6 +229,7 @@ describe('StyleSheet/compile', () => { { "display": "flex", "flexShrink": 1, + "marginBottom": "5px", "marginLeft": "10px", "marginRight": "10px", } @@ -276,12 +286,13 @@ describe('StyleSheet/compile', () => { test(`converts "start" properties for ${dir}`, () => { const initial = { - borderStartColor: 'red', - borderStartStyle: 'solid', - borderStartWidth: 1, - start: 1, - marginStart: 5, - paddingStart: 10 + borderInlineStartColor: 'red', + borderInlineStartStyle: 'solid', + borderInlineStartWidth: 1, + insetInlineStart: 1, + marginBlockStart: 5, + marginInlineStart: 5, + paddingInlineStart: 10 }; const expectedLTR = { @@ -290,6 +301,7 @@ describe('StyleSheet/compile', () => { borderLeftWidth: '1px', left: '1px', marginLeft: '5px', + marginTop: '5px', paddingLeft: '10px' }; const expectedRTL = { @@ -298,6 +310,7 @@ describe('StyleSheet/compile', () => { borderRightWidth: '1px', right: '1px', marginRight: '5px', + marginTop: '5px', paddingRight: '10px' }; expect(inline(initial, isRTL)).toEqual( @@ -307,12 +320,13 @@ describe('StyleSheet/compile', () => { test(`converts "end" properties for ${dir}`, () => { const initial = { - borderEndColor: 'red', - borderEndStyle: 'solid', - borderEndWidth: 1, - end: 1, - marginEnd: 5, - paddingEnd: 10 + borderInlineEndColor: 'red', + borderInlineEndStyle: 'solid', + borderInlineEndWidth: 1, + insetInlineEnd: 1, + marginBlockEnd: 5, + marginInlineEnd: 5, + paddingInlineEnd: 10 }; const expectedLTR = { @@ -320,6 +334,7 @@ describe('StyleSheet/compile', () => { borderRightStyle: 'solid', borderRightWidth: '1px', right: '1px', + marginBottom: '5px', marginRight: '5px', paddingRight: '10px' }; @@ -328,6 +343,7 @@ describe('StyleSheet/compile', () => { borderLeftStyle: 'solid', borderLeftWidth: '1px', left: '1px', + marginBottom: '5px', marginLeft: '5px', paddingLeft: '10px' }; @@ -341,7 +357,7 @@ describe('StyleSheet/compile', () => { clear: 'start', float: 'start', textAlign: 'start', - transitionProperty: 'start' + transitionProperty: 'insetInlineStart' }; const expectedLTR = { @@ -366,7 +382,7 @@ describe('StyleSheet/compile', () => { clear: 'end', float: 'end', textAlign: 'end', - transitionProperty: 'end' + transitionProperty: 'insetInlineEnd' }; const expectedLTR = { @@ -386,33 +402,39 @@ describe('StyleSheet/compile', () => { ); }); - test('end/start properties take precedence over left/right', () => { + test('physical properties take precedence over logical properties', () => { const initialLTR = { - borderStartWidth: 10, + borderInlineStartWidth: 10, borderLeftWidth: 0, - end: 10, + insetInlineEnd: 10, right: 0, - marginStart: 10, + insetBlockStart: 5, + top: 0, + marginInlineStart: 10, marginLeft: 0 }; const expectedLTR = { - borderLeftWidth: '10px', - marginLeft: '10px', - right: '10px' + borderLeftWidth: '0px', + marginLeft: '0px', + right: '0px', + top: '0px' }; const initialRTL = { - borderStartWidth: 10, + borderInlineStartWidth: 10, borderRightWidth: 0, - end: 10, + insetInlineEnd: 10, left: 0, - marginStart: 10, + insetBlockStart: 5, + top: 0, + marginInlineStart: 10, marginRight: 0 }; const expectedRTL = { - borderRightWidth: '10px', - marginRight: '10px', - left: '10px' + borderRightWidth: '0px', + marginRight: '0px', + left: '0px', + top: '0px' }; expect(inline(isRTL ? initialRTL : initialLTR, isRTL)).toEqual( isRTL ? expectedRTL : expectedLTR diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/index-test.js b/packages/react-native-web/src/exports/StyleSheet/__tests__/index-test.js index 2f1823d304..7148072498 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/index-test.js @@ -18,7 +18,7 @@ describe('StyleSheet', () => { button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;} html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);} input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-webkit-search-results-button,input::-webkit-search-results-decoration{display:none;} - [stylesheet-group=\\"2.2\\"]{} + [stylesheet-group=\\"3\\"]{} .r-bottom-1p0dtai{bottom:0px;} .r-left-1d2f490{left:0px;} .r-position-u8s1d{position:absolute;} @@ -335,8 +335,8 @@ describe('StyleSheet', () => { [ "", { - "marginLeft": "0px", - "marginRight": "0px", + "marginLeft": "1px", + "marginRight": "11px", "right": "12.34%", "textAlign": "right", }, @@ -361,48 +361,53 @@ describe('StyleSheet', () => { const staticStyle = [a, b, c]; expect(StyleSheet(staticStyle)).toMatchInlineSnapshot(` [ - "r-left-2s0hu9 r-textAlign-fdjqy7 r-marginRight-zso239", + "r-insetInlineStart-1xn1m1p r-textAlign-fdjqy7 r-marginInlineEnd-1l8l4mf", null, ] `); expect(StyleSheet(staticStyle, { writingDirection })) .toMatchInlineSnapshot(` [ - "r-right-1bnbe1j r-textAlign-1ff274t r-marginLeft-1n0xq6e", + "r-insetInlineStart-1y2vi53 r-textAlign-1ff274t r-marginInlineEnd-t1sew1", + null, + ] + `); + const z = StyleSheet.create({ x: { marginRight: 33 } }).x; + expect(StyleSheet([staticStyle, z])).toMatchInlineSnapshot(` + [ + "r-insetInlineStart-1xn1m1p r-textAlign-fdjqy7 r-marginInlineEnd-1l8l4mf r-marginRight-j4vy6k", null, ] `); - // logical wins expect( StyleSheet( [ staticStyle, { marginLeft: 1, marginEnd: 0, marginStart: 0, marginRight: 11 } ], + { writingDirection } ) ).toMatchInlineSnapshot(` [ - "r-right-1bnbe1j r-textAlign-1ff274t", + "r-insetInlineStart-1y2vi53 r-textAlign-1ff274t", { - "marginLeft": "0px", - "marginRight": "0px", + "marginLeft": "1px", + "marginRight": "11px", }, ] `); // logical can be nulled expect( - StyleSheet([staticStyle, { marginEnd: null, marginLeft: 11 }], { + StyleSheet([staticStyle, { marginEnd: null }], { writingDirection }) ).toMatchInlineSnapshot(` [ - "r-right-1bnbe1j r-textAlign-1ff274t", - { - "marginLeft": "11px", - }, + "r-insetInlineStart-1y2vi53 r-textAlign-1ff274t", + null, ] `); }); diff --git a/packages/react-native-web/src/exports/StyleSheet/__tests__/preprocess-test.js b/packages/react-native-web/src/exports/StyleSheet/__tests__/preprocess-test.js index 9519c57505..5e6803d18f 100644 --- a/packages/react-native-web/src/exports/StyleSheet/__tests__/preprocess-test.js +++ b/packages/react-native-web/src/exports/StyleSheet/__tests__/preprocess-test.js @@ -8,6 +8,75 @@ import { preprocess } from '../preprocess'; describe('StyleSheet/preprocess', () => { + describe('non-standard styles', () => { + test('converts non-standard logical styles', () => { + expect( + preprocess({ + end: 1, + marginEnd: 1, + marginHorizontal: 1, + marginStart: 1, + marginVertical: 1, + paddingEnd: 1, + paddingHorizontal: 1, + paddingStart: 1, + paddingVertical: 1, + start: 1 + }) + ).toEqual({ + insetInlineEnd: 1, + insetInlineStart: 1, + marginBlock: 1, + marginInline: 1, + marginInlineEnd: 1, + marginInlineStart: 1, + paddingBlock: 1, + paddingInline: 1, + paddingInlineEnd: 1, + paddingInlineStart: 1 + }); + }); + + test('respects standard logical styles', () => { + expect( + preprocess({ + end: 1, + marginEnd: 1, + marginHorizontal: 1, + marginStart: 1, + marginVertical: 1, + paddingEnd: 1, + paddingHorizontal: 1, + paddingStart: 1, + paddingVertical: 1, + start: 1, + // standard + insetInlineEnd: 2, + insetInlineStart: 2, + marginBlock: 2, + marginInline: 2, + marginInlineEnd: 2, + marginInlineStart: 2, + paddingBlock: 2, + paddingInline: 2, + paddingInlineEnd: 2, + paddingInlineStart: 2 + }) + ).toEqual({ + insetInlineEnd: 2, + insetInlineStart: 2, + marginBlock: 2, + marginInline: 2, + marginInlineEnd: 2, + marginInlineStart: 2, + paddingBlock: 2, + paddingInline: 2, + paddingInlineEnd: 2, + paddingInlineStart: 2 + }); + }); + }); + describe('preprocesses multiple shadow styles into a single declaration', () => { test('shadowColor only', () => { expect(preprocess({ shadowColor: 'red' })).toEqual({ diff --git a/packages/react-native-web/src/exports/StyleSheet/compiler/createReactDOMStyle.js b/packages/react-native-web/src/exports/StyleSheet/compiler/createReactDOMStyle.js index 35f9b7c40b..e28f380ca8 100644 --- a/packages/react-native-web/src/exports/StyleSheet/compiler/createReactDOMStyle.js +++ b/packages/react-native-web/src/exports/StyleSheet/compiler/createReactDOMStyle.js @@ -52,6 +52,8 @@ const STYLE_SHORT_FORM_EXPANSIONS = { 'borderBottomColor', 'borderLeftColor' ], + borderBlockColor: ['borderTopColor', 'borderBottomColor'], + borderInlineColor: ['borderRightColor', 'borderLeftColor'], borderRadius: [ 'borderTopLeftRadius', 'borderTopRightRadius', @@ -64,18 +66,52 @@ const STYLE_SHORT_FORM_EXPANSIONS = { 'borderBottomStyle', 'borderLeftStyle' ], + borderBlockStyle: ['borderTopStyle', 'borderBottomStyle'], + borderInlineStyle: ['borderRightStyle', 'borderLeftStyle'], borderWidth: [ 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth' ], - marginHorizontal: ['marginRight', 'marginLeft'], - marginVertical: ['marginTop', 'marginBottom'], + borderBlockWidth: ['borderTopWidth', 'borderBottomWidth'], + borderInlineWidth: ['borderRightWidth', 'borderLeftWidth'], + insetBlock: ['top', 'bottom'], + insetInline: ['left', 'right'], + marginBlock: ['marginTop', 'marginBottom'], + marginInline: ['marginRight', 'marginLeft'], + paddingBlock: ['paddingTop', 'paddingBottom'], + paddingInline: ['paddingRight', 'paddingLeft'], overflow: ['overflowX', 'overflowY'], overscrollBehavior: ['overscrollBehaviorX', 'overscrollBehaviorY'], - paddingHorizontal: ['paddingRight', 'paddingLeft'], - paddingVertical: ['paddingTop', 'paddingBottom'] + borderBlockStartColor: ['borderTopColor'], + borderBlockStartStyle: ['borderTopStyle'], + borderBlockStartWidth: ['borderTopWidth'], + borderBlockEndColor: ['borderBottomColor'], + borderBlockEndStyle: ['borderBottomStyle'], + borderBlockEndWidth: ['borderBottomWidth'], + //borderInlineStartColor: ['borderLeftColor'], + //borderInlineStartStyle: ['borderLeftStyle'], + //borderInlineStartWidth: ['borderLeftWidth'], + //borderInlineEndColor: ['borderRightColor'], + //borderInlineEndStyle: ['borderRightStyle'], + //borderInlineEndWidth: ['borderRightWidth'], + borderEndStartRadius: ['borderBottomLeftRadius'], + borderEndEndRadius: ['borderBottomRightRadius'], + borderStartStartRadius: ['borderTopLeftRadius'], + borderStartEndRadius: ['borderTopRightRadius'], + insetBlockEnd: ['bottom'], + insetBlockStart: ['top'], + //insetInlineEnd: ['right'], + //insetInlineStart: ['left'], + marginBlockStart: ['marginTop'], + marginBlockEnd: ['marginBottom'], + //marginInlineStart: ['marginLeft'], + //marginInlineEnd: ['marginRight'], + paddingBlockStart: ['paddingTop'], + paddingBlockEnd: ['paddingBottom'] + //paddingInlineStart: ['marginLeft'], + //paddingInlineEnd: ['marginRight'], }; /** @@ -193,21 +229,30 @@ const createReactDOMStyle = (style: Style, isInline?: boolean): Style => { } else { const value = normalizeValueWithProperty(style[prop], prop); const longFormProperties = STYLE_SHORT_FORM_EXPANSIONS[prop]; - if (isInline && prop === 'margin') { - if (style.marginHorizontal == null) { + if (isInline && prop === 'inset') { + if (style.insetInline == null) { + resolvedStyle.left = value; + resolvedStyle.right = value; + } + if (style.insetBlock == null) { + resolvedStyle.top = value; + resolvedStyle.bottom = value; + } + } else if (isInline && prop === 'margin') { + if (style.marginInline == null) { resolvedStyle.marginLeft = value; resolvedStyle.marginRight = value; } - if (style.marginVertical == null) { + if (style.marginBlock == null) { resolvedStyle.marginTop = value; resolvedStyle.marginBottom = value; } } else if (isInline && prop === 'padding') { - if (style.paddingHorizontal == null) { + if (style.paddingInline == null) { resolvedStyle.paddingLeft = value; resolvedStyle.paddingRight = value; } - if (style.paddingVertical == null) { + if (style.paddingBlock == null) { resolvedStyle.paddingTop = value; resolvedStyle.paddingBottom = value; } diff --git a/packages/react-native-web/src/exports/StyleSheet/compiler/index.js b/packages/react-native-web/src/exports/StyleSheet/compiler/index.js index 07952b0a47..639f532c4e 100644 --- a/packages/react-native-web/src/exports/StyleSheet/compiler/index.js +++ b/packages/react-native-web/src/exports/StyleSheet/compiler/index.js @@ -29,7 +29,7 @@ const cache = new Map(); const emptyObject = {}; const classicGroup = 1; -const atomicGroup = 2.2; +const atomicGroup = 3; const customGroup: { [key: string]: number } = { borderColor: 2, borderRadius: 2, @@ -37,14 +37,45 @@ const customGroup: { [key: string]: number } = { borderWidth: 2, display: 2, flex: 2, + inset: 2, margin: 2, overflow: 2, overscrollBehavior: 2, padding: 2, - marginHorizontal: 2.1, - marginVertical: 2.1, - paddingHorizontal: 2.1, - paddingVertical: 2.1 + insetBlock: 2.1, + insetInline: 2.1, + marginInline: 2.1, + marginBlock: 2.1, + paddingInline: 2.1, + paddingBlock: 2.1, + borderBlockStartColor: 2.2, + borderBlockStartStyle: 2.2, + borderBlockStartWidth: 2.2, + borderBlockEndColor: 2.2, + borderBlockEndStyle: 2.2, + borderBlockEndWidth: 2.2, + borderInlineStartColor: 2.2, + borderInlineStartStyle: 2.2, + borderInlineStartWidth: 2.2, + borderInlineEndColor: 2.2, + borderInlineEndStyle: 2.2, + borderInlineEndWidth: 2.2, + borderEndStartRadius: 2.2, + borderEndEndRadius: 2.2, + borderStartStartRadius: 2.2, + borderStartEndRadius: 2.2, + insetBlockEnd: 2.2, + insetBlockStart: 2.2, + insetInlineEnd: 2.2, + insetInlineStart: 2.2, + marginBlockStart: 2.2, + marginBlockEnd: 2.2, + marginInlineStart: 2.2, + marginInlineEnd: 2.2, + paddingBlockStart: 2.2, + paddingBlockEnd: 2.2, + paddingInlineStart: 2.2, + paddingInlineEnd: 2.2 }; const borderTopLeftRadius = 'borderTopLeftRadius'; @@ -86,22 +117,22 @@ const PROPERTIES_FLIP: { [key: string]: string } = { // Map of I18N property names to their LTR equivalent. const PROPERTIES_I18N: { [key: string]: string } = { - borderTopStartRadius: borderTopLeftRadius, - borderTopEndRadius: borderTopRightRadius, - borderBottomStartRadius: borderBottomLeftRadius, - borderBottomEndRadius: borderBottomRightRadius, - borderStartColor: borderLeftColor, - borderStartStyle: borderLeftStyle, - borderStartWidth: borderLeftWidth, - borderEndColor: borderRightColor, - borderEndStyle: borderRightStyle, - borderEndWidth: borderRightWidth, - end: right, - marginStart: marginLeft, - marginEnd: marginRight, - paddingStart: paddingLeft, - paddingEnd: paddingRight, - start: left + borderStartStartRadius: borderTopLeftRadius, + borderStartEndRadius: borderTopRightRadius, + borderEndStartRadius: borderBottomLeftRadius, + borderEndEndRadius: borderBottomRightRadius, + borderInlineStartColor: borderLeftColor, + borderInlineStartStyle: borderLeftStyle, + borderInlineStartWidth: borderLeftWidth, + borderInlineEndColor: borderRightColor, + borderInlineEndStyle: borderRightStyle, + borderInlineEndWidth: borderRightWidth, + insetInlineEnd: right, + insetInlineStart: left, + marginInlineStart: marginLeft, + marginInlineEnd: marginRight, + paddingInlineStart: paddingLeft, + paddingInlineEnd: paddingRight }; const PROPERTIES_VALUE = ['clear', 'float', 'textAlign']; @@ -110,7 +141,7 @@ export function atomic(style: Style): CompilerOutput { const compiledStyle: CompiledStyle = { $$css: true }; const compiledRules = []; - function atomicCompile(prop, value) { + function atomicCompile(srcProp, prop, value) { const valueString = stringifyValueWithProperty(value, prop); const cacheKey = prop + valueString; const cachedResult = cache.get(cacheKey); @@ -119,8 +150,9 @@ export function atomic(style: Style): CompilerOutput { identifier = cachedResult[0]; compiledRules.push(cachedResult[1]); } else { - identifier = createIdentifier('r', prop, value); - const order = customGroup[prop] || atomicGroup; + const v = srcProp !== prop ? cacheKey : valueString; + identifier = createIdentifier('r', srcProp, v); + const order = customGroup[srcProp] || atomicGroup; const rules = createAtomicRules(identifier, prop, value); const orderedRules = [rules, order]; compiledRules.push(orderedRules); @@ -131,14 +163,14 @@ export function atomic(style: Style): CompilerOutput { Object.keys(style) .sort() - .forEach((prop) => { - const value = style[prop]; + .forEach((srcProp) => { + const value = style[srcProp]; if (value != null) { let localizeableValue; // BiDi flip values - if (PROPERTIES_VALUE.indexOf(prop) > -1) { - const left = atomicCompile(prop, 'left'); - const right = atomicCompile(prop, 'right'); + if (PROPERTIES_VALUE.indexOf(srcProp) > -1) { + const left = atomicCompile(srcProp, srcProp, 'left'); + const right = atomicCompile(srcProp, srcProp, 'right'); if (value === 'start') { localizeableValue = [left, right]; } else if (value === 'end') { @@ -146,14 +178,18 @@ export function atomic(style: Style): CompilerOutput { } } // BiDi flip properties - const propPolyfill = PROPERTIES_I18N[prop]; + const propPolyfill = PROPERTIES_I18N[srcProp]; if (propPolyfill != null) { - const ltr = atomicCompile(propPolyfill, value); - const rtl = atomicCompile(PROPERTIES_FLIP[propPolyfill], value); + const ltr = atomicCompile(srcProp, propPolyfill, value); + const rtl = atomicCompile( + srcProp, + PROPERTIES_FLIP[propPolyfill], + value + ); localizeableValue = [ltr, rtl]; } // BiDi flip transitionProperty value - if (prop === 'transitionProperty') { + if (srcProp === 'transitionProperty') { const values = Array.isArray(value) ? value : [value]; const polyfillIndices = []; @@ -174,8 +210,8 @@ export function atomic(style: Style): CompilerOutput { const rtlPolyfill = PROPERTIES_FLIP[ltrPolyfill]; ltrPolyfillValues[i] = ltrPolyfill; rtlPolyfillValues[i] = rtlPolyfill; - const ltr = atomicCompile(prop, ltrPolyfillValues); - const rtl = atomicCompile(prop, rtlPolyfillValues); + const ltr = atomicCompile(srcProp, srcProp, ltrPolyfillValues); + const rtl = atomicCompile(srcProp, srcProp, rtlPolyfillValues); localizeableValue = [ltr, rtl]; } }); @@ -183,12 +219,12 @@ export function atomic(style: Style): CompilerOutput { } if (localizeableValue == null) { - localizeableValue = atomicCompile(prop, value); + localizeableValue = atomicCompile(srcProp, srcProp, value); } else { compiledStyle['$$css$localize'] = true; } - compiledStyle[prop] = localizeableValue; + compiledStyle[srcProp] = localizeableValue; } }); @@ -204,7 +240,7 @@ export function classic(style: Style, name: string): CompilerOutput { const compiledRules = []; const { animationKeyframes, ...rest } = style; - const identifier = createIdentifier('css', name, style); + const identifier = createIdentifier('css', name, JSON.stringify(style)); const selector = `.${identifier}`; let animationName; if (animationKeyframes != null) { @@ -270,6 +306,8 @@ export function inline( originalValues[i] = isRTL ? PROPERTIES_FLIP[valuePolyfill] : valuePolyfill; + + value = originalValues.join(' '); } } }); @@ -280,9 +318,13 @@ export function inline( nextStyle[prop] = value; } - if (PROPERTIES_I18N.hasOwnProperty(originalProp)) { + if (prop === originalProp) { frozenProps[prop] = true; } + + // if (PROPERTIES_I18N.hasOwnProperty(originalProp)) { + // frozenProps[prop] = true; + //} } return createReactDOMStyle(nextStyle, true); @@ -408,8 +450,8 @@ function createDeclarationBlock(style: Style): string { /** * An identifier is associated with a unique set of styles. */ -function createIdentifier(prefix: string, name: string, value: Value): string { - const hashedString = hash(name + stringifyValueWithProperty(value, name)); +function createIdentifier(prefix: string, name: string, key: string): string { + const hashedString = hash(name + key); return process.env.NODE_ENV !== 'production' ? `${prefix}-${name}-${hashedString}` : `${prefix}-${hashedString}`; @@ -420,7 +462,11 @@ function createIdentifier(prefix: string, name: string, value: Value): string { */ function createKeyframes(keyframes: Object): [string, Rules] { const prefixes = ['-webkit-', '']; - const identifier = createIdentifier('r', 'animation', keyframes); + const identifier = createIdentifier( + 'r', + 'animation', + JSON.stringify(keyframes) + ); const steps = '{' + diff --git a/packages/react-native-web/src/exports/StyleSheet/index.js b/packages/react-native-web/src/exports/StyleSheet/index.js index 281bf1a355..89bacb89b6 100644 --- a/packages/react-native-web/src/exports/StyleSheet/index.js +++ b/packages/react-native-web/src/exports/StyleSheet/index.js @@ -25,7 +25,7 @@ function customStyleq(styles, isRTL) { if (compiledStyle != null) { return localizeStyle(compiledStyle, isRTL); } - return style; + return preprocess(style); } })(styles); } @@ -147,7 +147,7 @@ function StyleSheet(styles: any, options?: Options): StyleProps { const isRTL = options != null && options.writingDirection === 'rtl'; const styleProps: StyleProps = customStyleq(styles, isRTL); if (Array.isArray(styleProps) && styleProps[1] != null) { - styleProps[1] = inline(preprocess(styleProps[1]), isRTL); + styleProps[1] = inline(styleProps[1], isRTL); } return styleProps; } diff --git a/packages/react-native-web/src/exports/StyleSheet/preprocess.js b/packages/react-native-web/src/exports/StyleSheet/preprocess.js index 155ca489e5..2a57070a4c 100644 --- a/packages/react-native-web/src/exports/StyleSheet/preprocess.js +++ b/packages/react-native-web/src/exports/StyleSheet/preprocess.js @@ -9,6 +9,7 @@ import normalizeColor from './compiler/normalizeColor'; import normalizeValueWithProperty from './compiler/normalizeValueWithProperty'; +import { warnOnce } from '../../modules/warnOnce'; const emptyObject = {}; @@ -55,6 +56,29 @@ export const createTextShadowValue = (style: Object): void | string => { } }; +const PROPERTIES_STANDARD: { [key: string]: string } = { + borderBottomEndRadius: 'borderEndEndRadius', + borderBottomStartRadius: 'borderEndStartRadius', + borderTopEndRadius: 'borderStartEndRadius', + borderTopStartRadius: 'borderStartStartRadius', + borderEndColor: 'borderInlineEndColor', + borderEndStyle: 'borderInlineEndStyle', + borderEndWidth: 'borderInlineEndWidth', + borderStartColor: 'borderInlineStartColor', + borderStartStyle: 'borderInlineStartStyle', + borderStartWidth: 'borderInlineStartWidth', + end: 'insetInlineEnd', + marginEnd: 'marginInlineEnd', + marginHorizontal: 'marginInline', + marginStart: 'marginInlineStart', + marginVertical: 'marginBlock', + paddingEnd: 'paddingInlineEnd', + paddingHorizontal: 'paddingInline', + paddingStart: 'paddingInlineStart', + paddingVertical: 'paddingBlock', + start: 'insetInlineStart' +}; + /** * Preprocess styles */ @@ -66,12 +90,12 @@ export const preprocess = ( for (const originalProp in style) { const originalValue = style[originalProp]; - let prop = originalProp; + let prop = PROPERTIES_STANDARD[originalProp] || originalProp; let value = originalValue; if ( !Object.prototype.hasOwnProperty.call(style, originalProp) || - originalValue == null + (prop !== originalProp && style[prop] != null) ) { continue; } diff --git a/packages/react-native-web/src/exports/StyleSheet/validate.js b/packages/react-native-web/src/exports/StyleSheet/validate.js index ccd83c5fcc..1bdbf3625f 100644 --- a/packages/react-native-web/src/exports/StyleSheet/validate.js +++ b/packages/react-native-web/src/exports/StyleSheet/validate.js @@ -29,8 +29,15 @@ const invalidMultiValueShortforms = { borderRadius: true, borderStyle: true, borderWidth: true, + inset: true, + insetBlock: true, + insetInline: true, + marginBlock: true, + marginInline: true, marginHorizontal: true, marginVertical: true, + paddingBlock: true, + paddingInline: true, paddingHorizontal: true, paddingVertical: true, overflow: true, diff --git a/packages/react-native-web/src/exports/Switch/__tests__/__snapshots__/index-test.js.snap b/packages/react-native-web/src/exports/Switch/__tests__/__snapshots__/index-test.js.snap index 4b95f1145a..7410a86716 100644 --- a/packages/react-native-web/src/exports/Switch/__tests__/__snapshots__/index-test.js.snap +++ b/packages/react-native-web/src/exports/Switch/__tests__/__snapshots__/index-test.js.snap @@ -9,7 +9,7 @@ exports[`components/Switch disabled when "true" and value="false", a disabled ch exports[`components/Switch disabled when "true" and value="false", a disabled checkbox is rendered with provided thumbColor 1`] = `
`; @@ -23,7 +23,7 @@ exports[`components/Switch disabled when "true" and value="false", a disabled ch exports[`components/Switch disabled when "true" and value="true", a disabled checkbox is rendered with provided activeThumbColor 1`] = `
`; diff --git a/packages/react-native-web/src/exports/Switch/index.js b/packages/react-native-web/src/exports/Switch/index.js index 4a90093052..cc33f6427d 100644 --- a/packages/react-native-web/src/exports/Switch/index.js +++ b/packages/react-native-web/src/exports/Switch/index.js @@ -218,7 +218,7 @@ const styles = StyleSheet.create({ transitionDuration: '0.1s' }, thumbActive: { - start: '100%' + insetInlineStart: '100%' }, nativeControl: { ...StyleSheet.absoluteFillObject, diff --git a/packages/react-native-web/src/types/styles.js b/packages/react-native-web/src/types/styles.js index 86e2a993de..b9e37147a0 100644 --- a/packages/react-native-web/src/types/styles.js +++ b/packages/react-native-web/src/types/styles.js @@ -51,29 +51,49 @@ type BorderRadiusValue = number | string; type BorderStyleValue = 'solid' | 'dotted' | 'dashed'; export type BorderStyles = {| + // color borderColor?: ?ColorValue, + borderBlockColor?: ?ColorValue, + borderBlockEndColor?: ?ColorValue, + borderBlockStartColor?: ?ColorValue, borderBottomColor?: ?ColorValue, - borderEndColor?: ?ColorValue, + borderInlineColor?: ?ColorValue, + borderInlineEndColor?: ?ColorValue, + borderInlineStartColor?: ?ColorValue, borderLeftColor?: ?ColorValue, borderRightColor?: ?ColorValue, - borderStartColor?: ?ColorValue, borderTopColor?: ?ColorValue, + // radius borderRadius?: ?BorderRadiusValue, - borderBottomEndRadius?: ?BorderRadiusValue, + borderEndEndRadius?: ?BorderRadiusValue, + borderEndStartRadius?: ?BorderRadiusValue, + borderStartEndRadius?: ?BorderRadiusValue, + borderStartStartRadius?: ?BorderRadiusValue, borderBottomLeftRadius?: ?BorderRadiusValue, borderBottomRightRadius?: ?BorderRadiusValue, - borderBottomStartRadius?: ?BorderRadiusValue, - borderTopEndRadius?: ?BorderRadiusValue, borderTopLeftRadius?: ?BorderRadiusValue, borderTopRightRadius?: ?BorderRadiusValue, - borderTopStartRadius?: ?BorderRadiusValue, + // style borderStyle?: ?BorderStyleValue, + borderBlockStyle?: ?BorderStyleValue, + borderBlockEndStyle?: ?BorderStyleValue, + borderBlockStartStyle?: ?BorderStyleValue, borderBottomStyle?: ?BorderStyleValue, - borderEndStyle?: ?BorderStyleValue, + borderInlineStyle?: ?BorderStyleValue, + borderInlineEndStyle?: ?BorderStyleValue, + borderInlineStartStyle?: ?BorderStyleValue, borderLeftStyle?: ?BorderStyleValue, borderRightStyle?: ?BorderStyleValue, + borderTopStyle?: ?BorderStyleValue, + // deprecated + borderEndColor?: ?ColorValue, + borderStartColor?: ?ColorValue, + borderEndStyle?: ?BorderStyleValue, borderStartStyle?: ?BorderStyleValue, - borderTopStyle?: ?BorderStyleValue + borderBottomEndRadius?: ?BorderRadiusValue, + borderBottomStartRadius?: ?BorderRadiusValue, + borderTopEndRadius?: ?BorderRadiusValue, + borderTopStartRadius?: ?BorderRadiusValue |}; /** @@ -171,24 +191,36 @@ export type LayoutStyles = {| aspectRatio?: ?number, backfaceVisibility?: ?VisiblilityValue, borderWidth?: ?DimensionValue, + borderBlockWidth?: ?DimensionValue, + borderBlockEndWidth?: ?DimensionValue, + borderBlockStartWidth?: ?DimensionValue, borderBottomWidth?: ?DimensionValue, - borderEndWidth?: ?DimensionValue, + borderInlineWidth?: ?DimensionValue, + borderInlineEndWidth?: ?DimensionValue, + borderInlineStartWidth?: ?DimensionValue, borderLeftWidth?: ?DimensionValue, borderRightWidth?: ?DimensionValue, - borderStartWidth?: ?DimensionValue, borderTopWidth?: ?DimensionValue, bottom?: ?DimensionValue, boxSizing?: ?('border-box' | 'content-box' | 'padding-box'), + columnGap?: ?DimensionValue, direction?: ?('inherit' | 'ltr' | 'rtl'), display?: ?string, - end?: ?DimensionValue, flex?: ?number, flexBasis?: ?DimensionValue, flexDirection?: ?('column' | 'column-reverse' | 'row' | 'row-reverse'), flexGrow?: ?number, flexShrink?: ?number, flexWrap?: ?('nowrap' | 'wrap' | 'wrap-reverse'), + gap?: ?DimensionValue, height?: ?DimensionValue, + inset?: ?DimensionValue, + insetBlock?: ?DimensionValue, + insetBlockEnd?: ?DimensionValue, + insetBlockStart?: ?DimensionValue, + insetInline?: ?DimensionValue, + insetInlineEnd?: ?DimensionValue, + insetInlineStart?: ?DimensionValue, justifyContent?: ?( | 'center' | 'flex-end' @@ -199,14 +231,16 @@ export type LayoutStyles = {| ), left?: ?DimensionValue, margin?: ?DimensionValue, + marginBlock?: ?DimensionValue, + marginBlockEnd?: ?DimensionValue, + marginBlockStart?: ?DimensionValue, marginBottom?: ?DimensionValue, - marginHorizontal?: ?DimensionValue, - marginEnd?: ?DimensionValue, + marginInline?: ?DimensionValue, + marginInlineEnd?: ?DimensionValue, + marginInlineStart?: ?DimensionValue, marginLeft?: ?DimensionValue, marginRight?: ?DimensionValue, - marginStart?: ?DimensionValue, marginTop?: ?DimensionValue, - marginVertical?: ?DimensionValue, maxHeight?: ?DimensionValue, maxWidth?: ?DimensionValue, minHeight?: ?DimensionValue, @@ -216,17 +250,19 @@ export type LayoutStyles = {| overflowX?: ?OverflowValue, overflowY?: ?OverflowValue, padding?: ?DimensionValue, + paddingBlock?: ?DimensionValue, + paddingBlockEnd?: ?DimensionValue, + paddingBlockStart?: ?DimensionValue, paddingBottom?: ?DimensionValue, - paddingHorizontal?: ?DimensionValue, - paddingEnd?: ?DimensionValue, + paddingInline?: ?DimensionValue, + paddingInlineEnd?: ?DimensionValue, + paddingInlineStart?: ?DimensionValue, paddingLeft?: ?DimensionValue, paddingRight?: ?DimensionValue, - paddingStart?: ?DimensionValue, paddingTop?: ?DimensionValue, - paddingVertical?: ?DimensionValue, position?: ?('absolute' | 'fixed' | 'relative' | 'static' | 'sticky'), right?: ?DimensionValue, - start?: ?DimensionValue, + rowGap?: ?DimensionValue, top?: ?DimensionValue, visibility?: ?VisiblilityValue, width?: ?DimensionValue, @@ -245,7 +281,22 @@ export type LayoutStyles = {| gridRowStart?: ?string, gridTemplateColumns?: ?string, gridTemplateRows?: ?string, - gridTemplateAreas?: ?string + gridTemplateAreas?: ?string, + /** + * @deprecated + */ + borderEndWidth?: ?DimensionValue, + borderStartWidth?: ?DimensionValue, + end?: ?DimensionValue, + marginHorizontal?: ?DimensionValue, + marginEnd?: ?DimensionValue, + marginStart?: ?DimensionValue, + marginVertical?: ?DimensionValue, + paddingHorizontal?: ?DimensionValue, + paddingStart?: ?DimensionValue, + paddingEnd?: ?DimensionValue, + paddingVertical?: ?DimensionValue, + start?: ?DimensionValue |}; /**