diff --git a/Libraries/StyleSheet/PlatformColorValueTypes.macos.js b/Libraries/StyleSheet/PlatformColorValueTypes.macos.js index 75f52deb457dfc..3e8a05f2222e07 100644 --- a/Libraries/StyleSheet/PlatformColorValueTypes.macos.js +++ b/Libraries/StyleSheet/PlatformColorValueTypes.macos.js @@ -19,12 +19,35 @@ export opaque type NativeColorValue = { light: ?(ColorValue | ProcessedColorValue), dark: ?(ColorValue | ProcessedColorValue), }, + colorWithSystemEffect?: { + baseColor: ?(ColorValue | ProcessedColorValue), + systemEffect: SystemEffectMacOSPrivate, + }, }; export const PlatformColor = (...names: Array): ColorValue => { return {semantic: names}; }; +export type SystemEffectMacOSPrivate = + | 'none' + | 'pressed' + | 'deepPressed' + | 'disabled' + | 'rollover'; + +export const ColorWithSystemEffectMacOSPrivate = ( + color: ColorValue, + effect: SystemEffectMacOSPrivate, +): ColorValue => { + return { + colorWithSystemEffect: { + baseColor: color, + systemEffect: effect, + }, + }; +}; + export type DynamicColorMacOSTuplePrivate = { light: ColorValue, dark: ColorValue, @@ -54,8 +77,20 @@ export const normalizeColorObject = ( }, }; return dynamicColor; + } else if ( + 'colorWithSystemEffect' in color && + color.colorWithSystemEffect != null + ) { + const processColor = require('./processColor'); + const colorWithSystemEffect = color.colorWithSystemEffect; + const colorObject: NativeColorValue = { + colorWithSystemEffect: { + baseColor: processColor(colorWithSystemEffect.baseColor), + systemEffect: colorWithSystemEffect.systemEffect, + }, + }; + return colorObject; } - return null; }; @@ -72,6 +107,19 @@ export const processColorObject = ( }, }; return dynamicColor; + } else if ( + 'colorWithSystemEffect' in color && + color.colorWithSystemEffect != null + ) { + const processColor = require('./processColor'); + const colorWithSystemEffect = color.colorWithSystemEffect; + const colorObject: NativeColorValue = { + colorWithSystemEffect: { + baseColor: processColor(colorWithSystemEffect.baseColor), + systemEffect: colorWithSystemEffect.systemEffect, + }, + }; + return colorObject; } return color; }; diff --git a/Libraries/StyleSheet/PlatformColorValueTypesMacOS.js b/Libraries/StyleSheet/PlatformColorValueTypesMacOS.js index 567205d2320088..5a665d9e99fa56 100644 --- a/Libraries/StyleSheet/PlatformColorValueTypesMacOS.js +++ b/Libraries/StyleSheet/PlatformColorValueTypesMacOS.js @@ -22,4 +22,20 @@ export const DynamicColorMacOS = ( ): ColorValue => { throw new Error('DynamicColorMacOS is not available on this platform.'); }; + +export type SystemEffectMacOS = + | 'none' + | 'pressed' + | 'deepPressed' + | 'disabled' + | 'rollover'; + +export const ColorWithSystemEffectMacOS = ( + color: ColorValue, + effect: SystemEffectMacOS, +): ColorValue => { + throw new Error( + 'ColorWithSystemEffectMacOS is not available on this platform.', + ); +}; // ]TODO(macOS ISS#2323203) diff --git a/Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js b/Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js index 613ed542aa1e5e..f66e7356951f77 100644 --- a/Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js +++ b/Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js @@ -11,7 +11,10 @@ 'use strict'; import type {ColorValue} from './StyleSheetTypes'; -import {DynamicColorMacOSPrivate} from './PlatformColorValueTypes'; +import { + DynamicColorMacOSPrivate, + ColorWithSystemEffectMacOSPrivate, +} from './PlatformColorValueTypes'; export type DynamicColorMacOSTuple = { light: ColorValue, @@ -23,4 +26,18 @@ export const DynamicColorMacOS = ( ): ColorValue => { return DynamicColorMacOSPrivate({light: tuple.light, dark: tuple.dark}); }; + +export type SystemEffectMacOS = + | 'none' + | 'pressed' + | 'deepPressed' + | 'disabled' + | 'rollover'; + +export const ColorWithSystemEffectMacOS = ( + color: ColorValue, + effect: SystemEffectMacOS, +): ColorValue => { + return ColorWithSystemEffectMacOSPrivate(color, effect); +}; // ]TODO(macOS ISS#2323203) diff --git a/RNTester/Podfile.lock b/RNTester/Podfile.lock index 66f45588305e1c..6eddf3da80b324 100644 --- a/RNTester/Podfile.lock +++ b/RNTester/Podfile.lock @@ -520,8 +520,8 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f DoubleConversion: 2b45d0f8e156a5b02354c8a4062de64d41ccb4e0 - FBLazyVector: 92d78d01de741fe34b2d751e55a037653358ac0c - FBReactNativeSpec: e8382054abb3fb8270af2bca565a9f0577830525 + FBLazyVector: 29fb6e7901d1f0a80f920b6f40e29b459e3ec4d1 + FBReactNativeSpec: 2abf54e37e2606a820a73b437b997605c563c2ff Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365 Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3 @@ -534,34 +534,34 @@ SPEC CHECKSUMS: libevent: 59938c595b8c19e50c83250628ffed9ebf662183 OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 RCT-Folly: 55d0039b24e192081ec0b2257f7bd9f42e382fb7 - RCTRequired: 12daee8719711b00cac01ab3f90678356431596e - RCTTypeSafety: a4fd9c36901830973a05d074afc75a5147b3e6f2 - React: 7cf7caa74c0c289d292ae2b2022a259e83b1c4c3 - React-ART: d50f359f8ba778f8d184cd4b7d5bade4bd3aad81 - React-callinvoker: 366e5648b012f7b02e1577d6c3d021763a10c9cc - React-Core: 712fe9e8aedce8c8f27d46f171a899487617403f - React-CoreModules: 75fc59024dea0708b2da5415298f491881de74e7 - React-cxxreact: 1935fb10e2eecdcea1b225b6679e329b00889611 - React-jsi: f7c5b9f6ed6bcc2b3ee6aa7a791d317ccbb8313f - React-jsiexecutor: cea9a058f0fcb1b8d4c1fad3fc3bb5088c2979bd - React-jsinspector: 6b83e9193f44d73358302e53a913e932c385cfa7 - React-RCTActionSheet: 3f81bc159b69758f2c859f3cd85b15bb9c223ecb - React-RCTAnimation: af41afc5b073b180274fcdb2026b9b7b10c3b798 - React-RCTBlob: 5a48ac364cc476941099367f5fbeffee0673fa87 - React-RCTImage: 39e2de7650342313728d40955fabd278e5c4c134 - React-RCTLinking: ed8eb075cff2349e89402663585ffef0381848a2 - React-RCTNetwork: 9de10fa1593b0db1cca5bbfd5b2a82e809c8758b - React-RCTPushNotification: 1e7591f9ef1fa557f017b1eaf99e5c88fd5c8e6f - React-RCTSettings: e7a081bcc8c518ce59749ba3803a040f90483ffc - React-RCTTest: aa3ca9247f85c78eee060d74d4a8dbdb0e90c47e - React-RCTText: efbf71e9af9d6e6a7f9fa5ac87b4bd8baf1d8249 - React-RCTVibration: d8ef2a3e93ebb0de2c4e0dbbaee56cdd54c5441b + RCTRequired: 57e1ef095e22d885256164d8c6df479dbd21da07 + RCTTypeSafety: f72f3ec5db9ee5fa6bb29fe9f7fa7dacf50adfdf + React: b97bad9179f2d53c1c1bb1d0c66e2acef1742872 + React-ART: 0ad249875e1b8884b3cd1c489e4647ff34996485 + React-callinvoker: 9d92ac3e7ede9a0a85f037a83910a4d66b0c92ca + React-Core: 51a5896743a633f4156873166f8df2ed9cb0b0d5 + React-CoreModules: e2b16910bbce831fba4ca8ac829b816d82c8eef1 + React-cxxreact: a32457255e1ec50d5a07f9af396870f4b9ed5bdd + React-jsi: 651f42a24396052d7597fec149a7f81ca812165b + React-jsiexecutor: bfe7c0dbc6682c6beb1202c0c6afac92493e6cea + React-jsinspector: 76b4c121774407834f4e595bffbab9ab2b52b32c + React-RCTActionSheet: d2197778c865bbcfb1017ee3fd2c50a19318005b + React-RCTAnimation: c9bc756f8fe2bf0b3bd6940c7ab03cd757d8a032 + React-RCTBlob: 1109c2570e7eb5fb33385b4cca2eec4dc302478c + React-RCTImage: 8390b4f788ffc069d0a7c284bb9b21650bc66116 + React-RCTLinking: 11d1b2a7cbc16e38c717cc4a5e77fe30870ba19f + React-RCTNetwork: 5e1de525f5e12e74dae2f34e534dbf2cca1d63d3 + React-RCTPushNotification: 3d65a4c1e7024261d74c764dd6faff4938cc01cb + React-RCTSettings: 73c143d2537688995cac0511e1285f9bec202a46 + React-RCTTest: f8ad362f336933a7ac2aca51bb72d351b62d0655 + React-RCTText: dba6bfe53bb0ecf817492cda78f6da8c4677e1ab + React-RCTVibration: a1e909ab9ae0b1f4090530e2e90b30ba598d67b4 React-TurboModuleCxx-RNW: 18bb71af41fe34c8b12a56bef60aae7ee32b0817 - React-TurboModuleCxx-WinRTPort: 4719553bda4c93a64b8e1d6a474a8afceb49419c - ReactCommon: f399d6afd467e33cc3042a9f2eed99e9b8c57eb3 - Yoga: 831921041b154f425e43cd8c236502457c632d71 + React-TurboModuleCxx-WinRTPort: 91af7d60f381ea47e2b43a2c0951175dda50218f + ReactCommon: eaa845b24197ed3e1f7a3f77d17cb45d98173975 + Yoga: 8b5431dfe1c915fb925390f0769410304a86e04c YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: baaa75a5807a228f32c4218f28c9260336518038 -COCOAPODS: 1.9.1 +COCOAPODS: 1.10.1 diff --git a/RNTester/js/examples/PlatformColor/PlatformColorExample.js b/RNTester/js/examples/PlatformColor/PlatformColorExample.js index 6968d0619bc765..33079fcffa8cd0 100644 --- a/RNTester/js/examples/PlatformColor/PlatformColorExample.js +++ b/RNTester/js/examples/PlatformColor/PlatformColorExample.js @@ -15,6 +15,7 @@ const ReactNative = require('react-native'); import Platform from '../../../../Libraries/Utilities/Platform'; const { ColorAndroid, + ColorWithSystemEffectMacOS, // TODO(macOS GH#750) DynamicColorIOS, DynamicColorMacOS, PlatformColor, @@ -352,6 +353,144 @@ function VariantColorsExample() { ); } +// [TODO(macOS GH#750) +function ColorWithSystemEffectMacOSExample() { + function createTable() { + let colors = [ + {label: 'gray', color: 'gray'}, + { + label: "ColorWithSystemEffectMacOS('gray', 'none')", + color: ColorWithSystemEffectMacOS('gray', 'none'), + }, + { + label: "ColorWithSystemEffectMacOS('gray', 'pressed')", + color: ColorWithSystemEffectMacOS('gray', 'pressed'), + }, + { + label: "ColorWithSystemEffectMacOS('gray', 'deepPressed')", + color: ColorWithSystemEffectMacOS('gray', 'deepPressed'), + }, + { + label: "ColorWithSystemEffectMacOS('gray', 'disabled')", + color: ColorWithSystemEffectMacOS('gray', 'disabled'), + }, + { + label: "ColorWithSystemEffectMacOS('gray', 'rollover')", + color: ColorWithSystemEffectMacOS('gray', 'rollover'), + }, + { + label: "PlatformColor('systemBlueColor')", + color: PlatformColor('systemBlueColor'), + }, + { + label: + "ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'none')", + color: ColorWithSystemEffectMacOS( + PlatformColor('systemBlueColor'), + 'none', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'pressed')", + color: ColorWithSystemEffectMacOS( + PlatformColor('systemBlueColor'), + 'pressed', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'deepPressed')", + color: ColorWithSystemEffectMacOS( + PlatformColor('systemBlueColor'), + 'deepPressed', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'disabled')", + color: ColorWithSystemEffectMacOS( + PlatformColor('systemBlueColor'), + 'disabled', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'rollover')", + color: ColorWithSystemEffectMacOS( + PlatformColor('systemBlueColor'), + 'rollover', + ), + }, + { + label: "DynamicColorMacOS({light: 'red', dark: 'blue'})", + color: DynamicColorMacOS({light: 'red', dark: 'blue'}), + }, + { + label: + "ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'none')", + color: ColorWithSystemEffectMacOS( + DynamicColorMacOS({light: 'red', dark: 'blue'}), + 'none', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'pressed')", + color: ColorWithSystemEffectMacOS( + DynamicColorMacOS({light: 'red', dark: 'blue'}), + 'pressed', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'deepPressed')", + color: ColorWithSystemEffectMacOS( + DynamicColorMacOS({light: 'red', dark: 'blue'}), + 'deepPressed', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'disabled')", + color: ColorWithSystemEffectMacOS( + DynamicColorMacOS({light: 'red', dark: 'blue'}), + 'disabled', + ), + }, + { + label: + "ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'rollover')", + color: ColorWithSystemEffectMacOS( + DynamicColorMacOS({light: 'red', dark: 'blue'}), + 'rollover', + ), + }, + ]; + + let table = []; + for (let color of colors) { + table.push( + + {color.label} + + , + ); + } + return table; + } + return Platform.OS === 'macos' ? ( + {createTable()} + ) : ( + Not applicable on this platform + ); +} // ]TODO(macOS GH#750) + const styles = StyleSheet.create({ column: {flex: 1, flexDirection: 'column'}, row: {flex: 0.75, flexDirection: 'row'}, @@ -398,4 +537,11 @@ exports.examples = [ return ; }, }, + // [TODO(macOS GH#750) + { + title: 'Color With System Effect macOS', + render(): React.Element { + return ; + }, + }, // ]TODO(macOS GH#750) ]; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 31f973429b5fc0..b5e005b306416a 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -951,6 +951,28 @@ + (RCTUIColor *)NSColor:(id)json } // ]TODO(macOS ISS#2323203) +// [TODO(macOS GH#750) +#if TARGET_OS_OSX +static NSColor *RCTColorWithSystemEffect(NSColor* color, NSString *systemEffectString) { + NSColor *colorWithEffect = color; + if (systemEffectString != nil) { + if ([systemEffectString isEqualToString:@"none"]) { + colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectNone]; + } else if ([systemEffectString isEqualToString:@"pressed"]) { + colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectPressed]; + } else if ([systemEffectString isEqualToString:@"deepPressed"]) { + colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectDeepPressed]; + } else if ([systemEffectString isEqualToString:@"disabled"]) { + colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectDisabled]; + } else if ([systemEffectString isEqualToString:@"rollover"]) { + colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectRollover]; + } + } + return colorWithEffect; +} +#endif //TARGET_OS_OSX +// ]TODO(macOS GH#750) + + (RCTUIColor *)UIColor:(id)json // TODO(OSS Candidate ISS#2710739) { if (!json) { @@ -1030,8 +1052,24 @@ + (RCTUIColor *)UIColor:(id)json // TODO(OSS Candidate ISS#2710739) RCTLogConvertError(json, @"a UIColor. Expected a dynamic appearance aware color."); return nil; } +// [TODO(macOS GH#750) +#if TARGET_OS_OSX + } else if((value = [dictionary objectForKey:@"colorWithSystemEffect"])) { + NSDictionary *colorWithSystemEffect = value; + id base = [colorWithSystemEffect objectForKey:@"baseColor"]; + NSColor *baseColor = [RCTConvert UIColor:base]; + NSString * systemEffectString = [colorWithSystemEffect objectForKey:@"systemEffect"]; + if (baseColor != nil && systemEffectString != nil) { + return RCTColorWithSystemEffect(baseColor, systemEffectString); + } else { + RCTLogConvertError( + json, @"a UIColor. Expected a color with a system effect string, but got something else"); + return nil; + } +#endif //TARGET_OS_OSX +// ]TODO(macOS GH#750) } else { - RCTLogConvertError(json, @"a UIColor. Expected a semantic color or dynamic appearance aware color."); + RCTLogConvertError(json, @"a UIColor. Expected a semantic color, dynamic appearance aware color, or color with system effect"); //TODO(macOS GH#750) return nil; } // ]TODO(macOS ISS#2323203) diff --git a/React/Base/macOS/RCTDynamicColor.m b/React/Base/macOS/RCTDynamicColor.m index 31b8e13a160dfd..e6899f63eabf7e 100644 --- a/React/Base/macOS/RCTDynamicColor.m +++ b/React/Base/macOS/RCTDynamicColor.m @@ -178,7 +178,9 @@ - (nullable NSColor *)blendedColorWithFraction:(CGFloat)fraction ofColor:(NSColo - (NSColor *)colorWithSystemEffect:(NSColorSystemEffect)systemEffect NS_AVAILABLE_MAC(10_14) { - return [[self effectiveColor] colorWithSystemEffect:systemEffect]; + NSColor *aquaColorWithSystemEffect = [_aquaColor colorWithSystemEffect:systemEffect]; + NSColor *darkAquaColorWithSystemEffect = [_darkAquaColor colorWithSystemEffect:systemEffect]; + return [[RCTDynamicColor alloc] initWithAquaColor:aquaColorWithSystemEffect darkAquaColor:darkAquaColorWithSystemEffect]; } - (NSUInteger)hash diff --git a/index.js b/index.js index db266061e3083a..a250d1b8e7c05d 100644 --- a/index.js +++ b/index.js @@ -99,6 +99,7 @@ import typeof processColor from './Libraries/StyleSheet/processColor'; import typeof {PlatformColor} from './Libraries/StyleSheet/PlatformColorValueTypes'; import typeof {DynamicColorIOS} from './Libraries/StyleSheet/PlatformColorValueTypesIOS'; import typeof {DynamicColorMacOS} from './Libraries/StyleSheet/PlatformColorValueTypesMacOS'; // TODO(macOS ISS#2323203) +import typeof {ColorWithSystemEffectMacOS} from './Libraries/StyleSheet/PlatformColorValueTypesMacOS'; // TODO(macOS GH#750) import typeof {ColorAndroid} from './Libraries/StyleSheet/PlatformColorValueTypesAndroid'; import typeof RootTagContext from './Libraries/ReactNative/RootTagContext'; import typeof DeprecatedColorPropType from './Libraries/DeprecatedPropTypes/DeprecatedColorPropType'; @@ -496,10 +497,16 @@ module.exports = { return require('./Libraries/StyleSheet/PlatformColorValueTypesIOS') .DynamicColorIOS; }, + // [TODO(macOS ISS#2323203) get DynamicColorMacOS(): DynamicColorMacOS { return require('./Libraries/StyleSheet/PlatformColorValueTypesMacOS') .DynamicColorMacOS; - }, + }, // [TODO(macOS ISS#2323203) + // [TODO(macOS GH#750) + get ColorWithSystemEffectMacOS(): ColorWithSystemEffectMacOS { + return require('./Libraries/StyleSheet/PlatformColorValueTypesMacOS') + .ColorWithSystemEffectMacOS; + }, // ]TODO(macOS GH#750) get ColorAndroid(): ColorAndroid { return require('./Libraries/StyleSheet/PlatformColorValueTypesAndroid') .ColorAndroid;