@@ -18,7 +18,21 @@ import {
1818import { calculateProps } from "./calculate-props" ;
1919
2020/**
21- * Checks if two style objects have non-overlapping properties
21+ * Checks if the left style object has any properties that are not present in the right style object.
22+ * This is used to determine if styles need to be preserved in an array or if right can completely override left.
23+ *
24+ * Note: This intentionally only checks one direction (left → right). We don't need to check if right has
25+ * properties that left doesn't have, because right will always be applied/merged. The question we're
26+ * answering is: "Does left have any properties that would be lost if we just used right?" If yes, we
27+ * create a style array [left, right] to preserve both. If no, right can safely replace left entirely.
28+ *
29+ * @param left - The left style object to check
30+ * @param right - The right style object to compare against
31+ * @returns true if left has at least one property key that doesn't exist in right, false otherwise
32+ *
33+ * @example
34+ * hasNonOverlappingProperties({color: 'red', fontSize: 12}, {color: 'blue'}) // true - fontSize is not in right
35+ * hasNonOverlappingProperties({color: 'red'}, {color: 'blue', fontSize: 12}) // false - all left keys exist in right
2236 */
2337function hasNonOverlappingProperties (
2438 left : Record < string , any > ,
@@ -41,7 +55,14 @@ function hasNonOverlappingProperties(
4155}
4256
4357/**
44- * Flattens a style array into a single object, with rightmost values taking precedence
58+ * Flattens a style array into a single object when possible, with rightmost values taking precedence.
59+ * Returns the original array if it contains any non-plain objects, arrays, or CSS variable objects.
60+ *
61+ * Note: This function assumes the input array has already been filtered (e.g., by filterCssVariables),
62+ * so empty arrays should not reach this function. If they do, they will be treated as non-flattenable.
63+ *
64+ * @param styleArray - The style array to potentially flatten
65+ * @returns A single merged object if all items are plain objects, otherwise the original array
4566 */
4667function flattenStyleArray ( styleArray : any [ ] ) : any {
4768 // Check if we can flatten to a single object (all items are plain objects)
@@ -62,9 +83,27 @@ function flattenStyleArray(styleArray: any[]): any {
6283}
6384
6485/**
65- * Recursively filters out CSS variable objects (with VAR_SYMBOL) from style values
86+ * Recursively filters out CSS variable objects (with VAR_SYMBOL) from style values.
87+ * This prevents CSS variable runtime objects from leaking into React Native component props.
88+ *
89+ * @param value - The value to filter (can be any type: object, array, primitive, etc.)
90+ * @param depth - Internal recursion depth counter to prevent stack overflow (max 100)
91+ * @returns The filtered value with CSS variables removed, or `undefined` if the entire value
92+ * should be filtered out (e.g., empty arrays, objects with only VAR_SYMBOL properties)
93+ *
94+ * Filtering behavior:
95+ * - Objects with VAR_SYMBOL property: returns `undefined` (completely filtered)
96+ * - Arrays: filters out VAR_SYMBOL objects, returns `undefined` if empty after filtering
97+ * - Objects: recursively filters properties, returns `undefined` if no properties remain
98+ * - Primitives (null, undefined, numbers, strings, booleans): returned as-is
99+ * - Symbol properties: intentionally filtered out for React Native compatibility
100+ *
101+ * @example
102+ * filterCssVariables({fontSize: 16, color: {[VAR_SYMBOL]: true}}) // {fontSize: 16}
103+ * filterCssVariables([{margin: 10}, {[VAR_SYMBOL]: true}]) // [{margin: 10}]
104+ * filterCssVariables({color: {[VAR_SYMBOL]: true}}) // undefined (all props filtered)
66105 */
67- function filterCssVariables ( value : any , depth = 0 ) : any {
106+ function filterCssVariables ( value : any , depth = 0 ) : any | undefined {
68107 // Prevent stack overflow on deeply nested structures
69108 if ( depth > 100 ) {
70109 return value ;
0 commit comments