From 7143a45d40defe5e7aca2aa65295d01ec76e0c6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 20:02:07 +0000 Subject: [PATCH 1/8] Initial plan From 824bea5f3c661dcae5eb29e736620c20b8433ef0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 20:07:36 +0000 Subject: [PATCH 2/8] Add ColorWithSystemEffect support to Fabric renderer Co-authored-by: Saadnajmi <6722175+Saadnajmi@users.noreply.github.com> --- .../renderer/graphics/HostPlatformColor.mm | 27 +++++++++++++++++ .../renderer/graphics/PlatformColorParser.mm | 29 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm index 069af91004855f..c81b0aeb300445 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm @@ -164,6 +164,33 @@ int32_t ColorFromUIColor(const std::shared_ptr &uiColor) return uiColor; } +#if TARGET_OS_OSX // [macOS +RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( + RCTUIColor *baseColor, + const std::string &systemEffectString) // [macOS] +{ + if (baseColor == nil) { + return nil; + } + + NSColor *colorWithEffect = baseColor; + if (!systemEffectString.empty()) { + if (systemEffectString == "none") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectNone]; + } else if (systemEffectString == "pressed") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectPressed]; + } else if (systemEffectString == "deepPressed") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDeepPressed]; + } else if (systemEffectString == "disabled") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDisabled]; + } else if (systemEffectString == "rollover") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectRollover]; + } + } + return colorWithEffect; +} +#endif // macOS] + int32_t hashFromUIColor(const std::shared_ptr &uiColor) { if (uiColor == nullptr) { diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm index 7cb04798066724..1ff0df0cb82baa 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm @@ -7,6 +7,7 @@ #import "PlatformColorParser.h" +#import // [macOS] #import #import #import @@ -18,6 +19,13 @@ NS_ASSUME_NONNULL_BEGIN +#if TARGET_OS_OSX // [macOS +// Forward declaration for ColorWithSystemEffect helper +RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( + RCTUIColor *baseColor, + const std::string &systemEffectString); +#endif // macOS] + namespace facebook::react { inline facebook::react::SharedColor RCTPlatformColorComponentsFromDynamicItems( @@ -63,6 +71,27 @@ SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t auto dynamicItems = (std::unordered_map)items.at("dynamic"); return RCTPlatformColorComponentsFromDynamicItems(contextContainer, surfaceId, dynamicItems); } +#if TARGET_OS_OSX // [macOS + else if ( + items.find("colorWithSystemEffect") != items.end() && + items.at("colorWithSystemEffect").hasType>()) { + auto colorWithSystemEffectItems = (std::unordered_map)items.at("colorWithSystemEffect"); + if (colorWithSystemEffectItems.find("baseColor") != colorWithSystemEffectItems.end() && + colorWithSystemEffectItems.find("systemEffect") != colorWithSystemEffectItems.end() && + colorWithSystemEffectItems.at("systemEffect").hasType()) { + SharedColor baseColorShared{}; + fromRawValue(contextContainer, surfaceId, colorWithSystemEffectItems.at("baseColor"), baseColorShared); + if (baseColorShared) { + RCTUIColor *baseColor = RCTPlatformColorFromColor(*baseColorShared); + std::string systemEffect = (std::string)colorWithSystemEffectItems.at("systemEffect"); + RCTUIColor *colorWithEffect = UIColorFromColorWithSystemEffect(baseColor, systemEffect); + if (colorWithEffect != nil) { + return SharedColor(Color(wrapManagedObject(colorWithEffect))); + } + } + } + } +#endif // macOS] } return clearColor(); From cd0b02ae3c46f93c773e174656dc4754081c1aeb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 20:37:31 +0000 Subject: [PATCH 3/8] Refactor: Move macOS-specific color code to dedicated platform folder Co-authored-by: Saadnajmi <6722175+Saadnajmi@users.noreply.github.com> --- .../renderer/graphics/React-graphics.podspec | 13 ++- .../renderer/graphics/HostPlatformColor.mm | 27 ----- .../renderer/graphics/PlatformColorParser.mm | 29 ------ .../renderer/graphics/HostPlatformColor.mm | 56 +++++++++++ .../renderer/graphics/PlatformColorParser.mm | 99 +++++++++++++++++++ 5 files changed, 165 insertions(+), 59 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm create mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec index a00b8b9006f96d..3545621bb4ede5 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec +++ b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec @@ -24,7 +24,10 @@ boost_config = get_boost_config() boost_compiler_flags = boost_config[:compiler_flags] Pod::Spec.new do |s| - source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}" + # [macOS Use platform specific sources + ios_source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}" + macos_source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}", "platform/macos/**/*.{m,mm,cpp,h}" + # macOS] header_search_paths = [ "\"$(PODS_ROOT)/boost\"", "\"$(PODS_TARGET_SRCROOT)/../../../\"", @@ -43,7 +46,11 @@ Pod::Spec.new do |s| s.platforms = min_supported_versions s.source = source s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags - s.source_files = source_files + # [macOS Use platform specific sources + s.ios.source_files = ios_source_files + s.visionos.source_files = ios_source_files + s.osx.source_files = macos_source_files + # macOS] s.header_dir = "react/renderer/graphics" # [macOS Restrict UIKit to iOS and visionOS s.ios.framework = "UIKit" @@ -54,7 +61,7 @@ Pod::Spec.new do |s| if ENV['USE_FRAMEWORKS'] s.module_name = "React_graphics" s.header_mappings_dir = "../../.." - header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""] + header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\"", "\"$(PODS_TARGET_SRCROOT)/platform/macos\""] # [macOS] end s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm index c81b0aeb300445..069af91004855f 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm @@ -164,33 +164,6 @@ int32_t ColorFromUIColor(const std::shared_ptr &uiColor) return uiColor; } -#if TARGET_OS_OSX // [macOS -RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( - RCTUIColor *baseColor, - const std::string &systemEffectString) // [macOS] -{ - if (baseColor == nil) { - return nil; - } - - NSColor *colorWithEffect = baseColor; - if (!systemEffectString.empty()) { - if (systemEffectString == "none") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectNone]; - } else if (systemEffectString == "pressed") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectPressed]; - } else if (systemEffectString == "deepPressed") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDeepPressed]; - } else if (systemEffectString == "disabled") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDisabled]; - } else if (systemEffectString == "rollover") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectRollover]; - } - } - return colorWithEffect; -} -#endif // macOS] - int32_t hashFromUIColor(const std::shared_ptr &uiColor) { if (uiColor == nullptr) { diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm index 1ff0df0cb82baa..7cb04798066724 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm @@ -7,7 +7,6 @@ #import "PlatformColorParser.h" -#import // [macOS] #import #import #import @@ -19,13 +18,6 @@ NS_ASSUME_NONNULL_BEGIN -#if TARGET_OS_OSX // [macOS -// Forward declaration for ColorWithSystemEffect helper -RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( - RCTUIColor *baseColor, - const std::string &systemEffectString); -#endif // macOS] - namespace facebook::react { inline facebook::react::SharedColor RCTPlatformColorComponentsFromDynamicItems( @@ -71,27 +63,6 @@ SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t auto dynamicItems = (std::unordered_map)items.at("dynamic"); return RCTPlatformColorComponentsFromDynamicItems(contextContainer, surfaceId, dynamicItems); } -#if TARGET_OS_OSX // [macOS - else if ( - items.find("colorWithSystemEffect") != items.end() && - items.at("colorWithSystemEffect").hasType>()) { - auto colorWithSystemEffectItems = (std::unordered_map)items.at("colorWithSystemEffect"); - if (colorWithSystemEffectItems.find("baseColor") != colorWithSystemEffectItems.end() && - colorWithSystemEffectItems.find("systemEffect") != colorWithSystemEffectItems.end() && - colorWithSystemEffectItems.at("systemEffect").hasType()) { - SharedColor baseColorShared{}; - fromRawValue(contextContainer, surfaceId, colorWithSystemEffectItems.at("baseColor"), baseColorShared); - if (baseColorShared) { - RCTUIColor *baseColor = RCTPlatformColorFromColor(*baseColorShared); - std::string systemEffect = (std::string)colorWithSystemEffectItems.at("systemEffect"); - RCTUIColor *colorWithEffect = UIColorFromColorWithSystemEffect(baseColor, systemEffect); - if (colorWithEffect != nil) { - return SharedColor(Color(wrapManagedObject(colorWithEffect))); - } - } - } - } -#endif // macOS] } return clearColor(); diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm new file mode 100644 index 00000000000000..f934faf91ed3a0 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm @@ -0,0 +1,56 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// [macOS] + +#import "HostPlatformColor.h" + +#import +#import +#import +#import +#import +#import + +using namespace facebook::react; + +NS_ASSUME_NONNULL_BEGIN + +namespace facebook::react { + +namespace { + +RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( + RCTUIColor *baseColor, + const std::string &systemEffectString) +{ + if (baseColor == nil) { + return nil; + } + + NSColor *colorWithEffect = baseColor; + if (!systemEffectString.empty()) { + if (systemEffectString == "none") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectNone]; + } else if (systemEffectString == "pressed") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectPressed]; + } else if (systemEffectString == "deepPressed") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDeepPressed]; + } else if (systemEffectString == "disabled") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDisabled]; + } else if (systemEffectString == "rollover") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectRollover]; + } + } + return colorWithEffect; +} + +} // anonymous namespace + +} // namespace facebook::react + +NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm new file mode 100644 index 00000000000000..fdc9abb83323c0 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm @@ -0,0 +1,99 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// [macOS] + +#import "PlatformColorParser.h" + +#import +#import +#import +#import +#import +#import +#import + +using namespace facebook::react; + +NS_ASSUME_NONNULL_BEGIN + +// Forward declaration for ColorWithSystemEffect helper +RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( + RCTUIColor *baseColor, + const std::string &systemEffectString); + +namespace facebook::react { + +inline facebook::react::SharedColor RCTPlatformColorComponentsFromDynamicItems( + const facebook::react::ContextContainer &contextContainer, + int32_t surfaceId, + std::unordered_map &dynamicItems) +{ + SharedColor lightSharedColor{}; + SharedColor darkSharedColor{}; + SharedColor highContrastLightSharedColor{}; + SharedColor highContrastDarkSharedColor{}; + if (dynamicItems.count("light")) { + fromRawValue(contextContainer, surfaceId, dynamicItems.at("light"), lightSharedColor); + } + if (dynamicItems.count("dark")) { + fromRawValue(contextContainer, surfaceId, dynamicItems.at("dark"), darkSharedColor); + } + if (dynamicItems.count("highContrastLight")) { + fromRawValue(contextContainer, surfaceId, dynamicItems.at("highContrastLight"), highContrastLightSharedColor); + } + if (dynamicItems.count("highContrastDark")) { + fromRawValue(contextContainer, surfaceId, dynamicItems.at("highContrastDark"), highContrastDarkSharedColor); + } + + Color color = Color(DynamicColor{ + (*lightSharedColor).getColor(), + (*darkSharedColor).getColor(), + (*highContrastLightSharedColor).getColor(), + (*highContrastDarkSharedColor).getColor()}); + return SharedColor(color); +} + +SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t surfaceId, const RawValue &value) +{ + if (value.hasType>()) { + auto items = (std::unordered_map)value; + if (items.find("semantic") != items.end() && items.at("semantic").hasType>()) { + auto semanticItems = (std::vector)items.at("semantic"); + return SharedColor(Color::createSemanticColor(semanticItems)); + } else if ( + items.find("dynamic") != items.end() && + items.at("dynamic").hasType>()) { + auto dynamicItems = (std::unordered_map)items.at("dynamic"); + return RCTPlatformColorComponentsFromDynamicItems(contextContainer, surfaceId, dynamicItems); + } else if ( + items.find("colorWithSystemEffect") != items.end() && + items.at("colorWithSystemEffect").hasType>()) { + auto colorWithSystemEffectItems = (std::unordered_map)items.at("colorWithSystemEffect"); + if (colorWithSystemEffectItems.find("baseColor") != colorWithSystemEffectItems.end() && + colorWithSystemEffectItems.find("systemEffect") != colorWithSystemEffectItems.end() && + colorWithSystemEffectItems.at("systemEffect").hasType()) { + SharedColor baseColorShared{}; + fromRawValue(contextContainer, surfaceId, colorWithSystemEffectItems.at("baseColor"), baseColorShared); + if (baseColorShared) { + RCTUIColor *baseColor = RCTPlatformColorFromColor(*baseColorShared); + std::string systemEffect = (std::string)colorWithSystemEffectItems.at("systemEffect"); + RCTUIColor *colorWithEffect = UIColorFromColorWithSystemEffect(baseColor, systemEffect); + if (colorWithEffect != nil) { + return SharedColor(Color(wrapManagedObject(colorWithEffect))); + } + } + } + } + } + + return clearColor(); +} + +} // namespace facebook::react + +NS_ASSUME_NONNULL_END From 5aafdb53130ab708b9149804d2378903c3fa47fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 20:39:19 +0000 Subject: [PATCH 4/8] Fix: Move UIColorFromColorWithSystemEffect out of anonymous namespace Co-authored-by: Saadnajmi <6722175+Saadnajmi@users.noreply.github.com> --- .../macos/react/renderer/graphics/HostPlatformColor.mm | 4 ---- .../macos/react/renderer/graphics/PlatformColorParser.mm | 1 - 2 files changed, 5 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm index f934faf91ed3a0..2b933bf76aa5f1 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm @@ -22,8 +22,6 @@ namespace facebook::react { -namespace { - RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( RCTUIColor *baseColor, const std::string &systemEffectString) @@ -49,8 +47,6 @@ return colorWithEffect; } -} // anonymous namespace - } // namespace facebook::react NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm index fdc9abb83323c0..63d4ceedf3459d 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm @@ -9,7 +9,6 @@ #import "PlatformColorParser.h" -#import #import #import #import From fadacf9b11c86d55c187b55629ded740327b67a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:36:29 +0000 Subject: [PATCH 5/8] Add macOS-specific semantic colors support (RCTPlatformColorUtils) Co-authored-by: Saadnajmi <6722175+Saadnajmi@users.noreply.github.com> --- .../graphics/RCTPlatformColorUtils.mm | 240 ++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm new file mode 100644 index 00000000000000..574881d038fa7f --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm @@ -0,0 +1,240 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// [macOS] + +#import "RCTPlatformColorUtils.h" + +#import +#import +#import +#import + +#include + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const kColorSuffix = @"Color"; +static NSString *const kFallbackARGBKey = @"fallback-argb"; +static NSString *const kFallbackKey = @"fallback"; +static NSString *const kSelectorKey = @"selector"; +static NSString *const kIndexKey = @"index"; + +static NSDictionary *_PlatformColorSelectorsDict() +{ + static NSDictionary *dict; + static dispatch_once_t once_token; + dispatch_once(&once_token, ^(void) { + NSMutableDictionary *map = [@{ + // https://developer.apple.com/documentation/appkit/nscolor/ui_element_colors + // Label Colors + @"labelColor": @{}, // 10_10 + @"secondaryLabelColor": @{}, // 10_10 + @"tertiaryLabelColor": @{}, // 10_10 + @"quaternaryLabelColor": @{}, // 10_10 + // Text Colors + @"textColor": @{}, + @"placeholderTextColor": @{}, // 10_10 + @"selectedTextColor": @{}, + @"textBackgroundColor": @{}, + @"selectedTextBackgroundColor": @{}, + @"keyboardFocusIndicatorColor": @{}, + @"unemphasizedSelectedTextColor": @{ // 10_14 + kFallbackKey: @"selectedTextColor" + }, + @"unemphasizedSelectedTextBackgroundColor": @{ // 10_14 + kFallbackKey: @"textBackgroundColor" + }, + // Content Colors + @"linkColor": @{}, // 10_10 + @"separatorColor": @{ // 10_14 + kFallbackKey: @"gridColor" + }, + @"selectedContentBackgroundColor": @{ // 10_14 + kFallbackKey: @"alternateSelectedControlColor" + }, + @"unemphasizedSelectedContentBackgroundColor": @{ // 10_14 + kFallbackKey: @"secondarySelectedControlColor" + }, + // Menu Colors + @"selectedMenuItemTextColor": @{}, + // Table Colors + @"gridColor": @{}, + @"headerTextColor": @{}, + @"alternatingEvenContentBackgroundColor": @{ // 10_14 + kSelectorKey: @"alternatingContentBackgroundColors", + kIndexKey: @0, + kFallbackKey: @"controlAlternatingRowBackgroundColors" + }, + @"alternatingOddContentBackgroundColor": @{ // 10_14 + kSelectorKey: @"alternatingContentBackgroundColors", + kIndexKey: @1, + kFallbackKey: @"controlAlternatingRowBackgroundColors" + }, + // Control Colors + @"controlAccentColor": @{ // 10_14 + kFallbackKey: @"controlColor" + }, + @"controlColor": @{}, + @"controlBackgroundColor": @{}, + @"controlTextColor": @{}, + @"disabledControlTextColor": @{}, + @"selectedControlColor": @{}, + @"selectedControlTextColor": @{}, + @"alternateSelectedControlTextColor": @{}, + @"scrubberTexturedBackgroundColor": @{}, // 10_12_2 + // Window Colors + @"windowBackgroundColor": @{}, + @"windowFrameTextColor": @{}, + @"underPageBackgroundColor": @{}, // 10_8 + // Highlights and Shadows + @"findHighlightColor": @{ // 10_13 + kFallbackKey: @"highlightColor" + }, + @"highlightColor": @{}, + @"shadowColor": @{}, + // https://developer.apple.com/documentation/appkit/nscolor/standard_colors + // Standard Colors + @"systemBlueColor": @{}, // 10_10 + @"systemBrownColor": @{}, // 10_10 + @"systemGrayColor": @{}, // 10_10 + @"systemGreenColor": @{}, // 10_10 + @"systemOrangeColor": @{}, // 10_10 + @"systemPinkColor": @{}, // 10_10 + @"systemPurpleColor": @{}, // 10_10 + @"systemRedColor": @{}, // 10_10 + @"systemYellowColor": @{}, // 10_10 + // Transparent Color + @"clearColor" : @{}, + } mutableCopy]; + + // Create aliases for Swift-style names (without "Color" suffix) + NSMutableDictionary *aliases = [NSMutableDictionary new]; + for (NSString *objcSelector in map) { + NSMutableDictionary *entry = [map[objcSelector] mutableCopy]; + if ([entry objectForKey:kSelectorKey] == nil) { + entry[kSelectorKey] = objcSelector; + } + if ([objcSelector hasSuffix:kColorSuffix]) { + NSString *swiftSelector = [objcSelector substringToIndex:[objcSelector length] - [kColorSuffix length]]; + aliases[swiftSelector] = entry; + } + } + [map addEntriesFromDictionary:aliases]; + + dict = [map copy]; + }); + return dict; +} + +static RCTUIColor *_UIColorFromHexValue(NSNumber *hexValue) +{ + NSUInteger hexIntValue = [hexValue unsignedIntegerValue]; + + CGFloat red = ((CGFloat)((hexIntValue & 0xFF000000) >> 24)) / 255.0; + CGFloat green = ((CGFloat)((hexIntValue & 0xFF0000) >> 16)) / 255.0; + CGFloat blue = ((CGFloat)((hexIntValue & 0xFF00) >> 8)) / 255.0; + CGFloat alpha = ((CGFloat)(hexIntValue & 0xFF)) / 255.0; + + return [RCTUIColor colorWithRed:red green:green blue:blue alpha:alpha]; +} + +static RCTUIColor *_Nullable _UIColorFromSemanticString(NSString *semanticString) +{ + NSString *platformColorString = [semanticString hasSuffix:kColorSuffix] + ? [semanticString substringToIndex:[semanticString length] - [kColorSuffix length]] + : semanticString; + NSDictionary *platformColorSelectorsDict = _PlatformColorSelectorsDict(); + NSDictionary *colorInfo = platformColorSelectorsDict[platformColorString]; + if (colorInfo) { + // Get the selector name, defaulting to the platform color string + NSString *selectorName = colorInfo[kSelectorKey]; + if (selectorName == nil) { + selectorName = [platformColorString stringByAppendingString:kColorSuffix]; + } + + SEL objcColorSelector = NSSelectorFromString(selectorName); + if (![RCTUIColor respondsToSelector:objcColorSelector]) { + // Try fallback ARGB value + NSNumber *fallbackRGB = colorInfo[kFallbackARGBKey]; + if (fallbackRGB) { + return _UIColorFromHexValue(fallbackRGB); + } + // Try fallback color name + NSString *fallbackColorName = colorInfo[kFallbackKey]; + if (fallbackColorName) { + return _UIColorFromSemanticString(fallbackColorName); + } + } else { + Class colorClass = [RCTUIColor class]; + IMP imp = [colorClass methodForSelector:objcColorSelector]; + id (*getColor)(id, SEL) = ((id(*)(id, SEL))imp); + id colorObject = getColor(colorClass, objcColorSelector); + + // Handle array results (like alternatingContentBackgroundColors) + if ([colorObject isKindOfClass:[NSArray class]]) { + NSNumber *index = colorInfo[kIndexKey]; + if (index != nil) { + NSArray *colors = colorObject; + NSUInteger idx = [index unsignedIntegerValue]; + if (idx < colors.count) { + colorObject = colors[idx]; + } + } + } + + if ([colorObject isKindOfClass:[RCTUIColor class]]) { + return colorObject; + } + } + } + return nil; +} + +static inline NSString *_NSStringFromCString( + const std::string &string, + const NSStringEncoding &encoding = NSUTF8StringEncoding) +{ + return [NSString stringWithCString:string.c_str() encoding:encoding]; +} + +static inline facebook::react::ColorComponents _ColorComponentsFromUIColor(RCTUIColor *color) +{ + CGFloat rgba[4]; + color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; + [color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]]; + return {(float)rgba[0], (float)rgba[1], (float)rgba[2], (float)rgba[3]}; +} + +facebook::react::ColorComponents RCTPlatformColorComponentsFromSemanticItems(std::vector &semanticItems) +{ + return _ColorComponentsFromUIColor(RCTPlatformColorFromSemanticItems(semanticItems)); +} + +RCTUIColor *RCTPlatformColorFromSemanticItems(std::vector &semanticItems) +{ + for (const auto &semanticCString : semanticItems) { + NSString *semanticNSString = _NSStringFromCString(semanticCString); + RCTUIColor *uiColor = [RCTUIColor colorNamed:semanticNSString]; + if (uiColor != nil) { + return uiColor; + } + uiColor = _UIColorFromSemanticString(semanticNSString); + if (uiColor != nil) { + return uiColor; + } + } + + return RCTUIColor.clearColor; +} + +RCTUIColor *RCTPlatformColorFromColor(const facebook::react::Color &color) +{ + return (RCTUIColor *)facebook::react::unwrapManagedObject(color.getUIColor()); +} + +NS_ASSUME_NONNULL_END From a6cbf7c1db27202e244c32cd55dba35a37f5d2f7 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Mon, 3 Nov 2025 14:06:28 -0800 Subject: [PATCH 6/8] Make back into iOS idfefs --- .../renderer/graphics/React-graphics.podspec | 11 +- .../renderer/graphics/HostPlatformColor.h | 10 + .../renderer/graphics/HostPlatformColor.mm | 42 +++ .../renderer/graphics/PlatformColorParser.mm | 18 ++ .../graphics/RCTPlatformColorUtils.mm | 154 ++++++++++- .../renderer/graphics/HostPlatformColor.mm | 52 ---- .../renderer/graphics/PlatformColorParser.mm | 98 ------- .../graphics/RCTPlatformColorUtils.mm | 240 ------------------ packages/rn-tester/Podfile.lock | 130 +++++----- 9 files changed, 288 insertions(+), 467 deletions(-) delete mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm delete mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm delete mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec index 3545621bb4ede5..79bdf60824f295 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec +++ b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec @@ -24,10 +24,7 @@ boost_config = get_boost_config() boost_compiler_flags = boost_config[:compiler_flags] Pod::Spec.new do |s| - # [macOS Use platform specific sources - ios_source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}" - macos_source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}", "platform/macos/**/*.{m,mm,cpp,h}" - # macOS] + source_files = ["*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}"] header_search_paths = [ "\"$(PODS_ROOT)/boost\"", "\"$(PODS_TARGET_SRCROOT)/../../../\"", @@ -46,11 +43,7 @@ Pod::Spec.new do |s| s.platforms = min_supported_versions s.source = source s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags - # [macOS Use platform specific sources - s.ios.source_files = ios_source_files - s.visionos.source_files = ios_source_files - s.osx.source_files = macos_source_files - # macOS] + s.source = source s.header_dir = "react/renderer/graphics" # [macOS Restrict UIKit to iOS and visionOS s.ios.framework = "UIKit" diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h index 8d47debe9920d3..a534bd9afeddab 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h @@ -20,9 +20,19 @@ struct DynamicColor { int32_t highContrastDarkColor = 0; }; +#if TARGET_OS_OSX // [macOS +struct ColorWithSystemEffect { + int32_t color = 0; + std::string effect; +}; +#endif // macOS] + struct Color { Color(int32_t color); Color(const DynamicColor& dynamicColor); +#if TARGET_OS_OSX // [macOS + Color(const ColorWithSystemEffect& colorWithSystemEffect); +#endif // macOS] Color(const ColorComponents& components); Color() : uiColor_(nullptr){}; int32_t getColor() const; diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm index 069af91004855f..6b3108105ccaa0 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm @@ -20,6 +20,33 @@ namespace facebook::react { +#if TARGET_OS_OSX // [macOS +RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( + RCTUIColor *baseColor, + const std::string &systemEffectString) +{ + if (baseColor == nil) { + return nil; + } + + NSColor *colorWithEffect = baseColor; + if (!systemEffectString.empty()) { + if (systemEffectString == "none") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectNone]; + } else if (systemEffectString == "pressed") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectPressed]; + } else if (systemEffectString == "deepPressed") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDeepPressed]; + } else if (systemEffectString == "disabled") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDisabled]; + } else if (systemEffectString == "rollover") { + colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectRollover]; + } + } + return colorWithEffect; +} +#endif // macOS] + namespace { bool UIColorIsP3ColorSpace(const std::shared_ptr &uiColor) @@ -224,6 +251,21 @@ int32_t hashFromUIColor(const std::shared_ptr &uiColor) 0); } +#if TARGET_OS_OSX // [macOS +Color::Color(const ColorWithSystemEffect &colorWithSystemEffect) +{ + RCTUIColor *baseColor = UIColorFromInt32(colorWithSystemEffect.color); + RCTUIColor *colorWithEffect = + UIColorFromColorWithSystemEffect(baseColor, colorWithSystemEffect.effect); + if (colorWithEffect != nil) { + uiColor_ = wrapManagedObject(colorWithEffect); + } + uiColorHashValue_ = facebook::react::hash_combine( + colorWithSystemEffect.color, + std::hash{}(colorWithSystemEffect.effect)); +} +#endif // macOS + Color::Color(const ColorComponents &components) { uiColor_ = wrapManagedObject(UIColorFromComponentsColor(components)); diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm index 7cb04798066724..859bc9e291ecc3 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.mm @@ -62,6 +62,24 @@ SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t items.at("dynamic").hasType>()) { auto dynamicItems = (std::unordered_map)items.at("dynamic"); return RCTPlatformColorComponentsFromDynamicItems(contextContainer, surfaceId, dynamicItems); +#if TARGET_OS_OSX // [macOS + } else if ( + items.find("colorWithSystemEffect") != items.end() && + items.at("colorWithSystemEffect").hasType>()) { + auto colorWithSystemEffectItems = + (std::unordered_map)items.at("colorWithSystemEffect"); + if (colorWithSystemEffectItems.find("baseColor") != colorWithSystemEffectItems.end() && + colorWithSystemEffectItems.find("systemEffect") != colorWithSystemEffectItems.end() && + colorWithSystemEffectItems.at("systemEffect").hasType()) { + SharedColor baseColorShared{}; + fromRawValue(contextContainer, surfaceId, colorWithSystemEffectItems.at("baseColor"), baseColorShared); + if (baseColorShared) { + std::string systemEffect = (std::string)colorWithSystemEffectItems.at("systemEffect"); + auto baseColor = (*baseColorShared).getColor(); + return SharedColor(Color(ColorWithSystemEffect{baseColor, systemEffect})); + } + } +#endif // macOS] } } diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm index 403fa049ce75b0..bcadb5d594649d 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm @@ -8,22 +8,33 @@ #import "RCTPlatformColorUtils.h" #import +#import #import // [macOS] +#if TARGET_OS_OSX // [macOS +#import +#endif // macOS] #import #import #include +#include NS_ASSUME_NONNULL_BEGIN static NSString *const kColorSuffix = @"Color"; static NSString *const kFallbackARGBKey = @"fallback-argb"; +#if TARGET_OS_OSX // [macOS +static NSString *const kFallbackKey = @"fallback"; +static NSString *const kSelectorKey = @"selector"; +static NSString *const kIndexKey = @"index"; +#endif // macOS] static NSDictionary *_PlatformColorSelectorsDict() { static NSDictionary *dict; static dispatch_once_t once_token; dispatch_once(&once_token, ^(void) { +#if !TARGET_OS_OSX // [macOS] dict = @{ // https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors // Label Colors @@ -130,6 +141,105 @@ kFallbackARGBKey : @(0x00000000) // iOS 13.0 }, }; +#else // [macOS + NSMutableDictionary *map = [@{ + // https://developer.apple.com/documentation/appkit/nscolor/ui_element_colors + // Label Colors + @"labelColor": @{}, + @"secondaryLabelColor": @{}, + @"tertiaryLabelColor": @{}, + @"quaternaryLabelColor": @{}, + // Text Colors + @"textColor": @{}, + @"placeholderTextColor": @{}, + @"selectedTextColor": @{}, + @"textBackgroundColor": @{}, + @"selectedTextBackgroundColor": @{}, + @"keyboardFocusIndicatorColor": @{}, + @"unemphasizedSelectedTextColor": @{ + kFallbackKey: @"selectedTextColor" + }, + @"unemphasizedSelectedTextBackgroundColor": @{ + kFallbackKey: @"textBackgroundColor" + }, + // Content Colors + @"linkColor": @{}, + @"separatorColor": @{ + kFallbackKey: @"gridColor" + }, + @"selectedContentBackgroundColor": @{ + kFallbackKey: @"alternateSelectedControlColor" + }, + @"unemphasizedSelectedContentBackgroundColor": @{ + kFallbackKey: @"secondarySelectedControlColor" + }, + // Menu Colors + @"selectedMenuItemTextColor": @{}, + // Table Colors + @"gridColor": @{}, + @"headerTextColor": @{}, + @"alternatingEvenContentBackgroundColor": @{ + kSelectorKey: @"alternatingContentBackgroundColors", + kIndexKey: @0, + kFallbackKey: @"controlAlternatingRowBackgroundColors" + }, + @"alternatingOddContentBackgroundColor": @{ + kSelectorKey: @"alternatingContentBackgroundColors", + kIndexKey: @1, + kFallbackKey: @"controlAlternatingRowBackgroundColors" + }, + // Control Colors + @"controlAccentColor": @{ + kFallbackKey: @"controlColor" + }, + @"controlColor": @{}, + @"controlBackgroundColor": @{}, + @"controlTextColor": @{}, + @"disabledControlTextColor": @{}, + @"selectedControlColor": @{}, + @"selectedControlTextColor": @{}, + @"alternateSelectedControlTextColor": @{}, + @"scrubberTexturedBackgroundColor": @{}, + // Window Colors + @"windowBackgroundColor": @{}, + @"windowFrameTextColor": @{}, + @"underPageBackgroundColor": @{}, + // Highlights and Shadows + @"findHighlightColor": @{ + kFallbackKey: @"highlightColor" + }, + @"highlightColor": @{}, + @"shadowColor": @{}, + // https://developer.apple.com/documentation/appkit/nscolor/standard_colors + // Standard Colors + @"systemBlueColor": @{}, + @"systemBrownColor": @{}, + @"systemGrayColor": @{}, + @"systemGreenColor": @{}, + @"systemOrangeColor": @{}, + @"systemPinkColor": @{}, + @"systemPurpleColor": @{}, + @"systemRedColor": @{}, + @"systemYellowColor": @{}, + // Transparent Color + @"clearColor" : @{}, + } mutableCopy]; + + NSMutableDictionary *aliases = [NSMutableDictionary new]; + for (NSString *objcSelector in map) { + NSMutableDictionary *entry = [map[objcSelector] mutableCopy]; + if ([entry objectForKey:kSelectorKey] == nil) { + entry[kSelectorKey] = objcSelector; + } + if ([objcSelector hasSuffix:kColorSuffix]) { + NSString *swiftSelector = [objcSelector substringToIndex:[objcSelector length] - [kColorSuffix length]]; + aliases[swiftSelector] = entry; + } + } + [map addEntriesFromDictionary:aliases]; + + dict = [map copy]; +#endif // macOS] }); return dict; } @@ -154,21 +264,59 @@ NSDictionary *platformColorSelectorsDict = _PlatformColorSelectorsDict(); NSDictionary *colorInfo = platformColorSelectorsDict[platformColorString]; if (colorInfo) { +#if !TARGET_OS_OSX // [macOS] SEL objcColorSelector = NSSelectorFromString([platformColorString stringByAppendingString:kColorSuffix]); - if (![RCTUIColor respondsToSelector:objcColorSelector]) { // [macOS] + if (![RCTUIColor respondsToSelector:objcColorSelector]) { NSNumber *fallbackRGB = colorInfo[kFallbackARGBKey]; if (fallbackRGB) { return _UIColorFromHexValue(fallbackRGB); } } else { - Class uiColorClass = [RCTUIColor class]; // [macOS] + Class uiColorClass = [RCTUIColor class]; IMP imp = [uiColorClass methodForSelector:objcColorSelector]; id (*getUIColor)(id, SEL) = ((id(*)(id, SEL))imp); id colorObject = getUIColor(uiColorClass, objcColorSelector); - if ([colorObject isKindOfClass:[RCTUIColor class]]) { // [macOS] + if ([colorObject isKindOfClass:[RCTUIColor class]]) { + return colorObject; + } + } +#else // [macOS + NSString *selectorName = colorInfo[kSelectorKey]; + if (selectorName == nil) { + selectorName = [platformColorString stringByAppendingString:kColorSuffix]; + } + + SEL objcColorSelector = NSSelectorFromString(selectorName); + if (![RCTUIColor respondsToSelector:objcColorSelector]) { + NSNumber *fallbackRGB = colorInfo[kFallbackARGBKey]; + if (fallbackRGB) { + return _UIColorFromHexValue(fallbackRGB); + } + NSString *fallbackColorName = colorInfo[kFallbackKey]; + if (fallbackColorName) { + return _UIColorFromSemanticString(fallbackColorName); + } + } else { + Class colorClass = [RCTUIColor class]; + IMP imp = [colorClass methodForSelector:objcColorSelector]; + id (*getColor)(id, SEL) = ((id(*)(id, SEL))imp); + id colorObject = getColor(colorClass, objcColorSelector); + if ([colorObject isKindOfClass:[NSArray class]]) { + NSNumber *index = colorInfo[kIndexKey]; + if (index != nil) { + NSArray *colors = colorObject; + NSUInteger idx = [index unsignedIntegerValue]; + if (idx < colors.count) { + colorObject = colors[idx]; + } + } + } + + if ([colorObject isKindOfClass:[RCTUIColor class]]) { return colorObject; } } +#endif } return nil; } diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm deleted file mode 100644 index 2b933bf76aa5f1..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.mm +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// [macOS] - -#import "HostPlatformColor.h" - -#import -#import -#import -#import -#import -#import - -using namespace facebook::react; - -NS_ASSUME_NONNULL_BEGIN - -namespace facebook::react { - -RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( - RCTUIColor *baseColor, - const std::string &systemEffectString) -{ - if (baseColor == nil) { - return nil; - } - - NSColor *colorWithEffect = baseColor; - if (!systemEffectString.empty()) { - if (systemEffectString == "none") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectNone]; - } else if (systemEffectString == "pressed") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectPressed]; - } else if (systemEffectString == "deepPressed") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDeepPressed]; - } else if (systemEffectString == "disabled") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectDisabled]; - } else if (systemEffectString == "rollover") { - colorWithEffect = [baseColor colorWithSystemEffect:NSColorSystemEffectRollover]; - } - } - return colorWithEffect; -} - -} // namespace facebook::react - -NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm deleted file mode 100644 index 63d4ceedf3459d..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.mm +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// [macOS] - -#import "PlatformColorParser.h" - -#import -#import -#import -#import -#import -#import - -using namespace facebook::react; - -NS_ASSUME_NONNULL_BEGIN - -// Forward declaration for ColorWithSystemEffect helper -RCTUIColor *_Nullable UIColorFromColorWithSystemEffect( - RCTUIColor *baseColor, - const std::string &systemEffectString); - -namespace facebook::react { - -inline facebook::react::SharedColor RCTPlatformColorComponentsFromDynamicItems( - const facebook::react::ContextContainer &contextContainer, - int32_t surfaceId, - std::unordered_map &dynamicItems) -{ - SharedColor lightSharedColor{}; - SharedColor darkSharedColor{}; - SharedColor highContrastLightSharedColor{}; - SharedColor highContrastDarkSharedColor{}; - if (dynamicItems.count("light")) { - fromRawValue(contextContainer, surfaceId, dynamicItems.at("light"), lightSharedColor); - } - if (dynamicItems.count("dark")) { - fromRawValue(contextContainer, surfaceId, dynamicItems.at("dark"), darkSharedColor); - } - if (dynamicItems.count("highContrastLight")) { - fromRawValue(contextContainer, surfaceId, dynamicItems.at("highContrastLight"), highContrastLightSharedColor); - } - if (dynamicItems.count("highContrastDark")) { - fromRawValue(contextContainer, surfaceId, dynamicItems.at("highContrastDark"), highContrastDarkSharedColor); - } - - Color color = Color(DynamicColor{ - (*lightSharedColor).getColor(), - (*darkSharedColor).getColor(), - (*highContrastLightSharedColor).getColor(), - (*highContrastDarkSharedColor).getColor()}); - return SharedColor(color); -} - -SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t surfaceId, const RawValue &value) -{ - if (value.hasType>()) { - auto items = (std::unordered_map)value; - if (items.find("semantic") != items.end() && items.at("semantic").hasType>()) { - auto semanticItems = (std::vector)items.at("semantic"); - return SharedColor(Color::createSemanticColor(semanticItems)); - } else if ( - items.find("dynamic") != items.end() && - items.at("dynamic").hasType>()) { - auto dynamicItems = (std::unordered_map)items.at("dynamic"); - return RCTPlatformColorComponentsFromDynamicItems(contextContainer, surfaceId, dynamicItems); - } else if ( - items.find("colorWithSystemEffect") != items.end() && - items.at("colorWithSystemEffect").hasType>()) { - auto colorWithSystemEffectItems = (std::unordered_map)items.at("colorWithSystemEffect"); - if (colorWithSystemEffectItems.find("baseColor") != colorWithSystemEffectItems.end() && - colorWithSystemEffectItems.find("systemEffect") != colorWithSystemEffectItems.end() && - colorWithSystemEffectItems.at("systemEffect").hasType()) { - SharedColor baseColorShared{}; - fromRawValue(contextContainer, surfaceId, colorWithSystemEffectItems.at("baseColor"), baseColorShared); - if (baseColorShared) { - RCTUIColor *baseColor = RCTPlatformColorFromColor(*baseColorShared); - std::string systemEffect = (std::string)colorWithSystemEffectItems.at("systemEffect"); - RCTUIColor *colorWithEffect = UIColorFromColorWithSystemEffect(baseColor, systemEffect); - if (colorWithEffect != nil) { - return SharedColor(Color(wrapManagedObject(colorWithEffect))); - } - } - } - } - } - - return clearColor(); -} - -} // namespace facebook::react - -NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm deleted file mode 100644 index 574881d038fa7f..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/RCTPlatformColorUtils.mm +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// [macOS] - -#import "RCTPlatformColorUtils.h" - -#import -#import -#import -#import - -#include - -NS_ASSUME_NONNULL_BEGIN - -static NSString *const kColorSuffix = @"Color"; -static NSString *const kFallbackARGBKey = @"fallback-argb"; -static NSString *const kFallbackKey = @"fallback"; -static NSString *const kSelectorKey = @"selector"; -static NSString *const kIndexKey = @"index"; - -static NSDictionary *_PlatformColorSelectorsDict() -{ - static NSDictionary *dict; - static dispatch_once_t once_token; - dispatch_once(&once_token, ^(void) { - NSMutableDictionary *map = [@{ - // https://developer.apple.com/documentation/appkit/nscolor/ui_element_colors - // Label Colors - @"labelColor": @{}, // 10_10 - @"secondaryLabelColor": @{}, // 10_10 - @"tertiaryLabelColor": @{}, // 10_10 - @"quaternaryLabelColor": @{}, // 10_10 - // Text Colors - @"textColor": @{}, - @"placeholderTextColor": @{}, // 10_10 - @"selectedTextColor": @{}, - @"textBackgroundColor": @{}, - @"selectedTextBackgroundColor": @{}, - @"keyboardFocusIndicatorColor": @{}, - @"unemphasizedSelectedTextColor": @{ // 10_14 - kFallbackKey: @"selectedTextColor" - }, - @"unemphasizedSelectedTextBackgroundColor": @{ // 10_14 - kFallbackKey: @"textBackgroundColor" - }, - // Content Colors - @"linkColor": @{}, // 10_10 - @"separatorColor": @{ // 10_14 - kFallbackKey: @"gridColor" - }, - @"selectedContentBackgroundColor": @{ // 10_14 - kFallbackKey: @"alternateSelectedControlColor" - }, - @"unemphasizedSelectedContentBackgroundColor": @{ // 10_14 - kFallbackKey: @"secondarySelectedControlColor" - }, - // Menu Colors - @"selectedMenuItemTextColor": @{}, - // Table Colors - @"gridColor": @{}, - @"headerTextColor": @{}, - @"alternatingEvenContentBackgroundColor": @{ // 10_14 - kSelectorKey: @"alternatingContentBackgroundColors", - kIndexKey: @0, - kFallbackKey: @"controlAlternatingRowBackgroundColors" - }, - @"alternatingOddContentBackgroundColor": @{ // 10_14 - kSelectorKey: @"alternatingContentBackgroundColors", - kIndexKey: @1, - kFallbackKey: @"controlAlternatingRowBackgroundColors" - }, - // Control Colors - @"controlAccentColor": @{ // 10_14 - kFallbackKey: @"controlColor" - }, - @"controlColor": @{}, - @"controlBackgroundColor": @{}, - @"controlTextColor": @{}, - @"disabledControlTextColor": @{}, - @"selectedControlColor": @{}, - @"selectedControlTextColor": @{}, - @"alternateSelectedControlTextColor": @{}, - @"scrubberTexturedBackgroundColor": @{}, // 10_12_2 - // Window Colors - @"windowBackgroundColor": @{}, - @"windowFrameTextColor": @{}, - @"underPageBackgroundColor": @{}, // 10_8 - // Highlights and Shadows - @"findHighlightColor": @{ // 10_13 - kFallbackKey: @"highlightColor" - }, - @"highlightColor": @{}, - @"shadowColor": @{}, - // https://developer.apple.com/documentation/appkit/nscolor/standard_colors - // Standard Colors - @"systemBlueColor": @{}, // 10_10 - @"systemBrownColor": @{}, // 10_10 - @"systemGrayColor": @{}, // 10_10 - @"systemGreenColor": @{}, // 10_10 - @"systemOrangeColor": @{}, // 10_10 - @"systemPinkColor": @{}, // 10_10 - @"systemPurpleColor": @{}, // 10_10 - @"systemRedColor": @{}, // 10_10 - @"systemYellowColor": @{}, // 10_10 - // Transparent Color - @"clearColor" : @{}, - } mutableCopy]; - - // Create aliases for Swift-style names (without "Color" suffix) - NSMutableDictionary *aliases = [NSMutableDictionary new]; - for (NSString *objcSelector in map) { - NSMutableDictionary *entry = [map[objcSelector] mutableCopy]; - if ([entry objectForKey:kSelectorKey] == nil) { - entry[kSelectorKey] = objcSelector; - } - if ([objcSelector hasSuffix:kColorSuffix]) { - NSString *swiftSelector = [objcSelector substringToIndex:[objcSelector length] - [kColorSuffix length]]; - aliases[swiftSelector] = entry; - } - } - [map addEntriesFromDictionary:aliases]; - - dict = [map copy]; - }); - return dict; -} - -static RCTUIColor *_UIColorFromHexValue(NSNumber *hexValue) -{ - NSUInteger hexIntValue = [hexValue unsignedIntegerValue]; - - CGFloat red = ((CGFloat)((hexIntValue & 0xFF000000) >> 24)) / 255.0; - CGFloat green = ((CGFloat)((hexIntValue & 0xFF0000) >> 16)) / 255.0; - CGFloat blue = ((CGFloat)((hexIntValue & 0xFF00) >> 8)) / 255.0; - CGFloat alpha = ((CGFloat)(hexIntValue & 0xFF)) / 255.0; - - return [RCTUIColor colorWithRed:red green:green blue:blue alpha:alpha]; -} - -static RCTUIColor *_Nullable _UIColorFromSemanticString(NSString *semanticString) -{ - NSString *platformColorString = [semanticString hasSuffix:kColorSuffix] - ? [semanticString substringToIndex:[semanticString length] - [kColorSuffix length]] - : semanticString; - NSDictionary *platformColorSelectorsDict = _PlatformColorSelectorsDict(); - NSDictionary *colorInfo = platformColorSelectorsDict[platformColorString]; - if (colorInfo) { - // Get the selector name, defaulting to the platform color string - NSString *selectorName = colorInfo[kSelectorKey]; - if (selectorName == nil) { - selectorName = [platformColorString stringByAppendingString:kColorSuffix]; - } - - SEL objcColorSelector = NSSelectorFromString(selectorName); - if (![RCTUIColor respondsToSelector:objcColorSelector]) { - // Try fallback ARGB value - NSNumber *fallbackRGB = colorInfo[kFallbackARGBKey]; - if (fallbackRGB) { - return _UIColorFromHexValue(fallbackRGB); - } - // Try fallback color name - NSString *fallbackColorName = colorInfo[kFallbackKey]; - if (fallbackColorName) { - return _UIColorFromSemanticString(fallbackColorName); - } - } else { - Class colorClass = [RCTUIColor class]; - IMP imp = [colorClass methodForSelector:objcColorSelector]; - id (*getColor)(id, SEL) = ((id(*)(id, SEL))imp); - id colorObject = getColor(colorClass, objcColorSelector); - - // Handle array results (like alternatingContentBackgroundColors) - if ([colorObject isKindOfClass:[NSArray class]]) { - NSNumber *index = colorInfo[kIndexKey]; - if (index != nil) { - NSArray *colors = colorObject; - NSUInteger idx = [index unsignedIntegerValue]; - if (idx < colors.count) { - colorObject = colors[idx]; - } - } - } - - if ([colorObject isKindOfClass:[RCTUIColor class]]) { - return colorObject; - } - } - } - return nil; -} - -static inline NSString *_NSStringFromCString( - const std::string &string, - const NSStringEncoding &encoding = NSUTF8StringEncoding) -{ - return [NSString stringWithCString:string.c_str() encoding:encoding]; -} - -static inline facebook::react::ColorComponents _ColorComponentsFromUIColor(RCTUIColor *color) -{ - CGFloat rgba[4]; - color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; - [color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]]; - return {(float)rgba[0], (float)rgba[1], (float)rgba[2], (float)rgba[3]}; -} - -facebook::react::ColorComponents RCTPlatformColorComponentsFromSemanticItems(std::vector &semanticItems) -{ - return _ColorComponentsFromUIColor(RCTPlatformColorFromSemanticItems(semanticItems)); -} - -RCTUIColor *RCTPlatformColorFromSemanticItems(std::vector &semanticItems) -{ - for (const auto &semanticCString : semanticItems) { - NSString *semanticNSString = _NSStringFromCString(semanticCString); - RCTUIColor *uiColor = [RCTUIColor colorNamed:semanticNSString]; - if (uiColor != nil) { - return uiColor; - } - uiColor = _UIColorFromSemanticString(semanticNSString); - if (uiColor != nil) { - return uiColor; - } - } - - return RCTUIColor.clearColor; -} - -RCTUIColor *RCTPlatformColorFromColor(const facebook::react::Color &color) -{ - return (RCTUIColor *)facebook::react::unwrapManagedObject(color.getUIColor()); -} - -NS_ASSUME_NONNULL_END diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 751b2a749f4820..ce54c1fd881d17 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -2053,82 +2053,82 @@ SPEC CHECKSUMS: boost: cea1d4f90a3a59537f3deb03ff5656489d7133dd DoubleConversion: d31b1eb37f6d6f456530c4fd9124b857d6889cab fast_float: 5596a99716f77fe44b617183d4db34777538174d - FBLazyVector: c3d0c3eb45c5a3c5985c4cdbe037b1530a7eef2d + FBLazyVector: 6b596ca2c7f49fb2545fbc384fa68dabfef41071 fmt: 24e7591456deb60b4a77518f83d9a916ac84223f glog: 0b31c25149b9d350b2666c7d459229861a00ec07 - hermes-engine: 9b033746b84dd3782beba1ee78de2d8ce709e5e1 + hermes-engine: cc8feeacabc5b95002c368a555a173cddafb29c5 MyNativeView: 012965daf7594f221bfe8f48c3a6be88dc926ec7 NativeCxxModuleExample: d89bddc6be7c578088d4c441e1de365cca37d369 OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 OSSLibraryExample: d57a46a4520f0964e36b3ac349cb37404a469ae3 RCT-Folly: 957ce397c08be7a9a91bb9245e57e69fa5255ec5 RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf - RCTRequired: dcedfb7f34fb38066e52e1cab957c57ccd7db9ad - RCTTypeSafety: 2c91e5de653d7c3b23201e16d633bbe86e1a68b6 - React: af07878ea8559b32d8b065186c2928675788bd6e - React-callinvoker: 10b8534fbdbbf1c0c109aebfa03bdde4bdd98398 - React-Core: 73c734a1cb66fc59f69e4966c52586bddf85531f - React-CoreModules: 1e50e62facd501e3f81a69c3f279f6c2a0785e41 - React-cxxreact: dbe209231951c184f8fc785699aca4e4792beef8 - React-debug: 02e3133cf01637dffc89c62deae2c881c27486dc - React-defaultsnativemodule: bd35f550f11cbf5c6dc72e5abe8b4f7afa41d14c - React-domnativemodule: 349bffb2ccd4cdd058b623e4f6d69729d430a482 - React-Fabric: 5428224da0383007e2ad070289ad0f5e2e19fb36 - React-FabricComponents: 542e573dac1ce367ecf916167c2cb7bf84c64835 - React-FabricImage: 23799abf2c5f0bdce9ffb3bcc26dafe97bc6cdee - React-featureflags: 60c98ff6dea8def99600224c3f6f70dfc694a242 - React-featureflagsnativemodule: f2c6690d9b26b802613f7c42fdb1967f6506f47a - React-graphics: da87e874689b2b4154b68f7a4dfa4814f8b13290 - React-hermes: 434a2f81b1f0b827a60deb7ac187721523d39123 - React-idlecallbacksnativemodule: 4ae844826cc8a8805fa50bcd8ffb15d89bce53e3 - React-ImageManager: 8f9670e145e307b031c36db00fe18503afbef8ae - React-jserrorhandler: 734bc5d129478ab1f4aa601f05d63b60f636174a - React-jsi: d0915ece43c59ecdb8b64e4fb372a9c1ad45d23d - React-jsiexecutor: 2107bcf79b1345263f88c808b1c18e22741d02d1 - React-jsinspector: 326fb8dd123a835532a702e85b9b3e92a8a91ce7 - React-jsinspectortracing: 0da6865c91ffcb6074a7a918075f1e16af40b379 - React-jsitooling: c1391fe5eee3b55df9bbe238e8b1ad0da4802be9 - React-jsitracing: 2859fb1906371bb6a3ca037d05f25ffa9edb75d5 - React-logger: f22a76c45f743c1bb5d9d8fa8cfd7b0114dc4b35 - React-Mapbuffer: 49d322ddf11ffa8973463d484836d0c2b059b1ce - React-microtasksnativemodule: 1f39febc6ecea57b1d75ba88d77d081e2689b8a8 - React-NativeModulesApple: ff4068eae18729a5689b0ee67638245db9a20751 - React-oscompat: d5a3795b18b684c669546d619fe37daad9682b8f - React-perflogger: 65216186ecadcd7c1ae7d664163d51c0d87391db - React-performancetimeline: 31f83c222133d3eff1fb34fe5593bbfa44e20dd3 - React-RCTActionSheet: b8fa8dc5462eeb5d6bf07de5c6205748625df025 - React-RCTAnimation: 06aabab19321735d02619d56d370d66cd7dfa724 - React-RCTAppDelegate: 5e27b038a0de10535cc17ee5eb0f9fb5ea8f05ff - React-RCTBlob: e5a049f652a015b59a44313879539325274d1fc0 - React-RCTFabric: e012c85f94a07dd63f2bb98831bfc514ffb80814 - React-RCTFBReactNativeSpec: f3b0131b2f651ba4272f5f41ee508db7cca9a715 - React-RCTImage: 07f34ba290ef73e1c7905197365eb0424ae24979 - React-RCTLinking: 65a5cf6bb17d8b056719206e62adf00d1b587d19 - React-RCTNetwork: 754630d124eace3ecb7e8c5d79f4f98fa8be1f6c - React-RCTPushNotification: f688a11d989f643b9581b48b762fa2aaed36e8b0 - React-RCTRuntime: d05f4ca1afba2d3b0ab92cb538f9acc58737ac6e - React-RCTSettings: e47018e632656bfbd7298c2d1becc2dfa914309b - React-RCTTest: f16c68419017c74b94bb3a61b8541c0352603e4b - React-RCTText: 41bc42eb95f304f797a3cc6f2ec3618d25df0c75 - React-RCTVibration: 49c58ededff60875d03d519a9e1f36f9616eed1e - React-rendererconsistency: ce698aa83e253467df7f3de853eb9cf975ab833a - React-renderercss: 5956a051ae04e2bbb1550e30f01361fed05d7649 - React-rendererdebug: ea93c790b40731bd6fedab213a0bca8d48e82752 - React-rncore: dddfbb3e510df07ea24a3d31432a114856ffebb4 - React-RuntimeApple: 9f9013c5ac7675ada7c4ea74250e77c87c131c82 - React-RuntimeCore: 2644fe75ab6889bfa23f3e097ddf5b2ede9372bb - React-runtimeexecutor: 693ad2e64732b5bce44b6fcc90eabe494dfc595a - React-RuntimeHermes: 2a30129486526ac5d53334f48fbe38875964ef01 - React-runtimescheduler: 1338928f41e96f431a85c7bbc78a4994b11f21b5 - React-timing: eb7eb17a751191160f60b886f4d57afe06a99c06 - React-utils: 63603fc28423587c8e36241b854fafc8996bbb71 - ReactAppDependencyProvider: 83ef076ee1b1457ea3ab8beaecc79f953db5be41 + RCTRequired: 86454663b1f55cdfc2980680a4b9b13de0cc4456 + RCTTypeSafety: ee5d62b4ee072ba32e2d4c0873c6413d16d0b4cb + React: b6fc1cb53e664f2c27cc75366341e5b418ee2e49 + React-callinvoker: 23477a5610b58fcf7a5f1db7d977e4d4f9a0a400 + React-Core: fe203286dd64ba843f4a221ef66f104b15d34fb7 + React-CoreModules: f3eeb16a433097a98b6bd8b9648bc81e52fcf5b4 + React-cxxreact: b9d13953a0b8a5ffb709e5434bf0846b5d20a60a + React-debug: cfc0beb3e370197470e661c8d0401657c50325b2 + React-defaultsnativemodule: 530b3b0f29591336a24b8bda12ecfa44c83a97f5 + React-domnativemodule: dd20f2587c98ca49944a941303804cb04ea00ef1 + React-Fabric: 113827c98aaff119b701207b2bee5f44420dc6ab + React-FabricComponents: 51768d34f9424ce2ea5d53f7b419681f2bdef2a0 + React-FabricImage: 2aa1c6abbe79b577f0381eac7244afac369b22e1 + React-featureflags: 8093b8f883cbf09197d8b1b039410092dcebb2e2 + React-featureflagsnativemodule: fce7a79614691cc337d92bf44b076185330ba932 + React-graphics: bcbe511cb3eb2bd37b92ee4ad15e5ebe78f0e09f + React-hermes: c5268c141bab5beea5c0c4bb0e6fa8a793294b8e + React-idlecallbacksnativemodule: 9e115c69e226f801ce85e42880245fc861e0e623 + React-ImageManager: a506404bacf1012cff8dc8f0ebf90ba2df680c94 + React-jserrorhandler: e5c2092ac14ac550bfa30060450665c553b26015 + React-jsi: a345e35e965737f289f9f4b973f09e4a3dd8d251 + React-jsiexecutor: b3646b17e151be01692f95e3b2a6ccc5f9f26598 + React-jsinspector: 0018a6ff602ea39239fe5ed3a9bfe97c34f805ca + React-jsinspectortracing: dd6d59c31e0a5d1f738ba3e0dfed7e61f29d5769 + React-jsitooling: e53fdd6596d1584d15d17d6ec1ee487e6a4f06d9 + React-jsitracing: f024e2343bdffcad54b0299e8ae5a027744af7c6 + React-logger: 8a274f46dc9107cf9c196dd28f837e0240e1a5d5 + React-Mapbuffer: 7067d4a4aa7b1b52c666d2d72af34249026661ec + React-microtasksnativemodule: cd101d2088e70aa4ec7ed7ce23ee0a1c69cfd1e9 + React-NativeModulesApple: 136199c113d6a0a784db13d53012b4d34c011260 + React-oscompat: ecb86c20032e4644a0edfd5b08c75a95d4ebe7df + React-perflogger: 874c4b4e0d31dae437432aab912fa5f0324d0ec0 + React-performancetimeline: cc01a8a86676c79b0fe45b8c58682d878bde57d4 + React-RCTActionSheet: db65e1aeaa7a828b6206e2330612a59b048f8e3b + React-RCTAnimation: 77bda20d1924a778ce34bc6d8c60d5d434b4c566 + React-RCTAppDelegate: 45b0c98ddade65676866580a61d7d10a32f63b3c + React-RCTBlob: 1907c2689a86aa9a692042eda0c5d7dc9a694fee + React-RCTFabric: 66d5bec10e64226b5864a09327866fe9eceb78dc + React-RCTFBReactNativeSpec: 471a8973f63ec04de7905934e854d90c2c539189 + React-RCTImage: cb685bce002f773c83993883c2d7a7b0dc5e4544 + React-RCTLinking: 2f95ec76b65d2688d673a43635bac9d90d917fe2 + React-RCTNetwork: d070672f686c7890db411fad867e09267b2aa6d8 + React-RCTPushNotification: 3f7c4fc97ef6c565f4851210dda561dca587d9dd + React-RCTRuntime: 64c87802788da23b2be95cfc4dbe755880a9a426 + React-RCTSettings: f9558fa28dbdbe823918b208097afa22bcbdc2e1 + React-RCTTest: a570bdf7581d4c87410f439f10b327d35f4b75d7 + React-RCTText: d67e5a124eb5a87e3b17972f2db15ec3e3068532 + React-RCTVibration: 9b9afc8f5d5dc83618dac92c1dc0177c11a39360 + React-rendererconsistency: 7a8e35d98fe9378239b440dadca2c664d263780f + React-renderercss: 706025c5843bcf9f7afddaf0bce06d88415f11d7 + React-rendererdebug: b6b4d888fd4fd0903034ed255cf04411460ec71a + React-rncore: d6740152a48598905aa2b91a8f7f1fd5cb45d073 + React-RuntimeApple: bcdcd08c36dacfc50b43b3cd5154dec568fc731d + React-RuntimeCore: a84e2bb6c2653450c9e466d599ffee8dbf597fe2 + React-runtimeexecutor: 79b6e1563a8ca5e5365c72e9be8e1b29483bdb2e + React-RuntimeHermes: a663d4f6c966b16d9fa6046d64d9286fe304c855 + React-runtimescheduler: 7cdd43930d2ab8366218e6a9b21230c25997631f + React-timing: bdf2b83b8a55e2afa81b56b2a836fbbd6d83f849 + React-utils: ca724a99789bffde817f5a573f94ebdac07131b6 + ReactAppDependencyProvider: 28145a720a0d3433489292c283fff4edbf0ed0f8 ReactCodegen: 0082198e27eef7ce13bf03680eb9d15bbde56601 - ReactCommon: 4b3b727acbd08deb6d3c318a2925f25c1cfa3cf5 - ReactCommon-Samples: 4281d6886e7c27ec967a2a9392a3836edfc110ca + ReactCommon: e37fc2ac5ae6cd0667723db1f76a228fa51e7231 + ReactCommon-Samples: 28b90659781e683ac67549891e57eaf81f575496 ScreenshotManager: c96f07e207c96f5d91080e408aff95df63875dae SocketRocket: a1845ec01e17d55e3da5df40600892972afb45e1 - Yoga: deb1f9afd79094c9e76d19fa2e312428a74ba934 + Yoga: 3678fec373520a6e6af00f87826bcb109bae244e PODFILE CHECKSUM: 07eddbe098f0e50aff590a91207f692788a9fe4c From 95f540b4c809ff8a9463049830718a37a17cab40 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Mon, 3 Nov 2025 14:06:42 -0800 Subject: [PATCH 7/8] update RNTester example --- .../PlatformColor/PlatformColorExample.js | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js b/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js index 02857a83bd900d..d494aadd2d68d9 100644 --- a/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js +++ b/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js @@ -122,6 +122,100 @@ function PlatformColorsExample() { {label: 'clear', color: PlatformColor('clear')}, {label: 'customColor', color: PlatformColor('customColor')}, ]; + // [macOS + } else if (Platform.OS === 'macos') { + colors = [ + // https://developer.apple.com/documentation/appkit/nscolor + // Text Colors + {label: 'labelColor', color: PlatformColor('labelColor')}, + { + label: 'secondaryLabelColor', + color: PlatformColor('secondaryLabelColor'), + }, + { + label: 'tertiaryLabelColor', + color: PlatformColor('tertiaryLabelColor'), + }, + { + label: 'quaternaryLabelColor', + color: PlatformColor('quaternaryLabelColor'), + }, + {label: 'textColor', color: PlatformColor('textColor')}, + { + label: 'placeholderTextColor', + color: PlatformColor('placeholderTextColor'), + }, + { + label: 'selectedTextColor', + color: PlatformColor('selectedTextColor'), + }, + { + label: 'selectedTextBackgroundColor', + color: PlatformColor('selectedTextBackgroundColor'), + }, + // Window and Control Colors + { + label: 'windowBackgroundColor', + color: PlatformColor('windowBackgroundColor'), + }, + { + label: 'underPageBackgroundColor', + color: PlatformColor('underPageBackgroundColor'), + }, + { + label: 'controlBackgroundColor', + color: PlatformColor('controlBackgroundColor'), + }, + { + label: 'selectedControlColor', + color: PlatformColor('selectedControlColor'), + }, + { + label: 'keyboardFocusIndicatorColor', + color: PlatformColor('keyboardFocusIndicatorColor'), + }, + // System Colors + { + label: 'systemBlueColor', + color: PlatformColor('systemBlueColor'), + }, + { + label: 'systemBrownColor', + color: PlatformColor('systemBrownColor'), + }, + { + label: 'systemGreenColor', + color: PlatformColor('systemGreenColor'), + }, + { + label: 'systemOrangeColor', + color: PlatformColor('systemOrangeColor'), + }, + { + label: 'systemPinkColor', + color: PlatformColor('systemPinkColor'), + }, + { + label: 'systemPurpleColor', + color: PlatformColor('systemPurpleColor'), + }, + { + label: 'systemRedColor', + color: PlatformColor('systemRedColor'), + }, + { + label: 'systemYellowColor', + color: PlatformColor('systemYellowColor'), + }, + // Accents and Grays + { + label: 'controlAccentColor', + color: PlatformColor('controlAccentColor'), + }, + {label: 'separatorColor', color: PlatformColor('separatorColor')}, + {label: 'gridColor', color: PlatformColor('gridColor')}, + {label: 'windowFrameColor', color: PlatformColor('windowFrameColor')}, + ]; // macOS] } else if (Platform.OS === 'android') { colors = [ {label: '?attr/colorAccent', color: PlatformColor('?attr/colorAccent')}, From 616287486e9285bd6c506145f032c587d607b311 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Mon, 3 Nov 2025 14:16:39 -0800 Subject: [PATCH 8/8] Add more docs --- docsite/api/intro.md | 2 +- docsite/api/platform-color.md | 50 +++++++++++++++++++++++++++++++++++ docsite/sidebarsApi.ts | 1 + 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 docsite/api/platform-color.md diff --git a/docsite/api/intro.md b/docsite/api/intro.md index 06c07fd761812b..68454cec6d673e 100644 --- a/docsite/api/intro.md +++ b/docsite/api/intro.md @@ -7,4 +7,4 @@ slug: / Welcome to the React Native macOS API reference documentation. This section covers macOS-specific props and events that extend the standard React Native components. -Most of the additional functionality out of React Native macOS directly is in the form of additional props and callback events implemented on ``, to provide macOS and desktop specific behavior +Most of the additional functionality out of React Native macOS directly is in the form of additional props and callback events implemented on ``, to provide macOS and desktop specific behavior. We also have some additional APIs, like platform specific colors. diff --git a/docsite/api/platform-color.md b/docsite/api/platform-color.md new file mode 100644 index 00000000000000..486db9a419145a --- /dev/null +++ b/docsite/api/platform-color.md @@ -0,0 +1,50 @@ +--- +sidebar_label: 'Platform Colors' +sidebar_position: 2 +--- + +# Platform Colors + +React Native macOS extends the core `PlatformColor` API with helpers that map directly to AppKit system colors. These helpers make it easier to adopt macOS appearance and accessibility behaviors without writing native code. + +## `DynamicColorMacOS` + +`DynamicColorMacOS` creates a color that automatically adapts to light, dark, and high-contrast appearances on macOS. + +:::note +`DynamicColorIOS` works on macOS too, they are essentially equivalent +::: + +| Option | Description | +| -------------------- | --------------------------------------------------------------- | +| `light` | Color used in the standard light appearance. | +| `dark` | Color used in the standard dark appearance. | +| `highContrastLight` | Optional color for high-contrast light mode. Defaults to `light`.| +| `highContrastDark` | Optional color for high-contrast dark mode. Defaults to `dark`. | + +## `ColorWithSystemEffectMacOS` + +`ColorWithSystemEffectMacOS(color, effect)` wraps an existing color so AppKit can apply control state effects such as pressed, disabled, or rollover. + +| Parameter | Description | +| --------- | ----------- | +| `color` | A string produced by `PlatformColor`, `DynamicColorMacOS`, or a CSS color string. | +| `effect` | One of `none`, `pressed`, `deepPressed`, `disabled`, or `rollover`. | + +```javascript +import { + ColorWithSystemEffectMacOS, + DynamicColorMacOS, + PlatformColor, + StyleSheet, +} from 'react-native'; + +const styles = StyleSheet.create({ + buttonPressed: { + backgroundColor: ColorWithSystemEffectMacOS( + PlatformColor('controlColor'), + 'pressed', + ), + }, +}); +``` diff --git a/docsite/sidebarsApi.ts b/docsite/sidebarsApi.ts index aa2ca6fcd88871..df07cc406dd926 100644 --- a/docsite/sidebarsApi.ts +++ b/docsite/sidebarsApi.ts @@ -3,6 +3,7 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; const sidebars: SidebarsConfig = { apiSidebar: [ 'intro', + 'platform-color', 'view-props', 'view-events', ],