From 2864890d3d36a71a722be62a9c714d482a5b5490 Mon Sep 17 00:00:00 2001 From: anees ur rahiman Date: Tue, 19 Jan 2021 17:53:30 +0530 Subject: [PATCH] upgrade react-native compability from 0.57.* to 0.62.2 --- README.md | 121 +- packages/react-native-dom-cli/.babelrc | 3 + packages/react-native-dom-cli/.gitignore | 4 + packages/react-native-dom-cli/package.json | 39 + .../src/buildDom/buildDom.js | 95 ++ .../src/generator-dom/index.js | 3 + packages/react-native-dom-cli/src/index.js | 26 + .../react-native-dom-cli/src/runDom/runDom.js | 121 ++ packages/react-native-dom-init/.babelrc | 3 + packages/react-native-dom-init/.gitignore | 3 + packages/react-native-dom-init/index.js | 2 + packages/react-native-dom-init/package.json | 41 + .../src/addCommandsToPackageJson.js | 25 + .../src/getReactNativeProject.js | 27 + packages/react-native-dom-init/src/index.js | 67 + .../react-native-dom-init/src/installRNDom.js | 166 +++ .../src/requireGenerateRNDom.js | 6 + .../react-native-dom-init/src/userError.js | 10 + packages/react-native-dom-init/src/utils.js | 5 + packages/react-native-dom-renderer/.babelrc | 51 + packages/react-native-dom-renderer/.gitignore | 3 + .../ReactDom/DevSupport/RCTDevLoadingView.js | 0 .../ReactDom/DevSupport/RCTDevMenu.js | 0 .../ReactDom/ReactDom.js | 2 +- .../ReactDom/base/NotificationCenter.js | 0 .../ReactDom/base/UIBorderView.js | 0 .../ReactDom/base/UIChildContainerView.js | 0 .../ReactDom/base/UIHitSlopView.js | 0 .../ReactDom/base/UIView.js | 0 .../ReactDom/bridge/RCTBridge.js | 0 .../ReactDom/bridge/RCTBridge.worker.js | 0 .../ReactDom/bridge/RCTBridgeMethod.js | 0 .../ReactDom/bridge/RCTEventDispatcher.js | 0 .../ReactDom/bridge/RCTModule.js | 34 +- .../ReactDom/bridge/RCTModuleConfig.js | 0 .../ReactDom/bridge/RCTRootView.js | 2 +- .../ReactDom/defs/InternalLib.js | 0 .../LayoutAnimation/RCTKeyframeGenerator.js | 0 .../RCTLayoutAnimationManager.js | 0 .../keyframeGenerator.test.js.snap | 0 .../__tests__/keyframeGenerator.test.js | 0 .../Drivers/RCTAnimationDriver.js | 0 .../Drivers/RCTDecayAnimation.js | 0 .../Drivers/RCTEventAnimation.js | 0 .../Drivers/RCTFrameAnimation.js | 0 .../Drivers/RCTSpringAnimation.js | 0 .../Nodes/RCTAdditionAnimatedNode.js | 0 .../NativeAnimation/Nodes/RCTAnimatedNode.js | 0 .../Nodes/RCTDiffClampAnimatedNode.js | 0 .../Nodes/RCTDivisionAnimatedNode.js | 0 .../Nodes/RCTInterpolationAnimatedNode.js | 0 .../Nodes/RCTModuloAnimatedNode.js | 0 .../Nodes/RCTMultiplicationAnimatedNode.js | 0 .../Nodes/RCTPropsAnimatedNode.js | 0 .../Nodes/RCTStyleAnimatedNode.js | 0 .../Nodes/RCTSubtractionAnimatedNode.js | 0 .../Nodes/RCTTrackingAnimatedNode.js | 0 .../Nodes/RCTTransformAnimatedNode.js | 0 .../Nodes/RCTValueAnimatedNode.js | 0 .../NativeAnimation/RCTAnimationUtils.js | 0 .../RCTNativeAnimatedModule.js | 0 .../RCTNativeAnimatedNodesManager.js | 0 .../ReactDom/modules/RCTAppState.js | 0 .../ReactDom/modules/RCTAsyncLocalStorage.js | 0 .../ReactDom/modules/RCTBlobManager.js | 0 .../ReactDom/modules/RCTDevSettings.js | 0 .../ReactDom/modules/RCTDeviceEventManager.js | 0 .../ReactDom/modules/RCTDeviceInfo.js | 0 .../ReactDom/modules/RCTExceptionsManager.js | 0 .../ReactDom/modules/RCTHistory.js | 8 +- .../ReactDom/modules/RCTI18nManager.js | 0 .../ReactDom/modules/RCTKeyboardObserver.js | 0 .../ReactDom/modules/RCTLinkingManager.js | 0 .../ReactDom/modules/RCTNativeEventEmitter.js | 0 .../RCTNativeViewHierarchyOptimizer.js | 0 .../ReactDom/modules/RCTNetworkingNative.js | 0 .../ReactDom/modules/RCTPlatform.js | 17 +- .../ReactDom/modules/RCTSourceCode.js | 0 .../ReactDom/modules/RCTStatusBarManager.js | 0 .../ReactDom/modules/RCTTiming.js | 0 .../ReactDom/modules/RCTTouchEvent.js | 0 .../ReactDom/modules/RCTTouchHandler.js | 0 .../ReactDom/modules/RCTUIManager.js | 8 +- .../RCTUIManagerObserverCoordinator.js | 0 .../ReactDom/modules/RCTVibration.js | 0 .../ReactDom/modules/RCTWebSocketModule.js | 0 .../ReactDom/modules/RedBox/RCTRedBox.js | 0 .../ReactDom/utils/BundleFromRoot.js | 0 .../ReactDom/utils/CanUse.js | 0 .../ReactDom/utils/ColorArrayFromHexARGB.js | 0 .../ReactDom/utils/Guid.js | 0 .../ReactDom/utils/Instrument.js | 0 .../ReactDom/utils/NativeMatrixMath.js | 0 .../ReactDom/utils/isIOS.js | 0 .../ReactDom/utils/prefixInlineStyles.js | 2 +- .../ReactDom/utils/static.js | 0 .../ReactDom/views/Image/RCTImageLoader.js | 32 + .../ReactDom/views/Image/RCTImageSource.js | 0 .../ReactDom/views/Image/RCTImageView.js | 0 .../views/Image/RCTImageViewManager.js | 0 .../views/RCTActivityIndicatorView.js | 0 .../views/RCTActivityIndicatorViewManager.js | 0 .../ReactDom/views/RCTComponent.js | 0 .../ReactDom/views/RCTComponentData.js | 0 .../ReactDom/views/RCTPropDescription.js | 0 .../ReactDom/views/RCTPropTypes.js | 0 .../ReactDom/views/RCTRootShadowView.js | 0 .../views/RCTScrollContentViewManager.js | 0 .../ReactDom/views/RCTScrollView.js | 0 .../ReactDom/views/RCTScrollViewLocalData.js | 0 .../ReactDom/views/RCTScrollViewManager.js | 8 +- .../ReactDom/views/RCTShadowScrollView.js | 0 .../ReactDom/views/RCTShadowView.js | 0 .../ReactDom/views/RCTView.js | 0 .../ReactDom/views/RCTViewManager.js | 0 .../SafeAreaView/RCTSafeAreaViewManager.js | 0 .../ReactDom/views/Switch/RCTSwitch.js | 0 .../ReactDom/views/Switch/RCTSwitchManager.js | 7 + .../views/Text/Metrics/TextMetrics.js | 0 .../ReactDom/views/Text/Metrics/TextStyle.js | 0 .../views/Text/Metrics/deepCopyProperties.js | 0 .../ReactDom/views/Text/RCTRawText.js | 0 .../ReactDom/views/Text/RCTRawTextManager.js | 0 .../ReactDom/views/Text/RCTShadowRawText.js | 0 .../ReactDom/views/Text/RCTShadowText.js | 0 .../views/Text/RCTSharedTextValues.js | 0 .../ReactDom/views/Text/RCTText.js | 0 .../ReactDom/views/Text/RCTTextInput.js | 0 .../views/Text/RCTTextInputManager.js | 0 .../ReactDom/views/Text/RCTTextManager.js | 0 .../ReactDom/views/WebView/RCTWebView.js | 0 .../views/WebView/RCTWebViewManager.js | 0 .../react-native-dom-renderer/package.json | 81 ++ .../scripts/babel-plugin-haste-require.js | 0 .../scripts/eslint-module-resolver-haste.js | 0 packages/react-native-dom/.gitignore | 15 +- .../Libraries/Alert/RCTAlertManager.dom.js | 16 - .../ActivityIndicator.dom.js | 187 --- .../Components/AppleTV/TVEventHandler.dom.js | 23 - .../Components/Navigation/NavigatorIOS.dom.js | 13 - .../Components/ReactNative/UIManager.dom.js | 88 -- .../SafeAreaView/SafeAreaView.dom.js | 48 - .../ScrollView/ScrollViewStickyHeader.dom.js | 62 - .../Libraries/Components/Slider/Slider.dom.js | 15 - .../Components/StatusBar/StatusBarIOS.dom.js | 16 - .../Libraries/Components/Switch/Switch.dom.js | 156 --- .../Components/TabBarIOS/TabBarIOS.dom.js | 38 - .../Components/TabBarIOS/TabBarItemIOS.dom.js | 42 - .../Components/TextInput/TextInput.dom.js | 967 ------------- .../TextInput/TextInputState.dom.js | 91 -- .../TimePickerAndroid.dom.js | 22 - .../ToolbarAndroid/ToolbarAndroid.dom.js | 13 - .../Touchable/TouchableNativeFeedback.dom.js | 13 - .../View/PlatformViewPropTypes.dom.js | 6 - .../ViewPager/ViewPagerAndroid.dom.js | 13 - .../Components/WebView/WebView.dom.js | 673 --------- .../Core/Devtools/setupDevtools.dom.js | 69 - .../Libraries/Image/Image.dom.js | 419 ------ .../Libraries/Network/RCTNetworking.dom.js | 93 -- .../Libraries/RCTTest/SnapshotViewIOS.dom.js | 13 - .../Libraries/Utilities/BackHandler.dom.js | 101 -- .../Libraries/Utilities/HMRLoadingView.dom.js | 32 - .../Libraries/Utilities/Platform.dom.js | 26 - .../Libraries/Vibration/VibrationIOS.dom.js | 23 - .../UI/YellowBoxInspectorHeader.dom.js | 120 -- .../Libraries/polyfills/setBabelHelper.js | 34 - packages/react-native-dom/README.md | 4 - packages/react-native-dom/RNTester.md | 52 - .../templates => dom}/bootstrap.js | 6 +- .../generator-dom/templates => dom}/entry.js | 0 .../templates => dom}/index.html | 0 packages/react-native-dom/generateDom.js | 2 + packages/react-native-dom/index.dom.js | 721 ++++++++++ packages/react-native-dom/just-task.js | 57 + .../react-native-dom/local-cli/.npmignore | 2 - .../react-native-dom/local-cli/constants.js | 2 - .../local-cli/core/dom/findDepConfigPath.js | 36 - .../core/dom/findVendorModulePath.js | 28 - .../local-cli/core/dom/getDomRequirePath.js | 34 - .../local-cli/core/dom/index.js | 29 - .../local-cli/generate-dom.js | 23 - .../local-cli/generator-dom/index.js | 64 - .../generator-dom/templates/App.dom.js | 41 - .../generator-dom/templates/_gitignore | 2 - .../local-cli/generator-utils.js | 52 - packages/react-native-dom/local-cli/index.js | 3 - .../local-cli/link/dom/getDependencyConfig.js | 6 - .../local-cli/link/dom/isInstalled.js | 22 - .../link/dom/registerNativeModule.js | 26 - .../link/dom/unregisterNativeModule.js | 15 - .../link/dom/updateDependencyConfig.js | 5 - .../link/dom/updateVendorModuleFile.js | 39 - .../react-native-dom/local-cli/link/index.js | 7 - .../react-native-dom/local-cli/platform.js | 6 - .../local-cli/runDom/runDom.js | 120 -- packages/react-native-dom/metro.config.js | 73 +- packages/react-native-dom/package.json | 129 +- .../react-native-dom/react-native.config.js | 15 + .../scripts/copyRNLibraries.js | 91 ++ .../Libraries/Alert/RCTAlertManager.dom.js | 26 + .../AccessibilityInfo.dom.js | 2 +- .../Libraries/Components/Button.dom.js | 131 +- .../Components/CheckBox/CheckBox.dom.js | 2 +- .../Components/Clipboard/Clipboard.dom.js | 0 .../DatePicker/DatePickerIOS.dom.js | 2 +- .../DatePickerAndroid.dom.js | 0 .../DrawerAndroid/DrawerLayoutAndroid.dom.js | 2 +- .../MaskedView/MaskedViewIOS.dom.js | 3 +- .../Components/Picker/PickerAndroid.dom.js | 6 +- .../Components/Picker/PickerIOS.dom.js | 4 +- .../ProgressBarAndroid.dom.js | 2 +- .../ProgressViewIOS/ProgressViewIOS.dom.js | 2 +- .../Components/ScrollView/ScrollView.dom.js | 1221 +++++++++++++++++ .../SegmentedControlIOS.dom.js | 2 +- .../Components/TextInput/TextInput.dom.js | 1173 ++++++++++++++++ .../ToastAndroid/ToastAndroid.dom.js | 0 .../View/ViewNativeComponent.dom.js | 79 ++ .../EventEmitter/NativeEventEmitter.dom.js | 28 +- .../src/Libraries/Image/Image.dom.js | 210 +++ .../Libraries/Image/NativeImageLoaderDOM.js | 32 + .../Libraries/Network/NativeNetworkingDOM.js | 38 + .../Libraries/Network/NetInfo.dom.js | 0 .../Libraries/Network/RCTNetworking.dom.js | 63 + .../Libraries/Settings/Settings.dom.js | 8 +- .../Libraries/Utilities/BackHandler.dom.js | 123 ++ .../Libraries/Utilities/LoadingView.dom.js | 40 + .../Utilities/NativePlatformConstantsDOM.js | 34 + .../src/Libraries/Utilities/Platform.dom.js | 66 + .../Libraries/Vibration/Vibration.dom.js | 56 +- scripts/smoke.js | 8 +- 230 files changed, 5151 insertions(+), 4393 deletions(-) create mode 100644 packages/react-native-dom-cli/.babelrc create mode 100644 packages/react-native-dom-cli/.gitignore create mode 100644 packages/react-native-dom-cli/package.json create mode 100644 packages/react-native-dom-cli/src/buildDom/buildDom.js create mode 100644 packages/react-native-dom-cli/src/generator-dom/index.js create mode 100644 packages/react-native-dom-cli/src/index.js create mode 100644 packages/react-native-dom-cli/src/runDom/runDom.js create mode 100644 packages/react-native-dom-init/.babelrc create mode 100644 packages/react-native-dom-init/.gitignore create mode 100644 packages/react-native-dom-init/index.js create mode 100644 packages/react-native-dom-init/package.json create mode 100644 packages/react-native-dom-init/src/addCommandsToPackageJson.js create mode 100644 packages/react-native-dom-init/src/getReactNativeProject.js create mode 100644 packages/react-native-dom-init/src/index.js create mode 100644 packages/react-native-dom-init/src/installRNDom.js create mode 100644 packages/react-native-dom-init/src/requireGenerateRNDom.js create mode 100644 packages/react-native-dom-init/src/userError.js create mode 100644 packages/react-native-dom-init/src/utils.js create mode 100644 packages/react-native-dom-renderer/.babelrc create mode 100644 packages/react-native-dom-renderer/.gitignore rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/DevSupport/RCTDevLoadingView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/DevSupport/RCTDevMenu.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/ReactDom.js (99%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/base/NotificationCenter.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/base/UIBorderView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/base/UIChildContainerView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/base/UIHitSlopView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/base/UIView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTBridge.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTBridge.worker.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTBridgeMethod.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTEventDispatcher.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTModule.js (75%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTModuleConfig.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/bridge/RCTRootView.js (99%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/defs/InternalLib.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/LayoutAnimation/RCTKeyframeGenerator.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/LayoutAnimation/RCTLayoutAnimationManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/LayoutAnimation/__tests__/__snapshots__/keyframeGenerator.test.js.snap (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/LayoutAnimation/__tests__/keyframeGenerator.test.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Drivers/RCTAnimationDriver.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Drivers/RCTDecayAnimation.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Drivers/RCTEventAnimation.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Drivers/RCTFrameAnimation.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Drivers/RCTSpringAnimation.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTAdditionAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTDivisionAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTInterpolationAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTModuloAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTMultiplicationAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTPropsAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTStyleAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTSubtractionAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTTrackingAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTTransformAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/Nodes/RCTValueAnimatedNode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/RCTAnimationUtils.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/RCTNativeAnimatedModule.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/NativeAnimation/RCTNativeAnimatedNodesManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTAppState.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTAsyncLocalStorage.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTBlobManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTDevSettings.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTDeviceEventManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTDeviceInfo.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTExceptionsManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTHistory.js (89%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTI18nManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTKeyboardObserver.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTLinkingManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTNativeEventEmitter.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTNativeViewHierarchyOptimizer.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTNetworkingNative.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTPlatform.js (59%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTSourceCode.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTStatusBarManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTTiming.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTTouchEvent.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTTouchHandler.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTUIManager.js (98%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTUIManagerObserverCoordinator.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTVibration.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RCTWebSocketModule.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/modules/RedBox/RCTRedBox.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/BundleFromRoot.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/CanUse.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/ColorArrayFromHexARGB.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/Guid.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/Instrument.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/NativeMatrixMath.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/isIOS.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/prefixInlineStyles.js (98%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/utils/static.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Image/RCTImageLoader.js (60%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Image/RCTImageSource.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Image/RCTImageView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Image/RCTImageViewManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTActivityIndicatorView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTActivityIndicatorViewManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTComponent.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTComponentData.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTPropDescription.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTPropTypes.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTRootShadowView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTScrollContentViewManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTScrollView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTScrollViewLocalData.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTScrollViewManager.js (93%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTShadowScrollView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTShadowView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/RCTViewManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/SafeAreaView/RCTSafeAreaViewManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Switch/RCTSwitch.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Switch/RCTSwitchManager.js (83%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/Metrics/TextMetrics.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/Metrics/TextStyle.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/Metrics/deepCopyProperties.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTRawText.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTRawTextManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTShadowRawText.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTShadowText.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTSharedTextValues.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTText.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTTextInput.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTTextInputManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/Text/RCTTextManager.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/WebView/RCTWebView.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/ReactDom/views/WebView/RCTWebViewManager.js (100%) create mode 100644 packages/react-native-dom-renderer/package.json rename packages/{react-native-dom => react-native-dom-renderer}/scripts/babel-plugin-haste-require.js (100%) rename packages/{react-native-dom => react-native-dom-renderer}/scripts/eslint-module-resolver-haste.js (100%) delete mode 100644 packages/react-native-dom/Libraries/Alert/RCTAlertManager.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/ActivityIndicator/ActivityIndicator.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/AppleTV/TVEventHandler.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/Navigation/NavigatorIOS.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/ReactNative/UIManager.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/SafeAreaView/SafeAreaView.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/ScrollView/ScrollViewStickyHeader.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/Slider/Slider.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/StatusBar/StatusBarIOS.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/Switch/Switch.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarIOS.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarItemIOS.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/TextInput/TextInput.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/TextInput/TextInputState.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/TimePickerAndroid/TimePickerAndroid.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/ToolbarAndroid/ToolbarAndroid.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/Touchable/TouchableNativeFeedback.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/View/PlatformViewPropTypes.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/ViewPager/ViewPagerAndroid.dom.js delete mode 100644 packages/react-native-dom/Libraries/Components/WebView/WebView.dom.js delete mode 100644 packages/react-native-dom/Libraries/Core/Devtools/setupDevtools.dom.js delete mode 100644 packages/react-native-dom/Libraries/Image/Image.dom.js delete mode 100644 packages/react-native-dom/Libraries/Network/RCTNetworking.dom.js delete mode 100644 packages/react-native-dom/Libraries/RCTTest/SnapshotViewIOS.dom.js delete mode 100644 packages/react-native-dom/Libraries/Utilities/BackHandler.dom.js delete mode 100644 packages/react-native-dom/Libraries/Utilities/HMRLoadingView.dom.js delete mode 100644 packages/react-native-dom/Libraries/Utilities/Platform.dom.js delete mode 100644 packages/react-native-dom/Libraries/Vibration/VibrationIOS.dom.js delete mode 100644 packages/react-native-dom/Libraries/YellowBox/UI/YellowBoxInspectorHeader.dom.js delete mode 100644 packages/react-native-dom/Libraries/polyfills/setBabelHelper.js delete mode 100644 packages/react-native-dom/README.md delete mode 100644 packages/react-native-dom/RNTester.md rename packages/react-native-dom/{local-cli/generator-dom/templates => dom}/bootstrap.js (72%) rename packages/react-native-dom/{local-cli/generator-dom/templates => dom}/entry.js (100%) rename packages/react-native-dom/{local-cli/generator-dom/templates => dom}/index.html (100%) create mode 100644 packages/react-native-dom/generateDom.js create mode 100644 packages/react-native-dom/index.dom.js create mode 100644 packages/react-native-dom/just-task.js delete mode 100644 packages/react-native-dom/local-cli/.npmignore delete mode 100644 packages/react-native-dom/local-cli/constants.js delete mode 100644 packages/react-native-dom/local-cli/core/dom/findDepConfigPath.js delete mode 100644 packages/react-native-dom/local-cli/core/dom/findVendorModulePath.js delete mode 100644 packages/react-native-dom/local-cli/core/dom/getDomRequirePath.js delete mode 100644 packages/react-native-dom/local-cli/core/dom/index.js delete mode 100644 packages/react-native-dom/local-cli/generate-dom.js delete mode 100644 packages/react-native-dom/local-cli/generator-dom/index.js delete mode 100644 packages/react-native-dom/local-cli/generator-dom/templates/App.dom.js delete mode 100644 packages/react-native-dom/local-cli/generator-dom/templates/_gitignore delete mode 100644 packages/react-native-dom/local-cli/generator-utils.js delete mode 100644 packages/react-native-dom/local-cli/index.js delete mode 100644 packages/react-native-dom/local-cli/link/dom/getDependencyConfig.js delete mode 100644 packages/react-native-dom/local-cli/link/dom/isInstalled.js delete mode 100644 packages/react-native-dom/local-cli/link/dom/registerNativeModule.js delete mode 100644 packages/react-native-dom/local-cli/link/dom/unregisterNativeModule.js delete mode 100644 packages/react-native-dom/local-cli/link/dom/updateDependencyConfig.js delete mode 100644 packages/react-native-dom/local-cli/link/dom/updateVendorModuleFile.js delete mode 100644 packages/react-native-dom/local-cli/link/index.js delete mode 100644 packages/react-native-dom/local-cli/platform.js delete mode 100644 packages/react-native-dom/local-cli/runDom/runDom.js create mode 100644 packages/react-native-dom/react-native.config.js create mode 100644 packages/react-native-dom/scripts/copyRNLibraries.js create mode 100644 packages/react-native-dom/src/Libraries/Alert/RCTAlertManager.dom.js rename packages/react-native-dom/{ => src}/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js (83%) rename packages/react-native-dom/{ => src}/Libraries/Components/Button.dom.js (58%) rename packages/react-native-dom/{ => src}/Libraries/Components/CheckBox/CheckBox.dom.js (84%) rename packages/react-native-dom/{ => src}/Libraries/Components/Clipboard/Clipboard.dom.js (100%) rename packages/react-native-dom/{ => src}/Libraries/Components/DatePicker/DatePickerIOS.dom.js (83%) rename packages/react-native-dom/{ => src}/Libraries/Components/DatePickerAndroid/DatePickerAndroid.dom.js (100%) rename packages/react-native-dom/{ => src}/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js (84%) rename packages/react-native-dom/{ => src}/Libraries/Components/MaskedView/MaskedViewIOS.dom.js (84%) rename packages/react-native-dom/{ => src}/Libraries/Components/Picker/PickerAndroid.dom.js (71%) rename packages/react-native-dom/{ => src}/Libraries/Components/Picker/PickerIOS.dom.js (74%) rename packages/react-native-dom/{ => src}/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js (84%) rename packages/react-native-dom/{ => src}/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js (85%) create mode 100644 packages/react-native-dom/src/Libraries/Components/ScrollView/ScrollView.dom.js rename packages/react-native-dom/{ => src}/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js (84%) create mode 100644 packages/react-native-dom/src/Libraries/Components/TextInput/TextInput.dom.js rename packages/react-native-dom/{ => src}/Libraries/Components/ToastAndroid/ToastAndroid.dom.js (100%) create mode 100644 packages/react-native-dom/src/Libraries/Components/View/ViewNativeComponent.dom.js rename packages/react-native-dom/{ => src}/Libraries/EventEmitter/NativeEventEmitter.dom.js (67%) create mode 100644 packages/react-native-dom/src/Libraries/Image/Image.dom.js create mode 100644 packages/react-native-dom/src/Libraries/Image/NativeImageLoaderDOM.js create mode 100644 packages/react-native-dom/src/Libraries/Network/NativeNetworkingDOM.js rename packages/react-native-dom/{ => src}/Libraries/Network/NetInfo.dom.js (100%) create mode 100644 packages/react-native-dom/src/Libraries/Network/RCTNetworking.dom.js rename packages/react-native-dom/{ => src}/Libraries/Settings/Settings.dom.js (72%) create mode 100644 packages/react-native-dom/src/Libraries/Utilities/BackHandler.dom.js create mode 100644 packages/react-native-dom/src/Libraries/Utilities/LoadingView.dom.js create mode 100644 packages/react-native-dom/src/Libraries/Utilities/NativePlatformConstantsDOM.js create mode 100644 packages/react-native-dom/src/Libraries/Utilities/Platform.dom.js rename packages/react-native-dom/{ => src}/Libraries/Vibration/Vibration.dom.js (59%) diff --git a/README.md b/README.md index 814ac97cc..be174ae98 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ An experimental, comprehensive port of React Native to the web. Native on mobile, all of your react components/app logic are run in web worker, leaving the main thread to entirely focus on rendering. - **Same layout behavior as React Native on mobile:** Powered by custom bindings - to Yoga and compiled to WebAssembly, avoid layout inconsistencies between - your native and web projects. + to Yoga and compiled to WebAssembly, avoid layout inconsistencies between your + native and web projects. - **Built with the same bundler used for existing React Native platforms:** Build both the "native" main and JS threads with the Metro Bundler along with all the developer experience features it provides. @@ -15,7 +15,8 @@ An experimental, comprehensive port of React Native to the web. bridge, expose DOM-specific APIs in a more generic way that can easily be made into a cross-platform module. -To see it in action, check out these live demos: +To see it in action, check out these live demos: (TODO: demos are not updated +with latest bundles) - [Movies Demo](https://rndom-movie-demo.now.sh) - [RNTester (component playground used for manual testing)](https://rntester.now.sh) @@ -32,10 +33,13 @@ For the best introduction to this project, check out ## **WARNING** -This project is still highly experimental and many aspects of it are subject to +This project is in experimental stage and many aspects of it are subject to breaking changes, continue at your own risk. ---- +please note: current version of react-native-dom is compatible only with +~0.62.\* of react-native. + +## ex : react-native init [project name] --version 0.62.2 ## Getting Started @@ -54,34 +58,32 @@ yarn global add react-native-cli Next, initialize your React Native project. ``` -react-native init [project name] +react-native init [project name] --version 0.62.2 ``` -Then, `cd` into your project and install `rnpm-plugin-dom` into your -`devDependencies`, after which you can initialize your React Native DOM -scaffolding with the `react-native dom` command. +Next, Install react-native-dom-init CLI Globally ``` -npm install --save-dev rnpm-plugin-dom +npm install -g react-native-dom-init # or -yarn add --dev rnpm-plugin-dom - -# Add DOM support to your React Native project -react-native dom +yarn global add react-native-dom-init ``` +Then, `cd` into your project and run command `react-native-dom-init` after which +react-native project will be initialized to react-native-dom + To run your initialized project in your browser, you can either: - Start the packager yourself using `react-native start` and navigate open your browser to `localhost:8081/dom` -- Leverage the built-in rnpm command `react-native run-dom` which will start the - packager and open the browser to the correct URL for you +- Leverage the built-in react-native cli command `react-native run-dom` which + will start the packager and open the browser to the correct URL for you **NOTE:** After setting up the DOM platform you may need to run `react-native start` with the `--reset-cache` flag at least once if you recieve an error message like `Unable to resolve module AccessibilityInfo`. -### Overview of files generated by the RNPM plugin +### Overview of files generated by the react-native-dom-init cli - `dom/bootstrap.js` - Entry point to the main thread bundle where you can set runtime configuration options, register custom native modules, or any other JS @@ -90,10 +92,6 @@ an error message like `Unable to resolve module AccessibilityInfo`. importing your App's entry point from the top-level folder of your project. - `dom/index.html` - HTML file which is what references and loads the JS bundles. -- (conditionally) `rn-cli.config.js` - Depending on if the project already has - one, the rnpm plugin will either create it with the proper configuration - options to support the DOM platform or will simply add the necessary entries - to your existing one. --- @@ -119,41 +117,17 @@ end of your development url (e.g. localhost:8081/dom?devtools) ## Building for Production -A built-in script for performing a production build is still in the backlog but -here is a manual script which does so (assuming the same directory structure -that gets generated from the rnpm plugin). - -```shell -# Ensure development-speecific code is stripped from the bundle -export NODE_ENV=production - -# Make the dist directory, or the build command below will fail. -mkdir -p ./dom/dist - -# Build the main thread bundle -react-native bundle \ - --config $(pwd)/rn-cli.config.js \ - --dev false \ - --platform dom \ - --entry-file ./dom/bootstrap.js \ - --assets-dest ./dom/dist \ - --bundle-output ./dom/dist/bootstrap.bundle - -# Build the JS thread bundle -react-native bundle \ - --config $(pwd)/rn-cli.config.js \ - --dev false \ - --entry-file ./dom/entry.js \ - --platform dom \ - --bundle-output ./dom/dist/entry.bundle \ - --assets-dest ./dom/dist - -# Copy the index.html file to the build destination -cp dom/index.html dom/dist/index.html +A built-in script for performing a production build is implemented and can be +invoked using + +``` +npm buildDom +or +yarn buildDom ``` The resulting folder in `dom/dist` will contain static HTML & JS ready to be -deployed to your provider of choice. +deployed to your hosting provider of choice. --- @@ -164,55 +138,30 @@ deployed to your provider of choice. The API for this is going to be overhauled soon with accompanying documentation. If you want to see what it currently looks like take a look at some of the built in native modules such as -[AsyncLocalStorage](../master/packages/react-native-dom/ReactDom/modules/RCTAsyncLocalStorage.js) +[AsyncLocalStorage](../master/packages/react-native-dom-renderer/ReactDom/modules/RCTAsyncLocalStorage.js) --- ## Repository Structure -This project is a lerna-managed monorepo with all the projects living in the -`packages` folder. +This project is a workspaces managed monorepo with all the projects living in +the `packages` folder and Library in `react-native-dom` folder. ### Package Overview - `react-native-dom` - The library itself (this is most likely the package you're interested in). -- `rnpm-plugin-dom` - RNPM plugin primarily used for bootstrapping DOM support - into a React Native project. +- `react-native-dom-cli` - CLI to build and run React Native for dom apps +- `react-native-dom-init` - CLI to bootstrap the addition of the dom platform to + react-native projects +- `react-native-dom-renderer` - Browser Implementation of react-native-dom + components - `rndom-*` - Custom web components (built with [svelte](https://svelte.technology)) used for some of the built-in widgets/views in `react-native-dom`. -One noticeable omission to the list of packages is the custom build of Yoga -which can be found in -[this separate repo](https://github.com/vincentriemer/yoga-dom). `yoga-dom` is -not included in this monorepo due to requiring a significantly different build -environment than this repo's entirely JS codebase. - --- -### Running RNTester/Examples - -To run the examples located in the `react-native-dom` source, run the following -commands from the root of the monorepo: - -```sh -# be sure to update the git submodules to pull the RNTester code -git submodule update --init - -# install dependencies -yarn && yarn compile - -# start the react-native packager -yarn run-examples -``` - -Then navigate to `localhost:8081/Examples` and choose which example you would -like to see. - -A live deployment of the RNTester project (used primarily for manually testing -changes) can be found at [rntester.now.sh](https://rntester.now.sh) - ## Contributors Thanks goes to these wonderful people diff --git a/packages/react-native-dom-cli/.babelrc b/packages/react-native-dom-cli/.babelrc new file mode 100644 index 000000000..69f50d59a --- /dev/null +++ b/packages/react-native-dom-cli/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["env"] +} \ No newline at end of file diff --git a/packages/react-native-dom-cli/.gitignore b/packages/react-native-dom-cli/.gitignore new file mode 100644 index 000000000..504f3eb89 --- /dev/null +++ b/packages/react-native-dom-cli/.gitignore @@ -0,0 +1,4 @@ +node_modules +.npmrc +build +lib \ No newline at end of file diff --git a/packages/react-native-dom-cli/package.json b/packages/react-native-dom-cli/package.json new file mode 100644 index 000000000..1ec3e0c39 --- /dev/null +++ b/packages/react-native-dom-cli/package.json @@ -0,0 +1,39 @@ +{ + "name": "react-native-dom-cli", + "version": "1.0.0", + "description": "CLI for react-native-dom", + "main": "build/index.js", + "homepage": "https://github.com/vincentriemer/react-native-dom", + "bugs": { + "url": "https://github.com/vincentriemer/react-native-dom/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/vincentriemer/react-native-dom.git" + }, + "license": "MIT", + "scripts": { + "compile": "babel src -d build", + "watch": "watch \"yarn compile\" src" + }, + "files": [ + "build" + ], + "keywords": [ + "react-native", + "react-native-dom", + "react-native-dom-cli" + ], + "devDependencies": { + "babel": "^6.23.0", + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.7.0", + "watch": "^1.0.2" + }, + "dependencies": { + "chalk": "^4.1.0", + "fs-extra": "^9.0.1", + "opn": "^6.0.0", + "wait-port": "^0.2.9" + } +} diff --git a/packages/react-native-dom-cli/src/buildDom/buildDom.js b/packages/react-native-dom-cli/src/buildDom/buildDom.js new file mode 100644 index 000000000..ad8ac6a25 --- /dev/null +++ b/packages/react-native-dom-cli/src/buildDom/buildDom.js @@ -0,0 +1,95 @@ +const { execSync } = require("child_process"); +const fs = require("fs"); +const path = require("path"); +const chalk = require("chalk"); + +const generateBundles = (loc) => { + const source = path.resolve(loc, "../") + copyFiles(source, loc) + editFiles(loc); + executeBundleCommands(loc); + clearBundleFiles(loc); +} + +const cleanDistFolder = (loc) => { + const files = fs.readdirSync(loc); + console.log(`cleaning ${chalk.yellow(loc.substring(loc.lastIndexOf("/")))} folder`) + for (const file of files) { + let stats = fs.statSync(`${loc}/${file}`); + if (stats.isDirectory()) { + cleanDistFolder(`${loc}/${file}`) + } else { + fs.unlinkSync(`${loc}/${file}`); + } + } +} + +const copyFiles = (source, dest) => { + console.log(`copying files from ${chalk.yellow("dom")} folder to ${chalk.yellow("dist")} folder`) + const files = fs.readdirSync(source); + for (const file of files) { + if (file !== "dist") { + fs.copyFileSync(`${source}/${file}`, `${dest}/${file}`); + } + } +} + +const editFiles = (loc) => { + const files = fs.readdirSync(loc); + console.log(`preparing files for bundling`); + for (const file of files) { + let stats = fs.statSync(`${loc}/${file}`); + if (stats.isDirectory()) { + editFiles(`${loc}/${file}`) + } else { + let data = fs.readFileSync(`${loc}/${file}`, 'utf-8'); + data = data.replace(/.bundle/g, ".bundle.js"); + fs.writeFileSync(`${loc}/${file}`, data, 'utf-8'); + } + } +} + +const executeBundleCommands = (loc) => { + const bootstrapEntry = `${loc}/bootstrap.js`; + const bootstrapBundle = `${loc}/bootstrap.bundle.js`; + const appEntry = `${loc}/entry.js`; + const appBundle = `${loc}/entry.bundle.js`; + console.log(`bundling ${chalk.yellow("bootstrap.js")}`); + execSync(`react-native bundle --dev false --platform dom --entry-file ${bootstrapEntry} --bundle-output ${bootstrapBundle} --assets-dest ${loc}`); + console.log(`bundling ${chalk.green("bootstrap.js")} complete`); + console.log(`bundling ${chalk.yellow("entry.js")}`); + execSync(`react-native bundle --dev false --platform dom --entry-file ${appEntry} --bundle-output ${appBundle} --assets-dest ${loc}`); + console.log(`bundling ${chalk.green("entry.js")} complete`); +} + +const clearBundleFiles = (loc) => { + console.log(`getting bundle ready for deployment`); + const files = fs.readdirSync(loc); + for (const file of files) { + if (file !== "assets" && !file.match("bundle.js") && !file.match("index.html")) { + fs.unlinkSync(`${loc}/${file}`); + } + } +} +const initiateBundling = () => { + const distLoc = `${process.cwd()}/dom/dist`; + if (!fs.existsSync(distLoc)) { + console.log(`creating dist directory at location ${chalk.green(distLoc)}`); + fs.mkdirSync(distLoc); + } else { + cleanDistFolder(distLoc); + } + generateBundles(distLoc) + console.log(chalk.green(`bundling completed`)); +}; + +function buildDom(){ + process.env.NODE_ENV="production"; + initiateBundling(); +} + +module.exports = { + name: "build-dom", + description: "bundles app and dom native code for deployment", + func: buildDom +}; \ No newline at end of file diff --git a/packages/react-native-dom-cli/src/generator-dom/index.js b/packages/react-native-dom-cli/src/generator-dom/index.js new file mode 100644 index 000000000..fcab9a132 --- /dev/null +++ b/packages/react-native-dom-cli/src/generator-dom/index.js @@ -0,0 +1,3 @@ +export const copyTemplate = () => { + +} \ No newline at end of file diff --git a/packages/react-native-dom-cli/src/index.js b/packages/react-native-dom-cli/src/index.js new file mode 100644 index 000000000..a8be56e38 --- /dev/null +++ b/packages/react-native-dom-cli/src/index.js @@ -0,0 +1,26 @@ +import * as path from "path"; + +import * as fse from "fs-extra"; + +import * as fs from 'fs'; + +import runDom from './runDom/runDom'; + +import buildDom from './buildDom/buildDom'; + +export function generateDom(projectDir, name) { + + const templatePath = path.dirname( + require.resolve("react-native-dom/package.json", { + paths: [projectDir] + }) + ); + + fse.copySync(`${templatePath}\\dom`, `${projectDir}\\dom`); + fs.copyFileSync(`${templatePath}/dom/_npmrc`, `${projectDir}/.npmrc`) +} + +export const commands = [runDom, buildDom]; +// export const dependencyConfig = dependencyConfigDom; +// export const projectConfig = projectConfigDom; + diff --git a/packages/react-native-dom-cli/src/runDom/runDom.js b/packages/react-native-dom-cli/src/runDom/runDom.js new file mode 100644 index 000000000..e6ffc23f5 --- /dev/null +++ b/packages/react-native-dom-cli/src/runDom/runDom.js @@ -0,0 +1,121 @@ +"use strict"; + +const child_process = require("child_process"); +const spawn = child_process.spawn, + spawnSync = child_process.spawnSync; +const fs = require("fs"); +const path = require("path"); +const opn = require("opn"); +const fetch = require("node-fetch"); +const waitPort = require("wait-port"); + + +/** + * Indicates whether or not the packager is running. It returns a promise that + * when fulfilled can returns one out of these possible values: + * - `running`: the packager is running + * - `not_running`: the packager nor any process is running on the expected + * port. + * - `unrecognized`: one other process is running on the port we expect the + * packager to be running. + */ +function isPackagerRunning(packagerPort) { + return fetch(`http://localhost:${packagerPort}/status`).then( + (res) => + res + .text() + .then( + (body) => + body === "packager-status:running" ? "running" : "unrecognized" + ), + () => "not_running" + ); +} + +function startServerInNewWindow(port = process.env.RCT_METRO_PORT || 8081) { + const isWindows = /^win/.test(process.platform); + const scriptFile = isWindows + ? "launchPackager.bat" + : "launchPackager.command"; + const scriptsDir = path.join( + process.cwd(), + "node_modules/react-native/scripts" + ); + const launchPackagerScript = path.resolve(scriptsDir, scriptFile); + const procConfig = { cwd: scriptsDir }; + const terminal = process.env.REACT_TERMINAL; + + // setup the .packager.env file to ensure the packager starts on the right port + const packagerFile = isWindows ? '.packager.bat' : '.packager.env'; + const packagerEnvFile = path.join(scriptsDir, packagerFile); + const content = isWindows ? `set RCT_METRO_PORT=${port}` : `export RCT_METRO_PORT=${port}`; + // ensure we overwrite file by passing the 'w' flag + fs.writeFileSync(packagerEnvFile, content, { encoding: "utf8", flag: "w" }); + + if (process.platform === "darwin") { + if (terminal) { + return spawnSync( + "open", + ["-a", terminal, launchPackagerScript], + procConfig + ); + } + return spawnSync("open", [launchPackagerScript], procConfig); + } else if (process.platform === "linux") { + procConfig.detached = true; + if (terminal) { + return spawn( + terminal, + ["-e", "sh " + launchPackagerScript], + procConfig + ); + } + return spawn("sh", [launchPackagerScript], procConfig); + } else if (isWindows) { + procConfig.detached = true; + procConfig.stdio = "ignore"; + return spawn( + "cmd.exe", + ["/C", launchPackagerScript], + procConfig + ); + } else { + console.log( + chalk.red( + `Cannot start the packager. Unknown platform ${process.platform}` + ) + ); + } +} + +function runDom (_argv, config, args) { + args.root = args.root || process.cwd(); + args.port = args.port || 8081; + isPackagerRunning(args.port) + .then((res) => { + const isCurrentlyRunning = res === "running"; + if (!isCurrentlyRunning) { + startServerInNewWindow(args.port); + return waitPort({ + host: "localhost", + port: args.port + }); + } + }) + .then(() => { + opn(`http://localhost:${args.port}/dom`); + }); +} + +module.exports = { + name: "run-dom", + description: "builds your app and starts it in your default browser", + func: runDom, + options: [ + { + name: "--port [number]", + description: "port to run the packager from", + parse: val => Number(val) + } + ] +}; \ No newline at end of file diff --git a/packages/react-native-dom-init/.babelrc b/packages/react-native-dom-init/.babelrc new file mode 100644 index 000000000..2f01e1d61 --- /dev/null +++ b/packages/react-native-dom-init/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["env"] +} \ No newline at end of file diff --git a/packages/react-native-dom-init/.gitignore b/packages/react-native-dom-init/.gitignore new file mode 100644 index 000000000..cd209f65a --- /dev/null +++ b/packages/react-native-dom-init/.gitignore @@ -0,0 +1,3 @@ +node_modules +.npmrc +build \ No newline at end of file diff --git a/packages/react-native-dom-init/index.js b/packages/react-native-dom-init/index.js new file mode 100644 index 000000000..d2564af06 --- /dev/null +++ b/packages/react-native-dom-init/index.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./build'); \ No newline at end of file diff --git a/packages/react-native-dom-init/package.json b/packages/react-native-dom-init/package.json new file mode 100644 index 000000000..e86657886 --- /dev/null +++ b/packages/react-native-dom-init/package.json @@ -0,0 +1,41 @@ +{ + "name": "react-native-dom-init", + "version": "1.0.0", + "description": "CLI to add react-native-dom to existing react-native project", + "homepage": "https://github.com/vincentriemer/react-native-dom", + "bugs": { + "url": "https://github.com/vincentriemer/react-native-dom/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/vincentriemer/react-native-dom.git" + }, + "license": "MIT", + "bin": { + "react-native-dom-init": "index.js" + }, + "scripts": { + "compile": "babel src -d build", + "watch": "watch \"yarn compile\" src" + }, + "files": [ + "index.js", + "build" + ], + "keywords": [ + "react-native-dom-init", + "react-native-dom", + "react-native" + ], + "dependencies": { + "chalk": "^4.1.0", + "find-up": "^5.0.0", + "semver": "^7.3.4", + "yargs": "^16.1.1" + }, + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.7.0", + "watch": "^1.0.2" + } +} diff --git a/packages/react-native-dom-init/src/addCommandsToPackageJson.js b/packages/react-native-dom-init/src/addCommandsToPackageJson.js new file mode 100644 index 000000000..4a0e2718f --- /dev/null +++ b/packages/react-native-dom-init/src/addCommandsToPackageJson.js @@ -0,0 +1,25 @@ +import {sync} from 'find-up' +import * as fs from 'fs' +import { userError } from "./userError"; + +export const addCommandsToPackageJson = () => { + const cwd = process.cwd(); + const pkgJsonPath = sync("package.json", { cwd }); + if (!pkgJsonPath) { + userError( + "Unable to find package.json. This should be run from within an existing react-native project.", + "NO_PACKAGE_JSON" + ); + } + + const pkgJson = require(pkgJsonPath); + if (pkgJson.scripts) { + pkgJson.scripts["dom"] = "react-native run-dom"; + pkgJson.scripts["bundleDom"] = "react-native build-dom"; + } else { + pkgJson["scripts"] = {}; + pkgJson.scripts["dom"] = "react-native run-dom"; + pkgJson.scripts["bundleDom"] = "react-native build-dom"; + } + fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2)); +} \ No newline at end of file diff --git a/packages/react-native-dom-init/src/getReactNativeProject.js b/packages/react-native-dom-init/src/getReactNativeProject.js new file mode 100644 index 000000000..e4aeca71e --- /dev/null +++ b/packages/react-native-dom-init/src/getReactNativeProject.js @@ -0,0 +1,27 @@ +import * as findUp from 'find-up'; +import * as fs from 'fs'; +import { userError } from './userError'; + +export const getReactNativeProjectName = () => { + console.log('Reading project name from package.json...'); + const cwd = process.cwd(); + const pkgJsonPath = findUp.sync('package.json', {cwd}); + if (!pkgJsonPath) { + userError( + 'Unable to find package.json. This should be run from within an existing react-native project.', + 'NO_PACKAGE_JSON', + ); + } + let name = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')).name; + if (!name) { + const appJsonPath = findUp.sync('app.json', {cwd}); + if (appJsonPath) { + console.log('Reading project name from app.json...'); + name = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')).name; + } + } + if (!name) { + console.error('Please specify name in package.json or app.json'); + } + return name; +} \ No newline at end of file diff --git a/packages/react-native-dom-init/src/index.js b/packages/react-native-dom-init/src/index.js new file mode 100644 index 000000000..afeafa3da --- /dev/null +++ b/packages/react-native-dom-init/src/index.js @@ -0,0 +1,67 @@ +import * as yargs from 'yargs'; +import { red } from 'chalk'; +import { getReactNativeProjectName } from './getReactNativeProject'; +import { installRNDom } from './installRNDom'; +import { requireGenerateRNDom } from './requireGenerateRNDom'; +import {addCommandsToPackageJson} from "./addCommandsToPackageJson"; +import { string } from 'yargs'; + +const argv = yargs + .version(false) + .strict(true) + .options({ + verbose: { + type: 'boolean', + describe: 'Enables logging.', + default: false, + }, + domVersion: { + type: 'string', + describe: 'The version of react-native-dom to use', + default: '' + }, + includeCanary: { + type: "boolean", + describe: "When resolving compatible react-native-dom versions, if canary releases should be considered", + default: false + }, + exact: { + type: "boolean", + describe: "Install react-native-dom at an exact version", + default: false + } + + }) + .check(a => { + if (a._.length !== 0) { + throw `Unrecognized option ${a._}`; + } + return true; + }).argv; +if (argv.verbose) { + console.log(argv); +} +(() => { + try { + const name = getReactNativeProjectName(); + installRNDom(argv) + .then((isInstalled) => { + if (isInstalled === "installed"){ + addCommandsToPackageJson(); + const generateRNDom = requireGenerateRNDom(); + generateRNDom(process.cwd(), name); + } + }) + .catch((err) => { + console.log(err); + }) + } catch (error){ + const exitCode = error.exitCode || 'UNKNOWN_ERROR'; + if (exitCode !== 'SUCCESS') { + console.error(red(error.message)); + if (argv.verbose) { + console.error(error); + } + } + } +})() \ No newline at end of file diff --git a/packages/react-native-dom-init/src/installRNDom.js b/packages/react-native-dom-init/src/installRNDom.js new file mode 100644 index 000000000..8beecf1ed --- /dev/null +++ b/packages/react-native-dom-init/src/installRNDom.js @@ -0,0 +1,166 @@ +import { execSync } from "child_process"; +import * as fs from "fs"; + +import { green } from "chalk"; +import { sync } from "find-up"; +import {valid, major, minor, patch, validRange, satisfies} from "semver"; +import NPMRegistry from 'npm-registry' +import { isUri } from 'valid-url' + +import { isProjectUsingYarn } from "./utils"; +import { userError } from "./userError"; + +const PKG = "react-native-dom" +const npmConfigReg = execSync("npm config get registry").toString().trim(); +const registryUrl = isUri(npmConfigReg) ? npmConfigReg : "http://registry.npmjs.org" +const npm = new NPMRegistry({registry: registryUrl}); + +const getLatestRND = () => { + return new Promise((resolve, reject) => { + npm.packages.release(PKG, "latest", (err, releases) => { + if (err) { + console.log("in if") + reject(new Error("Could not find react-native-dom@latest.")); + } else if (!releases || releases.length === 0) { + console.log("in elif") + reject(new Error("Could not find react-native-dom@latest.")); + } else { + console.log("in resolve"); + resolve(releases[0].version); + } + }); + }); +} +const getMatchingVersion = (version) => { + console.log(`Checking for react-native-dom version matching ${version}...`); + return new Promise((resolve, reject) => { + npm.packages.range(PKG, version, (error, release) => { + if (error || !release) { + console.log("checking for latest") + return getLatestRND() + .then((latestVersion) => { + reject(new Error(`Could not find react-native-dom@${version}. Latest version of react-native-dom is ${latestVersion}, try switching to react-native-dom@${major(latestVersion)}.${minor(latestVersion)}.*.`)); + }) + .catch((error) => { + console.log("in catch", error); + reject(new Error(`Could not find react-native-dom@${version}.`)) + } + ); + } else { + resolve(release.version); + } + }) + }) +} + +const getRNVersion = () => { + const pkgJsonPath = require.resolve("react-native/package.json", { + paths: [process.cwd()], + }) + if (fs.existsSync(pkgJsonPath)) { + let rnVersion = require(pkgJsonPath).version; + if (rnVersion) { + const validVersion = valid(rnVersion); + if (validVersion) { + return `${major(validVersion)}.${minor(validVersion)}.${patch(validVersion)}` + } + } + } + userError( + 'Must be run from a project that already depends on react-native, and has react-native installed.', + 'NO_REACTNATIVE_FOUND', + ); +} + +const getAllRNDVersion = canary => { + return new Promise((resolve, reject) => { + npm.packages.releases(PKG, (err, releases) => { + if (err) return reject(err); + resolve( + Object.keys(releases) + .filter((release) => { + if (["latest", "canary"].includes(release)) return false; + if (!canary && release.includes("alpha")) return false; + return true; + }, {}) + .map((r) => releases[r]) + ); + }) + }) +} + +const getMatchingRNDVersion = (version, includeCanary) => { + if (version) { + const validVersion = valid(version); + const Range = validRange(version); + + if (validVersion || Range) { + return getMatchingVersion(version); + } else { + return Promise.resolve(version); + } + } else { + const rnVersion = getRNVersion(); + if (rnVersion) { + return getAllRNDVersion(includeCanary) + .then((releases) => { + releases.sort((a, b) => { + if (a.date < b.date) return 1; + if (a.date > b.date) return -1; + return 0; + }); + for (const release of releases) { + if ( + satisfies( + rnVersion, + release.peerDependencies["react-native"] + ) + ) + return release.version; + } + + throw new Error( + `No version of 'react-native-dom' found that satisfies a peer dependency on 'react-native@${rnVersion}'` + ); + }) + .catch((err) => { + throw new Error(err); + }) + } + } +}; +export const installRNDom = (argv) => { + return new Promise((resolve, reject) => { + const cwd = process.cwd(); + const execOptions = argv.verbose ? { stdio: "inherit" } : {}; + const version = argv.domVersion; + const includeCanary = argv.includeCanary; + const exact = argv.exact; + const pkgCmd = isProjectUsingYarn(process.cwd()) + ? "yarn add" + (exact ? " --exact" : "") + : "npm install" + (exact ? " --save-exact" : " --save"); + + + console.log(`Installing ${green("react-native-dom")}...`); + const pkgJsonPath = sync("package.json", { cwd }); + + if (!pkgJsonPath) { + userError( + "Unable to find package.json. This should be run from within an existing react-native project.", + "NO_PACKAGE_JSON" + ); + } + getMatchingRNDVersion(version, includeCanary) + .then(versionToInstall => { + console.log(versionToInstall); + const rnDomPackage = `${PKG}@${versionToInstall}`; + execSync(`${pkgCmd} ${rnDomPackage}`, execOptions); + resolve("installed") + }) + .catch(err => { + console.log(err); + reject(err); + }); + + }) +} diff --git a/packages/react-native-dom-init/src/requireGenerateRNDom.js b/packages/react-native-dom-init/src/requireGenerateRNDom.js new file mode 100644 index 000000000..f721fea68 --- /dev/null +++ b/packages/react-native-dom-init/src/requireGenerateRNDom.js @@ -0,0 +1,6 @@ +export const requireGenerateRNDom = () => { + const requirePath = require.resolve('react-native-dom/generateDom', { + paths: [process.cwd()], + }); + return require(requirePath); +} \ No newline at end of file diff --git a/packages/react-native-dom-init/src/userError.js b/packages/react-native-dom-init/src/userError.js new file mode 100644 index 000000000..7870f8f60 --- /dev/null +++ b/packages/react-native-dom-init/src/userError.js @@ -0,0 +1,10 @@ +export class UserError extends Error { + constructor(message, exitCode) { + super(message); + this.exitCode = exitCode; + } +} + +export const userError = (err, exitCode) => { + throw new UserError(err, exitCode); +} diff --git a/packages/react-native-dom-init/src/utils.js b/packages/react-native-dom-init/src/utils.js new file mode 100644 index 000000000..8e5fe9627 --- /dev/null +++ b/packages/react-native-dom-init/src/utils.js @@ -0,0 +1,5 @@ +import * as findUp from 'find-up'; + +export const isProjectUsingYarn = cwd => { + return !!findUp.sync('yarn.lock', {cwd}); +} \ No newline at end of file diff --git a/packages/react-native-dom-renderer/.babelrc b/packages/react-native-dom-renderer/.babelrc new file mode 100644 index 000000000..4bf769797 --- /dev/null +++ b/packages/react-native-dom-renderer/.babelrc @@ -0,0 +1,51 @@ +{ + "presets": ["@babel/flow", "module:metro-react-native-babel-preset"], + "plugins": [ + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-object-rest-spread", + ["@babel/plugin-proposal-nullish-coalescing-operator", { "loose": true }], + [ + "@babel/plugin-transform-runtime", + { + "helpers": true, + "regenerator": true + } + ], + "transform-inline-environment-variables", + "preval", + "./scripts/babel-plugin-haste-require" + ], + "env": { + "lib": { + "presets": ["@babel/flow"] + }, + "production": { + "plugins": [ + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-object-rest-spread", + [ + "@babel/plugin-proposal-nullish-coalescing-operator", + { "loose": true } + ], + [ + "@babel/plugin-transform-runtime", + { + "helpers": true, + "regenerator": true + } + ], + "transform-inline-environment-variables", + "preval", + [ + "module-resolver", + { + "alias": { + "ReactDom": "./lib/ReactDom.js" + } + } + ], + "./scripts/babel-plugin-haste-require" + ] + } + } +} diff --git a/packages/react-native-dom-renderer/.gitignore b/packages/react-native-dom-renderer/.gitignore new file mode 100644 index 000000000..cd209f65a --- /dev/null +++ b/packages/react-native-dom-renderer/.gitignore @@ -0,0 +1,3 @@ +node_modules +.npmrc +build \ No newline at end of file diff --git a/packages/react-native-dom/ReactDom/DevSupport/RCTDevLoadingView.js b/packages/react-native-dom-renderer/ReactDom/DevSupport/RCTDevLoadingView.js similarity index 100% rename from packages/react-native-dom/ReactDom/DevSupport/RCTDevLoadingView.js rename to packages/react-native-dom-renderer/ReactDom/DevSupport/RCTDevLoadingView.js diff --git a/packages/react-native-dom/ReactDom/DevSupport/RCTDevMenu.js b/packages/react-native-dom-renderer/ReactDom/DevSupport/RCTDevMenu.js similarity index 100% rename from packages/react-native-dom/ReactDom/DevSupport/RCTDevMenu.js rename to packages/react-native-dom-renderer/ReactDom/DevSupport/RCTDevMenu.js diff --git a/packages/react-native-dom/ReactDom/ReactDom.js b/packages/react-native-dom-renderer/ReactDom/ReactDom.js similarity index 99% rename from packages/react-native-dom/ReactDom/ReactDom.js rename to packages/react-native-dom-renderer/ReactDom/ReactDom.js index 28e828c67..f6e843f9e 100644 --- a/packages/react-native-dom/ReactDom/ReactDom.js +++ b/packages/react-native-dom-renderer/ReactDom/ReactDom.js @@ -71,7 +71,7 @@ const builtInNativeModules: any[] = [ require("RCTNetworkingNative"), require("RCTBlobManager"), require("RCTVibration"), - require("RCTI18nManager") + require("RCTI18nManager"), ]; // Development Specific Native Modules diff --git a/packages/react-native-dom/ReactDom/base/NotificationCenter.js b/packages/react-native-dom-renderer/ReactDom/base/NotificationCenter.js similarity index 100% rename from packages/react-native-dom/ReactDom/base/NotificationCenter.js rename to packages/react-native-dom-renderer/ReactDom/base/NotificationCenter.js diff --git a/packages/react-native-dom/ReactDom/base/UIBorderView.js b/packages/react-native-dom-renderer/ReactDom/base/UIBorderView.js similarity index 100% rename from packages/react-native-dom/ReactDom/base/UIBorderView.js rename to packages/react-native-dom-renderer/ReactDom/base/UIBorderView.js diff --git a/packages/react-native-dom/ReactDom/base/UIChildContainerView.js b/packages/react-native-dom-renderer/ReactDom/base/UIChildContainerView.js similarity index 100% rename from packages/react-native-dom/ReactDom/base/UIChildContainerView.js rename to packages/react-native-dom-renderer/ReactDom/base/UIChildContainerView.js diff --git a/packages/react-native-dom/ReactDom/base/UIHitSlopView.js b/packages/react-native-dom-renderer/ReactDom/base/UIHitSlopView.js similarity index 100% rename from packages/react-native-dom/ReactDom/base/UIHitSlopView.js rename to packages/react-native-dom-renderer/ReactDom/base/UIHitSlopView.js diff --git a/packages/react-native-dom/ReactDom/base/UIView.js b/packages/react-native-dom-renderer/ReactDom/base/UIView.js similarity index 100% rename from packages/react-native-dom/ReactDom/base/UIView.js rename to packages/react-native-dom-renderer/ReactDom/base/UIView.js diff --git a/packages/react-native-dom/ReactDom/bridge/RCTBridge.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTBridge.js similarity index 100% rename from packages/react-native-dom/ReactDom/bridge/RCTBridge.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTBridge.js diff --git a/packages/react-native-dom/ReactDom/bridge/RCTBridge.worker.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTBridge.worker.js similarity index 100% rename from packages/react-native-dom/ReactDom/bridge/RCTBridge.worker.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTBridge.worker.js diff --git a/packages/react-native-dom/ReactDom/bridge/RCTBridgeMethod.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTBridgeMethod.js similarity index 100% rename from packages/react-native-dom/ReactDom/bridge/RCTBridgeMethod.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTBridgeMethod.js diff --git a/packages/react-native-dom/ReactDom/bridge/RCTEventDispatcher.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTEventDispatcher.js similarity index 100% rename from packages/react-native-dom/ReactDom/bridge/RCTEventDispatcher.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTEventDispatcher.js diff --git a/packages/react-native-dom/ReactDom/bridge/RCTModule.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTModule.js similarity index 75% rename from packages/react-native-dom/ReactDom/bridge/RCTModule.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTModule.js index 70b9e0b74..144978472 100644 --- a/packages/react-native-dom/ReactDom/bridge/RCTModule.js +++ b/packages/react-native-dom-renderer/ReactDom/bridge/RCTModule.js @@ -53,10 +53,12 @@ export default class RCTModule { functionMap: Array<() => any>; bridge: RCTBridge; + commandTable: Object;//TODO: type declaration for key/value needs to be defined constructor(bridge: RCTBridge) { this.bridge = bridge; this.functionMap = []; + this.commandTable = {}; } constantsToExport(): Constants { @@ -97,19 +99,27 @@ export default class RCTModule { if (name[0] === "$") { name = name.substring(1); - // by default functions are denoted as remote - // by prepending a $ onto the name the function is denoted as a special, - // async function that uses Promises - // the $ is removed from the name before registering with the react code - if (name[0] === "$") { - name = name.substring(1); - promiseFunctions.push(methodID); + // all the NativeCommands can be declared as methods pre-fixed with $$$ + // all the commands will be added to commandTable object + if (name[0] === "$" && name[1] === "$") { + name = name.substring(2); + + this.commandTable[name] = member; + } else { + // by default functions are denoted as remote + // by prepending a $ onto the name the function is denoted as a special, + // async function that uses Promises + // the $ is removed from the name before registering with the react code + if (name[0] === "$") { + name = name.substring(1); + promiseFunctions.push(methodID); + } + + // record the mapping from ID used by React to the real function + this.functionMap[methodID] = member; + functions.push(name); + methodID++; } - - // record the mapping from ID used by React to the real function - this.functionMap[methodID] = member; - functions.push(name); - methodID++; } } diff --git a/packages/react-native-dom/ReactDom/bridge/RCTModuleConfig.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTModuleConfig.js similarity index 100% rename from packages/react-native-dom/ReactDom/bridge/RCTModuleConfig.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTModuleConfig.js diff --git a/packages/react-native-dom/ReactDom/bridge/RCTRootView.js b/packages/react-native-dom-renderer/ReactDom/bridge/RCTRootView.js similarity index 99% rename from packages/react-native-dom/ReactDom/bridge/RCTRootView.js rename to packages/react-native-dom-renderer/ReactDom/bridge/RCTRootView.js index 6175d0c25..7bd34e12e 100644 --- a/packages/react-native-dom/ReactDom/bridge/RCTRootView.js +++ b/packages/react-native-dom-renderer/ReactDom/bridge/RCTRootView.js @@ -124,7 +124,7 @@ class RCTRootView extends UIView { return this._reactTag; } - set reactTag(value: number) {} + set reactTag(value: number) { } bundleFinishedLoading() { this.runApplication(); diff --git a/packages/react-native-dom/ReactDom/defs/InternalLib.js b/packages/react-native-dom-renderer/ReactDom/defs/InternalLib.js similarity index 100% rename from packages/react-native-dom/ReactDom/defs/InternalLib.js rename to packages/react-native-dom-renderer/ReactDom/defs/InternalLib.js diff --git a/packages/react-native-dom/ReactDom/modules/LayoutAnimation/RCTKeyframeGenerator.js b/packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/RCTKeyframeGenerator.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/LayoutAnimation/RCTKeyframeGenerator.js rename to packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/RCTKeyframeGenerator.js diff --git a/packages/react-native-dom/ReactDom/modules/LayoutAnimation/RCTLayoutAnimationManager.js b/packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/RCTLayoutAnimationManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/LayoutAnimation/RCTLayoutAnimationManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/RCTLayoutAnimationManager.js diff --git a/packages/react-native-dom/ReactDom/modules/LayoutAnimation/__tests__/__snapshots__/keyframeGenerator.test.js.snap b/packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/__tests__/__snapshots__/keyframeGenerator.test.js.snap similarity index 100% rename from packages/react-native-dom/ReactDom/modules/LayoutAnimation/__tests__/__snapshots__/keyframeGenerator.test.js.snap rename to packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/__tests__/__snapshots__/keyframeGenerator.test.js.snap diff --git a/packages/react-native-dom/ReactDom/modules/LayoutAnimation/__tests__/keyframeGenerator.test.js b/packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/__tests__/keyframeGenerator.test.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/LayoutAnimation/__tests__/keyframeGenerator.test.js rename to packages/react-native-dom-renderer/ReactDom/modules/LayoutAnimation/__tests__/keyframeGenerator.test.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTAnimationDriver.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTAnimationDriver.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTAnimationDriver.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTAnimationDriver.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTDecayAnimation.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTDecayAnimation.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTDecayAnimation.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTDecayAnimation.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTEventAnimation.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTEventAnimation.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTEventAnimation.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTEventAnimation.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTFrameAnimation.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTFrameAnimation.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTFrameAnimation.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTFrameAnimation.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTSpringAnimation.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTSpringAnimation.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Drivers/RCTSpringAnimation.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Drivers/RCTSpringAnimation.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTAdditionAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTAdditionAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTAdditionAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTAdditionAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTDivisionAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTDivisionAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTDivisionAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTDivisionAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTInterpolationAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTInterpolationAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTInterpolationAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTInterpolationAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTModuloAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTModuloAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTModuloAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTModuloAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTMultiplicationAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTMultiplicationAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTMultiplicationAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTMultiplicationAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTPropsAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTPropsAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTPropsAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTPropsAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTStyleAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTStyleAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTStyleAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTStyleAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTSubtractionAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTSubtractionAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTSubtractionAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTSubtractionAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTTrackingAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTTrackingAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTTrackingAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTTrackingAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTTransformAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTTransformAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTTransformAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTTransformAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTValueAnimatedNode.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTValueAnimatedNode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/Nodes/RCTValueAnimatedNode.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/Nodes/RCTValueAnimatedNode.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/RCTAnimationUtils.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/RCTAnimationUtils.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/RCTAnimationUtils.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/RCTAnimationUtils.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/RCTNativeAnimatedModule.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/RCTNativeAnimatedModule.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/RCTNativeAnimatedModule.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/RCTNativeAnimatedModule.js diff --git a/packages/react-native-dom/ReactDom/modules/NativeAnimation/RCTNativeAnimatedNodesManager.js b/packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/RCTNativeAnimatedNodesManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/NativeAnimation/RCTNativeAnimatedNodesManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/NativeAnimation/RCTNativeAnimatedNodesManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTAppState.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTAppState.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTAppState.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTAppState.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTAsyncLocalStorage.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTAsyncLocalStorage.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTAsyncLocalStorage.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTAsyncLocalStorage.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTBlobManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTBlobManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTBlobManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTBlobManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTDevSettings.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTDevSettings.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTDevSettings.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTDevSettings.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTDeviceEventManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTDeviceEventManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTDeviceEventManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTDeviceEventManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTDeviceInfo.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTDeviceInfo.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTDeviceInfo.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTDeviceInfo.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTExceptionsManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTExceptionsManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTExceptionsManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTExceptionsManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTHistory.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTHistory.js similarity index 89% rename from packages/react-native-dom/ReactDom/modules/RCTHistory.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTHistory.js index f7bbf51db..103000a66 100644 --- a/packages/react-native-dom/ReactDom/modules/RCTHistory.js +++ b/packages/react-native-dom-renderer/ReactDom/modules/RCTHistory.js @@ -1,9 +1,7 @@ /** @flow */ -import createHistory, { - type HashHistory, - type HashLocation -} from "history/createHashHistory"; +import type { HashHistory } from "history"; +import { createHashHistory } from "history"; import queryString from "query-string"; import RCTEventEmitter from "RCTNativeEventEmitter"; @@ -18,7 +16,7 @@ class RCTHistory extends RCTEventEmitter { constructor(bridge: RCTBridge) { super(bridge); - this.history = createHistory({ + this.history = createHashHistory({ basename: bridge.basename, hashType: "slash" }); diff --git a/packages/react-native-dom/ReactDom/modules/RCTI18nManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTI18nManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTI18nManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTI18nManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTKeyboardObserver.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTKeyboardObserver.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTKeyboardObserver.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTKeyboardObserver.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTLinkingManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTLinkingManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTLinkingManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTLinkingManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTNativeEventEmitter.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTNativeEventEmitter.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTNativeEventEmitter.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTNativeEventEmitter.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTNativeViewHierarchyOptimizer.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTNativeViewHierarchyOptimizer.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTNativeViewHierarchyOptimizer.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTNativeViewHierarchyOptimizer.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTNetworkingNative.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTNetworkingNative.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTNetworkingNative.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTNetworkingNative.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTPlatform.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTPlatform.js similarity index 59% rename from packages/react-native-dom/ReactDom/modules/RCTPlatform.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTPlatform.js index a477d207f..59580f518 100644 --- a/packages/react-native-dom/ReactDom/modules/RCTPlatform.js +++ b/packages/react-native-dom-renderer/ReactDom/modules/RCTPlatform.js @@ -1,5 +1,9 @@ /** @flow */ +/** + * TODO: Update this file to match 0.62.2 version of react-native + */ + import RCTModule from "RCTModule"; const supportsTouchForceChange = "ontouchforcechange" in window.document; @@ -10,12 +14,17 @@ class RCTPlatformConstants extends RCTModule { constantsToExport() { return { forceTouchAvailable: supportsTouchForceChange, + interfaceIdiom: "unknown", + isTesting: Boolean(__DEV__), + osVersion: "unknown", reactNativeVersion: { major: 0, - minor: 57, - patch: 0 - } - }; + minor: 62, + patch: 0, + prerelease: 0, + }, + systemName: "unknown", + } } } diff --git a/packages/react-native-dom/ReactDom/modules/RCTSourceCode.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTSourceCode.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTSourceCode.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTSourceCode.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTStatusBarManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTStatusBarManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTStatusBarManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTStatusBarManager.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTTiming.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTTiming.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTTiming.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTTiming.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTTouchEvent.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTTouchEvent.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTTouchEvent.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTTouchEvent.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTTouchHandler.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTTouchHandler.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTTouchHandler.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTTouchHandler.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTUIManager.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTUIManager.js similarity index 98% rename from packages/react-native-dom/ReactDom/modules/RCTUIManager.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTUIManager.js index fd698adf6..3a5faa27b 100644 --- a/packages/react-native-dom/ReactDom/modules/RCTUIManager.js +++ b/packages/react-native-dom-renderer/ReactDom/modules/RCTUIManager.js @@ -777,7 +777,7 @@ class RCTUIManager extends RCTModule { $dispatchViewManagerCommand( reactTag: number, - commandID: number, + commandID: number | string, //commandID can also be string as per NativeCommands in react-native framework commandArgs: any[] ) { const shadowView = this.shadowViewRegistry.get(reactTag); @@ -796,7 +796,11 @@ class RCTUIManager extends RCTModule { const args = [reactTag, ...commandArgs]; const manager = this.bridge.moduleForClass(managerClass); - manager.functionMap[commandID].apply(manager, args); + if (typeof commandID === "number") { + manager.functionMap[commandID].apply(manager, args); + } else if (typeof commandID === "string") { + manager.commandTable[commandID].apply(manager, args); + } } $focus(reactTag: number) { diff --git a/packages/react-native-dom/ReactDom/modules/RCTUIManagerObserverCoordinator.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTUIManagerObserverCoordinator.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTUIManagerObserverCoordinator.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTUIManagerObserverCoordinator.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTVibration.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTVibration.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTVibration.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTVibration.js diff --git a/packages/react-native-dom/ReactDom/modules/RCTWebSocketModule.js b/packages/react-native-dom-renderer/ReactDom/modules/RCTWebSocketModule.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RCTWebSocketModule.js rename to packages/react-native-dom-renderer/ReactDom/modules/RCTWebSocketModule.js diff --git a/packages/react-native-dom/ReactDom/modules/RedBox/RCTRedBox.js b/packages/react-native-dom-renderer/ReactDom/modules/RedBox/RCTRedBox.js similarity index 100% rename from packages/react-native-dom/ReactDom/modules/RedBox/RCTRedBox.js rename to packages/react-native-dom-renderer/ReactDom/modules/RedBox/RCTRedBox.js diff --git a/packages/react-native-dom/ReactDom/utils/BundleFromRoot.js b/packages/react-native-dom-renderer/ReactDom/utils/BundleFromRoot.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/BundleFromRoot.js rename to packages/react-native-dom-renderer/ReactDom/utils/BundleFromRoot.js diff --git a/packages/react-native-dom/ReactDom/utils/CanUse.js b/packages/react-native-dom-renderer/ReactDom/utils/CanUse.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/CanUse.js rename to packages/react-native-dom-renderer/ReactDom/utils/CanUse.js diff --git a/packages/react-native-dom/ReactDom/utils/ColorArrayFromHexARGB.js b/packages/react-native-dom-renderer/ReactDom/utils/ColorArrayFromHexARGB.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/ColorArrayFromHexARGB.js rename to packages/react-native-dom-renderer/ReactDom/utils/ColorArrayFromHexARGB.js diff --git a/packages/react-native-dom/ReactDom/utils/Guid.js b/packages/react-native-dom-renderer/ReactDom/utils/Guid.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/Guid.js rename to packages/react-native-dom-renderer/ReactDom/utils/Guid.js diff --git a/packages/react-native-dom/ReactDom/utils/Instrument.js b/packages/react-native-dom-renderer/ReactDom/utils/Instrument.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/Instrument.js rename to packages/react-native-dom-renderer/ReactDom/utils/Instrument.js diff --git a/packages/react-native-dom/ReactDom/utils/NativeMatrixMath.js b/packages/react-native-dom-renderer/ReactDom/utils/NativeMatrixMath.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/NativeMatrixMath.js rename to packages/react-native-dom-renderer/ReactDom/utils/NativeMatrixMath.js diff --git a/packages/react-native-dom/ReactDom/utils/isIOS.js b/packages/react-native-dom-renderer/ReactDom/utils/isIOS.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/isIOS.js rename to packages/react-native-dom-renderer/ReactDom/utils/isIOS.js diff --git a/packages/react-native-dom/ReactDom/utils/prefixInlineStyles.js b/packages/react-native-dom-renderer/ReactDom/utils/prefixInlineStyles.js similarity index 98% rename from packages/react-native-dom/ReactDom/utils/prefixInlineStyles.js rename to packages/react-native-dom-renderer/ReactDom/utils/prefixInlineStyles.js index ca5be8e17..5c428965d 100644 --- a/packages/react-native-dom/ReactDom/utils/prefixInlineStyles.js +++ b/packages/react-native-dom-renderer/ReactDom/utils/prefixInlineStyles.js @@ -1,6 +1,6 @@ /** @flow */ -import createPrefixer from "inline-style-prefixer/static/createPrefixer"; +import createPrefixer from "inline-style-prefixer/static/createPrefixer" import staticData from "./static"; diff --git a/packages/react-native-dom/ReactDom/utils/static.js b/packages/react-native-dom-renderer/ReactDom/utils/static.js similarity index 100% rename from packages/react-native-dom/ReactDom/utils/static.js rename to packages/react-native-dom-renderer/ReactDom/utils/static.js diff --git a/packages/react-native-dom/ReactDom/views/Image/RCTImageLoader.js b/packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageLoader.js similarity index 60% rename from packages/react-native-dom/ReactDom/views/Image/RCTImageLoader.js rename to packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageLoader.js index da40d6f91..5702363a7 100644 --- a/packages/react-native-dom/ReactDom/views/Image/RCTImageLoader.js +++ b/packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageLoader.js @@ -5,6 +5,7 @@ import type RCTBridge from "RCTBridge"; import RCTModule from "RCTModule"; class RCTImageLoader extends RCTModule { + static ERROR_GET_SIZE_FAILURE = "E_GET_SIZE_FAILURE"; static moduleName = "RCTImageLoader"; imageCache: { [cacheKey: string]: Promise }; @@ -40,6 +41,31 @@ class RCTImageLoader extends RCTModule { return loadPromise; } + getImageSizePromise(url: string): Promise { + const loadPromise = new Promise((resolve, reject) => { + const image = new Image(); + + // skip loading on data uris + if (url.startsWith("data:")) { + image.src = url; + return resolve([image.width, image.height]); + } + + if (url.startsWith("blob:")) { + const blob = this.bridge.blobManager.resolveURL(url); + url = URL.createObjectURL(blob); + } + + image.onload = () => resolve([image.width, image.height]); + //TODO : pass the correct additional params for rejection + image.onerror = (e) => reject(ERROR_GET_SIZE_FAILURE, e); + + image.src = url; + }); + + return loadPromise; + } + getImagePromise(url: string): Promise { const existingImage = this.imageCache[url]; if (existingImage != null) { @@ -60,6 +86,12 @@ class RCTImageLoader extends RCTModule { }; }); } + $$prefetchImage(url: string, resolveId: number, rejectId: number) { + return this.bridge.imageLoader.loadImageWithURLRequest(url); + } + $$getSize(request: string) { + return this.getImageSizePromise(request); + } } export default RCTImageLoader; diff --git a/packages/react-native-dom/ReactDom/views/Image/RCTImageSource.js b/packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageSource.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Image/RCTImageSource.js rename to packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageSource.js diff --git a/packages/react-native-dom/ReactDom/views/Image/RCTImageView.js b/packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Image/RCTImageView.js rename to packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageView.js diff --git a/packages/react-native-dom/ReactDom/views/Image/RCTImageViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageViewManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Image/RCTImageViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/Image/RCTImageViewManager.js diff --git a/packages/react-native-dom/ReactDom/views/RCTActivityIndicatorView.js b/packages/react-native-dom-renderer/ReactDom/views/RCTActivityIndicatorView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTActivityIndicatorView.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTActivityIndicatorView.js diff --git a/packages/react-native-dom/ReactDom/views/RCTActivityIndicatorViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/RCTActivityIndicatorViewManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTActivityIndicatorViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTActivityIndicatorViewManager.js diff --git a/packages/react-native-dom/ReactDom/views/RCTComponent.js b/packages/react-native-dom-renderer/ReactDom/views/RCTComponent.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTComponent.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTComponent.js diff --git a/packages/react-native-dom/ReactDom/views/RCTComponentData.js b/packages/react-native-dom-renderer/ReactDom/views/RCTComponentData.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTComponentData.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTComponentData.js diff --git a/packages/react-native-dom/ReactDom/views/RCTPropDescription.js b/packages/react-native-dom-renderer/ReactDom/views/RCTPropDescription.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTPropDescription.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTPropDescription.js diff --git a/packages/react-native-dom/ReactDom/views/RCTPropTypes.js b/packages/react-native-dom-renderer/ReactDom/views/RCTPropTypes.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTPropTypes.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTPropTypes.js diff --git a/packages/react-native-dom/ReactDom/views/RCTRootShadowView.js b/packages/react-native-dom-renderer/ReactDom/views/RCTRootShadowView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTRootShadowView.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTRootShadowView.js diff --git a/packages/react-native-dom/ReactDom/views/RCTScrollContentViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/RCTScrollContentViewManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTScrollContentViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTScrollContentViewManager.js diff --git a/packages/react-native-dom/ReactDom/views/RCTScrollView.js b/packages/react-native-dom-renderer/ReactDom/views/RCTScrollView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTScrollView.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTScrollView.js diff --git a/packages/react-native-dom/ReactDom/views/RCTScrollViewLocalData.js b/packages/react-native-dom-renderer/ReactDom/views/RCTScrollViewLocalData.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTScrollViewLocalData.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTScrollViewLocalData.js diff --git a/packages/react-native-dom/ReactDom/views/RCTScrollViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/RCTScrollViewManager.js similarity index 93% rename from packages/react-native-dom/ReactDom/views/RCTScrollViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTScrollViewManager.js index aea5ec188..70f55723c 100644 --- a/packages/react-native-dom/ReactDom/views/RCTScrollViewManager.js +++ b/packages/react-native-dom-renderer/ReactDom/views/RCTScrollViewManager.js @@ -31,7 +31,7 @@ class RCTScrollViewManager extends RCTViewManager { view.scrollEventThrottle = value != null ? value : 0; } - $getContentSize(reactTag: number, callbackId: number) { + $$$getContentSize(reactTag: number, callbackId: number) { this.bridge.uiManager.addUIBlock((_, viewRegistry: Map) => { const view = viewRegistry.get(reactTag); invariant( @@ -52,7 +52,7 @@ class RCTScrollViewManager extends RCTViewManager { }); } - $scrollTo( + $$$scrollTo( reactTag: number, offsetX: number, offsetY: number, @@ -71,7 +71,7 @@ class RCTScrollViewManager extends RCTViewManager { }); } - $scrollToEnd(reactTag: number, animated: boolean) { + $$$scrollToEnd(reactTag: number, animated: boolean) { this.bridge.uiManager.addUIBlock((_, viewRegistry: Map) => { const view = viewRegistry.get(reactTag); invariant( @@ -85,7 +85,7 @@ class RCTScrollViewManager extends RCTViewManager { }); } - $flashScrollIndicators(reactTag: number) { + $$$flashScrollIndicators(reactTag: number) { // no-op } diff --git a/packages/react-native-dom/ReactDom/views/RCTShadowScrollView.js b/packages/react-native-dom-renderer/ReactDom/views/RCTShadowScrollView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTShadowScrollView.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTShadowScrollView.js diff --git a/packages/react-native-dom/ReactDom/views/RCTShadowView.js b/packages/react-native-dom-renderer/ReactDom/views/RCTShadowView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTShadowView.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTShadowView.js diff --git a/packages/react-native-dom/ReactDom/views/RCTView.js b/packages/react-native-dom-renderer/ReactDom/views/RCTView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTView.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTView.js diff --git a/packages/react-native-dom/ReactDom/views/RCTViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/RCTViewManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/RCTViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/RCTViewManager.js diff --git a/packages/react-native-dom/ReactDom/views/SafeAreaView/RCTSafeAreaViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/SafeAreaView/RCTSafeAreaViewManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/SafeAreaView/RCTSafeAreaViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/SafeAreaView/RCTSafeAreaViewManager.js diff --git a/packages/react-native-dom/ReactDom/views/Switch/RCTSwitch.js b/packages/react-native-dom-renderer/ReactDom/views/Switch/RCTSwitch.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Switch/RCTSwitch.js rename to packages/react-native-dom-renderer/ReactDom/views/Switch/RCTSwitch.js diff --git a/packages/react-native-dom/ReactDom/views/Switch/RCTSwitchManager.js b/packages/react-native-dom-renderer/ReactDom/views/Switch/RCTSwitchManager.js similarity index 83% rename from packages/react-native-dom/ReactDom/views/Switch/RCTSwitchManager.js rename to packages/react-native-dom-renderer/ReactDom/views/Switch/RCTSwitchManager.js index 9e128529e..4e3b1ab65 100644 --- a/packages/react-native-dom/ReactDom/views/Switch/RCTSwitchManager.js +++ b/packages/react-native-dom-renderer/ReactDom/views/Switch/RCTSwitchManager.js @@ -24,6 +24,13 @@ class RCTSwitchManager extends RCTViewManager { } setValue(view: RCTSwitch, value: ?boolean) { + console.log("rct switch manager setvalue", value); + view.value = value; + } + + // NativeCommands setValue implementation + $$$setValue(view: RCTSwitch, value: ?boolean) { + console.log("rct switch manager $$$setvalue", value); view.value = value; } diff --git a/packages/react-native-dom/ReactDom/views/Text/Metrics/TextMetrics.js b/packages/react-native-dom-renderer/ReactDom/views/Text/Metrics/TextMetrics.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/Metrics/TextMetrics.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/Metrics/TextMetrics.js diff --git a/packages/react-native-dom/ReactDom/views/Text/Metrics/TextStyle.js b/packages/react-native-dom-renderer/ReactDom/views/Text/Metrics/TextStyle.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/Metrics/TextStyle.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/Metrics/TextStyle.js diff --git a/packages/react-native-dom/ReactDom/views/Text/Metrics/deepCopyProperties.js b/packages/react-native-dom-renderer/ReactDom/views/Text/Metrics/deepCopyProperties.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/Metrics/deepCopyProperties.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/Metrics/deepCopyProperties.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTRawText.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTRawText.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTRawText.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTRawText.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTRawTextManager.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTRawTextManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTRawTextManager.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTRawTextManager.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTShadowRawText.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTShadowRawText.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTShadowRawText.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTShadowRawText.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTShadowText.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTShadowText.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTShadowText.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTShadowText.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTSharedTextValues.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTSharedTextValues.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTSharedTextValues.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTSharedTextValues.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTText.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTText.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTText.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTText.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTTextInput.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTTextInput.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTTextInput.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTTextInput.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTTextInputManager.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTTextInputManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTTextInputManager.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTTextInputManager.js diff --git a/packages/react-native-dom/ReactDom/views/Text/RCTTextManager.js b/packages/react-native-dom-renderer/ReactDom/views/Text/RCTTextManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/Text/RCTTextManager.js rename to packages/react-native-dom-renderer/ReactDom/views/Text/RCTTextManager.js diff --git a/packages/react-native-dom/ReactDom/views/WebView/RCTWebView.js b/packages/react-native-dom-renderer/ReactDom/views/WebView/RCTWebView.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/WebView/RCTWebView.js rename to packages/react-native-dom-renderer/ReactDom/views/WebView/RCTWebView.js diff --git a/packages/react-native-dom/ReactDom/views/WebView/RCTWebViewManager.js b/packages/react-native-dom-renderer/ReactDom/views/WebView/RCTWebViewManager.js similarity index 100% rename from packages/react-native-dom/ReactDom/views/WebView/RCTWebViewManager.js rename to packages/react-native-dom-renderer/ReactDom/views/WebView/RCTWebViewManager.js diff --git a/packages/react-native-dom-renderer/package.json b/packages/react-native-dom-renderer/package.json new file mode 100644 index 000000000..b3897031d --- /dev/null +++ b/packages/react-native-dom-renderer/package.json @@ -0,0 +1,81 @@ +{ + "name": "react-native-dom-renderer", + "version": "1.0.0", + "description": "renderer for react-native-dom (to render react-native components on browser)", + "main": "build/ReactDom.js", + "homepage": "https://github.com/vincentriemer/react-native-dom", + "bugs": { + "url": "https://github.com/vincentriemer/react-native-dom/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/vincentriemer/react-native-dom.git" + }, + "license": "MIT", + "author": { + "name": "Vincent Riemer", + "email": "vincentriemer+rndom@gmail.com", + "url": "https://vincentriemer.com" + }, + "scripts": { + "precompile": "rimraf build", + "compile": "babel ReactDom --out-dir build --source-maps", + "postcompile": "flow-copy-source ReactDom build" + }, + "keywords": [ + "react-native", + "react-native-dom", + "react-native-dom-renderer", + "react-native on web" + ], + "files": [ + "package.json", + "build", + "ReactDom" + ], + "dependencies": { + "@webcomponents/webcomponentsjs": "^2.0.2", + "bezier-easing": "^2.0.3", + "cuid": "^2.1.1", + "debounce": "^1.0.2", + "deepmerge": "^1.5.0", + "detect-it": "^3.0.0", + "fast-memoize": "^2.2.7", + "history": "^5.0.0", + "idb-keyval": "^3.2.0", + "inline-style-prefixer": "^3.0.8", + "invariant": "^2.2.4", + "pepjs": "^0.4.3", + "query-string": "^6.1.0", + "resize-observer-polyfill": "^1.5.0", + "rndom-redbox": "0.5.0", + "rndom-switch": "0.5.0", + "rtl-detect": "^1.0.2", + "tinycolor2": "^1.4.1", + "web-animations-js": "^2.3.1", + "wolfy87-eventemitter": "^5.1.0", + "yoga-dom": "0.0.15" + }, + "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-flow": "^7.0.0", + "@babel/template": "^7.0.0", + "babel-core": "7.0.0-bridge.0", + "babel-jest": "^23.6.0", + "babel-plugin-module-resolver": "^3.1.1", + "babel-plugin-preval": "^1.3.2", + "babel-plugin-transform-inline-environment-variables": "^0.1.1", + "flow-bin": "^0.70.0", + "flow-copy-source": "^1.3.0", + "flow-typed": "^2.2.3", + "jest": "^23.6.0", + "lint-staged": "^6.0.0", + "metro-react-native-babel-preset": "^0.49.0", + "prettier": "^1.9.0" + } +} diff --git a/packages/react-native-dom/scripts/babel-plugin-haste-require.js b/packages/react-native-dom-renderer/scripts/babel-plugin-haste-require.js similarity index 100% rename from packages/react-native-dom/scripts/babel-plugin-haste-require.js rename to packages/react-native-dom-renderer/scripts/babel-plugin-haste-require.js diff --git a/packages/react-native-dom/scripts/eslint-module-resolver-haste.js b/packages/react-native-dom-renderer/scripts/eslint-module-resolver-haste.js similarity index 100% rename from packages/react-native-dom/scripts/eslint-module-resolver-haste.js rename to packages/react-native-dom-renderer/scripts/eslint-module-resolver-haste.js diff --git a/packages/react-native-dom/.gitignore b/packages/react-native-dom/.gitignore index 4ca754397..84c4e905f 100644 --- a/packages/react-native-dom/.gitignore +++ b/packages/react-native-dom/.gitignore @@ -1,8 +1,9 @@ -dist node_modules -lib -stats.html -yarn-error.log -flow-coverage -.yarnrc -yalc.lock \ No newline at end of file +.npmrc +flow +jest +Libraries +index.js +interface.js +rn-get-polyfills.js +!src/Libraries \ No newline at end of file diff --git a/packages/react-native-dom/Libraries/Alert/RCTAlertManager.dom.js b/packages/react-native-dom/Libraries/Alert/RCTAlertManager.dom.js deleted file mode 100644 index 8a7d1d660..000000000 --- a/packages/react-native-dom/Libraries/Alert/RCTAlertManager.dom.js +++ /dev/null @@ -1,16 +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 RCTAlertManager - * @flow - */ -"use strict"; - -var RCTAlertManager = require("NativeModules").AlertManager; - -module.exports = RCTAlertManager; diff --git a/packages/react-native-dom/Libraries/Components/ActivityIndicator/ActivityIndicator.dom.js b/packages/react-native-dom/Libraries/Components/ActivityIndicator/ActivityIndicator.dom.js deleted file mode 100644 index 3e256da53..000000000 --- a/packages/react-native-dom/Libraries/Components/ActivityIndicator/ActivityIndicator.dom.js +++ /dev/null @@ -1,187 +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 ActivityIndicator - * @flow - */ -"use strict"; - -const ColorPropType = require("ColorPropType"); -const NativeMethodsMixin = require("NativeMethodsMixin"); -const Platform = require("Platform"); -const React = require("React"); -const PropTypes = require("prop-types"); -const StyleSheet = require("StyleSheet"); -const View = require("View"); -const ViewPropTypes = require("ViewPropTypes"); - -const createReactClass = require("create-react-class"); -const requireNativeComponent = require("requireNativeComponent"); - -const GRAY = "#999999"; - -type IndicatorSize = number | "small" | "large"; - -type DefaultProps = { - animating: boolean, - color: any, - hidesWhenStopped: boolean, - size: IndicatorSize -}; - -/** - * Displays a circular loading indicator. - * - * ### Example - * - * ```ReactNativeWebPlayer - * import React, { Component } from 'react' - * import { - * ActivityIndicator, - * AppRegistry, - * StyleSheet, - * Text, - * View, - * } from 'react-native' - * - * class App extends Component { - * render() { - * return ( - * - * - * - * - * - * - * ) - * } - * } - * - * const styles = StyleSheet.create({ - * container: { - * flex: 1, - * justifyContent: 'center' - * }, - * horizontal: { - * flexDirection: 'row', - * justifyContent: 'space-around', - * padding: 10 - * } - * }) - * - * AppRegistry.registerComponent('App', () => App) - * ``` - */ -/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error when upgrading Flow's support for React. To see the - * error delete this comment and run Flow. */ -const ActivityIndicator = createReactClass({ - displayName: "ActivityIndicator", - mixins: [NativeMethodsMixin], - - propTypes: { - ...ViewPropTypes, - /** - * Whether to show the indicator (true, the default) or hide it (false). - */ - animating: PropTypes.bool, - /** - * The foreground color of the spinner (default is gray). - */ - color: ColorPropType, - /** - * Size of the indicator (default is 'small'). - * Passing a number to the size prop is only supported on Android. - */ - size: PropTypes.oneOfType([ - PropTypes.oneOf(["small", "large"]), - PropTypes.number - ]), - /** - * Whether the indicator should hide when not animating (true by default). - * - * @platform ios - */ - hidesWhenStopped: PropTypes.bool - }, - - getDefaultProps(): DefaultProps { - return { - animating: true, - color: Platform.OS === "ios" ? GRAY : undefined, - hidesWhenStopped: true, - size: "small" - }; - }, - - render() { - const { onLayout, style, ...props } = this.props; - let sizeStyle; - - switch (props.size) { - case "small": - sizeStyle = styles.sizeSmall; - break; - case "large": - sizeStyle = styles.sizeLarge; - break; - default: - sizeStyle = { height: props.size, width: props.size }; - break; - } - - return ( - - - - ); - } -}); - -const styles = StyleSheet.create({ - container: { - alignItems: "center", - justifyContent: "center" - }, - sizeSmall: { - width: 20, - height: 20 - }, - sizeLarge: { - width: 36, - height: 36 - } -}); - -if (Platform.OS === "ios" || Platform.OS === "dom") { - var RCTActivityIndicator = requireNativeComponent( - "RCTActivityIndicatorView", - ActivityIndicator, - { nativeOnly: { activityIndicatorViewStyle: true } } - ); -} else if (Platform.OS === "android") { - var RCTActivityIndicator = requireNativeComponent( - "AndroidProgressBar", - ActivityIndicator, - // Ignore props that are specific to non inderterminate ProgressBar. - { - nativeOnly: { - indeterminate: true, - progress: true, - styleAttr: true - } - } - ); -} - -module.exports = ActivityIndicator; diff --git a/packages/react-native-dom/Libraries/Components/AppleTV/TVEventHandler.dom.js b/packages/react-native-dom/Libraries/Components/AppleTV/TVEventHandler.dom.js deleted file mode 100644 index 67f151701..000000000 --- a/packages/react-native-dom/Libraries/Components/AppleTV/TVEventHandler.dom.js +++ /dev/null @@ -1,23 +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 TVEventHandler - * @flow - */ -"use strict"; - -function TVEventHandler() {} - -TVEventHandler.prototype.enable = function( - component: ?any, - callback: Function -) {}; - -TVEventHandler.prototype.disable = function() {}; - -module.exports = TVEventHandler; diff --git a/packages/react-native-dom/Libraries/Components/Navigation/NavigatorIOS.dom.js b/packages/react-native-dom/Libraries/Components/Navigation/NavigatorIOS.dom.js deleted file mode 100644 index 5d3a22536..000000000 --- a/packages/react-native-dom/Libraries/Components/Navigation/NavigatorIOS.dom.js +++ /dev/null @@ -1,13 +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 NavigatorIOS - */ -"use strict"; - -module.exports = require("UnimplementedView"); diff --git a/packages/react-native-dom/Libraries/Components/ReactNative/UIManager.dom.js b/packages/react-native-dom/Libraries/Components/ReactNative/UIManager.dom.js deleted file mode 100644 index 765e89136..000000000 --- a/packages/react-native-dom/Libraries/Components/ReactNative/UIManager.dom.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @providesModule UIManager - * @flow - * @format - */ -"use strict"; - -const NativeModules = require("NativeModules"); -const Platform = require("Platform"); - -const defineLazyObjectProperty = require("defineLazyObjectProperty"); -const invariant = require("fbjs/lib/invariant"); - -const { UIManager } = NativeModules; - -invariant( - UIManager, - "UIManager is undefined. The native module config is probably incorrect." -); - -// In past versions of ReactNative users called UIManager.takeSnapshot() -// However takeSnapshot was moved to ReactNative in order to support flat -// bundles and to avoid a cyclic dependency between UIManager and ReactNative. -// UIManager.takeSnapshot still exists though. In order to avoid confusion or -// accidental usage, mask the method with a deprecation warning. -UIManager.__takeSnapshot = UIManager.takeSnapshot; -UIManager.takeSnapshot = function() { - invariant( - false, - "UIManager.takeSnapshot should not be called directly. " + - "Use ReactNative.takeSnapshot instead." - ); -}; - -/** - * Copies the ViewManager constants and commands into UIManager. This is - * only needed for iOS, which puts the constants in the ViewManager - * namespace instead of UIManager, unlike Android. - */ -if (Platform.OS === "ios" || Platform.OS === "dom") { - Object.keys(UIManager).forEach((viewName) => { - const viewConfig = UIManager[viewName]; - if (viewConfig && viewConfig.Manager) { - defineLazyObjectProperty(viewConfig, "Constants", { - get: () => { - const viewManager = NativeModules[viewConfig.Manager]; - const constants = {}; - viewManager && - Object.keys(viewManager).forEach((key) => { - const value = viewManager[key]; - if (typeof value !== "function") { - constants[key] = value; - } - }); - return constants; - } - }); - defineLazyObjectProperty(viewConfig, "Commands", { - get: () => { - const viewManager = NativeModules[viewConfig.Manager]; - const commands = {}; - let index = 0; - viewManager && - Object.keys(viewManager).forEach((key) => { - const value = viewManager[key]; - if (typeof value === "function") { - commands[key] = index++; - } - }); - return commands; - } - }); - } - }); -} else if (Platform.OS === "android" && UIManager.ViewManagerNames) { - UIManager.ViewManagerNames.forEach((viewManagerName) => { - defineLazyObjectProperty(UIManager, viewManagerName, { - get: () => UIManager.getConstantsForViewManager(viewManagerName) - }); - }); -} - -module.exports = UIManager; diff --git a/packages/react-native-dom/Libraries/Components/SafeAreaView/SafeAreaView.dom.js b/packages/react-native-dom/Libraries/Components/SafeAreaView/SafeAreaView.dom.js deleted file mode 100644 index d8897889f..000000000 --- a/packages/react-native-dom/Libraries/Components/SafeAreaView/SafeAreaView.dom.js +++ /dev/null @@ -1,48 +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 SafeAreaView - * @flow - * @format - */ - -const React = require("React"); -const ViewPropTypes = require("ViewPropTypes"); -const requireNativeComponent = require("requireNativeComponent"); - -import type { ViewProps } from "ViewPropTypes"; - -type Props = ViewProps & { - children: any -}; - -/** - * 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 feflect physical limitation of the screen, - * such as rounded corners or camera notches (aka sensor housing area on iPhone X). - */ -class SafeAreaView extends React.Component { - static propTypes = { - ...ViewPropTypes - }; - - render() { - return ; - } -} - -const RCTSafeAreaView = requireNativeComponent("RCTSafeAreaView", { - name: "RCTSafeAreaView", - displayName: "RCTSafeAreaView", - propTypes: { - ...ViewPropTypes - } -}); - -module.exports = SafeAreaView; diff --git a/packages/react-native-dom/Libraries/Components/ScrollView/ScrollViewStickyHeader.dom.js b/packages/react-native-dom/Libraries/Components/ScrollView/ScrollViewStickyHeader.dom.js deleted file mode 100644 index 2036678b0..000000000 --- a/packages/react-native-dom/Libraries/Components/ScrollView/ScrollViewStickyHeader.dom.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @providesModule ScrollViewStickyHeader - * @flow - * @format - */ -"use strict"; - -const AnimatedImplementation = require("AnimatedImplementation"); -const React = require("React"); -const StyleSheet = require("StyleSheet"); -const View = require("View"); - -import type { LayoutEvent } from "CoreEventTypes"; - -type Props = { - children?: React.Element, - nextHeaderLayoutY: ?number, - onLayout: (event: LayoutEvent) => void, - scrollAnimatedValue: AnimatedImplementation.Value, - // Will cause sticky headers to stick at the bottom of the ScrollView instead - // of the top. - inverted: ?boolean, - // The height of the parent ScrollView. Currently only set when inverted. - scrollViewHeight: ?number -}; - -type State = {}; - -class ScrollViewStickyHeader extends React.Component { - state = {}; - - render() { - const { inverted, scrollViewHeight } = this.props; - - const child = React.Children.only(this.props.children); - - return ( - - {React.cloneElement(child, { - style: styles.fill, // We transfer the child style to the wrapper. - onLayout: undefined // we call this manually through our this._onLayout - })} - - ); - } -} - -const styles = StyleSheet.create({ - header: { - zIndex: 10 - }, - fill: { - flex: 1 - } -}); - -module.exports = ScrollViewStickyHeader; diff --git a/packages/react-native-dom/Libraries/Components/Slider/Slider.dom.js b/packages/react-native-dom/Libraries/Components/Slider/Slider.dom.js deleted file mode 100644 index 67a189de7..000000000 --- a/packages/react-native-dom/Libraries/Components/Slider/Slider.dom.js +++ /dev/null @@ -1,15 +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 Slider - * @flow - */ - -"use strict"; - -module.exports = require("UnimplementedView"); diff --git a/packages/react-native-dom/Libraries/Components/StatusBar/StatusBarIOS.dom.js b/packages/react-native-dom/Libraries/Components/StatusBar/StatusBarIOS.dom.js deleted file mode 100644 index 6a6297dfb..000000000 --- a/packages/react-native-dom/Libraries/Components/StatusBar/StatusBarIOS.dom.js +++ /dev/null @@ -1,16 +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 StatusBarIOS - * @flow - */ -"use strict"; - -const NativeEventEmitter = require("NativeEventEmitter"); - -module.exports = new NativeEventEmitter("StatusBarManager"); diff --git a/packages/react-native-dom/Libraries/Components/Switch/Switch.dom.js b/packages/react-native-dom/Libraries/Components/Switch/Switch.dom.js deleted file mode 100644 index 777d6dbc1..000000000 --- a/packages/react-native-dom/Libraries/Components/Switch/Switch.dom.js +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright (c) 2013-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 Switch - * @flow - */ -"use strict"; - -var ColorPropType = require("ColorPropType"); -var NativeMethodsMixin = require("NativeMethodsMixin"); -var Platform = require("Platform"); -var React = require("React"); -const PropTypes = require("prop-types"); -var StyleSheet = require("StyleSheet"); -const ViewPropTypes = require("ViewPropTypes"); - -var createReactClass = require("create-react-class"); -var requireNativeComponent = require("requireNativeComponent"); - -type DefaultProps = { - value: boolean, - disabled: boolean -}; - -/** - * Renders a boolean input. - * - * This is a controlled component that requires an `onValueChange` callback that - * updates the `value` prop in order for the component to reflect user actions. - * If the `value` prop is not updated, the component will continue to render - * the supplied `value` prop instead of the expected result of any user actions. - * - * @keyword checkbox - * @keyword toggle - */ -var Switch = createReactClass({ - displayName: "Switch", - propTypes: { - ...ViewPropTypes, - /** - * The value of the switch. If true the switch will be turned on. - * Default value is false. - */ - value: PropTypes.bool, - /** - * If true the user won't be able to toggle the switch. - * Default value is false. - */ - disabled: PropTypes.bool, - /** - * Invoked with the new value when the value changes. - */ - onValueChange: PropTypes.func, - /** - * Used to locate this view in end-to-end tests. - */ - testID: PropTypes.string, - - /** - * Border color on iOS and background color on Android when the switch is turned off. - */ - tintColor: ColorPropType, - /** - * Background color when the switch is turned on. - */ - onTintColor: ColorPropType, - /** - * Color of the foreground switch grip. - */ - thumbTintColor: ColorPropType - }, - - getDefaultProps: function(): DefaultProps { - return { - value: false, - disabled: false - }; - }, - - mixins: [NativeMethodsMixin], - - _rctSwitch: {}, - _onChange: function(event: Object) { - if (Platform.OS === "android") { - this._rctSwitch.setNativeProps({ on: this.props.value }); - } else { - this._rctSwitch.setNativeProps({ value: this.props.value }); - } - //Change the props after the native props are set in case the props change removes the component - /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error when upgrading Flow's support for React. To see the - * error delete this comment and run Flow. */ - this.props.onChange && this.props.onChange(event); - this.props.onValueChange && - this.props.onValueChange(event.nativeEvent.value); - }, - - render: function() { - var props = { ...this.props }; - props.onStartShouldSetResponder = () => true; - props.onResponderTerminationRequest = () => false; - if (Platform.OS === "android") { - props.enabled = !this.props.disabled; - props.on = this.props.value; - props.style = this.props.style; - props.trackTintColor = this.props.value - ? this.props.onTintColor - : this.props.tintColor; - } else { - props.style = [styles.rctSwitchIOS, this.props.style]; - } - return ( - =0.53.0 site=react_native_fb,react_native_oss) This - * comment suppresses an error when upgrading Flow's support for React. - * To see the error delete this comment and run Flow. */ - ref={(ref) => { - this._rctSwitch = ref; - }} - onChange={this._onChange} - /> - ); - } -}); - -var styles = StyleSheet.create({ - rctSwitchIOS: { - height: 31, - width: 51 - } -}); - -if (Platform.OS === "android") { - var RCTSwitch = requireNativeComponent("AndroidSwitch", Switch, { - nativeOnly: { - onChange: true, - on: true, - enabled: true, - trackTintColor: true - } - }); -} else { - var RCTSwitch = requireNativeComponent("RCTSwitch", Switch, { - nativeOnly: { - onChange: true - } - }); -} - -module.exports = Switch; diff --git a/packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarIOS.dom.js b/packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarIOS.dom.js deleted file mode 100644 index 6db7a3498..000000000 --- a/packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarIOS.dom.js +++ /dev/null @@ -1,38 +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 TabBarIOS - * @flow - */ - -"use strict"; - -const React = require("React"); -const StyleSheet = require("StyleSheet"); -const TabBarItemIOS = require("TabBarItemIOS"); -const View = require("View"); - -class DummyTabBarIOS extends React.Component { - static Item = TabBarItemIOS; - - render() { - return ( - - {this.props.children} - - ); - } -} - -const styles = StyleSheet.create({ - tabGroup: { - flex: 1 - } -}); - -module.exports = DummyTabBarIOS; diff --git a/packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarItemIOS.dom.js b/packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarItemIOS.dom.js deleted file mode 100644 index 3c487e820..000000000 --- a/packages/react-native-dom/Libraries/Components/TabBarIOS/TabBarItemIOS.dom.js +++ /dev/null @@ -1,42 +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 TabBarItemIOS - */ - -"use strict"; - -var React = require("React"); -var View = require("View"); -var StyleSheet = require("StyleSheet"); - -class DummyTab extends React.Component { - render() { - if (!this.props.selected) { - return ; - } - return ( - {this.props.children} - ); - } -} - -var styles = StyleSheet.create({ - tab: { - // TODO(5405356): Implement overflow: visible so position: absolute isn't useless - // position: 'absolute', - top: 0, - right: 0, - bottom: 0, - left: 0, - borderColor: "red", - borderWidth: 1 - } -}); - -module.exports = DummyTab; diff --git a/packages/react-native-dom/Libraries/Components/TextInput/TextInput.dom.js b/packages/react-native-dom/Libraries/Components/TextInput/TextInput.dom.js deleted file mode 100644 index 94fcf3dbd..000000000 --- a/packages/react-native-dom/Libraries/Components/TextInput/TextInput.dom.js +++ /dev/null @@ -1,967 +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 TextInput - * @flow - */ -"use strict"; - -const ColorPropType = require("ColorPropType"); -const DocumentSelectionState = require("DocumentSelectionState"); -const EventEmitter = require("EventEmitter"); -const NativeMethodsMixin = require("NativeMethodsMixin"); -const Platform = require("Platform"); -const React = require("React"); -const createReactClass = require("create-react-class"); -const PropTypes = require("prop-types"); -const ReactNative = require("ReactNative"); -const StyleSheet = require("StyleSheet"); -const Text = require("Text"); -const TextInputState = require("TextInputState"); -const TimerMixin = require("react-timer-mixin"); -const TouchableWithoutFeedback = require("TouchableWithoutFeedback"); -const UIManager = require("UIManager"); -const ViewPropTypes = require("ViewPropTypes"); - -const emptyFunction = require("fbjs/lib/emptyFunction"); -const invariant = require("fbjs/lib/invariant"); -const requireNativeComponent = require("requireNativeComponent"); -const warning = require("fbjs/lib/warning"); - -const onlyMultiline = { - onTextInput: true, - children: true -}; - -if (Platform.OS === "android") { - var AndroidTextInput = requireNativeComponent("AndroidTextInput", null); -} else if (Platform.OS === "ios") { - var RCTTextView = requireNativeComponent("RCTTextView", null); - var RCTTextField = requireNativeComponent("RCTTextField", null); -} else if (Platform.OS === "dom") { - var RCTTextInput = requireNativeComponent("RCTTextInput", null); - var RCTMultilineTextInput = require("UnimplementedView"); -} - -type Event = Object; -type Selection = { - start: number, - end?: number -}; - -const DataDetectorTypes = [ - "phoneNumber", - "link", - "address", - "calendarEvent", - "none", - "all" -]; - -/** - * A foundational component for inputting text into the app via a - * keyboard. Props provide configurability for several features, such as - * auto-correction, auto-capitalization, placeholder text, and different keyboard - * types, such as a numeric keypad. - * - * The simplest use case is to plop down a `TextInput` and subscribe to the - * `onChangeText` events to read the user input. There are also other events, - * such as `onSubmitEditing` and `onFocus` that can be subscribed to. A simple - * example: - * - * ```ReactNativeWebPlayer - * import React, { Component } from 'react'; - * import { AppRegistry, TextInput } from 'react-native'; - * - * export default class UselessTextInput extends Component { - * constructor(props) { - * super(props); - * this.state = { text: 'Useless Placeholder' }; - * } - * - * render() { - * return ( - * this.setState({text})} - * value={this.state.text} - * /> - * ); - * } - * } - * - * // skip this line if using Create React Native App - * AppRegistry.registerComponent('AwesomeProject', () => UselessTextInput); - * ``` - * - * Note that some props are only available with `multiline={true/false}`. - * Additionally, border styles that apply to only one side of the element - * (e.g., `borderBottomColor`, `borderLeftWidth`, etc.) will not be applied if - * `multiline=false`. To achieve the same effect, you can wrap your `TextInput` - * in a `View`: - * - * ```ReactNativeWebPlayer - * import React, { Component } from 'react'; - * import { AppRegistry, View, TextInput } from 'react-native'; - * - * class UselessTextInput extends Component { - * render() { - * return ( - * - * ); - * } - * } - * - * export default class UselessTextInputMultiline extends Component { - * constructor(props) { - * super(props); - * this.state = { - * text: 'Useless Multiline Placeholder', - * }; - * } - * - * // If you type something in the text box that is a color, the background will change to that - * // color. - * render() { - * return ( - * - * this.setState({text})} - * value={this.state.text} - * /> - * - * ); - * } - * } - * - * // skip these lines if using Create React Native App - * AppRegistry.registerComponent( - * 'AwesomeProject', - * () => UselessTextInputMultiline - * ); - * ``` - * - * `TextInput` has by default a border at the bottom of its view. This border - * has its padding set by the background image provided by the system, and it - * cannot be changed. Solutions to avoid this is to either not set height - * explicitly, case in which the system will take care of displaying the border - * in the correct position, or to not display the border by setting - * `underlineColorAndroid` to transparent. - * - * Note that on Android performing text selection in input can change - * app's activity `windowSoftInputMode` param to `adjustResize`. - * This may cause issues with components that have position: 'absolute' - * while keyboard is active. To avoid this behavior either specify `windowSoftInputMode` - * in AndroidManifest.xml ( https://developer.android.com/guide/topics/manifest/activity-element.html ) - * or control this param programmatically with native code. - * - */ -// $FlowFixMe(>=0.41.0) -const TextInput = createReactClass({ - displayName: "TextInput", - statics: { - /* TODO(brentvatne) docs are needed for this */ - State: TextInputState - }, - - propTypes: { - ...ViewPropTypes, - /** - * Can tell `TextInput` to automatically capitalize certain characters. - * - * - `characters`: all characters. - * - `words`: first letter of each word. - * - `sentences`: first letter of each sentence (*default*). - * - `none`: don't auto capitalize anything. - */ - autoCapitalize: PropTypes.oneOf([ - "none", - "sentences", - "words", - "characters" - ]), - /** - * If `false`, disables auto-correct. The default value is `true`. - */ - autoCorrect: PropTypes.bool, - /** - * If `false`, disables spell-check style (i.e. red underlines). - * The default value is inherited from `autoCorrect`. - * @platform ios - */ - spellCheck: PropTypes.bool, - /** - * If `true`, focuses the input on `componentDidMount`. - * The default value is `false`. - */ - autoFocus: PropTypes.bool, - /** - * If `false`, text is not editable. The default value is `true`. - */ - editable: PropTypes.bool, - /** - * Determines which keyboard to open, e.g.`numeric`. - * - * The following values work across platforms: - * - * - `default` - * - `numeric` - * - `email-address` - * - `phone-pad` - */ - keyboardType: PropTypes.oneOf([ - // Cross-platform - "default", - "email-address", - "numeric", - "phone-pad", - // iOS-only - "ascii-capable", - "numbers-and-punctuation", - "url", - "number-pad", - "name-phone-pad", - "decimal-pad", - "twitter", - "web-search" - ]), - /** - * Determines the color of the keyboard. - * @platform ios - */ - keyboardAppearance: PropTypes.oneOf(["default", "light", "dark"]), - /** - * Determines how the return key should look. On Android you can also use - * `returnKeyLabel`. - * - * *Cross platform* - * - * The following values work across platforms: - * - * - `done` - * - `go` - * - `next` - * - `search` - * - `send` - * - * *Android Only* - * - * The following values work on Android only: - * - * - `none` - * - `previous` - * - * *iOS Only* - * - * The following values work on iOS only: - * - * - `default` - * - `emergency-call` - * - `google` - * - `join` - * - `route` - * - `yahoo` - */ - returnKeyType: PropTypes.oneOf([ - // Cross-platform - "done", - "go", - "next", - "search", - "send", - // Android-only - "none", - "previous", - // iOS-only - "default", - "emergency-call", - "google", - "join", - "route", - "yahoo" - ]), - /** - * Sets the return key to the label. Use it instead of `returnKeyType`. - * @platform android - */ - returnKeyLabel: PropTypes.string, - /** - * Limits the maximum number of characters that can be entered. Use this - * instead of implementing the logic in JS to avoid flicker. - */ - maxLength: PropTypes.number, - /** - * Sets the number of lines for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. - * @platform android - */ - numberOfLines: PropTypes.number, - /** - * When `false`, if there is a small amount of space available around a text input - * (e.g. landscape orientation on a phone), the OS may choose to have the user edit - * the text inside of a full screen text input mode. When `true`, this feature is - * disabled and users will always edit the text directly inside of the text input. - * Defaults to `false`. - * @platform android - */ - disableFullscreenUI: PropTypes.bool, - /** - * If `true`, the keyboard disables the return key when there is no text and - * automatically enables it when there is text. The default value is `false`. - * @platform ios - */ - enablesReturnKeyAutomatically: PropTypes.bool, - /** - * If `true`, the text input can be multiple lines. - * The default value is `false`. - */ - multiline: PropTypes.bool, - /** - * Set text break strategy on Android API Level 23+, possible values are `simple`, `highQuality`, `balanced` - * The default value is `simple`. - * @platform android - */ - textBreakStrategy: PropTypes.oneOf(["simple", "highQuality", "balanced"]), - /** - * Callback that is called when the text input is blurred. - */ - onBlur: PropTypes.func, - /** - * Callback that is called when the text input is focused. - */ - onFocus: PropTypes.func, - /** - * Callback that is called when the text input's text changes. - */ - onChange: PropTypes.func, - /** - * Callback that is called when the text input's text changes. - * Changed text is passed as an argument to the callback handler. - */ - onChangeText: PropTypes.func, - /** - * Callback that is called when the text input's content size changes. - * This will be called with - * `{ nativeEvent: { contentSize: { width, height } } }`. - * - * Only called for multiline text inputs. - */ - onContentSizeChange: PropTypes.func, - /** - * Callback that is called when text input ends. - */ - onEndEditing: PropTypes.func, - /** - * Callback that is called when the text input selection is changed. - * This will be called with - * `{ nativeEvent: { selection: { start, end } } }`. - */ - onSelectionChange: PropTypes.func, - /** - * Callback that is called when the text input's submit button is pressed. - * Invalid if `multiline={true}` is specified. - */ - onSubmitEditing: PropTypes.func, - /** - * Callback that is called when a key is pressed. - * This will be called with `{ nativeEvent: { key: keyValue } }` - * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and - * the typed-in character otherwise including `' '` for space. - * Fires before `onChange` callbacks. - * @platform ios - */ - onKeyPress: PropTypes.func, - /** - * Invoked on mount and layout changes with `{x, y, width, height}`. - */ - onLayout: PropTypes.func, - /** - * Invoked on content scroll with `{ nativeEvent: { contentOffset: { x, y } } }`. - * May also contain other properties from ScrollEvent but on Android contentSize - * is not provided for performance reasons. - */ - onScroll: PropTypes.func, - /** - * The string that will be rendered before text input has been entered. - */ - placeholder: PropTypes.node, - /** - * The text color of the placeholder string. - */ - placeholderTextColor: ColorPropType, - /** - * If `true`, the text input obscures the text entered so that sensitive text - * like passwords stay secure. The default value is `false`. - */ - secureTextEntry: PropTypes.bool, - /** - * The highlight and cursor color of the text input. - */ - selectionColor: ColorPropType, - /** - * An instance of `DocumentSelectionState`, this is some state that is responsible for - * maintaining selection information for a document. - * - * Some functionality that can be performed with this instance is: - * - * - `blur()` - * - `focus()` - * - `update()` - * - * > You can reference `DocumentSelectionState` in - * > [`vendor/document/selection/DocumentSelectionState.js`](https://github.com/facebook/react-native/blob/master/Libraries/vendor/document/selection/DocumentSelectionState.js) - * - * @platform ios - */ - selectionState: PropTypes.instanceOf(DocumentSelectionState), - /** - * The start and end of the text input's selection. Set start and end to - * the same value to position the cursor. - */ - selection: PropTypes.shape({ - start: PropTypes.number.isRequired, - end: PropTypes.number - }), - /** - * The value to show for the text input. `TextInput` is a controlled - * component, which means the native value will be forced to match this - * value prop if provided. For most uses, this works great, but in some - * cases this may cause flickering - one common cause is preventing edits - * by keeping value the same. In addition to simply setting the same value, - * either set `editable={false}`, or set/update `maxLength` to prevent - * unwanted edits without flicker. - */ - value: PropTypes.string, - /** - * Provides an initial value that will change when the user starts typing. - * Useful for simple use-cases where you do not want to deal with listening - * to events and updating the value prop to keep the controlled state in sync. - */ - defaultValue: PropTypes.string, - /** - * When the clear button should appear on the right side of the text view. - * @platform ios - */ - clearButtonMode: PropTypes.oneOf([ - "never", - "while-editing", - "unless-editing", - "always" - ]), - /** - * If `true`, clears the text field automatically when editing begins. - * @platform ios - */ - clearTextOnFocus: PropTypes.bool, - /** - * If `true`, all text will automatically be selected on focus. - */ - selectTextOnFocus: PropTypes.bool, - /** - * If `true`, the text field will blur when submitted. - * The default value is true for single-line fields and false for - * multiline fields. Note that for multiline fields, setting `blurOnSubmit` - * to `true` means that pressing return will blur the field and trigger the - * `onSubmitEditing` event instead of inserting a newline into the field. - */ - blurOnSubmit: PropTypes.bool, - /** - * Note that not all Text styles are supported, - * see [Issue#7070](https://github.com/facebook/react-native/issues/7070) - * for more detail. - * - * [Styles](docs/style.html) - */ - style: Text.propTypes.style, - /** - * The color of the `TextInput` underline. - * @platform android - */ - underlineColorAndroid: ColorPropType, - - /** - * If defined, the provided image resource will be rendered on the left. - * @platform android - */ - inlineImageLeft: PropTypes.string, - - /** - * Padding between the inline image, if any, and the text input itself. - * @platform android - */ - inlineImagePadding: PropTypes.number, - - /** - * Determines the types of data converted to clickable URLs in the text input. - * Only valid if `multiline={true}` and `editable={false}`. - * By default no data types are detected. - * - * You can provide one type or an array of many types. - * - * Possible values for `dataDetectorTypes` are: - * - * - `'phoneNumber'` - * - `'link'` - * - `'address'` - * - `'calendarEvent'` - * - `'none'` - * - `'all'` - * - * @platform ios - */ - dataDetectorTypes: PropTypes.oneOfType([ - PropTypes.oneOf(DataDetectorTypes), - PropTypes.arrayOf(PropTypes.oneOf(DataDetectorTypes)) - ]), - /** - * If `true`, caret is hidden. The default value is `false`. - */ - caretHidden: PropTypes.bool - }, - - /** - * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We - * make `this` look like an actual native component class. - */ - mixins: [NativeMethodsMixin, TimerMixin], - - /** - * Returns `true` if the input is currently focused; `false` otherwise. - */ - isFocused: function(): boolean { - return ( - TextInputState.currentlyFocusedField() === - ReactNative.findNodeHandle(this._inputRef) - ); - }, - - contextTypes: { - onFocusRequested: PropTypes.func, - focusEmitter: PropTypes.instanceOf(EventEmitter) - }, - - _inputRef: (undefined: any), - _focusSubscription: (undefined: ?Function), - _lastNativeText: (undefined: ?string), - _lastNativeSelection: (undefined: ?Selection), - - componentDidMount: function() { - this._lastNativeText = this.props.value; - if (!this.context.focusEmitter) { - if (this.props.autoFocus) { - this.requestAnimationFrame(this.focus); - } - return; - } - this._focusSubscription = this.context.focusEmitter.addListener( - "focus", - (el) => { - if (this === el) { - this.requestAnimationFrame(this.focus); - } else if (this.isFocused()) { - this.blur(); - } - } - ); - if (this.props.autoFocus) { - this.context.onFocusRequested(this); - } - }, - - componentWillUnmount: function() { - this._focusSubscription && this._focusSubscription.remove(); - if (this.isFocused()) { - this.blur(); - } - }, - - getChildContext: function(): Object { - return { isInAParentText: true }; - }, - - childContextTypes: { - isInAParentText: PropTypes.bool - }, - - /** - * Removes all text from the `TextInput`. - */ - clear: function() { - this.setNativeProps({ text: "" }); - }, - - render: function() { - if (Platform.OS === "ios") { - return this._renderIOS(); - } else if (Platform.OS === "android") { - return this._renderAndroid(); - } else if (Platform.OS === "dom") { - return this._renderDom(); - } - }, - - _getText: function(): ?string { - return typeof this.props.value === "string" - ? this.props.value - : typeof this.props.defaultValue === "string" - ? this.props.defaultValue - : ""; - }, - - _setNativeRef: function(ref: any) { - this._inputRef = ref; - }, - - _renderIOS: function() { - var textContainer; - - var props = Object.assign({}, this.props); - props.style = [this.props.style]; - - if (props.selection && props.selection.end == null) { - props.selection = { - start: props.selection.start, - end: props.selection.start - }; - } - - if (!props.multiline) { - if (__DEV__) { - for (var propKey in onlyMultiline) { - if (props[propKey]) { - const error = new Error( - "TextInput prop `" + - propKey + - "` is only supported with multiline." - ); - warning(false, "%s", error.stack); - } - } - } - textContainer = ( - - ); - } else { - var children = props.children; - var childCount = 0; - React.Children.forEach(children, () => ++childCount); - invariant( - !(props.value && childCount), - "Cannot specify both value and children." - ); - if (childCount >= 1) { - children = {children}; - } - if (props.inputView) { - children = [children, props.inputView]; - } - props.style.unshift(styles.multilineInput); - textContainer = ( - - ); - } - - return ( - - {textContainer} - - ); - }, - - _renderAndroid: function() { - const props = Object.assign({}, this.props); - props.style = [this.props.style]; - props.autoCapitalize = - UIManager.AndroidTextInput.Constants.AutoCapitalizationType[ - this.props.autoCapitalize - ]; - var children = this.props.children; - var childCount = 0; - React.Children.forEach(children, () => ++childCount); - invariant( - !(this.props.value && childCount), - "Cannot specify both value and children." - ); - if (childCount > 1) { - children = {children}; - } - - if (props.selection && props.selection.end == null) { - props.selection = { - start: props.selection.start, - end: props.selection.start - }; - } - - const textContainer = ( - - ); - - return ( - - {textContainer} - - ); - }, - - _renderDom: function() { - var textContainer; - - var props = Object.assign({}, this.props); - props.style = [this.props.style]; - - if (props.selection && props.selection.end == null) { - props.selection = { - start: props.selection.start, - end: props.selection.start - }; - } - - if (!props.multiline) { - if (__DEV__) { - for (var propKey in onlyMultiline) { - if (props[propKey]) { - const error = new Error( - "TextInput prop `" + - propKey + - "` is only supported with multiline." - ); - warning(false, "%s", error.stack); - } - } - } - textContainer = ( - - ); - } else { - textContainer = ( - - ); - } - - return ( - - {textContainer} - - ); - }, - - _onFocus: function(event: Event) { - if (this.props.onFocus) { - this.props.onFocus(event); - } - - if (this.props.selectionState) { - this.props.selectionState.focus(); - } - }, - - _onPress: function(event: Event) { - if (this.props.editable || this.props.editable === undefined) { - this.focus(); - } - }, - - _onChange: function(event: Event) { - // Make sure to fire the mostRecentEventCount first so it is already set on - // native when the text value is set. - if (this._inputRef) { - this._inputRef.setNativeProps({ - mostRecentEventCount: event.nativeEvent.eventCount - }); - } - - var text = event.nativeEvent.text; - this.props.onChange && this.props.onChange(event); - this.props.onChangeText && this.props.onChangeText(text); - - if (!this._inputRef) { - // calling `this.props.onChange` or `this.props.onChangeText` - // may clean up the input itself. Exits here. - return; - } - - this._lastNativeText = text; - this.forceUpdate(); - }, - - _onSelectionChange: function(event: Event) { - this.props.onSelectionChange && this.props.onSelectionChange(event); - - if (!this._inputRef) { - // calling `this.props.onSelectionChange` - // may clean up the input itself. Exits here. - return; - } - - this._lastNativeSelection = event.nativeEvent.selection; - - if (this.props.selection || this.props.selectionState) { - this.forceUpdate(); - } - }, - - componentDidUpdate: function() { - // This is necessary in case native updates the text and JS decides - // that the update should be ignored and we should stick with the value - // that we have in JS. - const nativeProps = {}; - - if ( - this._lastNativeText !== this.props.value && - typeof this.props.value === "string" - ) { - nativeProps.text = this.props.value; - } - - // Selection is also a controlled prop, if the native value doesn't match - // JS, update to the JS value. - const { selection } = this.props; - if ( - this._lastNativeSelection && - selection && - (this._lastNativeSelection.start !== selection.start || - this._lastNativeSelection.end !== selection.end) - ) { - nativeProps.selection = this.props.selection; - } - - if (Object.keys(nativeProps).length > 0 && this._inputRef) { - this._inputRef.setNativeProps(nativeProps); - } - - if (this.props.selectionState && selection) { - this.props.selectionState.update(selection.start, selection.end); - } - }, - - _onBlur: function(event: Event) { - this.blur(); - if (this.props.onBlur) { - this.props.onBlur(event); - } - - if (this.props.selectionState) { - this.props.selectionState.blur(); - } - }, - - _onTextInput: function(event: Event) { - this.props.onTextInput && this.props.onTextInput(event); - }, - - _onScroll: function(event: Event) { - this.props.onScroll && this.props.onScroll(event); - } -}); - -var styles = StyleSheet.create({ - multilineInput: { - // This default top inset makes RCTTextView seem as close as possible - // to single-line RCTTextField defaults, using the system defaults - // of font size 17 and a height of 31 points. - paddingTop: 5 - } -}); - -module.exports = TextInput; diff --git a/packages/react-native-dom/Libraries/Components/TextInput/TextInputState.dom.js b/packages/react-native-dom/Libraries/Components/TextInput/TextInputState.dom.js deleted file mode 100644 index 8b273a2ce..000000000 --- a/packages/react-native-dom/Libraries/Components/TextInput/TextInputState.dom.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * - * This class is responsible for coordinating the "focused" - * state for TextInputs. All calls relating to the keyboard - * should be funneled through here - * - * @format - * @flow - */ - -"use strict"; - -const Platform = require("Platform"); -const UIManager = require("UIManager"); - -let currentlyFocusedID: ?number = null; -const inputs = new Set(); - -/** - * Returns the ID of the currently focused text field, if one exists - * If no text field is focused it returns null - */ -function currentlyFocusedField(): ?number { - return currentlyFocusedID; -} - -/** - * @param {number} TextInputID id of the text field to focus - * Focuses the specified text field - * noop if the text field was already focused - */ -function focusTextInput(textFieldID: ?number) { - if (currentlyFocusedID !== textFieldID && textFieldID !== null) { - currentlyFocusedID = textFieldID; - if (Platform.OS === "ios" || Platform.OS === "dom") { - UIManager.focus(textFieldID); - } else if (Platform.OS === "android") { - UIManager.dispatchViewManagerCommand( - textFieldID, - UIManager.AndroidTextInput.Commands.focusTextInput, - null - ); - } - } -} - -/** - * @param {number} textFieldID id of the text field to unfocus - * Unfocuses the specified text field - * noop if it wasn't focused - */ -function blurTextInput(textFieldID: ?number) { - if (currentlyFocusedID === textFieldID && textFieldID !== null) { - currentlyFocusedID = null; - if (Platform.OS === "ios" || Platform.OS === "dom") { - UIManager.blur(textFieldID); - } else if (Platform.OS === "android") { - UIManager.dispatchViewManagerCommand( - textFieldID, - UIManager.AndroidTextInput.Commands.blurTextInput, - null - ); - } - } -} - -function registerInput(textFieldID: number) { - inputs.add(textFieldID); -} - -function unregisterInput(textFieldID: number) { - inputs.delete(textFieldID); -} - -function isTextInput(textFieldID: number) { - return inputs.has(textFieldID); -} - -module.exports = { - currentlyFocusedField, - focusTextInput, - blurTextInput, - registerInput, - unregisterInput, - isTextInput -}; diff --git a/packages/react-native-dom/Libraries/Components/TimePickerAndroid/TimePickerAndroid.dom.js b/packages/react-native-dom/Libraries/Components/TimePickerAndroid/TimePickerAndroid.dom.js deleted file mode 100644 index d51f8c1f4..000000000 --- a/packages/react-native-dom/Libraries/Components/TimePickerAndroid/TimePickerAndroid.dom.js +++ /dev/null @@ -1,22 +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 TimePickerAndroid - * @flow - */ -"use strict"; - -const TimePickerAndroid = { - async open(options: Object): Promise { - return Promise.reject({ - message: "TimePickerAndroid is not supported on this platform." - }); - } -}; - -module.exports = TimePickerAndroid; diff --git a/packages/react-native-dom/Libraries/Components/ToolbarAndroid/ToolbarAndroid.dom.js b/packages/react-native-dom/Libraries/Components/ToolbarAndroid/ToolbarAndroid.dom.js deleted file mode 100644 index 4a58db03e..000000000 --- a/packages/react-native-dom/Libraries/Components/ToolbarAndroid/ToolbarAndroid.dom.js +++ /dev/null @@ -1,13 +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 ToolbarAndroid - */ -"use strict"; - -module.exports = require("UnimplementedView"); diff --git a/packages/react-native-dom/Libraries/Components/Touchable/TouchableNativeFeedback.dom.js b/packages/react-native-dom/Libraries/Components/Touchable/TouchableNativeFeedback.dom.js deleted file mode 100644 index 6d8cee22e..000000000 --- a/packages/react-native-dom/Libraries/Components/Touchable/TouchableNativeFeedback.dom.js +++ /dev/null @@ -1,13 +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 TouchableNativeFeedback - */ -"use strict"; - -module.exports = require("UnimplementedView"); diff --git a/packages/react-native-dom/Libraries/Components/View/PlatformViewPropTypes.dom.js b/packages/react-native-dom/Libraries/Components/View/PlatformViewPropTypes.dom.js deleted file mode 100644 index 43acf6842..000000000 --- a/packages/react-native-dom/Libraries/Components/View/PlatformViewPropTypes.dom.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @providesModule PlatformViewPropTypes - * @flow - */ - -module.exports = {}; diff --git a/packages/react-native-dom/Libraries/Components/ViewPager/ViewPagerAndroid.dom.js b/packages/react-native-dom/Libraries/Components/ViewPager/ViewPagerAndroid.dom.js deleted file mode 100644 index bac7fd411..000000000 --- a/packages/react-native-dom/Libraries/Components/ViewPager/ViewPagerAndroid.dom.js +++ /dev/null @@ -1,13 +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 ViewPagerAndroid - */ -"use strict"; - -module.exports = require("UnimplementedView"); diff --git a/packages/react-native-dom/Libraries/Components/WebView/WebView.dom.js b/packages/react-native-dom/Libraries/Components/WebView/WebView.dom.js deleted file mode 100644 index 5a20ccfc2..000000000 --- a/packages/react-native-dom/Libraries/Components/WebView/WebView.dom.js +++ /dev/null @@ -1,673 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @providesModule WebView - * @noflow - */ -"use strict"; - -const ActivityIndicator = require("ActivityIndicator"); -const EdgeInsetsPropType = require("EdgeInsetsPropType"); -const React = require("React"); -const PropTypes = require("prop-types"); -const ReactNative = require("ReactNative"); -const StyleSheet = require("StyleSheet"); -const Text = require("Text"); -const UIManager = require("UIManager"); -const View = require("View"); -const ViewPropTypes = require("ViewPropTypes"); -const ScrollView = require("ScrollView"); - -const deprecatedPropType = require("deprecatedPropType"); -const invariant = require("fbjs/lib/invariant"); -const keyMirror = require("fbjs/lib/keyMirror"); -const processDecelerationRate = require("processDecelerationRate"); -const requireNativeComponent = require("requireNativeComponent"); -const resolveAssetSource = require("resolveAssetSource"); - -const RCTWebViewManager = require("NativeModules").WebViewManager; - -const BGWASH = "rgba(255,255,255,0.8)"; -const RCT_WEBVIEW_REF = "webview"; - -const WebViewState = keyMirror({ - IDLE: null, - LOADING: null, - ERROR: null -}); - -const NavigationType = keyMirror({ - click: true, - formsubmit: true, - backforward: true, - reload: true, - formresubmit: true, - other: true -}); - -const JSNavigationScheme = "react-js-navigation"; - -type ErrorEvent = { - domain: any, - code: any, - description: any -}; - -type Event = Object; - -const DataDetectorTypes = [ - "phoneNumber", - "link", - "address", - "calendarEvent", - "none", - "all" -]; - -const defaultRenderLoading = () => ( - - - -); -const defaultRenderError = (errorDomain, errorCode, errorDesc) => ( - - Error loading page - {"Domain: " + errorDomain} - {"Error Code: " + errorCode} - {"Description: " + errorDesc} - -); - -/** - * `WebView` renders web content in a native view. - * - *``` - * import React, { Component } from 'react'; - * import { WebView } from 'react-native'; - * - * class MyWeb extends Component { - * render() { - * return ( - * - * ); - * } - * } - *``` - * - * You can use this component to navigate back and forth in the web view's - * history and configure various properties for the web content. - */ -class WebView extends React.Component { - static JSNavigationScheme = JSNavigationScheme; - static NavigationType = NavigationType; - static get extraNativeComponentConfig() { - return { - nativeOnly: { - onLoadingStart: true, - onLoadingError: true, - onLoadingFinish: true, - onMessage: true, - messagingEnabled: PropTypes.bool - } - }; - } - - static propTypes = { - ...ViewPropTypes, - - html: deprecatedPropType( - PropTypes.string, - "Use the `source` prop instead." - ), - - url: deprecatedPropType(PropTypes.string, "Use the `source` prop instead."), - - /** - * Loads static html or a uri (with optional headers) in the WebView. - */ - source: PropTypes.oneOfType([ - PropTypes.shape({ - /* - * The URI to load in the `WebView`. Can be a local or remote file. - */ - uri: PropTypes.string, - /* - * The HTTP Method to use. Defaults to GET if not specified. - * NOTE: On Android, only GET and POST are supported. - */ - method: PropTypes.string, - /* - * Additional HTTP headers to send with the request. - * NOTE: On Android, this can only be used with GET requests. - */ - headers: PropTypes.object, - /* - * The HTTP body to send with the request. This must be a valid - * UTF-8 string, and will be sent exactly as specified, with no - * additional encoding (e.g. URL-escaping or base64) applied. - * NOTE: On Android, this can only be used with POST requests. - */ - body: PropTypes.string - }), - PropTypes.shape({ - /* - * A static HTML page to display in the WebView. - */ - html: PropTypes.string, - /* - * The base URL to be used for any relative links in the HTML. - */ - baseUrl: PropTypes.string - }), - /* - * Used internally by packager. - */ - PropTypes.number - ]), - - /** - * Function that returns a view to show if there's an error. - */ - renderError: PropTypes.func, // view to show if there's an error - /** - * Function that returns a loading indicator. - */ - renderLoading: PropTypes.func, - /** - * Function that is invoked when the `WebView` has finished loading. - */ - onLoad: PropTypes.func, - /** - * Function that is invoked when the `WebView` load succeeds or fails. - */ - onLoadEnd: PropTypes.func, - /** - * Function that is invoked when the `WebView` starts loading. - */ - onLoadStart: PropTypes.func, - /** - * Function that is invoked when the `WebView` load fails. - */ - onError: PropTypes.func, - /** - * Boolean value that determines whether the web view bounces - * when it reaches the edge of the content. The default value is `true`. - * @platform ios - */ - bounces: PropTypes.bool, - /** - * A floating-point number that determines how quickly the scroll view - * decelerates after the user lifts their finger. You may also use the - * string shortcuts `"normal"` and `"fast"` which match the underlying iOS - * settings for `UIScrollViewDecelerationRateNormal` and - * `UIScrollViewDecelerationRateFast` respectively: - * - * - normal: 0.998 - * - fast: 0.99 (the default for iOS web view) - * @platform ios - */ - decelerationRate: PropTypes.oneOfType([ - PropTypes.oneOf(["fast", "normal"]), - PropTypes.number - ]), - /** - * Boolean value that determines whether scrolling is enabled in the - * `WebView`. The default value is `true`. - * @platform ios - */ - scrollEnabled: PropTypes.bool, - /** - * Controls whether to adjust the content inset for web views that are - * placed behind a navigation bar, tab bar, or toolbar. The default value - * is `true`. - */ - automaticallyAdjustContentInsets: PropTypes.bool, - /** - * The amount by which the web view content is inset from the edges of - * the scroll view. Defaults to {top: 0, left: 0, bottom: 0, right: 0}. - * @platform ios - */ - contentInset: EdgeInsetsPropType, - /** - * Function that is invoked when the `WebView` loading starts or ends. - */ - onNavigationStateChange: PropTypes.func, - /** - * A function that is invoked when the webview calls `window.postMessage`. - * Setting this property will inject a `postMessage` global into your - * webview, but will still call pre-existing values of `postMessage`. - * - * `window.postMessage` accepts one argument, `data`, which will be - * available on the event object, `event.nativeEvent.data`. `data` - * must be a string. - */ - onMessage: PropTypes.func, - /** - * Boolean value that forces the `WebView` to show the loading view - * on the first load. - */ - startInLoadingState: PropTypes.bool, - /** - * The style to apply to the `WebView`. - */ - style: ViewPropTypes.style, - - /** - * Determines the types of data converted to clickable URLs in the web view's content. - * By default only phone numbers are detected. - * - * You can provide one type or an array of many types. - * - * Possible values for `dataDetectorTypes` are: - * - * - `'phoneNumber'` - * - `'link'` - * - `'address'` - * - `'calendarEvent'` - * - `'none'` - * - `'all'` - * - * @platform ios - */ - dataDetectorTypes: PropTypes.oneOfType([ - PropTypes.oneOf(DataDetectorTypes), - PropTypes.arrayOf(PropTypes.oneOf(DataDetectorTypes)) - ]), - - /** - * Boolean value to enable JavaScript in the `WebView`. Used on Android only - * as JavaScript is enabled by default on iOS. The default value is `true`. - * @platform android - */ - javaScriptEnabled: PropTypes.bool, - - /** - * Boolean value to enable third party cookies in the `WebView`. Used on - * Android Lollipop and above only as third party cookies are enabled by - * default on Android Kitkat and below and on iOS. The default value is `true`. - * @platform android - */ - thirdPartyCookiesEnabled: PropTypes.bool, - - /** - * Boolean value to control whether DOM Storage is enabled. Used only in - * Android. - * @platform android - */ - domStorageEnabled: PropTypes.bool, - - /** - * Set this to provide JavaScript that will be injected into the web page - * when the view loads. - */ - injectedJavaScript: PropTypes.string, - - /** - * Sets the user-agent for the `WebView`. - * @platform android - */ - userAgent: PropTypes.string, - - /** - * Boolean that controls whether the web content is scaled to fit - * the view and enables the user to change the scale. The default value - * is `true`. - */ - scalesPageToFit: PropTypes.bool, - - /** - * Function that allows custom handling of any web view requests. Return - * `true` from the function to continue loading the request and `false` - * to stop loading. - * @platform ios - */ - onShouldStartLoadWithRequest: PropTypes.func, - - /** - * Boolean that determines whether HTML5 videos play inline or use the - * native full-screen controller. The default value is `false`. - * - * **NOTE** : In order for video to play inline, not only does this - * property need to be set to `true`, but the video element in the HTML - * document must also include the `webkit-playsinline` attribute. - * @platform ios - */ - allowsInlineMediaPlayback: PropTypes.bool, - - /** - * Boolean that determines whether HTML5 audio and video requires the user - * to tap them before they start playing. The default value is `true`. - */ - mediaPlaybackRequiresUserAction: PropTypes.bool, - - /** - * Function that accepts a string that will be passed to the WebView and - * executed immediately as JavaScript. - */ - injectJavaScript: PropTypes.func, - - /** - * Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin. - * - * Possible values for `mixedContentMode` are: - * - * - `'never'` (default) - WebView will not allow a secure origin to load content from an insecure origin. - * - `'always'` - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure. - * - `'compatibility'` - WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content. - * @platform android - */ - mixedContentMode: PropTypes.oneOf(["never", "always", "compatibility"]), - - /** - * Override the native component used to render the WebView. Enables a custom native - * WebView which uses the same JavaScript as the original WebView. - */ - nativeConfig: PropTypes.shape({ - /* - * The native component used to render the WebView. - */ - component: PropTypes.any, - /* - * Set props directly on the native component WebView. Enables custom props which the - * original WebView doesn't pass through. - */ - props: PropTypes.object, - /* - * Set the ViewManager to use for communcation with the native side. - * @platform ios - */ - viewManager: PropTypes.object - }) - }; - - static defaultProps = { - scalesPageToFit: true - }; - - state = { - viewState: WebViewState.IDLE, - lastErrorEvent: (null: ?ErrorEvent), - startInLoadingState: true - }; - - UNSAFE_componentWillMount() { - if (this.props.startInLoadingState) { - this.setState({ viewState: WebViewState.LOADING }); - } - } - - render() { - let otherView = null; - - if (this.state.viewState === WebViewState.LOADING) { - otherView = (this.props.renderLoading || defaultRenderLoading)(); - } else if (this.state.viewState === WebViewState.ERROR) { - const errorEvent = this.state.lastErrorEvent; - invariant(errorEvent != null, "lastErrorEvent expected to be non-null"); - otherView = (this.props.renderError || defaultRenderError)( - errorEvent.domain, - errorEvent.code, - errorEvent.description - ); - } else if (this.state.viewState !== WebViewState.IDLE) { - console.error( - "RCTWebView invalid state encountered: " + this.state.loading - ); - } - - const webViewStyles = [styles.container, styles.webView, this.props.style]; - if ( - this.state.viewState === WebViewState.LOADING || - this.state.viewState === WebViewState.ERROR - ) { - // if we're in either LOADING or ERROR states, don't show the webView - webViewStyles.push(styles.hidden); - } - - const nativeConfig = this.props.nativeConfig || {}; - - const viewManager = nativeConfig.viewManager || RCTWebViewManager; - - const onShouldStartLoadWithRequest = - this.props.onShouldStartLoadWithRequest && - ((event: Event) => { - const shouldStart = - this.props.onShouldStartLoadWithRequest && - this.props.onShouldStartLoadWithRequest(event.nativeEvent); - viewManager.startLoadWithResult( - !!shouldStart, - event.nativeEvent.lockIdentifier - ); - }); - - const decelerationRate = processDecelerationRate( - this.props.decelerationRate - ); - - const source = this.props.source || {}; - if (this.props.html) { - source.html = this.props.html; - } else if (this.props.url) { - source.uri = this.props.url; - } - - const messagingEnabled = typeof this.props.onMessage === "function"; - - const NativeWebView = nativeConfig.component || RCTWebView; - - const webView = ( - - ); - - return ( - - {webView} - {otherView} - - ); - } - - /** - * Go forward one page in the web view's history. - */ - goForward = () => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.RCTWebView.Commands.goForward, - null - ); - }; - - /** - * Go back one page in the web view's history. - */ - goBack = () => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.RCTWebView.Commands.goBack, - null - ); - }; - - /** - * Reloads the current page. - */ - reload = () => { - this.setState({ viewState: WebViewState.LOADING }); - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.RCTWebView.Commands.reload, - null - ); - }; - - /** - * Stop loading the current page. - */ - stopLoading = () => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.RCTWebView.Commands.stopLoading, - null - ); - }; - - /** - * Posts a message to the web view, which will emit a `message` event. - * Accepts one argument, `data`, which must be a string. - * - * In your webview, you'll need to something like the following. - * - * ```js - * document.addEventListener('message', e => { document.title = e.data; }); - * ``` - */ - postMessage = (data) => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.RCTWebView.Commands.postMessage, - [String(data)] - ); - }; - - /** - * Injects a javascript string into the referenced WebView. Deliberately does not - * return a response because using eval() to return a response breaks this method - * on pages with a Content Security Policy that disallows eval(). If you need that - * functionality, look into postMessage/onMessage. - */ - injectJavaScript = (data) => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.RCTWebView.Commands.injectJavaScript, - [data] - ); - }; - - /** - * We return an event with a bunch of fields including: - * url, title, loading, canGoBack, canGoForward - */ - _updateNavigationState = (event: Event) => { - if (this.props.onNavigationStateChange) { - this.props.onNavigationStateChange(event.nativeEvent); - } - }; - - /** - * Returns the native `WebView` node. - */ - getWebViewHandle = (): any => { - return ReactNative.findNodeHandle(this.refs[RCT_WEBVIEW_REF]); - }; - - _onLoadingStart = (event: Event) => { - const onLoadStart = this.props.onLoadStart; - onLoadStart && onLoadStart(event); - this._updateNavigationState(event); - }; - - _onLoadingError = (event: Event) => { - event.persist(); // persist this event because we need to store it - const { onError, onLoadEnd } = this.props; - onError && onError(event); - onLoadEnd && onLoadEnd(event); - console.warn("Encountered an error loading page", event.nativeEvent); - - this.setState({ - lastErrorEvent: event.nativeEvent, - viewState: WebViewState.ERROR - }); - }; - - _onLoadingFinish = (event: Event) => { - const { onLoad, onLoadEnd } = this.props; - onLoad && onLoad(event); - onLoadEnd && onLoadEnd(event); - this.setState({ - viewState: WebViewState.IDLE - }); - this._updateNavigationState(event); - }; - - _onMessage = (event: Event) => { - const { onMessage } = this.props; - onMessage && onMessage(event); - }; -} - -const RCTWebView = requireNativeComponent( - "RCTWebView", - WebView, - WebView.extraNativeComponentConfig -); - -const styles = StyleSheet.create({ - container: { - flex: 1 - }, - errorContainer: { - flex: 1, - justifyContent: "center", - alignItems: "center", - backgroundColor: BGWASH - }, - errorText: { - fontSize: 14, - textAlign: "center", - marginBottom: 2 - }, - errorTextTitle: { - fontSize: 15, - fontWeight: "500", - marginBottom: 10 - }, - hidden: { - height: 0, - flex: 0 // disable 'flex:1' when hiding a View - }, - loadingView: { - backgroundColor: BGWASH, - flex: 1, - justifyContent: "center", - alignItems: "center", - height: 100 - }, - webView: { - backgroundColor: "#ffffff" - } -}); - -module.exports = WebView; diff --git a/packages/react-native-dom/Libraries/Core/Devtools/setupDevtools.dom.js b/packages/react-native-dom/Libraries/Core/Devtools/setupDevtools.dom.js deleted file mode 100644 index dbd5a7ab3..000000000 --- a/packages/react-native-dom/Libraries/Core/Devtools/setupDevtools.dom.js +++ /dev/null @@ -1,69 +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 setupDevtools - * @flow - */ -"use strict"; - -type DevToolsPluginConnection = { - isAppActive: () => boolean, - host: string, - port: number -}; - -type DevToolsPlugin = { - connectToDevTools: (connection: DevToolsPluginConnection) => void -}; - -let register = function() { - // noop -}; - -if (__DEV__) { - const AppState = require("AppState"); - const WebSocket = require("WebSocket"); - const { PlatformConstants } = require("NativeModules"); - /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an - * error found when Flow v0.54 was deployed. To see the error delete this - * comment and run Flow. */ - const reactDevTools = require("react-devtools-core"); - - register = function(plugin: DevToolsPlugin) { - // Initialize dev tools only if the native module for WebSocket is available - if (self.__DEVTOOLS__ && WebSocket.isAvailable) { - // Don't steal the DevTools from currently active app. - // Note: if you add any AppState subscriptions to this file, - // you will also need to guard against `AppState.isAvailable`, - // or the code will throw for bundles that don't have it. - const isAppActive = () => true; - - // Special case: Genymotion is running on a different host. - const host = - PlatformConstants && PlatformConstants.ServerHost - ? PlatformConstants.ServerHost.split(":")[0] - : "localhost"; - - plugin.connectToDevTools({ - isAppActive, - host, - // Read the optional global variable for backward compatibility. - // It was added in https://github.com/facebook/react-native/commit/bf2b435322e89d0aeee8792b1c6e04656c2719a0. - port: window.__REACT_DEVTOOLS_PORT__, - resolveRNStyle: require("flattenStyle") - }); - } - }; - - register(reactDevTools); - global.registerDevtoolsPlugin = register; -} - -module.exports = { - register -}; diff --git a/packages/react-native-dom/Libraries/Image/Image.dom.js b/packages/react-native-dom/Libraries/Image/Image.dom.js deleted file mode 100644 index 64af8d1f6..000000000 --- a/packages/react-native-dom/Libraries/Image/Image.dom.js +++ /dev/null @@ -1,419 +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 Image - * @flow - */ -"use strict"; - -const EdgeInsetsPropType = require("EdgeInsetsPropType"); -const ImageResizeMode = require("ImageResizeMode"); -const ImageSourcePropType = require("ImageSourcePropType"); -const ImageStylePropTypes = require("ImageStylePropTypes"); -const NativeMethodsMixin = require("NativeMethodsMixin"); -const NativeModules = require("NativeModules"); -const React = require("React"); -const PropTypes = require("prop-types"); -const ReactNativeViewAttributes = require("ReactNativeViewAttributes"); -const StyleSheet = require("StyleSheet"); -const StyleSheetPropType = require("StyleSheetPropType"); - -const createReactClass = require("create-react-class"); -const flattenStyle = require("flattenStyle"); -const requireNativeComponent = require("requireNativeComponent"); -const resolveAssetSource = require("resolveAssetSource"); - -const ImageViewManager = NativeModules.ImageViewManager; - -/** - * 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. - * - * This example shows fetching and displaying an image from local storage - * as well as one from network and even from data provided in the `'data:'` uri scheme. - * - * > Note that for network and data images, you will need to manually specify the dimensions of your image! - * - * ```ReactNativeWebPlayer - * import React, { Component } from 'react'; - * import { AppRegistry, View, Image } from 'react-native'; - * - * export default class DisplayAnImage extends Component { - * render() { - * return ( - * - * - * - * - * - * ); - * } - * } - * - * // skip this line if using Create React Native App - * AppRegistry.registerComponent('DisplayAnImage', () => DisplayAnImage); - * ``` - * - * You can also add `style` to an image: - * - * ```ReactNativeWebPlayer - * import React, { Component } from 'react'; - * import { AppRegistry, View, Image, StyleSheet } from 'react-native'; - * - * const styles = StyleSheet.create({ - * stretch: { - * width: 50, - * height: 200 - * } - * }); - * - * export default class DisplayAnImageWithStyle extends Component { - * render() { - * return ( - * - * - * - * ); - * } - * } - * - * // skip these lines if using Create React Native App - * AppRegistry.registerComponent( - * 'DisplayAnImageWithStyle', - * () => DisplayAnImageWithStyle - * ); - * ``` - * - * ### GIF and WebP support on Android - * - * When building your own native code, GIF and WebP are not supported by default on Android. - * - * You will need to add some optional modules in `android/app/build.gradle`, depending on the needs of your app. - * - * ``` - * dependencies { - * // If your app supports Android versions before Ice Cream Sandwich (API level 14) - * compile 'com.facebook.fresco:animated-base-support:1.3.0' - * - * // For animated GIF support - * compile 'com.facebook.fresco:animated-gif:1.3.0' - * - * // For WebP support, including animated WebP - * compile 'com.facebook.fresco:animated-webp:1.3.0' - * compile 'com.facebook.fresco:webpsupport:1.3.0' - * - * // For WebP support, without animations - * compile 'com.facebook.fresco:webpsupport:1.3.0' - * } - * ``` - * - * Also, if you use GIF with ProGuard, you will need to add this rule in `proguard-rules.pro` : - * ``` - * -keep class com.facebook.imagepipeline.animated.factory.AnimatedFactoryImpl { - * public AnimatedFactoryImpl(com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory, com.facebook.imagepipeline.core.ExecutorSupplier); - * } - * ``` - * - */ -// $FlowFixMe(>=0.41.0) -const Image = createReactClass({ - displayName: "Image", - propTypes: { - /** - * > `ImageResizeMode` is an `Enum` for different image resizing modes, set via the - * > `resizeMode` style property on `Image` components. The values are `contain`, `cover`, - * > `stretch`, `center`, `repeat`. - */ - style: StyleSheetPropType(ImageStylePropTypes), - /** - * The image source (either a remote URL or a local file resource). - * - * This prop can also contain several remote URLs, specified together with - * their width and height and potentially with scale/other URI arguments. - * The native side will then choose the best `uri` to display based on the - * measured size of the image container. A `cache` property can be added to - * control how networked request interacts with the local cache. - * - * The currently supported formats are `png`, `jpg`, `jpeg`, `bmp`, `gif`, - * `webp` (Android only), `psd` (iOS only). - */ - source: ImageSourcePropType, - /** - * A static image to display while loading the image source. - * - * - `uri` - a string representing the resource identifier for the image, which - * should be either a local file path or the name of a static image resource - * (which should be wrapped in the `require('./path/to/image.png')` function). - * - `width`, `height` - can be specified if known at build time, in which case - * these will be used to set the default `` component dimensions. - * - `scale` - used to indicate the scale factor of the image. Defaults to 1.0 if - * unspecified, meaning that one image pixel equates to one display point / DIP. - * - `number` - Opaque type returned by something like `require('./image.jpg')`. - * - * @platform ios - */ - defaultSource: PropTypes.oneOfType([ - // TODO: Tooling to support documenting these directly and having them display in the docs. - PropTypes.shape({ - uri: PropTypes.string, - width: PropTypes.number, - height: PropTypes.number, - scale: PropTypes.number - }), - PropTypes.number - ]), - /** - * When true, indicates the image is an accessibility element. - * @platform ios - */ - accessible: PropTypes.bool, - /** - * The text that's read by the screen reader when the user interacts with - * the image. - * @platform ios - */ - accessibilityLabel: PropTypes.node, - /** - * blurRadius: the blur radius of the blur filter added to the image - */ - blurRadius: PropTypes.number, - /** - * When the image is resized, the corners of the size specified - * by `capInsets` will stay a fixed size, but the center content and borders - * of the image will be stretched. This is useful for creating resizable - * rounded buttons, shadows, and other resizable assets. More info in the - * [official Apple documentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/index.html#//apple_ref/occ/instm/UIImage/resizableImageWithCapInsets). - * - * @platform ios - */ - capInsets: EdgeInsetsPropType, - pointerEvents: PropTypes.oneOf(["box-none", "none", "box-only", "auto"]), - /** - * The mechanism that should be used to resize the image when the image's dimensions - * differ from the image view's dimensions. Defaults to `auto`. - * - * - `auto`: Use heuristics to pick between `resize` and `scale`. - * - * - `resize`: A software operation which changes the encoded image in memory before it - * gets decoded. This should be used instead of `scale` when the image is much larger - * than the view. - * - * - `scale`: The image gets drawn downscaled or upscaled. Compared to `resize`, `scale` is - * faster (usually hardware accelerated) and produces higher quality images. This - * should be used if the image is smaller than the view. It should also be used if the - * image is slightly bigger than the view. - * - * More details about `resize` and `scale` can be found at http://frescolib.org/docs/resizing-rotating.html. - * - * @platform android - */ - resizeMethod: PropTypes.oneOf(["auto", "resize", "scale"]), - /** - * Determines how to resize the image when the frame doesn't match the raw - * image dimensions. - * - * - `cover`: Scale the image uniformly (maintain the image's aspect ratio) - * so that both dimensions (width and height) of the image will be equal - * to or larger than the corresponding dimension of the view (minus padding). - * - * - `contain`: Scale the image uniformly (maintain the image's aspect ratio) - * so that both dimensions (width and height) of the image will be equal to - * or less than the corresponding dimension of the view (minus padding). - * - * - `stretch`: Scale width and height independently, This may change the - * aspect ratio of the src. - * - * - `repeat`: Repeat the image to cover the frame of the view. The - * image will keep it's size and aspect ratio. (iOS only) - */ - resizeMode: PropTypes.oneOf([ - "cover", - "contain", - "stretch", - "repeat", - "center" - ]), - /** - * A unique identifier for this element to be used in UI Automation - * testing scripts. - */ - testID: PropTypes.string, - /** - * Invoked on mount and layout changes with - * `{nativeEvent: {layout: {x, y, width, height}}}`. - */ - onLayout: PropTypes.func, - /** - * Invoked on load start. - * - * e.g., `onLoadStart={(e) => this.setState({loading: true})}` - */ - onLoadStart: PropTypes.func, - /** - * Invoked on download progress with `{nativeEvent: {loaded, total}}`. - * @platform ios - */ - onProgress: PropTypes.func, - /** - * Invoked on load error with `{nativeEvent: {error}}`. - */ - onError: PropTypes.func, - /** - * Invoked when a partial load of the image is complete. The definition of - * what constitutes a "partial load" is loader specific though this is meant - * for progressive JPEG loads. - * @platform ios - */ - onPartialLoad: PropTypes.func, - /** - * Invoked when load completes successfully. - */ - onLoad: PropTypes.func, - /** - * Invoked when load either succeeds or fails. - */ - onLoadEnd: PropTypes.func - }, - - statics: { - resizeMode: ImageResizeMode, - /** - * Retrieve the width and height (in pixels) of an image prior to displaying it. - * This method can fail if the image cannot be found, or fails to download. - * - * In order to retrieve the image dimensions, the image may first need to be - * loaded or downloaded, after which it will be cached. This means that in - * principle you could use this method to preload images, however it is not - * optimized for that purpose, and may in future be implemented in a way that - * does not fully load/download the image data. A proper, supported way to - * preload images will be provided as a separate API. - * - * Does not work for static image resources. - * - * @param uri The location of the image. - * @param success The function that will be called if the image was successfully found and width - * and height retrieved. - * @param failure The function that will be called if there was an error, such as failing to - * to retrieve the image. - * - * @returns void - * - * @platform ios - */ - getSize: function( - uri: string, - success: (width: number, height: number) => void, - failure?: (error: any) => void - ) { - ImageViewManager.getSize( - uri, - success, - failure || - function() { - console.warn("Failed to get size for image: " + uri); - } - ); - }, - /** - * Prefetches a remote image for later use by downloading it to the disk - * cache - * - * @param url The remote location of the image. - * - * @return The prefetched image. - */ - prefetch(url: string) { - return ImageViewManager.prefetchImage(url); - }, - /** - * Resolves an asset reference into an object which has the properties `uri`, `width`, - * and `height`. The input may either be a number (opaque type returned by - * require('./foo.png')) or an `ImageSource` like { uri: '' } - */ - resolveAssetSource: resolveAssetSource - }, - - mixins: [NativeMethodsMixin], - - /** - * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We - * make `this` look like an actual native component class. - */ - viewConfig: { - uiViewClassName: "UIView", - validAttributes: ReactNativeViewAttributes.UIView - }, - - render: function() { - const source = resolveAssetSource(this.props.source) || { - uri: undefined, - width: undefined, - height: undefined - }; - - let sources; - let style; - if (Array.isArray(source)) { - style = flattenStyle([styles.base, this.props.style]) || {}; - sources = source; - } else { - const { width, height, uri } = source; - style = - flattenStyle([{ width, height }, styles.base, this.props.style]) || {}; - sources = [source]; - - if (uri === "") { - console.warn("source.uri should not be an empty string"); - } - } - - const resizeMode = - this.props.resizeMode || (style || {}).resizeMode || "cover"; // Workaround for flow bug t7737108 - const tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 - - if (this.props.src) { - console.warn( - "The component requires a `source` property rather than `src`." - ); - } - - return ( - - ); - } -}); - -const styles = StyleSheet.create({ - base: { - overflow: "hidden" - } -}); - -const RCTImageView = requireNativeComponent("RCTImageView", Image, { - nativeOnly: { onStartShouldSetResponder: true } -}); - -module.exports = Image; diff --git a/packages/react-native-dom/Libraries/Network/RCTNetworking.dom.js b/packages/react-native-dom/Libraries/Network/RCTNetworking.dom.js deleted file mode 100644 index 7169e3e4a..000000000 --- a/packages/react-native-dom/Libraries/Network/RCTNetworking.dom.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @providesModule RCTNetworking - * @flow - */ -"use strict"; - -const MissingNativeEventEmitterShim = require("MissingNativeEventEmitterShim"); -const NativeEventEmitter = require("NativeEventEmitter"); -const RCTNetworkingNative = require("NativeModules").Networking; -const convertRequestBody = require("convertRequestBody"); - -import type { RequestBody } from "convertRequestBody"; - -import type { NativeResponseType } from "XMLHttpRequest"; - -class RCTNetworking extends NativeEventEmitter { - isAvailable: boolean = true; - - constructor() { - super(RCTNetworkingNative); - } - - sendRequest( - method: string, - trackingName: string, - url: string, - headers: Object, - data: RequestBody, - responseType: NativeResponseType, - incrementalUpdates: boolean, - timeout: number, - callback: (requestId: number) => any, - withCredentials: boolean - ) { - const body = convertRequestBody(data); - RCTNetworkingNative.sendRequest( - { - method, - url, - data: { ...body, trackingName }, - headers, - responseType, - incrementalUpdates, - timeout, - // TODO: Update upstream react-native to use latest fetch polyfill - withCredentials: false - }, - callback - ); - } - - abortRequest(requestId: number) { - RCTNetworkingNative.abortRequest(requestId); - } - - clearCookies(callback: (result: boolean) => any) { - RCTNetworkingNative.clearCookies(callback); - } -} - -if (__DEV__ && !RCTNetworkingNative) { - class MissingNativeRCTNetworkingShim extends MissingNativeEventEmitterShim { - constructor() { - super("RCTNetworking", "Networking"); - } - - sendRequest(...args: Array) { - this.throwMissingNativeModule(); - } - - abortRequest(...args: Array) { - this.throwMissingNativeModule(); - } - - clearCookies(...args: Array) { - this.throwMissingNativeModule(); - } - } - - // This module depends on the native `RCTNetworkingNative` module. If you don't include it, - // `RCTNetworking.isAvailable` will return `false`, and any method calls will throw. - // We reassign the class variable to keep the autodoc generator happy. - RCTNetworking = new MissingNativeRCTNetworkingShim(); -} else { - RCTNetworking = new RCTNetworking(); -} - -module.exports = RCTNetworking; diff --git a/packages/react-native-dom/Libraries/RCTTest/SnapshotViewIOS.dom.js b/packages/react-native-dom/Libraries/RCTTest/SnapshotViewIOS.dom.js deleted file mode 100644 index 58a252ba4..000000000 --- a/packages/react-native-dom/Libraries/RCTTest/SnapshotViewIOS.dom.js +++ /dev/null @@ -1,13 +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 SnapshotViewIOS - */ -"use strict"; - -module.exports = require("UnimplementedView"); diff --git a/packages/react-native-dom/Libraries/Utilities/BackHandler.dom.js b/packages/react-native-dom/Libraries/Utilities/BackHandler.dom.js deleted file mode 100644 index 1374ea81e..000000000 --- a/packages/react-native-dom/Libraries/Utilities/BackHandler.dom.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @providesModule BackHandler - */ - -"use strict"; - -var DeviceEventManager = require("NativeModules").DeviceEventManager; -var RCTDeviceEventEmitter = require("RCTDeviceEventEmitter"); - -var DEVICE_BACK_EVENT = "hardwareBackPress"; - -type BackPressEventName = $Enum<{ - backPress: string -}>; - -var _backPressSubscriptions = new Set(); - -RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() { - var invokeDefault = true; - var subscriptions = Array.from(_backPressSubscriptions.values()).reverse(); - - for (var i = 0; i < subscriptions.length; ++i) { - if (subscriptions[i]()) { - invokeDefault = false; - break; - } - } - - if (invokeDefault) { - BackHandler.exitApp(); - } -}); - -/** - * Detect hardware button presses for back navigation. - * - * Android: Detect hardware back button presses, and programmatically invoke the default back button - * functionality to exit the app if there are no listeners or if none of the listeners return true. - * - * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented: - * programmatically disable menu button handling - * functionality to exit the app if there are no listeners or if none of the listeners return true.) - * - * iOS: Not applicable. - * - * The event subscriptions are called in reverse order (i.e. last registered subscription first), - * and if one subscription returns true then subscriptions registered earlier will not be called. - * - * Example: - * - * ```javascript - * BackHandler.addEventListener('hardwareBackPress', function() { - * // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here - * // Typically you would use the navigator here to go to the last state. - * - * if (!this.onMainScreen()) { - * this.goBack(); - * return true; - * } - * return false; - * }); - * ``` - */ -var BackHandler = { - exitApp: function() { - DeviceEventManager.invokeDefaultBackPressHandler(); - }, - - /** - * Adds an event handler. Supported events: - * - * - `hardwareBackPress`: Fires when the Android hardware back button is pressed or when the - * tvOS menu button is pressed. - */ - addEventListener: function( - eventName: BackPressEventName, - handler: Function - ): { remove: () => void } { - _backPressSubscriptions.add(handler); - return { - remove: () => BackHandler.removeEventListener(eventName, handler) - }; - }, - - /** - * Removes the event handler. - */ - removeEventListener: function( - eventName: BackPressEventName, - handler: Function - ): void { - _backPressSubscriptions.delete(handler); - } -}; - -module.exports = BackHandler; diff --git a/packages/react-native-dom/Libraries/Utilities/HMRLoadingView.dom.js b/packages/react-native-dom/Libraries/Utilities/HMRLoadingView.dom.js deleted file mode 100644 index 155640ec2..000000000 --- a/packages/react-native-dom/Libraries/Utilities/HMRLoadingView.dom.js +++ /dev/null @@ -1,32 +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 HMRLoadingView - * @flow - */ - -"use strict"; - -const processColor = require("processColor"); -const { DevLoadingView } = require("NativeModules"); - -class HMRLoadingView { - static showMessage(message: string) { - DevLoadingView.showMessage( - message, - processColor("#000000"), - processColor("#aaaaaa") - ); - } - - static hide() { - DevLoadingView.hide(); - } -} - -module.exports = HMRLoadingView; diff --git a/packages/react-native-dom/Libraries/Utilities/Platform.dom.js b/packages/react-native-dom/Libraries/Utilities/Platform.dom.js deleted file mode 100644 index edca65934..000000000 --- a/packages/react-native-dom/Libraries/Utilities/Platform.dom.js +++ /dev/null @@ -1,26 +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"; - -const NativeModules = require("NativeModules"); - -const Platform = { - OS: "dom", - get ForceTouchAvailable() { - const constants = NativeModules.PlatformConstants; - return constants ? !!constants.forceTouchAvailable : false; - }, - select: (obj: Object) => ("dom" in obj ? obj.dom : obj.default) -}; - -module.exports = Platform; diff --git a/packages/react-native-dom/Libraries/Vibration/VibrationIOS.dom.js b/packages/react-native-dom/Libraries/Vibration/VibrationIOS.dom.js deleted file mode 100644 index 7e7e1eac1..000000000 --- a/packages/react-native-dom/Libraries/Vibration/VibrationIOS.dom.js +++ /dev/null @@ -1,23 +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. - * - * Stub of VibrationIOS for Android. - * - * @providesModule VibrationIOS - */ -"use strict"; - -var warning = require("fbjs/lib/warning"); - -var VibrationIOS = { - vibrate: function() { - warning("VibrationIOS is not supported on this platform!"); - } -}; - -module.exports = VibrationIOS; diff --git a/packages/react-native-dom/Libraries/YellowBox/UI/YellowBoxInspectorHeader.dom.js b/packages/react-native-dom/Libraries/YellowBox/UI/YellowBoxInspectorHeader.dom.js deleted file mode 100644 index 07c91fd68..000000000 --- a/packages/react-native-dom/Libraries/YellowBox/UI/YellowBoxInspectorHeader.dom.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -"use strict"; - -const Platform = require("Platform"); -const React = require("React"); -const SafeAreaView = require("SafeAreaView"); -const StyleSheet = require("StyleSheet"); -const Text = require("Text"); -const UTFSequence = require("UTFSequence"); -const View = require("View"); -const YellowBoxPressable = require("YellowBoxPressable"); -const YellowBoxStyle = require("YellowBoxStyle"); - -import type YellowBoxWarning from "YellowBoxWarning"; - -type Props = $ReadOnly<{| - onSelectIndex: (selectedIndex: number) => void, - selectedIndex: number, - warnings: $ReadOnlyArray -|}>; - -const YellowBoxInspectorHeader = (props: Props): React.Node => { - const prevIndex = props.selectedIndex - 1; - const nextIndex = props.selectedIndex + 1; - - const titleText = - props.warnings.length === 1 - ? "Single Occurrence" - : `Occurrence ${props.selectedIndex + 1} of ${props.warnings.length}`; - - return ( - - - props.onSelectIndex(prevIndex)} - /> - - {titleText} - - props.onSelectIndex(nextIndex)} - /> - - - ); -}; - -const YellowBoxInspectorHeaderButton = ( - props: $ReadOnly<{| - disabled: boolean, - label: React.Node, - onPress?: ?() => void - |}> -): React.Node => ( - - {props.disabled ? null : ( - {props.label} - )} - -); - -const styles = StyleSheet.create({ - root: { - backgroundColor: YellowBoxStyle.getBackgroundColor(0.95) - }, - header: { - flexDirection: "row", - height: Platform.select({ - android: 48, - ios: 44, - // THIS IS THE ONLY DOM-SPECIFIC CHANGE TO THIS MODULE - dom: 44 - }) - }, - headerButton: { - alignItems: "center", - aspectRatio: 1, - justifyContent: "center" - }, - headerButtonText: { - color: YellowBoxStyle.getTextColor(1), - fontSize: 16, - includeFontPadding: false, - lineHeight: 20 - }, - headerTitle: { - alignItems: "center", - flex: 1, - justifyContent: "center" - }, - headerTitleText: { - color: YellowBoxStyle.getTextColor(1), - fontSize: 16, - fontWeight: "600", - includeFontPadding: false, - lineHeight: 20 - } -}); - -module.exports = YellowBoxInspectorHeader; diff --git a/packages/react-native-dom/Libraries/polyfills/setBabelHelper.js b/packages/react-native-dom/Libraries/polyfills/setBabelHelper.js deleted file mode 100644 index 7021aba00..000000000 --- a/packages/react-native-dom/Libraries/polyfills/setBabelHelper.js +++ /dev/null @@ -1,34 +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. - * - * @polyfill - */ - -/* eslint-disable */ - -var babelHelpers = global.babelHelpers || {}; - -babelHelpers.set = function set(object, property, value, receiver) { - var desc = Object.getOwnPropertyDescriptor(object, property); - if (desc === undefined) { - var parent = Object.getPrototypeOf(object); - if (parent !== null) { - set(parent, property, value, receiver); - } - } else if ("value" in desc && desc.writable) { - desc.value = value; - } else { - var setter = desc.set; - if (setter !== undefined) { - setter.call(receiver, value); - } - } - return value; -}; - -global.babelHelpers = babelHelpers; diff --git a/packages/react-native-dom/README.md b/packages/react-native-dom/README.md deleted file mode 100644 index 7e050f9f7..000000000 --- a/packages/react-native-dom/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# React Native DOM - -Documentation for the framework as a whole can be found at the root Readme of -this monorepo. diff --git a/packages/react-native-dom/RNTester.md b/packages/react-native-dom/RNTester.md deleted file mode 100644 index bbc542044..000000000 --- a/packages/react-native-dom/RNTester.md +++ /dev/null @@ -1,52 +0,0 @@ -### Update the `RNTester` branch - -The same example apps from `react-native` are also available for -`react-native-dom`, including the -[RNTester](https://github.com/facebook/react-native/tree/master/Examples/UIExplorer). - -We maintain a fork of the `RNTester` folder from `react-native` as a submodule -of `react-native-dom`. The fork uses `git filter-branch` to produce a branch of -`react-native` that includes only the content of the Examples folder. We then -merge all the changes specific to `react-native-dom` with that filtered branch. - -```bash -# Be sure that you have all submodules initialized and up-to-date for react-native-dom. -cd RNTester - -# If you don't already have facebook/react-native set up as a Git remote... -git remote add facebook git@github.com:facebook/react-native - -# Fetch the latest from facebook -git fetch facebook - -# Create a new branch to run the `filter-branch` command only -git checkout -b fbmaster facebook/master - -# Filter the react-native master branch for Examples only, this will take some time -# You may have to use `-f` if you've previously run a `filter-branch` command -git filter-branch --prune-empty --subdirectory-filter RNTester fbmaster - -# Fetch the latest from react-native-dom -git fetch origin - -# Create a new staging branch to perform a merge onto the react-native-dom `examples` branch -git checkout -b staging origin/rntester - -# Merge the latest from facebook/react-native RNTester and resolve any merge conflicts -git merge fbmaster - -# Fast-forward the `rntester` branch from the `staging` branch -# Before doing this, it's probably a good idea to test that the examples are working by running them -# If anything has broken (it's common), fix it -git checkout rntester -git merge staging - -# Use the RNTester to test changes before pushing to react-native-dom - -# Push (or PR) your changes to react-native-dom -git push origin rntester - -# Cleanup your staging branches -git branch -D fbmaster -git branch -D staging -``` diff --git a/packages/react-native-dom/local-cli/generator-dom/templates/bootstrap.js b/packages/react-native-dom/dom/bootstrap.js similarity index 72% rename from packages/react-native-dom/local-cli/generator-dom/templates/bootstrap.js rename to packages/react-native-dom/dom/bootstrap.js index 3b1b45b93..d070d039c 100644 --- a/packages/react-native-dom/local-cli/generator-dom/templates/bootstrap.js +++ b/packages/react-native-dom/dom/bootstrap.js @@ -1,4 +1,8 @@ -import { RNDomInstance } from "react-native-dom"; +/** + * commented out temporary uncomment once we have npm registry for packages + */ +// import { RNDomInstance } from "react-native-dom-renderer"; +import { RNDomInstance } from "react-native-dom-renderer"; import { name as appName } from "../app.json"; // Path to RN Bundle Entrypoint ================================================ diff --git a/packages/react-native-dom/local-cli/generator-dom/templates/entry.js b/packages/react-native-dom/dom/entry.js similarity index 100% rename from packages/react-native-dom/local-cli/generator-dom/templates/entry.js rename to packages/react-native-dom/dom/entry.js diff --git a/packages/react-native-dom/local-cli/generator-dom/templates/index.html b/packages/react-native-dom/dom/index.html similarity index 100% rename from packages/react-native-dom/local-cli/generator-dom/templates/index.html rename to packages/react-native-dom/dom/index.html diff --git a/packages/react-native-dom/generateDom.js b/packages/react-native-dom/generateDom.js new file mode 100644 index 000000000..4131b0f47 --- /dev/null +++ b/packages/react-native-dom/generateDom.js @@ -0,0 +1,2 @@ +module.exports = require("react-native-dom-cli").generateDom; + diff --git a/packages/react-native-dom/index.dom.js b/packages/react-native-dom/index.dom.js new file mode 100644 index 000000000..ea1a04e17 --- /dev/null +++ b/packages/react-native-dom/index.dom.js @@ -0,0 +1,721 @@ +/** + * 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'; + +// Components +import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo'; +import typeof ActivityIndicator from './Libraries/Components/ActivityIndicator/ActivityIndicator'; +import typeof Button from './Libraries/Components/Button'; +import typeof DatePickerIOS from './Libraries/Components/DatePicker/DatePickerIOS'; +import typeof DrawerLayoutAndroid from './Libraries/Components/DrawerAndroid/DrawerLayoutAndroid'; +import typeof FlatList from './Libraries/Lists/FlatList'; +import typeof Image from './Libraries/Image/Image'; +import typeof ImageBackground from './Libraries/Image/ImageBackground'; +import typeof InputAccessoryView from './Libraries/Components/TextInput/InputAccessoryView'; +import typeof KeyboardAvoidingView from './Libraries/Components/Keyboard/KeyboardAvoidingView'; +import typeof MaskedViewIOS from './Libraries/Components/MaskedView/MaskedViewIOS'; +import typeof Modal from './Libraries/Modal/Modal'; +import typeof Picker from './Libraries/Components/Picker/Picker'; +import typeof PickerIOS from './Libraries/Components/Picker/PickerIOS'; +import typeof Pressable from './Libraries/Components/Pressable/Pressable'; +import typeof ProgressBarAndroid from './Libraries/Components/ProgressBarAndroid/ProgressBarAndroid'; +import typeof ProgressViewIOS from './Libraries/Components/ProgressViewIOS/ProgressViewIOS'; +import typeof RefreshControl from './Libraries/Components/RefreshControl/RefreshControl'; +import typeof SafeAreaView from './Libraries/Components/SafeAreaView/SafeAreaView'; +import typeof ScrollView from './Libraries/Components/ScrollView/ScrollView'; +import typeof SectionList from './Libraries/Lists/SectionList'; +import typeof SegmentedControlIOS from './Libraries/Components/SegmentedControlIOS/SegmentedControlIOS'; +import typeof Slider from './Libraries/Components/Slider/Slider'; +import typeof StatusBar from './Libraries/Components/StatusBar/StatusBar'; +import typeof Switch from './Libraries/Components/Switch/Switch'; +import typeof Text from './Libraries/Text/Text'; +import typeof TextInput from './Libraries/Components/TextInput/TextInput'; +import typeof Touchable from './Libraries/Components/Touchable/Touchable'; +import typeof TouchableHighlight from './Libraries/Components/Touchable/TouchableHighlight'; +import typeof TouchableNativeFeedback from './Libraries/Components/Touchable/TouchableNativeFeedback'; +import typeof TouchableOpacity from './Libraries/Components/Touchable/TouchableOpacity'; +import typeof TouchableWithoutFeedback from './Libraries/Components/Touchable/TouchableWithoutFeedback'; +import typeof View from './Libraries/Components/View/View'; +import typeof VirtualizedList from './Libraries/Lists/VirtualizedList'; +import typeof VirtualizedSectionList from './Libraries/Lists/VirtualizedSectionList'; + +// APIs +import typeof ActionSheetIOS from './Libraries/ActionSheetIOS/ActionSheetIOS'; +import typeof Alert from './Libraries/Alert/Alert'; +import typeof Animated from './Libraries/Animated/Animated'; +import typeof Appearance from './Libraries/Utilities/Appearance'; +import typeof AppRegistry from './Libraries/ReactNative/AppRegistry'; +import typeof AppState from './Libraries/AppState/AppState'; +import typeof AsyncStorage from './Libraries/Storage/AsyncStorage'; +import typeof BackHandler from './Libraries/Utilities/BackHandler'; +import typeof Clipboard from './Libraries/Components/Clipboard/Clipboard'; +import typeof DatePickerAndroid from './Libraries/Components/DatePickerAndroid/DatePickerAndroid'; +import typeof DeviceInfo from './Libraries/Utilities/DeviceInfo'; +import typeof DevSettings from './Libraries/Utilities/DevSettings'; +import typeof Dimensions from './Libraries/Utilities/Dimensions'; +import typeof Easing from './Libraries/Animated/Easing'; +import typeof ReactNative from './Libraries/Renderer/shims/ReactNative'; +import typeof I18nManager from './Libraries/ReactNative/I18nManager'; +import typeof ImagePickerIOS from './Libraries/Image/ImagePickerIOS'; +import typeof InteractionManager from './Libraries/Interaction/InteractionManager'; +import typeof Keyboard from './Libraries/Components/Keyboard/Keyboard'; +import typeof LayoutAnimation from './Libraries/LayoutAnimation/LayoutAnimation'; +import typeof Linking from './Libraries/Linking/Linking'; +import typeof LogBox from './Libraries/LogBox/LogBox'; +import typeof NativeDialogManagerAndroid from './Libraries/NativeModules/specs/NativeDialogManagerAndroid'; +import typeof NativeEventEmitter from './Libraries/EventEmitter/NativeEventEmitter'; +import typeof Networking from './Libraries/Network/RCTNetworking'; +import typeof PanResponder from './Libraries/Interaction/PanResponder'; +import typeof PermissionsAndroid from './Libraries/PermissionsAndroid/PermissionsAndroid'; +import typeof PixelRatio from './Libraries/Utilities/PixelRatio'; +import typeof PushNotificationIOS from './Libraries/PushNotificationIOS/PushNotificationIOS'; +import typeof Settings from './Libraries/Settings/Settings'; +import typeof Share from './Libraries/Share/Share'; +import typeof StatusBarIOS from './Libraries/Components/StatusBar/StatusBarIOS'; +import typeof StyleSheet from './Libraries/StyleSheet/StyleSheet'; +import typeof Systrace from './Libraries/Performance/Systrace'; +import typeof ToastAndroid from './Libraries/Components/ToastAndroid/ToastAndroid'; +import typeof * as TurboModuleRegistry from './Libraries/TurboModule/TurboModuleRegistry'; +import typeof UIManager from './Libraries/ReactNative/UIManager'; +import typeof useColorScheme from './Libraries/Utilities/useColorScheme'; +import typeof useWindowDimensions from './Libraries/Utilities/useWindowDimensions'; +import typeof UTFSequence from './Libraries/UTFSequence'; +import typeof Vibration from './Libraries/Vibration/Vibration'; +import typeof YellowBox from './Libraries/YellowBox/YellowBoxDeprecated'; + +// Plugins +import typeof {DynamicColorIOS} from './Libraries/StyleSheet/PlatformColorValueTypesIOS'; +import typeof NativeModules from './Libraries/BatchedBridge/NativeModules'; +import typeof Platform from './Libraries/Utilities/Platform'; +import typeof {PlatformColor} from './Libraries/StyleSheet/PlatformColorValueTypes'; +import typeof processColor from './Libraries/StyleSheet/processColor'; +import typeof RCTDeviceEventEmitter from './Libraries/EventEmitter/RCTDeviceEventEmitter'; +import typeof RCTNativeAppEventEmitter from './Libraries/EventEmitter/RCTNativeAppEventEmitter'; +import typeof {RootTagContext} from './Libraries/ReactNative/RootTag'; + +// Prop Types +import typeof DeprecatedColorPropType from './Libraries/DeprecatedPropTypes/DeprecatedColorPropType'; +import typeof DeprecatedEdgeInsetsPropType from './Libraries/DeprecatedPropTypes/DeprecatedEdgeInsetsPropType'; +import typeof DeprecatedPointPropType from './Libraries/DeprecatedPropTypes/DeprecatedPointPropType'; +import typeof DeprecatedViewPropTypes from './Libraries/DeprecatedPropTypes/DeprecatedViewPropTypes'; + +import type {HostComponent as _HostComponentInternal} from './Libraries/Renderer/shims/ReactNativeTypes'; + +export type HostComponent = _HostComponentInternal; + +const invariant = require('invariant'); +const warnOnce = require('./Libraries/Utilities/warnOnce'); + +module.exports = { + // Components + get AccessibilityInfo(): AccessibilityInfo { + return require('./Libraries/Components/AccessibilityInfo/AccessibilityInfo'); + }, + get ActivityIndicator(): ActivityIndicator { + return require('./Libraries/Components/ActivityIndicator/ActivityIndicator'); + }, + get Button(): Button { + return require('./Libraries/Components/Button'); + }, + // $FlowFixMe[value-as-type] + get DatePickerIOS(): DatePickerIOS { + warnOnce( + 'DatePickerIOS-merged', + 'DatePickerIOS has been merged with DatePickerAndroid and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + + 'See https://github.com/react-native-community/datetimepicker', + ); + return require('./Libraries/Components/DatePicker/DatePickerIOS'); + }, + // $FlowFixMe[value-as-type] + get DrawerLayoutAndroid(): DrawerLayoutAndroid { + return require('./Libraries/Components/DrawerAndroid/DrawerLayoutAndroid'); + }, + get FlatList(): FlatList { + return require('./Libraries/Lists/FlatList'); + }, + get Image(): Image { + return require('./Libraries/Image/Image'); + }, + get ImageBackground(): ImageBackground { + return require('./Libraries/Image/ImageBackground'); + }, + get InputAccessoryView(): InputAccessoryView { + return require('./Libraries/Components/TextInput/InputAccessoryView'); + }, + get KeyboardAvoidingView(): KeyboardAvoidingView { + return require('./Libraries/Components/Keyboard/KeyboardAvoidingView'); + }, + get MaskedViewIOS(): MaskedViewIOS { + warnOnce( + 'maskedviewios-moved', + 'MaskedViewIOS has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/masked-view' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-masked-view', + ); + return require('./Libraries/Components/MaskedView/MaskedViewIOS'); + }, + get Modal(): Modal { + return require('./Libraries/Modal/Modal'); + }, + get Picker(): Picker { + warnOnce( + 'picker-moved', + 'Picker has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/picker' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-picker', + ); + return require('./Libraries/Components/Picker/Picker'); + }, + // $FlowFixMe[value-as-type] + get PickerIOS(): PickerIOS { + warnOnce( + 'pickerios-moved', + 'PickerIOS has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/picker' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-picker', + ); + return require('./Libraries/Components/Picker/PickerIOS'); + }, + get Pressable(): Pressable { + return require('./Libraries/Components/Pressable/Pressable').default; + }, + // $FlowFixMe[value-as-type] + get ProgressBarAndroid(): ProgressBarAndroid { + warnOnce( + 'progress-bar-android-moved', + 'ProgressBarAndroid has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/progress-bar-android' instead of 'react-native'. " + + 'See https://github.com/react-native-community/progress-bar-android', + ); + return require('./Libraries/Components/ProgressBarAndroid/ProgressBarAndroid'); + }, + // $FlowFixMe[value-as-type] + get ProgressViewIOS(): ProgressViewIOS { + warnOnce( + 'progress-view-ios-moved', + 'ProgressViewIOS has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/progress-view' instead of 'react-native'. " + + 'See https://github.com/react-native-community/progress-view', + ); + return require('./Libraries/Components/ProgressViewIOS/ProgressViewIOS'); + }, + get RefreshControl(): RefreshControl { + return require('./Libraries/Components/RefreshControl/RefreshControl'); + }, + get SafeAreaView(): SafeAreaView { + return require('./Libraries/Components/SafeAreaView/SafeAreaView'); + }, + get ScrollView(): ScrollView { + return require('./Libraries/Components/ScrollView/ScrollView'); + }, + get SectionList(): SectionList { + return require('./Libraries/Lists/SectionList'); + }, + // $FlowFixMe[value-as-type] + get SegmentedControlIOS(): SegmentedControlIOS { + warnOnce( + 'segmented-control-ios-moved', + 'SegmentedControlIOS has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/segmented-control' instead of 'react-native'. " + + 'See https://github.com/react-native-community/segmented-control', + ); + return require('./Libraries/Components/SegmentedControlIOS/SegmentedControlIOS'); + }, + get Slider(): Slider { + warnOnce( + 'slider-moved', + 'Slider has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/slider' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-slider', + ); + return require('./Libraries/Components/Slider/Slider'); + }, + get StatusBar(): StatusBar { + return require('./Libraries/Components/StatusBar/StatusBar'); + }, + get Switch(): Switch { + return require('./Libraries/Components/Switch/Switch'); + }, + get Text(): Text { + return require('./Libraries/Text/Text'); + }, + get TextInput(): TextInput { + return require('./Libraries/Components/TextInput/TextInput'); + }, + get Touchable(): Touchable { + return require('./Libraries/Components/Touchable/Touchable'); + }, + get TouchableHighlight(): TouchableHighlight { + return require('./Libraries/Components/Touchable/TouchableHighlight'); + }, + get TouchableNativeFeedback(): TouchableNativeFeedback { + return require('./Libraries/Components/Touchable/TouchableNativeFeedback'); + }, + get TouchableOpacity(): TouchableOpacity { + return require('./Libraries/Components/Touchable/TouchableOpacity'); + }, + get TouchableWithoutFeedback(): TouchableWithoutFeedback { + return require('./Libraries/Components/Touchable/TouchableWithoutFeedback'); + }, + get View(): View { + return require('./Libraries/Components/View/View'); + }, + get VirtualizedList(): VirtualizedList { + return require('./Libraries/Lists/VirtualizedList'); + }, + get VirtualizedSectionList(): VirtualizedSectionList { + return require('./Libraries/Lists/VirtualizedSectionList'); + }, + + // APIs + get ActionSheetIOS(): ActionSheetIOS { + return require('./Libraries/ActionSheetIOS/ActionSheetIOS'); + }, + get Alert(): Alert { + return require('./Libraries/Alert/Alert'); + }, + get Animated(): Animated { + return require('./Libraries/Animated/Animated'); + }, + get Appearance(): Appearance { + return require('./Libraries/Utilities/Appearance'); + }, + get AppRegistry(): AppRegistry { + return require('./Libraries/ReactNative/AppRegistry'); + }, + get AppState(): AppState { + return require('./Libraries/AppState/AppState'); + }, + // $FlowFixMe[value-as-type] + get AsyncStorage(): AsyncStorage { + warnOnce( + 'async-storage-moved', + 'AsyncStorage has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/async-storage' instead of 'react-native'. " + + 'See https://github.com/react-native-community/async-storage', + ); + return require('./Libraries/Storage/AsyncStorage'); + }, + get BackHandler(): BackHandler { + return require('./Libraries/Utilities/BackHandler'); + }, + get Clipboard(): Clipboard { + warnOnce( + 'clipboard-moved', + 'Clipboard has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/clipboard' instead of 'react-native'. " + + 'See https://github.com/react-native-community/clipboard', + ); + return require('./Libraries/Components/Clipboard/Clipboard'); + }, + // $FlowFixMe[value-as-type] + get DatePickerAndroid(): DatePickerAndroid { + warnOnce( + 'DatePickerAndroid-merged', + 'DatePickerAndroid has been merged with DatePickerIOS and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + + 'See https://github.com/react-native-community/datetimepicker', + ); + return require('./Libraries/Components/DatePickerAndroid/DatePickerAndroid'); + }, + get DeviceInfo(): DeviceInfo { + return require('./Libraries/Utilities/DeviceInfo'); + }, + get DevSettings(): DevSettings { + return require('./Libraries/Utilities/DevSettings'); + }, + get Dimensions(): Dimensions { + return require('./Libraries/Utilities/Dimensions'); + }, + get Easing(): Easing { + return require('./Libraries/Animated/Easing'); + }, + get findNodeHandle(): $PropertyType { + return require('./Libraries/Renderer/shims/ReactNative').findNodeHandle; + }, + get I18nManager(): I18nManager { + return require('./Libraries/ReactNative/I18nManager'); + }, + get ImagePickerIOS(): ImagePickerIOS { + warnOnce( + 'imagePickerIOS-moved', + 'ImagePickerIOS has been extracted from react-native core and will be removed in a future release. ' + + "Please upgrade to use either '@react-native-community/react-native-image-picker' or 'expo-image-picker'. " + + "If you cannot upgrade to a different library, please install the deprecated '@react-native-community/image-picker-ios' package. " + + 'See https://github.com/react-native-community/react-native-image-picker-ios', + ); + return require('./Libraries/Image/ImagePickerIOS'); + }, + get InteractionManager(): InteractionManager { + return require('./Libraries/Interaction/InteractionManager'); + }, + get Keyboard(): Keyboard { + return require('./Libraries/Components/Keyboard/Keyboard'); + }, + get LayoutAnimation(): LayoutAnimation { + return require('./Libraries/LayoutAnimation/LayoutAnimation'); + }, + get Linking(): Linking { + return require('./Libraries/Linking/Linking'); + }, + get LogBox(): LogBox { + return require('./Libraries/LogBox/LogBox'); + }, + get NativeDialogManagerAndroid(): NativeDialogManagerAndroid { + return require('./Libraries/NativeModules/specs/NativeDialogManagerAndroid') + .default; + }, + get NativeEventEmitter(): NativeEventEmitter { + return require('./Libraries/EventEmitter/NativeEventEmitter').default; + }, + // $FlowFixMe[value-as-type] + get Networking(): Networking { + return require('./Libraries/Network/RCTNetworking'); + }, + get PanResponder(): PanResponder { + return require('./Libraries/Interaction/PanResponder'); + }, + get PermissionsAndroid(): PermissionsAndroid { + return require('./Libraries/PermissionsAndroid/PermissionsAndroid'); + }, + get PixelRatio(): PixelRatio { + return require('./Libraries/Utilities/PixelRatio'); + }, + get PushNotificationIOS(): PushNotificationIOS { + warnOnce( + 'pushNotificationIOS-moved', + 'PushNotificationIOS has been extracted from react-native core and will be removed in a future release. ' + + "It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. " + + 'See https://github.com/react-native-community/push-notification-ios', + ); + return require('./Libraries/PushNotificationIOS/PushNotificationIOS'); + }, + // $FlowFixMe[value-as-type] + get Settings(): Settings { + return require('./Libraries/Settings/Settings'); + }, + get Share(): Share { + return require('./Libraries/Share/Share'); + }, + get StatusBarIOS(): StatusBarIOS { + warnOnce( + 'StatusBarIOS-merged', + 'StatusBarIOS has been merged with StatusBar and will be removed in a future release. Use StatusBar for mutating the status bar', + ); + return require('./Libraries/Components/StatusBar/StatusBarIOS'); + }, + get StyleSheet(): StyleSheet { + return require('./Libraries/StyleSheet/StyleSheet'); + }, + get Systrace(): Systrace { + return require('./Libraries/Performance/Systrace'); + }, + // $FlowFixMe[value-as-type] + get ToastAndroid(): ToastAndroid { + return require('./Libraries/Components/ToastAndroid/ToastAndroid'); + }, + get TurboModuleRegistry(): TurboModuleRegistry { + return require('./Libraries/TurboModule/TurboModuleRegistry'); + }, + get UIManager(): UIManager { + return require('./Libraries/ReactNative/UIManager'); + }, + get unstable_batchedUpdates(): $PropertyType< + ReactNative, + 'unstable_batchedUpdates', + > { + return require('./Libraries/Renderer/shims/ReactNative') + .unstable_batchedUpdates; + }, + get useColorScheme(): useColorScheme { + return require('./Libraries/Utilities/useColorScheme').default; + }, + get useWindowDimensions(): useWindowDimensions { + return require('./Libraries/Utilities/useWindowDimensions').default; + }, + get UTFSequence(): UTFSequence { + return require('./Libraries/UTFSequence'); + }, + get Vibration(): Vibration { + return require('./Libraries/Vibration/Vibration'); + }, + get YellowBox(): YellowBox { + return require('./Libraries/YellowBox/YellowBoxDeprecated'); + }, + + // Plugins + get DeviceEventEmitter(): RCTDeviceEventEmitter { + return require('./Libraries/EventEmitter/RCTDeviceEventEmitter').default; + }, + get DynamicColorIOS(): DynamicColorIOS { + return require('./Libraries/StyleSheet/PlatformColorValueTypesIOS') + .DynamicColorIOS; + }, + get NativeAppEventEmitter(): RCTNativeAppEventEmitter { + return require('./Libraries/EventEmitter/RCTNativeAppEventEmitter'); + }, + get NativeModules(): NativeModules { + return require('./Libraries/BatchedBridge/NativeModules'); + }, + get Platform(): Platform { + return require('./Libraries/Utilities/Platform'); + }, + get PlatformColor(): PlatformColor { + return require('./Libraries/StyleSheet/PlatformColorValueTypes') + .PlatformColor; + }, + get processColor(): processColor { + return require('./Libraries/StyleSheet/processColor'); + }, + get requireNativeComponent(): ( + uiViewClassName: string, + ) => HostComponent { + return require('./Libraries/ReactNative/requireNativeComponent'); + }, + get unstable_RootTagContext(): RootTagContext { + return require('./Libraries/ReactNative/RootTag').RootTagContext; + }, + get unstable_enableLogBox(): () => void { + return () => + console.warn( + 'LogBox is enabled by default so there is no need to call unstable_enableLogBox() anymore. This is a no op and will be removed in the next version.', + ); + }, + // Prop Types + // $FlowFixMe[value-as-type] + get ColorPropType(): DeprecatedColorPropType { + return require('./Libraries/DeprecatedPropTypes/DeprecatedColorPropType'); + }, + // $FlowFixMe[value-as-type] + get EdgeInsetsPropType(): DeprecatedEdgeInsetsPropType { + return require('./Libraries/DeprecatedPropTypes/DeprecatedEdgeInsetsPropType'); + }, + // $FlowFixMe[value-as-type] + get PointPropType(): DeprecatedPointPropType { + return require('./Libraries/DeprecatedPropTypes/DeprecatedPointPropType'); + }, + // $FlowFixMe[value-as-type] + get ViewPropTypes(): DeprecatedViewPropTypes { + return require('./Libraries/DeprecatedPropTypes/DeprecatedViewPropTypes'); + }, + + // Additional windows exports (Typescript components exported as flow any) + get DatePicker(): any { + warnOnce( + 'datepicker-moved', + 'DatePicker has been extracted from react-native-windows and will be removed in a future release. ' + + "It can now be installed and imported as DateTimePicker from '@react-native-community/datetimepicker'. " + + 'See https://github.com/react-native-datetimepicker/datetimepicker', + ); + return (require('./Libraries/Components/DatePicker/DatePicker'): any) + .DatePicker; + }, + get Flyout(): any { + return require('./Libraries/Components/Flyout/Flyout').Flyout; + }, + get Glyph(): any { + return require('./Libraries/Components/Glyph/Glyph').Glyph; + }, + get PickerWindows(): any { + warnOnce( + 'picker-windows-moved', + 'PickerWindows has been extracted from react-native-windows and will be removed in a future release. ' + + "It can now be installed and imported as Picker from '@react-native-picker/picker'. " + + 'See https://github.com/react-native-picker/picker', + ); + return require('./Libraries/Components/Picker/PickerWindows').Picker; + }, + get Popup(): any { + return require('./Libraries/Components/Popup/Popup').Popup; + }, + get supportKeyboard(): any { + return require('./Libraries/Components/Keyboard/KeyboardExt') + .supportKeyboard; + }, + get DayOfWeek(): any { + return require('./Libraries/Components/DatePicker/DatePickerProps') + .DayOfWeek; + }, + get EventPhase(): any { + return require('./Libraries/Components/Keyboard/KeyboardExtProps') + .HandledEventPhase; + }, + get HandledEventPhase(): any { + return require('./Libraries/Components/Keyboard/KeyboardExtProps') + .HandledEventPhase; + }, + get ViewWindows(): any { + return require('./Libraries/Components/View/ViewWindows').ViewWindows; + }, + get AppTheme(): any { + return require('./Libraries/AppTheme/AppTheme').AppTheme; + }, +}; + +if (__DEV__) { + // $FlowFixMe This is intentional: Flow will error when attempting to access ART. + Object.defineProperty(module.exports, 'ART', { + configurable: true, + get() { + invariant( + false, + 'ART has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/art' instead of 'react-native'. " + + 'See https://github.com/react-native-community/art', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access ListView. + Object.defineProperty(module.exports, 'ListView', { + configurable: true, + get() { + invariant( + false, + 'ListView has been removed from React Native. ' + + 'See https://fb.me/nolistview for more information or use ' + + '`deprecated-react-native-listview`.', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access SwipeableListView. + Object.defineProperty(module.exports, 'SwipeableListView', { + configurable: true, + get() { + invariant( + false, + 'SwipeableListView has been removed from React Native. ' + + 'See https://fb.me/nolistview for more information or use ' + + '`deprecated-react-native-swipeable-listview`.', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access WebView. + Object.defineProperty(module.exports, 'WebView', { + configurable: true, + get() { + invariant( + false, + 'WebView has been removed from React Native. ' + + "It can now be installed and imported from 'react-native-webview' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-webview', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access NetInfo. + Object.defineProperty(module.exports, 'NetInfo', { + configurable: true, + get() { + invariant( + false, + 'NetInfo has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/netinfo' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-netinfo', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access CameraRoll. + Object.defineProperty(module.exports, 'CameraRoll', { + configurable: true, + get() { + invariant( + false, + 'CameraRoll has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/cameraroll' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-cameraroll', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access ImageStore. + Object.defineProperty(module.exports, 'ImageStore', { + configurable: true, + get() { + invariant( + false, + 'ImageStore has been removed from React Native. ' + + 'To get a base64-encoded string from a local image use either of the following third-party libraries:' + + "* expo-file-system: `readAsStringAsync(filepath, 'base64')`" + + "* react-native-fs: `readFile(filepath, 'base64')`", + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access ImageEditor. + Object.defineProperty(module.exports, 'ImageEditor', { + configurable: true, + get() { + invariant( + false, + 'ImageEditor has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/image-editor' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-image-editor', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access TimePickerAndroid. + Object.defineProperty(module.exports, 'TimePickerAndroid', { + configurable: true, + get() { + invariant( + false, + 'TimePickerAndroid has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + + 'See https://github.com/react-native-community/datetimepicker', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access ToolbarAndroid. + Object.defineProperty(module.exports, 'ToolbarAndroid', { + configurable: true, + get() { + invariant( + false, + 'ToolbarAndroid has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/toolbar-android' instead of 'react-native'. " + + 'See https://github.com/react-native-community/toolbar-android', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access ViewPagerAndroid. + Object.defineProperty(module.exports, 'ViewPagerAndroid', { + configurable: true, + get() { + invariant( + false, + 'ViewPagerAndroid has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/viewpager' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-viewpager', + ); + }, + }); + + // $FlowFixMe This is intentional: Flow will error when attempting to access CheckBox. + Object.defineProperty(module.exports, 'CheckBox', { + configurable: true, + get() { + invariant( + false, + 'CheckBox has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/checkbox' instead of 'react-native'. " + + 'See https://github.com/react-native-community/react-native-checkbox', + ); + }, + }); +} diff --git a/packages/react-native-dom/just-task.js b/packages/react-native-dom/just-task.js new file mode 100644 index 000000000..952f3cadc --- /dev/null +++ b/packages/react-native-dom/just-task.js @@ -0,0 +1,57 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + * @ts-check + */ + +const path = require('path'); +const { + task, + series, + condition, + option, + argv, + eslintTask, +} = require('just-scripts'); +const {execSync} = require('child_process'); +const fs = require('fs'); +const copyRNLibaries = require('./scripts/copyRNLibraries'); + +option('production'); +option('clean'); + +task('flow-check', () => { + require('child_process').execSync('npx flow check', {stdio: 'inherit'}); +}); + +task('eslint', eslintTask()); +task('eslint:fix', eslintTask({fix: true})); + +task('copyRNLibraries', copyRNLibaries.copyTask(__dirname)); + +task('copyReadmeAndLicenseFromRoot', () => { + fs.copyFileSync( + path.resolve(__dirname, '../README.md'), + path.resolve(__dirname, 'README.md'), + ); + fs.copyFileSync( + path.resolve(__dirname, '../LICENSE'), + path.resolve(__dirname, 'LICENSE'), + ); +}); + +task('cleanRnLibraries', copyRNLibaries.cleanTask(__dirname)); + +task( + 'build', + series( + condition('clean', () => argv().clean), + 'copyRNLibraries' + ), +); + +task('clean', series('cleanRnLibraries')); + +task('lint', series('eslint', 'flow-check')); +task('lint:fix', series('eslint:fix')); \ No newline at end of file diff --git a/packages/react-native-dom/local-cli/.npmignore b/packages/react-native-dom/local-cli/.npmignore deleted file mode 100644 index c6210087a..000000000 --- a/packages/react-native-dom/local-cli/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -# make sure rnpm folder is not published -rnpm/ \ No newline at end of file diff --git a/packages/react-native-dom/local-cli/constants.js b/packages/react-native-dom/local-cli/constants.js deleted file mode 100644 index 8542b9523..000000000 --- a/packages/react-native-dom/local-cli/constants.js +++ /dev/null @@ -1,2 +0,0 @@ -exports.NATIVE_MODULE_IDENT = "RN_DOM_VENDOR_NATIVE_MODULES"; -exports.RN_MAIN_PJSON_NAME = "rn:main"; diff --git a/packages/react-native-dom/local-cli/core/dom/findDepConfigPath.js b/packages/react-native-dom/local-cli/core/dom/findDepConfigPath.js deleted file mode 100644 index 3f7f7ce48..000000000 --- a/packages/react-native-dom/local-cli/core/dom/findDepConfigPath.js +++ /dev/null @@ -1,36 +0,0 @@ -const fs = require("fs"); -const glob = require("glob"); -const path = require("path"); - -const DEP_CONFIG_FILENAME = "domDependencyConfig.json"; - -module.exports = function findDependencyConfigPath(folder) { - const depConfigPaths = glob.sync(path.join("**", DEP_CONFIG_FILENAME), { - cwd: folder, - ignore: [ - "node_modules/**", - "**/build/**", - "Examples/**", - "examples/**", - "**/bin/**", - "**/obj/**", - "**/dist/**" - ] - }); - - if (depConfigPaths.length === 0) { - throw new Error( - `Could not find ${DEP_CONFIG_FILENAME} in your project, please add it.` - ); - } - - if (depConfigPaths.length > 1) { - throw new Error( - `Multiple ${DEP_CONFIG_FILENAME} files found: [${depConfigPaths.join( - ", " - )}]` - ); - } - - return path.join(folder, depConfigPaths[0]); -}; diff --git a/packages/react-native-dom/local-cli/core/dom/findVendorModulePath.js b/packages/react-native-dom/local-cli/core/dom/findVendorModulePath.js deleted file mode 100644 index f9ced11b9..000000000 --- a/packages/react-native-dom/local-cli/core/dom/findVendorModulePath.js +++ /dev/null @@ -1,28 +0,0 @@ -const fs = require("fs"); -const glob = require("glob"); -const path = require("path"); - -const { NATIVE_MODULE_IDENT } = require("../../constants"); - -module.exports = function findVendorModulePath(folder) { - const jsPaths = glob.sync(path.join("**", "*.js"), { - cwd: folder, - ignore: [ - "node_modules/**", - "**/build/**", - "Examples/**", - "examples/**", - "**/bin/**", - "**/obj/**", - "**/dist/**" - ] - }); - - // Search for file that contains usage of `new RNDomInstance` - for (var filePath of jsPaths) { - const file = fs.readFileSync(path.join(folder, filePath), "utf8"); - if (file.includes(NATIVE_MODULE_IDENT)) { - return path.join(folder, filePath); - } - } -}; diff --git a/packages/react-native-dom/local-cli/core/dom/getDomRequirePath.js b/packages/react-native-dom/local-cli/core/dom/getDomRequirePath.js deleted file mode 100644 index 8184665e0..000000000 --- a/packages/react-native-dom/local-cli/core/dom/getDomRequirePath.js +++ /dev/null @@ -1,34 +0,0 @@ -const path = require("path"); -const fs = require("fs"); -const glob = require("glob"); - -const { RN_MAIN_PJSON_NAME } = require("../../constants"); - -module.exports = function getDomRequirePath(folder) { - const packageName = path.basename(folder); - - const pJsons = glob.sync(path.join("**", "package.json"), { - cwd: folder, - ignore: ["node_modules/**", "ios/**", "android/**"] - }); - - for (pJsonPath of pJsons) { - const fullPath = path.join(folder, pJsonPath); - const pJson = JSON.parse(fs.readFileSync(fullPath, "utf8")); - - if (pJson.hasOwnProperty(RN_MAIN_PJSON_NAME)) { - return path.join(packageName, path.dirname(pJsonPath)); - } - } - - const defaultDomLocation = path.join(packageName, "dom"); - - try { - require.resolve(defaultDomLocation); - return defaultDomLocation; - } catch (err) { - /* NO OP */ - } - - return null; -}; diff --git a/packages/react-native-dom/local-cli/core/dom/index.js b/packages/react-native-dom/local-cli/core/dom/index.js deleted file mode 100644 index 3a76e8bb1..000000000 --- a/packages/react-native-dom/local-cli/core/dom/index.js +++ /dev/null @@ -1,29 +0,0 @@ -const path = require("path"); - -const findDependencyConfigPath = require("./findDepConfigPath"); -const findVendorModulePath = require("./findVendorModulePath"); -const getDomRequirePath = require("./getDomRequirePath"); - -exports.projectConfig = function projectConfigDom(folder, userConfig) { - const depConfigPath = - userConfig.depConfigPath || findDependencyConfigPath(folder); - - const vendorModulePath = - userConfig.bootstrapPath || findVendorModulePath(folder); - - const nodeModulesFolder = path.join(folder, "node_modules"); - - return { - depConfigPath, - vendorModulePath, - nodeModulesFolder - }; -}; - -exports.dependencyConfig = function dependencyConfigDom(folder, userConfig) { - const requirePath = getDomRequirePath(folder); - - if (requirePath == null) return null; - - return { requirePath: requirePath }; -}; diff --git a/packages/react-native-dom/local-cli/generate-dom.js b/packages/react-native-dom/local-cli/generate-dom.js deleted file mode 100644 index bb09687ee..000000000 --- a/packages/react-native-dom/local-cli/generate-dom.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; - -const fs = require("fs"); -const path = require("path"); -const yeoman = require("yeoman-environment"); - -function generateDom(projectDir, name, verbose) { - const oldCwd = process.cwd(); - - if (!fs.existsSync(projectDir)) { - fs.mkdirSync(projectDir); - } - - const env = yeoman.createEnv(); - const generatorPath = path.join(__dirname, "generator-dom"); - env.register(generatorPath, "react:dom"); - const args = ["react:dom", name].concat(process.argv.slice(4)); - env.run(args, { verbose: verbose }, function() { - process.chdir(oldCwd); - }); -} - -module.exports = generateDom; diff --git a/packages/react-native-dom/local-cli/generator-dom/index.js b/packages/react-native-dom/local-cli/generator-dom/index.js deleted file mode 100644 index ef10150ce..000000000 --- a/packages/react-native-dom/local-cli/generator-dom/index.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; - -const path = require("path"); -const fs = require("fs"); -const Generator = require("yeoman-generator"); - -const utils = require("../generator-utils"); - -const REACT_NATIVE_PACKAGE_JSON_PATH = () => { - return path.resolve( - process.cwd(), - "node_modules", - "react-native", - "package.json" - ); -}; - -module.exports = class extends Generator { - constructor(args, opts) { - super(args, opts); - - this.argument("name", { type: String, required: true }); - - this.option("verbose", { - desc: "Enables logging", - type: Boolean, - defaults: false - }); - } - - configuring() { - this.fs.copy( - this.templatePath("_gitignore"), - this.destinationPath(path.join("dom", ".gitignore")) - ); - } - - writting() { - const templateVars = { name: this.name }; - - this.fs.copyTpl( - this.templatePath("bootstrap.js"), - this.destinationPath(path.join("dom", "bootstrap.js")), - templateVars - ); - - this.fs.copyTpl( - this.templatePath("entry.js"), - this.destinationPath(path.join("dom", "entry.js")), - templateVars - ); - - this.fs.copyTpl( - this.templatePath("index.html"), - this.destinationPath(path.join("dom", "index.html")), - templateVars - ); - } - - end() { - this.log("To run your app on the browser:"); - this.log(" react-native run-dom"); - } -}; diff --git a/packages/react-native-dom/local-cli/generator-dom/templates/App.dom.js b/packages/react-native-dom/local-cli/generator-dom/templates/App.dom.js deleted file mode 100644 index 65920ac2e..000000000 --- a/packages/react-native-dom/local-cli/generator-dom/templates/App.dom.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Sample React Native App - * https://github.com/facebook/react-native - * @flow - */ - -import React, { Component } from "react"; -import { Platform, StyleSheet, Text, View } from "react-native"; - -const instructions = "Press Ctrl/Cmd+R to reload,\n" + "Shift+F10 for dev menu"; - -export default class App extends Component<{}> { - render() { - return ( - - Welcome to React Native! - To get started, edit App.dom.js - {instructions} - - ); - } -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: "center", - alignItems: "center", - backgroundColor: "#F5FCFF" - }, - welcome: { - fontSize: 20, - textAlign: "center", - margin: 10 - }, - instructions: { - textAlign: "center", - color: "#333333", - marginBottom: 5 - } -}); diff --git a/packages/react-native-dom/local-cli/generator-dom/templates/_gitignore b/packages/react-native-dom/local-cli/generator-dom/templates/_gitignore deleted file mode 100644 index ec7386c1a..000000000 --- a/packages/react-native-dom/local-cli/generator-dom/templates/_gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# react-native-dom build artifacts -dist \ No newline at end of file diff --git a/packages/react-native-dom/local-cli/generator-utils.js b/packages/react-native-dom/local-cli/generator-utils.js deleted file mode 100644 index a1d7b8bf5..000000000 --- a/packages/react-native-dom/local-cli/generator-utils.js +++ /dev/null @@ -1,52 +0,0 @@ -"use-strict"; - -const path = require("path"); -const fs = require("fs"); - -function validatePackageName(name) { - if (!name.match(/^[$A-Z_][0-9A-Z_$]*$/i)) { - console.error( - '"%s" is not a valid name for a project. Please use a valid identifier ' + - "name (alphanumeric).", - name - ); - process.exit(1); - } -} - -function getPackageJson() { - const packagePath = path.resolve(process.cwd(), "package.json"); - - if (!fs.existsSync(packagePath)) { - console.error("package.json file could not be found in %s", process.cwd()); - process.exit(1); - } - - let pkg; - try { - pkg = JSON.parse(fs.readFileSync(packagePath, "utf8")); - } catch (err) { - console.error("Could not parse project package.json"); - console.error(err.message); - process.exit(1); - } - - return pkg; -} - -function getExistingProjectName() { - const pkg = getPackageJson(); - - if (pkg.name == null) { - console.error("project does not have a name in its package.json"); - process.exit(1); - } - - return pkg.name; -} - -module.exports = { - validatePackageName: validatePackageName, - getPackageJson: getPackageJson, - getExistingProjectName: getExistingProjectName -}; diff --git a/packages/react-native-dom/local-cli/index.js b/packages/react-native-dom/local-cli/index.js deleted file mode 100644 index b4b812c17..000000000 --- a/packages/react-native-dom/local-cli/index.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; - -module.exports = [require("./runDom/runDom")]; diff --git a/packages/react-native-dom/local-cli/link/dom/getDependencyConfig.js b/packages/react-native-dom/local-cli/link/dom/getDependencyConfig.js deleted file mode 100644 index 2004a6869..000000000 --- a/packages/react-native-dom/local-cli/link/dom/getDependencyConfig.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require("fs"); - -module.exports = function getDependencyConfig(depConfigPath) { - const rawConfig = fs.readFileSync(depConfigPath, "utf8"); - return JSON.parse(rawConfig); -}; diff --git a/packages/react-native-dom/local-cli/link/dom/isInstalled.js b/packages/react-native-dom/local-cli/link/dom/isInstalled.js deleted file mode 100644 index 069323487..000000000 --- a/packages/react-native-dom/local-cli/link/dom/isInstalled.js +++ /dev/null @@ -1,22 +0,0 @@ -const fs = require("fs"); -const path = require("path"); - -const getDependencyConfig = require("./getDependencyConfig"); - -function isDependencyIncluded(requirePath, vendorModulePath) { - const vendorModuleContents = fs.readFileSync(vendorModulePath, "utf8"); - return vendorModuleContents.includes(requirePath); -} - -module.exports = function isInstalled(config, dependencyConfig) { - const { depConfigPath, vendorModulePath } = config; - - const depConfig = getDependencyConfig(depConfigPath); - - if (depConfig.hasOwnProperty(dependencyConfig)) { - const requirePath = depConfig[dependencyConfig]; - return isDependencyIncluded(requirePath, vendorModulePath); - } - - return false; -}; diff --git a/packages/react-native-dom/local-cli/link/dom/registerNativeModule.js b/packages/react-native-dom/local-cli/link/dom/registerNativeModule.js deleted file mode 100644 index a0b167fe4..000000000 --- a/packages/react-native-dom/local-cli/link/dom/registerNativeModule.js +++ /dev/null @@ -1,26 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const glob = require("glob"); - -const getDependencyConfig = require("./getDependencyConfig"); -const updateDependencyConfig = require("./updateDependencyConfig"); -const updateVendorModule = require("./updateVendorModuleFile"); - -module.exports = function registerNativeDomModule( - name, - domConfig, - params, - projectConfig -) { - if (!name.startsWith("react-native") || name === "react-native-dom") return; - - const requirePath = domConfig.requirePath; - - // Add to domDependencyConfig.json - const depConfig = getDependencyConfig(projectConfig.depConfigPath); - depConfig[name] = requirePath; - updateDependencyConfig(depConfig, projectConfig.depConfigPath); - - // Re-generate vendor module file - updateVendorModule(depConfig, projectConfig.vendorModulePath); -}; diff --git a/packages/react-native-dom/local-cli/link/dom/unregisterNativeModule.js b/packages/react-native-dom/local-cli/link/dom/unregisterNativeModule.js deleted file mode 100644 index 3e5aeeb58..000000000 --- a/packages/react-native-dom/local-cli/link/dom/unregisterNativeModule.js +++ /dev/null @@ -1,15 +0,0 @@ -const getDependencyConfig = require("./getDependencyConfig"); -const updateVendorModule = require("./updateVendorModuleFile"); -const updateDependencyConfig = require("./updateDependencyConfig"); - -module.exports = function unregisterNativeDomModule( - name, - domConfig, - projectConfig -) { - const depConfig = getDependencyConfig(projectConfig.depConfigPath); - delete depConfig[name]; - - updateDependencyConfig(depConfig, projectConfig.depConfigPath); - updateVendorModule(depConfig, projectConfig.vendorModulePath); -}; diff --git a/packages/react-native-dom/local-cli/link/dom/updateDependencyConfig.js b/packages/react-native-dom/local-cli/link/dom/updateDependencyConfig.js deleted file mode 100644 index c32aebad1..000000000 --- a/packages/react-native-dom/local-cli/link/dom/updateDependencyConfig.js +++ /dev/null @@ -1,5 +0,0 @@ -const fs = require("fs"); - -module.exports = function updateDependencyConfig(config, path) { - fs.writeFileSync(path, JSON.stringify(config, null, " ")); -}; diff --git a/packages/react-native-dom/local-cli/link/dom/updateVendorModuleFile.js b/packages/react-native-dom/local-cli/link/dom/updateVendorModuleFile.js deleted file mode 100644 index 514eb0f14..000000000 --- a/packages/react-native-dom/local-cli/link/dom/updateVendorModuleFile.js +++ /dev/null @@ -1,39 +0,0 @@ -const fs = require("fs"); -const template = require("@babel/template").default; -const generate = require("@babel/generator").default; -const t = require("@babel/types"); - -const { NATIVE_MODULE_IDENT } = require("../../constants"); - -const buildModule = template( - ` -const ${NATIVE_MODULE_IDENT} = SOURCE_ARRAY; -export default ${NATIVE_MODULE_IDENT}; -`, - { - placeholderPattern: /^SOURCE_ARRAY$/ - } -); - -function buildSourceArray(dependencyConfig) { - const elements = []; - for (let depName in dependencyConfig) { - const requirePath = dependencyConfig[depName]; - elements.push(template.expression(`require("${requirePath}")`)()); - } - return t.arrayExpression(elements); -} - -module.exports = function updateVendorModule( - dependencyConfig, - vendorModulePath -) { - const sourceArray = buildSourceArray(dependencyConfig); - - const ast = buildModule({ - SOURCE_ARRAY: sourceArray - }); - const code = generate(t.program(ast)).code; - - fs.writeFileSync(vendorModulePath, code); -}; diff --git a/packages/react-native-dom/local-cli/link/index.js b/packages/react-native-dom/local-cli/link/index.js deleted file mode 100644 index b1ca7c07a..000000000 --- a/packages/react-native-dom/local-cli/link/index.js +++ /dev/null @@ -1,7 +0,0 @@ -exports.linkConfig = function() { - return { - isInstalled: require("./dom/isInstalled"), - register: require("./dom/registerNativeModule"), - unregister: require("./dom/unregisterNativeModule") - }; -}; diff --git a/packages/react-native-dom/local-cli/platform.js b/packages/react-native-dom/local-cli/platform.js deleted file mode 100644 index 1d91070b9..000000000 --- a/packages/react-native-dom/local-cli/platform.js +++ /dev/null @@ -1,6 +0,0 @@ -let config = {}; - -Object.assign(config, require("./core/dom")); -Object.assign(config, require("./link")); - -module.exports = { dom: config }; diff --git a/packages/react-native-dom/local-cli/runDom/runDom.js b/packages/react-native-dom/local-cli/runDom/runDom.js deleted file mode 100644 index 6223978fa..000000000 --- a/packages/react-native-dom/local-cli/runDom/runDom.js +++ /dev/null @@ -1,120 +0,0 @@ -"use strict"; - -const child_process = require("child_process"); -const spawn = child_process.spawn, - execSync = child_process.execSync; -const fs = require("fs"); -const http = require("http"); -const path = require("path"); -const opn = require("opn"); -const fetch = require("node-fetch"); -const waitPort = require("wait-port"); - -/** - * Indicates whether or not the packager is running. It returns a promise that - * when fulfilled can returns one out of these possible values: - * - `running`: the packager is running - * - `not_running`: the packager nor any process is running on the expected - * port. - * - `unrecognized`: one other process is running on the port we expect the - * packager to be running. - */ -function isPackagerRunning(packagerPort) { - return fetch(`http://localhost:${packagerPort}/status`).then( - (res) => - res - .text() - .then( - (body) => - body === "packager-status:running" ? "running" : "unrecognized" - ), - () => "not_running" - ); -} - -function startServerInNewWindow(port = process.env.RCT_METRO_PORT || 8081) { - const scriptFile = /^win/.test(process.platform) - ? "launchPackager.bat" - : "launchPackager.command"; - const scriptsDir = path.join( - process.cwd(), - "node_modules/react-native/scripts" - ); - const launchPackagerScript = path.resolve(scriptsDir, scriptFile); - const procConfig = { cwd: scriptsDir }; - const terminal = process.env.REACT_TERMINAL; - - // setup the .packager.env file to ensure the packager starts on the right port - const packagerEnvFile = path.join(scriptsDir, ".packager.env"); - const content = `export RCT_METRO_PORT=${port}`; - // ensure we overwrite file by passing the 'w' flag - fs.writeFileSync(packagerEnvFile, content, { encoding: "utf8", flag: "w" }); - - if (process.platform === "darwin") { - if (terminal) { - return child_process.spawnSync( - "open", - ["-a", terminal, launchPackagerScript], - procConfig - ); - } - return child_process.spawnSync("open", [launchPackagerScript], procConfig); - } else if (process.platform === "linux") { - procConfig.detached = true; - if (terminal) { - return child_process.spawn( - terminal, - ["-e", "sh " + launchPackagerScript], - procConfig - ); - } - return child_process.spawn("sh", [launchPackagerScript], procConfig); - } else if (/^win/.test(process.platform)) { - procConfig.detached = true; - procConfig.stdio = "ignore"; - return child_process.spawn( - "cmd.exe", - ["/C", launchPackagerScript], - procConfig - ); - } else { - console.log( - chalk.red( - `Cannot start the packager. Unknown platform ${process.platform}` - ) - ); - } -} - -function runDom(config, args, options) { - // fix up options - options.root = options.root || process.cwd(); - options.port = options.port || 8081; - - isPackagerRunning() - .then((res) => { - const isCurrentlyRunning = res === "running"; - if (!isCurrentlyRunning) { - startServerInNewWindow(options.port); - return waitPort({ - host: "localhost", - port: options.port - }); - } - }) - .then(() => { - opn(`http://localhost:${options.port}/dom`); - }); -} - -module.exports = { - name: "run-dom", - description: "builds your app and starts it in your default browser", - func: runDom, - options: [ - { - command: "--port", - description: "port to run the packager from" - } - ] -}; diff --git a/packages/react-native-dom/metro.config.js b/packages/react-native-dom/metro.config.js index d3a9ffce5..2e347b1ee 100644 --- a/packages/react-native-dom/metro.config.js +++ b/packages/react-native-dom/metro.config.js @@ -1,18 +1,65 @@ -"use strict"; +/** + * @format + */ +const fs = require('fs'); +const path = require('path'); +const rndPath = __dirname; +const {resolve} = require('metro-resolver'); +const blacklist = require('metro-config/src/defaults/blacklist'); -var path = require("path"); +function reactNativePlatformResolver(platformImplementations) { + return (context, _realModuleName, platform, moduleName) => { + console.log('moduleName = ', moduleName); + let backupResolveRequest = context.resolveRequest; + delete context.resolveRequest; -var config = { - projectRoot: path.resolve(__dirname, "../.."), + try { + let modifiedModuleName = moduleName; + if (platformImplementations[platform]) { + if (moduleName === 'react-native') { + modifiedModuleName = platformImplementations[platform]; + } else if (moduleName.startsWith('react-native/')) { + modifiedModuleName = `${ + platformImplementations[platform] + }/${modifiedModuleName.slice('react-native/'.length)}`; + } + } + let result = resolve(context, modifiedModuleName, platform); + return result; + } catch (e) { + throw e; + } finally { + context.resolveRequest = backupResolveRequest; + } + }; +} + +module.exports = { resolver: { - hasteImplModulePath: require.resolve("./jest/hasteImpl"), - platforms: ["dom"], - providesModuleNodeModules: ["react-native-dom"], + // We need a custom resolveRequest right now since our integration tests use a "windesktop" platform thats specific to integration tests. + resolveRequest: reactNativePlatformResolver({ + dom: 'react-native-dom' + /** + * TODO: uncomment once temporary package registry is solved + */ + // dom: 'react-native-dom' + }), extraNodeModules: { - "react-native-dom": __dirname, - "react-native": path.resolve(__dirname, "./node_modules/react-native") - } - } -}; + // Redirect react-native-windows to this folder + 'react-native-dom': rndPath, + /** + * TODO: uncomment once temporary package registry is solved + */ + // 'react-native-dom': rndPath, + }, + }, -module.exports = config; + transformer: { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: false, + }, + }), + }, +}; diff --git a/packages/react-native-dom/package.json b/packages/react-native-dom/package.json index 7f6a28e53..df6022a18 100644 --- a/packages/react-native-dom/package.json +++ b/packages/react-native-dom/package.json @@ -15,113 +15,38 @@ "email": "vincentriemer+rndom@gmail.com", "url": "https://vincentriemer.com" }, - "files": [ - "lib", - "Libraries", - "local-cli", - "flow-typed", - "jest" - ], - "main": "lib/ReactDom.js", + "main": "index.js", "scripts": { - "prebuild:rntester": "rimraf dist && mkdir -p dist", - "build:rntester": "NODE_ENV=production yarn run build:rntester:client && yarn run build:rntester:bundle && cp ./RNTester/js/index.html ./dist/index.html", - "build:rntester:bundle": "react-native bundle --config $(pwd)/metro.config.js --dev false --entry-file $(pwd)/RNTester/js/RNTesterApp.dom.js --bundle-output ./dist/RNTesterApp.dom.bundle --sourcemap-output ./dist/RNTesterApp.bundle.map --platform dom --assets-dest ./dist --reset-cache", - "build:rntester:client": "react-native bundle --config $(pwd)/metro.config.js --dev false --entry-file $(pwd)/RNTester/js/client.js --bundle-output ./dist/client.bundle --sourcemap-output ./dist/client.bundle.map --platform dom --reset-cache", - "precompile": "rimraf lib", - "compile": "BABEL_ENV=lib babel ReactDom --out-dir lib --source-maps", - "postcompile": "flow-copy-source ReactDom lib", - "flow": "flow", - "prepublishOnly": "yarn compile", - "run-examples": "react-native start --port 8081", - "test": "jest" - }, - "jest": { - "haste": { - "defaultPlatform": "dom", - "providesModuleNodeModules": [ - "react-native-dom" - ], - "platforms": [ - "dom" - ] - }, - "roots": [ - "/Libraries/", - "/ReactDom/" - ] - }, - "dependencies": { - "@babel/generator": "^7.0.0", - "@babel/runtime": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/types": "^7.0.0", - "@webcomponents/webcomponentsjs": "^2.0.2", - "bezier-easing": "^2.0.3", - "cuid": "^2.1.1", - "debounce": "^1.0.2", - "deepmerge": "^1.5.0", - "detect-it": "^3.0.0", - "fast-memoize": "^2.2.7", - "history": "^4.7.2", - "idb-keyval": "^3.0.5", - "inline-style-prefixer": "^3.0.8", - "invariant": "^2.2.2", - "node-fetch": "^1.7.3", - "normalize-css-color": "^1.0.2", - "opn": "^5.2.0", - "pepjs": "^0.4.3", - "query-string": "^6.1.0", - "resize-observer-polyfill": "^1.5.0", - "rndom-redbox": "0.5.0", - "rndom-switch": "0.5.0", - "rtl-detect": "^1.0.2", - "tinycolor2": "^1.4.1", - "wait-port": "^0.2.2", - "web-animations-js": "^2.3.1", - "wolfy87-eventemitter": "^5.1.0", - "yeoman-environment": "^2.2.0", - "yeoman-generator": "^2.0.5", - "yoga-dom": "0.0.15" + "compile": "just-scripts build", + "test": "just-scripts test", + "package": "npm pack" }, + "keywords": [ + "react-native", + "react-native-dom" + ], + "files": [ + "react-native.config.js", + "metro.config.js", + "rn-get-polyfills.js", + "index.js", + "index.dom.js", + "generateDom.js", + "dom", + "scripts", + "Libraries" + ], "devDependencies": { - "@babel/cli": "^7.0.0", - "@babel/core": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/preset-flow": "^7.0.0", - "@babel/template": "^7.0.0", - "babel-core": "7.0.0-bridge.0", - "babel-jest": "^23.6.0", - "babel-plugin-module-resolver": "^3.1.1", - "babel-plugin-preval": "^1.3.2", - "babel-plugin-transform-inline-environment-variables": "^0.1.1", - "flow-bin": "^0.70.0", - "flow-copy-source": "^1.3.0", - "flow-typed": "^2.2.3", - "jest": "^23.6.0", - "lint-staged": "^6.0.0", - "metro-react-native-babel-preset": "^0.49.0", - "prettier": "^1.9.0", - "react": "16.6.0-alpha.8af6728", - "react-native": "~0.57.8", - "resolve": "^1.7.1", - "rimraf": "^2.6.1" + "just-scripts": "^1.2.6", + "react-native": "0.62.2" }, "peerDependencies": { - "react-native": "~0.57.0" + "react-native": "~0.62.0" }, - "rnpm": { - "haste": { - "providesModuleNodeModules": [ - "react-native-dom" - ], - "platforms": [ - "dom" - ] - }, - "plugin": "./local-cli/index.js" + "dependencies": { + "metro-config": "^0.64.0", + "metro-resolver": "^0.64.0", + "react-native-dom-cli": "^1.0.0", + "react-native-dom-renderer": "^1.0.0" } } diff --git a/packages/react-native-dom/react-native.config.js b/packages/react-native-dom/react-native.config.js new file mode 100644 index 000000000..fbc407bb1 --- /dev/null +++ b/packages/react-native-dom/react-native.config.js @@ -0,0 +1,15 @@ +// @ts-check +const cli = require('react-native-dom-cli'); + +module.exports = { + // **** This section defined commands and options on how to provide the Windows platform to external applications + commands: cli.commands, + platforms: { + dom: { + linkConfig: () => null, + projectConfig: () => null, + dependencyConfig: () => null, + npmPackageName: 'react-native-dom', + }, + }, + }; diff --git a/packages/react-native-dom/scripts/copyRNLibraries.js b/packages/react-native-dom/scripts/copyRNLibraries.js new file mode 100644 index 000000000..0a0b7eee4 --- /dev/null +++ b/packages/react-native-dom/scripts/copyRNLibraries.js @@ -0,0 +1,91 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + * @ts-check + */ + +const glob = require('glob'); +const path = require('path'); +const {cleanTask, copyTask, series} = require('just-scripts'); + +const rnDir = path.dirname(require.resolve('react-native/package.json')); +// const rnCopiesDir = path.join( +// path.dirname(require.resolve('react-native-dom/package.json')), +// 'ReactCopies', +// ); + +exports.copyTask = baseDir => { + const reactNative = (...files) => { + return files.map(f => { + return path.join(rnDir, f) + }); + } + // const reactCopies = (...files) => files.map(f => path.join(rnCopiesDir, f)); + const src = (...files) => files.map(f => path.join(baseDir, 'src', f)); + const base = file => path.join(baseDir, file); + + return series( + exports.cleanTask(baseDir), + + copyTask({ + paths: reactNative('flow/**'), + dest: base('flow'), + }), + copyTask({ + paths: reactNative('flow-typed/**'), + dest: base('flow-typed'), + }), + copyTask({ + paths: reactNative('jest/**'), + dest: base('jest'), + }), + // copyTask({ + // paths: reactCopies('IntegrationTests/**'), + // dest: base('IntegrationTests'), + // }), + copyTask({ + paths: reactNative('Libraries/**/*.+(js|jsx|png|gif|jpg|html)'), + dest: base('Libraries'), + }), + + copyTask({ + paths: reactNative('index.js', 'interface.js', 'rn-get-polyfills.js'), + dest: base('.'), + }), + + copyTask({paths: src('**/*+(.d.ts|.js|.png)'), dest: base('.')}), + ); +}; + +exports.cleanTask = baseDir => { + const base = file => path.join(baseDir, file); + + return cleanTask({ + paths: [ + base('flow'), + base('jest'), + + // IntegrationTests overlaps with the desktop test runner, so we need to + // be careful about what is removed until that is fixed. + ...glob.sync('IntegrationTests/**/*.+(js|command|png)', { + cwd: baseDir, + absolute: true, + }), + + base('Libraries'), + base('index.js'), + base('interface.js'), + base('rn-get-polyfills.js'), + + // Remove TS compiled gunk in our root + ...glob.sync( + '+(index|typings-index)*(.windows|.win32)*(.d)+(.js|.ts)*(.map)', + { + cwd: baseDir, + absolute: true, + }, + ), + ], + }); +}; diff --git a/packages/react-native-dom/src/Libraries/Alert/RCTAlertManager.dom.js b/packages/react-native-dom/src/Libraries/Alert/RCTAlertManager.dom.js new file mode 100644 index 000000000..8ededddf4 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Alert/RCTAlertManager.dom.js @@ -0,0 +1,26 @@ +/** + * 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 strict-local + */ + +'use strict'; + +import NativeAlertManager from './NativeAlertManager'; +import type {Args} from './NativeAlertManager'; + +module.exports = { + alertWithArgs( + args: Args, + callback: (id: number, value: string) => void, + ): void { + if (NativeAlertManager == null) { + return; + } + NativeAlertManager.alertWithArgs(args, callback); + }, +}; diff --git a/packages/react-native-dom/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js b/packages/react-native-dom/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js similarity index 83% rename from packages/react-native-dom/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js rename to packages/react-native-dom/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js index ac1e1822c..da977ba06 100644 --- a/packages/react-native-dom/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.dom.js @@ -10,4 +10,4 @@ * @flow */ -module.exports = {}; +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/Libraries/Components/Button.dom.js b/packages/react-native-dom/src/Libraries/Components/Button.dom.js similarity index 58% rename from packages/react-native-dom/Libraries/Components/Button.dom.js rename to packages/react-native-dom/src/Libraries/Components/Button.dom.js index 3015e146b..eaeb0d23c 100644 --- a/packages/react-native-dom/Libraries/Components/Button.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/Button.dom.js @@ -8,19 +8,19 @@ * @flow */ -"use strict"; +'use strict'; -const Platform = require("Platform"); -const React = require("React"); -const StyleSheet = require("StyleSheet"); -const Text = require("Text"); -const TouchableNativeFeedback = require("TouchableNativeFeedback"); -const TouchableOpacity = require("TouchableOpacity"); -const View = require("View"); +const Platform = require('../Utilities/Platform'); +const React = require('react'); +const StyleSheet = require('../StyleSheet/StyleSheet'); +const Text = require('../Text/Text'); +const TouchableNativeFeedback = require('./Touchable/TouchableNativeFeedback'); +const TouchableOpacity = require('./Touchable/TouchableOpacity'); +const View = require('./View/View'); -const invariant = require("fbjs/lib/invariant"); +const invariant = require('invariant'); -import type { PressEvent } from "CoreEventTypes"; +import type {PressEvent} from '../Types/CoreEventTypes'; type ButtonProps = $ReadOnly<{| /** @@ -33,6 +33,11 @@ type ButtonProps = $ReadOnly<{| */ onPress: (event?: PressEvent) => mixed, + /** + * If true, doesn't play system sound on touch (Android Only) + **/ + touchSoundDisabled?: ?boolean, + /** * Color of the text (iOS), or background color of the button (Android) */ @@ -43,6 +48,41 @@ type ButtonProps = $ReadOnly<{| */ hasTVPreferredFocus?: ?boolean, + /** + * TV next focus down (see documentation for the View component). + * + * @platform android + */ + nextFocusDown?: ?number, + + /** + * TV next focus forward (see documentation for the View component). + * + * @platform android + */ + nextFocusForward?: ?number, + + /** + * TV next focus left (see documentation for the View component). + * + * @platform android + */ + nextFocusLeft?: ?number, + + /** + * TV next focus right (see documentation for the View component). + * + * @platform android + */ + nextFocusRight?: ?number, + + /** + * TV next focus up (see documentation for the View component). + * + * @platform android + */ + nextFocusUp?: ?number, + /** * Text to display for blindness accessibility features */ @@ -56,7 +96,7 @@ type ButtonProps = $ReadOnly<{| /** * Used to locate this view in end-to-end tests. */ - testID?: ?string + testID?: ?string, |}>; /** @@ -88,49 +128,60 @@ type ButtonProps = $ReadOnly<{| */ class Button extends React.Component { - render() { + render(): React.Node { const { accessibilityLabel, color, onPress, + touchSoundDisabled, title, hasTVPreferredFocus, + nextFocusDown, + nextFocusForward, + nextFocusLeft, + nextFocusRight, + nextFocusUp, disabled, - testID + testID, } = this.props; const buttonStyles = [styles.button]; const textStyles = [styles.text]; if (color) { - if (Platform.OS === "ios") { - textStyles.push({ color: color }); + if (Platform.OS === 'ios') { + textStyles.push({color: color}); } else { - buttonStyles.push({ backgroundColor: color }); + buttonStyles.push({backgroundColor: color}); } } - const accessibilityStates = []; + const accessibilityState = {}; if (disabled) { buttonStyles.push(styles.buttonDisabled); textStyles.push(styles.textDisabled); - accessibilityStates.push("disabled"); + accessibilityState.disabled = true; } invariant( - typeof title === "string", - "The title prop of a Button must be a string" + typeof title === 'string', + 'The title prop of a Button must be a string', ); const formattedTitle = - Platform.OS === "android" ? title.toUpperCase() : title; + Platform.OS === 'android' ? title.toUpperCase() : title; const Touchable = - Platform.OS === "android" ? TouchableNativeFeedback : TouchableOpacity; + Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity; return ( + touchSoundDisabled={touchSoundDisabled}> {formattedTitle} @@ -147,40 +198,40 @@ const styles = StyleSheet.create({ android: { elevation: 4, // Material design blue from https://material.google.com/style/color.html#color-color-palette - backgroundColor: "#2196F3", - borderRadius: 2 + backgroundColor: '#2196F3', + borderRadius: 2, }, dom: { - backgroundColor: "#007bff", + backgroundColor: '#007bff', borderRadius: 2 } }), text: { - textAlign: "center", - padding: 8, + textAlign: 'center', + margin: 8, ...Platform.select({ ios: { // iOS blue from https://developer.apple.com/ios/human-interface-guidelines/visual-design/color/ - color: "#007AFF", - fontSize: 18 + color: '#007AFF', + fontSize: 18, }, android: { - color: "white", - fontWeight: "500" + color: 'white', + fontWeight: '500', }, dom: { - color: "white", - textAlign: "center", + color: 'white', + textAlign: 'center', paddingVertical: 8, paddingHorizontal: 12 } - }) + }), }, buttonDisabled: Platform.select({ ios: {}, android: { elevation: 0, - backgroundColor: "#dfdfdf" + backgroundColor: '#dfdfdf', }, dom: { opacity: 0.65 @@ -188,13 +239,13 @@ const styles = StyleSheet.create({ }), textDisabled: Platform.select({ ios: { - color: "#cdcdcd" + color: '#cdcdcd', }, android: { - color: "#a1a1a1" + color: '#a1a1a1', }, dom: {} - }) + }), }); module.exports = Button; diff --git a/packages/react-native-dom/Libraries/Components/CheckBox/CheckBox.dom.js b/packages/react-native-dom/src/Libraries/Components/CheckBox/CheckBox.dom.js similarity index 84% rename from packages/react-native-dom/Libraries/Components/CheckBox/CheckBox.dom.js rename to packages/react-native-dom/src/Libraries/Components/CheckBox/CheckBox.dom.js index 31566abef..366aacb05 100644 --- a/packages/react-native-dom/Libraries/Components/CheckBox/CheckBox.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/CheckBox/CheckBox.dom.js @@ -11,4 +11,4 @@ */ "use strict"; -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/Libraries/Components/Clipboard/Clipboard.dom.js b/packages/react-native-dom/src/Libraries/Components/Clipboard/Clipboard.dom.js similarity index 100% rename from packages/react-native-dom/Libraries/Components/Clipboard/Clipboard.dom.js rename to packages/react-native-dom/src/Libraries/Components/Clipboard/Clipboard.dom.js diff --git a/packages/react-native-dom/Libraries/Components/DatePicker/DatePickerIOS.dom.js b/packages/react-native-dom/src/Libraries/Components/DatePicker/DatePickerIOS.dom.js similarity index 83% rename from packages/react-native-dom/Libraries/Components/DatePicker/DatePickerIOS.dom.js rename to packages/react-native-dom/src/Libraries/Components/DatePicker/DatePickerIOS.dom.js index 6fb0701e5..86e1add0f 100644 --- a/packages/react-native-dom/Libraries/Components/DatePicker/DatePickerIOS.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/DatePicker/DatePickerIOS.dom.js @@ -10,4 +10,4 @@ * @flow */ -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/Libraries/Components/DatePickerAndroid/DatePickerAndroid.dom.js b/packages/react-native-dom/src/Libraries/Components/DatePickerAndroid/DatePickerAndroid.dom.js similarity index 100% rename from packages/react-native-dom/Libraries/Components/DatePickerAndroid/DatePickerAndroid.dom.js rename to packages/react-native-dom/src/Libraries/Components/DatePickerAndroid/DatePickerAndroid.dom.js diff --git a/packages/react-native-dom/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js b/packages/react-native-dom/src/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js similarity index 84% rename from packages/react-native-dom/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js rename to packages/react-native-dom/src/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js index 27a1d9ceb..58519bac4 100644 --- a/packages/react-native-dom/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.dom.js @@ -10,4 +10,4 @@ */ "use strict"; -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/Libraries/Components/MaskedView/MaskedViewIOS.dom.js b/packages/react-native-dom/src/Libraries/Components/MaskedView/MaskedViewIOS.dom.js similarity index 84% rename from packages/react-native-dom/Libraries/Components/MaskedView/MaskedViewIOS.dom.js rename to packages/react-native-dom/src/Libraries/Components/MaskedView/MaskedViewIOS.dom.js index ab442df25..2b9608a70 100644 --- a/packages/react-native-dom/Libraries/Components/MaskedView/MaskedViewIOS.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/MaskedView/MaskedViewIOS.dom.js @@ -11,4 +11,5 @@ */ "use strict"; -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); + diff --git a/packages/react-native-dom/Libraries/Components/Picker/PickerAndroid.dom.js b/packages/react-native-dom/src/Libraries/Components/Picker/PickerAndroid.dom.js similarity index 71% rename from packages/react-native-dom/Libraries/Components/Picker/PickerAndroid.dom.js rename to packages/react-native-dom/src/Libraries/Components/Picker/PickerAndroid.dom.js index 4ba623b05..1153828cb 100644 --- a/packages/react-native-dom/Libraries/Components/Picker/PickerAndroid.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/Picker/PickerAndroid.dom.js @@ -10,8 +10,6 @@ */ "use strict"; -module.exports = require("UnimplementedView"); - -const UnimplementedView = require("UnimplementedView"); -UnimplementedView.Item = require("UnimplementedView"); +const UnimplementedView = require('../UnimplementedViews/UnimplementedView'); +UnimplementedView.Item = require('../UnimplementedViews/UnimplementedView'); module.exports = UnimplementedView; diff --git a/packages/react-native-dom/Libraries/Components/Picker/PickerIOS.dom.js b/packages/react-native-dom/src/Libraries/Components/Picker/PickerIOS.dom.js similarity index 74% rename from packages/react-native-dom/Libraries/Components/Picker/PickerIOS.dom.js rename to packages/react-native-dom/src/Libraries/Components/Picker/PickerIOS.dom.js index 8b242f1c5..13f183126 100644 --- a/packages/react-native-dom/Libraries/Components/Picker/PickerIOS.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/Picker/PickerIOS.dom.js @@ -12,6 +12,6 @@ */ "use strict"; -const UnimplementedView = require("UnimplementedView"); -UnimplementedView.Item = require("UnimplementedView"); +const UnimplementedView = require('../UnimplementedViews/UnimplementedView'); +UnimplementedView.Item = require('../UnimplementedViews/UnimplementedView'); module.exports = UnimplementedView; diff --git a/packages/react-native-dom/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js b/packages/react-native-dom/src/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js similarity index 84% rename from packages/react-native-dom/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js rename to packages/react-native-dom/src/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js index 322641712..bb1ff3dc4 100644 --- a/packages/react-native-dom/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.dom.js @@ -10,4 +10,4 @@ */ "use strict"; -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js b/packages/react-native-dom/src/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js similarity index 85% rename from packages/react-native-dom/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js rename to packages/react-native-dom/src/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js index 2035dd1ea..d94340e62 100644 --- a/packages/react-native-dom/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/ProgressViewIOS/ProgressViewIOS.dom.js @@ -13,4 +13,4 @@ "use strict"; -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/src/Libraries/Components/ScrollView/ScrollView.dom.js b/packages/react-native-dom/src/Libraries/Components/ScrollView/ScrollView.dom.js new file mode 100644 index 000000000..63d41fec5 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Components/ScrollView/ScrollView.dom.js @@ -0,0 +1,1221 @@ +/** + * 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 strict-local + */ + +'use strict'; + +const AnimatedImplementation = require('../../Animated/src/AnimatedImplementation'); +const Platform = require('../../Utilities/Platform'); +const React = require('react'); +const ReactNative = require('../../Renderer/shims/ReactNative'); +require('../../Renderer/shims/ReactNative'); // Force side effects to prevent T55744311 +const ScrollResponder = require('../ScrollResponder'); +const ScrollViewStickyHeader = require('./ScrollViewStickyHeader'); +const StyleSheet = require('../../StyleSheet/StyleSheet'); +const View = require('../View/View'); + +const dismissKeyboard = require('../../Utilities/dismissKeyboard'); +const flattenStyle = require('../../StyleSheet/flattenStyle'); +const invariant = require('invariant'); +const processDecelerationRate = require('./processDecelerationRate'); +const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); +const resolveAssetSource = require('../../Image/resolveAssetSource'); +const splitLayoutProps = require('../../StyleSheet/splitLayoutProps'); + +import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType'; +import type {PointProp} from '../../StyleSheet/PointPropType'; +import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; +import type {ColorValue} from '../../StyleSheet/StyleSheetTypes'; +import type { + PressEvent, + ScrollEvent, + LayoutEvent, +} from '../../Types/CoreEventTypes'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import type {State as ScrollResponderState} from '../ScrollResponder'; +import type {ViewProps} from '../View/ViewPropTypes'; +import type {Props as ScrollViewStickyHeaderProps} from './ScrollViewStickyHeader'; + +import ScrollViewNativeComponent from './ScrollViewNativeComponent'; +import ScrollContentViewNativeComponent from './ScrollContentViewNativeComponent'; +import AndroidHorizontalScrollViewNativeComponent from './AndroidHorizontalScrollViewNativeComponent'; +import AndroidHorizontalScrollContentViewNativeComponent from './AndroidHorizontalScrollContentViewNativeComponent'; + +let AndroidScrollView; +let AndroidHorizontalScrollContentView; +let AndroidHorizontalScrollView; +let RCTScrollView; +let RCTScrollContentView; + +if (Platform.OS === 'android') { + AndroidScrollView = ScrollViewNativeComponent; + AndroidHorizontalScrollView = AndroidHorizontalScrollViewNativeComponent; + AndroidHorizontalScrollContentView = AndroidHorizontalScrollContentViewNativeComponent; +} else if (Platform.OS === 'dom' || Platform.OS === 'ios') { + RCTScrollView = ScrollViewNativeComponent; + RCTScrollContentView = ScrollContentViewNativeComponent; +} else { + RCTScrollView = requireNativeComponent('RCTScrollView'); + RCTScrollContentView = requireNativeComponent('RCTScrollContentView'); +} + +export type ScrollResponderType = { + // We'd like to do ...ScrollView here, however Flow doesn't seem + // to see the imperative methods of ScrollView that way. Workaround the + // issue by specifying them manually. + getScrollableNode: $PropertyType, + getInnerViewNode: $PropertyType, + getInnerViewRef: $PropertyType, + getNativeScrollRef: $PropertyType, + setNativeProps: $PropertyType, + scrollTo: $PropertyType, + flashScrollIndicators: $PropertyType, + ...typeof ScrollResponder.Mixin, + ... +}; + +type IOSProps = $ReadOnly<{| + /** + * Controls whether iOS should automatically adjust the content inset + * for scroll views that are placed behind a navigation bar or + * tab bar/ toolbar. The default value is true. + * @platform ios + */ + automaticallyAdjustContentInsets?: ?boolean, + /** + * The amount by which the scroll view content is inset from the edges + * of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`. + * @platform ios + */ + contentInset?: ?EdgeInsetsProp, + /** + * Used to manually set the starting scroll offset. + * The default value is `{x: 0, y: 0}`. + * @platform ios + */ + contentOffset?: ?PointProp, + /** + * When true, the scroll view bounces when it reaches the end of the + * content if the content is larger then the scroll view along the axis of + * the scroll direction. When false, it disables all bouncing even if + * the `alwaysBounce*` props are true. The default value is true. + * @platform ios + */ + bounces?: ?boolean, + /** + * By default, ScrollView has an active pan responder that hijacks panresponders + * deeper in the render tree in order to prevent accidental touches while scrolling. + * However, in certain occasions (such as when using snapToInterval) in a vertical scrollview + * You may want to disable this behavior in order to prevent the ScrollView from blocking touches + */ + disableScrollViewPanResponder?: ?boolean, + /** + * When true, gestures can drive zoom past min/max and the zoom will animate + * to the min/max value at gesture end, otherwise the zoom will not exceed + * the limits. + * @platform ios + */ + bouncesZoom?: ?boolean, + /** + * When true, the scroll view bounces horizontally when it reaches the end + * even if the content is smaller than the scroll view itself. The default + * value is true when `horizontal={true}` and false otherwise. + * @platform ios + */ + alwaysBounceHorizontal?: ?boolean, + /** + * When true, the scroll view bounces vertically when it reaches the end + * even if the content is smaller than the scroll view itself. The default + * value is false when `horizontal={true}` and true otherwise. + * @platform ios + */ + alwaysBounceVertical?: ?boolean, + /** + * When true, the scroll view automatically centers the content when the + * content is smaller than the scroll view bounds; when the content is + * larger than the scroll view, this property has no effect. The default + * value is false. + * @platform ios + */ + centerContent?: ?boolean, + /** + * The style of the scroll indicators. + * + * - `'default'` (the default), same as `black`. + * - `'black'`, scroll indicator is black. This style is good against a light background. + * - `'white'`, scroll indicator is white. This style is good against a dark background. + * + * @platform ios + */ + indicatorStyle?: ?('default' | 'black' | 'white'), + /** + * When true, the ScrollView will try to lock to only vertical or horizontal + * scrolling while dragging. The default value is false. + * @platform ios + */ + directionalLockEnabled?: ?boolean, + /** + * When false, once tracking starts, won't try to drag if the touch moves. + * The default value is true. + * @platform ios + */ + canCancelContentTouches?: ?boolean, + /** + * When set, the scroll view will adjust the scroll position so that the first child that is + * currently visible and at or beyond `minIndexForVisible` will not change position. This is + * useful for lists that are loading content in both directions, e.g. a chat thread, where new + * messages coming in might otherwise cause the scroll position to jump. A value of 0 is common, + * but other values such as 1 can be used to skip loading spinners or other content that should + * not maintain position. + * + * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll + * to the top after making the adjustment if the user was within the threshold of the top before + * the adjustment was made. This is also useful for chat-like applications where you want to see + * new messages scroll into place, but not if the user has scrolled up a ways and it would be + * disruptive to scroll a bunch. + * + * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause + * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, + * don't re-order the content of any ScrollViews or Lists that use this feature. + * + * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute + * visibility. Occlusion, transforms, and other complexity won't be taken into account as to + * whether content is "visible" or not. + * + * @platform ios + */ + maintainVisibleContentPosition?: ?$ReadOnly<{| + minIndexForVisible: number, + autoscrollToTopThreshold?: ?number, + |}>, + /** + * The maximum allowed zoom scale. The default value is 1.0. + * @platform ios + */ + maximumZoomScale?: ?number, + /** + * The minimum allowed zoom scale. The default value is 1.0. + * @platform ios + */ + minimumZoomScale?: ?number, + /** + * When true, ScrollView allows use of pinch gestures to zoom in and out. + * The default value is true. + * @platform ios + */ + pinchGestureEnabled?: ?boolean, + /** + * This controls how often the scroll event will be fired while scrolling + * (as a time interval in ms). A lower number yields better accuracy for code + * that is tracking the scroll position, but can lead to scroll performance + * problems due to the volume of information being send over the bridge. + * + * Values between 0 and 17ms indicate 60fps updates are needed and throttling + * will be disabled. + * + * If you do not need precise scroll position tracking, set this value higher + * to limit the information being sent across the bridge. + * + * The default value is zero, which results in the scroll event being sent only + * once each time the view is scrolled. + * + * @platform ios + */ + scrollEventThrottle?: ?number, + /** + * The amount by which the scroll view indicators are inset from the edges + * of the scroll view. This should normally be set to the same value as + * the `contentInset`. Defaults to `{0, 0, 0, 0}`. + * @platform ios + */ + scrollIndicatorInsets?: ?EdgeInsetsProp, + /** + * When true, the scroll view can be programmatically scrolled beyond its + * content size. The default value is false. + * @platform ios + */ + scrollToOverflowEnabled?: ?boolean, + /** + * When true, the scroll view scrolls to top when the status bar is tapped. + * The default value is true. + * @platform ios + */ + scrollsToTop?: ?boolean, + /** + * Fires when the scroll view scrolls to top after the status bar has been tapped + * @platform ios + */ + onScrollToTop?: (event: ScrollEvent) => void, + /** + * When true, shows a horizontal scroll indicator. + * The default value is true. + */ + showsHorizontalScrollIndicator?: ?boolean, + /** + * When `snapToInterval` is set, `snapToAlignment` will define the relationship + * of the snapping to the scroll view. + * + * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical) + * - `'center'` will align the snap in the center + * - `'end'` will align the snap at the right (horizontal) or bottom (vertical) + * + * @platform ios + */ + snapToAlignment?: ?('start' | 'center' | 'end'), + /** + * The current scale of the scroll view content. The default value is 1.0. + * @platform ios + */ + zoomScale?: ?number, + /** + * This property specifies how the safe area insets are used to modify the + * content area of the scroll view. The default value of this property is + * "never". Available on iOS 11 and later. + * @platform ios + */ + contentInsetAdjustmentBehavior?: ?( + | 'automatic' + | 'scrollableAxes' + | 'never' + | 'always' + ), + /** + * When true, ScrollView will emit updateChildFrames data in scroll events, + * otherwise will not compute or emit child frame data. This only exists + * to support legacy issues, `onLayout` should be used instead to retrieve + * frame data. + * The default value is false. + * @platform ios + */ + DEPRECATED_sendUpdatedChildFrames?: ?boolean, +|}>; + +type AndroidProps = $ReadOnly<{| + /** + * Enables nested scrolling for Android API level 21+. + * Nested scrolling is supported by default on iOS + * @platform android + */ + nestedScrollEnabled?: ?boolean, + /** + * Sometimes a scrollview takes up more space than its content fills. When this is + * the case, this prop will fill the rest of the scrollview with a color to avoid setting + * a background and creating unnecessary overdraw. This is an advanced optimization + * that is not needed in the general case. + * @platform android + */ + endFillColor?: ?ColorValue, + /** + * Tag used to log scroll performance on this scroll view. Will force + * momentum events to be turned on (see sendMomentumEvents). This doesn't do + * anything out of the box and you need to implement a custom native + * FpsListener for it to be useful. + * @platform android + */ + scrollPerfTag?: ?string, + /** + * Used to override default value of overScroll mode. + * + * Possible values: + * + * - `'auto'` - Default value, allow a user to over-scroll + * this view only if the content is large enough to meaningfully scroll. + * - `'always'` - Always allow a user to over-scroll this view. + * - `'never'` - Never allow a user to over-scroll this view. + * + * @platform android + */ + overScrollMode?: ?('auto' | 'always' | 'never'), + /** + * Causes the scrollbars not to turn transparent when they are not in use. + * The default value is false. + * + * @platform android + */ + persistentScrollbar?: ?boolean, + /** + * Fades out the edges of the the scroll content. + * + * If the value is greater than 0, the fading edges will be set accordingly + * to the current scroll direction and position, + * indicating if there is more content to show. + * + * The default value is 0. + * + * @platform android + */ + fadingEdgeLength?: ?number, +|}>; + +type VRProps = $ReadOnly<{| + /** + * Optionally an image can be used for the scroll bar thumb. This will + * override the color. While the image is loading or the image fails to + * load the color will be used instead. Use an alpha of 0 in the color + * to avoid seeing it while the image is loading. + * + * - `uri` - a string representing the resource identifier for the image, which + * should be either a local file path or the name of a static image resource + * - `number` - Opaque type returned by something like + * `import IMAGE from './image.jpg'`. + * @platform vr + */ + scrollBarThumbImage?: ?($ReadOnly<{||}> | number), // Opaque type returned by import IMAGE from './image.jpg' +|}>; + +type StickyHeaderComponentType = React.AbstractComponent< + ScrollViewStickyHeaderProps, + $ReadOnly<{setNextHeaderY: number => void, ...}>, +>; + +export type Props = $ReadOnly<{| + ...ViewProps, + ...IOSProps, + ...AndroidProps, + ...VRProps, + + /** + * These styles will be applied to the scroll view content container which + * wraps all of the child views. Example: + * + * ``` + * return ( + * + * + * ); + * ... + * const styles = StyleSheet.create({ + * contentContainer: { + * paddingVertical: 20 + * } + * }); + * ``` + */ + contentContainerStyle?: ?ViewStyleProp, + /** + * When true, the scroll view stops on the next index (in relation to scroll + * position at release) regardless of how fast the gesture is. This can be + * used for horizontal pagination when the page is less than the width of + * the ScrollView. The default value is false. + */ + disableIntervalMomentum?: ?boolean, + /** + * A floating-point number that determines how quickly the scroll view + * decelerates after the user lifts their finger. You may also use string + * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings + * for `UIScrollViewDecelerationRateNormal` and + * `UIScrollViewDecelerationRateFast` respectively. + * + * - `'normal'`: 0.998 on iOS, 0.985 on Android (the default) + * - `'fast'`: 0.99 on iOS, 0.9 on Android + */ + decelerationRate?: ?('fast' | 'normal' | number), + /** + * When true, the scroll view's children are arranged horizontally in a row + * instead of vertically in a column. The default value is false. + */ + horizontal?: ?boolean, + /** + * If sticky headers should stick at the bottom instead of the top of the + * ScrollView. This is usually used with inverted ScrollViews. + */ + invertStickyHeaders?: ?boolean, + /** + * Determines whether the keyboard gets dismissed in response to a drag. + * + * *Cross platform* + * + * - `'none'` (the default), drags do not dismiss the keyboard. + * - `'on-drag'`, the keyboard is dismissed when a drag begins. + * + * *iOS Only* + * + * - `'interactive'`, the keyboard is dismissed interactively with the drag and moves in + * synchrony with the touch; dragging upwards cancels the dismissal. + * On android this is not supported and it will have the same behavior as 'none'. + */ + keyboardDismissMode?: ?// default + (| 'none' // cross-platform + | 'on-drag' + | 'interactive' + ), // ios only + /** + * Determines when the keyboard should stay visible after a tap. + * + * - `'never'` (the default), tapping outside of the focused text input when the keyboard + * is up dismisses the keyboard. When this happens, children won't receive the tap. + * - `'always'`, the keyboard will not dismiss automatically, and the scroll view will not + * catch taps, but children of the scroll view can catch taps. + * - `'handled'`, the keyboard will not dismiss automatically when the tap was handled by + * a children, (or captured by an ancestor). + * - `false`, deprecated, use 'never' instead + * - `true`, deprecated, use 'always' instead + */ + keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | true | false), + /** + * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop). + */ + onMomentumScrollBegin?: ?(event: ScrollEvent) => void, + /** + * Called when the momentum scroll ends (scroll which occurs as the ScrollView glides to a stop). + */ + onMomentumScrollEnd?: ?(event: ScrollEvent) => void, + + /** + * Fires at most once per frame during scrolling. The frequency of the + * events can be controlled using the `scrollEventThrottle` prop. + */ + onScroll?: ?(event: ScrollEvent) => void, + /** + * Called when the user begins to drag the scroll view. + */ + onScrollBeginDrag?: ?(event: ScrollEvent) => void, + /** + * Called when the user stops dragging the scroll view and it either stops + * or begins to glide. + */ + onScrollEndDrag?: ?(event: ScrollEvent) => void, + /** + * Called when scrollable content view of the ScrollView changes. + * + * Handler function is passed the content width and content height as parameters: + * `(contentWidth, contentHeight)` + * + * It's implemented using onLayout handler attached to the content container + * which this ScrollView renders. + */ + onContentSizeChange?: (contentWidth: number, contentHeight: number) => void, + onKeyboardDidShow?: (event: PressEvent) => void, + /** + * When true, the scroll view stops on multiples of the scroll view's size + * when scrolling. This can be used for horizontal pagination. The default + * value is false. + * + * Note: Vertical pagination is not supported on Android. + */ + pagingEnabled?: ?boolean, + + /** + * When false, the view cannot be scrolled via touch interaction. + * The default value is true. + * + * Note that the view can always be scrolled by calling `scrollTo`. + */ + scrollEnabled?: ?boolean, + /** + * When true, shows a vertical scroll indicator. + * The default value is true. + */ + showsVerticalScrollIndicator?: ?boolean, + /** + * An array of child indices determining which children get docked to the + * top of the screen when scrolling. For example, passing + * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the + * top of the scroll view. This property is not supported in conjunction + * with `horizontal={true}`. + */ + stickyHeaderIndices?: ?$ReadOnlyArray, + /** + * A React Component that will be used to render sticky headers. + * To be used together with `stickyHeaderIndices` or with `SectionList`, defaults to `ScrollViewStickyHeader`. + * You may need to set this if your sticky header uses custom transforms (eg. translation), + * for example when you want your list to have an animated hidable header. + */ + StickyHeaderComponent?: StickyHeaderComponentType, + /** + * When set, causes the scroll view to stop at multiples of the value of + * `snapToInterval`. This can be used for paginating through children + * that have lengths smaller than the scroll view. Typically used in + * combination with `snapToAlignment` and `decelerationRate="fast"`. + * + * Overrides less configurable `pagingEnabled` prop. + */ + snapToInterval?: ?number, + /** + * When set, causes the scroll view to stop at the defined offsets. + * This can be used for paginating through variously sized children + * that have lengths smaller than the scroll view. Typically used in + * combination with `decelerationRate="fast"`. + * + * Overrides less configurable `pagingEnabled` and `snapToInterval` props. + */ + snapToOffsets?: ?$ReadOnlyArray, + /** + * Use in conjunction with `snapToOffsets`. By default, the beginning + * of the list counts as a snap offset. Set `snapToStart` to false to disable + * this behavior and allow the list to scroll freely between its start and + * the first `snapToOffsets` offset. + * The default value is true. + */ + snapToStart?: ?boolean, + /** + * Use in conjunction with `snapToOffsets`. By default, the end + * of the list counts as a snap offset. Set `snapToEnd` to false to disable + * this behavior and allow the list to scroll freely between its end and + * the last `snapToOffsets` offset. + * The default value is true. + */ + snapToEnd?: ?boolean, + /** + * Experimental: When true, offscreen child views (whose `overflow` value is + * `hidden`) are removed from their native backing superview when offscreen. + * This can improve scrolling performance on long lists. The default value is + * true. + */ + removeClippedSubviews?: ?boolean, + /** + * A RefreshControl component, used to provide pull-to-refresh + * functionality for the ScrollView. Only works for vertical ScrollViews + * (`horizontal` prop must be `false`). + * + * See [RefreshControl](docs/refreshcontrol.html). + */ + // $FlowFixMe - how to handle generic type without existential operator? + refreshControl?: ?React.Element, + children?: React.Node, +|}>; + +type State = {| + layoutHeight: ?number, + ...ScrollResponderState, +|}; + +function createScrollResponder( + node: React.ElementRef, +): typeof ScrollResponder.Mixin { + const scrollResponder = {...ScrollResponder.Mixin}; + + for (const key in scrollResponder) { + if (typeof scrollResponder[key] === 'function') { + scrollResponder[key] = scrollResponder[key].bind(node); + } + } + + return scrollResponder; +} + +type ContextType = {|horizontal: boolean|} | null; +const Context = React.createContext(null); +const standardHorizontalContext: ContextType = Object.freeze({ + horizontal: true, +}); +const standardVerticalContext: ContextType = Object.freeze({horizontal: false}); + +/** + * Component that wraps platform ScrollView while providing + * integration with touch locking "responder" system. + * + * Keep in mind that ScrollViews must have a bounded height in order to work, + * since they contain unbounded-height children into a bounded container (via + * a scroll interaction). In order to bound the height of a ScrollView, either + * set the height of the view directly (discouraged) or make sure all parent + * views have bounded height. Forgetting to transfer `{flex: 1}` down the + * view stack can lead to errors here, which the element inspector makes + * easy to debug. + * + * Doesn't yet support other contained responders from blocking this scroll + * view from becoming the responder. + * + * + * `` vs [``](/react-native/docs/flatlist.html) - which one to use? + * + * `ScrollView` simply renders all its react child components at once. That + * makes it very easy to understand and use. + * + * On the other hand, this has a performance downside. Imagine you have a very + * long list of items you want to display, maybe several screens worth of + * content. Creating JS components and native views for everything all at once, + * much of which may not even be shown, will contribute to slow rendering and + * increased memory usage. + * + * This is where `FlatList` comes into play. `FlatList` renders items lazily, + * just when they are about to appear, and removes items that scroll way off + * screen to save memory and processing time. + * + * `FlatList` is also handy if you want to render separators between your items, + * multiple columns, infinite scroll loading, or any number of other features it + * supports out of the box. + */ +class ScrollView extends React.Component { + static Context: React$Context = Context; + /** + * Part 1: Removing ScrollResponder.Mixin: + * + * 1. Mixin methods should be flow typed. That's why we create a + * copy of ScrollResponder.Mixin and attach it to this._scrollResponder. + * Otherwise, we'd have to manually declare each method on the component + * class and assign it a flow type. + * 2. Mixin methods can call component methods, and access the component's + * props and state. So, we need to bind all mixin methods to the + * component instance. + * 3. Continued... + */ + _scrollResponder: typeof ScrollResponder.Mixin = createScrollResponder(this); + + constructor(props: Props) { + super(props); + + /** + * Part 2: Removing ScrollResponder.Mixin + * + * 3. Mixin methods access other mixin methods via dynamic dispatch using + * this. Since mixin methods are bound to the component instance, we need + * to copy all mixin methods to the component instance. This is also + * necessary because getScrollResponder() is a public method that returns + * an object that can be used to execute all scrollResponder methods. + * Since the object returned from that method is the ScrollView instance, + * we need to bind all mixin methods to the ScrollView instance. + */ + for (const key in ScrollResponder.Mixin) { + if ( + typeof ScrollResponder.Mixin[key] === 'function' && + key.startsWith('scrollResponder') + ) { + // $FlowFixMe - dynamically adding properties to a class + (this: any)[key] = ScrollResponder.Mixin[key].bind(this); + } + } + + /** + * Part 3: Removing ScrollResponder.Mixin + * + * 4. Mixins can initialize properties and use properties on the component + * instance. + */ + Object.keys(ScrollResponder.Mixin) + .filter(key => typeof ScrollResponder.Mixin[key] !== 'function') + .forEach(key => { + // $FlowFixMe - dynamically adding properties to a class + (this: any)[key] = ScrollResponder.Mixin[key]; + }); + } + + _scrollAnimatedValue: AnimatedImplementation.Value = new AnimatedImplementation.Value( + 0, + ); + _scrollAnimatedValueAttachment: ?{detach: () => void, ...} = null; + _stickyHeaderRefs: Map< + string, + React.ElementRef, + > = new Map(); + _headerLayoutYs: Map = new Map(); + + state: State = { + layoutHeight: null, + ...ScrollResponder.Mixin.scrollResponderMixinGetInitialState(), + }; + + UNSAFE_componentWillMount() { + this._scrollResponder.UNSAFE_componentWillMount(); + this._scrollAnimatedValue = new AnimatedImplementation.Value( + this.props.contentOffset ? this.props.contentOffset.y : 0, + ); + this._scrollAnimatedValue.setOffset( + this.props.contentInset ? this.props.contentInset.top || 0 : 0, + ); + this._stickyHeaderRefs = new Map(); + this._headerLayoutYs = new Map(); + } + + UNSAFE_componentWillReceiveProps(nextProps: Props) { + const currentContentInsetTop = this.props.contentInset + ? this.props.contentInset.top + : 0; + const nextContentInsetTop = nextProps.contentInset + ? nextProps.contentInset.top + : 0; + if (currentContentInsetTop !== nextContentInsetTop) { + this._scrollAnimatedValue.setOffset(nextContentInsetTop || 0); + } + } + + componentDidMount() { + this._updateAnimatedNodeAttachment(); + } + + componentDidUpdate() { + this._updateAnimatedNodeAttachment(); + } + + componentWillUnmount() { + this._scrollResponder.componentWillUnmount(); + if (this._scrollAnimatedValueAttachment) { + this._scrollAnimatedValueAttachment.detach(); + } + } + + setNativeProps(props: {[key: string]: mixed, ...}) { + this._scrollViewRef && this._scrollViewRef.setNativeProps(props); + } + + /** + * Returns a reference to the underlying scroll responder, which supports + * operations like `scrollTo`. All ScrollView-like components should + * implement this method so that they can be composed while providing access + * to the underlying scroll responder's methods. + */ + getScrollResponder(): ScrollResponderType { + // $FlowFixMe - overriding type to include ScrollResponder.Mixin + return ((this: any): ScrollResponderType); + } + + getScrollableNode(): ?number { + return ReactNative.findNodeHandle(this._scrollViewRef); + } + + getInnerViewNode(): ?number { + return ReactNative.findNodeHandle(this._innerViewRef); + } + + getInnerViewRef(): ?React.ElementRef> { + return this._innerViewRef; + } + + getNativeScrollRef(): ?React.ElementRef> { + return this._scrollViewRef; + } + + /** + * Scrolls to a given x, y offset, either immediately or with a smooth animation. + * + * Example: + * + * `scrollTo({x: 0, y: 0, animated: true})` + * + * Note: The weird function signature is due to the fact that, for historical reasons, + * the function also accepts separate arguments as an alternative to the options object. + * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED. + */ + scrollTo( + options?: + | { + x?: number, + y?: number, + animated?: boolean, + ... + } + | number, + deprecatedX?: number, + deprecatedAnimated?: boolean, + ) { + let x, y, animated; + if (typeof options === 'number') { + console.warn( + '`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, ' + + 'animated: true})` instead.', + ); + y = options; + x = deprecatedX; + animated = deprecatedAnimated; + } else if (options) { + y = options.y; + x = options.x; + animated = options.animated; + } + this._scrollResponder.scrollResponderScrollTo({ + x: x || 0, + y: y || 0, + animated: animated !== false, + }); + } + + /** + * If this is a vertical ScrollView scrolls to the bottom. + * If this is a horizontal ScrollView scrolls to the right. + * + * Use `scrollToEnd({animated: true})` for smooth animated scrolling, + * `scrollToEnd({animated: false})` for immediate scrolling. + * If no options are passed, `animated` defaults to true. + */ + scrollToEnd(options?: ?{animated?: boolean, ...}) { + // Default to true + const animated = (options && options.animated) !== false; + this._scrollResponder.scrollResponderScrollToEnd({ + animated: animated, + }); + } + + /** + * Displays the scroll indicators momentarily. + * + * @platform ios + */ + flashScrollIndicators() { + this._scrollResponder.scrollResponderFlashScrollIndicators(); + } + + _getKeyForIndex(index, childArray) { + const child = childArray[index]; + return child && child.key; + } + + _updateAnimatedNodeAttachment() { + if (this._scrollAnimatedValueAttachment) { + this._scrollAnimatedValueAttachment.detach(); + } + if ( + this.props.stickyHeaderIndices && + this.props.stickyHeaderIndices.length > 0 + ) { + this._scrollAnimatedValueAttachment = AnimatedImplementation.attachNativeEvent( + this._scrollViewRef, + 'onScroll', + [{nativeEvent: {contentOffset: {y: this._scrollAnimatedValue}}}], + ); + } + } + + _setStickyHeaderRef( + key: string, + ref: ?React.ElementRef, + ) { + if (ref) { + this._stickyHeaderRefs.set(key, ref); + } else { + this._stickyHeaderRefs.delete(key); + } + } + + _onStickyHeaderLayout(index, event, key) { + const {stickyHeaderIndices} = this.props; + if (!stickyHeaderIndices) { + return; + } + const childArray = React.Children.toArray(this.props.children); + if (key !== this._getKeyForIndex(index, childArray)) { + // ignore stale layout update + return; + } + + const layoutY = event.nativeEvent.layout.y; + this._headerLayoutYs.set(key, layoutY); + + const indexOfIndex = stickyHeaderIndices.indexOf(index); + const previousHeaderIndex = stickyHeaderIndices[indexOfIndex - 1]; + if (previousHeaderIndex != null) { + const previousHeader = this._stickyHeaderRefs.get( + this._getKeyForIndex(previousHeaderIndex, childArray), + ); + previousHeader && + previousHeader.setNextHeaderY && + previousHeader.setNextHeaderY(layoutY); + } + } + + _handleScroll = (e: ScrollEvent) => { + if (__DEV__) { + if ( + this.props.onScroll && + this.props.scrollEventThrottle == null && + Platform.OS === 'ios' + ) { + console.log( + 'You specified `onScroll` on a but not ' + + '`scrollEventThrottle`. You will only receive one event. ' + + 'Using `16` you get all the events but be aware that it may ' + + "cause frame drops, use a bigger number if you don't need as " + + 'much precision.', + ); + } + } + if (Platform.OS === 'android') { + if ( + this.props.keyboardDismissMode === 'on-drag' && + this.state.isTouching + ) { + dismissKeyboard(); + } + } + this._scrollResponder.scrollResponderHandleScroll(e); + }; + + _handleLayout = (e: LayoutEvent) => { + if (this.props.invertStickyHeaders === true) { + this.setState({layoutHeight: e.nativeEvent.layout.height}); + } + if (this.props.onLayout) { + this.props.onLayout(e); + } + }; + + _handleContentOnLayout = (e: LayoutEvent) => { + const {width, height} = e.nativeEvent.layout; + this.props.onContentSizeChange && + this.props.onContentSizeChange(width, height); + }; + + _scrollViewRef: ?React.ElementRef> = null; + _setScrollViewRef = (ref: ?React.ElementRef>) => { + this._scrollViewRef = ref; + }; + + _innerViewRef: ?React.ElementRef> = null; + _setInnerViewRef = (ref: ?React.ElementRef>) => { + this._innerViewRef = ref; + }; + + render(): React.Node | React.Element { + let ScrollViewClass; + let ScrollContentContainerViewClass; + if (Platform.OS === 'android') { + if (this.props.horizontal === true) { + ScrollViewClass = AndroidHorizontalScrollView; + ScrollContentContainerViewClass = AndroidHorizontalScrollContentView; + } else { + ScrollViewClass = AndroidScrollView; + ScrollContentContainerViewClass = View; + } + } else { + ScrollViewClass = RCTScrollView; + ScrollContentContainerViewClass = RCTScrollContentView; + } + + invariant( + ScrollViewClass !== undefined, + 'ScrollViewClass must not be undefined', + ); + + invariant( + ScrollContentContainerViewClass !== undefined, + 'ScrollContentContainerViewClass must not be undefined', + ); + + const contentContainerStyle = [ + this.props.horizontal === true && styles.contentContainerHorizontal, + this.props.contentContainerStyle, + ]; + if (__DEV__ && this.props.style !== undefined) { + const style = flattenStyle(this.props.style); + const childLayoutProps = ['alignItems', 'justifyContent'].filter( + prop => style && style[prop] !== undefined, + ); + invariant( + childLayoutProps.length === 0, + 'ScrollView child layout (' + + JSON.stringify(childLayoutProps) + + ') must be applied through the contentContainerStyle prop.', + ); + } + + let contentSizeChangeProps = {}; + if (this.props.onContentSizeChange) { + contentSizeChangeProps = { + onLayout: this._handleContentOnLayout, + }; + } + + const {stickyHeaderIndices} = this.props; + let children = this.props.children; + + if (stickyHeaderIndices != null && stickyHeaderIndices.length > 0) { + const childArray = React.Children.toArray(this.props.children); + + children = childArray.map((child, index) => { + const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1; + if (indexOfIndex > -1) { + const key = child.key; + const nextIndex = stickyHeaderIndices[indexOfIndex + 1]; + const StickyHeaderComponent = + this.props.StickyHeaderComponent || ScrollViewStickyHeader; + return ( + this._setStickyHeaderRef(key, ref)} + nextHeaderLayoutY={this._headerLayoutYs.get( + this._getKeyForIndex(nextIndex, childArray), + )} + onLayout={event => this._onStickyHeaderLayout(index, event, key)} + scrollAnimatedValue={this._scrollAnimatedValue} + inverted={this.props.invertStickyHeaders} + scrollViewHeight={this.state.layoutHeight}> + {child} + + ); + } else { + return child; + } + }); + } + children = ( + + {children} + + ); + + const hasStickyHeaders = + Array.isArray(stickyHeaderIndices) && stickyHeaderIndices.length > 0; + + const contentContainer = ( + /* $FlowFixMe(>=0.112.0 site=react_native_fb) This comment suppresses an + * error found when Flow v0.112 was deployed. To see the error, delete + * this comment and run Flow. */ + + {children} + + ); + + const alwaysBounceHorizontal = + this.props.alwaysBounceHorizontal !== undefined + ? this.props.alwaysBounceHorizontal + : this.props.horizontal; + + const alwaysBounceVertical = + this.props.alwaysBounceVertical !== undefined + ? this.props.alwaysBounceVertical + : !this.props.horizontal; + + const DEPRECATED_sendUpdatedChildFrames = !!this.props + .DEPRECATED_sendUpdatedChildFrames; + + const baseStyle = + this.props.horizontal === true + ? styles.baseHorizontal + : styles.baseVertical; + const props = { + ...this.props, + alwaysBounceHorizontal, + alwaysBounceVertical, + style: [baseStyle, this.props.style], + // Override the onContentSizeChange from props, since this event can + // bubble up from TextInputs + onContentSizeChange: null, + onLayout: this._handleLayout, + onMomentumScrollBegin: this._scrollResponder + .scrollResponderHandleMomentumScrollBegin, + onMomentumScrollEnd: this._scrollResponder + .scrollResponderHandleMomentumScrollEnd, + onResponderGrant: this._scrollResponder + .scrollResponderHandleResponderGrant, + onResponderReject: this._scrollResponder + .scrollResponderHandleResponderReject, + onResponderRelease: this._scrollResponder + .scrollResponderHandleResponderRelease, + onResponderTerminationRequest: this._scrollResponder + .scrollResponderHandleTerminationRequest, + onScrollBeginDrag: this._scrollResponder + .scrollResponderHandleScrollBeginDrag, + onScrollEndDrag: this._scrollResponder.scrollResponderHandleScrollEndDrag, + onScrollShouldSetResponder: this._scrollResponder + .scrollResponderHandleScrollShouldSetResponder, + onStartShouldSetResponder: this._scrollResponder + .scrollResponderHandleStartShouldSetResponder, + onStartShouldSetResponderCapture: this._scrollResponder + .scrollResponderHandleStartShouldSetResponderCapture, + onTouchEnd: this._scrollResponder.scrollResponderHandleTouchEnd, + onTouchMove: this._scrollResponder.scrollResponderHandleTouchMove, + onTouchStart: this._scrollResponder.scrollResponderHandleTouchStart, + onTouchCancel: this._scrollResponder.scrollResponderHandleTouchCancel, + onScroll: this._handleScroll, + scrollBarThumbImage: resolveAssetSource(this.props.scrollBarThumbImage), + scrollEventThrottle: hasStickyHeaders + ? 1 + : this.props.scrollEventThrottle, + sendMomentumEvents: + this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd + ? true + : false, + DEPRECATED_sendUpdatedChildFrames, + // default to true + snapToStart: this.props.snapToStart !== false, + // default to true + snapToEnd: this.props.snapToEnd !== false, + // pagingEnabled is overridden by snapToInterval / snapToOffsets + pagingEnabled: Platform.select({ + // on iOS, pagingEnabled must be set to false to have snapToInterval / snapToOffsets work + ios: + this.props.pagingEnabled === true && + this.props.snapToInterval == null && + this.props.snapToOffsets == null, + // on Android, pagingEnabled must be set to true to have snapToInterval / snapToOffsets work + android: + this.props.pagingEnabled === true || + this.props.snapToInterval != null || + this.props.snapToOffsets != null, + }), + }; + + const {decelerationRate} = this.props; + if (decelerationRate != null) { + props.decelerationRate = processDecelerationRate(decelerationRate); + } + + const refreshControl = this.props.refreshControl; + + if (refreshControl) { + if (Platform.OS === 'ios') { + // On iOS the RefreshControl is a child of the ScrollView. + // tvOS lacks native support for RefreshControl, so don't include it in that case + return ( + + {Platform.isTV ? null : refreshControl} + {contentContainer} + + ); + } else if (Platform.OS === 'android') { + // On Android wrap the ScrollView with a AndroidSwipeRefreshLayout. + // Since the ScrollView is wrapped add the style props to the + // AndroidSwipeRefreshLayout and use flex: 1 for the ScrollView. + // Note: we should split props.style on the inner and outer props + // however, the ScrollView still needs the baseStyle to be scrollable + const {outer, inner} = splitLayoutProps(flattenStyle(props.style)); + return React.cloneElement( + refreshControl, + {style: [baseStyle, outer]}, + + {contentContainer} + , + ); + } + } + return ( + + {contentContainer} + + ); + } +} + +const styles = StyleSheet.create({ + baseVertical: { + flexGrow: 1, + flexShrink: 1, + flexDirection: 'column', + overflow: 'scroll', + }, + baseHorizontal: { + flexGrow: 1, + flexShrink: 1, + flexDirection: 'row', + overflow: 'scroll', + }, + contentContainerHorizontal: { + flexDirection: 'row', + }, +}); + +module.exports = ScrollView; diff --git a/packages/react-native-dom/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js b/packages/react-native-dom/src/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js similarity index 84% rename from packages/react-native-dom/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js rename to packages/react-native-dom/src/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js index 5c43fbf54..67c5c2d56 100644 --- a/packages/react-native-dom/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js +++ b/packages/react-native-dom/src/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.dom.js @@ -11,4 +11,4 @@ "use strict"; -module.exports = require("UnimplementedView"); +module.exports = require('../UnimplementedViews/UnimplementedView'); diff --git a/packages/react-native-dom/src/Libraries/Components/TextInput/TextInput.dom.js b/packages/react-native-dom/src/Libraries/Components/TextInput/TextInput.dom.js new file mode 100644 index 000000000..de1c11f35 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Components/TextInput/TextInput.dom.js @@ -0,0 +1,1173 @@ +/** + * 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 + */ + +'use strict'; + +const DeprecatedTextInputPropTypes = require('../../DeprecatedPropTypes/DeprecatedTextInputPropTypes'); +const Platform = require('../../Utilities/Platform'); +const React = require('react'); +const ReactNative = require('../../Renderer/shims/ReactNative'); +const StyleSheet = require('../../StyleSheet/StyleSheet'); +const Text = require('../../Text/Text'); +const TextAncestor = require('../../Text/TextAncestor'); +const TextInputState = require('./TextInputState'); +const TouchableWithoutFeedback = require('../Touchable/TouchableWithoutFeedback'); + +const invariant = require('invariant'); +const nullthrows = require('nullthrows'); +const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); +const setAndForwardRef = require('../../Utilities/setAndForwardRef'); + +import type {TextStyleProp, ViewStyleProp} from '../../StyleSheet/StyleSheet'; +import type {ColorValue} from '../../StyleSheet/StyleSheetTypes'; +import type {ViewProps} from '../View/ViewPropTypes'; +import type {SyntheticEvent, ScrollEvent} from '../../Types/CoreEventTypes'; +import type {PressEvent} from '../../Types/CoreEventTypes'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; + +const {useEffect, useRef, useState} = React; + +type ReactRefSetter = {current: null | T, ...} | ((ref: null | T) => mixed); + +let AndroidTextInput; +let RCTMultilineTextInputView; +let RCTSinglelineTextInputView; + +if (Platform.OS === 'android') { + AndroidTextInput = require('./AndroidTextInputNativeComponent').default; +} else if (Platform.OS === 'ios') { + RCTMultilineTextInputView = requireNativeComponent( + 'RCTMultilineTextInputView', + ); + RCTSinglelineTextInputView = requireNativeComponent( + 'RCTSinglelineTextInputView', + ); +} else if (Platform.OS === 'dom') { + RCTSinglelineTextInputView = RCTMultilineTextInputView = requireNativeComponent( + 'RCTTextInput', + ); +} + +export type ChangeEvent = SyntheticEvent< + $ReadOnly<{| + eventCount: number, + target: number, + text: string, + |}>, +>; + +export type TextInputEvent = SyntheticEvent< + $ReadOnly<{| + eventCount: number, + previousText: string, + range: $ReadOnly<{| + start: number, + end: number, + |}>, + target: number, + text: string, + |}>, +>; + +export type ContentSizeChangeEvent = SyntheticEvent< + $ReadOnly<{| + target: number, + contentSize: $ReadOnly<{| + width: number, + height: number, + |}>, + |}>, +>; + +type TargetEvent = SyntheticEvent< + $ReadOnly<{| + target: number, + |}>, +>; + +export type BlurEvent = TargetEvent; +export type FocusEvent = TargetEvent; + +type Selection = $ReadOnly<{| + start: number, + end: number, +|}>; + +export type SelectionChangeEvent = SyntheticEvent< + $ReadOnly<{| + selection: Selection, + target: number, + |}>, +>; + +export type KeyPressEvent = SyntheticEvent< + $ReadOnly<{| + key: string, + target?: ?number, + eventCount?: ?number, + |}>, +>; + +export type EditingEvent = SyntheticEvent< + $ReadOnly<{| + eventCount: number, + text: string, + target: number, + |}>, +>; + +type DataDetectorTypesType = + | 'phoneNumber' + | 'link' + | 'address' + | 'calendarEvent' + | 'none' + | 'all'; + +export type KeyboardType = + // Cross Platform + | 'default' + | 'email-address' + | 'numeric' + | 'phone-pad' + | 'number-pad' + | 'decimal-pad' + // iOS-only + | 'ascii-capable' + | 'numbers-and-punctuation' + | 'url' + | 'name-phone-pad' + | 'twitter' + | 'web-search' + // iOS 10+ only + | 'ascii-capable-number-pad' + // Android-only + | 'visible-password'; + +export type ReturnKeyType = + // Cross Platform + | 'done' + | 'go' + | 'next' + | 'search' + | 'send' + // Android-only + | 'none' + | 'previous' + // iOS-only + | 'default' + | 'emergency-call' + | 'google' + | 'join' + | 'route' + | 'yahoo'; + +export type AutoCapitalize = 'none' | 'sentences' | 'words' | 'characters'; + +export type TextContentType = + | 'none' + | 'URL' + | 'addressCity' + | 'addressCityAndState' + | 'addressState' + | 'countryName' + | 'creditCardNumber' + | 'emailAddress' + | 'familyName' + | 'fullStreetAddress' + | 'givenName' + | 'jobTitle' + | 'location' + | 'middleName' + | 'name' + | 'namePrefix' + | 'nameSuffix' + | 'nickname' + | 'organizationName' + | 'postalCode' + | 'streetAddressLine1' + | 'streetAddressLine2' + | 'sublocality' + | 'telephoneNumber' + | 'username' + | 'password' + | 'newPassword' + | 'oneTimeCode'; + +type PasswordRules = string; + +type IOSProps = $ReadOnly<{| + /** + * If `false`, disables spell-check style (i.e. red underlines). + * The default value is inherited from `autoCorrect`. + * @platform ios + */ + spellCheck?: ?boolean, + + /** + * Determines the color of the keyboard. + * @platform ios + */ + keyboardAppearance?: ?('default' | 'light' | 'dark'), + + /** + * If `true`, the keyboard disables the return key when there is no text and + * automatically enables it when there is text. The default value is `false`. + * @platform ios + */ + enablesReturnKeyAutomatically?: ?boolean, + + /** + * When the clear button should appear on the right side of the text view. + * This property is supported only for single-line TextInput component. + * @platform ios + */ + clearButtonMode?: ?('never' | 'while-editing' | 'unless-editing' | 'always'), + + /** + * If `true`, clears the text field automatically when editing begins. + * @platform ios + */ + clearTextOnFocus?: ?boolean, + + /** + * Determines the types of data converted to clickable URLs in the text input. + * Only valid if `multiline={true}` and `editable={false}`. + * By default no data types are detected. + * + * You can provide one type or an array of many types. + * + * Possible values for `dataDetectorTypes` are: + * + * - `'phoneNumber'` + * - `'link'` + * - `'address'` + * - `'calendarEvent'` + * - `'none'` + * - `'all'` + * + * @platform ios + */ + dataDetectorTypes?: + | ?DataDetectorTypesType + | $ReadOnlyArray, + + /** + * An optional identifier which links a custom InputAccessoryView to + * this text input. The InputAccessoryView is rendered above the + * keyboard when this text input is focused. + * @platform ios + */ + inputAccessoryViewID?: ?string, + + /** + * Give the keyboard and the system information about the + * expected semantic meaning for the content that users enter. + * @platform ios + */ + textContentType?: ?TextContentType, + + PasswordRules?: ?PasswordRules, + + /* + * @platform ios + */ + rejectResponderTermination?: ?boolean, + + /** + * If `false`, scrolling of the text view will be disabled. + * The default value is `true`. Does only work with 'multiline={true}'. + * @platform ios + */ + scrollEnabled?: ?boolean, +|}>; + +type AndroidProps = $ReadOnly<{| + /** + * Determines which content to suggest on auto complete, e.g.`username`. + * To disable auto complete, use `off`. + * + * *Android Only* + * + * The following values work on Android only: + * + * - `username` + * - `password` + * - `email` + * - `name` + * - `tel` + * - `street-address` + * - `postal-code` + * - `cc-number` + * - `cc-csc` + * - `cc-exp` + * - `cc-exp-month` + * - `cc-exp-year` + * - `off` + * + * @platform android + */ + autoCompleteType?: ?( + | 'cc-csc' + | 'cc-exp' + | 'cc-exp-month' + | 'cc-exp-year' + | 'cc-number' + | 'email' + | 'name' + | 'password' + | 'postal-code' + | 'street-address' + | 'tel' + | 'username' + | 'off' + ), + + /** + * Sets the return key to the label. Use it instead of `returnKeyType`. + * @platform android + */ + returnKeyLabel?: ?string, + + /** + * Sets the number of lines for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. + * @platform android + */ + numberOfLines?: ?number, + + /** + * When `false`, if there is a small amount of space available around a text input + * (e.g. landscape orientation on a phone), the OS may choose to have the user edit + * the text inside of a full screen text input mode. When `true`, this feature is + * disabled and users will always edit the text directly inside of the text input. + * Defaults to `false`. + * @platform android + */ + disableFullscreenUI?: ?boolean, + + /** + * Set text break strategy on Android API Level 23+, possible values are `simple`, `highQuality`, `balanced` + * The default value is `simple`. + * @platform android + */ + textBreakStrategy?: ?('simple' | 'highQuality' | 'balanced'), + + /** + * The color of the `TextInput` underline. + * @platform android + */ + underlineColorAndroid?: ?ColorValue, + + /** + * If defined, the provided image resource will be rendered on the left. + * The image resource must be inside `/android/app/src/main/res/drawable` and referenced + * like + * ``` + * + * ``` + * @platform android + */ + inlineImageLeft?: ?string, + + /** + * Padding between the inline image, if any, and the text input itself. + * @platform android + */ + inlineImagePadding?: ?number, + + importantForAutofill?: ?( + | 'auto' + | 'no' + | 'noExcludeDescendants' + | 'yes' + | 'yesExcludeDescendants' + ), + + /** + * When `false`, it will prevent the soft keyboard from showing when the field is focused. + * Defaults to `true`. + * @platform android + */ + showSoftInputOnFocus?: ?boolean, +|}>; + +export type Props = $ReadOnly<{| + ...$Diff>, + ...IOSProps, + ...AndroidProps, + + /** + * Can tell `TextInput` to automatically capitalize certain characters. + * + * - `characters`: all characters. + * - `words`: first letter of each word. + * - `sentences`: first letter of each sentence (*default*). + * - `none`: don't auto capitalize anything. + */ + autoCapitalize?: ?AutoCapitalize, + + /** + * If `false`, disables auto-correct. The default value is `true`. + */ + autoCorrect?: ?boolean, + + /** + * If `true`, focuses the input on `componentDidMount`. + * The default value is `false`. + */ + autoFocus?: ?boolean, + + /** + * Specifies whether fonts should scale to respect Text Size accessibility settings. The + * default is `true`. + */ + allowFontScaling?: ?boolean, + + /** + * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. + * Possible values: + * `null/undefined` (default): inherit from the parent node or the global default (0) + * `0`: no max, ignore parent/global default + * `>= 1`: sets the maxFontSizeMultiplier of this node to this value + */ + maxFontSizeMultiplier?: ?number, + + /** + * If `false`, text is not editable. The default value is `true`. + */ + editable?: ?boolean, + + /** + * Determines which keyboard to open, e.g.`numeric`. + * + * The following values work across platforms: + * + * - `default` + * - `numeric` + * - `number-pad` + * - `decimal-pad` + * - `email-address` + * - `phone-pad` + * + * *iOS Only* + * + * The following values work on iOS only: + * + * - `ascii-capable` + * - `numbers-and-punctuation` + * - `url` + * - `name-phone-pad` + * - `twitter` + * - `web-search` + * + * *Android Only* + * + * The following values work on Android only: + * + * - `visible-password` + */ + keyboardType?: ?KeyboardType, + + /** + * Determines how the return key should look. On Android you can also use + * `returnKeyLabel`. + * + * *Cross platform* + * + * The following values work across platforms: + * + * - `done` + * - `go` + * - `next` + * - `search` + * - `send` + * + * *Android Only* + * + * The following values work on Android only: + * + * - `none` + * - `previous` + * + * *iOS Only* + * + * The following values work on iOS only: + * + * - `default` + * - `emergency-call` + * - `google` + * - `join` + * - `route` + * - `yahoo` + */ + returnKeyType?: ?ReturnKeyType, + + /** + * Limits the maximum number of characters that can be entered. Use this + * instead of implementing the logic in JS to avoid flicker. + */ + maxLength?: ?number, + + /** + * If `true`, the text input can be multiple lines. + * The default value is `false`. + */ + multiline?: ?boolean, + + /** + * Callback that is called when the text input is blurred. + */ + onBlur?: ?(e: BlurEvent) => mixed, + + /** + * Callback that is called when the text input is focused. + */ + onFocus?: ?(e: FocusEvent) => mixed, + + /** + * Callback that is called when the text input's text changes. + */ + onChange?: ?(e: ChangeEvent) => mixed, + + /** + * Callback that is called when the text input's text changes. + * Changed text is passed as an argument to the callback handler. + */ + onChangeText?: ?(text: string) => mixed, + + /** + * Callback that is called when the text input's content size changes. + * This will be called with + * `{ nativeEvent: { contentSize: { width, height } } }`. + * + * Only called for multiline text inputs. + */ + onContentSizeChange?: ?(e: ContentSizeChangeEvent) => mixed, + + /** + * Callback that is called when text input ends. + */ + onEndEditing?: ?(e: EditingEvent) => mixed, + + /** + * Callback that is called when the text input selection is changed. + * This will be called with + * `{ nativeEvent: { selection: { start, end } } }`. + */ + onSelectionChange?: ?(e: SelectionChangeEvent) => mixed, + + /** + * Callback that is called when the text input's submit button is pressed. + * Invalid if `multiline={true}` is specified. + */ + onSubmitEditing?: ?(e: EditingEvent) => mixed, + + /** + * Callback that is called when a key is pressed. + * This will be called with `{ nativeEvent: { key: keyValue } }` + * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and + * the typed-in character otherwise including `' '` for space. + * Fires before `onChange` callbacks. + */ + onKeyPress?: ?(e: KeyPressEvent) => mixed, + + /** + * Invoked on content scroll with `{ nativeEvent: { contentOffset: { x, y } } }`. + * May also contain other properties from ScrollEvent but on Android contentSize + * is not provided for performance reasons. + */ + onScroll?: ?(e: ScrollEvent) => mixed, + + /** + * The string that will be rendered before text input has been entered. + */ + placeholder?: ?Stringish, + + /** + * The text color of the placeholder string. + */ + placeholderTextColor?: ?ColorValue, + + /** + * If `true`, the text input obscures the text entered so that sensitive text + * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'. + */ + secureTextEntry?: ?boolean, + + /** + * The highlight and cursor color of the text input. + */ + selectionColor?: ?ColorValue, + + /** + * The start and end of the text input's selection. Set start and end to + * the same value to position the cursor. + */ + selection?: ?$ReadOnly<{| + start: number, + end?: ?number, + |}>, + + /** + * The value to show for the text input. `TextInput` is a controlled + * component, which means the native value will be forced to match this + * value prop if provided. For most uses, this works great, but in some + * cases this may cause flickering - one common cause is preventing edits + * by keeping value the same. In addition to simply setting the same value, + * either set `editable={false}`, or set/update `maxLength` to prevent + * unwanted edits without flicker. + */ + value?: ?Stringish, + + /** + * Provides an initial value that will change when the user starts typing. + * Useful for simple use-cases where you do not want to deal with listening + * to events and updating the value prop to keep the controlled state in sync. + */ + defaultValue?: ?Stringish, + + /** + * If `true`, all text will automatically be selected on focus. + */ + selectTextOnFocus?: ?boolean, + + /** + * If `true`, the text field will blur when submitted. + * The default value is true for single-line fields and false for + * multiline fields. Note that for multiline fields, setting `blurOnSubmit` + * to `true` means that pressing return will blur the field and trigger the + * `onSubmitEditing` event instead of inserting a newline into the field. + */ + blurOnSubmit?: ?boolean, + + /** + * Note that not all Text styles are supported, an incomplete list of what is not supported includes: + * + * - `borderLeftWidth` + * - `borderTopWidth` + * - `borderRightWidth` + * - `borderBottomWidth` + * - `borderTopLeftRadius` + * - `borderTopRightRadius` + * - `borderBottomRightRadius` + * - `borderBottomLeftRadius` + * + * see [Issue#7070](https://github.com/facebook/react-native/issues/7070) + * for more detail. + * + * [Styles](docs/style.html) + */ + style?: ?TextStyleProp, + + /** + * If `true`, caret is hidden. The default value is `false`. + * This property is supported only for single-line TextInput component on iOS. + */ + caretHidden?: ?boolean, + + /* + * If `true`, contextMenuHidden is hidden. The default value is `false`. + */ + contextMenuHidden?: ?boolean, + + forwardedRef?: ?ReactRefSetter< + React.ElementRef> & ImperativeMethods, + >, +|}>; + +type ImperativeMethods = $ReadOnly<{| + clear: () => void, + isFocused: () => boolean, + getNativeRef: () => ?React.ElementRef>, +|}>; + +const emptyFunctionThatReturnsTrue = () => true; + +function useFocusOnMount( + initialAutoFocus: ?boolean, + inputRef: {| + current: null | React.ElementRef>, + |}, +) { + const initialAutoFocusValue = useRef(initialAutoFocus); + + useEffect(() => { + // We only want to autofocus on initial mount. + // Since initialAutoFocusValue and inputRef will never change + // this should match the expected behavior + if (initialAutoFocusValue.current) { + const focus = () => { + if (inputRef.current != null) { + inputRef.current.focus(); + } + }; + + let rafId; + if (Platform.OS === 'android') { + // On Android this needs to be executed in a rAF callback + // otherwise the keyboard opens then closes immediately. + rafId = requestAnimationFrame(focus); + } else { + focus(); + } + + return () => { + if (rafId != null) { + cancelAnimationFrame(rafId); + } + }; + } + }, [initialAutoFocusValue, inputRef]); +} +/** + * A foundational component for inputting text into the app via a + * keyboard. Props provide configurability for several features, such as + * auto-correction, auto-capitalization, placeholder text, and different keyboard + * types, such as a numeric keypad. + * + * The simplest use case is to plop down a `TextInput` and subscribe to the + * `onChangeText` events to read the user input. There are also other events, + * such as `onSubmitEditing` and `onFocus` that can be subscribed to. A simple + * example: + * + * ```ReactNativeWebPlayer + * import React, { Component } from 'react'; + * import { AppRegistry, TextInput } from 'react-native'; + * + * export default class UselessTextInput extends Component { + * constructor(props) { + * super(props); + * this.state = { text: 'Useless Placeholder' }; + * } + * + * render() { + * return ( + * this.setState({text})} + * value={this.state.text} + * /> + * ); + * } + * } + * + * // skip this line if using Create React Native App + * AppRegistry.registerComponent('AwesomeProject', () => UselessTextInput); + * ``` + * + * Two methods exposed via the native element are .focus() and .blur() that + * will focus or blur the TextInput programmatically. + * + * Note that some props are only available with `multiline={true/false}`. + * Additionally, border styles that apply to only one side of the element + * (e.g., `borderBottomColor`, `borderLeftWidth`, etc.) will not be applied if + * `multiline=false`. To achieve the same effect, you can wrap your `TextInput` + * in a `View`: + * + * ```ReactNativeWebPlayer + * import React, { Component } from 'react'; + * import { AppRegistry, View, TextInput } from 'react-native'; + * + * class UselessTextInput extends Component { + * render() { + * return ( + * + * ); + * } + * } + * + * export default class UselessTextInputMultiline extends Component { + * constructor(props) { + * super(props); + * this.state = { + * text: 'Useless Multiline Placeholder', + * }; + * } + * + * // If you type something in the text box that is a color, the background will change to that + * // color. + * render() { + * return ( + * + * this.setState({text})} + * value={this.state.text} + * /> + * + * ); + * } + * } + * + * // skip these lines if using Create React Native App + * AppRegistry.registerComponent( + * 'AwesomeProject', + * () => UselessTextInputMultiline + * ); + * ``` + * + * `TextInput` has by default a border at the bottom of its view. This border + * has its padding set by the background image provided by the system, and it + * cannot be changed. Solutions to avoid this is to either not set height + * explicitly, case in which the system will take care of displaying the border + * in the correct position, or to not display the border by setting + * `underlineColorAndroid` to transparent. + * + * Note that on Android performing text selection in input can change + * app's activity `windowSoftInputMode` param to `adjustResize`. + * This may cause issues with components that have position: 'absolute' + * while keyboard is active. To avoid this behavior either specify `windowSoftInputMode` + * in AndroidManifest.xml ( https://developer.android.com/guide/topics/manifest/activity-element.html ) + * or control this param programmatically with native code. + * + */ +function InternalTextInput(props: Props): React.Node { + const inputRef = useRef>>(null); + + const selection: ?Selection = + props.selection == null + ? null + : { + start: props.selection.start, + end: props.selection.end ?? props.selection.start, + }; + + const [lastNativeText, setLastNativeText] = useState(props.value); + const [lastNativeSelection, setLastNativeSelection] = useState( + selection, + ); + + // This is necessary in case native updates the text and JS decides + // that the update should be ignored and we should stick with the value + // that we have in JS. + useEffect(() => { + const nativeUpdate = {}; + + if (lastNativeText !== props.value && typeof props.value === 'string') { + nativeUpdate.text = props.value; + setLastNativeText(props.value); + } + + if ( + selection && + lastNativeSelection && + (lastNativeSelection.start !== selection.start || + lastNativeSelection.end !== selection.end) + ) { + nativeUpdate.selection = selection; + setLastNativeSelection(selection); + } + + if (Object.keys(nativeUpdate).length > 0 && inputRef.current) { + inputRef.current.setNativeProps(nativeUpdate); + } + }, [inputRef, props.value, lastNativeText, selection, lastNativeSelection]); + + useFocusOnMount(props.autoFocus, inputRef); + + useEffect(() => { + const tag = ReactNative.findNodeHandle(inputRef.current); + if (tag != null) { + TextInputState.registerInput(tag); + + return () => { + TextInputState.unregisterInput(tag); + }; + } + }, [inputRef]); + + useEffect(() => { + // When unmounting we need to blur the input + return () => { + if (isFocused()) { + nullthrows(inputRef.current).blur(); + } + }; + }, [inputRef]); + + function clear(): void { + if (inputRef.current != null) { + inputRef.current.setNativeProps({text: ''}); + } + } + + // TODO: Fix this returning true on null === null, when no input is focused + function isFocused(): boolean { + return ( + TextInputState.currentlyFocusedField() === + ReactNative.findNodeHandle(inputRef.current) + ); + } + + function getNativeRef(): ?React.ElementRef> { + return inputRef.current; + } + + function _getText(): ?string { + return typeof props.value === 'string' + ? props.value + : typeof props.defaultValue === 'string' + ? props.defaultValue + : ''; + } + + const _setNativeRef = setAndForwardRef({ + getForwardedRef: () => props.forwardedRef, + setLocalRef: ref => { + inputRef.current = ref; + + /* + Hi reader from the future. I'm sorry for this. + + This is a hack. Ideally we would forwardRef to the underlying + host component. However, since TextInput has it's own methods that can be + called as well, if we used the standard forwardRef then these + methods wouldn't be accessible and thus be a breaking change. + + We have a couple of options of how to handle this: + - Return a new ref with everything we methods from both. This is problematic + because we need React to also know it is a host component which requires + internals of the class implementation of the ref. + - Break the API and have some other way to call one set of the methods or + the other. This is our long term approach as we want to eventually + get the methods on host components off the ref. So instead of calling + ref.measure() you might call ReactNative.measure(ref). This would hopefully + let the ref for TextInput then have the methods like `.clear`. Or we do it + the other way and make it TextInput.clear(textInputRef) which would be fine + too. Either way though is a breaking change that is longer term. + - Mutate this ref. :( Gross, but accomplishes what we need in the meantime + before we can get to the long term breaking change. + */ + if (ref) { + ref.clear = clear; + ref.isFocused = isFocused; + ref.getNativeRef = getNativeRef; + } + }, + }); + + const _onPress = (event: PressEvent) => { + if (props.editable || props.editable === undefined) { + nullthrows(inputRef.current).focus(); + } + }; + + const _onChange = (event: ChangeEvent) => { + // Make sure to fire the mostRecentEventCount first so it is already set on + // native when the text value is set. + if (inputRef.current) { + inputRef.current.setNativeProps({ + mostRecentEventCount: event.nativeEvent.eventCount, + }); + } + + const text = event.nativeEvent.text; + props.onChange && props.onChange(event); + props.onChangeText && props.onChangeText(text); + + if (!inputRef.current) { + // calling `props.onChange` or `props.onChangeText` + // may clean up the input itself. Exits here. + return; + } + + setLastNativeText(text); + }; + + const _onSelectionChange = (event: SelectionChangeEvent) => { + props.onSelectionChange && props.onSelectionChange(event); + + if (!inputRef.current) { + // calling `props.onSelectionChange` + // may clean up the input itself. Exits here. + return; + } + + setLastNativeSelection(event.nativeEvent.selection); + }; + + const _onFocus = (event: FocusEvent) => { + TextInputState.focusField(ReactNative.findNodeHandle(inputRef.current)); + if (props.onFocus) { + props.onFocus(event); + } + }; + + const _onBlur = (event: BlurEvent) => { + TextInputState.blurField(ReactNative.findNodeHandle(inputRef.current)); + if (props.onBlur) { + props.onBlur(event); + } + }; + + const _onScroll = (event: ScrollEvent) => { + props.onScroll && props.onScroll(event); + }; + + let textInput = null; + let additionalTouchableProps: {| + rejectResponderTermination?: $PropertyType< + Props, + 'rejectResponderTermination', + >, + // This is a hack to let Flow know we want an exact object + |} = {...null}; + + if (Platform.OS === 'ios' || Platform.OS === 'dom') { + const RCTTextInputView = props.multiline + ? RCTMultilineTextInputView + : RCTSinglelineTextInputView; + + const style = props.multiline + ? [styles.multilineInput, props.style] + : props.style; + + additionalTouchableProps.rejectResponderTermination = + props.rejectResponderTermination; + + textInput = ( + + ); + } else if (Platform.OS === 'android') { + const style = [props.style]; + const autoCapitalize = props.autoCapitalize || 'sentences'; + let children = props.children; + let childCount = 0; + React.Children.forEach(children, () => ++childCount); + invariant( + !(props.value && childCount), + 'Cannot specify both value and children.', + ); + if (childCount > 1) { + children = {children}; + } + + textInput = ( + /* $FlowFixMe the types for AndroidTextInput don't match up exactly with + the props for TextInput. This will need to get fixed */ + + ); + } + return ( + + + {textInput} + + + ); +} + +const ExportedForwardRef: React.AbstractComponent< + React.ElementConfig, + React.ElementRef> & ImperativeMethods, +> = React.forwardRef(function TextInput( + props, + forwardedRef: ReactRefSetter< + React.ElementRef> & ImperativeMethods, + >, +) { + return ; +}); + +// $FlowFixMe +ExportedForwardRef.defaultProps = { + allowFontScaling: true, + rejectResponderTermination: true, + underlineColorAndroid: 'transparent', +}; + +// TODO: Deprecate this +// $FlowFixMe +ExportedForwardRef.propTypes = DeprecatedTextInputPropTypes; + +// $FlowFixMe +ExportedForwardRef.State = { + currentlyFocusedField: TextInputState.currentlyFocusedField, + focusTextInput: TextInputState.focusTextInput, + blurTextInput: TextInputState.blurTextInput, +}; + +type TextInputComponentStatics = $ReadOnly<{| + State: $ReadOnly<{| + currentlyFocusedField: typeof TextInputState.currentlyFocusedField, + focusTextInput: typeof TextInputState.focusTextInput, + blurTextInput: typeof TextInputState.blurTextInput, + |}>, + propTypes: typeof DeprecatedTextInputPropTypes, +|}>; + +const styles = StyleSheet.create({ + multilineInput: { + // This default top inset makes RCTMultilineTextInputView seem as close as possible + // to single-line RCTSinglelineTextInputView defaults, using the system defaults + // of font size 17 and a height of 31 points. + paddingTop: 5, + }, +}); + +module.exports = ((ExportedForwardRef: any): React.AbstractComponent< + React.ElementConfig, + $ReadOnly<{| + ...React.ElementRef>, + ...ImperativeMethods, + |}>, +> & + TextInputComponentStatics); diff --git a/packages/react-native-dom/Libraries/Components/ToastAndroid/ToastAndroid.dom.js b/packages/react-native-dom/src/Libraries/Components/ToastAndroid/ToastAndroid.dom.js similarity index 100% rename from packages/react-native-dom/Libraries/Components/ToastAndroid/ToastAndroid.dom.js rename to packages/react-native-dom/src/Libraries/Components/ToastAndroid/ToastAndroid.dom.js diff --git a/packages/react-native-dom/src/Libraries/Components/View/ViewNativeComponent.dom.js b/packages/react-native-dom/src/Libraries/Components/View/ViewNativeComponent.dom.js new file mode 100644 index 000000000..dc9b1941b --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Components/View/ViewNativeComponent.dom.js @@ -0,0 +1,79 @@ +/** + * 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 Platform = require('../../Utilities/Platform'); +const ReactNativeViewViewConfigAndroid = require('./ReactNativeViewViewConfigAndroid'); + +const registerGeneratedViewConfig = require('../../Utilities/registerGeneratedViewConfig'); +const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); + +import * as React from 'react'; + +import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; +import type {ViewProps} from './ViewPropTypes'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; + +export type ViewNativeComponentType = HostComponent; + +let NativeViewComponent; +let viewConfig: + | {...} + | {| + bubblingEventTypes?: $ReadOnly<{ + [eventName: string]: $ReadOnly<{| + phasedRegistrationNames: $ReadOnly<{| + bubbled: string, + captured: string, + |}>, + |}>, + ..., + }>, + directEventTypes?: $ReadOnly<{ + [eventName: string]: $ReadOnly<{|registrationName: string|}>, + ..., + }>, + uiViewClassName: string, + validAttributes?: { + [propName: string]: + | true + | $ReadOnly<{| + diff?: (arg1: any, arg2: any) => boolean, + process?: (arg1: any) => any, + |}>, + ..., + }, + |}; +/** + * TODO: implement viewConfig attributes on native side and eliminate use of viewNativeComponent.dom.js file + * +*/ +NativeViewComponent = requireNativeComponent('RCTView'); + +export const __INTERNAL_VIEW_CONFIG = viewConfig; + +interface NativeCommands { + +hotspotUpdate: ( + viewRef: React.ElementRef>, + x: number, + y: number, + ) => void; + +setPressed: ( + viewRef: React.ElementRef>, + pressed: boolean, + ) => void; +} + +export const Commands: NativeCommands = codegenNativeCommands({ + supportedCommands: ['hotspotUpdate', 'setPressed'], +}); + +export default ((NativeViewComponent: any): ViewNativeComponentType); diff --git a/packages/react-native-dom/Libraries/EventEmitter/NativeEventEmitter.dom.js b/packages/react-native-dom/src/Libraries/EventEmitter/NativeEventEmitter.dom.js similarity index 67% rename from packages/react-native-dom/Libraries/EventEmitter/NativeEventEmitter.dom.js rename to packages/react-native-dom/src/Libraries/EventEmitter/NativeEventEmitter.dom.js index b3091cb46..0f7a58b7d 100644 --- a/packages/react-native-dom/Libraries/EventEmitter/NativeEventEmitter.dom.js +++ b/packages/react-native-dom/src/Libraries/EventEmitter/NativeEventEmitter.dom.js @@ -1,25 +1,27 @@ /** - * Copyright (c) 2015-present, Facebook, Inc. + * 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. * - * @providesModule NativeEventEmitter + * @format * @flow */ -"use strict"; -const EventEmitter = require("EventEmitter"); -const Platform = require("Platform"); -const RCTDeviceEventEmitter = require("RCTDeviceEventEmitter"); +'use strict'; -const invariant = require("fbjs/lib/invariant"); +const EventEmitter = require('../vendor/emitter/EventEmitter'); +const Platform = require('../Utilities/Platform'); +const RCTDeviceEventEmitter = require('./RCTDeviceEventEmitter'); -import type EmitterSubscription from "EmitterSubscription"; +const invariant = require('invariant'); + +import type EmitterSubscription from '../vendor/emitter/EmitterSubscription'; type NativeModule = { +addListener: (eventType: string) => void, - +removeListeners: (count: number) => void + +removeListeners: (count: number) => void, + ... }; /** @@ -31,8 +33,8 @@ class NativeEventEmitter extends EventEmitter { constructor(nativeModule: ?NativeModule) { super(RCTDeviceEventEmitter.sharedSubscriber); - if (Platform.OS === "ios" || Platform.OS === "dom") { - invariant(nativeModule, "Native module cannot be null."); + if (Platform.OS === 'ios' || Platform.OS === 'dom') { + invariant(nativeModule, 'Native module cannot be null.'); this._nativeModule = nativeModule; } } @@ -40,7 +42,7 @@ class NativeEventEmitter extends EventEmitter { addListener( eventType: string, listener: Function, - context: ?Object + context: ?Object, ): EmitterSubscription { if (this._nativeModule != null) { this._nativeModule.addListener(eventType); @@ -49,7 +51,7 @@ class NativeEventEmitter extends EventEmitter { } removeAllListeners(eventType: string) { - invariant(eventType, "eventType argument is required."); + invariant(eventType, 'eventType argument is required.'); const count = this.listeners(eventType).length; if (this._nativeModule != null) { this._nativeModule.removeListeners(count); diff --git a/packages/react-native-dom/src/Libraries/Image/Image.dom.js b/packages/react-native-dom/src/Libraries/Image/Image.dom.js new file mode 100644 index 000000000..28af89e5d --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Image/Image.dom.js @@ -0,0 +1,210 @@ +/** + * 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 + */ + +'use strict'; + +const DeprecatedImagePropType = require('../DeprecatedPropTypes/DeprecatedImagePropType'); +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 resolveAssetSource = require('./resolveAssetSource'); + +import type {ImageProps as ImagePropsType} from './ImageProps'; + +import type {ImageStyleProp} from '../StyleSheet/StyleSheet'; +import NativeImageLoaderDOM from './NativeImageLoaderDOM'; + +const RCTImageView = require('./ImageViewNativeComponent'); + +function getSize( + uri: string, + success: (width: number, height: number) => void, + failure?: (error: any) => void, +) { + NativeImageLoaderDOM.getSize(uri) + .then(([width, height]) => success(width, height)) + .catch( + failure || + function() { + console.warn('Failed to get size for image ' + uri); + }, + ); +} + +function getSizeWithHeaders( + uri: string, + headers: {[string]: string, ...}, + success: (width: number, height: number) => void, + failure?: (error: any) => void, +): any { + return NativeImageLoaderDOM.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): any { + return NativeImageLoaderDOM.prefetchImage(url); +} + +async function queryCache( + urls: Array, +): Promise<{[string]: 'memory' | 'disk' | 'disk/memory', ...}> { + return await NativeImageLoaderDOM.queryCache(urls); +} + +type ImageComponentStatics = $ReadOnly<{| + getSize: typeof getSize, + getSizeWithHeaders: typeof getSizeWithHeaders, + prefetch: typeof prefetch, + queryCache: typeof queryCache, + resolveAssetSource: typeof resolveAssetSource, + 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) => { + 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', + }, +}); + +module.exports = ((Image: any): React.AbstractComponent< + ImagePropsType, + React.ElementRef, +> & + ImageComponentStatics); diff --git a/packages/react-native-dom/src/Libraries/Image/NativeImageLoaderDOM.js b/packages/react-native-dom/src/Libraries/Image/NativeImageLoaderDOM.js new file mode 100644 index 000000000..842294d0a --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Image/NativeImageLoaderDOM.js @@ -0,0 +1,32 @@ +/** + * 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 + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {||}; + // Return [width, height] of image uri + +getSize: (uri: string) => Promise<$ReadOnlyArray>; + +getSizeWithHeaders: ( + uri: string, + headers: Object, + ) => Promise<{ + width: number, + height: number, + ... + }>; + +prefetchImage: (uri: string) => Promise; + +queryCache: (uris: Array) => Promise; +} + +export default (TurboModuleRegistry.getEnforcing('ImageLoader'): Spec); diff --git a/packages/react-native-dom/src/Libraries/Network/NativeNetworkingDOM.js b/packages/react-native-dom/src/Libraries/Network/NativeNetworkingDOM.js new file mode 100644 index 000000000..59b3da849 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Network/NativeNetworkingDOM.js @@ -0,0 +1,38 @@ +/** + * 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 + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +sendRequest: ( + query: {| + method: string, + url: string, + data: Object, + headers: Object, + responseType: string, + incrementalUpdates: boolean, + timeout: number, + withCredentials: boolean, + |}, + callback: (requestId: number) => void, + ) => void; + +abortRequest: (requestId: number) => void; + +clearCookies: (callback: (result: boolean) => void) => void; + + // RCTEventEmitter + +addListener: (eventName: string) => void; + +removeListeners: (count: number) => void; +} + +export default (TurboModuleRegistry.getEnforcing('Networking'): Spec); diff --git a/packages/react-native-dom/Libraries/Network/NetInfo.dom.js b/packages/react-native-dom/src/Libraries/Network/NetInfo.dom.js similarity index 100% rename from packages/react-native-dom/Libraries/Network/NetInfo.dom.js rename to packages/react-native-dom/src/Libraries/Network/NetInfo.dom.js diff --git a/packages/react-native-dom/src/Libraries/Network/RCTNetworking.dom.js b/packages/react-native-dom/src/Libraries/Network/RCTNetworking.dom.js new file mode 100644 index 000000000..715389ce6 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Network/RCTNetworking.dom.js @@ -0,0 +1,63 @@ +/** + * 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 NativeEventEmitter = require('../EventEmitter/NativeEventEmitter'); + +const convertRequestBody = require('./convertRequestBody'); + +import NativeNetworkingDOM from './NativeNetworkingDOM'; +import type {NativeResponseType} from './XMLHttpRequest'; +import type {RequestBody} from './convertRequestBody'; + +class RCTNetworking extends NativeEventEmitter { + constructor() { + super(NativeNetworkingDOM); + } + + sendRequest( + method: string, + trackingName: string, + url: string, + headers: Object, + data: RequestBody, + responseType: NativeResponseType, + incrementalUpdates: boolean, + timeout: number, + callback: (requestId: number) => void, + withCredentials: boolean, + ) { + const body = convertRequestBody(data); + NativeNetworkingDOM.sendRequest( + { + method, + url, + data: {...body, trackingName}, + headers, + responseType, + incrementalUpdates, + timeout, + withCredentials: false, + }, + callback, + ); + } + + abortRequest(requestId: number) { + NativeNetworkingDOM.abortRequest(requestId); + } + + clearCookies(callback: (result: boolean) => void) { + NativeNetworkingDOM.clearCookies(callback); + } +} + +module.exports = (new RCTNetworking(): RCTNetworking); diff --git a/packages/react-native-dom/Libraries/Settings/Settings.dom.js b/packages/react-native-dom/src/Libraries/Settings/Settings.dom.js similarity index 72% rename from packages/react-native-dom/Libraries/Settings/Settings.dom.js rename to packages/react-native-dom/src/Libraries/Settings/Settings.dom.js index 7b05b9158..36de066c9 100644 --- a/packages/react-native-dom/Libraries/Settings/Settings.dom.js +++ b/packages/react-native-dom/src/Libraries/Settings/Settings.dom.js @@ -13,21 +13,21 @@ var Settings = { get(key: string): mixed { - console.warn("Settings is not yet supported on Web"); + console.warn("Settings is not yet supported on Dom"); return null; }, set(settings: Object) { - console.warn("Settings is not yet supported on Web"); + console.warn("Settings is not yet supported on Dom"); }, watchKeys(keys: string | Array, callback: Function): number { - console.warn("Settings is not yet supported on Web"); + console.warn("Settings is not yet supported on Dom"); return -1; }, clearWatch(watchId: number) { - console.warn("Settings is not yet supported on Web"); + console.warn("Settings is not yet supported on Dom"); } }; diff --git a/packages/react-native-dom/src/Libraries/Utilities/BackHandler.dom.js b/packages/react-native-dom/src/Libraries/Utilities/BackHandler.dom.js new file mode 100644 index 000000000..ff2f1c862 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Utilities/BackHandler.dom.js @@ -0,0 +1,123 @@ +/** + * 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 + */ + +// On Apple TV, this implements back navigation using the TV remote's menu button. +// On iOS, this just implements a stub. + +'use strict'; + +const Platform = require('./Platform'); +const TVEventHandler = require('../Components/AppleTV/TVEventHandler'); + +type BackPressEventName = 'backPress' | 'hardwareBackPress'; + +function emptyFunction(): void {} + +/** + * Detect hardware button presses for back navigation. + * + * Android: Detect hardware back button presses, and programmatically invoke the default back button + * functionality to exit the app if there are no listeners or if none of the listeners return true. + * + * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented: + * programmatically disable menu button handling + * functionality to exit the app if there are no listeners or if none of the listeners return true.) + * + * iOS: Not applicable. + * + * The event subscriptions are called in reverse order (i.e. last registered subscription first), + * and if one subscription returns true then subscriptions registered earlier will not be called. + * + * Example: + * + * ```javascript + * BackHandler.addEventListener('hardwareBackPress', function() { + * // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here + * // Typically you would use the navigator here to go to the last state. + * + * if (!this.onMainScreen()) { + * this.goBack(); + * return true; + * } + * return false; + * }); + * ``` + */ +type TBackHandler = {| + +exitApp: () => void, + +addEventListener: ( + eventName: BackPressEventName, + handler: Function, + ) => {remove: () => void, ...}, + +removeEventListener: ( + eventName: BackPressEventName, + handler: Function, + ) => void, +|}; + +let BackHandler: TBackHandler; + +if (Platform.isTV) { + const _tvEventHandler = new TVEventHandler(); + const _backPressSubscriptions = new Set(); + + _tvEventHandler.enable(this, function(cmp, evt) { + if (evt && evt.eventType === 'menu') { + let invokeDefault = true; + const subscriptions = Array.from( + _backPressSubscriptions.values(), + ).reverse(); + + for (let i = 0; i < subscriptions.length; ++i) { + if (subscriptions[i]()) { + invokeDefault = false; + break; + } + } + + if (invokeDefault) { + BackHandler.exitApp(); + } + } + }); + + BackHandler = { + exitApp: emptyFunction, + + addEventListener: function( + eventName: BackPressEventName, + handler: Function, + ): {remove: () => void, ...} { + _backPressSubscriptions.add(handler); + return { + remove: () => BackHandler.removeEventListener(eventName, handler), + }; + }, + + removeEventListener: function( + eventName: BackPressEventName, + handler: Function, + ): void { + _backPressSubscriptions.delete(handler); + }, + }; +} else { + BackHandler = { + exitApp: emptyFunction, + addEventListener(_eventName: BackPressEventName, _handler: Function) { + return { + remove: emptyFunction, + }; + }, + removeEventListener(_eventName: BackPressEventName, _handler: Function) {}, + }; +} + +module.exports = BackHandler; diff --git a/packages/react-native-dom/src/Libraries/Utilities/LoadingView.dom.js b/packages/react-native-dom/src/Libraries/Utilities/LoadingView.dom.js new file mode 100644 index 000000000..e8f7d133f --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Utilities/LoadingView.dom.js @@ -0,0 +1,40 @@ +/** + * 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 strict-local + */ + +'use strict'; + +import processColor from '../StyleSheet/processColor'; +import NativeDevLoadingView from './NativeDevLoadingView'; + +module.exports = { + showMessage(message: string, type: 'load' | 'refresh') { + if (NativeDevLoadingView) { + const green = processColor('#005a00'); + const blue = processColor('#2584e8'); + const white = processColor('#ffffff'); + + NativeDevLoadingView.showMessage( + message, + // Use same colors as iOS "Personal Hotspot" bar. + typeof white === 'number' ? white : null, + type && type === 'load' + ? typeof green === 'number' + ? green + : null + : typeof blue === 'number' + ? blue + : null, + ); + } + }, + hide() { + NativeDevLoadingView && NativeDevLoadingView.hide(); + }, +}; diff --git a/packages/react-native-dom/src/Libraries/Utilities/NativePlatformConstantsDOM.js b/packages/react-native-dom/src/Libraries/Utilities/NativePlatformConstantsDOM.js new file mode 100644 index 000000000..407228455 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Utilities/NativePlatformConstantsDOM.js @@ -0,0 +1,34 @@ +/** + * 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 strict + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {| + isTesting: boolean, + reactNativeVersion: {| + major: number, + minor: number, + patch: number, + prerelease: ?number, + |}, + forceTouchAvailable: boolean, + osVersion: string, + systemName: string, + interfaceIdiom: string, + |}; +}; + +export default (TurboModuleRegistry.getEnforcing( + 'PlatformConstants', +): Spec); diff --git a/packages/react-native-dom/src/Libraries/Utilities/Platform.dom.js b/packages/react-native-dom/src/Libraries/Utilities/Platform.dom.js new file mode 100644 index 000000000..aded79999 --- /dev/null +++ b/packages/react-native-dom/src/Libraries/Utilities/Platform.dom.js @@ -0,0 +1,66 @@ +/** + * 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 NativePlatformConstantsDOM from './NativePlatformConstantsDOM'; + +export type PlatformSelectSpec = { + default?: D, + native?: N, + ios?: I, + ... +}; + +const Platform = { + __constants: null, + OS: 'dom', + get Version(): string { + return this.constants.osVersion; + }, + get constants(): {| + forceTouchAvailable: boolean, + interfaceIdiom: string, + isTesting: boolean, + osVersion: string, + reactNativeVersion: {| + major: number, + minor: number, + patch: number, + prerelease: ?number, + |}, + systemName: string, + |} { + this.__constants = NativePlatformConstantsDOM.getConstants(); + return this.__constants; + }, + get isPad(): boolean { + return this.constants.interfaceIdiom === 'pad'; + }, + /** + * Deprecated, use `isTV` instead. + */ + get isTVOS(): boolean { + return Platform.isTV; + }, + get isTV(): boolean { + return this.constants.interfaceIdiom === 'tv'; + }, + get isTesting(): boolean { + if (__DEV__) { + return this.constants.isTesting; + } + return false; + }, + select: (spec: PlatformSelectSpec): D | N | I => + 'dom' in spec ? spec.dom : 'native' in spec ? spec.native : spec.default, +}; + +module.exports = Platform; diff --git a/packages/react-native-dom/Libraries/Vibration/Vibration.dom.js b/packages/react-native-dom/src/Libraries/Vibration/Vibration.dom.js similarity index 59% rename from packages/react-native-dom/Libraries/Vibration/Vibration.dom.js rename to packages/react-native-dom/src/Libraries/Vibration/Vibration.dom.js index c313893df..f3cfbfd15 100644 --- a/packages/react-native-dom/Libraries/Vibration/Vibration.dom.js +++ b/packages/react-native-dom/src/Libraries/Vibration/Vibration.dom.js @@ -1,17 +1,18 @@ /** - * Copyright (c) 2015-present, Facebook, Inc. + * 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. * - * @providesModule Vibration + * @format * @flow * @jsdoc */ -"use strict"; -var RCTVibration = require("NativeModules").Vibration; -var Platform = require("Platform"); +'use strict'; + +import NativeVibration from './NativeVibration'; +const Platform = require('../Utilities/Platform'); /** * Vibration API @@ -19,8 +20,9 @@ var Platform = require("Platform"); * See https://facebook.github.io/react-native/docs/vibration.html */ -var _vibrating: boolean = false; -var _id: number = 0; // _id is necessary to prevent race condition. +let _vibrating: boolean = false; +let _id: number = 0; // _id is necessary to prevent race condition. +const _default_vibration_length = 400; function vibrateByPattern(pattern: Array, repeat: boolean = false) { if (_vibrating) { @@ -28,7 +30,7 @@ function vibrateByPattern(pattern: Array, repeat: boolean = false) { } _vibrating = true; if (pattern[0] === 0) { - RCTVibration.vibrate(); + NativeVibration.vibrate(_default_vibration_length); pattern = pattern.slice(1); } if (pattern.length === 0) { @@ -42,12 +44,12 @@ function vibrateScheduler( id, pattern: Array, repeat: boolean, - nextIndex: number + nextIndex: number, ) { if (!_vibrating || id !== _id) { return; } - RCTVibration.vibrate(); + NativeVibration.vibrate(_default_vibration_length); if (nextIndex >= pattern.length) { if (repeat) { nextIndex = 0; @@ -58,42 +60,38 @@ function vibrateScheduler( } setTimeout( () => vibrateScheduler(id, pattern, repeat, nextIndex + 1), - pattern[nextIndex] + pattern[nextIndex], ); } -var Vibration = { +const Vibration = { /** * Trigger a vibration with specified `pattern`. * * See https://facebook.github.io/react-native/docs/vibration.html#vibrate */ vibrate: function( - pattern: number | Array = 400, - repeat: boolean = false + pattern: number | Array = _default_vibration_length, + repeat: boolean = false, ) { - if (Platform.OS === "android" || Platform.OS === "dom") { - if (typeof pattern === "number") { - RCTVibration.vibrate(pattern); + if (Platform.OS === 'android' || Platform.OS === 'dom') { + if (typeof pattern === 'number') { + NativeVibration.vibrate(pattern); } else if (Array.isArray(pattern)) { - if (Platform.OS === "android") { - RCTVibration.vibrateByPattern(pattern, repeat ? 0 : -1); - } else { - RCTVibration.vibrateByPattern(pattern, repeat); - } + NativeVibration.vibrateByPattern(pattern, repeat ? 0 : -1); } else { - throw new Error("Vibration pattern should be a number or array"); + throw new Error('Vibration pattern should be a number or array'); } } else { if (_vibrating) { return; } - if (typeof pattern === "number") { - RCTVibration.vibrate(); + if (typeof pattern === 'number') { + NativeVibration.vibrate(pattern); } else if (Array.isArray(pattern)) { vibrateByPattern(pattern, repeat); } else { - throw new Error("Vibration pattern should be a number or array"); + throw new Error('Vibration pattern should be a number or array'); } } }, @@ -103,12 +101,12 @@ var Vibration = { * See https://facebook.github.io/react-native/docs/vibration.html#cancel */ cancel: function() { - if (Platform.OS === "ios") { + if (Platform.OS === 'ios') { _vibrating = false; } else { - RCTVibration.cancel(); + NativeVibration.cancel(); } - } + }, }; module.exports = Vibration; diff --git a/scripts/smoke.js b/scripts/smoke.js index 93e011f99..62ba430fc 100644 --- a/scripts/smoke.js +++ b/scripts/smoke.js @@ -25,7 +25,7 @@ guardedExec( // Initialize new React Native Project guardedExec( - `react-native init ${APP_NAME}`, + `react-native init ${APP_NAME} --version 0.62.2`, "Error: Failed to initialize new React Native project" ); @@ -33,13 +33,13 @@ shell.cd(`/tmp/${APP_NAME}`); // Install RNDom's RNPM Plugin guardedExec( - "yarn add --dev --exact rnpm-plugin-dom@canary", - "Error: Failed to install rnpm-plugin-dom" + "yarn global add react-native-dom-init", + "Error: Failed to install react-native-dom-init" ); // Bootstrap React Native DOM guardedExec( - "react-native dom --exact --domVersion canary", + "react-native-dom-init", "Error: Failed to bootstrap react-native-dom into new React Native project" );