Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,38 @@ package com.facebook.react.uimanager.common

import androidx.annotation.IntDef

/**
* Annotation class that defines the type of UIManager being used in React Native.
*
* This annotation is used to distinguish between the legacy UIManager implementation and the newer
* Fabric renderer. It helps ensure type safety when working with UIManager-related code by
* restricting values to the defined constants.
*
* @see UIManagerType.LEGACY for legacy (Paper) UIManager
* @see UIManagerType.FABRIC for Fabric renderer
*/
@Retention(AnnotationRetention.SOURCE)
@Suppress("DEPRECATION")
@IntDef(UIManagerType.DEFAULT, UIManagerType.LEGACY, UIManagerType.FABRIC)
public annotation class UIManagerType {
public companion object {
/**
* Default UIManager type. Equivalent to [LEGACY].
*
* @deprecated Use [LEGACY] instead.
*/
@Deprecated(
"UIManagerType.DEFAULT will be deleted in the next release of React Native. Use [LEGACY] instead."
)
public const val DEFAULT: Int = 1

/** Represents the legacy (Paper) UIManager implementation. */
public const val LEGACY: Int = 1

/**
* Represents the Fabric renderer, React Native's new rendering system that provides improved
* performance and better integration with the host platform.
*/
public const val FABRIC: Int = 2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,23 @@ package com.facebook.react.uimanager.common

import android.view.View

/**
* Utility object providing helper methods for working with React Native views.
*
* This object contains utilities for determining which UIManager (Legacy/Paper or Fabric) a view
* belongs to, based on view tags and surface IDs. These utilities are essential for routing events
* and operations to the correct UIManager implementation.
*
* @see UIManagerType
*/
public object ViewUtil {

/**
* Constant representing the absence of a surface ID.
*
* This value (-1) is used as a placeholder when no surface ID is available, typically indicating
* that the view or event originated from the legacy (Paper) UIManager rather than Fabric.
*/
public const val NO_SURFACE_ID: Int = -1

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import android.graphics.Shader
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType

/**
* Represents a single layer of a background image, typically containing a gradient.
*
* This class encapsulates gradient definitions (linear or radial) that can be applied as background
* layers to React Native views. It provides parsing from React Native bridge data and shader
* generation for rendering.
*
* @see LinearGradient
* @see RadialGradient
*/
public class BackgroundImageLayer() {
private lateinit var gradient: Gradient

Expand All @@ -20,6 +30,16 @@ public class BackgroundImageLayer() {
}

public companion object {
/**
* Parses a ReadableMap into a BackgroundImageLayer.
*
* The map should contain gradient configuration including a "type" key specifying either
* "linear-gradient" or "radial-gradient".
*
* @param gradientMap The map containing gradient configuration
* @param context Android context for resource resolution
* @return A BackgroundImageLayer instance, or null if parsing fails
*/
public fun parse(gradientMap: ReadableMap?, context: Context): BackgroundImageLayer? {
if (gradientMap == null) {
return null
Expand All @@ -41,5 +61,12 @@ public class BackgroundImageLayer() {
}
}

/**
* Creates a shader for rendering this background layer.
*
* @param width The width of the area to fill
* @param height The height of the area to fill
* @return A Shader instance for rendering the gradient
*/
public fun getShader(width: Float, height: Float): Shader = gradient.getShader(width, height)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,33 @@ import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.uimanager.LengthPercentage

/**
* Represents the position of a background image within its container.
*
* This class models CSS-like background-position values, allowing specification of offsets from any
* edge (top, left, right, bottom). Each offset can be a length or percentage value.
*
* @property top Offset from the top edge, or null if not specified
* @property left Offset from the left edge, or null if not specified
* @property right Offset from the right edge, or null if not specified
* @property bottom Offset from the bottom edge, or null if not specified
*/
internal class BackgroundPosition(
public val top: LengthPercentage?,
public val left: LengthPercentage?,
public val right: LengthPercentage?,
public val bottom: LengthPercentage?,
) {
public companion object {
/**
* Parses a ReadableMap into a BackgroundPosition.
*
* The map may contain "top", "left", "right", and/or "bottom" keys with length or percentage
* values.
*
* @param backgroundPositionMap The map containing position values
* @return A BackgroundPosition instance, or null if the map is null
*/
public fun parse(backgroundPositionMap: ReadableMap?): BackgroundPosition? {
if (backgroundPositionMap == null) return null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,45 @@ package com.facebook.react.uimanager.style
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType

/**
* Enum representing the possible repeat behavior keywords for background images.
*
* These values correspond to CSS background-repeat keywords.
*/
internal enum class BackgroundRepeatKeyword {
/** The image is repeated as much as needed to cover the background area. */
Repeat,
/** The image is repeated as much as possible without clipping, with space distributed evenly. */
Space,
/** The image is repeated as much as possible without clipping, scaling to fit evenly. */
Round,
/** The image is not repeated and only shown once. */
NoRepeat,
}

/**
* Represents the background repeat behavior for both horizontal and vertical axes.
*
* This class models the CSS background-repeat property, specifying how background images should be
* repeated in each direction.
*
* @property x The repeat behavior for the horizontal axis
* @property y The repeat behavior for the vertical axis
*/
internal class BackgroundRepeat(
public val x: BackgroundRepeatKeyword,
public val y: BackgroundRepeatKeyword,
) {
public companion object {
/**
* Parses a ReadableMap into a BackgroundRepeat.
*
* The map should contain "x" and/or "y" keys with string values matching the
* BackgroundRepeatKeyword values. Missing values default to Repeat.
*
* @param backgroundRepeatMap The map containing repeat values
* @return A BackgroundRepeat instance, or null if the map is null
*/
public fun parse(backgroundRepeatMap: ReadableMap?): BackgroundRepeat? {
if (backgroundRepeatMap == null) return null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,44 @@ import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.uimanager.LengthPercentage

/**
* Represents a background size value with horizontal (x) and vertical (y) length/percentage
* components.
*
* This class handles CSS-like background-size values where each dimension can be a length,
* percentage, or "auto". A null value for x or y indicates "auto" sizing for that dimension.
*
* @property x The horizontal size component, or null for "auto"
* @property y The vertical size component, or null for "auto"
*/
internal class BackgroundSizeLengthPercentage(
public val x: LengthPercentage?,
public val y: LengthPercentage?,
) {
/**
* Checks if the horizontal dimension is set to auto.
*
* @return true if x is null (auto), false otherwise
*/
public fun isXAuto(): Boolean = x == null

/**
* Checks if the vertical dimension is set to auto.
*
* @return true if y is null (auto), false otherwise
*/
public fun isYAuto(): Boolean = y == null

public companion object {
/**
* Parses a ReadableMap into a BackgroundSizeLengthPercentage.
*
* The map should contain "x" and/or "y" keys with values that are either numbers (treated as
* points), percentage strings (e.g., "50%"), or "auto".
*
* @param backgroundSizeMap The map containing x and y size values
* @return A BackgroundSizeLengthPercentage instance, or null if the map is null
*/
public fun parse(backgroundSizeMap: ReadableMap?): BackgroundSizeLengthPercentage? {
if (backgroundSizeMap == null) return null

Expand Down Expand Up @@ -78,11 +107,32 @@ internal class BackgroundSizeLengthPercentage(
}
}

/**
* Sealed class representing CSS background-size property values.
*
* This class models the different ways a background size can be specified in CSS, currently
* supporting length/percentage/auto values for both dimensions.
*
* @see BackgroundSizeLengthPercentage
*/
internal sealed class BackgroundSize {
/**
* Represents a background size specified using length, percentage, or auto values.
*
* @property lengthPercentage The parsed size values for x and y dimensions
*/
public class LengthPercentageAuto(public val lengthPercentage: BackgroundSizeLengthPercentage) :
BackgroundSize()

public companion object {
/**
* Parses a Dynamic value into a BackgroundSize.
*
* Currently supports map values containing x/y dimensions.
*
* @param backgroundSizeValue The dynamic value to parse
* @return A BackgroundSize instance, or null if parsing fails
*/
public fun parse(backgroundSizeValue: Dynamic?): BackgroundSize? {
if (backgroundSizeValue == null) return null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,51 @@ import android.util.LayoutDirection
import androidx.annotation.ColorInt
import com.facebook.react.modules.i18nmanager.I18nUtil

/**
* Represents resolved border colors for all four physical edges of a box.
*
* This data class contains the final computed color values after resolving logical properties based
* on layout direction.
*
* @property left Color for the left edge
* @property top Color for the top edge
* @property right Color for the right edge
* @property bottom Color for the bottom edge
*/
internal data class ColorEdges(
@param:ColorInt val left: Int = Color.BLACK,
@param:ColorInt val top: Int = Color.BLACK,
@param:ColorInt val right: Int = Color.BLACK,
@param:ColorInt val bottom: Int = Color.BLACK,
)

/**
* Represents border colors using logical edge properties.
*
* This inline value class stores colors for all logical edges (start, end, block-start, block-end,
* etc.) and resolves them to physical edges based on layout direction and RTL settings.
*
* @property edgeColors Array of colors indexed by [LogicalEdge] ordinal values
* @see LogicalEdge
* @see ColorEdges
*/
@JvmInline
internal value class BorderColors(
@param:ColorInt val edgeColors: Array<Int?> = arrayOfNulls<Int?>(LogicalEdge.values().size)
) {

/**
* Resolves logical edge colors to physical edge colors based on layout direction.
*
* This method handles RTL layout direction and the doLeftAndRightSwapInRTL setting to correctly
* map logical properties (start, end, block-start, block-end) to physical edges (left, right,
* top, bottom).
*
* @param layoutDirection The resolved layout direction (LTR or RTL)
* @param context Android context for RTL swap preference
* @return ColorEdges with resolved physical edge colors
* @throws IllegalArgumentException if layoutDirection is not LTR or RTL
*/
fun resolve(layoutDirection: Int, context: Context): ColorEdges {
return when (layoutDirection) {
LayoutDirection.LTR ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,19 @@ import com.facebook.react.bridge.JSApplicationCausedNativeException
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType

/** Represents all logical properties and shorthands for border radius. */
/**
* Represents a box shadow effect that can be applied to a React Native view.
*
* This data class models the CSS box-shadow property, including offset, blur, spread, color, and
* inset options.
*
* @property offsetX The horizontal offset of the shadow in pixels
* @property offsetY The vertical offset of the shadow in pixels
* @property color The color of the shadow, or null for default
* @property blurRadius The blur radius of the shadow, or null for no blur
* @property spreadDistance The spread distance of the shadow, or null for no spread
* @property inset Whether the shadow is inset (inner shadow), or null for outer shadow
*/
public data class BoxShadow(
val offsetX: Float,
val offsetY: Float,
Expand All @@ -24,6 +36,16 @@ public data class BoxShadow(
val inset: Boolean? = null,
) {
public companion object {
/**
* Parses a ReadableMap into a BoxShadow.
*
* The map must contain "offsetX" and "offsetY" keys. Optional keys include "color",
* "blurRadius", "spreadDistance", and "inset".
*
* @param boxShadow The map containing box shadow configuration
* @param context Android context for color resolution
* @return A BoxShadow instance, or null if required fields are missing
*/
@JvmStatic
public fun parse(boxShadow: ReadableMap?, context: Context): BoxShadow? {
if (boxShadow == null || !(boxShadow.hasKey("offsetX") && boxShadow.hasKey("offsetY"))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,37 @@ package com.facebook.react.uimanager.style
import com.facebook.react.uimanager.LengthPercentage
import com.facebook.react.uimanager.PixelUtil

/** Represents the resolved horizontal and vertical radii of the ellipse representing a corner. */
/**
* Represents the resolved horizontal and vertical radii of the ellipse representing a corner.
*
* This data class stores the computed radius values for a single corner of a view's border. Each
* corner can have an elliptical shape with different horizontal and vertical radii.
*
* @property horizontal The horizontal radius of the corner ellipse in pixels
* @property vertical The vertical radius of the corner ellipse in pixels
*/
public data class CornerRadii(
val horizontal: Float = 0f,
val vertical: Float = 0f,
) {
/**
* Creates CornerRadii by resolving a LengthPercentage value against reference dimensions.
*
* @param length The length/percentage value to resolve
* @param referenceWidth The reference width for percentage calculations
* @param referenceHeight The reference height for percentage calculations
*/
public constructor(
length: LengthPercentage,
referenceWidth: Float,
referenceHeight: Float,
) : this(horizontal = length.resolve(referenceWidth), vertical = length.resolve(referenceHeight))

/**
* Converts the corner radii from density-independent pixels (DIP) to physical pixels.
*
* @return A new CornerRadii with values converted to pixels
*/
public fun toPixelFromDIP(): CornerRadii {
return CornerRadii(PixelUtil.toPixelFromDIP(horizontal), PixelUtil.toPixelFromDIP(vertical))
}
Expand Down
Loading