Skip to content

Commit b7e23c9

Browse files
committed
Add ColorWithSystemEffectMacOS API to react-native-macos (microsoft#751)
* add pull yml * remove yml * Getting there.. * Closer.. * Remove commented out code * More simplification * remove typo * Make ColorWithSystemEffect it's own sub-object * It works! * Add examples of DynamicColorMacOS with a SystemEffect (currently broken) * Add None Effect too * Fix typo * Essentially feature complete * Rename API * Missed a file * Fix the bug where we call processColor too many times * Replace blah with the issue number * Change one more title * Stub out test on other platforms * Add ifdef macos check, some null checks, and fix up a bunch of the tags * Fix more of the tags * Fix lint errors * ifdef around colorWithEffect method
1 parent 5db7d60 commit b7e23c9

File tree

7 files changed

+279
-5
lines changed

7 files changed

+279
-5
lines changed

Libraries/StyleSheet/PlatformColorValueTypes.macos.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,35 @@ export opaque type NativeColorValue = {
1919
light: ?(ColorValue | ProcessedColorValue),
2020
dark: ?(ColorValue | ProcessedColorValue),
2121
},
22+
colorWithSystemEffect?: {
23+
baseColor: ?(ColorValue | ProcessedColorValue),
24+
systemEffect: SystemEffectMacOSPrivate,
25+
},
2226
};
2327

2428
export const PlatformColor = (...names: Array<string>): ColorValue => {
2529
return {semantic: names};
2630
};
2731

32+
export type SystemEffectMacOSPrivate =
33+
| 'none'
34+
| 'pressed'
35+
| 'deepPressed'
36+
| 'disabled'
37+
| 'rollover';
38+
39+
export const ColorWithSystemEffectMacOSPrivate = (
40+
color: ColorValue,
41+
effect: SystemEffectMacOSPrivate,
42+
): ColorValue => {
43+
return {
44+
colorWithSystemEffect: {
45+
baseColor: color,
46+
systemEffect: effect,
47+
},
48+
};
49+
};
50+
2851
export type DynamicColorMacOSTuplePrivate = {
2952
light: ColorValue,
3053
dark: ColorValue,
@@ -54,8 +77,20 @@ export const normalizeColorObject = (
5477
},
5578
};
5679
return dynamicColor;
80+
} else if (
81+
'colorWithSystemEffect' in color &&
82+
color.colorWithSystemEffect != null
83+
) {
84+
const processColor = require('./processColor');
85+
const colorWithSystemEffect = color.colorWithSystemEffect;
86+
const colorObject: NativeColorValue = {
87+
colorWithSystemEffect: {
88+
baseColor: processColor(colorWithSystemEffect.baseColor),
89+
systemEffect: colorWithSystemEffect.systemEffect,
90+
},
91+
};
92+
return colorObject;
5793
}
58-
5994
return null;
6095
};
6196

@@ -72,6 +107,19 @@ export const processColorObject = (
72107
},
73108
};
74109
return dynamicColor;
110+
} else if (
111+
'colorWithSystemEffect' in color &&
112+
color.colorWithSystemEffect != null
113+
) {
114+
const processColor = require('./processColor');
115+
const colorWithSystemEffect = color.colorWithSystemEffect;
116+
const colorObject: NativeColorValue = {
117+
colorWithSystemEffect: {
118+
baseColor: processColor(colorWithSystemEffect.baseColor),
119+
systemEffect: colorWithSystemEffect.systemEffect,
120+
},
121+
};
122+
return colorObject;
75123
}
76124
return color;
77125
};

Libraries/StyleSheet/PlatformColorValueTypesMacOS.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,20 @@ export const DynamicColorMacOS = (
2222
): ColorValue => {
2323
throw new Error('DynamicColorMacOS is not available on this platform.');
2424
};
25+
26+
export type SystemEffectMacOS =
27+
| 'none'
28+
| 'pressed'
29+
| 'deepPressed'
30+
| 'disabled'
31+
| 'rollover';
32+
33+
export const ColorWithSystemEffectMacOS = (
34+
color: ColorValue,
35+
effect: SystemEffectMacOS,
36+
): ColorValue => {
37+
throw new Error(
38+
'ColorWithSystemEffectMacOS is not available on this platform.',
39+
);
40+
};
2541
// ]TODO(macOS ISS#2323203)

Libraries/StyleSheet/PlatformColorValueTypesMacOS.macos.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
'use strict';
1212

1313
import type {ColorValue} from './StyleSheetTypes';
14-
import {DynamicColorMacOSPrivate} from './PlatformColorValueTypes';
14+
import {
15+
DynamicColorMacOSPrivate,
16+
ColorWithSystemEffectMacOSPrivate,
17+
} from './PlatformColorValueTypes';
1518

1619
export type DynamicColorMacOSTuple = {
1720
light: ColorValue,
@@ -23,4 +26,18 @@ export const DynamicColorMacOS = (
2326
): ColorValue => {
2427
return DynamicColorMacOSPrivate({light: tuple.light, dark: tuple.dark});
2528
};
29+
30+
export type SystemEffectMacOS =
31+
| 'none'
32+
| 'pressed'
33+
| 'deepPressed'
34+
| 'disabled'
35+
| 'rollover';
36+
37+
export const ColorWithSystemEffectMacOS = (
38+
color: ColorValue,
39+
effect: SystemEffectMacOS,
40+
): ColorValue => {
41+
return ColorWithSystemEffectMacOSPrivate(color, effect);
42+
};
2643
// ]TODO(macOS ISS#2323203)

RNTester/js/examples/PlatformColor/PlatformColorExample.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const ReactNative = require('react-native');
1515
import Platform from '../../../../Libraries/Utilities/Platform';
1616
const {
1717
ColorAndroid,
18+
ColorWithSystemEffectMacOS, // TODO(macOS GH#750)
1819
DynamicColorIOS,
1920
DynamicColorMacOS,
2021
PlatformColor,
@@ -352,6 +353,144 @@ function VariantColorsExample() {
352353
);
353354
}
354355

356+
// [TODO(macOS GH#750)
357+
function ColorWithSystemEffectMacOSExample() {
358+
function createTable() {
359+
let colors = [
360+
{label: 'gray', color: 'gray'},
361+
{
362+
label: "ColorWithSystemEffectMacOS('gray', 'none')",
363+
color: ColorWithSystemEffectMacOS('gray', 'none'),
364+
},
365+
{
366+
label: "ColorWithSystemEffectMacOS('gray', 'pressed')",
367+
color: ColorWithSystemEffectMacOS('gray', 'pressed'),
368+
},
369+
{
370+
label: "ColorWithSystemEffectMacOS('gray', 'deepPressed')",
371+
color: ColorWithSystemEffectMacOS('gray', 'deepPressed'),
372+
},
373+
{
374+
label: "ColorWithSystemEffectMacOS('gray', 'disabled')",
375+
color: ColorWithSystemEffectMacOS('gray', 'disabled'),
376+
},
377+
{
378+
label: "ColorWithSystemEffectMacOS('gray', 'rollover')",
379+
color: ColorWithSystemEffectMacOS('gray', 'rollover'),
380+
},
381+
{
382+
label: "PlatformColor('systemBlueColor')",
383+
color: PlatformColor('systemBlueColor'),
384+
},
385+
{
386+
label:
387+
"ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'none')",
388+
color: ColorWithSystemEffectMacOS(
389+
PlatformColor('systemBlueColor'),
390+
'none',
391+
),
392+
},
393+
{
394+
label:
395+
"ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'pressed')",
396+
color: ColorWithSystemEffectMacOS(
397+
PlatformColor('systemBlueColor'),
398+
'pressed',
399+
),
400+
},
401+
{
402+
label:
403+
"ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'deepPressed')",
404+
color: ColorWithSystemEffectMacOS(
405+
PlatformColor('systemBlueColor'),
406+
'deepPressed',
407+
),
408+
},
409+
{
410+
label:
411+
"ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'disabled')",
412+
color: ColorWithSystemEffectMacOS(
413+
PlatformColor('systemBlueColor'),
414+
'disabled',
415+
),
416+
},
417+
{
418+
label:
419+
"ColorWithSystemEffectMacOS(PlatformColor('systemBlueColor'), 'rollover')",
420+
color: ColorWithSystemEffectMacOS(
421+
PlatformColor('systemBlueColor'),
422+
'rollover',
423+
),
424+
},
425+
{
426+
label: "DynamicColorMacOS({light: 'red', dark: 'blue'})",
427+
color: DynamicColorMacOS({light: 'red', dark: 'blue'}),
428+
},
429+
{
430+
label:
431+
"ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'none')",
432+
color: ColorWithSystemEffectMacOS(
433+
DynamicColorMacOS({light: 'red', dark: 'blue'}),
434+
'none',
435+
),
436+
},
437+
{
438+
label:
439+
"ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'pressed')",
440+
color: ColorWithSystemEffectMacOS(
441+
DynamicColorMacOS({light: 'red', dark: 'blue'}),
442+
'pressed',
443+
),
444+
},
445+
{
446+
label:
447+
"ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'deepPressed')",
448+
color: ColorWithSystemEffectMacOS(
449+
DynamicColorMacOS({light: 'red', dark: 'blue'}),
450+
'deepPressed',
451+
),
452+
},
453+
{
454+
label:
455+
"ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'disabled')",
456+
color: ColorWithSystemEffectMacOS(
457+
DynamicColorMacOS({light: 'red', dark: 'blue'}),
458+
'disabled',
459+
),
460+
},
461+
{
462+
label:
463+
"ColorWithSystemEffectMacOS(DynamicColorMacOS({light: 'red', dark: 'blue'}), 'rollover')",
464+
color: ColorWithSystemEffectMacOS(
465+
DynamicColorMacOS({light: 'red', dark: 'blue'}),
466+
'rollover',
467+
),
468+
},
469+
];
470+
471+
let table = [];
472+
for (let color of colors) {
473+
table.push(
474+
<View style={styles.row} key={color.label}>
475+
<Text style={styles.labelCell}>{color.label}</Text>
476+
<View
477+
style={{
478+
...styles.colorCell,
479+
backgroundColor: color.color,
480+
}}
481+
/>
482+
</View>,
483+
);
484+
}
485+
return table;
486+
}
487+
return Platform.OS === 'macos' ? (
488+
<View style={styles.column}>{createTable()}</View>
489+
) : (
490+
<Text style={styles.labelCell}>Not applicable on this platform</Text>
491+
);
492+
} // ]TODO(macOS GH#750)
493+
355494
const styles = StyleSheet.create({
356495
column: {flex: 1, flexDirection: 'column'},
357496
row: {flex: 0.75, flexDirection: 'row'},
@@ -398,4 +537,11 @@ exports.examples = [
398537
return <VariantColorsExample />;
399538
},
400539
},
540+
// [TODO(macOS GH#750)
541+
{
542+
title: 'Color With System Effect macOS',
543+
render(): React.Element<any> {
544+
return <ColorWithSystemEffectMacOSExample />;
545+
},
546+
}, // ]TODO(macOS GH#750)
401547
];

React/Base/RCTConvert.m

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,28 @@ + (RCTUIColor *)NSColor:(id)json
951951
}
952952
// ]TODO(macOS ISS#2323203)
953953

954+
// [TODO(macOS GH#750)
955+
#if TARGET_OS_OSX
956+
static NSColor *RCTColorWithSystemEffect(NSColor* color, NSString *systemEffectString) {
957+
NSColor *colorWithEffect = color;
958+
if (systemEffectString != nil) {
959+
if ([systemEffectString isEqualToString:@"none"]) {
960+
colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectNone];
961+
} else if ([systemEffectString isEqualToString:@"pressed"]) {
962+
colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectPressed];
963+
} else if ([systemEffectString isEqualToString:@"deepPressed"]) {
964+
colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectDeepPressed];
965+
} else if ([systemEffectString isEqualToString:@"disabled"]) {
966+
colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectDisabled];
967+
} else if ([systemEffectString isEqualToString:@"rollover"]) {
968+
colorWithEffect = [color colorWithSystemEffect:NSColorSystemEffectRollover];
969+
}
970+
}
971+
return colorWithEffect;
972+
}
973+
#endif //TARGET_OS_OSX
974+
// ]TODO(macOS GH#750)
975+
954976
+ (RCTUIColor *)UIColor:(id)json // TODO(OSS Candidate ISS#2710739)
955977
{
956978
if (!json) {
@@ -1030,8 +1052,24 @@ + (RCTUIColor *)UIColor:(id)json // TODO(OSS Candidate ISS#2710739)
10301052
RCTLogConvertError(json, @"a UIColor. Expected a dynamic appearance aware color.");
10311053
return nil;
10321054
}
1055+
// [TODO(macOS GH#750)
1056+
#if TARGET_OS_OSX
1057+
} else if((value = [dictionary objectForKey:@"colorWithSystemEffect"])) {
1058+
NSDictionary *colorWithSystemEffect = value;
1059+
id base = [colorWithSystemEffect objectForKey:@"baseColor"];
1060+
NSColor *baseColor = [RCTConvert UIColor:base];
1061+
NSString * systemEffectString = [colorWithSystemEffect objectForKey:@"systemEffect"];
1062+
if (baseColor != nil && systemEffectString != nil) {
1063+
return RCTColorWithSystemEffect(baseColor, systemEffectString);
1064+
} else {
1065+
RCTLogConvertError(
1066+
json, @"a UIColor. Expected a color with a system effect string, but got something else");
1067+
return nil;
1068+
}
1069+
#endif //TARGET_OS_OSX
1070+
// ]TODO(macOS GH#750)
10331071
} else {
1034-
RCTLogConvertError(json, @"a UIColor. Expected a semantic color or dynamic appearance aware color.");
1072+
RCTLogConvertError(json, @"a UIColor. Expected a semantic color, dynamic appearance aware color, or color with system effect"); //TODO(macOS GH#750)
10351073
return nil;
10361074
}
10371075
// ]TODO(macOS ISS#2323203)

React/Base/macOS/RCTDynamicColor.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ - (nullable NSColor *)blendedColorWithFraction:(CGFloat)fraction ofColor:(NSColo
178178

179179
- (NSColor *)colorWithSystemEffect:(NSColorSystemEffect)systemEffect NS_AVAILABLE_MAC(10_14)
180180
{
181-
return [[self effectiveColor] colorWithSystemEffect:systemEffect];
181+
NSColor *aquaColorWithSystemEffect = [_aquaColor colorWithSystemEffect:systemEffect];
182+
NSColor *darkAquaColorWithSystemEffect = [_darkAquaColor colorWithSystemEffect:systemEffect];
183+
return [[RCTDynamicColor alloc] initWithAquaColor:aquaColorWithSystemEffect darkAquaColor:darkAquaColorWithSystemEffect];
182184
}
183185

184186
- (NSUInteger)hash

index.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ import typeof processColor from './Libraries/StyleSheet/processColor';
9999
import typeof {PlatformColor} from './Libraries/StyleSheet/PlatformColorValueTypes';
100100
import typeof {DynamicColorIOS} from './Libraries/StyleSheet/PlatformColorValueTypesIOS';
101101
import typeof {DynamicColorMacOS} from './Libraries/StyleSheet/PlatformColorValueTypesMacOS'; // TODO(macOS ISS#2323203)
102+
import typeof {ColorWithSystemEffectMacOS} from './Libraries/StyleSheet/PlatformColorValueTypesMacOS'; // TODO(macOS GH#750)
102103
import typeof {ColorAndroid} from './Libraries/StyleSheet/PlatformColorValueTypesAndroid';
103104
import typeof RootTagContext from './Libraries/ReactNative/RootTagContext';
104105
import typeof DeprecatedColorPropType from './Libraries/DeprecatedPropTypes/DeprecatedColorPropType';
@@ -496,10 +497,16 @@ module.exports = {
496497
return require('./Libraries/StyleSheet/PlatformColorValueTypesIOS')
497498
.DynamicColorIOS;
498499
},
500+
// [TODO(macOS ISS#2323203)
499501
get DynamicColorMacOS(): DynamicColorMacOS {
500502
return require('./Libraries/StyleSheet/PlatformColorValueTypesMacOS')
501503
.DynamicColorMacOS;
502-
},
504+
}, // [TODO(macOS ISS#2323203)
505+
// [TODO(macOS GH#750)
506+
get ColorWithSystemEffectMacOS(): ColorWithSystemEffectMacOS {
507+
return require('./Libraries/StyleSheet/PlatformColorValueTypesMacOS')
508+
.ColorWithSystemEffectMacOS;
509+
}, // ]TODO(macOS GH#750)
503510
get ColorAndroid(): ColorAndroid {
504511
return require('./Libraries/StyleSheet/PlatformColorValueTypesAndroid')
505512
.ColorAndroid;

0 commit comments

Comments
 (0)