Skip to content

Commit

Permalink
feat: Add logical border block color properties (#35999)
Browse files Browse the repository at this point in the history
Summary:
This PR implements logical border block color properties as requested on #34425. This implementation includes the addition of the following style properties

- `borderBlockColor`, equivalent to `borderTopColor` and `borderBottomColor`.
- `borderBlockEndColor`, equivalent to `borderBottomColor`.
- `borderBlockStartColor`, equivalent to `borderTopColor`.

## Changelog

[GENERAL] [ADDED] - Add logical border block color properties

Pull Request resolved: #35999

Test Plan:
1. Open the RNTester app and navigate to the `View` page
2. Test the new style properties through the `Logical Border Color` section

<table>
<tr>
    <td>Android</td>
    <td>iOS</td>
</tr>
  <tr>
    <td><video src="https://user-images.githubusercontent.com/11707729/215384882-5b96518e-ad70-4157-a7f3-130f488cc41c.mov"  alt="1" width="360px"   />
    </td>
<td>
<video src="https://user-images.githubusercontent.com/11707729/215392728-cfc6a097-26c1-4ffe-ab0e-f0a5a71a902d.mov"2" width="360px"  />
</td>
   </tr>
</table>

Reviewed By: cipolleschi

Differential Revision: D42849911

Pulled By: jacdebug

fbshipit-source-id: 822cff5264689c42031d496105537032b5cd31ef
  • Loading branch information
gabrieldonadel authored and facebook-github-bot committed Jan 31, 2023
1 parent dea48e2 commit 597a1ff
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Libraries/Components/View/ReactNativeStyleAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
*/
backfaceVisibility: true,
backgroundColor: colorAttributes,
borderBlockColor: colorAttributes,
borderBlockEndColor: colorAttributes,
borderBlockStartColor: colorAttributes,
borderBottomColor: colorAttributes,
borderBottomEndRadius: true,
borderBottomLeftRadius: true,
Expand Down
9 changes: 9 additions & 0 deletions Libraries/Components/View/ViewNativeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
borderEndColor: {
process: require('../../StyleSheet/processColor').default,
},
borderBlockColor: {
process: require('../../StyleSheet/processColor').default,
},
borderBlockEndColor: {
process: require('../../StyleSheet/processColor').default,
},
borderBlockStartColor: {
process: require('../../StyleSheet/processColor').default,
},

focusable: true,
overflow: true,
Expand Down
3 changes: 3 additions & 0 deletions Libraries/StyleSheet/StyleSheetTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ export interface TransformsStyle {
export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
backfaceVisibility?: 'visible' | 'hidden' | undefined;
backgroundColor?: ColorValue | undefined;
borderBlockColor?: ColorValue | undefined;
borderBlockEndColor?: ColorValue | undefined;
borderBlockStartColor?: ColorValue | undefined;
borderBottomColor?: ColorValue | undefined;
borderBottomEndRadius?: number | undefined;
borderBottomLeftRadius?: number | undefined;
Expand Down
3 changes: 3 additions & 0 deletions Libraries/StyleSheet/StyleSheetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,9 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
borderRightColor?: ____ColorValue_Internal,
borderStartColor?: ____ColorValue_Internal,
borderTopColor?: ____ColorValue_Internal,
borderBlockColor?: ____ColorValue_Internal,
borderBlockEndColor?: ____ColorValue_Internal,
borderBlockStartColor?: ____ColorValue_Internal,
borderRadius?: number | AnimatedNode,
borderBottomEndRadius?: number | AnimatedNode,
borderBottomLeftRadius?: number | AnimatedNode,
Expand Down
7 changes: 7 additions & 0 deletions React/Views/RCTView.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
@property (nonatomic, strong) UIColor *borderStartColor;
@property (nonatomic, strong) UIColor *borderEndColor;
@property (nonatomic, strong) UIColor *borderColor;
@property (nonatomic, strong) UIColor *borderBlockColor;
@property (nonatomic, strong) UIColor *borderBlockEndColor;
@property (nonatomic, strong) UIColor *borderBlockStartColor;

/**
* Border widths.
Expand All @@ -97,6 +100,10 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
@property (nonatomic, assign) CGFloat borderStartWidth;
@property (nonatomic, assign) CGFloat borderEndWidth;
@property (nonatomic, assign) CGFloat borderWidth;
// TODO: Implement logical border width logic
@property (nonatomic, assign) CGFloat borderBlockWidth;
@property (nonatomic, assign) CGFloat borderBlockEndWidth;
@property (nonatomic, assign) CGFloat borderBlockStartWidth;

/**
* Border curve.
Expand Down
13 changes: 12 additions & 1 deletion React/Views/RCTView.m
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,17 @@ - (RCTBorderColors)borderColorsWithTraitCollection:(UITraitCollection *)traitCol
UIColor *borderTopColor = _borderTopColor;
UIColor *borderBottomColor = _borderBottomColor;

if (_borderBlockColor) {
borderTopColor = _borderBlockColor;
borderBottomColor = _borderBlockColor;
}
if (_borderBlockEndColor) {
borderBottomColor = _borderBlockEndColor;
}
if (_borderBlockStartColor) {
borderTopColor = _borderBlockStartColor;
}

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
borderColor = [borderColor resolvedColorWithTraitCollection:self.traitCollection];
Expand Down Expand Up @@ -924,7 +935,7 @@ -(void)setBorder##side##Color : (UIColor *)color \
}

setBorderColor() setBorderColor(Top) setBorderColor(Right) setBorderColor(Bottom) setBorderColor(Left)
setBorderColor(Start) setBorderColor(End)
setBorderColor(Start) setBorderColor(End) setBorderColor(Block) setBorderColor(BlockEnd) setBorderColor(BlockStart)

#pragma mark - Border Width

Expand Down
3 changes: 3 additions & 0 deletions React/Views/RCTViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ - (RCTShadowView *)shadowView
RCT_VIEW_BORDER_PROPERTY(Left)
RCT_VIEW_BORDER_PROPERTY(Start)
RCT_VIEW_BORDER_PROPERTY(End)
RCT_VIEW_BORDER_PROPERTY(Block)
RCT_VIEW_BORDER_PROPERTY(BlockEnd)
RCT_VIEW_BORDER_PROPERTY(BlockStart)

#define RCT_VIEW_BORDER_RADIUS_PROPERTY(SIDE) \
RCT_CUSTOM_VIEW_PROPERTY(border##SIDE##Radius, CGFloat, RCTView) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,18 @@ public class Spacing {
* Spacing type that represents all directions (left, top, right, bottom). E.g. {@code margin}.
*/
public static final int ALL = 8;
/** Spacing type that represents block directions (top, bottom). E.g. {@code marginBlock}. */
public static final int BLOCK = 9;
/** Spacing type that represents the block end direction (bottom). E.g. {@code marginBlockEnd}. */
public static final int BLOCK_END = 10;
/**
* Spacing type that represents the block start direction (top). E.g. {@code marginBlockStart}.
*/
public static final int BLOCK_START = 11;

private static final int[] sFlagsMap = {
1, /*LEFT*/ 2, /*TOP*/ 4, /*RIGHT*/ 8, /*BOTTOM*/ 16, /*START*/ 32, /*END*/ 64, /*HORIZONTAL*/
128, /*VERTICAL*/ 256, /*ALL*/
128, /*VERTICAL*/ 256, /*ALL*/ 512, /*BLOCK*/ 1024, /*BLOCK_END*/ 2048, /*BLOCK_START*/
};

private final float[] mSpacing;
Expand Down Expand Up @@ -96,7 +104,8 @@ public boolean set(int spacingType, float value) {
mHasAliasesSet =
(mValueFlags & sFlagsMap[ALL]) != 0
|| (mValueFlags & sFlagsMap[VERTICAL]) != 0
|| (mValueFlags & sFlagsMap[HORIZONTAL]) != 0;
|| (mValueFlags & sFlagsMap[HORIZONTAL]) != 0
|| (mValueFlags & sFlagsMap[BLOCK]) != 0;

return true;
}
Expand All @@ -111,7 +120,13 @@ public boolean set(int spacingType, float value) {
*/
public float get(int spacingType) {
float defaultValue =
(spacingType == START || spacingType == END ? YogaConstants.UNDEFINED : mDefaultValue);
(spacingType == START
|| spacingType == END
|| spacingType == BLOCK
|| spacingType == BLOCK_END
|| spacingType == BLOCK_START
? YogaConstants.UNDEFINED
: mDefaultValue);

if (mValueFlags == 0) {
return defaultValue;
Expand Down Expand Up @@ -174,6 +189,9 @@ private static float[] newFullSpacingArray() {
YogaConstants.UNDEFINED,
YogaConstants.UNDEFINED,
YogaConstants.UNDEFINED,
YogaConstants.UNDEFINED,
YogaConstants.UNDEFINED,
YogaConstants.UNDEFINED,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ public class ViewProps {
public static final String BORDER_RIGHT_COLOR = "borderRightColor";
public static final String BORDER_TOP_COLOR = "borderTopColor";
public static final String BORDER_BOTTOM_COLOR = "borderBottomColor";
public static final String BORDER_BLOCK_COLOR = "borderBlockColor";
public static final String BORDER_BLOCK_END_COLOR = "borderBlockEndColor";
public static final String BORDER_BLOCK_START_COLOR = "borderBlockStartColor";
public static final String BORDER_TOP_START_RADIUS = "borderTopStartRadius";
public static final String BORDER_TOP_END_RADIUS = "borderTopEndRadius";
public static final String BORDER_BOTTOM_START_RADIUS = "borderBottomStartRadius";
Expand Down Expand Up @@ -299,6 +302,15 @@ public static boolean isLayoutOnly(ReadableMap map, String prop) {
case BORDER_BOTTOM_COLOR:
return map.getType(BORDER_BOTTOM_COLOR) == ReadableType.Number
&& map.getInt(BORDER_BOTTOM_COLOR) == Color.TRANSPARENT;
case BORDER_BLOCK_COLOR:
return map.getType(BORDER_BLOCK_COLOR) == ReadableType.Number
&& map.getInt(BORDER_BLOCK_COLOR) == Color.TRANSPARENT;
case BORDER_BLOCK_END_COLOR:
return map.getType(BORDER_BLOCK_END_COLOR) == ReadableType.Number
&& map.getInt(BORDER_BLOCK_END_COLOR) == Color.TRANSPARENT;
case BORDER_BLOCK_START_COLOR:
return map.getType(BORDER_BLOCK_START_COLOR) == ReadableType.Number
&& map.getInt(BORDER_BLOCK_START_COLOR) == Color.TRANSPARENT;
case BORDER_WIDTH:
return map.isNull(BORDER_WIDTH) || map.getDouble(BORDER_WIDTH) == 0d;
case BORDER_LEFT_WIDTH:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ object ReactMapBufferPropSetter {
private const val EDGE_START = 4
private const val EDGE_END = 5
private const val EDGE_ALL = 6
private const val EDGE_BLOCK = 7
private const val EDGE_BLOCK_END = 8
private const val EDGE_BLOCK_START = 9

private const val CORNER_TOP_LEFT = 0
private const val CORNER_TOP_RIGHT = 1
Expand Down Expand Up @@ -349,6 +352,9 @@ object ReactMapBufferPropSetter {
EDGE_BOTTOM -> 4
EDGE_START -> 5
EDGE_END -> 6
EDGE_BLOCK -> 7
EDGE_BLOCK_END -> 8
EDGE_BLOCK_START -> 9
else -> throw IllegalArgumentException("Unknown key for border color: $key")
}
val colorValue = entry.intValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,21 @@ private void drawRoundedBackgroundWithBorders(Canvas canvas) {
int colorRight = getBorderColor(Spacing.RIGHT);
int colorBottom = getBorderColor(Spacing.BOTTOM);

int colorBlock = getBorderColor(Spacing.BLOCK);
int colorBlockStart = getBorderColor(Spacing.BLOCK_START);
int colorBlockEnd = getBorderColor(Spacing.BLOCK_END);

if (isBorderColorDefined(Spacing.BLOCK)) {
colorBottom = colorBlock;
colorTop = colorBlock;
}
if (isBorderColorDefined(Spacing.BLOCK_END)) {
colorBottom = colorBlockEnd;
}
if (isBorderColorDefined(Spacing.BLOCK_START)) {
colorTop = colorBlockStart;
}

if (borderWidth.top > 0
|| borderWidth.bottom > 0
|| borderWidth.left > 0
Expand Down Expand Up @@ -552,13 +567,19 @@ private void updatePath() {
int colorRight = getBorderColor(Spacing.RIGHT);
int colorBottom = getBorderColor(Spacing.BOTTOM);
int borderColor = getBorderColor(Spacing.ALL);
int colorBlock = getBorderColor(Spacing.BLOCK);
int colorBlockStart = getBorderColor(Spacing.BLOCK_START);
int colorBlockEnd = getBorderColor(Spacing.BLOCK_END);

// Clip border ONLY if its color is non transparent
if (Color.alpha(colorLeft) != 0
&& Color.alpha(colorTop) != 0
&& Color.alpha(colorRight) != 0
&& Color.alpha(colorBottom) != 0
&& Color.alpha(borderColor) != 0) {
&& Color.alpha(borderColor) != 0
&& Color.alpha(colorBlock) != 0
&& Color.alpha(colorBlockStart) != 0
&& Color.alpha(colorBlockEnd) != 0) {

mInnerClipTempRectForBorderRadius.top += borderWidth.top;
mInnerClipTempRectForBorderRadius.bottom -= borderWidth.bottom;
Expand Down Expand Up @@ -1128,6 +1149,21 @@ private void drawRectangularBackgroundWithBorders(Canvas canvas) {
int colorRight = getBorderColor(Spacing.RIGHT);
int colorBottom = getBorderColor(Spacing.BOTTOM);

int colorBlock = getBorderColor(Spacing.BLOCK);
int colorBlockStart = getBorderColor(Spacing.BLOCK_START);
int colorBlockEnd = getBorderColor(Spacing.BLOCK_END);

if (isBorderColorDefined(Spacing.BLOCK)) {
colorBottom = colorBlock;
colorTop = colorBlock;
}
if (isBorderColorDefined(Spacing.BLOCK_END)) {
colorBottom = colorBlockEnd;
}
if (isBorderColorDefined(Spacing.BLOCK_START)) {
colorTop = colorBlockStart;
}

final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
int colorStart = getBorderColor(Spacing.START);
int colorEnd = getBorderColor(Spacing.END);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
Spacing.BOTTOM,
Spacing.START,
Spacing.END,
Spacing.BLOCK,
Spacing.BLOCK_END,
Spacing.BLOCK_START
};
private static final int CMD_HOTSPOT_UPDATE = 1;
private static final int CMD_SET_PRESSED = 2;
Expand Down Expand Up @@ -238,7 +241,10 @@ public void setBorderWidth(ReactViewGroup view, int index, float width) {
ViewProps.BORDER_TOP_COLOR,
ViewProps.BORDER_BOTTOM_COLOR,
ViewProps.BORDER_START_COLOR,
ViewProps.BORDER_END_COLOR
ViewProps.BORDER_END_COLOR,
ViewProps.BORDER_BLOCK_COLOR,
ViewProps.BORDER_BLOCK_END_COLOR,
ViewProps.BORDER_BLOCK_START_COLOR
},
customType = "Color")
public void setBorderColor(ReactViewGroup view, int index, Integer color) {
Expand Down
21 changes: 17 additions & 4 deletions ReactCommon/react/renderer/components/view/primitives.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ struct CascadedRectangleEdges {
OptionalT horizontal{};
OptionalT vertical{};
OptionalT all{};
OptionalT block{};
OptionalT blockStart{};
OptionalT blockEnd{};

Counterpart resolve(bool isRTL, T defaults) const {
const auto leadingEdge = isRTL ? end : start;
Expand All @@ -111,10 +114,14 @@ struct CascadedRectangleEdges {
return {
/* .left = */
left.value_or(leadingEdge.value_or(horizontalOrAllOrDefault)),
/* .top = */ top.value_or(verticalOrAllOrDefault),
/* .top = */
blockStart.value_or(
block.value_or(top.value_or(verticalOrAllOrDefault))),
/* .right = */
right.value_or(trailingEdge.value_or(horizontalOrAllOrDefault)),
/* .bottom = */ bottom.value_or(verticalOrAllOrDefault),
/* .bottom = */
blockEnd.value_or(
block.value_or(bottom.value_or(verticalOrAllOrDefault))),
};
}

Expand All @@ -128,7 +135,10 @@ struct CascadedRectangleEdges {
this->end,
this->horizontal,
this->vertical,
this->all) ==
this->all,
this->block,
this->blockStart,
this->blockEnd) ==
std::tie(
rhs.left,
rhs.top,
Expand All @@ -138,7 +148,10 @@ struct CascadedRectangleEdges {
rhs.end,
rhs.horizontal,
rhs.vertical,
rhs.all);
rhs.all,
rhs.block,
rhs.blockStart,
rhs.blockEnd);
}

bool operator!=(const CascadedRectangleEdges<T> &rhs) const {
Expand Down
24 changes: 24 additions & 0 deletions ReactCommon/react/renderer/components/view/propsConversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,30 @@ static inline CascadedRectangleEdges<T> convertRawProp(
defaultValue.vertical,
prefix,
suffix);
result.block = convertRawProp(
context,
rawProps,
"Block",
sourceValue.block,
defaultValue.block,
prefix,
suffix);
result.blockEnd = convertRawProp(
context,
rawProps,
"BlockEnd",
sourceValue.blockEnd,
defaultValue.blockEnd,
prefix,
suffix);
result.blockStart = convertRawProp(
context,
rawProps,
"BlockStart",
sourceValue.blockStart,
defaultValue.blockStart,
prefix,
suffix);

result.all = convertRawProp(
context, rawProps, "", sourceValue.all, defaultValue.all, prefix, suffix);
Expand Down

0 comments on commit 597a1ff

Please sign in to comment.