diff --git a/change/react-native-windows-2019-12-16-18-55-30-windowsBrush.json b/change/react-native-windows-2019-12-16-18-55-30-windowsBrush.json
new file mode 100644
index 00000000000..3e309afb530
--- /dev/null
+++ b/change/react-native-windows-2019-12-16-18-55-30-windowsBrush.json
@@ -0,0 +1,8 @@
+{
+ "type": "prerelease",
+ "comment": "port windowsbrush changes from Microsoft fork of react-native",
+ "packageName": "react-native-windows",
+ "email": "kmelmon@microsoft.com",
+ "commit": "a195ce0d079f30dcfd3b376e89240916891204bd",
+ "date": "2019-12-17T02:55:30.505Z"
+}
\ No newline at end of file
diff --git a/vnext/src/Libraries/Color/normalizeColor.windows.js b/vnext/src/Libraries/Color/normalizeColor.windows.js
new file mode 100644
index 00000000000..8aecb3defc2
--- /dev/null
+++ b/vnext/src/Libraries/Color/normalizeColor.windows.js
@@ -0,0 +1,393 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @format
+ * @flow
+ */
+
+/* eslint no-bitwise: 0 */
+'use strict';
+
+import type {NativeOrDynamicColorType} from './NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
+
+function normalizeColor(
+ color: ?(
+ | string
+ | number
+ | NativeOrDynamicColorType
+ ) /* TODO(macOS ISS#2323203) */,
+): ?(number | NativeOrDynamicColorType) /* TODO(macOS ISS#2323203) */ {
+ const matchers = getMatchers();
+ let match;
+
+ if (typeof color === 'number') {
+ if (color >>> 0 === color && color >= 0 && color <= 0xffffffff) {
+ return color;
+ }
+ return null;
+ }
+
+ // [TODO(macOS ISS#2323203)
+ if (typeof color === 'object' && color !== null) {
+ const normalizeColorObject = require('normalizeColorObject'); // TODO(macOS ISS#2323203)
+
+ const normalizedColorObj = normalizeColorObject(color);
+
+ if (normalizedColorObj !== null) {
+ return color;
+ }
+ }
+
+ if (typeof color !== 'string') {
+ return null;
+ } // ]TODO(macOS ISS#2323203)
+
+ // Ordered based on occurrences on Facebook codebase
+ if ((match = matchers.hex6.exec(color))) {
+ return parseInt(match[1] + 'ff', 16) >>> 0;
+ }
+
+ if (names.hasOwnProperty(color)) {
+ return names[color];
+ }
+
+ if ((match = matchers.rgb.exec(color))) {
+ return (
+ // b
+ ((parse255(match[1]) << 24) | // r
+ (parse255(match[2]) << 16) | // g
+ (parse255(match[3]) << 8) |
+ 0x000000ff) >>> // a
+ 0
+ );
+ }
+
+ if ((match = matchers.rgba.exec(color))) {
+ return (
+ // b
+ ((parse255(match[1]) << 24) | // r
+ (parse255(match[2]) << 16) | // g
+ (parse255(match[3]) << 8) |
+ parse1(match[4])) >>> // a
+ 0
+ );
+ }
+
+ if ((match = matchers.hex3.exec(color))) {
+ return (
+ parseInt(
+ match[1] +
+ match[1] + // r
+ match[2] +
+ match[2] + // g
+ match[3] +
+ match[3] + // b
+ 'ff', // a
+ 16,
+ ) >>> 0
+ );
+ }
+
+ // https://drafts.csswg.org/css-color-4/#hex-notation
+ if ((match = matchers.hex8.exec(color))) {
+ return parseInt(match[1], 16) >>> 0;
+ }
+
+ if ((match = matchers.hex4.exec(color))) {
+ return (
+ parseInt(
+ match[1] +
+ match[1] + // r
+ match[2] +
+ match[2] + // g
+ match[3] +
+ match[3] + // b
+ match[4] +
+ match[4], // a
+ 16,
+ ) >>> 0
+ );
+ }
+
+ if ((match = matchers.hsl.exec(color))) {
+ return (
+ (hslToRgb(
+ parse360(match[1]), // h
+ parsePercentage(match[2]), // s
+ parsePercentage(match[3]), // l
+ ) |
+ 0x000000ff) >>> // a
+ 0
+ );
+ }
+
+ if ((match = matchers.hsla.exec(color))) {
+ return (
+ (hslToRgb(
+ parse360(match[1]), // h
+ parsePercentage(match[2]), // s
+ parsePercentage(match[3]), // l
+ ) |
+ parse1(match[4])) >>> // a
+ 0
+ );
+ }
+
+ return null;
+}
+
+function hue2rgb(p: number, q: number, t: number): number {
+ if (t < 0) {
+ t += 1;
+ }
+ if (t > 1) {
+ t -= 1;
+ }
+ if (t < 1 / 6) {
+ return p + (q - p) * 6 * t;
+ }
+ if (t < 1 / 2) {
+ return q;
+ }
+ if (t < 2 / 3) {
+ return p + (q - p) * (2 / 3 - t) * 6;
+ }
+ return p;
+}
+
+function hslToRgb(h: number, s: number, l: number): number {
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ const p = 2 * l - q;
+ const r = hue2rgb(p, q, h + 1 / 3);
+ const g = hue2rgb(p, q, h);
+ const b = hue2rgb(p, q, h - 1 / 3);
+
+ return (
+ (Math.round(r * 255) << 24) |
+ (Math.round(g * 255) << 16) |
+ (Math.round(b * 255) << 8)
+ );
+}
+
+// var INTEGER = '[-+]?\\d+';
+const NUMBER = '[-+]?\\d*\\.?\\d+';
+const PERCENTAGE = NUMBER + '%';
+
+function call(...args) {
+ return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)';
+}
+
+let cachedMatchers;
+
+function getMatchers() {
+ if (cachedMatchers === undefined) {
+ cachedMatchers = {
+ rgb: new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER)),
+ rgba: new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER)),
+ hsl: new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE)),
+ hsla: new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER)),
+ hex3: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
+ hex4: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
+ hex6: /^#([0-9a-fA-F]{6})$/,
+ hex8: /^#([0-9a-fA-F]{8})$/,
+ };
+ }
+ return cachedMatchers;
+}
+
+function parse255(str: string): number {
+ const int = parseInt(str, 10);
+ if (int < 0) {
+ return 0;
+ }
+ if (int > 255) {
+ return 255;
+ }
+ return int;
+}
+
+function parse360(str: string): number {
+ const int = parseFloat(str);
+ return (((int % 360) + 360) % 360) / 360;
+}
+
+function parse1(str: string): number {
+ const num = parseFloat(str);
+ if (num < 0) {
+ return 0;
+ }
+ if (num > 1) {
+ return 255;
+ }
+ return Math.round(num * 255);
+}
+
+function parsePercentage(str: string): number {
+ // parseFloat conveniently ignores the final %
+ const int = parseFloat(str);
+ if (int < 0) {
+ return 0;
+ }
+ if (int > 100) {
+ return 1;
+ }
+ return int / 100;
+}
+
+const names = {
+ transparent: 0x00000000,
+
+ // http://www.w3.org/TR/css3-color/#svg-color
+ aliceblue: 0xf0f8ffff,
+ antiquewhite: 0xfaebd7ff,
+ aqua: 0x00ffffff,
+ aquamarine: 0x7fffd4ff,
+ azure: 0xf0ffffff,
+ beige: 0xf5f5dcff,
+ bisque: 0xffe4c4ff,
+ black: 0x000000ff,
+ blanchedalmond: 0xffebcdff,
+ blue: 0x0000ffff,
+ blueviolet: 0x8a2be2ff,
+ brown: 0xa52a2aff,
+ burlywood: 0xdeb887ff,
+ burntsienna: 0xea7e5dff,
+ cadetblue: 0x5f9ea0ff,
+ chartreuse: 0x7fff00ff,
+ chocolate: 0xd2691eff,
+ coral: 0xff7f50ff,
+ cornflowerblue: 0x6495edff,
+ cornsilk: 0xfff8dcff,
+ crimson: 0xdc143cff,
+ cyan: 0x00ffffff,
+ darkblue: 0x00008bff,
+ darkcyan: 0x008b8bff,
+ darkgoldenrod: 0xb8860bff,
+ darkgray: 0xa9a9a9ff,
+ darkgreen: 0x006400ff,
+ darkgrey: 0xa9a9a9ff,
+ darkkhaki: 0xbdb76bff,
+ darkmagenta: 0x8b008bff,
+ darkolivegreen: 0x556b2fff,
+ darkorange: 0xff8c00ff,
+ darkorchid: 0x9932ccff,
+ darkred: 0x8b0000ff,
+ darksalmon: 0xe9967aff,
+ darkseagreen: 0x8fbc8fff,
+ darkslateblue: 0x483d8bff,
+ darkslategray: 0x2f4f4fff,
+ darkslategrey: 0x2f4f4fff,
+ darkturquoise: 0x00ced1ff,
+ darkviolet: 0x9400d3ff,
+ deeppink: 0xff1493ff,
+ deepskyblue: 0x00bfffff,
+ dimgray: 0x696969ff,
+ dimgrey: 0x696969ff,
+ dodgerblue: 0x1e90ffff,
+ firebrick: 0xb22222ff,
+ floralwhite: 0xfffaf0ff,
+ forestgreen: 0x228b22ff,
+ fuchsia: 0xff00ffff,
+ gainsboro: 0xdcdcdcff,
+ ghostwhite: 0xf8f8ffff,
+ gold: 0xffd700ff,
+ goldenrod: 0xdaa520ff,
+ gray: 0x808080ff,
+ green: 0x008000ff,
+ greenyellow: 0xadff2fff,
+ grey: 0x808080ff,
+ honeydew: 0xf0fff0ff,
+ hotpink: 0xff69b4ff,
+ indianred: 0xcd5c5cff,
+ indigo: 0x4b0082ff,
+ ivory: 0xfffff0ff,
+ khaki: 0xf0e68cff,
+ lavender: 0xe6e6faff,
+ lavenderblush: 0xfff0f5ff,
+ lawngreen: 0x7cfc00ff,
+ lemonchiffon: 0xfffacdff,
+ lightblue: 0xadd8e6ff,
+ lightcoral: 0xf08080ff,
+ lightcyan: 0xe0ffffff,
+ lightgoldenrodyellow: 0xfafad2ff,
+ lightgray: 0xd3d3d3ff,
+ lightgreen: 0x90ee90ff,
+ lightgrey: 0xd3d3d3ff,
+ lightpink: 0xffb6c1ff,
+ lightsalmon: 0xffa07aff,
+ lightseagreen: 0x20b2aaff,
+ lightskyblue: 0x87cefaff,
+ lightslategray: 0x778899ff,
+ lightslategrey: 0x778899ff,
+ lightsteelblue: 0xb0c4deff,
+ lightyellow: 0xffffe0ff,
+ lime: 0x00ff00ff,
+ limegreen: 0x32cd32ff,
+ linen: 0xfaf0e6ff,
+ magenta: 0xff00ffff,
+ maroon: 0x800000ff,
+ mediumaquamarine: 0x66cdaaff,
+ mediumblue: 0x0000cdff,
+ mediumorchid: 0xba55d3ff,
+ mediumpurple: 0x9370dbff,
+ mediumseagreen: 0x3cb371ff,
+ mediumslateblue: 0x7b68eeff,
+ mediumspringgreen: 0x00fa9aff,
+ mediumturquoise: 0x48d1ccff,
+ mediumvioletred: 0xc71585ff,
+ midnightblue: 0x191970ff,
+ mintcream: 0xf5fffaff,
+ mistyrose: 0xffe4e1ff,
+ moccasin: 0xffe4b5ff,
+ navajowhite: 0xffdeadff,
+ navy: 0x000080ff,
+ oldlace: 0xfdf5e6ff,
+ olive: 0x808000ff,
+ olivedrab: 0x6b8e23ff,
+ orange: 0xffa500ff,
+ orangered: 0xff4500ff,
+ orchid: 0xda70d6ff,
+ palegoldenrod: 0xeee8aaff,
+ palegreen: 0x98fb98ff,
+ paleturquoise: 0xafeeeeff,
+ palevioletred: 0xdb7093ff,
+ papayawhip: 0xffefd5ff,
+ peachpuff: 0xffdab9ff,
+ peru: 0xcd853fff,
+ pink: 0xffc0cbff,
+ plum: 0xdda0ddff,
+ powderblue: 0xb0e0e6ff,
+ purple: 0x800080ff,
+ rebeccapurple: 0x663399ff,
+ red: 0xff0000ff,
+ rosybrown: 0xbc8f8fff,
+ royalblue: 0x4169e1ff,
+ saddlebrown: 0x8b4513ff,
+ salmon: 0xfa8072ff,
+ sandybrown: 0xf4a460ff,
+ seagreen: 0x2e8b57ff,
+ seashell: 0xfff5eeff,
+ sienna: 0xa0522dff,
+ silver: 0xc0c0c0ff,
+ skyblue: 0x87ceebff,
+ slateblue: 0x6a5acdff,
+ slategray: 0x708090ff,
+ slategrey: 0x708090ff,
+ snow: 0xfffafaff,
+ springgreen: 0x00ff7fff,
+ steelblue: 0x4682b4ff,
+ tan: 0xd2b48cff,
+ teal: 0x008080ff,
+ thistle: 0xd8bfd8ff,
+ tomato: 0xff6347ff,
+ turquoise: 0x40e0d0ff,
+ violet: 0xee82eeff,
+ wheat: 0xf5deb3ff,
+ white: 0xffffffff,
+ whitesmoke: 0xf5f5f5ff,
+ yellow: 0xffff00ff,
+ yellowgreen: 0x9acd32ff,
+};
+
+module.exports = normalizeColor;
diff --git a/vnext/src/Libraries/Components/ActivityIndicator/ActivityIndicator.windows.js b/vnext/src/Libraries/Components/ActivityIndicator/ActivityIndicator.windows.js
new file mode 100644
index 00000000000..0cebe9f7bf6
--- /dev/null
+++ b/vnext/src/Libraries/Components/ActivityIndicator/ActivityIndicator.windows.js
@@ -0,0 +1,144 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @format
+ * @flow
+ */
+
+'use strict';
+
+const Platform = require('../../Utilities/Platform');
+const React = require('react');
+const StyleSheet = require('../../StyleSheet/StyleSheet');
+const View = require('../View/View');
+
+const RCTActivityIndicatorViewNativeComponent = require('./RCTActivityIndicatorViewNativeComponent');
+
+import type {NativeComponent} from '../../Renderer/shims/ReactNative';
+import type {ViewProps} from '../View/ViewPropTypes';
+import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // ]TODO(macOS ISS#2323203)
+
+const RCTActivityIndicator =
+ Platform.OS === 'android'
+ ? require('../ProgressBarAndroid/ProgressBarAndroid')
+ : RCTActivityIndicatorViewNativeComponent;
+
+const GRAY = '#999999';
+
+type IndicatorSize = number | 'small' | 'large';
+
+type IOSProps = $ReadOnly<{|
+ /**
+ * Whether the indicator should hide when not animating (true by default).
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#hideswhenstopped
+ */
+ hidesWhenStopped?: ?boolean,
+|}>;
+type Props = $ReadOnly<{|
+ ...ViewProps,
+ ...IOSProps,
+
+ /**
+ * Whether to show the indicator (true, the default) or hide it (false).
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#animating
+ */
+ animating?: ?boolean,
+
+ /**
+ * The foreground color of the spinner (default is gray).
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#color
+ */
+ color?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+
+ /**
+ * Size of the indicator (default is 'small').
+ * Passing a number to the size prop is only supported on Android.
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#size
+ */
+ size?: ?IndicatorSize,
+|}>;
+
+/**
+ * Displays a circular loading indicator.
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html
+ */
+const ActivityIndicator = (props: Props, forwardedRef?: any) => {
+ const {onLayout, style, size, ...restProps} = props;
+ let sizeStyle;
+ let sizeProp;
+
+ switch (size) {
+ case 'small':
+ sizeStyle = styles.sizeSmall;
+ sizeProp = 'small';
+ break;
+ case 'large':
+ sizeStyle = styles.sizeLarge;
+ sizeProp = 'large';
+ break;
+ default:
+ sizeStyle = {height: props.size, width: props.size};
+ break;
+ }
+
+ const nativeProps = {
+ ...restProps,
+ ref: forwardedRef,
+ style: sizeStyle,
+ size: sizeProp,
+ styleAttr: 'Normal',
+ indeterminate: true,
+ };
+
+ return (
+
+ {/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was
+ * found when making Flow check .android.js files. */}
+
+
+ );
+};
+
+const ActivityIndicatorWithRef = React.forwardRef(ActivityIndicator);
+ActivityIndicatorWithRef.displayName = 'ActivityIndicator';
+
+/* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an error
+ * found when Flow v0.89 was deployed. To see the error, delete this comment
+ * and run Flow. */
+ActivityIndicatorWithRef.defaultProps = {
+ animating: true,
+ color: Platform.OS === 'ios' ? GRAY : null,
+ hidesWhenStopped: true,
+ size: 'small',
+};
+
+const styles = StyleSheet.create({
+ container: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ sizeSmall: {
+ width: 20,
+ height: 20,
+ },
+ sizeLarge: {
+ width: 36,
+ height: 36,
+ },
+});
+
+/* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an error
+ * found when Flow v0.89 was deployed. To see the error, delete this comment
+ * and run Flow. */
+module.exports = (ActivityIndicatorWithRef: Class>);
diff --git a/vnext/src/Libraries/Components/ActivityIndicator/RCTActivityIndicatorViewNativeComponent.windows.js b/vnext/src/Libraries/Components/ActivityIndicator/RCTActivityIndicatorViewNativeComponent.windows.js
new file mode 100644
index 00000000000..6b8a581cab5
--- /dev/null
+++ b/vnext/src/Libraries/Components/ActivityIndicator/RCTActivityIndicatorViewNativeComponent.windows.js
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @format
+ * @flow
+ */
+
+'use strict';
+
+const requireNativeComponent = require('../../ReactNative/requireNativeComponent');
+
+import type {ViewProps} from '../View/ViewPropTypes';
+import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
+import type {NativeComponent} from '../../Renderer/shims/ReactNative';
+import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // ]TODO(macOS ISS#2323203)
+
+type NativeProps = $ReadOnly<{|
+ ...ViewProps,
+
+ /**
+ * Whether the indicator should hide when not animating (true by default).
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#hideswhenstopped
+ */
+ hidesWhenStopped?: ?boolean,
+
+ /**
+ * Whether to show the indicator (true, the default) or hide it (false).
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#animating
+ */
+ animating?: ?boolean,
+
+ /**
+ * The foreground color of the spinner (default is gray).
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#color
+ */
+ color?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+
+ /**
+ * Size of the indicator (default is 'small').
+ * Passing a number to the size prop is only supported on Android.
+ *
+ * See http://facebook.github.io/react-native/docs/activityindicator.html#size
+ */
+ size?: ?('small' | 'large'),
+
+ style?: ?ViewStyleProp,
+ styleAttr?: ?string,
+ indeterminate?: ?boolean,
+|}>;
+
+type ActivityIndicatorNativeType = Class>;
+
+module.exports = ((requireNativeComponent(
+ 'RCTActivityIndicatorView',
+): any): ActivityIndicatorNativeType);
diff --git a/vnext/src/Libraries/Components/Picker/RCTPickerNativeComponent.windows.js b/vnext/src/Libraries/Components/Picker/RCTPickerNativeComponent.windows.js
new file mode 100644
index 00000000000..9eb84db6493
--- /dev/null
+++ b/vnext/src/Libraries/Components/Picker/RCTPickerNativeComponent.windows.js
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @flow
+ * @format
+ */
+'use strict';
+
+const requireNativeComponent = require('../../ReactNative/requireNativeComponent');
+
+import type {SyntheticEvent} from '../../Types/CoreEventTypes';
+import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
+import type {NativeComponent} from '../../Renderer/shims/ReactNative';
+import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // ]TODO(macOS ISS#2323203)
+
+type PickerIOSChangeEvent = SyntheticEvent<
+ $ReadOnly<{|
+ newValue: number | string,
+ newIndex: number,
+ |}>,
+>;
+
+type RCTPickerIOSItemType = $ReadOnly<{|
+ label: ?Label,
+ value: ?(number | string),
+ textColor: ?(number | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+|}>;
+
+type Label = Stringish | number;
+
+type RCTPickerIOSType = Class<
+ NativeComponent<
+ $ReadOnly<{|
+ items: $ReadOnlyArray,
+ onChange: (event: PickerIOSChangeEvent) => void,
+ onResponderTerminationRequest: () => boolean,
+ onStartShouldSetResponder: () => boolean,
+ selectedIndex: number,
+ style?: ?TextStyleProp,
+ testID?: ?string,
+ |}>,
+ >,
+>;
+
+module.exports = ((requireNativeComponent('RCTPicker'): any): RCTPickerIOSType);
diff --git a/vnext/src/Libraries/Components/Switch/SwitchNativeComponent.windows.js b/vnext/src/Libraries/Components/Switch/SwitchNativeComponent.windows.js
new file mode 100644
index 00000000000..4a8fad3bd44
--- /dev/null
+++ b/vnext/src/Libraries/Components/Switch/SwitchNativeComponent.windows.js
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @flow
+ * @format
+ */
+
+'use strict';
+
+const Platform = require('../../Utilities/Platform');
+const ReactNative = require('../../Renderer/shims/ReactNative');
+
+const requireNativeComponent = require('../../ReactNative/requireNativeComponent');
+
+import type {SwitchChangeEvent} from '../../Types/CoreEventTypes';
+import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
+import type {ViewProps} from '../View/ViewPropTypes';
+import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
+
+type SwitchProps = $ReadOnly<{|
+ ...ViewProps,
+ disabled?: ?boolean,
+ onChange?: ?(event: SwitchChangeEvent) => mixed,
+ thumbColor?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+ trackColorForFalse?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+ trackColorForTrue?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+ value?: ?boolean,
+|}>;
+
+// @see ReactSwitchManager.java
+export type NativeAndroidProps = $ReadOnly<{|
+ ...SwitchProps,
+
+ enabled?: ?boolean,
+ on?: ?boolean,
+ thumbTintColor?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+ trackTintColor?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+|}>;
+
+// @see RCTSwitchManager.m
+export type NativeIOSProps = $ReadOnly<{|
+ ...SwitchProps,
+
+ onTintColor?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+ thumbTintColor?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+ tintColor?: ?(string | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
+|}>;
+
+type SwitchNativeComponentType = Class<
+ ReactNative.NativeComponent<
+ $ReadOnly<{|
+ ...NativeAndroidProps,
+ ...NativeIOSProps,
+ |}>,
+ >,
+>;
+
+const SwitchNativeComponent: SwitchNativeComponentType =
+ Platform.OS === 'android'
+ ? (requireNativeComponent('AndroidSwitch'): any)
+ : (requireNativeComponent('RCTSwitch'): any);
+
+module.exports = SwitchNativeComponent;
diff --git a/vnext/src/Libraries/ReactNative/getNativeComponentAttributes.windows.js b/vnext/src/Libraries/ReactNative/getNativeComponentAttributes.windows.js
new file mode 100644
index 00000000000..0ef09a566e8
--- /dev/null
+++ b/vnext/src/Libraries/ReactNative/getNativeComponentAttributes.windows.js
@@ -0,0 +1,190 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @flow
+ * @format
+ */
+
+'use strict';
+
+const ReactNativeStyleAttributes = require('../Components/View/ReactNativeStyleAttributes');
+const UIManager = require('./UIManager');
+
+const insetsDiffer = require('../Utilities/differ/insetsDiffer');
+const matricesDiffer = require('../Utilities/differ/matricesDiffer');
+const pointsDiffer = require('../Utilities/differ/pointsDiffer');
+const processColor = require('../StyleSheet/processColor');
+const resolveAssetSource = require('../Image/resolveAssetSource');
+const sizesDiffer = require('../Utilities/differ/sizesDiffer');
+const invariant = require('invariant');
+const warning = require('fbjs/lib/warning');
+import type {NativeOrDynamicColorType} from 'NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
+
+function getNativeComponentAttributes(uiViewClassName: string) {
+ const viewConfig = UIManager.getViewManagerConfig(uiViewClassName);
+
+ invariant(
+ viewConfig != null && viewConfig.NativeProps != null,
+ 'requireNativeComponent: "%s" was not found in the UIManager.',
+ uiViewClassName,
+ );
+
+ // TODO: This seems like a whole lot of runtime initialization for every
+ // native component that can be either avoided or simplified.
+ let {baseModuleName, bubblingEventTypes, directEventTypes} = viewConfig;
+ let nativeProps = viewConfig.NativeProps;
+ while (baseModuleName) {
+ const baseModule = UIManager.getViewManagerConfig(baseModuleName);
+ if (!baseModule) {
+ warning(false, 'Base module "%s" does not exist', baseModuleName);
+ baseModuleName = null;
+ } else {
+ bubblingEventTypes = {
+ ...baseModule.bubblingEventTypes,
+ ...bubblingEventTypes,
+ };
+ directEventTypes = {
+ ...baseModule.directEventTypes,
+ ...directEventTypes,
+ };
+ nativeProps = {
+ ...baseModule.NativeProps,
+ ...nativeProps,
+ };
+ baseModuleName = baseModule.baseModuleName;
+ }
+ }
+
+ const validAttributes = {};
+
+ for (const key in nativeProps) {
+ const typeName = nativeProps[key];
+ const diff = getDifferForType(typeName);
+ const process = getProcessorForType(typeName);
+
+ validAttributes[key] =
+ diff == null && process == null ? true : {diff, process};
+ }
+
+ // Unfortunately, the current setup declares style properties as top-level
+ // props. This makes it so we allow style properties in the `style` prop.
+ // TODO: Move style properties into a `style` prop and disallow them as
+ // top-level props on the native side.
+ validAttributes.style = ReactNativeStyleAttributes;
+
+ Object.assign(viewConfig, {
+ uiViewClassName,
+ validAttributes,
+ bubblingEventTypes,
+ directEventTypes,
+ });
+
+ if (!hasAttachedDefaultEventTypes) {
+ attachDefaultEventTypes(viewConfig);
+ hasAttachedDefaultEventTypes = true;
+ }
+
+ return viewConfig;
+}
+
+// TODO: Figure out how this makes sense. We're using a global boolean to only
+// initialize this on the first eagerly initialized native component.
+let hasAttachedDefaultEventTypes = false;
+function attachDefaultEventTypes(viewConfig: any) {
+ // This is supported on UIManager platforms (ex: Android),
+ // as lazy view managers are not implemented for all platforms.
+ // See [UIManager] for details on constants and implementations.
+ if (UIManager.ViewManagerNames || UIManager.LazyViewManagersEnabled) {
+ // Lazy view managers enabled.
+ viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes());
+ } else {
+ viewConfig.bubblingEventTypes = merge(
+ viewConfig.bubblingEventTypes,
+ UIManager.genericBubblingEventTypes,
+ );
+ viewConfig.directEventTypes = merge(
+ viewConfig.directEventTypes,
+ UIManager.genericDirectEventTypes,
+ );
+ }
+}
+
+// TODO: Figure out how to avoid all this runtime initialization cost.
+function merge(destination: ?Object, source: ?Object): ?Object {
+ if (!source) {
+ return destination;
+ }
+ if (!destination) {
+ return source;
+ }
+
+ for (const key in source) {
+ if (!source.hasOwnProperty(key)) {
+ continue;
+ }
+
+ let sourceValue = source[key];
+ if (destination.hasOwnProperty(key)) {
+ const destinationValue = destination[key];
+ if (
+ typeof sourceValue === 'object' &&
+ typeof destinationValue === 'object'
+ ) {
+ sourceValue = merge(destinationValue, sourceValue);
+ }
+ }
+ destination[key] = sourceValue;
+ }
+ return destination;
+}
+
+function getDifferForType(
+ typeName: string,
+): ?(prevProp: any, nextProp: any) => boolean {
+ switch (typeName) {
+ // iOS Types
+ case 'CATransform3D':
+ return matricesDiffer;
+ case 'CGPoint':
+ return pointsDiffer;
+ case 'CGSize':
+ return sizesDiffer;
+ case 'UIEdgeInsets':
+ return insetsDiffer;
+ // Android Types
+ // (not yet implemented)
+ }
+ return null;
+}
+
+function getProcessorForType(typeName: string): ?(nextProp: any) => any {
+ switch (typeName) {
+ // iOS Types
+ case 'CGColor':
+ case 'UIColor':
+ return processColor;
+ case 'CGColorArray':
+ case 'UIColorArray':
+ return processColorArray;
+ case 'CGImage':
+ case 'UIImage':
+ case 'RCTImageSource':
+ return resolveAssetSource;
+ // Android Types
+ case 'Color':
+ return processColor;
+ case 'ColorArray':
+ return processColorArray;
+ }
+ return null;
+}
+
+function processColorArray(
+ colors: ?Array,
+): ?Array(number | NativeOrDynamicColorType)> /* TODO(macOS ISS#2323203) */ {
+ // ]TODO(macOS ISS#2323203)
+ return colors == null ? null : colors.map(processColor);
+}
+
+module.exports = getNativeComponentAttributes;
diff --git a/vnext/src/Libraries/StyleSheet/StyleSheetTypes.windows.js b/vnext/src/Libraries/StyleSheet/StyleSheetTypes.windows.js
new file mode 100644
index 00000000000..3016b2facb8
--- /dev/null
+++ b/vnext/src/Libraries/StyleSheet/StyleSheetTypes.windows.js
@@ -0,0 +1,657 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+const AnimatedNode = require('../Animated/src/nodes/AnimatedNode');
+import type {NativeOrDynamicColorType} from '../Color/NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
+
+export type ColorValue = null | string | NativeOrDynamicColorType; // TODO(macOS ISS#2323203)
+export type DimensionValue = null | number | string | AnimatedNode;
+
+/**
+ * React Native's layout system is based on Flexbox and is powered both
+ * on iOS and Android by an open source project called `Yoga`:
+ * https://github.com/facebook/yoga
+ *
+ * The implementation in Yoga is slightly different from what the
+ * Flexbox spec defines - for example, we chose more sensible default
+ * values. Since our layout docs are generated from the comments in this
+ * file, please keep a brief comment describing each prop type.
+ *
+ * These properties are a subset of our styles that are consumed by the layout
+ * algorithm and affect the positioning and sizing of views.
+ */
+type ____LayoutStyle_Internal = $ReadOnly<{|
+ /** `display` sets the display type of this component.
+ *
+ * It works similarly to `display` in CSS, but only support 'flex' and 'none'.
+ * 'flex' is the default.
+ */
+ display?: 'none' | 'flex',
+
+ /** `width` sets the width of this component.
+ *
+ * It works similarly to `width` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/width for more details.
+ */
+ width?: DimensionValue,
+
+ /** `height` sets the height of this component.
+ *
+ * It works similarly to `height` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/height for more details.
+ */
+ height?: DimensionValue,
+
+ /** `bottom` is the number of logical pixels to offset the bottom edge of
+ * this component.
+ *
+ * It works similarly to `bottom` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/bottom
+ * for more details of how `bottom` affects layout.
+ */
+ bottom?: DimensionValue,
+
+ /**
+ * When the direction is `ltr`, `end` is equivalent to `right`.
+ * When the direction is `rtl`, `end` is equivalent to `left`.
+ *
+ * This style takes precedence over the `left` and `right` styles.
+ */
+ end?: DimensionValue,
+
+ /** `left` is the number of logical pixels to offset the left edge of
+ * this component.
+ *
+ * It works similarly to `left` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/left
+ * for more details of how `left` affects layout.
+ */
+ left?: DimensionValue,
+
+ /** `right` is the number of logical pixels to offset the right edge of
+ * this component.
+ *
+ * It works similarly to `right` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/right
+ * for more details of how `right` affects layout.
+ */
+ right?: DimensionValue,
+
+ /**
+ * When the direction is `ltr`, `start` is equivalent to `left`.
+ * When the direction is `rtl`, `start` is equivalent to `right`.
+ *
+ * This style takes precedence over the `left`, `right`, and `end` styles.
+ */
+ start?: DimensionValue,
+
+ /** `top` is the number of logical pixels to offset the top edge of
+ * this component.
+ *
+ * It works similarly to `top` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/top
+ * for more details of how `top` affects layout.
+ */
+ top?: DimensionValue,
+
+ /** `minWidth` is the minimum width for this component, in logical pixels.
+ *
+ * It works similarly to `min-width` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/min-width
+ * for more details.
+ */
+ minWidth?: DimensionValue,
+
+ /** `maxWidth` is the maximum width for this component, in logical pixels.
+ *
+ * It works similarly to `max-width` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/max-width
+ * for more details.
+ */
+ maxWidth?: DimensionValue,
+
+ /** `minHeight` is the minimum height for this component, in logical pixels.
+ *
+ * It works similarly to `min-height` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/min-height
+ * for more details.
+ */
+ minHeight?: DimensionValue,
+
+ /** `maxHeight` is the maximum height for this component, in logical pixels.
+ *
+ * It works similarly to `max-height` in CSS, but in React Native you
+ * must use points or percentages. Ems and other units are not supported.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/max-height
+ * for more details.
+ */
+ maxHeight?: DimensionValue,
+
+ /** Setting `margin` has the same effect as setting each of
+ * `marginTop`, `marginLeft`, `marginBottom`, and `marginRight`.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/margin
+ * for more details.
+ */
+ margin?: DimensionValue,
+
+ /** `marginBottom` works like `margin-bottom` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom
+ * for more details.
+ */
+ marginBottom?: DimensionValue,
+
+ /**
+ * When direction is `ltr`, `marginEnd` is equivalent to `marginRight`.
+ * When direction is `rtl`, `marginEnd` is equivalent to `marginLeft`.
+ */
+ marginEnd?: DimensionValue,
+
+ /** Setting `marginHorizontal` has the same effect as setting
+ * both `marginLeft` and `marginRight`.
+ */
+ marginHorizontal?: DimensionValue,
+
+ /** `marginLeft` works like `margin-left` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left
+ * for more details.
+ */
+ marginLeft?: DimensionValue,
+
+ /** `marginRight` works like `margin-right` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right
+ * for more details.
+ */
+ marginRight?: DimensionValue,
+
+ /**
+ * When direction is `ltr`, `marginStart` is equivalent to `marginLeft`.
+ * When direction is `rtl`, `marginStart` is equivalent to `marginRight`.
+ */
+ marginStart?: DimensionValue,
+
+ /** `marginTop` works like `margin-top` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top
+ * for more details.
+ */
+ marginTop?: DimensionValue,
+
+ /** Setting `marginVertical` has the same effect as setting both
+ * `marginTop` and `marginBottom`.
+ */
+ marginVertical?: DimensionValue,
+
+ /** Setting `padding` has the same effect as setting each of
+ * `paddingTop`, `paddingBottom`, `paddingLeft`, and `paddingRight`.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/padding
+ * for more details.
+ */
+ padding?: DimensionValue,
+
+ /** `paddingBottom` works like `padding-bottom` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom
+ * for more details.
+ */
+ paddingBottom?: DimensionValue,
+
+ /**
+ * When direction is `ltr`, `paddingEnd` is equivalent to `paddingRight`.
+ * When direction is `rtl`, `paddingEnd` is equivalent to `paddingLeft`.
+ */
+ paddingEnd?: DimensionValue,
+
+ /** Setting `paddingHorizontal` is like setting both of
+ * `paddingLeft` and `paddingRight`.
+ */
+ paddingHorizontal?: DimensionValue,
+
+ /** `paddingLeft` works like `padding-left` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left
+ * for more details.
+ */
+ paddingLeft?: DimensionValue,
+
+ /** `paddingRight` works like `padding-right` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right
+ * for more details.
+ */
+ paddingRight?: DimensionValue,
+
+ /**
+ * When direction is `ltr`, `paddingStart` is equivalent to `paddingLeft`.
+ * When direction is `rtl`, `paddingStart` is equivalent to `paddingRight`.
+ */
+ paddingStart?: DimensionValue,
+
+ /** `paddingTop` works like `padding-top` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top
+ * for more details.
+ */
+ paddingTop?: DimensionValue,
+
+ /** Setting `paddingVertical` is like setting both of
+ * `paddingTop` and `paddingBottom`.
+ */
+ paddingVertical?: DimensionValue,
+
+ /** `borderWidth` works like `border-width` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/border-width
+ * for more details.
+ */
+ borderWidth?: number,
+
+ /** `borderBottomWidth` works like `border-bottom-width` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width
+ * for more details.
+ */
+ borderBottomWidth?: number,
+
+ /**
+ * When direction is `ltr`, `borderEndWidth` is equivalent to `borderRightWidth`.
+ * When direction is `rtl`, `borderEndWidth` is equivalent to `borderLeftWidth`.
+ */
+ borderEndWidth?: number,
+
+ /** `borderLeftWidth` works like `border-left-width` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width
+ * for more details.
+ */
+ borderLeftWidth?: number,
+
+ /** `borderRightWidth` works like `border-right-width` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width
+ * for more details.
+ */
+ borderRightWidth?: number,
+
+ /**
+ * When direction is `ltr`, `borderStartWidth` is equivalent to `borderLeftWidth`.
+ * When direction is `rtl`, `borderStartWidth` is equivalent to `borderRightWidth`.
+ */
+ borderStartWidth?: number,
+
+ /** `borderTopWidth` works like `border-top-width` in CSS.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width
+ * for more details.
+ */
+ borderTopWidth?: number,
+
+ /** `position` in React Native is similar to regular CSS, but
+ * everything is set to `relative` by default, so `absolute`
+ * positioning is always just relative to the parent.
+ *
+ * If you want to position a child using specific numbers of logical
+ * pixels relative to its parent, set the child to have `absolute`
+ * position.
+ *
+ * If you want to position a child relative to something
+ * that is not its parent, just don't use styles for that. Use the
+ * component tree.
+ *
+ * See https://github.com/facebook/yoga
+ * for more details on how `position` differs between React Native
+ * and CSS.
+ */
+ position?: 'absolute' | 'relative',
+
+ /** `flexDirection` controls which directions children of a container go.
+ * `row` goes left to right, `column` goes top to bottom, and you may
+ * be able to guess what the other two do. It works like `flex-direction`
+ * in CSS, except the default is `column`.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction
+ * for more details.
+ */
+ flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse',
+
+ /** `flexWrap` controls whether children can wrap around after they
+ * hit the end of a flex container.
+ * It works like `flex-wrap` in CSS (default: nowrap).
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap
+ * for more details.
+ */
+ flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse',
+
+ /** `justifyContent` aligns children in the main direction.
+ * For example, if children are flowing vertically, `justifyContent`
+ * controls how they align vertically.
+ * It works like `justify-content` in CSS (default: flex-start).
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
+ * for more details.
+ */
+ justifyContent?:
+ | 'flex-start'
+ | 'flex-end'
+ | 'center'
+ | 'space-between'
+ | 'space-around'
+ | 'space-evenly',
+
+ /** `alignItems` aligns children in the cross direction.
+ * For example, if children are flowing vertically, `alignItems`
+ * controls how they align horizontally.
+ * It works like `align-items` in CSS (default: stretch).
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/align-items
+ * for more details.
+ */
+ alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline',
+
+ /** `alignSelf` controls how a child aligns in the cross direction,
+ * overriding the `alignItems` of the parent. It works like `align-self`
+ * in CSS (default: auto).
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/align-self
+ * for more details.
+ */
+ alignSelf?:
+ | 'auto'
+ | 'flex-start'
+ | 'flex-end'
+ | 'center'
+ | 'stretch'
+ | 'baseline',
+
+ /** `alignContent` controls how rows align in the cross direction,
+ * overriding the `alignContent` of the parent.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/align-content
+ * for more details.
+ */
+ alignContent?:
+ | 'flex-start'
+ | 'flex-end'
+ | 'center'
+ | 'stretch'
+ | 'space-between'
+ | 'space-around',
+
+ /** `overflow` controls how children are measured and displayed.
+ * `overflow: hidden` causes views to be clipped while `overflow: scroll`
+ * causes views to be measured independently of their parents main axis.
+ * It works like `overflow` in CSS (default: visible).
+ * See https://developer.mozilla.org/en/docs/Web/CSS/overflow
+ * for more details.
+ * `overflow: visible` only works on iOS. On Android, all views will clip
+ * their children.
+ */
+ overflow?: 'visible' | 'hidden' | 'scroll',
+
+ /** In React Native `flex` does not work the same way that it does in CSS.
+ * `flex` is a number rather than a string, and it works
+ * according to the `Yoga` library
+ * at https://github.com/facebook/yoga
+ *
+ * When `flex` is a positive number, it makes the component flexible
+ * and it will be sized proportional to its flex value. So a
+ * component with `flex` set to 2 will take twice the space as a
+ * component with `flex` set to 1.
+ *
+ * When `flex` is 0, the component is sized according to `width`
+ * and `height` and it is inflexible.
+ *
+ * When `flex` is -1, the component is normally sized according
+ * `width` and `height`. However, if there's not enough space,
+ * the component will shrink to its `minWidth` and `minHeight`.
+ *
+ * flexGrow, flexShrink, and flexBasis work the same as in CSS.
+ */
+ flex?: number,
+ flexGrow?: number,
+ flexShrink?: number,
+ flexBasis?: number | string,
+
+ /**
+ * Aspect ratio control the size of the undefined dimension of a node. Aspect ratio is a
+ * non-standard property only available in react native and not CSS.
+ *
+ * - On a node with a set width/height aspect ratio control the size of the unset dimension
+ * - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis
+ * if unset
+ * - On a node with a measure function aspect ratio works as though the measure function measures
+ * the flex basis
+ * - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis
+ * if unset
+ * - Aspect ratio takes min/max dimensions into account
+ */
+ aspectRatio?: number,
+
+ /** `zIndex` controls which components display on top of others.
+ * Normally, you don't use `zIndex`. Components render according to
+ * their order in the document tree, so later components draw over
+ * earlier ones. `zIndex` may be useful if you have animations or custom
+ * modal interfaces where you don't want this behavior.
+ *
+ * It works like the CSS `z-index` property - components with a larger
+ * `zIndex` will render on top. Think of the z-direction like it's
+ * pointing from the phone into your eyeball.
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/z-index for
+ * more details.
+ */
+ zIndex?: number,
+
+ /** `direction` specifies the directional flow of the user interface.
+ * The default is `inherit`, except for root node which will have
+ * value based on the current locale.
+ * See https://facebook.github.io/yoga/docs/rtl/
+ * for more details.
+ * @platform ios
+ */
+ direction?: 'inherit' | 'ltr' | 'rtl',
+|}>;
+
+type ____TransformStyle_Internal = $ReadOnly<{|
+ /**
+ * `transform` accepts an array of transformation objects. Each object specifies
+ * the property that will be transformed as the key, and the value to use in the
+ * transformation. Objects should not be combined. Use a single key/value pair
+ * per object.
+ *
+ * The rotate transformations require a string so that the transform may be
+ * expressed in degrees (deg) or radians (rad). For example:
+ *
+ * `transform([{ rotateX: '45deg' }, { rotateZ: '0.785398rad' }])`
+ *
+ * The skew transformations require a string so that the transform may be
+ * expressed in degrees (deg). For example:
+ *
+ * `transform([{ skewX: '45deg' }])`
+ */
+ transform?: $ReadOnlyArray<
+ | {|+perspective: number | AnimatedNode|}
+ | {|+rotate: string | AnimatedNode|}
+ | {|+rotateX: string | AnimatedNode|}
+ | {|+rotateY: string | AnimatedNode|}
+ | {|+rotateZ: string | AnimatedNode|}
+ | {|+scale: number | AnimatedNode|}
+ | {|+scaleX: number | AnimatedNode|}
+ | {|+scaleY: number | AnimatedNode|}
+ | {|+translateX: number | AnimatedNode|}
+ | {|+translateY: number | AnimatedNode|}
+ | {|
+ +translate:
+ | [number | AnimatedNode, number | AnimatedNode]
+ | AnimatedNode,
+ |}
+ | {|+skewX: string|}
+ | {|+skewY: string|}
+ // TODO: what is the actual type it expects?
+ | {|
+ +matrix: $ReadOnlyArray | AnimatedNode,
+ |},
+ >,
+|}>;
+
+/**
+ * These props can be used to dynamically generate shadows on views, images, text, etc.
+ *
+ * Because they are dynamically generated, they may cause performance regressions. Static
+ * shadow image asset may be a better way to go for optimal performance.
+ *
+ * These properties are iOS only - for similar functionality on Android, use the [`elevation`
+ * property](docs/viewstyleproptypes.html#elevation).
+ */
+export type ____ShadowStyle_Internal = $ReadOnly<{|
+ /**
+ * Sets the drop shadow color
+ * @platform ios
+ */
+ shadowColor?: ColorValue,
+ /**
+ * Sets the drop shadow offset
+ * @platform ios
+ */
+ shadowOffset?: $ReadOnly<{|
+ width?: number,
+ height?: number,
+ |}>,
+ /**
+ * Sets the drop shadow opacity (multiplied by the color's alpha component)
+ * @platform ios
+ */
+ shadowOpacity?: number | AnimatedNode,
+ /**
+ * Sets the drop shadow blur radius
+ * @platform ios
+ */
+ shadowRadius?: number,
+|}>;
+
+export type ____ViewStyle_Internal = $ReadOnly<{|
+ ...$Exact<____LayoutStyle_Internal>,
+ ...$Exact<____ShadowStyle_Internal>,
+ ...$Exact<____TransformStyle_Internal>,
+ backfaceVisibility?: 'visible' | 'hidden',
+ backgroundColor?: ColorValue,
+ borderColor?: ColorValue,
+ borderBottomColor?: ColorValue,
+ borderEndColor?: ColorValue,
+ borderLeftColor?: ColorValue,
+ borderRightColor?: ColorValue,
+ borderStartColor?: ColorValue,
+ borderTopColor?: ColorValue,
+ borderRadius?: number | AnimatedNode,
+ borderBottomEndRadius?: number | AnimatedNode,
+ borderBottomLeftRadius?: number | AnimatedNode,
+ borderBottomRightRadius?: number | AnimatedNode,
+ borderBottomStartRadius?: number | AnimatedNode,
+ borderTopEndRadius?: number | AnimatedNode,
+ borderTopLeftRadius?: number | AnimatedNode,
+ borderTopRightRadius?: number | AnimatedNode,
+ borderTopStartRadius?: number | AnimatedNode,
+ borderStyle?: 'solid' | 'dotted' | 'dashed',
+ borderWidth?: number | AnimatedNode,
+ borderBottomWidth?: number | AnimatedNode,
+ borderEndWidth?: number | AnimatedNode,
+ borderLeftWidth?: number | AnimatedNode,
+ borderRightWidth?: number | AnimatedNode,
+ borderStartWidth?: number | AnimatedNode,
+ borderTopWidth?: number | AnimatedNode,
+ opacity?: number | AnimatedNode,
+ elevation?: number,
+|}>;
+
+export type ____TextStyle_Internal = $ReadOnly<{|
+ ...$Exact<____ViewStyle_Internal>,
+ color?: ColorValue,
+ fontFamily?: string,
+ fontSize?: number,
+ fontStyle?: 'normal' | 'italic',
+ fontWeight?:
+ | 'normal'
+ | 'bold'
+ | '100'
+ | '200'
+ | '300'
+ | '400'
+ | '500'
+ | '600'
+ | '700'
+ | '800'
+ | '900',
+ fontVariant?: $ReadOnlyArray<
+ | 'small-caps'
+ | 'oldstyle-nums'
+ | 'lining-nums'
+ | 'tabular-nums'
+ | 'proportional-nums',
+ >,
+ textShadowOffset?: $ReadOnly<{|
+ width: number,
+ height: number,
+ |}>,
+ textShadowRadius?: number,
+ textShadowColor?: ColorValue,
+ letterSpacing?: number,
+ lineHeight?: number,
+ textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify',
+ textAlignVertical?: 'auto' | 'top' | 'bottom' | 'center',
+ includeFontPadding?: boolean,
+ textDecorationLine?:
+ | 'none'
+ | 'underline'
+ | 'line-through'
+ | 'underline line-through',
+ textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed',
+ textDecorationColor?: ColorValue,
+ textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase',
+ writingDirection?: 'auto' | 'ltr' | 'rtl',
+|}>;
+
+export type ____ImageStyle_Internal = $ReadOnly<{|
+ ...$Exact<____ViewStyle_Internal>,
+ resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat',
+ tintColor?: ColorValue,
+ overlayColor?: string,
+|}>;
+
+export type ____DangerouslyImpreciseStyle_Internal = {
+ ...$Exact<____TextStyle_Internal>,
+ +resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat',
+ +tintColor?: ColorValue,
+ +overlayColor?: string,
+};
+
+type GenericStyleProp<+T> =
+ | null
+ | void
+ | T
+ | false
+ | ''
+ | $ReadOnlyArray>;
+
+export type ____DangerouslyImpreciseStyleProp_Internal = GenericStyleProp<
+ $Shape<____DangerouslyImpreciseStyle_Internal>,
+>;
+export type ____ViewStyleProp_Internal = GenericStyleProp<
+ $ReadOnly<$Shape<____ViewStyle_Internal>>,
+>;
+export type ____TextStyleProp_Internal = GenericStyleProp<
+ $ReadOnly<$Shape<____TextStyle_Internal>>,
+>;
+export type ____ImageStyleProp_Internal = GenericStyleProp<
+ $ReadOnly<$Shape<____ImageStyle_Internal>>,
+>;
+
+export type ____Styles_Internal = {
+ +[key: string]: $Shape<____DangerouslyImpreciseStyle_Internal>,
+};
diff --git a/vnext/src/Libraries/StyleSheet/processColor.windows.js b/vnext/src/Libraries/StyleSheet/processColor.windows.js
new file mode 100644
index 00000000000..4589713f622
--- /dev/null
+++ b/vnext/src/Libraries/StyleSheet/processColor.windows.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ *
+ * @format
+ * @flow strict-local
+ */
+
+'use strict';
+
+const Platform = require('../Utilities/Platform');
+
+const normalizeColor = require('../Color/normalizeColor');
+import type {NativeOrDynamicColorType} from '../Color/NativeOrDynamicColorType'; // ]TODO(macOS ISS#2323203)
+
+/* eslint no-bitwise: 0 */
+function processColor(
+ color?: ?(string | number | NativeOrDynamicColorType),
+): ?(number | NativeOrDynamicColorType) /* TODO(macOS ISS#2323203) */ {
+ if (color === undefined || color === null) {
+ return color;
+ }
+
+ let int32Color = normalizeColor(color);
+ if (int32Color === null || int32Color === undefined) {
+ return undefined;
+ }
+
+ if (typeof int32Color === 'object') {
+ const processColorObject = require('processColorObject'); // TODO(macOS ISS#2323203)
+
+ const processedColorObj = processColorObject(int32Color);
+
+ if (processedColorObj !== null) {
+ return processedColorObj;
+ }
+ }
+
+ if (typeof int32Color !== 'number') {
+ return null;
+ } // ]TODO(macOS ISS#2323203)
+
+ // Converts 0xrrggbbaa into 0xaarrggbb
+ int32Color = ((int32Color << 24) | (int32Color >>> 8)) >>> 0;
+
+ if (Platform.OS === 'android') {
+ // Android use 32 bit *signed* integer to represent the color
+ // We utilize the fact that bitwise operations in JS also operates on
+ // signed 32 bit integers, so that we can use those to convert from
+ // *unsigned* to *signed* 32bit int that way.
+ int32Color = int32Color | 0x0;
+ }
+ return int32Color;
+}
+
+module.exports = processColor;
diff --git a/vnext/src/RNTester/RNTesterList.windows.ts b/vnext/src/RNTester/RNTesterList.windows.ts
index 143f0dc176a..e09814c2ccb 100644
--- a/vnext/src/RNTester/RNTesterList.windows.ts
+++ b/vnext/src/RNTester/RNTesterList.windows.ts
@@ -215,6 +215,10 @@ const APIExamples: Array = [
key: 'ThemingExample',
module: require('./ThemingExample'),
},
+ {
+ key: 'WindowsBrushExample',
+ module: require('./WindowsBrushExample'),
+ },
{
key: 'TransformExample',
module: require('react-native/RNTester/js/TransformExample'),
diff --git a/vnext/src/RNTester/WindowsBrushExample.windows.tsx b/vnext/src/RNTester/WindowsBrushExample.windows.tsx
new file mode 100644
index 00000000000..a3b325cd245
--- /dev/null
+++ b/vnext/src/RNTester/WindowsBrushExample.windows.tsx
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License.
+ * @format
+ */
+
+import React = require('react');
+import {Text, View, Button} from 'react-native';
+
+class WindowsBrushExample extends React.Component {
+ _onPress = () => {};
+
+ public render() {
+ return (
+
+
+ Sample Text
+
+
+
+ );
+ }
+}
+
+export const displayName = (_undefined?: string) => {};
+export const title = 'WindowsBrush';
+export const description = 'Usage of windowsbrush for color props';
+export const examples = [
+ {
+ title: 'WindowsBrush control',
+ render: function(): JSX.Element {
+ return ;
+ },
+ },
+];