Add isolate property (#45883)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45883

Isolate property lets us easily define when a <View> should set a stacking context.

This is particularly useful when used with `mix-blend-mode`

Changelog: [Internal]

Reviewed By: christophpurrer, NickGerleman

Differential Revision: D60604683

fbshipit-source-id: 449079abe45ae57e98315bdf27b54ec5cf9d6fdc
This commit is contained in:
Jorge Cabiedes Acosta
2024-08-15 16:55:26 -07:00
committed by Facebook GitHub Bot
parent 0a698e5971
commit 17017d2b81
12 changed files with 79 additions and 5 deletions
@@ -127,6 +127,11 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
*/
experimental_mixBlendMode: true,
/**
* Isolation
*/
isolation: true,
/*
* BoxShadow
*/
@@ -170,6 +170,7 @@ const validAttributesForNonEventProps = {
process: require('../StyleSheet/processFilter').default,
},
experimental_mixBlendMode: true,
isolation: true,
opacity: true,
elevation: true,
shadowColor: {process: require('../StyleSheet/processColor').default},
@@ -228,6 +228,8 @@ const validAttributesForNonEventProps = {
experimental_boxShadow: {
process: require('../StyleSheet/processBoxShadow').default,
},
experimental_mixBlendMode: true,
isolation: true,
borderTopWidth: true,
borderTopColor: {process: require('../StyleSheet/processColor').default},
@@ -332,6 +332,7 @@ export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
* Controls whether the View can be the target of touch events.
*/
pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto' | undefined;
isolation?: 'auto' | 'isolate' | undefined;
cursor?: CursorValue | undefined;
}
@@ -792,6 +792,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
experimental_filter?: $ReadOnlyArray<FilterFunction> | string,
experimental_mixBlendMode?: ____BlendMode_Internal,
experimental_backgroundImage?: $ReadOnlyArray<GradientValue> | string,
isolation?: 'auto' | 'isolate',
}>;
export type ____ViewStyle_Internal = $ReadOnly<{
@@ -8408,6 +8408,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
experimental_filter?: $ReadOnlyArray<FilterFunction> | string,
experimental_mixBlendMode?: ____BlendMode_Internal,
experimental_backgroundImage?: $ReadOnlyArray<GradientValue> | string,
isolation?: \\"auto\\" | \\"isolate\\",
}>;
export type ____ViewStyle_Internal = $ReadOnly<{
...____ViewStyle_InternalCore,
@@ -184,6 +184,14 @@ BaseViewProps::BaseViewProps(
"experimental_mixBlendMode",
sourceProps.mixBlendMode,
{})),
isolation(
CoreFeatures::enablePropIteratorSetter ? sourceProps.isolation
: convertRawProp(
context,
rawProps,
"isolation",
sourceProps.isolation,
{})),
transform(
CoreFeatures::enablePropIteratorSetter ? sourceProps.transform
: convertRawProp(
@@ -330,6 +338,7 @@ void BaseViewProps::setProp(
RAW_SET_PROP_SWITCH_CASE_BASIC(shouldRasterize);
RAW_SET_PROP_SWITCH_CASE_BASIC(zIndex);
RAW_SET_PROP_SWITCH_CASE_BASIC(pointerEvents);
RAW_SET_PROP_SWITCH_CASE_BASIC(isolation);
RAW_SET_PROP_SWITCH_CASE_BASIC(hitSlop);
RAW_SET_PROP_SWITCH_CASE_BASIC(onLayout);
RAW_SET_PROP_SWITCH_CASE_BASIC(collapsable);
@@ -18,6 +18,7 @@
#include <react/renderer/graphics/BoxShadow.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Filter.h>
#include <react/renderer/graphics/Isolation.h>
#include <react/renderer/graphics/Transform.h>
#include <optional>
@@ -68,7 +69,10 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps {
std::vector<GradientValue> backgroundImage{};
// MixBlendMode
BlendMode mixBlendMode;
BlendMode mixBlendMode{BlendMode::Normal};
// Isolate
Isolation isolation{Isolation::Auto};
// Transform
Transform transform{};
@@ -63,6 +63,7 @@ void ViewShadowNode::initialize() noexcept {
viewProps.removeClippedSubviews || viewProps.cursor != Cursor::Auto ||
!viewProps.filter.empty() ||
viewProps.mixBlendMode != BlendMode::Normal ||
viewProps.isolation == Isolation::Isolate ||
HostPlatformViewTraitsInitializer::formsStackingContext(viewProps);
bool formsView = formsStackingContext ||
@@ -20,6 +20,7 @@
#include <react/renderer/graphics/BlendMode.h>
#include <react/renderer/graphics/BoxShadow.h>
#include <react/renderer/graphics/Filter.h>
#include <react/renderer/graphics/Isolation.h>
#include <react/renderer/graphics/PlatformColorParser.h>
#include <react/renderer/graphics/Transform.h>
#include <react/renderer/graphics/ValueUnit.h>
@@ -1184,6 +1185,27 @@ inline void fromRawValue(
result = backgroundImage;
}
inline void fromRawValue(
const PropsParserContext& /*context*/,
const RawValue& value,
Isolation& result) {
react_native_expect(value.hasType<std::string>());
result = Isolation::Auto;
if (!value.hasType<std::string>()) {
return;
}
auto rawIsolation = static_cast<std::string>(value);
std::optional<Isolation> isolation = isolationFromString(rawIsolation);
if (!isolation) {
LOG(ERROR) << "Could not parse isolation: " << rawIsolation;
return;
}
result = isolation.value();
}
template <size_t N>
inline std::string toString(const std::array<float, N> vec) {
std::string s;
@@ -7,12 +7,8 @@
#pragma once
#include <react/renderer/graphics/Float.h>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
namespace facebook::react {
@@ -0,0 +1,31 @@
/*
* 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.
*/
#pragma once
#include <optional>
#include <string_view>
namespace facebook::react {
// https://www.w3.org/TR/compositing-1/#isolation
enum class Isolation {
Auto,
Isolate,
};
inline std::optional<Isolation> isolationFromString(
std::string_view isolationSetting) {
if (isolationSetting == "auto") {
return Isolation::Auto;
} else if (isolationSetting == "isolate") {
return Isolation::Isolate;
} else {
return std::nullopt;
}
}
} // namespace facebook::react