-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: ios fabric transform origin #38559
Closed
intergalacticspacehighway
wants to merge
21
commits into
facebook:main
from
intergalacticspacehighway:feat/ios-fabric-transformorigin
Closed
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
4b13fb1
feat: transform origin ios fabric
intergalacticspacehighway 26b8430
move transform in invalidateLayer
intergalacticspacehighway e65fbf3
fix: lint errors
intergalacticspacehighway fbaf6c0
revert needs invalidate layer
intergalacticspacehighway 35badaf
transform origin struct
intergalacticspacehighway 302a9aa
nit: pr suggestions
intergalacticspacehighway be6b4d5
revert non fabric changes
intergalacticspacehighway ffa6afc
fix: tests
intergalacticspacehighway ab174da
nit: header fix
intergalacticspacehighway a9632d6
merge main
intergalacticspacehighway eefec92
merge main
intergalacticspacehighway 40ed8db
fix: PR feedback
intergalacticspacehighway 8902301
fix: PR feedback
intergalacticspacehighway 0e91714
PR feedback
intergalacticspacehighway a74fdf8
remove redundant type
intergalacticspacehighway 854710a
fix min error
intergalacticspacehighway 9a3c230
fix min error
intergalacticspacehighway 55ad2c9
add value unit struct
intergalacticspacehighway 696621e
Apply suggestions from code review
intergalacticspacehighway 0f27a0c
Merge branch 'feat/add-value-unit-struct' into feat/ios-fabric-transf…
intergalacticspacehighway a30ed3d
use ValueUnit struct
intergalacticspacehighway File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
...t-native/Libraries/StyleSheet/__tests__/__snapshots__/processTransformOrigin-test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`processTransformOrigin validation only accepts three values 1`] = `"Transform origin must have exactly 3 values."`; | ||
|
||
exports[`processTransformOrigin validation only accepts three values 2`] = `"Transform origin must have exactly 3 values."`; |
134 changes: 134 additions & 0 deletions
134
packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @format | ||
* @oncall react_native | ||
*/ | ||
|
||
import processTransformOrigin from '../processTransformOrigin'; | ||
|
||
describe('processTransformOrigin', () => { | ||
describe('validation', () => { | ||
it('only accepts three values', () => { | ||
expect(() => { | ||
processTransformOrigin([]); | ||
}).toThrowErrorMatchingSnapshot(); | ||
expect(() => { | ||
processTransformOrigin(['50%', '50%']); | ||
}).toThrowErrorMatchingSnapshot(); | ||
}); | ||
|
||
it('should transform a string', () => { | ||
expect(processTransformOrigin('50% 50% 5px')).toEqual(['50%', '50%', 5]); | ||
}); | ||
|
||
it('should handle one value', () => { | ||
expect(processTransformOrigin('top')).toEqual(['50%', 0, 0]); | ||
expect(processTransformOrigin('right')).toEqual(['100%', '50%', 0]); | ||
expect(processTransformOrigin('bottom')).toEqual(['50%', '100%', 0]); | ||
expect(processTransformOrigin('left')).toEqual([0, '50%', 0]); | ||
}); | ||
|
||
it('should handle two values', () => { | ||
expect(processTransformOrigin('30% top')).toEqual(['30%', 0, 0]); | ||
expect(processTransformOrigin('right 30%')).toEqual(['100%', '30%', 0]); | ||
expect(processTransformOrigin('30% bottom')).toEqual(['30%', '100%', 0]); | ||
expect(processTransformOrigin('left 30%')).toEqual([0, '30%', 0]); | ||
}); | ||
|
||
it('should handle two keywords in either order', () => { | ||
expect(processTransformOrigin('right bottom')).toEqual([ | ||
'100%', | ||
'100%', | ||
0, | ||
]); | ||
expect(processTransformOrigin('bottom right')).toEqual([ | ||
'100%', | ||
'100%', | ||
0, | ||
]); | ||
expect(processTransformOrigin('right bottom 5px')).toEqual([ | ||
'100%', | ||
'100%', | ||
5, | ||
]); | ||
expect(processTransformOrigin('bottom right 5px')).toEqual([ | ||
'100%', | ||
'100%', | ||
5, | ||
]); | ||
}); | ||
|
||
it('should not allow specifying same position twice', () => { | ||
expect(() => { | ||
processTransformOrigin('top top'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Could not parse transform-origin: top top"`, | ||
); | ||
expect(() => { | ||
processTransformOrigin('right right'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Transform-origin right can only be used for x-position"`, | ||
); | ||
expect(() => { | ||
processTransformOrigin('bottom bottom'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Could not parse transform-origin: bottom bottom"`, | ||
); | ||
expect(() => { | ||
processTransformOrigin('left left'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Transform-origin left can only be used for x-position"`, | ||
); | ||
expect(() => { | ||
processTransformOrigin('top bottom'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Could not parse transform-origin: top bottom"`, | ||
); | ||
expect(() => { | ||
processTransformOrigin('left right'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Transform-origin right can only be used for x-position"`, | ||
); | ||
}); | ||
|
||
it('should handle three values', () => { | ||
expect(processTransformOrigin('30% top 10px')).toEqual(['30%', 0, 10]); | ||
expect(processTransformOrigin('right 30% 10px')).toEqual([ | ||
'100%', | ||
'30%', | ||
10, | ||
]); | ||
expect(processTransformOrigin('30% bottom 10px')).toEqual([ | ||
'30%', | ||
'100%', | ||
10, | ||
]); | ||
expect(processTransformOrigin('left 30% 10px')).toEqual([0, '30%', 10]); | ||
}); | ||
|
||
it('should enforce two value ordering', () => { | ||
expect(() => { | ||
processTransformOrigin('top 30%'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Could not parse transform-origin: top 30%"`, | ||
); | ||
}); | ||
|
||
it('should not allow percents for z-position', () => { | ||
expect(() => { | ||
processTransformOrigin('top 30% 30%'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Could not parse transform-origin: top 30% 30%"`, | ||
); | ||
expect(() => { | ||
processTransformOrigin('top 30% center'); | ||
}).toThrowErrorMatchingInlineSnapshot( | ||
`"Could not parse transform-origin: top 30% center"`, | ||
); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
packages/react-native/Libraries/StyleSheet/processTransformOrigin.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @format | ||
* @flow | ||
*/ | ||
|
||
import invariant from 'invariant'; | ||
|
||
const INDEX_X = 0; | ||
const INDEX_Y = 1; | ||
const INDEX_Z = 2; | ||
|
||
/* eslint-disable no-labels */ | ||
export default function processTransformOrigin( | ||
transformOrigin: Array<string | number> | string, | ||
): Array<string | number> { | ||
if (typeof transformOrigin === 'string') { | ||
const transformOriginString = transformOrigin; | ||
const regex = /(top|bottom|left|right|center|\d+(?:%|px)|0)/gi; | ||
const transformOriginArray: Array<string | number> = ['50%', '50%', 0]; | ||
|
||
let index = INDEX_X; | ||
let matches; | ||
outer: while ((matches = regex.exec(transformOriginString))) { | ||
let nextIndex = index + 1; | ||
|
||
const value = matches[0]; | ||
const valueLower = value.toLowerCase(); | ||
|
||
switch (valueLower) { | ||
case 'left': | ||
case 'right': { | ||
invariant( | ||
index === INDEX_X, | ||
'Transform-origin %s can only be used for x-position', | ||
value, | ||
); | ||
transformOriginArray[INDEX_X] = valueLower === 'left' ? 0 : '100%'; | ||
break; | ||
} | ||
case 'top': | ||
case 'bottom': { | ||
invariant( | ||
index !== INDEX_Z, | ||
'Transform-origin %s can only be used for y-position', | ||
value, | ||
); | ||
transformOriginArray[INDEX_Y] = valueLower === 'top' ? 0 : '100%'; | ||
|
||
// Handle [[ center | left | right ] && [ center | top | bottom ]] <length>? | ||
if (index === INDEX_X) { | ||
const horizontal = regex.exec(transformOriginString); | ||
if (horizontal == null) { | ||
break outer; | ||
} | ||
|
||
switch (horizontal[0].toLowerCase()) { | ||
case 'left': | ||
transformOriginArray[INDEX_X] = 0; | ||
break; | ||
case 'right': | ||
transformOriginArray[INDEX_X] = '100%'; | ||
break; | ||
case 'center': | ||
transformOriginArray[INDEX_X] = '50%'; | ||
break; | ||
default: | ||
invariant( | ||
false, | ||
'Could not parse transform-origin: %s', | ||
transformOriginString, | ||
); | ||
} | ||
nextIndex = INDEX_Z; | ||
} | ||
|
||
break; | ||
} | ||
case 'center': { | ||
invariant( | ||
index !== INDEX_Z, | ||
'Transform-origin value %s cannot be used for z-position', | ||
value, | ||
); | ||
transformOriginArray[index] = '50%'; | ||
break; | ||
} | ||
default: { | ||
if (value.endsWith('%')) { | ||
transformOriginArray[index] = value; | ||
} else { | ||
transformOriginArray[index] = parseFloat(value); // Remove `px` | ||
} | ||
break; | ||
} | ||
} | ||
|
||
index = nextIndex; | ||
} | ||
|
||
transformOrigin = transformOriginArray; | ||
} | ||
|
||
if (__DEV__) { | ||
_validateTransformOrigin(transformOrigin); | ||
} | ||
|
||
return transformOrigin; | ||
} | ||
|
||
function _validateTransformOrigin(transformOrigin: Array<string | number>) { | ||
invariant( | ||
transformOrigin.length === 3, | ||
'Transform origin must have exactly 3 values.', | ||
); | ||
const [x, y, z] = transformOrigin; | ||
invariant( | ||
typeof x === 'number' || (typeof x === 'string' && x.endsWith('%')), | ||
'Transform origin x-position must be a number. Passed value: %s.', | ||
x, | ||
); | ||
invariant( | ||
typeof y === 'number' || (typeof y === 'string' && y.endsWith('%')), | ||
'Transform origin y-position must be a number. Passed value: %s.', | ||
y, | ||
); | ||
invariant( | ||
typeof z === 'number', | ||
'Transform origin z-position must be a number. Passed value: %s.', | ||
z, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this required?
transformOrigin
should be included via____TransformStyle_Internal
already.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad. Updated!