diff --git a/change/@office-iss-react-native-win32-2019-12-20-11-19-05-win32defork.json b/change/@office-iss-react-native-win32-2019-12-20-11-19-05-win32defork.json new file mode 100644 index 00000000000..1dbfdc2b4de --- /dev/null +++ b/change/@office-iss-react-native-win32-2019-12-20-11-19-05-win32defork.json @@ -0,0 +1,8 @@ +{ + "type": "patch", + "comment": "Remove remaining need for fork of RN for win32 JS", + "packageName": "@office-iss/react-native-win32", + "email": "acoates@microsoft.com", + "commit": "b17624cd44d682c73db5ae17a3d10c8bed07c5f8", + "date": "2019-12-20T19:19:05.418Z" +} \ No newline at end of file diff --git a/change/react-native-windows-2019-12-20-15-20-03-win32defork.json b/change/react-native-windows-2019-12-20-15-20-03-win32defork.json new file mode 100644 index 00000000000..2462198aaf3 --- /dev/null +++ b/change/react-native-windows-2019-12-20-15-20-03-win32defork.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Fix RNTester bundle (#2728)", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "commit": "65167fb5e52f042879d00891e89ed951bdda84bc", + "date": "2019-12-20T23:20:03.026Z" +} \ No newline at end of file diff --git a/packages/react-native-win32/.flowconfig b/packages/react-native-win32/.flowconfig new file mode 100644 index 00000000000..1a7db771dee --- /dev/null +++ b/packages/react-native-win32/.flowconfig @@ -0,0 +1,158 @@ +[ignore] +; We fork some components by platform - ignore all platforms except win32 +.*/*[.]android.js +.*/*[.]ios.js +.*/*[.]macos.js +.*/*[.]windesktop.js + +; These modules have base components and win32 versions. +; Ideally we'd delete the base versions of files that had .win32 overrides as part of the +; initRNLibraries build step +/Libraries/Alert/Alert.js +/Libraries/Color/normalizeColor.js +/Libraries/Color/normalizeColorObject.js +/Libraries/Color/NativeOrDynamicColorType.js +/Libraries/Components/SafeAreaView/SafeAreaView.js +/Libraries/Components/StatusBar/StatusBar.js +/Libraries/Components/TextInput/TextInput.js +/Libraries/Components/TextInput/TextInputState.js +/Libraries/Components/Touchable/TouchableNativeFeedback.js +/Libraries/Components/View/ReactNativeViewAttributes.js +/Libraries/Image/Image.js +/Libraries/Inspector/Inspector.js +/Libraries/Inspector/InspectorOverlay.js +/Libraries/Network/RCTNetworking.js +/Libraries/StyleSheet/StyleSheet.js +/Libraries/Utilities/DeviceInfo.js +/Libraries/Utilities/Dimensions.js +/Libraries/YellowBox/UI/YellowBoxInspectorHeader.js +/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.js +/Libraries/YellowBox/UI/YellowBoxList.js +; This example currently uses mac dynamic colors +/RNTester/js/ActivityIndicatorExample.js +; This example currently uses mac dynamic colors +/RNTester/js/DarkModeExample.js + + +; Ignore react-native files in node_modules since they are copied into project root +.*/node_modules/react-native/.* + +; These files dont need to be checked and just increase the build time +.*/node_modules/microsoft-reactnative-sampleapps/.* + +; Ignore templates for 'react-native init' +/template/.* + +; Ignore the Dangerfile +/bots/dangerfile.js + +; Ignore "BUCK" generated dirs +/\.buckd/ + +; Ignore unexpected extra "@providesModule" +.*/node_modules/.*/node_modules/fbjs/.* + +; Ignore duplicate module providers +; For RN Apps installed via npm, "Libraries" folder is inside +; "node_modules/react-native" but in the source repo it is in the root +.*/Libraries/react-native/React.js + +; Ignore polyfills +.*/Libraries/polyfills/.* + +; These should not be required directly +; require from fbjs/lib instead: require('fbjs/lib/warning') +.*/node_modules/warning/.* + +; Flow doesn't support platforms +.*/Libraries/Utilities/HMRLoadingView.js + +; Ignore the src folder - flow files are combined with ones from react-native into the root Libraries folder +.*/react-native-win32/src/.* + +[untyped] +.*/node_modules/@react-native-community/cli/.*/.* +; Should work out how to do this properly +.*/react-native-win32/Libraries/Image/resolveAssetSource.win32.js + +[include] +; Need to include hoisted modules +../../node_modules/ + +[libs] +Libraries/react-native/react-native-interface.js +flow/ + +[options] +emoji=true + +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable + +module.file_ext=.js +module.file_ext=.json +module.file_ext=.win32.js + +module.system=haste +module.system.haste.use_name_reducers=true +# keep the following in sync with server/haste/hasteImpl.js +# get basename +module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' +# strip .js or .js.flow suffix +module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' +# strip .ios suffix +module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.macos$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.win32$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.windesktop$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' +module.system.haste.paths.blacklist=/src/.* +module.system.haste.paths.blacklist=.*/__tests__/.* +module.system.haste.paths.blacklist=.*/__mocks__/.* +module.system.haste.paths.whitelist=/Libraries/.* +module.system.haste.paths.whitelist=/RNTester/.* +module.system.haste.paths.whitelist=/IntegrationTests/.* +module.system.haste.paths.blacklist=/Libraries/react-native/react-native-implementation.js +module.system.haste.paths.blacklist=/Libraries/Animated/src/polyfills/.* +module.system.haste.paths.blacklist=/Libraries/Image/resolveAssetSource.js + +munge_underscores=true + +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' +module.name_mapper='react-native$' -> '/Libraries/react-native/react-native-implementation.js' +module.name_mapper='react-native/\(.*\)' -> '/\1' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState + +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError + +[lints] +sketchy-null-number=warn +sketchy-null-mixed=warn +sketchy-number=warn +untyped-type-import=warn +nonstrict-import=warn +deprecated-type=warn +unsafe-getters-setters=warn +inexact-spread=warn +unnecessary-invariant=warn +signature-verification-failure=warn +deprecated-utility=error + +[strict] +deprecated-type +nonstrict-import +sketchy-null +unclear-type +unsafe-getters-setters +untyped-import +untyped-type-import + +[version] +^0.98.0 \ No newline at end of file diff --git a/packages/react-native-win32/.gitignore b/packages/react-native-win32/.gitignore index a05f096b923..d1d45db75a4 100644 --- a/packages/react-native-win32/.gitignore +++ b/packages/react-native-win32/.gitignore @@ -1,5 +1,7 @@ /demo /dist +/flow +/flow-typed /index.* /IntegrationTests /jest diff --git a/packages/react-native-win32/just-task.js b/packages/react-native-win32/just-task.js index 70d78a0e3a9..5cded4f0ba9 100644 --- a/packages/react-native-win32/just-task.js +++ b/packages/react-native-win32/just-task.js @@ -47,7 +47,11 @@ task('copyPngFiles', () => { return copyTask(['src/**/*.png'], '.'); }); task('initRNLibraries', () => { - require('./scripts/copyRNLibraries').copyRNLibraries(); + require('../../vnext/scripts/copyRNLibraries').copyRNLibraries(__dirname); +}); + +task('flow-check', () => { + require('child_process').execSync('npx flow check', {stdio: 'inherit'}); }); task('ts', () => { @@ -63,8 +67,8 @@ task('ts', () => { }); task('clean', () => { return cleanTask( - ['jest', 'Libraries', 'RNTester', 'lib'].map(p => - path.join(process.cwd(), p), + ['dist', 'flow', 'flow-typed', 'jest', 'Libraries', 'RNTester', 'lib'].map( + p => path.join(process.cwd(), p), ), ); }); @@ -95,6 +99,7 @@ task( // trickle // react-test 'ts', + 'flow-check', condition('apiExtractorVerify', () => argv().ci), 'apiExtractorUpdate', 'apiDocumenter', diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json index 57468030272..711b9f5999b 100644 --- a/packages/react-native-win32/package.json +++ b/packages/react-native-win32/package.json @@ -6,16 +6,17 @@ "typings": "./Libraries/react-native/typings-main.d.ts", "scripts": { "build": "just-scripts build", + "bundle": "just-scripts prepareBundle && react-native bundle --platform win32 --entry-file RNTester.js --bundle-output dist/win32/dev/RNTester.bundle --assets-dest dist/win32/dev", "change": "beachball change", "clean": "just-scripts clean", - "start": "react-native start", - "lint": "just-scripts eslint", + "flow-check": "flow check", "lint:fix": "eslint ./**/*.js ./**/*.ts? --fix", - "watch": "tsc -w", - "bundle": "just-scripts prepareBundle && react-native bundle --platform win32 --entry-file RNTester.js --bundle-output dist/win32/dev/RNTester.bundle --assets-dest dist/win32/dev", - "run-win32": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev", + "lint": "just-scripts eslint", + "run-win32-dev-web": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev --useWebDebugger", "run-win32-devmain": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev --useDevMain", - "run-win32-dev-web": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev --useWebDebugger" + "run-win32": "rex-win32 --bundle RNTester --component RNTesterApp --basePath ./dist/win32/dev", + "start": "react-native start", + "watch": "tsc -w" }, "dependencies": { "@babel/runtime": "^7.4.0", @@ -40,15 +41,17 @@ "whatwg-fetch": "^3.0.0" }, "devDependencies": { - "react-native": "https://github.com/microsoft/react-native/archive/v0.60.0-microsoft.31.tar.gz", "@office-iss/rex-win32": "0.0.30", "@types/es6-collections": "^0.5.29", "@types/es6-promise": "0.0.32", "@types/node": "^12.11.2", "@types/prop-types": "15.5.1", - "@types/react": "16.9.11", "@types/react-native": "~0.60.5", + "@types/react": "16.9.11", + "flow-bin": "^0.98.0", + "jscodeshift": "^0.6.2", "just-scripts": "^0.24.2", + "react-native": "https://github.com/microsoft/react-native/archive/v0.60.0-microsoft.31.tar.gz", "react": "16.8.6", "rimraf": "^3.0.0" }, diff --git a/packages/react-native-win32/scripts/copyRNLibraries.js b/packages/react-native-win32/scripts/copyRNLibraries.js deleted file mode 100644 index c0ece716381..00000000000 --- a/packages/react-native-win32/scripts/copyRNLibraries.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @format - */ -// @ts-check -const path = require('path'); -const fs = require('fs'); -const rimraf = require('rimraf'); - -function copyFileSync(source, target) { - var targetFile = target; - - //if target is a directory a new file with the same name will be created - if (fs.existsSync(target)) { - if (fs.lstatSync(target).isDirectory()) { - targetFile = path.join(target, path.basename(source)); - } - } - - fs.writeFileSync(targetFile, fs.readFileSync(source)); -} - -function copyJSFolderRecursiveSync(source, target) { - var files = []; - - //check if folder needs to be created or integrated - var targetFolder = path.join(target, path.basename(source)); - if (!fs.existsSync(targetFolder)) { - fs.mkdirSync(targetFolder); - } - - //copy - if (fs.lstatSync(source).isDirectory()) { - files = fs.readdirSync(source); - files.forEach(function(file) { - var curSource = path.join(source, file); - if (fs.lstatSync(curSource).isDirectory()) { - copyJSFolderRecursiveSync(curSource, targetFolder); - } else { - if ( - curSource.endsWith('.js') || - curSource.endsWith('.png') || - curSource.endsWith('.gif') - ) { - copyFileSync(curSource, targetFolder); - } - } - }); - } -} - -exports.copyRNLibraries = () => { - const rnPath = path.dirname(require.resolve('react-native/package.json')); - - const integrationTestsDest = path.resolve(__dirname, '../IntegrationTests'); - if (fs.existsSync(integrationTestsDest)) { - rimraf.sync(integrationTestsDest + path.sep + '*.js'); - } - const librariesDest = path.resolve(__dirname, '../Libraries'); - if (fs.existsSync(librariesDest)) { - rimraf.sync(librariesDest); - } - const jestDest = path.resolve(__dirname, '../jest'); - if (fs.existsSync(jestDest)) { - rimraf.sync(jestDest); - } - const rnTesterDest = path.resolve(__dirname, '../RNTester'); - if (fs.existsSync(rnTesterDest)) { - rimraf.sync(rnTesterDest); - } - const baseDir = path.resolve(__dirname, '..'); - if (fs.existsSync(path.resolve(rnPath, 'IntegrationTests'))) { - copyJSFolderRecursiveSync( - path.resolve(rnPath, 'IntegrationTests'), - baseDir, - ); - } - copyJSFolderRecursiveSync(path.resolve(rnPath, 'Libraries'), baseDir); - copyJSFolderRecursiveSync(path.resolve(rnPath, 'jest'), baseDir); - copyJSFolderRecursiveSync(path.resolve(baseDir, 'src/jest'), baseDir); // Copy js files from src/jest to jest - - fs.writeFileSync( - path.resolve(__dirname, '../rn-get-polyfills.js'), - fs.readFileSync(path.resolve(rnPath, 'rn-get-polyfills.js')), - ); - - if (fs.existsSync(path.resolve(rnPath, 'RNTester'))) { - copyJSFolderRecursiveSync(path.resolve(rnPath, 'RNTester'), baseDir); - } - - /* - if (!fs.existsSync(path.resolve(__dirname, '../lib/local-cli'))) { - fs.mkdirSync(path.resolve(__dirname, '../lib/local-cli')); - } - if (!fs.existsSync(path.resolve(__dirname, '../lib/local-cli/bundle'))) { - fs.mkdirSync(path.resolve(__dirname, '../lib/local-cli/bundle')); - } - */ -}; diff --git a/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js b/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js new file mode 100644 index 00000000000..aa1763c4629 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @flow + * @format + */ +'use strict'; + +const NativeModules = require('../BatchedBridge/NativeModules'); +const PLYAlertManager = NativeModules.PLYAlertManager; + +export type Buttons = Array<{ + text?: string, + onPress?: ?Function, + style?: AlertButtonStyle, +}>; + +type Options = { + cancelable?: ?boolean, + onDismiss?: ?Function, +}; + +export type AlertType = $Keys<{ + default: string, + 'plain-text': string, + 'secure-text': string, + 'login-password': string, +}>; + +export type AlertButtonStyle = $Keys<{ + default: string, + cancel: string, + destructive: string, +}>; + +class Alert { + static alert( + title: ?string, + message?: ?string, + buttons?: Buttons, + options?: Options, + ): void { + PLYAlertManager.showAlert( + title || '', + message || '', + buttons, + options, + buttonIndex => { + if ( + buttonIndex >= 0 && + buttons && + buttonIndex < buttons.length && + buttons[buttonIndex].onPress + ) { + buttons[buttonIndex].onPress(); + } + + if ( + options && + options.onDismiss && + buttonIndex === -1 && + options.onDismiss + ) { + options.onDismiss(); + } + }, + ); + } + + static prompt( + title: ?string, + message?: ?string, + callbackOrButtons?: ?(((text: string) => void) | Buttons), + type?: ?AlertType = 'plain-text', + defaultValue?: string, + keyboardType?: string, + ): void { + throw new Error( + 'Alert.prompt not currently implemented in react-native-win32', + ); + } +} + +module.exports = Alert; diff --git a/packages/react-native-win32/src/Libraries/Color/NativeOrDynamicColorType.win32.js b/packages/react-native-win32/src/Libraries/Color/NativeOrDynamicColorType.win32.js new file mode 100644 index 00000000000..031657e2eab --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Color/NativeOrDynamicColorType.win32.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * @format + * @flow strict + */ + +'use strict'; + +export type ColorStop = { + color: string | number | NativeOrDynamicColorType, + offset: number, +}; + +export type NativeOrDynamicColorType = { + gradientDirection: string, + colorStops: Array, +}; diff --git a/packages/react-native-win32/src/Libraries/Color/normalizeColor.win32.js b/packages/react-native-win32/src/Libraries/Color/normalizeColor.win32.js new file mode 100644 index 00000000000..8aecb3defc2 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Color/normalizeColor.win32.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/packages/react-native-win32/src/Libraries/Color/normalizeColorObject.win32.js b/packages/react-native-win32/src/Libraries/Color/normalizeColorObject.win32.js index 52138078109..207f6ef69cf 100644 --- a/packages/react-native-win32/src/Libraries/Color/normalizeColorObject.win32.js +++ b/packages/react-native-win32/src/Libraries/Color/normalizeColorObject.win32.js @@ -4,48 +4,54 @@ * @format * @flow */ -// [TODO(macOS ISS#2323203) 'use strict'; const invariant = require('invariant'); -const normalizeColor = require('normalizeColor'); +const normalizeColor = require('./normalizeColor'); -export type NativeOrDynamicColorType = IGradientColorType; +import type {NativeOrDynamicColorType} from './NativeOrDynamicColorType'; -export interface IColorStop { - color: string | number | NativeOrDynamicColorType; - offset: number; -} - -export interface IGradientColorType { - gradientDirection: string; - colorStops: Array; -} - -function normalizeColorObject(color?: IGradientColorType) { +function normalizeColorObject( + color: NativeOrDynamicColorType, +): ?NativeOrDynamicColorType { if (color && typeof color === 'object') { - if (color.hasOwnProperty('colorStops') && color.hasOwnProperty('gradientDirection')) { - invariant(color.colorStops.length >= 2, 'Gradients must contain at least two colors.'); + if ( + color.hasOwnProperty('colorStops') && + color.hasOwnProperty('gradientDirection') + ) { + invariant( + color.colorStops.length >= 2, + 'Gradients must contain at least two colors.', + ); invariant( color.gradientDirection === 'ToTop' || color.gradientDirection === 'ToBottom' || color.gradientDirection === 'ToLeft' || color.gradientDirection === 'ToRight', - 'Unsupported gradient direction; currently supports ToTop, ToBottom, ToLeft, and ToRight.' + 'Unsupported gradient direction; currently supports ToTop, ToBottom, ToLeft, and ToRight.', ); - const gradientColorStops: Array = []; - color.colorStops.forEach((colorStop: IColorStop) => { - gradientColorStops.push({ - color: normalizeColor(colorStop.color), - offset: colorStop.offset - }); - }); + const gradientColorStops: Array<{ + color: string | number | NativeOrDynamicColorType, + offset: number, + }> = []; + color.colorStops.forEach( + (colorStop: { + color: string | number | NativeOrDynamicColorType, + offset: number, + }) => { + gradientColorStops.push({ + // $FlowFixMe + color: normalizeColor(colorStop.color), + offset: colorStop.offset, + }); + }, + ); return { gradientDirection: color.gradientDirection, - colorStops: gradientColorStops + colorStops: gradientColorStops, }; } } @@ -54,4 +60,3 @@ function normalizeColorObject(color?: IGradientColorType) { } module.exports = normalizeColorObject; -// ]TODO(macOS ISS#2323203) diff --git a/packages/react-native-win32/src/Libraries/Components/AppleTV/TVEventHandler.win32.ts b/packages/react-native-win32/src/Libraries/Components/AppleTV/TVEventHandler.win32.ts deleted file mode 100644 index 6bdf9e0cd5d..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/AppleTV/TVEventHandler.win32.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @providesModule TVEventHandler - * @flow - */ -'use strict'; - -/* tslint:disable:no-any */ -/* tslint:disable:no-empty */ -/* tslint:disable:no-function-expression */ - -class TVEventHandler { - public enable(component: any, callback: any) {} - - public disable() {} -} - -export = TVEventHandler; diff --git a/packages/react-native-win32/src/Libraries/Components/DatePicker/DatePickerIOS.win32.js b/packages/react-native-win32/src/Libraries/Components/DatePicker/DatePickerIOS.win32.js new file mode 100644 index 00000000000..1a86a7a9072 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/DatePicker/DatePickerIOS.win32.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +'use strict'; + +module.exports = require('UnimplementedView'); diff --git a/packages/react-native-win32/src/Libraries/Components/DatePickerAndroid/DatePickerAndroid.win32.js b/packages/react-native-win32/src/Libraries/Components/DatePickerAndroid/DatePickerAndroid.win32.js new file mode 100644 index 00000000000..1a86a7a9072 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/DatePickerAndroid/DatePickerAndroid.win32.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +'use strict'; + +module.exports = require('UnimplementedView'); diff --git a/packages/react-native-win32/src/Libraries/Components/EnterString.win32.tsx b/packages/react-native-win32/src/Libraries/Components/EnterString.win32.tsx index 67c4bd17f17..242ff22c3a1 100644 --- a/packages/react-native-win32/src/Libraries/Components/EnterString.win32.tsx +++ b/packages/react-native-win32/src/Libraries/Components/EnterString.win32.tsx @@ -1,6 +1,5 @@ /** * @providesModule EnterString - * @flow */ 'use strict'; @@ -72,14 +71,14 @@ class EnterStringNative extends React.Component { /** * Callback when text is changed */ - onChanged: PropTypes.func + onChanged: PropTypes.func, }; public static DefaultProps: IEnterStringNativeProps = { disabled: false, value: '', label: '', - onChanged: null + onChanged: null, }; public render() { @@ -94,7 +93,7 @@ export default class EnterString extends React.Component disabled: false, value: '', label: '', - onChanged: null + onChanged: null, }; public render() { diff --git a/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js b/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js new file mode 100644 index 00000000000..1a86a7a9072 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +'use strict'; + +module.exports = require('UnimplementedView'); diff --git a/packages/react-native-win32/src/Libraries/Components/ProgressViewIOS/ProgressViewIOS.win32.js b/packages/react-native-win32/src/Libraries/Components/ProgressViewIOS/ProgressViewIOS.win32.js new file mode 100644 index 00000000000..1a86a7a9072 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/ProgressViewIOS/ProgressViewIOS.win32.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +'use strict'; + +module.exports = require('UnimplementedView'); diff --git a/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js b/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js new file mode 100644 index 00000000000..25db723d470 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js @@ -0,0 +1,68 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @flow + * @format + */ + +const Platform = require('../../Utilities/Platform'); +const React = require('react'); +const View = require('../View/View'); + +import type {ViewProps} from '../View/ViewPropTypes'; +import type {NativeComponent} from '../../Renderer/shims/ReactNative'; + +type Props = $ReadOnly<{| + ...ViewProps, + emulateUnlessSupported?: boolean, +|}>; + +let exported; + +/** + * Renders nested content and automatically applies paddings reflect the portion + * of the view that is not covered by navigation bars, tab bars, toolbars, and + * other ancestor views. + * + * Moreover, and most importantly, Safe Area's paddings reflect physical + * limitation of the screen, such as rounded corners or camera notches (aka + * sensor housing area on iPhone X). + */ +// [Win32 - Added win32 to if +if (Platform.OS === 'android' || Platform.OS === 'win32') { + // Win32] + const SafeAreaView = ( + props: Props, + forwardedRef?: ?React.Ref, + ) => { + const {emulateUnlessSupported, ...localProps} = props; + return ; + }; + + const SafeAreaViewRef = React.forwardRef(SafeAreaView); + SafeAreaViewRef.displayName = 'SafeAreaView'; + exported = ((SafeAreaViewRef: any): Class>); +} else { + const RCTSafeAreaViewNativeComponent = require('./RCTSafeAreaViewNativeComponent'); + + const SafeAreaView = ( + props: Props, + forwardedRef?: ?React.Ref, + ) => { + return ( + + ); + }; + + const SafeAreaViewRef = React.forwardRef(SafeAreaView); + SafeAreaViewRef.displayName = 'SafeAreaView'; + exported = ((SafeAreaViewRef: any): Class>); +} + +module.exports = exported; diff --git a/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollView.win32.tsx b/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollView.win32.tsx deleted file mode 100644 index 8d4fb026cea..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollView.win32.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @providesModule ScrollView - */ -'use strict'; - -import * as React from 'react'; -import { requireNativeComponent, NativeModules, StyleSheet, findNodeHandle, View, StyleProp, ViewStyle } from 'react-native'; -import { IScrollViewProps, IScrollViewState } from './ScrollViewTypes'; - -const RCTScrollView = requireNativeComponent('RCTScrollView'); - -class ScrollView extends React.Component { - private styles = StyleSheet.create({ - contentContainerStyleHorizontal: { - flexDirection: 'row' - } - }); - - constructor(props: IScrollViewProps) { - super(props); - this._handleContentOnLayout = this._handleContentOnLayout.bind(this); - } - - // to properly handle contentContainerStyle and onContentSizeChange - // all children will get thrown inside a View that is a child of the RCTScrollView - // this is more in line with the React Native ScrollView implementation for Android and IOS - public render() { - const containerStyle: StyleProp = [ - this.props.contentContainerStyle, - this.props.horizontal && this.styles.contentContainerStyleHorizontal - ]; - return ( - - - { this.props.children } - - - ); - } - - public scrollToEnd() { - NativeModules.UIManager.dispatchViewManagerCommand( - findNodeHandle(this), - NativeModules.UIManager.RCTScrollView.Commands.ScrollToEnd, - null - ); - } - - public scrollTo(offsets) { - NativeModules.UIManager.dispatchViewManagerCommand(findNodeHandle(this), NativeModules.UIManager.RCTScrollView.Commands.ScrollTo, [ - offsets.x || 0, - offsets.y || 0, - false /*animation not supported*/ - ]); - } - - private _handleContentOnLayout(e: INativeContainerOnLayoutEventArgs) { - const { width, height } = e.nativeEvent.layout; - this.props.onContentSizeChange && this.props.onContentSizeChange(width, height); - } -} - -/* subset of what will actually be passed back from native side */ -interface INativeContainerOnLayoutEventArgs { - nativeEvent: { layout: { width: number; height: number; x: number; y: number } }; -} - -export = ScrollView; diff --git a/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollViewTypes.ts b/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollViewTypes.ts deleted file mode 100644 index 9bf8f6a8bde..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollViewTypes.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ScrollViewProps } from 'react-native'; - -export interface IScrollViewProps extends ScrollViewProps {} - -export interface IScrollViewState {} diff --git a/packages/react-native-win32/src/Libraries/Components/TextInput/Tests/TextInputTest.tsx b/packages/react-native-win32/src/Libraries/Components/TextInput/Tests/TextInputTest.tsx index 29b911dc130..ac60313374f 100644 --- a/packages/react-native-win32/src/Libraries/Components/TextInput/Tests/TextInputTest.tsx +++ b/packages/react-native-win32/src/Libraries/Components/TextInput/Tests/TextInputTest.tsx @@ -1,6 +1,5 @@ 'use strict'; import * as React from 'react'; -import { IRNTesterPage } from 'src/RNTester/RNTester.types'; import { StyleSheet, Text, TextInput, View } from 'react-native'; // Disabling no-jsx-lambda so functional components are more convenient to use @@ -38,7 +37,7 @@ const PlaceholderTextInputTest: React.FC<{}> = () => { const ControllingTextInputTest: React.FC<{}> = () => { const [value, setValue] = React.useState(''); - return( + return ( This TextInput inserts spaces between characters = () => { const BlurringAndFocusingTextInputTest: React.FC<{}> = () => { const [isFocused, setIsFocused] = React.useState(false); - return( + return ( This TextInput is currently focused: + {isFocused ? 'true' : 'false'} = () => { const LayoutListeningTextInputTest: React.FC<{}> = () => { const [eventCounter, setEventCounter] = React.useState(0); - return( + return ( The number of onContentSizeChanges is listed here + {eventCounter} = () => { const KeyPressListeningTextInputTest: React.FC<{}> = () => { const [value, setValue] = React.useState(''); - return( + return ( This TextInput uses onKeyPress to maintain state: it is slow = () => { }; const StyleTextInputTest: React.FC<{}> = () => { - return( + return ( This TextInput is styled differently = () => { ); }; -const TextInputTestPage: IRNTesterPage = { - title: '', - displayName: 'TextInput', - description: 'TextInput Examples and Tests', - examples: [ +export const title = ''; +export const displayName = 'TextInput'; +export const description = 'TextInput Examples and Tests'; +export const examples = [ { title: 'Autofocus Example', description: 'autoFocus in action', render(): JSX.Element { return (); - } + }, }, { title: 'Placeholders Example', description: 'placeholder in action', render(): JSX.Element { return (); - } + }, }, { title: 'Controlled Example', description: 'Controlling inputs in action', render(): JSX.Element { return (); - } + }, }, { title: 'Focus and Blur Example', description: 'onFocus/onBlur in action', render(): JSX.Element { return (); - } + }, }, { title: 'ContentSizeChange Example', description: 'onContentSizeChange in action', render(): JSX.Element { return (); - } + }, }, { title: 'Control via onKeyPress Example', description: 'onKeyPress in action', render(): JSX.Element { return (); - } + }, }, { title: 'Super Styling Example', description: 'Styling in action', render(): JSX.Element { return (); - } - } - ] -}; + }, + }, + ]; const styles = StyleSheet.create({ input: { - height: 20 + height: 20, }, blue: { color: 'blue', - height: 20 + height: 20, }, green: { color: 'green', @@ -185,7 +182,5 @@ const styles = StyleSheet.create({ fontWeight: 'bold', fontFamily: 'times-new-roman', height: 100, - } + }, }); - -export = TextInputTestPage; diff --git a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx index 2e404c9b52b..2b923c54b48 100644 --- a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx +++ b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx @@ -147,14 +147,14 @@ class TextInput extends React.Component { * Returns true if the TextInput is focused */ public isFocused(): boolean { - return TextInputState.currentlyFocusedField === findNodeHandle(this); + return TextInputState.currentlyFocusedField() === findNodeHandle(this); } /** * Focuses the TextInput */ public focus = (): void => { - TextInputState.currentlyFocusedField = findNodeHandle(this); + TextInputState.setFocusedTextInput(findNodeHandle(this)); NativeModules.UIManager. dispatchViewManagerCommand(findNodeHandle(this), TextInputViewManager.Commands.focus, null); } @@ -163,7 +163,7 @@ class TextInput extends React.Component { * Blurs the TextInput */ public blur = (): void => { - TextInputState.currentlyFocusedField = null; + TextInputState.blurTextInput(findNodeHandle(this)); NativeModules.UIManager. dispatchViewManagerCommand(findNodeHandle(this), TextInputViewManager.Commands.blur, null); } @@ -207,7 +207,7 @@ class TextInput extends React.Component { } private _onFocus = (e: IFocusEvent): void => { - TextInputState.currentlyFocusedField = findNodeHandle(this); + this.focus(); this.props.onFocus && this.props.onFocus(e); } diff --git a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js index b3e51f25042..3dbda09847b 100644 --- a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js +++ b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js @@ -2,13 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * * @format - * @flow strict-local + * @flow */ 'use strict'; -const Platform = require('../../Utilities/Platform'); -const UIManager = require('../../ReactNative/UIManager'); +const UIManager = require('UIManager'); let currentlyFocusedID: ?number = null; const inputs = new Set(); @@ -28,25 +27,7 @@ function currentlyFocusedField(): ?number { */ function focusTextInput(textFieldID: ?number) { if (currentlyFocusedID !== textFieldID && textFieldID !== null) { - currentlyFocusedID = textFieldID; - if (Platform.OS === 'ios') { - UIManager.focus(textFieldID); - } else if (Platform.OS === 'android') { - UIManager.dispatchViewManagerCommand( - textFieldID, - UIManager.getViewManagerConfig('AndroidTextInput').Commands - .focusTextInput, - null, - ); - // [Win32 - } else if (Platform.OS === 'win32') { - UIManager.dispatchViewManagerCommand( - textFieldID, - UIManager.RCTView.Commands.focus, - null, - ); - } - // Win32] + UIManager.focus(textFieldID); } } @@ -58,27 +39,32 @@ function focusTextInput(textFieldID: ?number) { function blurTextInput(textFieldID: ?number) { if (currentlyFocusedID === textFieldID && textFieldID !== null) { currentlyFocusedID = null; - if (Platform.OS === 'ios') { - UIManager.blur(textFieldID); - } else if (Platform.OS === 'android') { - UIManager.dispatchViewManagerCommand( - textFieldID, - UIManager.getViewManagerConfig('AndroidTextInput').Commands - .blurTextInput, - null, - ); - // [Win32 - } else if (Platform.OS === 'win32') { - UIManager.dispatchViewManagerCommand( - textFieldID, - UIManager.RCTView.Commands.blur, - null, - ); - } - // Win32] + UIManager.blur(textFieldID); + } +} + +/** [TODO(android ISS) + * @param {number} TextInputID id of the text field that has received focus + * Should be called after the view has received focus and fired the onFocus event + * noop if the focused text field is same + */ +function setFocusedTextInput(textFieldID: ?number) { + if (currentlyFocusedID !== textFieldID && textFieldID !== null) { + currentlyFocusedID = textFieldID; } } +/** + * @param {number} TextInputID id of the text field whose focus has to be cleared + * Should be called after the view has cleared focus and fired the onFocus event + * noop if the focused text field is not same + */ +function clearFocusedTextInput(textFieldID: ?number) { + if (currentlyFocusedID === textFieldID && textFieldID !== null) { + currentlyFocusedID = null; + } +} // ]TODO(android ISS) + function registerInput(textFieldID: number) { inputs.add(textFieldID); } @@ -93,6 +79,8 @@ function isTextInput(textFieldID: number) { module.exports = { currentlyFocusedField, + setFocusedTextInput, // TODO(android ISS) + clearFocusedTextInput, // TODO(android ISS) focusTextInput, blurTextInput, registerInput, diff --git a/packages/react-native-win32/src/Libraries/Components/TimePickerAndroid/TimePickerAndroid.win32.js b/packages/react-native-win32/src/Libraries/Components/TimePickerAndroid/TimePickerAndroid.win32.js new file mode 100644 index 00000000000..1a86a7a9072 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/TimePickerAndroid/TimePickerAndroid.win32.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +'use strict'; + +module.exports = require('UnimplementedView'); diff --git a/packages/react-native-win32/src/Libraries/Components/Touchable/Tests/TouchableWin32Test.tsx b/packages/react-native-win32/src/Libraries/Components/Touchable/Tests/TouchableWin32Test.tsx index 8948f6ac11e..d3d65f02692 100644 --- a/packages/react-native-win32/src/Libraries/Components/Touchable/Tests/TouchableWin32Test.tsx +++ b/packages/react-native-win32/src/Libraries/Components/Touchable/Tests/TouchableWin32Test.tsx @@ -8,7 +8,6 @@ import { ViewWin32 } from '../../View/ViewWin32'; import { IViewWin32Props, IKeyboardEvent } from '../../View/ViewWin32.Props'; import { TouchableWin32 } from '../TouchableWin32'; import { IPressEvent, IRenderChild } from '../TouchableWin32.Types'; -import { IRNTesterPage } from 'src/RNTester/RNTester.types'; import { ITouchableWin32State } from '../TouchableWin32.Props'; /** @@ -20,13 +19,13 @@ const styles = StyleSheet.create({ width: 600, justifyContent: 'space-between', alignItems: 'center', - flexDirection: 'row' + flexDirection: 'row', }, smallContainer: { height: 90, width: 90, justifyContent: 'center', - alignContent: 'center' + alignContent: 'center', }, highlight: { height: 150, @@ -34,7 +33,7 @@ const styles = StyleSheet.create({ justifyContent: 'space-around', alignContent: 'center', alignItems: 'center', - flexDirection: 'row' + flexDirection: 'row', }, outerTouch: { height: 150, @@ -42,14 +41,14 @@ const styles = StyleSheet.create({ justifyContent: 'space-around', alignContent: 'center', alignItems: 'center', - flexDirection: 'row' + flexDirection: 'row', }, innerTouch: { height: 90, width: 90, alignItems: 'center', - justifyContent: 'center' - } + justifyContent: 'center', + }, }); /** @@ -59,7 +58,7 @@ const PRESS_RETENTION_OFFSET: Insets = { top: 100, left: 100, right: 100, - bottom: 100 + bottom: 100, }; interface ITouchableWin32WithoutFeedbackProps extends IViewWin32Props { @@ -165,7 +164,7 @@ class TouchableWin32WithoutFeedback extends React.Component { const finalStyle: ViewStyle = { borderWidth: state.isFocused ? 5 : 0, - borderColor: 'red' + borderColor: 'red', }; return Object.assign({}, this.props.style, finalStyle); }; @@ -388,13 +387,13 @@ class TouchableHighlightExample extends React.Component<{}, IExampleState> { borderColor: state.isFocused ? 'green' : 'pink', borderWidth: state.isHovered ? 10 : 5, height: 70, - width: 70 + width: 70, }} > @@ -425,26 +424,23 @@ class TouchableHighlightExample extends React.Component<{}, IExampleState> { }; } -const TouchableWin32TestPage: IRNTesterPage = { - title: '', - displayName: 'TouchableWin32 Examples', - description: 'Demonstration of touchable + focus + hover behavior all in one component', - examples: [ +export const displayName = 'TouchableWin32 Examples'; +export const title = ''; +export const description = 'Demonstration of touchable + focus + hover behavior all in one component'; + +export const examples = [ { title: 'TouchableWithoutFeedback Example', description: 'A simple example implementation of without feedback behavior', render(): JSX.Element { return ; - } + }, }, { title: 'TouchableHighlight Example', description: 'A simple example implementation of highlight behavior', render(): JSX.Element { return ; - } - } - ] -}; - -export = TouchableWin32TestPage; + }, + }, + ]; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/DatePickerAndroid.win32.ts b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/DatePickerAndroid.win32.ts deleted file mode 100644 index 00a69ddf455..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/DatePickerAndroid.win32.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @providesModule DatePickerAndroid - * @flow - */ -'use strict'; - -// var warning = require('fbjs/lib/warning'); - -export = { - async open(options: Object): Promise { - return Promise.reject({ - message: 'DatePickerAndroid is not supported on this platform.' - }); - } -}; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/DatePickerIOS.tsx b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/DatePickerIOS.tsx deleted file mode 100644 index 393c1dc465b..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/DatePickerIOS.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @providesModule DatePickerIOS - */ - -'use strict'; -import UnimplementedView from './UnimplementedViews'; -import { DatePickerIOSProps } from 'react-native'; - -class DatePickerIOS extends UnimplementedView {} - -export = DatePickerIOS; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/MaskedViewIOS.win32.tsx b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/MaskedViewIOS.win32.tsx deleted file mode 100644 index f25dbbc2f8b..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/MaskedViewIOS.win32.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @providesModule MaskedViewIOS - */ - -'use strict'; -import UnimplementedView from './UnimplementedViews'; -import { ViewProps } from 'react-native'; - -class MaskedViewIOS extends UnimplementedView {} - -export = MaskedViewIOS; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/ProgressViewIOS.tsx b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/ProgressViewIOS.tsx deleted file mode 100644 index 5fb2b59fef8..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/ProgressViewIOS.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @providesModule ProgressViewIOS - */ - -'use strict'; -import UnimplementedView from './UnimplementedViews'; -import { ProgressViewIOSProps } from 'react-native'; - -class ProgressViewIOS extends UnimplementedView {} - -export = ProgressViewIOS; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/SafeAreaView.win32.tsx b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/SafeAreaView.win32.tsx deleted file mode 100644 index ac84eb0c92b..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/SafeAreaView.win32.tsx +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @providesModule SafeAreaView - */ - -'use strict'; -import { View } from 'react-native'; - -export = View; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/Settings.win32.ts b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/Settings.win32.ts deleted file mode 100644 index 4b54252ab45..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/Settings.win32.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @providesModule Settings - * @flow - */ -'use strict'; - -export = { - // tslint:disable-next-line no-reserved-keywords -- get name matching facebook implementation - get(key: string) { - console.warn('Settings is not yet supported on win32'); - return null; - }, - - // tslint:disable-next-line no-reserved-keywords -- set name matching facebook implementation - set(settings: Object) { - console.warn('Settings is not yet supported on win32'); - }, - - watchKeys(keys: string | Array, callback: Function): number { - console.warn('Settings is not yet supported on win32'); - return -1; - }, - - clearWatch(watchId: number) { - console.warn('Settings is not yet supported on win32'); - } -}; diff --git a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/TimePickerAndroid.win32.ts b/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/TimePickerAndroid.win32.ts deleted file mode 100644 index 3f52f0ca55a..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/UnimplementedStubs/TimePickerAndroid.win32.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @providesModule TimePickerAndroid - * @flow - */ -'use strict'; - -// var warning = require('fbjs/lib/warning'); - -export = { - async open(options: Object): Promise { - return Promise.reject({ - message: 'TimePickerAndroid is not supported on this platform.' - }); - } -}; diff --git a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js new file mode 100644 index 00000000000..90cb4706d8c --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js @@ -0,0 +1,61 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * @flow strict-local + * @format + */ + +'use strict'; + +const ReactNativeStyleAttributes = require('./ReactNativeStyleAttributes'); + +const ReactNativeViewAttributes = {}; + +ReactNativeViewAttributes.UIView = { + pointerEvents: true, + accessible: true, + accessibilityActions: true, + accessibilityLabel: true, + accessibilityLiveRegion: true, + accessibilityRole: true, + accessibilityStates: true, + accessibilityHint: true, + acceptsKeyboardFocus: true, // TODO(macOS ISS#2323203) + enableFocusRing: true, // TODO(macOS ISS#2323203) + importantForAccessibility: true, + nativeID: true, + testID: true, + textStyle: true, // [Win32] Once we flush out our JS theming story this property will no longer be needed + tooltip: true, // [Win32] + tabIndex: true, // TODO(win ISS#2323203) + renderToHardwareTextureAndroid: true, + shouldRasterizeIOS: true, + onLayout: true, + onAccessibilityAction: true, + onAccessibilityTap: true, + onMagicTap: true, + onAccessibilityEscape: true, + collapsable: true, + needsOffscreenAlphaCompositing: true, + onMouseEnter: true, // [TODO(macOS ISS#2323203) + onMouseLeave: true, + onDragEnter: true, + onDragLeave: true, + onDrop: true, + draggedTypes: true, // ]TODO(macOS ISS#2323203) + style: ReactNativeStyleAttributes, +}; + +ReactNativeViewAttributes.RCTView = { + ...ReactNativeViewAttributes.UIView, + + // This is a special performance property exposed by RCTView and useful for + // scrolling content when there are many subviews, most of which are offscreen. + // For this property to be effective, it must be applied to a view that contains + // many subviews that extend outside its bound. The subviews must also have + // overflow: hidden, as should the containing view (or one of its superviews). + removeClippedSubviews: true, +}; + +module.exports = ReactNativeViewAttributes; diff --git a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.ts b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.ts deleted file mode 100644 index 7271c08d50d..00000000000 --- a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.ts +++ /dev/null @@ -1,9 +0,0 @@ -const ReactNativeViewAttributes = require('./ReactNativeViewAttributes.js'); - -// win32 currently uses an extra property on text -// We add it to view, since TextAttributes isn't split out into a separate module the same way that view is. -// Once we flush out our JS theming story this property will no longer be needed -ReactNativeViewAttributes.UIView.textStyle = true; -ReactNativeViewAttributes.UIView.tooltip = true; - -export = ReactNativeViewAttributes; diff --git a/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx b/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx index 4f4f3a0abdd..adc649938c1 100644 --- a/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx +++ b/packages/react-native-win32/src/Libraries/Components/View/Tests/ViewWin32Test.tsx @@ -3,27 +3,26 @@ import * as React from 'react'; import { StyleSheet, Text, TouchableHighlight } from 'react-native'; import { ViewWin32 } from '../ViewWin32'; import { IKeyboardEvent, IHandledKeyboardEvent } from '../ViewWin32.Props'; -import { IRNTesterPage } from 'src/RNTester/RNTester.types'; const styles = StyleSheet.create({ border: { borderStyle: 'dotted', - borderColor: 'black' + borderColor: 'black', }, keyComponentRoot: { borderWidth: 2, flexDirection: 'row', marginVertical: 5, backgroundColor: 'whitesmoke', - justifyContent: 'space-around' + justifyContent: 'space-around', }, keyEnterVisualizer: { margin: 5, alignItems: 'center', minWidth: 100, - minHeight: 30 + minHeight: 30, }, - blackbox: { height: 30, width: 30, borderColor: 'black', borderWidth: 3 } + blackbox: { height: 30, width: 30, borderColor: 'black', borderWidth: 3 }, }); interface IFocusableComponentState { @@ -35,7 +34,7 @@ class FocusMoverTestComponent extends React.Component<{}, IFocusableComponentSta public constructor(props) { super(props); this.state = { - hasFocus: false + hasFocus: false, }; } public render() { @@ -69,13 +68,13 @@ class FocusMoverTestComponent extends React.Component<{}, IFocusableComponentSta private _onFocus = () => { this.setState({ - hasFocus: true + hasFocus: true, }); }; private _onBlur = () => { this.setState({ - hasFocus: false + hasFocus: false, }); }; } @@ -90,7 +89,7 @@ const handledNativeKeyboardEvents: IHandledKeyboardEvent[] = [ { key: 'ArrowUp' }, { key: 'ArrowLeft' }, { key: 'ArrowRight' }, - { key: 'Tab' } + { key: 'Tab' }, ]; class KeyboardTestComponent extends React.Component<{}, IFocusableComponentState & IKeyboardableComponentState> { @@ -99,7 +98,7 @@ class KeyboardTestComponent extends React.Component<{}, IFocusableComponentState this.state = { hasFocus: false, lastKeyDown: null, - lastKeyUp: null + lastKeyUp: null, }; } @@ -131,13 +130,13 @@ class KeyboardTestComponent extends React.Component<{}, IFocusableComponentState private _onFocus = () => { this.setState({ - hasFocus: true + hasFocus: true, }); }; private _onBlur = () => { this.setState({ - hasFocus: false + hasFocus: false, }); }; @@ -157,7 +156,7 @@ class HoverTestComponent extends React.Component = () => { style={{ backgroundColor: 'red', height: 100, - width: 100 + width: 100, }} tooltip="Example tooltip" /> ); }; -const ViewWin32TestPage: IRNTesterPage = { - title: '', - displayName: 'ViewWin32 Example', - description: 'All the stock View props plus Win32 specific ones', - examples: [ +export const title = ''; +export const displayName = 'ViewWin32 Example'; +export const description = 'All the stock View props plus Win32 specific ones'; +export const examples = [ { title: 'focus() method example', description: 'Each of these black boxes moves focus to the ViewWin32 on the right', @@ -223,30 +221,27 @@ const ViewWin32TestPage: IRNTesterPage = { ); - } + }, }, { title: 'KeyboardEvents example', description: 'Native keyboarding has been prevented', render(): JSX.Element { return ; - } + }, }, { title: 'Hover example', description: 'Hover a rainbow', render(): JSX.Element { return ; - } + }, }, { title: 'Tooltip example', description: 'Displays a tooltip on hover', render(): JSX.Element { return ; - } - } - ] -}; - -export = ViewWin32TestPage; + }, + }, + ]; diff --git a/packages/react-native-win32/src/Libraries/Image/Image.win32.js b/packages/react-native-win32/src/Libraries/Image/Image.win32.js new file mode 100644 index 00000000000..adcfd5630a1 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Image/Image.win32.js @@ -0,0 +1,232 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * @flow + * @format + */ + +// TODO(macOS ISS#2323203) TODO(windows ISS): this file is Image.ios.js in facebook's repo. Renamed to Image.js since it is shared here between ios, macos, and windows. + +'use strict'; + +const DeprecatedImagePropType = require('../DeprecatedPropTypes/DeprecatedImagePropType'); +const NativeModules = require('../BatchedBridge/NativeModules'); +const React = require('react'); +const ReactNative = require('../Renderer/shims/ReactNative'); // eslint-disable-line no-unused-vars +const StyleSheet = require('../StyleSheet/StyleSheet'); + +const flattenStyle = require('../StyleSheet/flattenStyle'); +const requireNativeComponent = require('../ReactNative/requireNativeComponent'); +const resolveAssetSource = require('./resolveAssetSource'); + +const ImageViewManager = NativeModules.ImageViewManager; +const ImageLoader = NativeModules.ImageLoader; // [Win32 uses ImageLoader for getSize] + +const RCTImageView = requireNativeComponent('RCTImage'); // [Win32] Uses RCTImage instead of RCTImageView + +import type {ImageProps as ImagePropsType} from './ImageProps'; + +import type {ImageStyleProp} from '../StyleSheet/StyleSheet'; + +function getSize( + uri: string, + success: (width: number, height: number) => void, + failure?: (error: any) => void, +) { + //[Win32 + /* + ImageViewManager.getSize( + uri, + success, + failure || + function() { + console.warn('Failed to get size for image: ' + uri); + }, + ); + */ + + ImageLoader.getSize(uri, (width: number, height: number, err?: string) => { + if (!err) { + success(width, height); + } else { + if (failure) { + failure(err); + } else { + console.warn('Failure to get size for image: ' + uri); + } + } + }); + // ]Win32 +} + +function getSizeWithHeaders( + uri: string, + headers: {[string]: string}, + success: (width: number, height: number) => void, + failure?: (error: any) => void, +) { + return ImageViewManager.getSizeWithHeaders({uri, headers}) + .then(function(sizes) { + success(sizes.width, sizes.height); + }) + .catch( + failure || + function() { + console.warn('Failed to get size for image: ' + uri); + }, + ); +} + +function prefetch(url: string) { + return ImageViewManager.prefetchImage(url); +} + +async function queryCache( + urls: Array, +): Promise<{[string]: 'memory' | 'disk' | 'disk/memory'}> { + return await ImageViewManager.queryCache(urls); +} + +declare class ImageComponentType extends ReactNative.NativeComponent< + ImagePropsType, +> { + static getSize: typeof getSize; + static getSizeWithHeaders: typeof getSizeWithHeaders; + static prefetch: typeof prefetch; + static queryCache: typeof queryCache; + static resolveAssetSource: typeof resolveAssetSource; + static propTypes: typeof DeprecatedImagePropType; +} + +/** + * A React component for displaying different types of images, + * including network images, static resources, temporary local images, and + * images from local disk, such as the camera roll. + * + * See https://facebook.github.io/react-native/docs/image.html + */ +let Image = ( + props: ImagePropsType, + forwardedRef: ?React.Ref<'RCTImageView'>, +) => { + const source = resolveAssetSource(props.source) || { + uri: undefined, + width: undefined, + height: undefined, + }; + + let sources; + let style: ImageStyleProp; + if (Array.isArray(source)) { + // $FlowFixMe flattenStyle is not strong enough + style = flattenStyle([styles.base, props.style]) || {}; + sources = source; + } else { + const {width, height, uri} = source; + // $FlowFixMe flattenStyle is not strong enough + style = flattenStyle([{width, height}, styles.base, props.style]) || {}; + sources = [source]; + + if (uri === '') { + console.warn('source.uri should not be an empty string'); + } + } + + const resizeMode = props.resizeMode || style.resizeMode || 'cover'; + const tintColor = style.tintColor; + + if (props.src != null) { + console.warn( + 'The component requires a `source` property rather than `src`.', + ); + } + + if (props.children != null) { + throw new Error( + 'The component cannot contain children. If you want to render content on top of the image, consider using the component or absolute positioning.', + ); + } + + return ( + + ); +}; + +Image = React.forwardRef(Image); +Image.displayName = 'Image'; + +/** + * Retrieve the width and height (in pixels) of an image prior to displaying it. + * + * See https://facebook.github.io/react-native/docs/image.html#getsize + */ +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.getSize = getSize; + +/** + * Retrieve the width and height (in pixels) of an image prior to displaying it + * with the ability to provide the headers for the request. + * + * See https://facebook.github.io/react-native/docs/image.html#getsizewithheaders + */ +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.getSizeWithHeaders = getSizeWithHeaders; + +/** + * Prefetches a remote image for later use by downloading it to the disk + * cache. + * + * See https://facebook.github.io/react-native/docs/image.html#prefetch + */ +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.prefetch = prefetch; + +/** + * Performs cache interrogation. + * + * See https://facebook.github.io/react-native/docs/image.html#querycache + */ +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.queryCache = queryCache; + +/** + * Resolves an asset reference into an object. + * + * See https://facebook.github.io/react-native/docs/image.html#resolveassetsource + */ +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.resolveAssetSource = resolveAssetSource; + +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.propTypes = DeprecatedImagePropType; + +const styles = StyleSheet.create({ + base: { + overflow: 'hidden', + }, +}); + +/* $FlowFixMe(>=0.89.0 site=react_native_ios_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 = (Image: Class); diff --git a/packages/react-native-win32/src/Libraries/Image/Image.win32.tsx b/packages/react-native-win32/src/Libraries/Image/Image.win32.tsx deleted file mode 100644 index 6fa6f326b9c..00000000000 --- a/packages/react-native-win32/src/Libraries/Image/Image.win32.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @providesModule Image - */ - -'use strict'; - -import * as React from 'react'; -import { requireNativeComponent } from 'react-native'; -import { IImageProps, IImageState } from './ImageTypes'; -const NativeModules = require('NativeModules'); -const resolveAssetSource = require('resolveAssetSource'); - -const ImageLoader = NativeModules.ImageLoader; - -const RCTImage: React.ComponentClass = requireNativeComponent('RCTImage'); - -class Image extends React.Component { - public static getSize( - uri: string, - success: (width: number, height: number) => void, - // tslint:disable-next-line no-any - failure?: (error: any) => void - ) { - ImageLoader.getSize(uri, (width: number, height: number, err?: string) => { - if (!err) { - success(width, height); - } else { - if (failure) { - failure(err); - } else { - console.warn('Failure to get size for image: ' + uri); - } - } - }); - } - - public render() { - const props = { ...this.props }; - if (this.props.source) { - props.source = typeof this.props.source === 'string' ? { uri: this.props.source } : resolveAssetSource(this.props.source); - } - return ; - } -} - -export = Image; diff --git a/packages/react-native-win32/src/Libraries/Image/Tests/ImageWin32Test.tsx b/packages/react-native-win32/src/Libraries/Image/Tests/ImageWin32Test.tsx index 3ab8d02b4f3..7395502e278 100644 --- a/packages/react-native-win32/src/Libraries/Image/Tests/ImageWin32Test.tsx +++ b/packages/react-native-win32/src/Libraries/Image/Tests/ImageWin32Test.tsx @@ -1,14 +1,12 @@ import * as React from 'react'; -import { IRNTesterPage } from 'src/RNTester/RNTester.types'; import { Image } from 'react-native'; const testImage = require('./img/dpitest.png'); -const ImageWin32TestPage: IRNTesterPage = { - title: '', - displayName: 'Image Win32 test', - description: 'Image Win32 test', - examples: [ +export const title = ''; +export const displayName = 'Image Win32 test'; +export const description = 'Image Win32 test'; +export const examples = [ { title: 'Win32 Image control test', description: 'Test Image', @@ -19,9 +17,6 @@ const ImageWin32TestPage: IRNTesterPage = { source={ testImage } /> ); - } - } - ] -}; - -export = ImageWin32TestPage; \ No newline at end of file + }, + }, + ]; diff --git a/packages/react-native-win32/src/Libraries/Image/resolveAssetSource.win32.ts b/packages/react-native-win32/src/Libraries/Image/resolveAssetSource.win32.js similarity index 60% rename from packages/react-native-win32/src/Libraries/Image/resolveAssetSource.win32.ts rename to packages/react-native-win32/src/Libraries/Image/resolveAssetSource.win32.js index d173c7998c3..02c74daa52b 100644 --- a/packages/react-native-win32/src/Libraries/Image/resolveAssetSource.win32.ts +++ b/packages/react-native-win32/src/Libraries/Image/resolveAssetSource.win32.js @@ -1,45 +1,52 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * @flow strict-local + * @format + */ + 'use strict'; const resolveAssetSource = require('./resolveAssetSource.js'); // Get base impl -const Platform = require('Platform'); +const Platform = require('../Utilities/Platform'); -interface IPackagerAsset { - __packager_asset: boolean; - fileSystemLocation: string; - httpServerLocation: string; - width?: number; - height?: number; - scales: Array; - hash: string; - name: string; - // tslint:disable-next-line no-reserved-keywords - type variable name used by facebook - type: string; -} +type IPackagerAsset = { + __packager_asset: boolean, + fileSystemLocation: string, + httpServerLocation: string, + width?: ?number, + height?: ?number, + scales: Array, + hash: string, + name: string, + type: string, +}; -interface IAssetResolver { - serverUrl?: string; +type IAssetResolver = { + serverUrl?: ?string, // where the bundle is being run from - bundleUrl?: string; + bundleUrl?: ?string, // the asset to resolve - asset: IPackagerAsset; -} + asset: IPackagerAsset, +}; -// Wrapper on top of facebooks Asset resolver that keeps scaling info in the returned asset so that the native side can do the resolution +// Wrapper on top of Facebook's Asset resolver that keeps scaling info in the returned asset so that the native side can do the resolution class AssetResolverLateScaleResolution { - private _resolver: IAssetResolver; + _resolver: IAssetResolver; constructor(resolver: IAssetResolver) { this._resolver = resolver; } - public defaultAsset() { + defaultAsset() { if (this._isLoadedFromServer()) { return this._assetServerURL(); } return this._scaledAssetURLInBundle(); } - private _isLoadedFromServer(): boolean { + _isLoadedFromServer(): boolean { return !!this._resolver.serverUrl; } @@ -47,7 +54,7 @@ class AssetResolverLateScaleResolution { * Resolves to where the bundle is running from, with a asset filename * E.g. 'file:///sdcard/bundle/assets/AwesomeModule/icon.png' */ - private _scaledAssetURLInBundle() { + _scaledAssetURLInBundle() { const path = this._resolver.bundleUrl || 'file://'; return this._fromSource(path + this._getAssetPath()); } @@ -56,21 +63,32 @@ class AssetResolverLateScaleResolution { * Returns an absolute URL which can be used to fetch the asset * from the devserver */ - private _assetServerURL() { + _assetServerURL() { return this._fromSource( - this._resolver.serverUrl + this._getAssetPath() + '?platform=' + Platform.OS + '&hash=' + this._resolver.asset.hash + this._resolver.serverUrl + + this._getAssetPath() + + '?platform=' + + Platform.OS + + '&hash=' + + this._resolver.asset.hash, ); } /** * Returns a path like 'assets/AwesomeModule/icon.png' */ - private _getAssetPath(): string { + _getAssetPath(): string { const assetDir = this._getBasePath(); - return assetDir + '/' + this._resolver.asset.name + '.' + this._resolver.asset.type; + return ( + assetDir + + '/' + + this._resolver.asset.name + + '.' + + this._resolver.asset.type + ); } - private _getBasePath() { + _getBasePath() { let basePath = this._resolver.asset.httpServerLocation; if (basePath[0] === '/') { basePath = basePath.substr(1); @@ -78,7 +96,7 @@ class AssetResolverLateScaleResolution { return basePath; } - private _fromSource(source: string) { + _fromSource(source: string) { return { __packager_asset: true, width: this._resolver.asset.width, @@ -98,4 +116,4 @@ resolveAssetSource.setCustomSourceTransformer(resolver => { return lsrResolver.defaultAsset(); }); -export = resolveAssetSource; +module.exports = resolveAssetSource; diff --git a/packages/react-native-win32/src/Libraries/Inspector/Inspector.win32.js b/packages/react-native-win32/src/Libraries/Inspector/Inspector.win32.js index 7cdf65cef91..5561fcc98c8 100644 --- a/packages/react-native-win32/src/Libraries/Inspector/Inspector.win32.js +++ b/packages/react-native-win32/src/Libraries/Inspector/Inspector.win32.js @@ -1,36 +1,58 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + 'use strict'; -const InspectorOverlay = require('InspectorOverlay'); -const InspectorPanel = require('InspectorPanel'); -const React = require('React'); -const ReactNative = require('ReactNative'); -const StyleSheet = require('StyleSheet'); -const Touchable = require('Touchable'); -const UIManager = require('UIManager'); -const View = require('View'); +const Dimensions = require('../Utilities/Dimensions'); +const InspectorOverlay = require('./InspectorOverlay'); +const InspectorPanel = require('./InspectorPanel'); +const Platform = require('../Utilities/Platform'); +const React = require('react'); +const ReactNative = require('../Renderer/shims/ReactNative'); +const StyleSheet = require('../StyleSheet/StyleSheet'); +const Touchable = require('../Components/Touchable/Touchable'); +const UIManager = require('../ReactNative/UIManager'); +const View = require('../Components/View/View'); const invariant = require('invariant'); export type ReactRenderer = { - getInspectorDataForViewTag: (viewTag: number) => Object + getInspectorDataForViewTag: (viewTag: number) => Object, }; const hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; const renderers = findRenderers(); // required for devtools to be able to edit react native styles -hook.resolveRNStyle = require('flattenStyle'); +hook.resolveRNStyle = require('../StyleSheet/flattenStyle'); function findRenderers(): $ReadOnlyArray { - const allRenderers = Object.keys(hook._renderers).map(key => hook._renderers[key]); - invariant(allRenderers.length >= 1, 'Expected to find at least one React Native renderer on DevTools hook.'); + const allRenderers = Object.keys(hook._renderers).map( + key => hook._renderers[key], + ); + invariant( + allRenderers.length >= 1, + 'Expected to find at least one React Native renderer on DevTools hook.', + ); return allRenderers; } function getInspectorDataForViewTag(touchedViewTag: number) { for (let i = 0; i < renderers.length; i++) { const renderer = renderers[i]; - if (Object.prototype.hasOwnProperty.call(renderer, 'getInspectorDataForViewTag')) { + if ( + Object.prototype.hasOwnProperty.call( + renderer, + 'getInspectorDataForViewTag', + ) + ) { const inspectorData = renderer.getInspectorDataForViewTag(touchedViewTag); if (inspectorData.hierarchy.length > 0) { return inspectorData; @@ -42,7 +64,7 @@ function getInspectorDataForViewTag(touchedViewTag: number) { class Inspector extends React.Component< { inspectedViewTag: ?number, - onRequestRerenderApp: (callback: (tag: ?number) => void) => void + onRequestRerenderApp: (callback: (tag: ?number) => void) => void, }, { devtoolsAgent: ?Object, @@ -53,8 +75,8 @@ class Inspector extends React.Component< perfing: boolean, inspected: any, inspectedViewTag: any, - networking: boolean - } + networking: boolean, + }, > { _subs: ?Array<() => void>; @@ -70,7 +92,7 @@ class Inspector extends React.Component< inspected: null, selection: null, inspectedViewTag: this.props.inspectedViewTag, - networking: false + networking: false, }; } @@ -90,12 +112,12 @@ class Inspector extends React.Component< } UNSAFE_componentWillReceiveProps(newProps: Object) { - this.setState({ inspectedViewTag: newProps.inspectedViewTag }); + this.setState({inspectedViewTag: newProps.inspectedViewTag}); } attachToDevtools = (agent: Object) => { let _hideWait = null; - const hlSub = agent.sub('highlight', ({ node, name, props }) => { + const hlSub = agent.sub('highlight', ({node, name, props}) => { clearTimeout(_hideWait); if (typeof node !== 'number') { @@ -107,9 +129,9 @@ class Inspector extends React.Component< this.setState({ hierarchy: [], inspected: { - frame: { left, top, width, height }, - style: props ? props.style : {} - } + frame: {left, top, width, height}, + style: props ? props.style : {}, + }, }); }); }); @@ -120,34 +142,36 @@ class Inspector extends React.Component< // we wait to actually hide in order to avoid flicker _hideWait = setTimeout(() => { this.setState({ - inspected: null + inspected: null, }); }, 100); }); this._subs = [hlSub, hideSub]; agent.on('shutdown', () => { - this.setState({ devtoolsAgent: null }); + this.setState({devtoolsAgent: null}); this._subs = null; }); this.setState({ - devtoolsAgent: agent + devtoolsAgent: agent, }); }; setSelection(i: number) { const hierarchyItem = this.state.hierarchy[i]; // we pass in ReactNative.findNodeHandle as the method is injected - const { measure, props, source } = hierarchyItem.getInspectorData(ReactNative.findNodeHandle); + const {measure, props, source} = hierarchyItem.getInspectorData( + ReactNative.findNodeHandle, + ); measure((x, y, width, height, left, top) => { this.setState({ inspected: { - frame: { left, top, width, height }, + frame: {left, top, width, height}, style: props.style, - source + source, }, - selection: i + selection: i, }); }); } @@ -156,14 +180,21 @@ class Inspector extends React.Component< // Most likely the touched instance is a native wrapper (like RCTView) // which is not very interesting. Most likely user wants a composite // instance that contains it (like View) - const { hierarchy, props, selection, source } = getInspectorDataForViewTag(touchedViewTag); + const {hierarchy, props, selection, source} = getInspectorDataForViewTag( + touchedViewTag, + ); if (this.state.devtoolsAgent) { // Skip host leafs const offsetFromLeaf = hierarchy.length - 1 - selection; - this.state.devtoolsAgent.selectFromDOMNode(touchedViewTag, true, offsetFromLeaf); + this.state.devtoolsAgent.selectFromDOMNode( + touchedViewTag, + true, + offsetFromLeaf, + ); } + // [Win32 Avoid Dimensions call const node = ReactNative.findNodeHandle(this); UIManager.measure(node, (x, y, width, height, left, top) => { this.setState({ @@ -173,10 +204,11 @@ class Inspector extends React.Component< inspected: { style: props.style, frame, - source - } + source, + }, }); }); + // ]Win32 } setPerfing(val: boolean) { @@ -184,21 +216,21 @@ class Inspector extends React.Component< perfing: val, inspecting: false, inspected: null, - networking: false + networking: false, }); } setInspecting(val: boolean) { this.setState({ inspecting: val, - inspected: null + inspected: null, }); } setTouchTargeting(val: boolean) { Touchable.TOUCH_TARGET_DEBUG = val; this.props.onRequestRerenderApp(inspectedViewTag => { - this.setState({ inspectedViewTag }); + this.setState({inspectedViewTag}); }); } @@ -207,13 +239,15 @@ class Inspector extends React.Component< networking: val, perfing: false, inspecting: false, - inspected: null + inspected: null, }); } render() { - const panelContainerStyle = this.state.panelPos === 'bottom' ? { bottom: 0 } : { top: 0 }; - + const panelContainerStyle = + this.state.panelPos === 'bottom' + ? {bottom: 0} + : {top: Platform.OS === 'ios' ? 20 : 0}; return ( {this.state.inspecting && ( @@ -252,13 +286,13 @@ const styles = StyleSheet.create({ top: 0, left: 0, right: 0, - bottom: 0 + bottom: 0, }, panelContainer: { position: 'absolute', left: 0, - right: 0 - } + right: 0, + }, }); module.exports = Inspector; diff --git a/packages/react-native-win32/src/Libraries/Inspector/InspectorOverlay.win32.js b/packages/react-native-win32/src/Libraries/Inspector/InspectorOverlay.win32.js index 66991baa31f..d2920676d5a 100644 --- a/packages/react-native-win32/src/Libraries/Inspector/InspectorOverlay.win32.js +++ b/packages/react-native-win32/src/Libraries/Inspector/InspectorOverlay.win32.js @@ -1,31 +1,50 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + 'use strict'; -const ElementBox = require('ElementBox'); -const React = require('React'); -const StyleSheet = require('StyleSheet'); -const UIManager = require('UIManager'); -const View = require('View'); +const Dimensions = require('../Utilities/Dimensions'); +const ElementBox = require('./ElementBox'); +const React = require('react'); +const StyleSheet = require('../StyleSheet/StyleSheet'); +const UIManager = require('../ReactNative/UIManager'); +const View = require('../Components/View/View'); -import type { PressEvent } from 'CoreEventTypes'; -import type { ViewStyleProp } from 'StyleSheet'; +import type {PressEvent} from '../Types/CoreEventTypes'; +import type {ViewStyleProp} from '../StyleSheet/StyleSheet'; type Inspected = $ReadOnly<{| frame?: Object, - style?: ViewStyleProp + style?: ViewStyleProp, |}>; type Props = $ReadOnly<{| inspected?: Inspected, inspectedViewTag?: ?number, - onTouchViewTag: (tag: number, frame: Object, pointerY: number) => mixed + onTouchViewTag: (tag: number, frame: Object, pointerY: number) => mixed, |}>; class InspectorOverlay extends React.Component { findViewForTouchEvent = (e: PressEvent) => { - const { locationX, locationY } = e.nativeEvent.touches[0]; - UIManager.findSubviewIn(this.props.inspectedViewTag, [locationX, locationY], (nativeViewTag, left, top, width, height) => { - this.props.onTouchViewTag(nativeViewTag, { left, top, width, height }, locationY); - }); + const {locationX, locationY} = e.nativeEvent.touches[0]; + UIManager.findSubviewIn( + this.props.inspectedViewTag, + [locationX, locationY], + (nativeViewTag, left, top, width, height) => { + this.props.onTouchViewTag( + nativeViewTag, + {left, top, width, height}, + locationY, + ); + }, + ); }; shouldSetResponser = (e: PressEvent): boolean => { @@ -36,15 +55,20 @@ class InspectorOverlay extends React.Component { render() { let content = null; if (this.props.inspected) { - content = ; + content = ( + + ); } + // [Win32, height replaced with 100% to avoid Dimensions call] return ( + style={[styles.inspector, {height: '100%'}]}> {content} ); @@ -57,8 +81,8 @@ const styles = StyleSheet.create({ position: 'absolute', left: 0, top: 0, - right: 0 - } + right: 0, + }, }); module.exports = InspectorOverlay; diff --git a/packages/react-native-win32/src/Libraries/Settings/Settings.win32.js b/packages/react-native-win32/src/Libraries/Settings/Settings.win32.js new file mode 100644 index 00000000000..6d921bfa18f --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Settings/Settings.win32.js @@ -0,0 +1,28 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +'use strict'; + +var Settings = { + get(key: string): mixed { + console.warn('Settings is not yet supported on Win32'); + return null; + }, + + set(settings: Object) { + console.warn('Settings is not yet supported on Win32'); + }, + + watchKeys(keys: string | Array, callback: Function): number { + console.warn('Settings is not yet supported on Win32'); + return -1; + }, + + clearWatch(watchId: number) { + console.warn('Settings is not yet supported on Win32'); + }, +}; + +module.exports = Settings; diff --git a/packages/react-native-win32/src/Libraries/StyleSheet/processColorObject.win32.js b/packages/react-native-win32/src/Libraries/StyleSheet/processColorObject.win32.js index 1dd88ebb00f..85fd9f40ed0 100644 --- a/packages/react-native-win32/src/Libraries/StyleSheet/processColorObject.win32.js +++ b/packages/react-native-win32/src/Libraries/StyleSheet/processColorObject.win32.js @@ -4,37 +4,47 @@ * @format * @flow */ -// [TODO(macOS ISS#2323203) 'use strict'; const invariant = require('invariant'); const processColor = require('processColor'); -import { IGradientColorType, IColorStop } from '../Color/normalizeColorObject.win32'; -function processColorObject(color?: IGradientColorType) { +import type { + ColorStop, + NativeOrDynamicColorType, +} from '../Color/NativeOrDynamicColorType'; + +function processColorObject(color?: NativeOrDynamicColorType) { if (color && typeof color === 'object') { - if (color.hasOwnProperty('colorStops') && color.hasOwnProperty('gradientDirection')) { - invariant(color.colorStops.length >= 2, 'Gradients must contain at least two colors.'); + if ( + color.hasOwnProperty('colorStops') && + color.hasOwnProperty('gradientDirection') + ) { + invariant( + color.colorStops.length >= 2, + 'Gradients must contain at least two colors.', + ); invariant( color.gradientDirection === 'ToTop' || color.gradientDirection === 'ToBottom' || color.gradientDirection === 'ToLeft' || color.gradientDirection === 'ToRight', - 'Unsupported gradient direction; currently supports ToTop, ToBottom, ToLeft, and ToRight.' + 'Unsupported gradient direction; currently supports ToTop, ToBottom, ToLeft, and ToRight.', ); - const gradientColorStops: Array = []; - color.colorStops.forEach((colorStop: IColorStop) => { + const gradientColorStops: Array = []; + color.colorStops.forEach((colorStop: ColorStop) => { gradientColorStops.push({ + //$FlowFixMe color: processColor(colorStop.color), - offset: colorStop.offset + offset: colorStop.offset, }); }); return { gradientDirection: color.gradientDirection, - colorStops: gradientColorStops + colorStops: gradientColorStops, }; } } diff --git a/packages/react-native-win32/src/Libraries/Utilities/Alert.win32.ts b/packages/react-native-win32/src/Libraries/Utilities/Alert.win32.ts deleted file mode 100644 index 2835ae3e564..00000000000 --- a/packages/react-native-win32/src/Libraries/Utilities/Alert.win32.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @providesModule Alert - */ -'use strict'; -/* tslint:disable:no-any */ - -declare module 'react-native' { - /* tslint:disable-next-line interface-name */ - interface NativeModulesStatic { - /* tslint:disable-next-line no-any */ - PLYAlertManager: any; - } -} - -import * as NativeModules from 'react-native/Libraries/BatchedBridge/NativeModules'; -import { AlertButton, AlertOptions } from 'react-native'; - -class Alert { - // tslint:disable-next-line: function-name -- matching facebook name - public static alert(title: string, content?: string, buttons?: AlertButton[], options?: AlertOptions) { - NativeModules.PLYAlertManager.showAlert(title, content, buttons, options, buttonIndex => { - if (buttonIndex >= 0 && buttonIndex < buttons.length) { - buttons[buttonIndex].onPress(); - } - - if (options && options.onDismiss && buttonIndex === -1) { - options.onDismiss(); - } - }); - } -} - -export = Alert; diff --git a/packages/react-native-win32/src/Libraries/Utilities/DeviceInfo.win32.ts b/packages/react-native-win32/src/Libraries/Utilities/DeviceInfo.win32.js similarity index 57% rename from packages/react-native-win32/src/Libraries/Utilities/DeviceInfo.win32.ts rename to packages/react-native-win32/src/Libraries/Utilities/DeviceInfo.win32.js index 8beb7d7353c..f2c280abe95 100644 --- a/packages/react-native-win32/src/Libraries/Utilities/DeviceInfo.win32.ts +++ b/packages/react-native-win32/src/Libraries/Utilities/DeviceInfo.win32.js @@ -1,11 +1,15 @@ /** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * * Device info doesn't can't be a global set of data for win32 * (probably not for android either). * * Since the API as designed by facebook can't work, we just return null here to crash when used - * @providesModule DeviceInfo + * @format + * @flow */ 'use strict'; -export = null; +module.exports = {isIPhoneX_deprecated: false}; diff --git a/packages/react-native-win32/src/Libraries/Utilities/Dimensions.win32.ts b/packages/react-native-win32/src/Libraries/Utilities/Dimensions.win32.ts index e5d1f606462..21d09be7c44 100644 --- a/packages/react-native-win32/src/Libraries/Utilities/Dimensions.win32.ts +++ b/packages/react-native-win32/src/Libraries/Utilities/Dimensions.win32.ts @@ -1,23 +1,29 @@ /** - * @providesModule Dimensions + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + + * @format + * @flow */ 'use strict'; -/* tslint:disable:no-any */ class Dimensions { - // tslint:disable-next-line no-reserved-keywords function-name -- get name matching facebook implementation - public static get(dim: string) { - throw new Error('Having a global Dimensions object is too simplistic for Win32, so this API does not work'); + public static get(dim: string): Object { + throw new Error( + 'Having a global Dimensions object is too simplistic for Win32, so this API does not work', + ); } - // tslint:disable-next-line no-reserved-keywords function-name -- type name matching facebook implementation - public static addEventListener(type: string, handler: any) { - throw new Error('Having a global Dimensions object is too simplistic for Win32, so this API does not work'); + public static addEventListener(type: string, handler: Function) { + throw new Error( + 'Having a global Dimensions object is too simplistic for Win32, so this API does not work', + ); } - // tslint:disable-next-line no-reserved-keywords function-name -- type name matching facebook implementation - public static removeEventListener(type: string, handler: any) { - throw new Error('Having a global Dimensions object is too simplistic for Win32, so this API does not work'); + public static removeEventListener(type: string, handler: Function) { + throw new Error( + 'Having a global Dimensions object is too simplistic for Win32, so this API does not work', + ); } } -export = Dimensions; +module.exports = Dimensions; diff --git a/packages/react-native-win32/src/Libraries/Utilities/Platform.win32.js b/packages/react-native-win32/src/Libraries/Utilities/Platform.win32.js new file mode 100644 index 00000000000..06c8cec229b --- /dev/null +++ b/packages/react-native-win32/src/Libraries/Utilities/Platform.win32.js @@ -0,0 +1,30 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * @format + * @flow + */ + +'use strict'; + +const NativeModules = require('NativeModules'); + +const Platform = { + OS: 'win32', + get Version() { + const constants = NativeModules.PlatformConstants; + return constants && constants.Version; + }, + get isTesting(): boolean { + const constants = NativeModules.PlatformConstants; + return constants && constants.isTesting; + }, + select: (obj: Object) => ('win32' in obj ? obj.win32 : obj.default), + get isTV() { + const constants = NativeModules.PlatformConstants; + return constants ? constants.interfaceIdiom === 'tv' : false; + }, +}; + +module.exports = Platform; diff --git a/packages/react-native-win32/src/Libraries/Utilities/Platform.win32.ts b/packages/react-native-win32/src/Libraries/Utilities/Platform.win32.ts deleted file mode 100644 index 938fc977110..00000000000 --- a/packages/react-native-win32/src/Libraries/Utilities/Platform.win32.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Platform - * @flow - */ - -'use strict'; - -export = { - OS: 'win32', - /* tslint:disable:no-any */ - select: (obj: any) => obj.win32 - /* tslint:enable:no-any */ -}; diff --git a/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorHeader.win32.js b/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorHeader.win32.js new file mode 100644 index 00000000000..ca58c413826 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorHeader.win32.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @flow + * @format + */ + +'use strict'; +const React = require('react'); +const View = require('../../Components/View/View'); + +// The RN YellowBoxInspectorHeader uses PixelRatio, which isn't multi DPI aware. +// So we just stub the header for now +module.exports = () => ; diff --git a/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorHeader.win32.tsx b/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorHeader.win32.tsx deleted file mode 100644 index 974dffdbba7..00000000000 --- a/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorHeader.win32.tsx +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; -import * as React from 'react'; -import { View } from 'react-native'; - -// The RN YellowBoxInspectorHeader uses PixelRatio, which isn't multi DPI aware. -// So we just stub the header for now -export = () => ; diff --git a/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.win32.js b/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.win32.js new file mode 100644 index 00000000000..7c2632d0878 --- /dev/null +++ b/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.win32.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * + * @flow strict-local + * @format + */ + +'use strict'; + +const React = require('react'); +const Text = require('../../Text/Text'); +import type {PressEvent} from '../../Types/CoreEventTypes'; + +// [Win32] - Replace implementation since react-native uses Animated.Image which win32 doesn't support + +type Props = $ReadOnly<{| + onPress?: ?(event: PressEvent) => void, + status: 'COMPLETE' | 'FAILED' | 'NONE' | 'PENDING', +|}>; + +module.exports = (props: Props) => {props.status}; diff --git a/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.win32.tsx b/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.win32.tsx deleted file mode 100644 index edead6526bb..00000000000 --- a/packages/react-native-win32/src/Libraries/YellowBox/UI/YellowBoxInspectorSourceMapStatus.win32.tsx +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -import React = require('react'); -import { Text } from 'react-native'; - -interface IYellowBoxInspectorSourceMapStatusProps { - status: 'COMPLETE' | 'FAILED' | 'NONE' | 'PENDING'; -} - -export = (props: IYellowBoxInspectorSourceMapStatusProps) => {props.status}; diff --git a/packages/react-native-win32/src/RNTester.ts b/packages/react-native-win32/src/RNTester.ts index 0874d3ac620..6d20d46871a 100644 --- a/packages/react-native-win32/src/RNTester.ts +++ b/packages/react-native-win32/src/RNTester.ts @@ -1 +1,6 @@ -import './RNTester/RNTesterApp'; +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ +import './RNTester/js/RNTesterApp'; diff --git a/packages/react-native-win32/src/RNTester/APIExamples/AccessibilityExampleWin32.tsx b/packages/react-native-win32/src/RNTester/APIExamples/AccessibilityExampleWin32.tsx index 11d0625798a..98f2b67b4e7 100644 --- a/packages/react-native-win32/src/RNTester/APIExamples/AccessibilityExampleWin32.tsx +++ b/packages/react-native-win32/src/RNTester/APIExamples/AccessibilityExampleWin32.tsx @@ -1,13 +1,12 @@ 'use strict'; import * as React from 'react'; -import { IRNTesterPage } from 'src/RNTester/RNTester.types'; import { FlatList, StyleSheet, Text, TouchableHighlight, ListRenderItemInfo } from 'react-native'; import { ViewWin32 } from '../../Libraries/Components/View/ViewWin32'; const styles = StyleSheet.create({ border: { borderStyle: 'dotted', - borderColor: 'black' + borderColor: 'black', }, box: { borderWidth: 2, @@ -15,11 +14,11 @@ const styles = StyleSheet.create({ marginVertical: 5, height: 20, backgroundColor: 'whitesmoke', - justifyContent: 'space-around' + justifyContent: 'space-around', }, listContainer: { - height: 150 - } + height: 150, + }, }); interface IFocusableComponentState { @@ -50,7 +49,7 @@ class ButtonExample extends React.Component<{}, IFocusableComponentState & IExpa super(props); this.state = { hasFocus: false, - expanded: false + expanded: false, }; } @@ -92,25 +91,25 @@ class ButtonExample extends React.Component<{}, IFocusableComponentState & IExpa private _expand = () => { this.setState({ - expanded: true + expanded: true, }); }; private _collapse = () => { this.setState({ - expanded: false + expanded: false, }); }; private _onFocus = () => { this.setState({ - hasFocus: true + hasFocus: true, }); }; private _onBlur = () => { this.setState({ - hasFocus: false + hasFocus: false, }); }; @@ -128,14 +127,14 @@ class MultiSelectionExample extends React.Component<{}, IMultiSelectionExampleSt super(props); this.state = { - selectedItems: [] + selectedItems: [], }; } public handleAdd = item => { if (this.state.selectedItems.indexOf(item) === -1) { this.setState({ - selectedItems: this.state.selectedItems.concat([item]) + selectedItems: this.state.selectedItems.concat([item]), }); } }; @@ -146,7 +145,7 @@ class MultiSelectionExample extends React.Component<{}, IMultiSelectionExampleSt const index = array.indexOf(item); array.splice(index, 1); this.setState({ - selectedItems: array + selectedItems: array, }); } }; @@ -256,7 +255,7 @@ class ListItem extends React.PureComponent public constructor(props) { super(props); this.state = { - hasFocus: false + hasFocus: false, }; } @@ -281,13 +280,13 @@ class ListItem extends React.PureComponent private _onFocus = () => { this.setState({ - hasFocus: true + hasFocus: true, }); }; private _onBlur = () => { this.setState({ - hasFocus: false + hasFocus: false, }); }; } @@ -344,44 +343,40 @@ function generateList(size: number): Array { label: i.toString(), level: 1, setSize: size, - positionInSet: i + positionInSet: i, }; list[i - 1] = item; } return list; } -const AccessibilityTestPage: IRNTesterPage = { - title: 'Accessibility Examples', - displayName: 'Accessibility Examples', - description: 'Demonstrates accessibility props', - examples: [ +export const title = 'Accessibility Examples'; +export const displayName = 'Accessibility Examples'; +export const description = 'Demonstrates accessibility props'; +export const examples = [ { title: 'Annotation Example', description: 'A comment that exposes annotation properties.', - render: () => + render: () => , }, { title: 'Button Example', description: 'A button with some basic accessibility props and expand/collapse', - render: () => + render: () => , }, { title: 'MultiSelection Example', description: 'A list of items that can be selected', - render: () => + render: () => , }, { title: 'FlatList Example', description: 'A flat list of headers with n of m support', - render: () => + render: () => , }, { title: 'Virtualized FlatList Example', description: 'A virtualized flat list of 30 items with n of m support', - render: () => - } - ] -}; - -export = AccessibilityTestPage; + render: () => , + }, + ]; diff --git a/packages/react-native-win32/src/RNTester/APIExamples/ThemingModuleAPI.tsx b/packages/react-native-win32/src/RNTester/APIExamples/ThemingModuleAPI.tsx index 69c55cb2c36..ff92f5573f7 100644 --- a/packages/react-native-win32/src/RNTester/APIExamples/ThemingModuleAPI.tsx +++ b/packages/react-native-win32/src/RNTester/APIExamples/ThemingModuleAPI.tsx @@ -1,7 +1,6 @@ 'use strict'; import * as React from 'react'; import { View, Text, StyleSheet, TextInput, NativeModules, ScrollView } from 'react-native'; -import { IRNTesterPage } from 'src/RNTester/RNTester.types'; // import { ViewWin32 } from '../../Libraries/Components/View/ViewWin32'; const styles = StyleSheet.create({ @@ -91,11 +90,10 @@ const ThemingConstants: React.FunctionComponent<{}> = props => { ); }; -const ThemingModuleTestPage: IRNTesterPage = { - title: 'Theming Module APIs', - displayName: 'Theming Module APIs', - description: 'Tests shape of Theming Native Module', - examples: [ +export const title = 'Theming Module APIs'; +export const displayName = 'Theming Module APIs'; +export const description = 'Tests shape of Theming Native Module'; +export const examples = [ { title: 'Theming Module Constants', description: 'All constants', @@ -106,7 +104,4 @@ const ThemingModuleTestPage: IRNTesterPage = { description: 'Method invoker', render: () => ifModuleAvailable(), }, - ], -}; - -export = ThemingModuleTestPage; + ]; diff --git a/packages/react-native-win32/src/RNTester/RNTester.types.ts b/packages/react-native-win32/src/RNTester/RNTester.types.ts deleted file mode 100644 index 2aaa16a59f0..00000000000 --- a/packages/react-native-win32/src/RNTester/RNTester.types.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface IRNTesterExample { - title: string; - description: string; - render: () => JSX.Element; -} - -export interface IRNTesterPage { - title: string; - description?: string; - displayName?: string; - examples: IRNTesterExample[]; -} diff --git a/packages/react-native-win32/src/RNTester/RNTesterActions.win32.ts b/packages/react-native-win32/src/RNTester/RNTesterActions.win32.ts deleted file mode 100644 index efc21aac337..00000000000 --- a/packages/react-native-win32/src/RNTester/RNTesterActions.win32.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - * @format - */ -export interface IRNTesterBackAction { - // tslint:disable-next-line no-reserved-keywords - type: 'RNTesterBackAction'; -} - -export interface IRNTesterListAction { - // tslint:disable-next-line no-reserved-keywords - type: 'RNTesterListAction'; -} - -export interface IRNTesterExampleAction { - // tslint:disable-next-line no-reserved-keywords - type: 'RNTesterExampleAction'; - openExample: string; -} - -export interface IRNTesterInitialAction { - // tslint:disable-next-line no-reserved-keywords - type: 'InitialAction'; -} - -export type RNTesterAction = - | IRNTesterBackAction - | IRNTesterListAction - | IRNTesterExampleAction - | IRNTesterInitialAction; diff --git a/packages/react-native-win32/src/RNTester/RNTesterNavigationReducer.win32.ts b/packages/react-native-win32/src/RNTester/RNTesterNavigationReducer.win32.ts deleted file mode 100644 index 5f65e0e9a51..00000000000 --- a/packages/react-native-win32/src/RNTester/RNTesterNavigationReducer.win32.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - * @format - */ -'use strict'; - -import RNTesterList from './RNTesterList.win32'; -import {RNTesterAction} from './RNTesterActions.win32'; - -interface IRNTesterNavigationState { - openExample?: string; -} - -function rnTesterNavigationReducer( - state: IRNTesterNavigationState | undefined, - action: RNTesterAction, -): IRNTesterNavigationState { - if ( - // Default value is to see example list - !state || - // Handle the explicit list action - action.type === 'RNTesterListAction' || - // Handle requests to go back to the list when an example is open - (state.openExample && action.type === 'RNTesterBackAction') - ) { - return { - // A null openExample will cause the views to display the RNTester example list - openExample: undefined, - }; - } - - if (action.type === 'RNTesterExampleAction') { - // Make sure we see the module before returning the new state - const ExampleModule = RNTesterList.Modules[action.openExample]; - - if (ExampleModule) { - return { - openExample: action.openExample, - }; - } - } - - return state; -} - -export default rnTesterNavigationReducer; diff --git a/packages/react-native-win32/src/RNTester/RNTesterApp.win32.tsx b/packages/react-native-win32/src/RNTester/js/RNTesterApp.win32.tsx similarity index 87% rename from packages/react-native-win32/src/RNTester/RNTesterApp.win32.tsx rename to packages/react-native-win32/src/RNTester/js/RNTesterApp.win32.tsx index fd978d6bfe1..5a9866abe53 100644 --- a/packages/react-native-win32/src/RNTester/RNTesterApp.win32.tsx +++ b/packages/react-native-win32/src/RNTester/js/RNTesterApp.win32.tsx @@ -10,9 +10,8 @@ import {Button, AppRegistry, StyleSheet, Text, View} from 'react-native'; const RNTesterActions = require('react-native/RNTester/js/RNTesterActions'); const RNTesterExampleContainer = require('react-native/RNTester/js/RNTesterExampleContainer'); const RNTesterExampleList = require('react-native/RNTester/js/RNTesterExampleList'); -import RNTesterList from './RNTesterList.win32'; -import RNTesterNavigationReducer from './RNTesterNavigationReducer.win32'; -import {RNTesterAction} from './RNTesterActions.win32'; +const RNTesterList = require('./RNTesterList.win32'); +const RNTesterNavigationReducer = require('react-native/RNTester/js/RNTesterNavigationReducer'); const styles = StyleSheet.create({ headerContainer: { @@ -69,14 +68,16 @@ class RNTesterApp extends React.Component< IRNTesterAppProps, IRNTesterNavigationState > { - public render() { + public render(): JSX.Element { if (!this.state) { return null state; } if (this.state.openExample) { const Component = RNTesterList.Modules[this.state.openExample]; if (Component.external) { - return ; + // tslint:disable-next-line:no-any + const Comp = Component as any; + return ; } else { return ( @@ -103,7 +104,7 @@ class RNTesterApp extends React.Component< } */ - public componentDidMount() { + public componentDidMount(): void { /* Linking.getInitialURL().then((url) => { AsyncStorage.getItem(APP_STATE_KEY, (err, storedString) => { @@ -112,9 +113,10 @@ class RNTesterApp extends React.Component< const launchAction = exampleAction || urlAction; if (err || !storedString) { */ - const initialAction: RNTesterAction = /*launchAction ||*/ { + const initialAction = /*launchAction ||*/ { type: 'InitialAction', }; + // eslint-disable-next-line react/no-did-mount-set-state this.setState(RNTesterNavigationReducer(undefined, initialAction)); return; /* @@ -138,7 +140,7 @@ class RNTesterApp extends React.Component< this._handleAction(RNTesterActions.Back()); }; - private _handleAction = (action?: RNTesterAction) => { + private _handleAction = (action: any) => { if (!action) { return; } diff --git a/packages/react-native-win32/src/RNTester/js/RNTesterExampleFilter.js b/packages/react-native-win32/src/RNTester/js/RNTesterExampleFilter.js new file mode 100644 index 00000000000..48004fc4c99 --- /dev/null +++ b/packages/react-native-win32/src/RNTester/js/RNTesterExampleFilter.js @@ -0,0 +1,140 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +import Platform from '../../Libraries/Utilities/Platform'; // TODO(macOS ISS#2323203) +const React = require('react'); +const {StyleSheet, TextInput, View} = require('react-native'); + +type Props = { + filter: Function, + render: Function, + sections: Object, + disableSearch?: boolean, + testID?: string, +}; + +type State = { + filter: string, +}; + +class RNTesterExampleFilter extends React.Component { + state = {filter: ''}; + + render() { + const filterText = this.state.filter; + let filterRegex = /.*/; + + try { + filterRegex = new RegExp(String(filterText), 'i'); + } catch (error) { + console.warn( + 'Failed to create RegExp: %s\n%s', + filterText, + error.message, + ); + } + + const filter = example => + this.props.disableSearch || this.props.filter({example, filterRegex}); + + const filteredSections = this.props.sections.map(section => ({ + ...section, + data: section.data.filter(filter), + })); + + return ( + + {this._renderTextInput()} + {this.props.render({filteredSections})} + + ); + } + + _renderTextInput(): ?React.Element { + if (this.props.disableSearch) { + return null; + } + return ( + + { + this.setState(() => ({filter: text})); + }} + placeholder="Search..." + placeholderTextColor={ + Platform.select({ + macos: {semantic: 'placeholderTextColor'}, + ios: {semantic: 'placeholderTextColor'}, + default: undefined, + }) /*TODO(macOS ISS#2323203)*/ + } + underlineColorAndroid="transparent" + style={styles.searchTextInput} + testID={this.props.testID} + value={this.state.filter} + /> + + ); + } +} + +const styles = StyleSheet.create({ + searchRow: { + // [TODO(macOS ISS#2323203) + ...Platform.select({ + macos: { + backgroundColor: {semantic: 'windowBackgroundColor'}, + }, + ios: { + backgroundColor: {semantic: 'systemGroupedBackgroundColor'}, + }, + default: { + // ]TODO(macOS ISS#2323203) + backgroundColor: '#eeeeee', + }, // [TODO(macOS ISS#2323203) + }), // ]TODO(macOS ISS#2323203) + padding: 10, + }, + searchTextInput: { + // [TODO(macOS ISS#2323203) + ...Platform.select({ + macos: { + color: {semantic: 'textColor'}, + backgroundColor: {semantic: 'textBackgroundColor'}, + borderColor: {semantic: 'quaternaryLabelColor'}, + }, + ios: { + color: {semantic: 'labelColor'}, + backgroundColor: {semantic: 'secondarySystemGroupedBackgroundColor'}, + borderColor: {semantic: 'quaternaryLabelColor'}, + }, + default: { + // ]TODO(macOS ISS#2323203) + // backgroundColor: 'white', // [Win32 - TextInput doesn't support backgroundColor currently] + borderColor: '#cccccc', + }, // [TODO(macOS ISS#2323203) + }), // ]TODO(macOS ISS#2323203) + borderRadius: 3, + borderWidth: 1, + paddingLeft: 8, + paddingVertical: 0, + height: 35, + }, + container: { + flex: 1, + }, +}); + +module.exports = RNTesterExampleFilter; diff --git a/packages/react-native-win32/src/RNTester/RNTesterList.win32.ts b/packages/react-native-win32/src/RNTester/js/RNTesterList.win32.ts similarity index 56% rename from packages/react-native-win32/src/RNTester/RNTesterList.win32.ts rename to packages/react-native-win32/src/RNTester/js/RNTesterList.win32.ts index 61af755b19f..7df3b35a416 100644 --- a/packages/react-native-win32/src/RNTester/RNTesterList.win32.ts +++ b/packages/react-native-win32/src/RNTester/js/RNTesterList.win32.ts @@ -1,15 +1,34 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + * @format + */ 'use strict'; +import React = require('react'); interface IRNTesterExample { key: string; // tslint:disable-next-line no-reserved-keywords - module: Object; + module: IRNTesterModule; +} + +interface IRNTesterModule { + title: string; + description: string; + external: boolean; + examples: [IRNTesterModuleExample]; +} + +interface IRNTesterModuleExample { + title: string; + description: string; + render(): React.Component; } const ComponentExamples: Array = [ { key: 'TouchableWin32Example', - module: require('../Libraries/Components/Touchable/Tests/TouchableWin32Test'), + module: require('../../Libraries/Components/Touchable/Tests/TouchableWin32Test'), }, { key: 'ScrollViewSimpleExample', @@ -25,22 +44,22 @@ const ComponentExamples: Array = [ }, { key: 'ViewWin32Test', - module: require('../Libraries/Components/View/Tests/ViewWin32Test'), + module: require('../../Libraries/Components/View/Tests/ViewWin32Test'), }, { key: 'TextInputExample', - module: require('../Libraries/Components/TextInput/Tests/TextInputTest'), + module: require('../../Libraries/Components/TextInput/Tests/TextInputTest'), }, { key: 'ImageWin32Test', - module: require('../Libraries/Image/Tests/ImageWin32Test'), + module: require('../../Libraries/Image/Tests/ImageWin32Test'), }, ]; const APIExamples: Array = [ { key: 'AccessibilityExampleWin32', - module: require('./APIExamples/AccessibilityExampleWin32'), + module: require('../APIExamples/AccessibilityExampleWin32'), }, { key: 'AppStateExample', @@ -60,13 +79,13 @@ const APIExamples: Array = [ }, { key: 'ThemingExample', - module: require('./APIExamples/ThemingModuleAPI'), + module: require('../APIExamples/ThemingModuleAPI'), }, ]; -const Modules = {}; +const Modules: {[key: string]: IRNTesterModule} = {}; -APIExamples.concat(ComponentExamples).forEach(Example => { +APIExamples.concat(ComponentExamples).forEach((Example: IRNTesterExample) => { Modules[Example.key] = Example.module; }); @@ -76,4 +95,4 @@ const RNTesterList = { Modules, }; -export default RNTesterList; +export = RNTesterList; diff --git a/vnext/Scripts/copyRNLibraries.js b/vnext/Scripts/copyRNLibraries.js index 04db6efd2a6..41ce5f741db 100644 --- a/vnext/Scripts/copyRNLibraries.js +++ b/vnext/Scripts/copyRNLibraries.js @@ -48,41 +48,38 @@ function copyJSFolderRecursiveSync(source, target) { } } -exports.copyRNLibraries = () => { +exports.copyRNLibraries = baseDir => { const rnPath = path.dirname(require.resolve('react-native/package.json')); - const rnCodeGenDest = path.resolve( - __dirname, - '../packages/react-native-codegen', - ); + const rnCodeGenDest = path.resolve(baseDir, 'packages/react-native-codegen'); if (fs.existsSync(rnCodeGenDest)) { rimraf.sync(rnCodeGenDest); } - const integrationTestsDest = path.resolve(__dirname, '../IntegrationTests'); + const integrationTestsDest = path.resolve(baseDir, 'IntegrationTests'); if (fs.existsSync(integrationTestsDest)) { rimraf.sync(integrationTestsDest + path.sep + '*.js'); } - const librariesDest = path.resolve(__dirname, '../Libraries'); + const librariesDest = path.resolve(baseDir, 'Libraries'); if (fs.existsSync(librariesDest)) { rimraf.sync(librariesDest); } - const flowDest = path.resolve(__dirname, '../flow'); + const flowDest = path.resolve(baseDir, 'flow'); if (fs.existsSync(flowDest)) { rimraf.sync(flowDest); } - const flowTypedDest = path.resolve(__dirname, '../flow-typed'); + const flowTypedDest = path.resolve(baseDir, 'flow-typed'); if (fs.existsSync(flowTypedDest)) { rimraf.sync(flowTypedDest); } - const jestDest = path.resolve(__dirname, '../jest'); + const jestDest = path.resolve(baseDir, 'jest'); if (fs.existsSync(jestDest)) { rimraf.sync(jestDest); } - const rnTesterDest = path.resolve(__dirname, '../RNTester'); + const rnTesterDest = path.resolve(baseDir, 'RNTester'); if (fs.existsSync(rnTesterDest)) { rimraf.sync(rnTesterDest); } - const baseDir = path.resolve(__dirname, '..'); + if (fs.existsSync(path.resolve(rnPath, 'IntegrationTests'))) { copyJSFolderRecursiveSync( path.resolve(rnPath, 'IntegrationTests'), @@ -90,13 +87,11 @@ exports.copyRNLibraries = () => { ); } - if (!fs.existsSync(path.resolve(__dirname, '../packages'))) { - fs.mkdirSync(path.resolve(__dirname, '../packages')); + if (!fs.existsSync(path.resolve(baseDir, 'packages'))) { + fs.mkdirSync(path.resolve(baseDir, 'packages')); } - if ( - !fs.existsSync(path.resolve(__dirname, '../packages/react-native-codegen')) - ) { - fs.mkdirSync(path.resolve(__dirname, '../packages/react-native-codegen')); + if (!fs.existsSync(path.resolve(baseDir, 'packages/react-native-codegen'))) { + fs.mkdirSync(path.resolve(baseDir, 'packages/react-native-codegen')); } copyJSFolderRecursiveSync( @@ -110,7 +105,7 @@ exports.copyRNLibraries = () => { copyJSFolderRecursiveSync(path.resolve(baseDir, 'src/jest'), baseDir); // Copy js files from src/jest to jest fs.writeFileSync( - path.resolve(__dirname, '../rn-get-polyfills.js'), + path.resolve(baseDir, 'rn-get-polyfills.js'), fs.readFileSync(path.resolve(rnPath, 'rn-get-polyfills.js')), ); @@ -119,11 +114,11 @@ exports.copyRNLibraries = () => { } /* - if (!fs.existsSync(path.resolve(__dirname, '../lib/local-cli'))) { - fs.mkdirSync(path.resolve(__dirname, '../lib/local-cli')); + if (!fs.existsSync(path.resolve(baseDir, 'lib/local-cli'))) { + fs.mkdirSync(path.resolve(baseDir, 'lib/local-cli')); } - if (!fs.existsSync(path.resolve(__dirname, '../lib/local-cli/bundle'))) { - fs.mkdirSync(path.resolve(__dirname, '../lib/local-cli/bundle')); + if (!fs.existsSync(path.resolve(baseDir, 'lib/local-cli/bundle'))) { + fs.mkdirSync(path.resolve(baseDir, 'lib/local-cli/bundle')); } */ }; diff --git a/vnext/just-task.js b/vnext/just-task.js index b5611db05bd..7987885e11e 100644 --- a/vnext/just-task.js +++ b/vnext/just-task.js @@ -47,7 +47,7 @@ task('copyFlowFiles', () => { return copyTask(['src/**/*.js'], '.'); }); task('initRNLibraries', () => { - require('./Scripts/copyRNLibraries').copyRNLibraries(); + require('./Scripts/copyRNLibraries').copyRNLibraries(__dirname); }); task('ts', () => {