From 44f3f386c347e7a38fbc326fae70345920cf367d Mon Sep 17 00:00:00 2001 From: Christopher Chedeau Date: Sat, 14 Mar 2015 17:00:52 -0700 Subject: [PATCH] update website --- Examples/Movies/AppDelegate.h | 10 - Examples/Movies/AppDelegate.m | 44 - Examples/Movies/Base.lproj/LaunchScreen.xib | 41 - .../AppIcon.appiconset/Contents.json | 38 - Examples/Movies/Info.plist | 40 - Examples/Movies/MovieCell.js | 86 - Examples/Movies/MovieScreen.js | 155 -- .../Movies/Movies.xcodeproj/project.pbxproj | 435 ---- .../xcshareddata/xcschemes/Movies.xcscheme | 86 - Examples/Movies/MoviesApp.js | 41 - Examples/Movies/SearchScreen.js | 337 --- .../Movies/__tests__/getImageSource-test.js | 36 - Examples/Movies/getImageSource.js | 15 - Examples/Movies/getStyleFromScore.js | 35 - Examples/Movies/getTextFromScore.js | 11 - Examples/Movies/main.m | 10 - Examples/TicTacToe/AppDelegate.h | 9 - Examples/TicTacToe/AppDelegate.m | 44 - .../TicTacToe/Base.lproj/LaunchScreen.xib | 41 - .../AppIcon.appiconset/Contents.json | 38 - Examples/TicTacToe/Info.plist | 40 - .../TicTacToe.xcodeproj/project.pbxproj | 389 ---- .../xcshareddata/xcschemes/TicTacToe.xcscheme | 86 - Examples/TicTacToe/TicTacToeApp.js | 322 --- Examples/TicTacToe/main.m | 10 - .../UIExplorer/ActivityIndicatorExample.js | 151 -- Examples/UIExplorer/AppDelegate.h | 10 - Examples/UIExplorer/AppDelegate.m | 44 - .../UIExplorer/Base.lproj/LaunchScreen.xib | 41 - Examples/UIExplorer/DatePickerExample.js | 157 -- Examples/UIExplorer/ExpandingTextExample.js | 54 - Examples/UIExplorer/GeoLocationExample.js | 72 - Examples/UIExplorer/ImageCapInsetsExample.js | 66 - Examples/UIExplorer/ImageExample.js | 305 --- .../AppIcon.appiconset/Contents.json | 44 - .../AppIcon.appiconset/uie_icon@2x-1.png | Bin 31759 -> 0 bytes .../AppIcon.appiconset/uie_icon@2x-2.png | Bin 31759 -> 0 bytes .../AppIcon.appiconset/uie_icon@2x-3.png | Bin 31759 -> 0 bytes .../AppIcon.appiconset/uie_icon@2x-4.png | Bin 31759 -> 0 bytes .../AppIcon.appiconset/uie_icon@2x-5.png | Bin 31759 -> 0 bytes .../AppIcon.appiconset/uie_icon@2x.png | Bin 31759 -> 0 bytes .../story-background.imageset/Contents.json | 22 - .../story-background.png | Bin 336 -> 0 bytes .../story-background@2x.png | Bin 657 -> 0 bytes .../Contents.json | 21 - .../uie_comment_highlighted@2x.png | Bin 403 -> 0 bytes .../uie_comment_normal.imageset/Contents.json | 21 - .../uie_comment_normal@2x.png | Bin 420 -> 0 bytes .../uie_thumb_normal.imageset/Contents.json | 21 - .../uie_thumb_normal@2x.png | Bin 850 -> 0 bytes .../uie_thumb_selected.imageset/Contents.json | 21 - .../uie_thumb_selected@2x.png | Bin 1110 -> 0 bytes Examples/UIExplorer/Info.plist | 42 - Examples/UIExplorer/LayoutExample.js | 145 -- Examples/UIExplorer/ListViewPagingExample.js | 249 --- Examples/UIExplorer/ListViewSimpleExample.js | 120 - Examples/UIExplorer/NavigatorIOSExample.js | 216 -- Examples/UIExplorer/PointerEventsExample.js | 239 -- Examples/UIExplorer/ScrollViewExample.js | 102 - Examples/UIExplorer/SliderExample.js | 57 - Examples/UIExplorer/StatusBarIOSExample.js | 87 - Examples/UIExplorer/SwitchExample.js | 141 -- Examples/UIExplorer/TabBarExample.js | 101 - Examples/UIExplorer/TextExample.ios.js | 279 --- Examples/UIExplorer/TextInputExample.js | 221 -- Examples/UIExplorer/TouchableExample.js | 188 -- .../UIExplorer.xcodeproj/project.pbxproj | 459 ---- .../contents.xcworkspacedata | 7 - .../xcschemes/UIExplorer.xcscheme | 86 - Examples/UIExplorer/UIExplorerApp.js | 44 - Examples/UIExplorer/UIExplorerBlock.js | 93 - Examples/UIExplorer/UIExplorerList.js | 118 - Examples/UIExplorer/UIExplorerPage.js | 67 - Examples/UIExplorer/UIExplorerTitle.js | 43 - Examples/UIExplorer/ViewExample.js | 123 -- Examples/UIExplorer/createExamplePage.js | 60 - Examples/UIExplorer/main.m | 10 - LICENSE | 15 - Libraries/Animation/LayoutAnimation.js | 89 - Libraries/Animation/POPAnimationMixin.js | 250 --- Libraries/AppRegistry/AppRegistry.js | 68 - .../BatchedBridgedModules/NativeModules.js | 16 - .../NativeModulesDeprecated.js | 16 - .../BatchedBridgedModules/POPAnimation.js | 166 -- .../BatchedBridgedModules/RCTEventEmitter.js | 11 - .../BatchedBridgedModules/RCTJSTimers.js | 12 - .../RKAlertManager.ios.js | 10 - .../BatchingImplementation/BatchedBridge.js | 32 - .../BatchedBridgeFactory.js | 106 - .../ActivityIndicatorIOS.ios.js | 98 - .../DatePicker/DatePickerIOS.ios.js | 155 -- Libraries/Components/ListView/ListView.js | 475 ---- .../Components/ListView/ListViewDataSource.js | 379 ---- .../Components/Navigation/NavigatorIOS.ios.js | 566 ----- Libraries/Components/ScrollResponder.js | 458 ---- Libraries/Components/ScrollView/ScrollView.js | 349 --- Libraries/Components/Slider/Slider.js | 83 - Libraries/Components/StaticRenderer.js | 25 - .../Components/StatusBar/StatusBarIOS.ios.js | 35 - Libraries/Components/Subscribable.js | 333 --- .../Components/SwitchIOS/SwitchIOS.android.js | 41 - .../Components/SwitchIOS/SwitchIOS.ios.js | 117 - .../Components/TabBarIOS/TabBarIOS.android.js | 29 - .../Components/TabBarIOS/TabBarIOS.ios.js | 36 - .../TabBarIOS/TabBarItemIOS.android.js | 38 - .../Components/TabBarIOS/TabBarItemIOS.ios.js | 94 - .../Components/TextInput/TextInput.ios.js | 435 ---- .../Components/TextInput/TextInputState.js | 53 - .../Touchable/TouchableFeedbackPropType.js | 22 - .../Touchable/TouchableHighlight.js | 205 -- .../Components/Touchable/TouchableOpacity.js | 147 -- .../Touchable/TouchableWithoutFeedback.js | 81 - .../Touchable/ensureComponentIsNative.js | 18 - Libraries/Components/View/View.js | 147 -- .../Components/View/ViewStylePropTypes.js | 41 - Libraries/Device/RCTDeviceEventEmitter.js | 12 - Libraries/Fetch/fetch.js | 313 --- Libraries/GeoLocation/Geolocation.ios.js | 98 - .../RCTGeolocation.xcodeproj/project.pbxproj | 256 --- Libraries/GeoLocation/RCTLocationObserver.h | 7 - Libraries/GeoLocation/RCTLocationObserver.m | 319 --- Libraries/Image/Image.ios.js | 168 -- Libraries/Image/ImageResizeMode.js | 33 - Libraries/Image/ImageStylePropTypes.js | 45 - Libraries/Image/RCTGIFImage.h | 8 - Libraries/Image/RCTGIFImage.m | 91 - .../Image/RCTImage.xcodeproj/project.pbxproj | 286 --- Libraries/Image/RCTImageDownloader.h | 22 - Libraries/Image/RCTImageDownloader.m | 157 -- Libraries/Image/RCTNetworkImage.podspec | 28 - Libraries/Image/RCTNetworkImageView.h | 33 - Libraries/Image/RCTNetworkImageView.m | 118 - Libraries/Image/RCTNetworkImageViewManager.h | 8 - Libraries/Image/RCTNetworkImageViewManager.m | 25 - Libraries/Image/RCTStaticImage.h | 10 - Libraries/Image/RCTStaticImage.m | 55 - Libraries/Image/RCTStaticImageManager.h | 7 - Libraries/Image/RCTStaticImageManager.m | 43 - Libraries/Image/ix.js | 26 - Libraries/Interaction/InteractionManager.js | 143 -- .../InitializeJavaScriptAppEngine.js | 152 -- .../Initialization/SourceMap.js | 1958 ----------------- .../Initialization/errorToString.js | 54 - .../Initialization/loadSourceMap.js | 24 - .../System/JSTimers/JSTimers.js | 135 -- .../System/JSTimers/JSTimersExecution.js | 128 -- Libraries/Network/RCTDataManager.h | 10 - Libraries/Network/RCTDataManager.m | 72 - Libraries/Network/RCTDataManager.podspec | 28 - .../RCTNetwork.xcodeproj/project.pbxproj | 256 --- Libraries/Network/XMLHttpRequest.ios.js | 163 -- Libraries/RKBackendNode/queryLayoutByID.js | 39 - .../ReactIOS/IOSDefaultEventPluginOrder.js | 13 - .../ReactIOS/IOSNativeBridgeEventPlugin.js | 72 - Libraries/ReactIOS/NativeMethodsMixin.js | 123 -- Libraries/ReactIOS/React.js | 21 - Libraries/ReactIOS/ReactIOS.js | 119 - .../ReactIOS/ReactIOSComponentEnvironment.js | 39 - Libraries/ReactIOS/ReactIOSComponentMixin.js | 73 - Libraries/ReactIOS/ReactIOSDOMIDOperations.js | 98 - .../ReactIOS/ReactIOSDefaultInjection.js | 87 - Libraries/ReactIOS/ReactIOSEventEmitter.js | 191 -- .../ReactIOSGlobalInteractionHandler.js | 25 - .../ReactIOSGlobalResponderHandler.js | 21 - Libraries/ReactIOS/ReactIOSMount.js | 207 -- Libraries/ReactIOS/ReactIOSNativeComponent.js | 268 --- .../ReactIOS/ReactIOSReconcileTransaction.js | 99 - Libraries/ReactIOS/ReactIOSStyleAttributes.js | 25 - Libraries/ReactIOS/ReactIOSTagHandles.js | 88 - Libraries/ReactIOS/ReactIOSTextComponent.js | 62 - Libraries/ReactIOS/ReactIOSViewAttributes.js | 31 - .../createReactIOSNativeComponentClass.js | 30 - Libraries/ReactIOS/diffRawProperties.js | 85 - Libraries/ReactIOS/renderApplication.ios.js | 20 - Libraries/StyleSheet/EdgeInsetsPropType.js | 20 - Libraries/StyleSheet/LayoutPropTypes.js | 92 - Libraries/StyleSheet/PointPropType.js | 18 - Libraries/StyleSheet/StyleSheet.js | 120 - Libraries/StyleSheet/StyleSheetPropType.js | 24 - Libraries/StyleSheet/StyleSheetRegistry.js | 38 - Libraries/StyleSheet/flattenStyle.js | 37 - Libraries/StyleSheet/styleDiffer.js | 55 - Libraries/Text/ExpandingText.js | 130 -- Libraries/Text/RCTRawTextManager.h | 7 - Libraries/Text/RCTRawTextManager.m | 20 - Libraries/Text/RCTShadowRawText.h | 9 - Libraries/Text/RCTShadowRawText.m | 16 - Libraries/Text/RCTShadowText.h | 26 - Libraries/Text/RCTShadowText.m | 199 -- Libraries/Text/RCTText.h | 13 - Libraries/Text/RCTText.m | 100 - Libraries/Text/RCTText.podspec | 28 - .../Text/RCTText.xcodeproj/project.pbxproj | 272 --- Libraries/Text/RCTTextManager.h | 8 - Libraries/Text/RCTTextManager.m | 127 -- Libraries/Text/Text.js | 195 -- Libraries/Text/TextStylePropTypes.js | 46 - Libraries/Utilities/Dimensions.js | 44 - Libraries/Utilities/ErrorUtils.js | 21 - Libraries/Utilities/MessageQueue.js | 476 ---- Libraries/Utilities/PixelRatio.js | 54 - Libraries/Utilities/Platform.ios.js | 11 - Libraries/Utilities/RCTLog.js | 37 - Libraries/Utilities/RCTRenderingPerf.js | 56 - Libraries/Utilities/TimerMixin.js | 97 - .../Utilities/createStrictShapeTypeChecker.js | 64 - .../deepFreezeAndThrowOnMutationInDev.js | 57 - Libraries/Utilities/differ/deepDiffer.js | 48 - Libraries/Utilities/differ/insetsDiffer.js | 26 - Libraries/Utilities/differ/matricesDiffer.js | 39 - Libraries/Utilities/differ/pointsDiffer.js | 19 - Libraries/Utilities/logError.js | 22 - Libraries/Utilities/mergeFast.js | 28 - Libraries/Utilities/mergeIntoFast.js | 21 - Libraries/Utilities/truncate.js | 32 - Libraries/react-native/addons.js | 34 - Libraries/react-native/package.json | 5 - .../react-native/react-native-interface.js | 36 - Libraries/react-native/react-native.js | 36 - Libraries/vendor/core/ES6Promise.js | 364 --- Libraries/vendor/core/Map.js | 626 ------ Libraries/vendor/core/Promise.js | 88 - Libraries/vendor/core/Set.js | 201 -- .../core/_shouldPolyfillES6Collection.js | 78 - Libraries/vendor/core/copyProperties.js | 53 - Libraries/vendor/core/getObjectValues.js | 36 - Libraries/vendor/core/guid.js | 31 - .../vendor/core/immediate/setImmediate.js | 201 -- Libraries/vendor/core/isEmpty.js | 34 - Libraries/vendor/core/merge.js | 50 - Libraries/vendor/core/mergeHelpers.js | 160 -- Libraries/vendor/core/mergeInto.js | 59 - Libraries/vendor/core/setImmediate.js | 19 - Libraries/vendor/core/throwImmediate.js | 38 - Libraries/vendor/core/toIterator.js | 180 -- Libraries/vendor/crypto/crc32.js | 76 - .../selection/DocumentSelectionState.js | 156 -- .../vendor/emitter/EmitterSubscription.js | 42 - Libraries/vendor/emitter/EventEmitter.js | 182 -- .../vendor/emitter/EventEmitterWithHolding.js | 164 -- Libraries/vendor/emitter/EventHolder.js | 123 -- Libraries/vendor/emitter/EventSubscription.js | 42 - .../vendor/emitter/EventSubscriptionVendor.js | 101 - Libraries/vendor/emitter/EventValidator.js | 144 -- Libraries/vendor/emitter/mixInEventEmitter.js | 135 -- .../eventPlugins/ResponderEventPlugin.js | 599 ----- .../eventPlugins/ResponderSyntheticEvent.js | 47 - .../ResponderTouchHistoryStore.js | 171 -- .../vendor/react/core/ReactInstanceHandles.js | 348 --- .../vendor/react/event/EventPropagators.js | 163 -- Libraries/vendor/react/platform/NodeHandle.js | 83 - .../worker/UniversalWorkerNodeHandle.js | 19 - .../vendor/core/ExecutionEnvironment.ios.js | 48 - .../StaticContainer/StaticContainer.js | 50 - .../interactions/Touchable/Touchable.js | 662 ------ .../pooledClasses/BoundingDimensions.js | 37 - .../react_contrib/pooledClasses/Position.js | 27 - README.md | 224 -- ReactKit/Base/RCTAssert.h | 36 - ReactKit/Base/RCTAssert.m | 12 - ReactKit/Base/RCTBridge.h | 81 - ReactKit/Base/RCTBridge.m | 817 ------- ReactKit/Base/RCTBridgeModule.h | 60 - ReactKit/Base/RCTCache.h | 22 - ReactKit/Base/RCTCache.m | 224 -- ReactKit/Base/RCTConvert.h | 93 - ReactKit/Base/RCTConvert.m | 841 ------- ReactKit/Base/RCTEventDispatcher.h | 66 - ReactKit/Base/RCTEventDispatcher.m | 119 - ReactKit/Base/RCTInvalidating.h | 16 - ReactKit/Base/RCTJSMethodRegistrar.h | 24 - ReactKit/Base/RCTJavaScriptExecutor.h | 35 - ReactKit/Base/RCTKeyCommands.h | 28 - ReactKit/Base/RCTKeyCommands.m | 116 - ReactKit/Base/RCTLog.h | 58 - ReactKit/Base/RCTLog.m | 86 - ReactKit/Base/RCTRedBox.h | 16 - ReactKit/Base/RCTRedBox.m | 295 --- ReactKit/Base/RCTRootView.h | 44 - ReactKit/Base/RCTRootView.m | 249 --- ReactKit/Base/RCTSparseArray.h | 31 - ReactKit/Base/RCTSparseArray.m | 116 - ReactKit/Base/RCTTouchHandler.h | 15 - ReactKit/Base/RCTTouchHandler.m | 349 --- ReactKit/Base/RCTUtils.h | 46 - ReactKit/Base/RCTUtils.m | 185 -- ReactKit/Executors/RCTContextExecutor.h | 21 - ReactKit/Executors/RCTContextExecutor.m | 293 --- ReactKit/Executors/RCTWebViewExecutor.h | 35 - ReactKit/Executors/RCTWebViewExecutor.m | 184 -- ReactKit/Layout/Layout.c | 817 ------- ReactKit/Layout/Layout.h | 148 -- ReactKit/Modules/RCTAlertManager.h | 9 - ReactKit/Modules/RCTAlertManager.m | 107 - ReactKit/Modules/RCTExceptionsManager.h | 9 - ReactKit/Modules/RCTExceptionsManager.m | 23 - ReactKit/Modules/RCTStatusBarManager.h | 9 - ReactKit/Modules/RCTStatusBarManager.m | 67 - ReactKit/Modules/RCTTiming.h | 10 - ReactKit/Modules/RCTTiming.m | 208 -- ReactKit/Modules/RCTUIManager.h | 56 - ReactKit/Modules/RCTUIManager.m | 1405 ------------ ReactKit/ReactKit.podspec | 16 - ReactKit/ReactKit.xcodeproj/project.pbxproj | 587 ----- ReactKit/Views/RCTAnimationType.h | 11 - ReactKit/Views/RCTAutoInsetsProtocol.h | 13 - ReactKit/Views/RCTDatePickerManager.h | 7 - ReactKit/Views/RCTDatePickerManager.m | 51 - ReactKit/Views/RCTNavItem.h | 14 - ReactKit/Views/RCTNavItem.m | 8 - ReactKit/Views/RCTNavItemManager.h | 8 - ReactKit/Views/RCTNavItemManager.m | 23 - ReactKit/Views/RCTNavigator.h | 26 - ReactKit/Views/RCTNavigator.m | 560 ----- ReactKit/Views/RCTNavigatorManager.h | 8 - ReactKit/Views/RCTNavigatorManager.m | 47 - ReactKit/Views/RCTPointerEvents.h | 10 - ReactKit/Views/RCTScrollView.h | 37 - ReactKit/Views/RCTScrollView.m | 592 ----- ReactKit/Views/RCTScrollViewManager.h | 8 - ReactKit/Views/RCTScrollViewManager.m | 55 - ReactKit/Views/RCTScrollableProtocol.h | 18 - ReactKit/Views/RCTShadowView.h | 157 -- ReactKit/Views/RCTShadowView.m | 525 ----- ReactKit/Views/RCTSliderManager.h | 7 - ReactKit/Views/RCTSliderManager.m | 43 - ReactKit/Views/RCTSwitch.h | 10 - ReactKit/Views/RCTSwitch.m | 15 - ReactKit/Views/RCTSwitchManager.h | 7 - ReactKit/Views/RCTSwitchManager.m | 39 - ReactKit/Views/RCTTabBar.h | 11 - ReactKit/Views/RCTTabBar.m | 139 -- ReactKit/Views/RCTTabBarItem.h | 11 - ReactKit/Views/RCTTabBarItem.m | 83 - ReactKit/Views/RCTTabBarItemManager.h | 7 - ReactKit/Views/RCTTabBarItemManager.m | 25 - ReactKit/Views/RCTTabBarManager.h | 7 - ReactKit/Views/RCTTabBarManager.m | 17 - ReactKit/Views/RCTTextField.h | 15 - ReactKit/Views/RCTTextField.m | 126 -- ReactKit/Views/RCTTextFieldManager.h | 8 - ReactKit/Views/RCTTextFieldManager.m | 49 - .../Views/RCTUIActivityIndicatorViewManager.h | 7 - .../Views/RCTUIActivityIndicatorViewManager.m | 38 - ReactKit/Views/RCTView.h | 27 - ReactKit/Views/RCTView.m | 118 - ReactKit/Views/RCTViewControllerProtocol.h | 13 - ReactKit/Views/RCTViewManager.h | 141 -- ReactKit/Views/RCTViewManager.m | 145 -- ReactKit/Views/RCTViewNodeProtocol.h | 34 - ReactKit/Views/RCTWrapperViewController.h | 29 - ReactKit/Views/RCTWrapperViewController.m | 127 -- ReactKit/Views/UIView+ReactKit.h | 24 - ReactKit/Views/UIView+ReactKit.m | 82 - _index.html | 12 + .../react-native/css => css}/react-native.css | 0 docs/GettingStarted.md | 79 - docs/Image.md | 60 - docs/Network.md | 42 - docs/Physical vs Logical Pixels.md | 31 - docs/Style.md | 79 - docs/Text.md | 103 - docs/Timers.md | 66 - docs/activityindicatorios.html | 13 + docs/animation.html | 91 + docs/appregistry.html | 111 + docs/appstate.html | 67 + docs/appstateios.html | 70 + docs/asyncstorage.html | 246 +++ docs/cameraroll.html | 93 + docs/datepickerios.html | 11 + docs/expandingtext.html | 25 + docs/getting-started.html | 33 + docs/image.html | 47 + docs/layoutanimation.html | 114 + docs/listview.html | 64 + docs/mapview.html | 28 + docs/navigatorios.html | 50 + docs/network.html | 33 + docs/pickerios.html | 12 + docs/pixelratio.html | 58 + docs/pixels.html | 16 + docs/scrollview.html | 54 + docs/slider.html | 16 + docs/statusbarios.html | 87 + docs/style.html | 47 + docs/stylesheet.html | 140 ++ docs/switchios.html | 18 + docs/tabbarios.html | 12 + docs/text.html | 88 + docs/textinput.html | 37 + docs/timers.html | 28 + docs/touchablehighlight.html | 29 + docs/touchableopacity.html | 25 + docs/touchablewithoutfeedback.html | 14 + docs/view.html | 47 + .../src/react-native/img => img}/favicon.png | Bin .../src/react-native/img => img}/logo.png | Bin .../react-native/img => img}/opengraph.png | Bin .../react-native/img => img}/react-native.png | Bin jestSupport/env.js | 5 - jestSupport/scriptPreprocess.js | 25 - lint/linterTransform.js | 76 - linter.js | 10 - package.json | 49 - packager/blacklist.js | 44 - packager/launchEditor.js | 40 - packager/launchPackager.command | 10 - packager/packager.js | 121 - packager/packager.sh | 6 - packager/parseCommandLine.js | 52 - packager/react-packager/.npmignore | 8 - packager/react-packager/__mocks__/debug.js | 5 - packager/react-packager/__mocks__/net.js | 26 - .../react-packager/example_project/bar.js | 5 - .../example_project/config.json | 10 - .../react-packager/example_project/foo/foo.js | 23 - .../react-packager/example_project/index.js | 10 - .../example_project/js/Channel.js | 46 - .../react-packager/example_project/js/XHR.js | 22 - .../react-packager/example_project/js/code.js | 51 - .../react-packager/example_project/js/main.js | 57 - .../example_project/public/css/index.css | 94 - .../example_project/public/index.html | 30 - packager/react-packager/index.js | 39 - .../src/Activity/__tests__/Activity-test.js | 85 - packager/react-packager/src/Activity/index.js | 163 -- .../DependencyResolver/ModuleDescriptor.js | 36 - .../haste/DependencyGraph/__mocks__/fs.js | 101 - .../__tests__/DependencyGraph-test.js | 772 ------- .../haste/DependencyGraph/docblock.js | 90 - .../haste/DependencyGraph/index.js | 514 ----- .../__tests__/HasteDependencyResolver-test.js | 254 --- .../src/DependencyResolver/haste/index.js | 163 -- .../haste/polyfills/console.js | 143 -- .../haste/polyfills/error-guard.js | 82 - .../haste/polyfills/polyfills.js | 75 - .../haste/polyfills/prelude.js | 2 - .../haste/polyfills/prelude_dev.js | 2 - .../haste/polyfills/require.js | 627 ------ .../src/DependencyResolver/index.js | 14 - .../src/DependencyResolver/node/index.js | 43 - .../src/FileWatcher/__mocks__/sane.js | 5 - .../FileWatcher/__tests__/FileWatcher-test.js | 43 - .../react-packager/src/FileWatcher/index.js | 86 - .../react-packager/src/JSTransformer/Cache.js | 160 -- .../src/JSTransformer/README.md | 0 .../src/JSTransformer/__mocks__/q.js | 6 - .../src/JSTransformer/__mocks__/underscore.js | 5 - .../src/JSTransformer/__mocks__/worker.js | 5 - .../src/JSTransformer/__tests__/Cache-test.js | 200 -- .../__tests__/Transformer-test.js | 70 - .../react-packager/src/JSTransformer/index.js | 158 -- .../src/JSTransformer/worker.js | 26 - .../react-packager/src/Packager/Package.js | 205 -- .../src/Packager/__tests__/Package-test.js | 106 - .../src/Packager/__tests__/Packager-test.js | 84 - .../react-packager/src/Packager/base64-vlq.js | 169 -- packager/react-packager/src/Packager/index.js | 144 -- .../src/Server/__tests__/Server-test.js | 208 -- packager/react-packager/src/Server/index.js | 269 --- .../src/lib/__mocks__/declareOpts.js | 12 - .../src/lib/__tests__/declareOpts-test.js | 84 - .../react-packager/src/lib/declareOpts.js | 57 - packager/transformer.js | 65 - support.html | 12 + website/.gitignore | 2 - website/README.md | 44 - website/core/DocsSidebar.js | 96 - website/core/H2.js | 17 - website/core/Header.js | 24 - website/core/HeaderLinks.js | 34 - website/core/Marked.js | 1094 --------- website/core/Prism.js | 357 --- website/core/Site.js | 69 - website/core/center.js | 16 - website/core/slugify.js | 35 - website/core/unindent.js | 22 - website/layout/AutodocsLayout.js | 101 - website/layout/DocsLayout.js | 33 - website/layout/PageLayout.js | 26 - website/package.json | 15 - website/publish.sh | 22 - website/react-docgen/.gitignore | 1 - website/react-docgen/CONTRIBUTING.md | 43 - website/react-docgen/LICENSE | 30 - website/react-docgen/PATENTS | 23 - website/react-docgen/README.md | 222 -- website/react-docgen/bin/react-docgen.js | 168 -- website/react-docgen/example/buildDocs.sh | 42 - .../example/components/Component.js | 27 - .../example/components/NoComponent.js | 4 - .../react-docgen/example/generateMarkdown.js | 80 - website/react-docgen/flow/react-docgen.js | 35 - website/react-docgen/flow/recast.js | 35 - website/react-docgen/lib/Documentation.js | 62 - .../lib/__mocks__/Documentation.js | 28 - .../react-docgen/lib/__tests__/main-test.js | 75 - .../react-docgen/lib/__tests__/parse-test.js | 52 - .../componentDocblockHandler-test.js | 84 - .../__tests__/defaultPropsHandler-test.js | 73 - .../__tests__/propDocblockHandler-test.js | 195 -- .../__tests__/propTypeHandler-test.js | 203 -- .../lib/handlers/componentDocblockHandler.js | 50 - .../lib/handlers/defaultPropsHandler.js | 79 - website/react-docgen/lib/handlers/index.js | 16 - .../lib/handlers/propDocBlockHandler.js | 45 - .../lib/handlers/propTypeHandler.js | 121 - website/react-docgen/lib/main.js | 61 - website/react-docgen/lib/parse.js | 69 - .../findAllReactCreateClassCalls-test.js | 106 - .../findExportedReactCreateClassCall-test.js | 106 - .../resolver/findAllReactCreateClassCalls.js | 47 - .../findExportedReactCreateClassCall.js | 78 - website/react-docgen/lib/resolver/index.js | 16 - .../lib/utils/__tests__/docblock-test.js | 40 - .../lib/utils/__tests__/getMembers-test.js | 51 - .../lib/utils/__tests__/getPropType-test.js | 144 -- .../__tests__/getPropertyValuePath-test.js | 42 - .../isExportsOrModuleAssignment-test.js | 46 - .../lib/utils/__tests__/match-test.js | 41 - website/react-docgen/lib/utils/docblock.js | 60 - .../react-docgen/lib/utils/expressionTo.js | 80 - website/react-docgen/lib/utils/getMembers.js | 62 - .../react-docgen/lib/utils/getNameOrValue.js | 34 - website/react-docgen/lib/utils/getPropType.js | 153 -- .../react-docgen/lib/utils/getPropertyName.js | 32 - .../lib/utils/getPropertyValuePath.js | 31 - website/react-docgen/lib/utils/index.js | 23 - .../lib/utils/isExportsOrModuleAssignment.js | 37 - .../lib/utils/isReactCreateClassCall.js | 37 - .../lib/utils/isReactModuleName.js | 28 - website/react-docgen/lib/utils/match.js | 40 - .../react-docgen/lib/utils/resolveToModule.js | 54 - .../react-docgen/lib/utils/resolveToValue.js | 46 - website/react-docgen/package.json | 41 - website/react-docgen/preprocessor.js | 9 - website/react-docgen/tests/preprocessor.js | 9 - website/react-docgen/tests/utils.js | 49 - website/server/convert.js | 126 -- website/server/extractDocs.js | 60 - website/server/generate.js | 61 - website/server/server.js | 53 - website/src/react-native/index.js | 34 - website/src/react-native/support.js | 44 - 545 files changed, 1848 insertions(+), 52021 deletions(-) delete mode 100644 Examples/Movies/AppDelegate.h delete mode 100644 Examples/Movies/AppDelegate.m delete mode 100644 Examples/Movies/Base.lproj/LaunchScreen.xib delete mode 100644 Examples/Movies/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Examples/Movies/Info.plist delete mode 100644 Examples/Movies/MovieCell.js delete mode 100644 Examples/Movies/MovieScreen.js delete mode 100644 Examples/Movies/Movies.xcodeproj/project.pbxproj delete mode 100644 Examples/Movies/Movies.xcodeproj/xcshareddata/xcschemes/Movies.xcscheme delete mode 100644 Examples/Movies/MoviesApp.js delete mode 100644 Examples/Movies/SearchScreen.js delete mode 100644 Examples/Movies/__tests__/getImageSource-test.js delete mode 100644 Examples/Movies/getImageSource.js delete mode 100644 Examples/Movies/getStyleFromScore.js delete mode 100644 Examples/Movies/getTextFromScore.js delete mode 100644 Examples/Movies/main.m delete mode 100644 Examples/TicTacToe/AppDelegate.h delete mode 100644 Examples/TicTacToe/AppDelegate.m delete mode 100644 Examples/TicTacToe/Base.lproj/LaunchScreen.xib delete mode 100644 Examples/TicTacToe/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Examples/TicTacToe/Info.plist delete mode 100644 Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj delete mode 100644 Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme delete mode 100755 Examples/TicTacToe/TicTacToeApp.js delete mode 100644 Examples/TicTacToe/main.m delete mode 100644 Examples/UIExplorer/ActivityIndicatorExample.js delete mode 100644 Examples/UIExplorer/AppDelegate.h delete mode 100644 Examples/UIExplorer/AppDelegate.m delete mode 100644 Examples/UIExplorer/Base.lproj/LaunchScreen.xib delete mode 100644 Examples/UIExplorer/DatePickerExample.js delete mode 100644 Examples/UIExplorer/ExpandingTextExample.js delete mode 100644 Examples/UIExplorer/GeoLocationExample.js delete mode 100644 Examples/UIExplorer/ImageCapInsetsExample.js delete mode 100644 Examples/UIExplorer/ImageExample.js delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-1.png delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-2.png delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-3.png delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-4.png delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-5.png delete mode 100644 Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x.png delete mode 100644 Examples/UIExplorer/Images.xcassets/story-background.imageset/Contents.json delete mode 100644 Examples/UIExplorer/Images.xcassets/story-background.imageset/story-background.png delete mode 100644 Examples/UIExplorer/Images.xcassets/story-background.imageset/story-background@2x.png delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/Contents.json delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/uie_comment_highlighted@2x.png delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/Contents.json delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/uie_comment_normal@2x.png delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_thumb_normal.imageset/Contents.json delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_thumb_normal.imageset/uie_thumb_normal@2x.png delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/Contents.json delete mode 100644 Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/uie_thumb_selected@2x.png delete mode 100644 Examples/UIExplorer/Info.plist delete mode 100644 Examples/UIExplorer/LayoutExample.js delete mode 100644 Examples/UIExplorer/ListViewPagingExample.js delete mode 100644 Examples/UIExplorer/ListViewSimpleExample.js delete mode 100644 Examples/UIExplorer/NavigatorIOSExample.js delete mode 100644 Examples/UIExplorer/PointerEventsExample.js delete mode 100644 Examples/UIExplorer/ScrollViewExample.js delete mode 100644 Examples/UIExplorer/SliderExample.js delete mode 100644 Examples/UIExplorer/StatusBarIOSExample.js delete mode 100644 Examples/UIExplorer/SwitchExample.js delete mode 100644 Examples/UIExplorer/TabBarExample.js delete mode 100644 Examples/UIExplorer/TextExample.ios.js delete mode 100644 Examples/UIExplorer/TextInputExample.js delete mode 100644 Examples/UIExplorer/TouchableExample.js delete mode 100644 Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj delete mode 100644 Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme delete mode 100644 Examples/UIExplorer/UIExplorerApp.js delete mode 100644 Examples/UIExplorer/UIExplorerBlock.js delete mode 100644 Examples/UIExplorer/UIExplorerList.js delete mode 100644 Examples/UIExplorer/UIExplorerPage.js delete mode 100644 Examples/UIExplorer/UIExplorerTitle.js delete mode 100644 Examples/UIExplorer/ViewExample.js delete mode 100644 Examples/UIExplorer/createExamplePage.js delete mode 100644 Examples/UIExplorer/main.m delete mode 100644 LICENSE delete mode 100644 Libraries/Animation/LayoutAnimation.js delete mode 100644 Libraries/Animation/POPAnimationMixin.js delete mode 100644 Libraries/AppRegistry/AppRegistry.js delete mode 100644 Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js delete mode 100644 Libraries/BatchedBridge/BatchedBridgedModules/NativeModulesDeprecated.js delete mode 100644 Libraries/BatchedBridge/BatchedBridgedModules/POPAnimation.js delete mode 100644 Libraries/BatchedBridge/BatchedBridgedModules/RCTEventEmitter.js delete mode 100644 Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js delete mode 100644 Libraries/BatchedBridge/BatchedBridgedModules/RKAlertManager.ios.js delete mode 100644 Libraries/BatchedBridge/BatchingImplementation/BatchedBridge.js delete mode 100644 Libraries/BatchedBridge/BatchingImplementation/BatchedBridgeFactory.js delete mode 100644 Libraries/Components/ActivityIndicatorIOS/ActivityIndicatorIOS.ios.js delete mode 100644 Libraries/Components/DatePicker/DatePickerIOS.ios.js delete mode 100644 Libraries/Components/ListView/ListView.js delete mode 100644 Libraries/Components/ListView/ListViewDataSource.js delete mode 100644 Libraries/Components/Navigation/NavigatorIOS.ios.js delete mode 100644 Libraries/Components/ScrollResponder.js delete mode 100644 Libraries/Components/ScrollView/ScrollView.js delete mode 100644 Libraries/Components/Slider/Slider.js delete mode 100644 Libraries/Components/StaticRenderer.js delete mode 100644 Libraries/Components/StatusBar/StatusBarIOS.ios.js delete mode 100644 Libraries/Components/Subscribable.js delete mode 100644 Libraries/Components/SwitchIOS/SwitchIOS.android.js delete mode 100644 Libraries/Components/SwitchIOS/SwitchIOS.ios.js delete mode 100644 Libraries/Components/TabBarIOS/TabBarIOS.android.js delete mode 100644 Libraries/Components/TabBarIOS/TabBarIOS.ios.js delete mode 100644 Libraries/Components/TabBarIOS/TabBarItemIOS.android.js delete mode 100644 Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js delete mode 100644 Libraries/Components/TextInput/TextInput.ios.js delete mode 100644 Libraries/Components/TextInput/TextInputState.js delete mode 100644 Libraries/Components/Touchable/TouchableFeedbackPropType.js delete mode 100644 Libraries/Components/Touchable/TouchableHighlight.js delete mode 100644 Libraries/Components/Touchable/TouchableOpacity.js delete mode 100644 Libraries/Components/Touchable/TouchableWithoutFeedback.js delete mode 100644 Libraries/Components/Touchable/ensureComponentIsNative.js delete mode 100644 Libraries/Components/View/View.js delete mode 100644 Libraries/Components/View/ViewStylePropTypes.js delete mode 100644 Libraries/Device/RCTDeviceEventEmitter.js delete mode 100644 Libraries/Fetch/fetch.js delete mode 100644 Libraries/GeoLocation/Geolocation.ios.js delete mode 100644 Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj delete mode 100644 Libraries/GeoLocation/RCTLocationObserver.h delete mode 100644 Libraries/GeoLocation/RCTLocationObserver.m delete mode 100644 Libraries/Image/Image.ios.js delete mode 100644 Libraries/Image/ImageResizeMode.js delete mode 100644 Libraries/Image/ImageStylePropTypes.js delete mode 100644 Libraries/Image/RCTGIFImage.h delete mode 100644 Libraries/Image/RCTGIFImage.m delete mode 100644 Libraries/Image/RCTImage.xcodeproj/project.pbxproj delete mode 100644 Libraries/Image/RCTImageDownloader.h delete mode 100644 Libraries/Image/RCTImageDownloader.m delete mode 100644 Libraries/Image/RCTNetworkImage.podspec delete mode 100644 Libraries/Image/RCTNetworkImageView.h delete mode 100644 Libraries/Image/RCTNetworkImageView.m delete mode 100644 Libraries/Image/RCTNetworkImageViewManager.h delete mode 100644 Libraries/Image/RCTNetworkImageViewManager.m delete mode 100644 Libraries/Image/RCTStaticImage.h delete mode 100644 Libraries/Image/RCTStaticImage.m delete mode 100644 Libraries/Image/RCTStaticImageManager.h delete mode 100644 Libraries/Image/RCTStaticImageManager.m delete mode 100644 Libraries/Image/ix.js delete mode 100644 Libraries/Interaction/InteractionManager.js delete mode 100644 Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js delete mode 100644 Libraries/JavaScriptAppEngine/Initialization/SourceMap.js delete mode 100644 Libraries/JavaScriptAppEngine/Initialization/errorToString.js delete mode 100644 Libraries/JavaScriptAppEngine/Initialization/loadSourceMap.js delete mode 100644 Libraries/JavaScriptAppEngine/System/JSTimers/JSTimers.js delete mode 100644 Libraries/JavaScriptAppEngine/System/JSTimers/JSTimersExecution.js delete mode 100644 Libraries/Network/RCTDataManager.h delete mode 100644 Libraries/Network/RCTDataManager.m delete mode 100644 Libraries/Network/RCTDataManager.podspec delete mode 100644 Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj delete mode 100644 Libraries/Network/XMLHttpRequest.ios.js delete mode 100644 Libraries/RKBackendNode/queryLayoutByID.js delete mode 100644 Libraries/ReactIOS/IOSDefaultEventPluginOrder.js delete mode 100644 Libraries/ReactIOS/IOSNativeBridgeEventPlugin.js delete mode 100644 Libraries/ReactIOS/NativeMethodsMixin.js delete mode 100644 Libraries/ReactIOS/React.js delete mode 100644 Libraries/ReactIOS/ReactIOS.js delete mode 100644 Libraries/ReactIOS/ReactIOSComponentEnvironment.js delete mode 100644 Libraries/ReactIOS/ReactIOSComponentMixin.js delete mode 100644 Libraries/ReactIOS/ReactIOSDOMIDOperations.js delete mode 100644 Libraries/ReactIOS/ReactIOSDefaultInjection.js delete mode 100644 Libraries/ReactIOS/ReactIOSEventEmitter.js delete mode 100644 Libraries/ReactIOS/ReactIOSGlobalInteractionHandler.js delete mode 100644 Libraries/ReactIOS/ReactIOSGlobalResponderHandler.js delete mode 100644 Libraries/ReactIOS/ReactIOSMount.js delete mode 100644 Libraries/ReactIOS/ReactIOSNativeComponent.js delete mode 100644 Libraries/ReactIOS/ReactIOSReconcileTransaction.js delete mode 100644 Libraries/ReactIOS/ReactIOSStyleAttributes.js delete mode 100644 Libraries/ReactIOS/ReactIOSTagHandles.js delete mode 100644 Libraries/ReactIOS/ReactIOSTextComponent.js delete mode 100644 Libraries/ReactIOS/ReactIOSViewAttributes.js delete mode 100644 Libraries/ReactIOS/createReactIOSNativeComponentClass.js delete mode 100644 Libraries/ReactIOS/diffRawProperties.js delete mode 100644 Libraries/ReactIOS/renderApplication.ios.js delete mode 100644 Libraries/StyleSheet/EdgeInsetsPropType.js delete mode 100644 Libraries/StyleSheet/LayoutPropTypes.js delete mode 100644 Libraries/StyleSheet/PointPropType.js delete mode 100644 Libraries/StyleSheet/StyleSheet.js delete mode 100644 Libraries/StyleSheet/StyleSheetPropType.js delete mode 100644 Libraries/StyleSheet/StyleSheetRegistry.js delete mode 100644 Libraries/StyleSheet/flattenStyle.js delete mode 100644 Libraries/StyleSheet/styleDiffer.js delete mode 100644 Libraries/Text/ExpandingText.js delete mode 100644 Libraries/Text/RCTRawTextManager.h delete mode 100644 Libraries/Text/RCTRawTextManager.m delete mode 100644 Libraries/Text/RCTShadowRawText.h delete mode 100644 Libraries/Text/RCTShadowRawText.m delete mode 100644 Libraries/Text/RCTShadowText.h delete mode 100644 Libraries/Text/RCTShadowText.m delete mode 100644 Libraries/Text/RCTText.h delete mode 100644 Libraries/Text/RCTText.m delete mode 100644 Libraries/Text/RCTText.podspec delete mode 100644 Libraries/Text/RCTText.xcodeproj/project.pbxproj delete mode 100644 Libraries/Text/RCTTextManager.h delete mode 100644 Libraries/Text/RCTTextManager.m delete mode 100644 Libraries/Text/Text.js delete mode 100644 Libraries/Text/TextStylePropTypes.js delete mode 100644 Libraries/Utilities/Dimensions.js delete mode 100644 Libraries/Utilities/ErrorUtils.js delete mode 100644 Libraries/Utilities/MessageQueue.js delete mode 100644 Libraries/Utilities/PixelRatio.js delete mode 100644 Libraries/Utilities/Platform.ios.js delete mode 100644 Libraries/Utilities/RCTLog.js delete mode 100644 Libraries/Utilities/RCTRenderingPerf.js delete mode 100644 Libraries/Utilities/TimerMixin.js delete mode 100644 Libraries/Utilities/createStrictShapeTypeChecker.js delete mode 100644 Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.js delete mode 100644 Libraries/Utilities/differ/deepDiffer.js delete mode 100644 Libraries/Utilities/differ/insetsDiffer.js delete mode 100644 Libraries/Utilities/differ/matricesDiffer.js delete mode 100644 Libraries/Utilities/differ/pointsDiffer.js delete mode 100644 Libraries/Utilities/logError.js delete mode 100644 Libraries/Utilities/mergeFast.js delete mode 100644 Libraries/Utilities/mergeIntoFast.js delete mode 100644 Libraries/Utilities/truncate.js delete mode 100644 Libraries/react-native/addons.js delete mode 100644 Libraries/react-native/package.json delete mode 100644 Libraries/react-native/react-native-interface.js delete mode 100644 Libraries/react-native/react-native.js delete mode 100644 Libraries/vendor/core/ES6Promise.js delete mode 100644 Libraries/vendor/core/Map.js delete mode 100644 Libraries/vendor/core/Promise.js delete mode 100644 Libraries/vendor/core/Set.js delete mode 100644 Libraries/vendor/core/_shouldPolyfillES6Collection.js delete mode 100644 Libraries/vendor/core/copyProperties.js delete mode 100644 Libraries/vendor/core/getObjectValues.js delete mode 100644 Libraries/vendor/core/guid.js delete mode 100644 Libraries/vendor/core/immediate/setImmediate.js delete mode 100644 Libraries/vendor/core/isEmpty.js delete mode 100644 Libraries/vendor/core/merge.js delete mode 100644 Libraries/vendor/core/mergeHelpers.js delete mode 100644 Libraries/vendor/core/mergeInto.js delete mode 100644 Libraries/vendor/core/setImmediate.js delete mode 100644 Libraries/vendor/core/throwImmediate.js delete mode 100644 Libraries/vendor/core/toIterator.js delete mode 100644 Libraries/vendor/crypto/crc32.js delete mode 100644 Libraries/vendor/document/selection/DocumentSelectionState.js delete mode 100644 Libraries/vendor/emitter/EmitterSubscription.js delete mode 100644 Libraries/vendor/emitter/EventEmitter.js delete mode 100644 Libraries/vendor/emitter/EventEmitterWithHolding.js delete mode 100644 Libraries/vendor/emitter/EventHolder.js delete mode 100644 Libraries/vendor/emitter/EventSubscription.js delete mode 100644 Libraries/vendor/emitter/EventSubscriptionVendor.js delete mode 100644 Libraries/vendor/emitter/EventValidator.js delete mode 100644 Libraries/vendor/emitter/mixInEventEmitter.js delete mode 100644 Libraries/vendor/react/browser/eventPlugins/ResponderEventPlugin.js delete mode 100644 Libraries/vendor/react/browser/eventPlugins/ResponderSyntheticEvent.js delete mode 100644 Libraries/vendor/react/browser/eventPlugins/ResponderTouchHistoryStore.js delete mode 100644 Libraries/vendor/react/core/ReactInstanceHandles.js delete mode 100644 Libraries/vendor/react/event/EventPropagators.js delete mode 100644 Libraries/vendor/react/platform/NodeHandle.js delete mode 100644 Libraries/vendor/react/platformImplementations/universal/worker/UniversalWorkerNodeHandle.js delete mode 100644 Libraries/vendor/react/vendor/core/ExecutionEnvironment.ios.js delete mode 100644 Libraries/vendor/react_contrib/StaticContainer/StaticContainer.js delete mode 100644 Libraries/vendor/react_contrib/interactions/Touchable/Touchable.js delete mode 100644 Libraries/vendor/react_contrib/pooledClasses/BoundingDimensions.js delete mode 100644 Libraries/vendor/react_contrib/pooledClasses/Position.js delete mode 100644 README.md delete mode 100644 ReactKit/Base/RCTAssert.h delete mode 100644 ReactKit/Base/RCTAssert.m delete mode 100644 ReactKit/Base/RCTBridge.h delete mode 100644 ReactKit/Base/RCTBridge.m delete mode 100644 ReactKit/Base/RCTBridgeModule.h delete mode 100644 ReactKit/Base/RCTCache.h delete mode 100644 ReactKit/Base/RCTCache.m delete mode 100644 ReactKit/Base/RCTConvert.h delete mode 100644 ReactKit/Base/RCTConvert.m delete mode 100644 ReactKit/Base/RCTEventDispatcher.h delete mode 100644 ReactKit/Base/RCTEventDispatcher.m delete mode 100644 ReactKit/Base/RCTInvalidating.h delete mode 100644 ReactKit/Base/RCTJSMethodRegistrar.h delete mode 100644 ReactKit/Base/RCTJavaScriptExecutor.h delete mode 100644 ReactKit/Base/RCTKeyCommands.h delete mode 100644 ReactKit/Base/RCTKeyCommands.m delete mode 100644 ReactKit/Base/RCTLog.h delete mode 100644 ReactKit/Base/RCTLog.m delete mode 100644 ReactKit/Base/RCTRedBox.h delete mode 100644 ReactKit/Base/RCTRedBox.m delete mode 100644 ReactKit/Base/RCTRootView.h delete mode 100644 ReactKit/Base/RCTRootView.m delete mode 100644 ReactKit/Base/RCTSparseArray.h delete mode 100644 ReactKit/Base/RCTSparseArray.m delete mode 100644 ReactKit/Base/RCTTouchHandler.h delete mode 100644 ReactKit/Base/RCTTouchHandler.m delete mode 100644 ReactKit/Base/RCTUtils.h delete mode 100644 ReactKit/Base/RCTUtils.m delete mode 100644 ReactKit/Executors/RCTContextExecutor.h delete mode 100644 ReactKit/Executors/RCTContextExecutor.m delete mode 100644 ReactKit/Executors/RCTWebViewExecutor.h delete mode 100644 ReactKit/Executors/RCTWebViewExecutor.m delete mode 100644 ReactKit/Layout/Layout.c delete mode 100644 ReactKit/Layout/Layout.h delete mode 100644 ReactKit/Modules/RCTAlertManager.h delete mode 100644 ReactKit/Modules/RCTAlertManager.m delete mode 100644 ReactKit/Modules/RCTExceptionsManager.h delete mode 100644 ReactKit/Modules/RCTExceptionsManager.m delete mode 100644 ReactKit/Modules/RCTStatusBarManager.h delete mode 100644 ReactKit/Modules/RCTStatusBarManager.m delete mode 100644 ReactKit/Modules/RCTTiming.h delete mode 100644 ReactKit/Modules/RCTTiming.m delete mode 100644 ReactKit/Modules/RCTUIManager.h delete mode 100644 ReactKit/Modules/RCTUIManager.m delete mode 100644 ReactKit/ReactKit.podspec delete mode 100644 ReactKit/ReactKit.xcodeproj/project.pbxproj delete mode 100644 ReactKit/Views/RCTAnimationType.h delete mode 100644 ReactKit/Views/RCTAutoInsetsProtocol.h delete mode 100644 ReactKit/Views/RCTDatePickerManager.h delete mode 100644 ReactKit/Views/RCTDatePickerManager.m delete mode 100644 ReactKit/Views/RCTNavItem.h delete mode 100644 ReactKit/Views/RCTNavItem.m delete mode 100644 ReactKit/Views/RCTNavItemManager.h delete mode 100644 ReactKit/Views/RCTNavItemManager.m delete mode 100644 ReactKit/Views/RCTNavigator.h delete mode 100644 ReactKit/Views/RCTNavigator.m delete mode 100644 ReactKit/Views/RCTNavigatorManager.h delete mode 100644 ReactKit/Views/RCTNavigatorManager.m delete mode 100644 ReactKit/Views/RCTPointerEvents.h delete mode 100644 ReactKit/Views/RCTScrollView.h delete mode 100644 ReactKit/Views/RCTScrollView.m delete mode 100644 ReactKit/Views/RCTScrollViewManager.h delete mode 100644 ReactKit/Views/RCTScrollViewManager.m delete mode 100644 ReactKit/Views/RCTScrollableProtocol.h delete mode 100644 ReactKit/Views/RCTShadowView.h delete mode 100644 ReactKit/Views/RCTShadowView.m delete mode 100644 ReactKit/Views/RCTSliderManager.h delete mode 100644 ReactKit/Views/RCTSliderManager.m delete mode 100644 ReactKit/Views/RCTSwitch.h delete mode 100644 ReactKit/Views/RCTSwitch.m delete mode 100644 ReactKit/Views/RCTSwitchManager.h delete mode 100644 ReactKit/Views/RCTSwitchManager.m delete mode 100644 ReactKit/Views/RCTTabBar.h delete mode 100644 ReactKit/Views/RCTTabBar.m delete mode 100644 ReactKit/Views/RCTTabBarItem.h delete mode 100644 ReactKit/Views/RCTTabBarItem.m delete mode 100644 ReactKit/Views/RCTTabBarItemManager.h delete mode 100644 ReactKit/Views/RCTTabBarItemManager.m delete mode 100644 ReactKit/Views/RCTTabBarManager.h delete mode 100644 ReactKit/Views/RCTTabBarManager.m delete mode 100644 ReactKit/Views/RCTTextField.h delete mode 100644 ReactKit/Views/RCTTextField.m delete mode 100644 ReactKit/Views/RCTTextFieldManager.h delete mode 100644 ReactKit/Views/RCTTextFieldManager.m delete mode 100644 ReactKit/Views/RCTUIActivityIndicatorViewManager.h delete mode 100644 ReactKit/Views/RCTUIActivityIndicatorViewManager.m delete mode 100644 ReactKit/Views/RCTView.h delete mode 100644 ReactKit/Views/RCTView.m delete mode 100644 ReactKit/Views/RCTViewControllerProtocol.h delete mode 100644 ReactKit/Views/RCTViewManager.h delete mode 100644 ReactKit/Views/RCTViewManager.m delete mode 100644 ReactKit/Views/RCTViewNodeProtocol.h delete mode 100644 ReactKit/Views/RCTWrapperViewController.h delete mode 100644 ReactKit/Views/RCTWrapperViewController.m delete mode 100644 ReactKit/Views/UIView+ReactKit.h delete mode 100644 ReactKit/Views/UIView+ReactKit.m create mode 100644 _index.html rename {website/src/react-native/css => css}/react-native.css (100%) delete mode 100644 docs/GettingStarted.md delete mode 100644 docs/Image.md delete mode 100644 docs/Network.md delete mode 100644 docs/Physical vs Logical Pixels.md delete mode 100644 docs/Style.md delete mode 100644 docs/Text.md delete mode 100644 docs/Timers.md create mode 100644 docs/activityindicatorios.html create mode 100644 docs/animation.html create mode 100644 docs/appregistry.html create mode 100644 docs/appstate.html create mode 100644 docs/appstateios.html create mode 100644 docs/asyncstorage.html create mode 100644 docs/cameraroll.html create mode 100644 docs/datepickerios.html create mode 100644 docs/expandingtext.html create mode 100644 docs/getting-started.html create mode 100644 docs/image.html create mode 100644 docs/layoutanimation.html create mode 100644 docs/listview.html create mode 100644 docs/mapview.html create mode 100644 docs/navigatorios.html create mode 100644 docs/network.html create mode 100644 docs/pickerios.html create mode 100644 docs/pixelratio.html create mode 100644 docs/pixels.html create mode 100644 docs/scrollview.html create mode 100644 docs/slider.html create mode 100644 docs/statusbarios.html create mode 100644 docs/style.html create mode 100644 docs/stylesheet.html create mode 100644 docs/switchios.html create mode 100644 docs/tabbarios.html create mode 100644 docs/text.html create mode 100644 docs/textinput.html create mode 100644 docs/timers.html create mode 100644 docs/touchablehighlight.html create mode 100644 docs/touchableopacity.html create mode 100644 docs/touchablewithoutfeedback.html create mode 100644 docs/view.html rename {website/src/react-native/img => img}/favicon.png (100%) rename {website/src/react-native/img => img}/logo.png (100%) rename {website/src/react-native/img => img}/opengraph.png (100%) rename {website/src/react-native/img => img}/react-native.png (100%) delete mode 100644 jestSupport/env.js delete mode 100644 jestSupport/scriptPreprocess.js delete mode 100644 lint/linterTransform.js delete mode 100644 linter.js delete mode 100644 package.json delete mode 100644 packager/blacklist.js delete mode 100644 packager/launchEditor.js delete mode 100755 packager/launchPackager.command delete mode 100644 packager/packager.js delete mode 100755 packager/packager.sh delete mode 100644 packager/parseCommandLine.js delete mode 100644 packager/react-packager/.npmignore delete mode 100644 packager/react-packager/__mocks__/debug.js delete mode 100644 packager/react-packager/__mocks__/net.js delete mode 100644 packager/react-packager/example_project/bar.js delete mode 100644 packager/react-packager/example_project/config.json delete mode 100644 packager/react-packager/example_project/foo/foo.js delete mode 100644 packager/react-packager/example_project/index.js delete mode 100644 packager/react-packager/example_project/js/Channel.js delete mode 100644 packager/react-packager/example_project/js/XHR.js delete mode 100644 packager/react-packager/example_project/js/code.js delete mode 100644 packager/react-packager/example_project/js/main.js delete mode 100644 packager/react-packager/example_project/public/css/index.css delete mode 100644 packager/react-packager/example_project/public/index.html delete mode 100644 packager/react-packager/index.js delete mode 100644 packager/react-packager/src/Activity/__tests__/Activity-test.js delete mode 100644 packager/react-packager/src/Activity/index.js delete mode 100644 packager/react-packager/src/DependencyResolver/ModuleDescriptor.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__mocks__/fs.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/DependencyGraph/docblock.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/__tests__/HasteDependencyResolver-test.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/index.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/polyfills/console.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/polyfills/error-guard.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/polyfills/polyfills.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/polyfills/prelude.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/polyfills/prelude_dev.js delete mode 100644 packager/react-packager/src/DependencyResolver/haste/polyfills/require.js delete mode 100644 packager/react-packager/src/DependencyResolver/index.js delete mode 100644 packager/react-packager/src/DependencyResolver/node/index.js delete mode 100644 packager/react-packager/src/FileWatcher/__mocks__/sane.js delete mode 100644 packager/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js delete mode 100644 packager/react-packager/src/FileWatcher/index.js delete mode 100644 packager/react-packager/src/JSTransformer/Cache.js delete mode 100644 packager/react-packager/src/JSTransformer/README.md delete mode 100644 packager/react-packager/src/JSTransformer/__mocks__/q.js delete mode 100644 packager/react-packager/src/JSTransformer/__mocks__/underscore.js delete mode 100644 packager/react-packager/src/JSTransformer/__mocks__/worker.js delete mode 100644 packager/react-packager/src/JSTransformer/__tests__/Cache-test.js delete mode 100644 packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js delete mode 100644 packager/react-packager/src/JSTransformer/index.js delete mode 100644 packager/react-packager/src/JSTransformer/worker.js delete mode 100644 packager/react-packager/src/Packager/Package.js delete mode 100644 packager/react-packager/src/Packager/__tests__/Package-test.js delete mode 100644 packager/react-packager/src/Packager/__tests__/Packager-test.js delete mode 100644 packager/react-packager/src/Packager/base64-vlq.js delete mode 100644 packager/react-packager/src/Packager/index.js delete mode 100644 packager/react-packager/src/Server/__tests__/Server-test.js delete mode 100644 packager/react-packager/src/Server/index.js delete mode 100644 packager/react-packager/src/lib/__mocks__/declareOpts.js delete mode 100644 packager/react-packager/src/lib/__tests__/declareOpts-test.js delete mode 100644 packager/react-packager/src/lib/declareOpts.js delete mode 100644 packager/transformer.js create mode 100644 support.html delete mode 100644 website/.gitignore delete mode 100644 website/README.md delete mode 100644 website/core/DocsSidebar.js delete mode 100644 website/core/H2.js delete mode 100644 website/core/Header.js delete mode 100644 website/core/HeaderLinks.js delete mode 100644 website/core/Marked.js delete mode 100644 website/core/Prism.js delete mode 100644 website/core/Site.js delete mode 100644 website/core/center.js delete mode 100644 website/core/slugify.js delete mode 100644 website/core/unindent.js delete mode 100644 website/layout/AutodocsLayout.js delete mode 100644 website/layout/DocsLayout.js delete mode 100644 website/layout/PageLayout.js delete mode 100644 website/package.json delete mode 100755 website/publish.sh delete mode 100644 website/react-docgen/.gitignore delete mode 100644 website/react-docgen/CONTRIBUTING.md delete mode 100644 website/react-docgen/LICENSE delete mode 100644 website/react-docgen/PATENTS delete mode 100644 website/react-docgen/README.md delete mode 100755 website/react-docgen/bin/react-docgen.js delete mode 100755 website/react-docgen/example/buildDocs.sh delete mode 100644 website/react-docgen/example/components/Component.js delete mode 100644 website/react-docgen/example/components/NoComponent.js delete mode 100644 website/react-docgen/example/generateMarkdown.js delete mode 100644 website/react-docgen/flow/react-docgen.js delete mode 100644 website/react-docgen/flow/recast.js delete mode 100644 website/react-docgen/lib/Documentation.js delete mode 100644 website/react-docgen/lib/__mocks__/Documentation.js delete mode 100644 website/react-docgen/lib/__tests__/main-test.js delete mode 100644 website/react-docgen/lib/__tests__/parse-test.js delete mode 100644 website/react-docgen/lib/handlers/__tests__/componentDocblockHandler-test.js delete mode 100644 website/react-docgen/lib/handlers/__tests__/defaultPropsHandler-test.js delete mode 100644 website/react-docgen/lib/handlers/__tests__/propDocblockHandler-test.js delete mode 100644 website/react-docgen/lib/handlers/__tests__/propTypeHandler-test.js delete mode 100644 website/react-docgen/lib/handlers/componentDocblockHandler.js delete mode 100644 website/react-docgen/lib/handlers/defaultPropsHandler.js delete mode 100644 website/react-docgen/lib/handlers/index.js delete mode 100644 website/react-docgen/lib/handlers/propDocBlockHandler.js delete mode 100644 website/react-docgen/lib/handlers/propTypeHandler.js delete mode 100644 website/react-docgen/lib/main.js delete mode 100644 website/react-docgen/lib/parse.js delete mode 100644 website/react-docgen/lib/resolver/__tests__/findAllReactCreateClassCalls-test.js delete mode 100644 website/react-docgen/lib/resolver/__tests__/findExportedReactCreateClassCall-test.js delete mode 100644 website/react-docgen/lib/resolver/findAllReactCreateClassCalls.js delete mode 100644 website/react-docgen/lib/resolver/findExportedReactCreateClassCall.js delete mode 100644 website/react-docgen/lib/resolver/index.js delete mode 100644 website/react-docgen/lib/utils/__tests__/docblock-test.js delete mode 100644 website/react-docgen/lib/utils/__tests__/getMembers-test.js delete mode 100644 website/react-docgen/lib/utils/__tests__/getPropType-test.js delete mode 100644 website/react-docgen/lib/utils/__tests__/getPropertyValuePath-test.js delete mode 100644 website/react-docgen/lib/utils/__tests__/isExportsOrModuleAssignment-test.js delete mode 100644 website/react-docgen/lib/utils/__tests__/match-test.js delete mode 100644 website/react-docgen/lib/utils/docblock.js delete mode 100644 website/react-docgen/lib/utils/expressionTo.js delete mode 100644 website/react-docgen/lib/utils/getMembers.js delete mode 100644 website/react-docgen/lib/utils/getNameOrValue.js delete mode 100644 website/react-docgen/lib/utils/getPropType.js delete mode 100644 website/react-docgen/lib/utils/getPropertyName.js delete mode 100644 website/react-docgen/lib/utils/getPropertyValuePath.js delete mode 100644 website/react-docgen/lib/utils/index.js delete mode 100644 website/react-docgen/lib/utils/isExportsOrModuleAssignment.js delete mode 100644 website/react-docgen/lib/utils/isReactCreateClassCall.js delete mode 100644 website/react-docgen/lib/utils/isReactModuleName.js delete mode 100644 website/react-docgen/lib/utils/match.js delete mode 100644 website/react-docgen/lib/utils/resolveToModule.js delete mode 100644 website/react-docgen/lib/utils/resolveToValue.js delete mode 100644 website/react-docgen/package.json delete mode 100644 website/react-docgen/preprocessor.js delete mode 100644 website/react-docgen/tests/preprocessor.js delete mode 100644 website/react-docgen/tests/utils.js delete mode 100644 website/server/convert.js delete mode 100644 website/server/extractDocs.js delete mode 100644 website/server/generate.js delete mode 100644 website/server/server.js delete mode 100644 website/src/react-native/index.js delete mode 100644 website/src/react-native/support.js diff --git a/Examples/Movies/AppDelegate.h b/Examples/Movies/AppDelegate.h deleted file mode 100644 index f0ec66bdb5b..00000000000 --- a/Examples/Movies/AppDelegate.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface AppDelegate : UIResponder - -@property (nonatomic, strong) UIWindow *window; - -@end - diff --git a/Examples/Movies/AppDelegate.m b/Examples/Movies/AppDelegate.m deleted file mode 100644 index c01fc2ca9f2..00000000000 --- a/Examples/Movies/AppDelegate.m +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "AppDelegate.h" - -#import "RCTRootView.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - NSURL *jsCodeLocation; - RCTRootView *rootView = [[RCTRootView alloc] init]; - - // Loading JavaScript code - uncomment the one you want. - - // OPTION 1 - // Load from development server. Start the server from the repository root: - // - // $ npm start - // - // To run on device, change `localhost` to the IP address of your computer, and make sure your computer and - // iOS device are on the same Wi-Fi network. - jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle"]; - - // OPTION 2 - // Load from pre-bundled file on disk. To re-generate the static bundle, run - // - // $ curl http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle -o main.jsbundle - // - // and uncomment the next following line - // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; - - rootView.scriptURL = jsCodeLocation; - rootView.moduleName = @"MoviesApp"; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [[UIViewController alloc] init]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - return YES; -} - -@end diff --git a/Examples/Movies/Base.lproj/LaunchScreen.xib b/Examples/Movies/Base.lproj/LaunchScreen.xib deleted file mode 100644 index d3f0b52a88a..00000000000 --- a/Examples/Movies/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/Movies/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/Movies/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 118c98f7461..00000000000 --- a/Examples/Movies/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/Movies/Info.plist b/Examples/Movies/Info.plist deleted file mode 100644 index 3c7e8c72e4a..00000000000 --- a/Examples/Movies/Info.plist +++ /dev/null @@ -1,40 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.facebook.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UIViewControllerBasedStatusBarAppearance - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/Examples/Movies/MovieCell.js b/Examples/Movies/MovieCell.js deleted file mode 100644 index 749efa1d231..00000000000 --- a/Examples/Movies/MovieCell.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * @flow - */ -'use strict'; - -var React = require('react-native'); -var { - Image, - PixelRatio, - StyleSheet, - Text, - TouchableHighlight, - View -} = React; - -var getStyleFromScore = require('./getStyleFromScore'); -var getImageSource = require('./getImageSource'); -var getTextFromScore = require('./getTextFromScore'); - -var MovieCell = React.createClass({ - render: function() { - var criticsScore = this.props.movie.ratings.critics_score; - return ( - - - - - - - {this.props.movie.title} - - - {this.props.movie.year} - {' '}•{' '} - - Critics {getTextFromScore(criticsScore)} - - - - - - - - ); - } -}); - -var styles = StyleSheet.create({ - textContainer: { - flex: 1, - }, - movieTitle: { - flex: 1, - fontSize: 16, - fontWeight: 'bold', - marginBottom: 2, - }, - movieYear: { - color: '#999999', - fontSize: 12, - }, - row: { - alignItems: 'center', - backgroundColor: 'white', - flexDirection: 'row', - padding: 5, - }, - cellImage: { - backgroundColor: '#dddddd', - height: 93, - marginRight: 10, - width: 60, - }, - cellBorder: { - backgroundColor: 'rgba(0, 0, 0, 0.1)', - // Trick to get the thinest line the device can display - height: 1 / PixelRatio.get(), - marginLeft: 4, - }, -}); - -module.exports = MovieCell; diff --git a/Examples/Movies/MovieScreen.js b/Examples/Movies/MovieScreen.js deleted file mode 100644 index 53c8879dc02..00000000000 --- a/Examples/Movies/MovieScreen.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * @flow - */ -'use strict'; - -var React = require('react-native'); -var { - ExpandingText, - Image, - PixelRatio, - ScrollView, - StyleSheet, - Text, - View, -} = React; - -var getImageSource = require('./getImageSource'); -var getStyleFromScore = require('./getStyleFromScore'); -var getTextFromScore = require('./getTextFromScore'); - -var MovieScreen = React.createClass({ - render: function() { - return ( - - - - - {this.props.movie.title} - {this.props.movie.year} - - - {this.props.movie.mpaa_rating} - - - - - - - - - - - ); - }, -}); - -var Ratings = React.createClass({ - render: function() { - var criticsScore = this.props.ratings.critics_score; - var audienceScore = this.props.ratings.audience_score; - - return ( - - - Critics: - - {getTextFromScore(criticsScore)} - - - - Audience: - - {getTextFromScore(audienceScore)} - - - - ); - }, -}); - -var Cast = React.createClass({ - render: function() { - if (!this.props.actors) { - return null; - } - - return ( - - Actors - {this.props.actors.map(actor => - - • {actor.name} - - )} - - ); - }, -}); - -var styles = StyleSheet.create({ - contentContainer: { - padding: 10, - }, - rightPane: { - justifyContent: 'space-between', - flex: 1, - }, - movieTitle: { - flex: 1, - fontSize: 16, - fontWeight: 'bold', - }, - rating: { - marginTop: 10, - }, - ratingTitle: { - fontSize: 14, - }, - ratingValue: { - fontSize: 28, - fontWeight: 'bold', - }, - mpaaWrapper: { - alignSelf: 'flex-start', - borderColor: 'black', - borderWidth: 1, - paddingHorizontal: 3, - marginVertical: 5, - }, - mpaaText: { - fontFamily: 'Palatino', - fontSize: 13, - fontWeight: 'bold', - }, - mainSection: { - flexDirection: 'row', - }, - detailsImage: { - width: 134, - height: 200, - backgroundColor: '#eaeaea', - marginRight: 10, - }, - separator: { - backgroundColor: 'rgba(0, 0, 0, 0.1)', - height: 1 / PixelRatio.get(), - marginVertical: 10, - }, - castTitle: { - fontWeight: 'bold', - marginBottom: 3, - }, - castActor: { - marginLeft: 2, - }, -}); - -module.exports = MovieScreen; diff --git a/Examples/Movies/Movies.xcodeproj/project.pbxproj b/Examples/Movies/Movies.xcodeproj/project.pbxproj deleted file mode 100644 index 5d450af8b0e..00000000000 --- a/Examples/Movies/Movies.xcodeproj/project.pbxproj +++ /dev/null @@ -1,435 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341801B1AA91740003F314A /* libRCTNetwork.a */; }; - 13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13442C051AA90E7D0037E5B0 /* libRCTImage.a */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; - 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5725B1AA6236500CDF9C8 /* libRCTText.a */; }; - 58C5726C1AA623A200CDF9C8 /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C572681AA6236600CDF9C8 /* libReactKit.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 1341801A1AA91740003F314A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B511DB1A9E6C8500147676; - remoteInfo = RCTNetwork; - }; - 13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5115D1A9E6B3D00147676; - remoteInfo = RCTImage; - }; - 58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5119B1A9E6C1200147676; - remoteInfo = RCTText; - }; - 58C572671AA6236600CDF9C8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; - remoteInfo = ReactKit; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 134180151AA91740003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = ""; }; - 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* Movies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Movies.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = SOURCE_ROOT; }; - 587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */, - 13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */, - 58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */, - 58C5726C1AA623A200CDF9C8 /* libReactKit.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 134180161AA91740003F314A /* Products */ = { - isa = PBXGroup; - children = ( - 1341801B1AA91740003F314A /* libRCTNetwork.a */, - ); - name = Products; - sourceTree = ""; - }; - 13442C011AA90E7D0037E5B0 /* Products */ = { - isa = PBXGroup; - children = ( - 13442C051AA90E7D0037E5B0 /* libRCTImage.a */, - ); - name = Products; - sourceTree = ""; - }; - 13B07FAE1A68108700A75B9A /* Movies */ = { - isa = PBXGroup; - children = ( - 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.m */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, - 13B07FB61A68108700A75B9A /* Info.plist */, - 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, - 13B07FB71A68108700A75B9A /* main.m */, - ); - name = Movies; - sourceTree = ""; - }; - 58C571FC1AA6124500CDF9C8 /* Libraries */ = { - isa = PBXGroup; - children = ( - 134180151AA91740003F314A /* RCTNetwork.xcodeproj */, - 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */, - 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */, - 587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */, - ); - name = Libraries; - sourceTree = ""; - }; - 58C572571AA6236500CDF9C8 /* Products */ = { - isa = PBXGroup; - children = ( - 58C5725B1AA6236500CDF9C8 /* libRCTText.a */, - ); - name = Products; - sourceTree = ""; - }; - 58C5725C1AA6236500CDF9C8 /* Products */ = { - isa = PBXGroup; - children = ( - 58C572681AA6236600CDF9C8 /* libReactKit.a */, - ); - name = Products; - sourceTree = ""; - }; - 83CBB9F61A601CBA00E9B192 = { - isa = PBXGroup; - children = ( - 13B07FAE1A68108700A75B9A /* Movies */, - 58C571FC1AA6124500CDF9C8 /* Libraries */, - 83CBBA001A601CBA00E9B192 /* Products */, - ); - sourceTree = ""; - }; - 83CBBA001A601CBA00E9B192 /* Products */ = { - isa = PBXGroup; - children = ( - 13B07F961A680F5B00A75B9A /* Movies.app */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 13B07F861A680F5B00A75B9A /* Movies */ = { - isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Movies" */; - buildPhases = ( - 13B07F871A680F5B00A75B9A /* Sources */, - 13B07F8C1A680F5B00A75B9A /* Frameworks */, - 13B07F8E1A680F5B00A75B9A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Movies; - productName = "Hello World"; - productReference = 13B07F961A680F5B00A75B9A /* Movies.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83CBB9F71A601CBA00E9B192 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Movies" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83CBB9F61A601CBA00E9B192; - productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 13442C011AA90E7D0037E5B0 /* Products */; - ProjectRef = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */; - }, - { - ProductGroup = 134180161AA91740003F314A /* Products */; - ProjectRef = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */; - }, - { - ProductGroup = 58C572571AA6236500CDF9C8 /* Products */; - ProjectRef = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */; - }, - { - ProductGroup = 58C5725C1AA6236500CDF9C8 /* Products */; - ProjectRef = 587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 13B07F861A680F5B00A75B9A /* Movies */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 1341801B1AA91740003F314A /* libRCTNetwork.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTNetwork.a; - remoteRef = 1341801A1AA91740003F314A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 13442C051AA90E7D0037E5B0 /* libRCTImage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTImage.a; - remoteRef = 13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 58C5725B1AA6236500CDF9C8 /* libRCTText.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTText.a; - remoteRef = 58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 58C572681AA6236600CDF9C8 /* libReactKit.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReactKit.a; - remoteRef = 58C572671AA6236600CDF9C8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 13B07F8E1A680F5B00A75B9A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, - 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 13B07F871A680F5B00A75B9A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 13B07FB21A68108700A75B9A /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 13B07F941A680F5B00A75B9A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Network/build/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = Movies; - }; - name = Debug; - }; - 13B07F951A680F5B00A75B9A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Network/build/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = Movies; - }; - name = Release; - }; - 83CBBA201A601CBA00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 83CBBA211A601CBA00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Movies" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 13B07F941A680F5B00A75B9A /* Debug */, - 13B07F951A680F5B00A75B9A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Movies" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug */, - 83CBBA211A601CBA00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; -} diff --git a/Examples/Movies/Movies.xcodeproj/xcshareddata/xcschemes/Movies.xcscheme b/Examples/Movies/Movies.xcodeproj/xcshareddata/xcschemes/Movies.xcscheme deleted file mode 100644 index 18b45cad0a4..00000000000 --- a/Examples/Movies/Movies.xcodeproj/xcshareddata/xcschemes/Movies.xcscheme +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/Movies/MoviesApp.js b/Examples/Movies/MoviesApp.js deleted file mode 100644 index 768ad895aba..00000000000 --- a/Examples/Movies/MoviesApp.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule MoviesApp - * @flow - */ -'use strict'; - -var React = require('react-native/addons'); -var { - AppRegistry, - NavigatorIOS, - StyleSheet, -} = React; - -var SearchScreen = require('./SearchScreen'); - -var MoviesApp = React.createClass({ - render: function() { - return ( - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: 'white', - }, -}); - -AppRegistry.registerComponent('MoviesApp', () => MoviesApp); - -module.exports = MoviesApp; diff --git a/Examples/Movies/SearchScreen.js b/Examples/Movies/SearchScreen.js deleted file mode 100644 index 3c451fd67b0..00000000000 --- a/Examples/Movies/SearchScreen.js +++ /dev/null @@ -1,337 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * @flow - */ -'use strict'; - -var React = require('react-native'); -var { - ListView, - ScrollView, - ActivityIndicatorIOS, - StyleSheet, - Text, - TextInput, - TimerMixin, - View, -} = React; - -var MovieCell = require('./MovieCell'); -var MovieScreen = require('./MovieScreen'); - -var fetch = require('fetch'); - -var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/'; -var API_KEYS = ['7waqfqbprs7pajbz28mqf6vz', 'y4vwv8m33hed9ety83jmv52f']; - -// Results should be cached keyed by the query -// with values of null meaning "being fetched" -// and anything besides null and undefined -// as the result of a valid query -var resultsCache = { - dataForQuery: {}, - nextPageNumberForQuery: {}, - totalForQuery: {}, -}; - -var LOADING = {}; - -var SearchScreen = React.createClass({ - mixins: [TimerMixin], - - getInitialState: function() { - return { - isLoading: false, - isLoadingTail: false, - dataSource: new ListView.DataSource({ - rowHasChanged: (row1, row2) => row1 !== row2, - }), - filter: '', - queryNumber: 0, - }; - }, - - componentDidMount: function() { - this.searchMovies(''); - }, - - _urlForQueryAndPage: function(query: string, pageNumber: ?number): string { - var apiKey = API_KEYS[this.state.queryNumber % API_KEYS.length]; - if (query) { - return ( - API_URL + 'movies.json?apikey=' + apiKey + '&q=' + - encodeURIComponent(query) + '&page_limit=20&page=' + pageNumber - ); - } else { - // With no query, load latest movies - return ( - API_URL + 'lists/movies/in_theaters.json?apikey=' + apiKey + - '&page_limit=20&page=' + pageNumber - ); - } - }, - - searchMovies: function(query: string) { - this.timeoutID = null; - - this.setState({filter: query}); - - var cachedResultsForQuery = resultsCache.dataForQuery[query]; - if (cachedResultsForQuery) { - if (!LOADING[query]) { - this.setState({ - dataSource: this.getDataSource(cachedResultsForQuery), - isLoading: false - }); - } else { - this.setState({isLoading: true}); - } - return; - } - - LOADING[query] = true; - resultsCache.dataForQuery[query] = null; - this.setState({ - isLoading: true, - queryNumber: this.state.queryNumber + 1, - isLoadingTail: false, - }); - - fetch(this._urlForQueryAndPage(query, 1)) - .then((response) => response.json()) - .then((responseData) => { - LOADING[query] = false; - resultsCache.totalForQuery[query] = responseData.total; - resultsCache.dataForQuery[query] = responseData.movies; - resultsCache.nextPageNumberForQuery[query] = 2; - - if (this.state.filter !== query) { - // do not update state if the query is stale - return; - } - - this.setState({ - isLoading: false, - dataSource: this.getDataSource(responseData.movies), - }); - }) - .catch((error) => { - LOADING[query] = false; - resultsCache.dataForQuery[query] = undefined; - - this.setState({ - dataSource: this.getDataSource([]), - isLoading: false, - }); - }); - }, - - hasMore: function(): boolean { - var query = this.state.filter; - if (!resultsCache.dataForQuery[query]) { - return true; - } - return ( - resultsCache.totalForQuery[query] !== - resultsCache.dataForQuery[query].length - ); - }, - - onEndReached: function() { - var query = this.state.filter; - if (!this.hasMore() || this.state.isLoadingTail) { - // We're already fetching or have all the elements so noop - return; - } - - if (LOADING[query]) { - return; - } - - LOADING[query] = true; - this.setState({ - queryNumber: this.state.queryNumber + 1, - isLoadingTail: true, - }); - - var page = resultsCache.nextPageNumberForQuery[query]; - fetch(this._urlForQueryAndPage(query, page)) - .then((response) => response.json()) - .then((responseData) => { - var moviesForQuery = resultsCache.dataForQuery[query].slice(); - - LOADING[query] = false; - // We reached the end of the list before the expected number of results - if (!responseData.movies) { - resultsCache.totalForQuery[query] = moviesForQuery.length; - } else { - for (var i in responseData.movies) { - moviesForQuery.push(responseData.movies[i]); - } - resultsCache.dataForQuery[query] = moviesForQuery; - resultsCache.nextPageNumberForQuery[query] += 1; - } - - if (this.state.filter !== query) { - // do not update state if the query is stale - return; - } - - this.setState({ - isLoadingTail: false, - dataSource: this.getDataSource(resultsCache.dataForQuery[query]), - }); - }) - .catch((error) => { - console.error(error); - LOADING[query] = false; - this.setState({ - isLoadingTail: false, - }); - }); - }, - - getDataSource: function(movies: Array): ListView.DataSource { - return this.state.dataSource.cloneWithRows(movies); - }, - - selectMovie: function(movie: Object) { - this.props.navigator.push({ - title: movie.title, - component: MovieScreen, - passProps: {movie}, - }); - }, - - onSearchChange: function(event: Object) { - var filter = event.nativeEvent.text.toLowerCase(); - - this.clearTimeout(this.timeoutID); - this.timeoutID = this.setTimeout(() => this.searchMovies(filter), 100); - }, - - renderFooter: function() { - if (!this.hasMore() || !this.state.isLoadingTail) { - return ; - } - return ; - }, - - renderRow: function(movie: Object) { - return ( - this.selectMovie(movie)} - movie={movie} - /> - ); - }, - - render: function() { - var content = this.state.dataSource.getRowCount() === 0 ? - : - ; - - return ( - - this.refs.listview.getScrollResponder().scrollTo(0, 0)} - /> - - {content} - - ); - }, -}); - -var NoMovies = React.createClass({ - render: function() { - var text = ''; - if (this.props.filter) { - text = `No results for “${this.props.filter}”`; - } else if (!this.props.isLoading) { - // If we're looking at the latest movies, aren't currently loading, and - // still have no results, show a message - text = 'No movies found'; - } - - return ( - - {text} - - ); - } -}); - -var SearchBar = React.createClass({ - render: function() { - return ( - - - - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: 'white', - }, - centerText: { - alignItems: 'center', - }, - noMoviesText: { - marginTop: 80, - color: '#888888', - }, - searchBar: { - marginTop: 64, - padding: 3, - paddingLeft: 8, - flexDirection: 'row', - alignItems: 'center', - }, - searchBarInput: { - fontSize: 15, - flex: 1, - height: 30, - }, - separator: { - height: 1, - backgroundColor: '#eeeeee', - }, - spinner: { - width: 30, - }, - scrollSpinner: { - marginVertical: 20, - }, -}); - -module.exports = SearchScreen; diff --git a/Examples/Movies/__tests__/getImageSource-test.js b/Examples/Movies/__tests__/getImageSource-test.js deleted file mode 100644 index d4a2e9df1b5..00000000000 --- a/Examples/Movies/__tests__/getImageSource-test.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - */ -'use strict'; - -jest.dontMock('../getImageSource'); - -var getImageSource = require('../getImageSource'); - -describe('getImageSource', () => { - it('returns null for invalid input', () => { - expect(getImageSource().uri).toBe(null); - }); - - it('returns a movie thumbnail', () => { - var uri = 'https://facebook.com'; - var source = { - posters: { - thumbnail: uri, - }, - }; - expect(getImageSource(source).uri).toBe(uri); - }); - - it('returns a movie thumbnail with kind', () => { - var uri = 'https://facebook.com?tmb'; - var source = { - posters: { - thumbnail: uri, - }, - }; - expect(getImageSource(source, 'kind').uri).toBe( - 'https://facebook.com?kind' - ); - }); -}); diff --git a/Examples/Movies/getImageSource.js b/Examples/Movies/getImageSource.js deleted file mode 100644 index b01cc286a47..00000000000 --- a/Examples/Movies/getImageSource.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * @flow - */ -'use strict'; - -function getImageSource(movie: Object, kind: ?string): {uri: ?string} { - var uri = movie && movie.posters ? movie.posters.thumbnail : null; - if (uri && kind) { - uri = uri.replace('tmb', kind); - } - return { uri }; -} - -module.exports = getImageSource; diff --git a/Examples/Movies/getStyleFromScore.js b/Examples/Movies/getStyleFromScore.js deleted file mode 100644 index 37252095e2d..00000000000 --- a/Examples/Movies/getStyleFromScore.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * @flow - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, -} = React; - -var MAX_VALUE = 200; - -function getStyleFromScore(score: number): {color: string} { - if (score < 0) { - return styles.noScore; - } - - var normalizedScore = Math.round((score / 100) * MAX_VALUE); - return { - color: 'rgb(' + - (MAX_VALUE - normalizedScore) + ', ' + - normalizedScore + ', ' + - 0 + - ')' - }; -} - -var styles = StyleSheet.create({ - noScore: { - color: '#999999', - }, -}); - -module.exports = getStyleFromScore; diff --git a/Examples/Movies/getTextFromScore.js b/Examples/Movies/getTextFromScore.js deleted file mode 100644 index d0ad6d31cd6..00000000000 --- a/Examples/Movies/getTextFromScore.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * @flow - */ -'use strict'; - -function getTextFromScore(score: number): string { - return score > 0 ? score + '%' : 'N/A'; -} - -module.exports = getTextFromScore; diff --git a/Examples/Movies/main.m b/Examples/Movies/main.m deleted file mode 100644 index 357a233b128..00000000000 --- a/Examples/Movies/main.m +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/Examples/TicTacToe/AppDelegate.h b/Examples/TicTacToe/AppDelegate.h deleted file mode 100644 index 062fb99c000..00000000000 --- a/Examples/TicTacToe/AppDelegate.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface AppDelegate : UIResponder - -@property (nonatomic, strong) UIWindow *window; - -@end diff --git a/Examples/TicTacToe/AppDelegate.m b/Examples/TicTacToe/AppDelegate.m deleted file mode 100644 index 52e6827524c..00000000000 --- a/Examples/TicTacToe/AppDelegate.m +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "AppDelegate.h" - -#import "RCTRootView.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - NSURL *jsCodeLocation; - RCTRootView *rootView = [[RCTRootView alloc] init]; - - // Loading JavaScript code - uncomment the one you want. - - // OPTION 1 - // Load from development server. Start the server from the repository root: - // - // $ npm start - // - // To run on device, change `localhost` to the IP address of your computer, and make sure your computer and - // iOS device are on the same Wi-Fi network. - jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/TicTacToe/TicTacToeApp.includeRequire.runModule.bundle"]; - - // OPTION 2 - // Load from pre-bundled file on disk. To re-generate the static bundle, run - // - // $ curl http://localhost:8081/Examples/TicTacToe/TicTacToeApp.includeRequire.runModule.bundle -o main.jsbundle - // - // and uncomment the next following line - // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; - - rootView.scriptURL = jsCodeLocation; - rootView.moduleName = @"TicTacToeApp"; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [[UIViewController alloc] init]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - return YES; -} - -@end diff --git a/Examples/TicTacToe/Base.lproj/LaunchScreen.xib b/Examples/TicTacToe/Base.lproj/LaunchScreen.xib deleted file mode 100644 index c2d4e907904..00000000000 --- a/Examples/TicTacToe/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/TicTacToe/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/TicTacToe/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 118c98f7461..00000000000 --- a/Examples/TicTacToe/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/TicTacToe/Info.plist b/Examples/TicTacToe/Info.plist deleted file mode 100644 index 9a7ca7e3cc9..00000000000 --- a/Examples/TicTacToe/Info.plist +++ /dev/null @@ -1,40 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.facebook.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj b/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj deleted file mode 100644 index 7cc9c357b6c..00000000000 --- a/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj +++ /dev/null @@ -1,389 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1341803E1AA91802003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341803D1AA917ED003F314A /* libRCTImage.a */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; - 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 58C572501AA6229900CDF9C8 /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C572471AA6224300CDF9C8 /* libReactKit.a */; }; - 58C572511AA6229D00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5724D1AA6224400CDF9C8 /* libRCTText.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 1341803C1AA917ED003F314A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 134180381AA917ED003F314A /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5115D1A9E6B3D00147676; - remoteInfo = RCTImage; - }; - 58C572461AA6224300CDF9C8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; - remoteInfo = ReactKit; - }; - 58C5724C1AA6224400CDF9C8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5119B1A9E6C1200147676; - remoteInfo = RCTText; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 134180381AA917ED003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* TicTacToe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TicTacToe.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = ""; }; - 587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1341803E1AA91802003F314A /* libRCTImage.a in Frameworks */, - 58C572501AA6229900CDF9C8 /* libReactKit.a in Frameworks */, - 58C572511AA6229D00CDF9C8 /* libRCTText.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 134180391AA917ED003F314A /* Products */ = { - isa = PBXGroup; - children = ( - 1341803D1AA917ED003F314A /* libRCTImage.a */, - ); - name = Products; - sourceTree = ""; - }; - 13B07FAE1A68108700A75B9A /* TicTacToe */ = { - isa = PBXGroup; - children = ( - 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.m */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, - 13B07FB61A68108700A75B9A /* Info.plist */, - 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, - 13B07FB71A68108700A75B9A /* main.m */, - ); - name = TicTacToe; - sourceTree = ""; - }; - 58C572071AA6126D00CDF9C8 /* Libraries */ = { - isa = PBXGroup; - children = ( - 134180381AA917ED003F314A /* RCTImage.xcodeproj */, - 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */, - 587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */, - ); - name = Libraries; - sourceTree = ""; - }; - 58C572411AA6224300CDF9C8 /* Products */ = { - isa = PBXGroup; - children = ( - 58C572471AA6224300CDF9C8 /* libReactKit.a */, - ); - name = Products; - sourceTree = ""; - }; - 58C572481AA6224300CDF9C8 /* Products */ = { - isa = PBXGroup; - children = ( - 58C5724D1AA6224400CDF9C8 /* libRCTText.a */, - ); - name = Products; - sourceTree = ""; - }; - 83CBB9F61A601CBA00E9B192 = { - isa = PBXGroup; - children = ( - 13B07FAE1A68108700A75B9A /* TicTacToe */, - 58C572071AA6126D00CDF9C8 /* Libraries */, - 83CBBA001A601CBA00E9B192 /* Products */, - ); - sourceTree = ""; - }; - 83CBBA001A601CBA00E9B192 /* Products */ = { - isa = PBXGroup; - children = ( - 13B07F961A680F5B00A75B9A /* TicTacToe.app */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 13B07F861A680F5B00A75B9A /* TicTacToe */ = { - isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "TicTacToe" */; - buildPhases = ( - 13B07F871A680F5B00A75B9A /* Sources */, - 13B07F8C1A680F5B00A75B9A /* Frameworks */, - 13B07F8E1A680F5B00A75B9A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TicTacToe; - productName = "Hello World"; - productReference = 13B07F961A680F5B00A75B9A /* TicTacToe.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83CBB9F71A601CBA00E9B192 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83CBB9F61A601CBA00E9B192; - productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 134180391AA917ED003F314A /* Products */; - ProjectRef = 134180381AA917ED003F314A /* RCTImage.xcodeproj */; - }, - { - ProductGroup = 58C572481AA6224300CDF9C8 /* Products */; - ProjectRef = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */; - }, - { - ProductGroup = 58C572411AA6224300CDF9C8 /* Products */; - ProjectRef = 587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 13B07F861A680F5B00A75B9A /* TicTacToe */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 1341803D1AA917ED003F314A /* libRCTImage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTImage.a; - remoteRef = 1341803C1AA917ED003F314A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 58C572471AA6224300CDF9C8 /* libReactKit.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReactKit.a; - remoteRef = 58C572461AA6224300CDF9C8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 58C5724D1AA6224400CDF9C8 /* libRCTText.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTText.a; - remoteRef = 58C5724C1AA6224400CDF9C8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 13B07F8E1A680F5B00A75B9A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, - 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 13B07F871A680F5B00A75B9A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 13B07FB21A68108700A75B9A /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 13B07F941A680F5B00A75B9A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = TicTacToe; - }; - name = Debug; - }; - 13B07F951A680F5B00A75B9A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = TicTacToe; - }; - name = Release; - }; - 83CBBA201A601CBA00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 83CBBA211A601CBA00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "TicTacToe" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 13B07F941A680F5B00A75B9A /* Debug */, - 13B07F951A680F5B00A75B9A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug */, - 83CBBA211A601CBA00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; -} diff --git a/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme b/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme deleted file mode 100644 index 5903ce6f405..00000000000 --- a/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/TicTacToe/TicTacToeApp.js b/Examples/TicTacToe/TicTacToeApp.js deleted file mode 100755 index 913123c4541..00000000000 --- a/Examples/TicTacToe/TicTacToeApp.js +++ /dev/null @@ -1,322 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TicTacToeApp - * @flow - */ -'use strict'; - -var React = require('react-native'); -var { - AppRegistry, - Image, - StyleSheet, - Text, - TouchableHighlight, - View, -} = React; - -class Board { - grid: Array>; - turn: number; - - constructor() { - var size = 3; - var grid = Array(size); - for (var i = 0; i < size; i++) { - var row = Array(size); - for (var j = 0; j < size; j++) { - row[j] = 0; - } - grid[i] = row; - } - this.grid = grid; - - this.turn = 1; - } - - mark(row: number, col: number, player: number): Board { - this.grid[row][col] = player; - return this; - } - - hasMark(row: number, col: number): boolean { - return this.grid[row][col] !== 0; - } - - winner(): ?number { - for (var i = 0; i < 3; i++) { - if (this.grid[i][0] !== 0 && this.grid[i][0] === this.grid[i][1] && - this.grid[i][0] === this.grid[i][2]) { - return this.grid[i][0]; - } - } - - for (var i = 0; i < 3; i++) { - if (this.grid[0][i] !== 0 && this.grid[0][i] === this.grid[1][i] && - this.grid[0][i] === this.grid[2][i]) { - return this.grid[0][i]; - } - } - - if (this.grid[0][0] !== 0 && this.grid[0][0] === this.grid[1][1] && - this.grid[0][0] === this.grid[2][2]) { - return this.grid[0][0]; - } - - if (this.grid[0][2] !== 0 && this.grid[0][2] === this.grid[1][1] && - this.grid[0][2] === this.grid[2][0]) { - return this.grid[0][2]; - } - - return null; - } - - tie(): boolean { - for (var i = 0; i < 3; i++) { - for (var j = 0; j < 3; j++) { - if (this.grid[i][j] === 0) { - return false; - } - } - } - - return this.winner() === null; - } -} - -var Cell = React.createClass({ - cellStyle() { - switch (this.props.player) { - case 1: - return styles.cellX; - case 2: - return styles.cellO; - default: - return null; - } - }, - - textStyle() { - switch (this.props.player) { - case 1: - return styles.cellTextX; - case 2: - return styles.cellTextO; - default: - return {}; - } - }, - - textContents() { - switch (this.props.player) { - case 1: - return 'X'; - case 2: - return 'O'; - default: - return ''; - } - }, - - imageContents() { - switch (this.props.player) { - case 1: - return 'http://www.picgifs.com/alphabets/alphabets/children-5/alphabets-children-5-277623.gif'; - case 2: - return 'http://www.picgifs.com/alphabets/alphabets/children-5/alphabets-children-5-730492.gif'; - default: - return ''; - } - }, - - render() { - return ( - - - - - - ); - } -}); - -var GameEndOverlay = React.createClass({ - render() { - var board = this.props.board; - - var tie = board.tie(); - var winner = board.winner(); - if (!winner && !tie) { - return ; - } - - var message; - if (tie) { - message = 'It\'s a tie!'; - } else { - message = (winner === 1 ? 'X' : 'O') + ' wins!'; - } - - return ( - - {message} - - - New Game - - - - ); - } -}); - -var TicTacToeApp = React.createClass({ - getInitialState() { - return { board: new Board(), player: 1 }; - }, - - restartGame() { - this.setState(this.getInitialState()); - }, - - nextPlayer(): number { - return this.state.player === 1 ? 2 : 1; - }, - - handleCellPress(row: number, col: number) { - if (this.state.board.hasMark(row, col)) { - return; - } - - this.setState({ - board: this.state.board.mark(row, col, this.state.player), - player: this.nextPlayer(), - }); - }, - - render() { - var rows = this.state.board.grid.map((cells, row) => - - {cells.map((player, col) => - - )} - - ); - - return ( - - EXTREME T3 - - {rows} - - - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'white' - }, - title: { - fontFamily: 'Chalkduster', - fontSize: 39, - marginBottom: 20, - }, - board: { - padding: 5, - backgroundColor: '#47525d', - borderRadius: 10, - }, - row: { - flexDirection: 'row', - }, - - // CELL - - cell: { - width: 80, - height: 80, - borderRadius: 5, - backgroundColor: '#7b8994', - margin: 5, - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, - cellX: { - backgroundColor: '#72d0eb', - }, - cellO: { - backgroundColor: '#7ebd26', - }, - - // CELL TEXT - - cellText: { - borderRadius: 5, - fontSize: 50, - fontFamily: 'AvenirNext-Bold', - }, - cellTextX: { - color: '#19a9e5', - }, - cellTextO: { - color: '#b9dc2f', - }, - - // GAME OVER - - overlay: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - backgroundColor: 'rgba(221, 221, 221, 0.5)', - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - }, - overlayMessage: { - fontSize: 40, - marginBottom: 20, - marginLeft: 20, - marginRight: 20, - fontFamily: 'AvenirNext-DemiBold', - textAlign: 'center', - }, - newGame: { - backgroundColor: '#887766', - padding: 20, - borderRadius: 5, - }, - newGameText: { - color: 'white', - fontSize: 20, - fontFamily: 'AvenirNext-DemiBold', - }, -}); - -AppRegistry.registerComponent('TicTacToeApp', () => TicTacToeApp); - -module.exports = TicTacToeApp; diff --git a/Examples/TicTacToe/main.m b/Examples/TicTacToe/main.m deleted file mode 100644 index 357a233b128..00000000000 --- a/Examples/TicTacToe/main.m +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/Examples/UIExplorer/ActivityIndicatorExample.js b/Examples/UIExplorer/ActivityIndicatorExample.js deleted file mode 100644 index ec96febd5a4..00000000000 --- a/Examples/UIExplorer/ActivityIndicatorExample.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ActivityIndicatorExample - */ -'use strict'; - -var React = require('react-native'); -var { - ActivityIndicatorIOS, - StyleSheet, - TimerMixin, - View, -} = React; - -var ToggleAnimatingActivityIndicator = React.createClass({ - mixins: [TimerMixin], - - getInitialState: function() { - return { - animating: true, - }; - }, - - setToggleTimeout: function() { - this.setTimeout( - () => { - this.setState({animating: !this.state.animating}); - this.setToggleTimeout(); - }, - 1200 - ); - }, - - componentDidMount: function() { - this.setToggleTimeout(); - }, - - render: function() { - return ( - - ); - } -}); - -exports.framework = 'React'; -exports.title = ''; -exports.description = 'Animated loading indicators.'; - -exports.examples = [ - { - title: 'Default (small, white)', - render: function() { - return ( - - ); - } - }, - { - title: 'Gray', - render: function() { - return ( - - - - - ); - } - }, - { - title: 'Custom colors', - render: function() { - return ( - - - - - - - ); - } - }, - { - title: 'Large', - render: function() { - return ( - - ); - } - }, - { - title: 'Large, custom colors', - render: function() { - return ( - - - - - - - ); - } - }, - { - title: 'Start/stop', - render: function() { - return ; - } - }, -]; - -var styles = StyleSheet.create({ - centering: { - alignItems: 'center', - justifyContent: 'center', - }, - gray: { - backgroundColor: '#cccccc', - }, - horizontal: { - flexDirection: 'row', - justifyContent: 'space-around', - }, -}); diff --git a/Examples/UIExplorer/AppDelegate.h b/Examples/UIExplorer/AppDelegate.h deleted file mode 100644 index f0ec66bdb5b..00000000000 --- a/Examples/UIExplorer/AppDelegate.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface AppDelegate : UIResponder - -@property (nonatomic, strong) UIWindow *window; - -@end - diff --git a/Examples/UIExplorer/AppDelegate.m b/Examples/UIExplorer/AppDelegate.m deleted file mode 100644 index a3fdbd6297a..00000000000 --- a/Examples/UIExplorer/AppDelegate.m +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "AppDelegate.h" - -#import "RCTRootView.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - NSURL *jsCodeLocation; - RCTRootView *rootView = [[RCTRootView alloc] init]; - - // Loading JavaScript code - uncomment the one you want. - - // OPTION 1 - // Load from development server. Start the server from the repository root: - // - // $ npm start - // - // To run on device, change `localhost` to the IP address of your computer, and make sure your computer and - // iOS device are on the same Wi-Fi network. - jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.includeRequire.runModule.bundle"]; - - // OPTION 2 - // Load from pre-bundled file on disk. To re-generate the static bundle, run - // - // $ curl http://localhost:8081/Examples/UIExplorer/UIExplorerApp.includeRequire.runModule.bundle -o main.jsbundle - // - // and uncomment the next following line - // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; - - rootView.scriptURL = jsCodeLocation; - rootView.moduleName = @"UIExplorerApp"; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [[UIViewController alloc] init]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - return YES; -} - -@end diff --git a/Examples/UIExplorer/Base.lproj/LaunchScreen.xib b/Examples/UIExplorer/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 3b7dcb4a082..00000000000 --- a/Examples/UIExplorer/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/UIExplorer/DatePickerExample.js b/Examples/UIExplorer/DatePickerExample.js deleted file mode 100644 index a212546f438..00000000000 --- a/Examples/UIExplorer/DatePickerExample.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule DatePickerExample - */ -'use strict'; - -var React = require('react-native'); -var { - DatePickerIOS, - StyleSheet, - Text, - TextInput, - View, -} = React; - -var DatePickerExample = React.createClass({ - getDefaultProps: function () { - return { - date: new Date(), - timeZoneOffsetInHours: (-1) * (new Date()).getTimezoneOffset() / 60, - }; - }, - - getInitialState: function() { - return { - date: this.props.date, - timeZoneOffsetInHours: this.props.timeZoneOffsetInHours, - }; - }, - - onDateChange: function(date) { - this.setState({date: date}); - }, - - onTimezoneChange: function(event) { - var offset = parseInt(event.nativeEvent.text, 10); - if (isNaN(offset)) { - return; - } - this.setState({timeZoneOffsetInHours: offset}); - }, - - render: function() { - // Ideally, the timezone input would be a picker rather than a - // text input, but we don't have any pickers yet :( - return ( - - - { - this.state.date.toLocaleDateString() + - ' ' + - this.state.date.toLocaleTimeString() - } - - - - hours from UTC - - - - - - - - - ); - }, -}); - -var WithLabel = React.createClass({ - render: function() { - return ( - - - - {this.props.label} - - - {this.props.children} - - ); - } -}); - -var Heading = React.createClass({ - render: function() { - return ( - - - {this.props.label} - - - ); - } -}); - -exports.title = ''; -exports.description = 'Select dates and times using the native UIDatePicker.'; -exports.examples = [ -{ - title: '', - render: function() { - return ; - }, -}]; - -var styles = StyleSheet.create({ - textinput: { - height: 26, - width: 50, - borderWidth: 0.5, - borderColor: '#0f0f0f', - padding: 4, - fontSize: 13, - }, - labelContainer: { - flexDirection: 'row', - alignItems: 'center', - marginVertical: 2, - }, - labelView: { - marginRight: 10, - paddingVertical: 2, - }, - label: { - fontWeight: 'bold', - }, - headingContainer: { - padding: 4, - backgroundColor: '#f6f7f8', - }, - heading: { - fontWeight: 'bold', - fontSize: 14, - }, -}); diff --git a/Examples/UIExplorer/ExpandingTextExample.js b/Examples/UIExplorer/ExpandingTextExample.js deleted file mode 100644 index 74d6eb30053..00000000000 --- a/Examples/UIExplorer/ExpandingTextExample.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ExpandingTextExample - */ -'use strict'; - -var React = require('react-native'); -var { - ExpandingText -} = React; - -var LOREM = 'Lorem ipsum dolor sit amet, mea adipisci inimicus ex, paulo essent bonorum et ius, rebum deserunt mediocritatem ius ei.'; - -exports.title = ''; -exports.description = 'Base component for rendering text that is truncated and can be expanded upon tap.'; -exports.examples = [ -{ - title: 'Expanding text (truncLength=20)', - description: 'Setting the truncLength prop will cause the text to truncate to that character length', - render: function() { - return ; - } -}, { - title: 'Expanding text (truncLength=80)', - description: 'The higher the truncLength the more characters that will be shown by default', - render: function() { - return ; - } -}, { - title: 'Expanding text with custom style', - description: 'You can style the text within the ExpandingText component', - render: function() { - return ( - - ); - } -}, { - title: 'See More button with custom style' , - description: 'You can also style just the See More button', - render: function() { - return ( - - ); - } -}]; diff --git a/Examples/UIExplorer/GeoLocationExample.js b/Examples/UIExplorer/GeoLocationExample.js deleted file mode 100644 index fac3dd205f3..00000000000 --- a/Examples/UIExplorer/GeoLocationExample.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule GeolocationExample - */ -/* eslint no-console: 0 */ -'use strict'; - - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -exports.framework = 'React'; -exports.title = 'Geolocation'; -exports.description = 'Examples of using the Geolocation API.'; - -exports.examples = [ - { - title: 'navigator.geolocation', - render: function() { - return ; - }, - } -]; - -var GeolocationExample = React.createClass({ - getInitialState: function() { - return { - initialPosition: 'unknown', - lastPosition: 'unknown', - }; - }, - - componentDidMount: function() { - navigator.geolocation.getCurrentPosition( - (initialPosition) => this.setState({initialPosition}), - (error) => console.error(error) - ); - this.watchID = navigator.geolocation.watchPosition((lastPosition) => { - this.setState({lastPosition}); - }); - }, - - componentWillUnmount: function() { - navigator.geolocation.clearWatch(this.watchID); - }, - - render: function() { - return ( - - - Initial position: - {JSON.stringify(this.state.initialPosition)} - - - Current position: - {JSON.stringify(this.state.lastPosition)} - - - ); - } -}); - -var styles = StyleSheet.create({ - title: { - fontWeight: 'bold', - }, -}); diff --git a/Examples/UIExplorer/ImageCapInsetsExample.js b/Examples/UIExplorer/ImageCapInsetsExample.js deleted file mode 100644 index 20fea43c712..00000000000 --- a/Examples/UIExplorer/ImageCapInsetsExample.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ImageCapInsetsExample - */ -'use strict'; - -var React = require('react-native'); -var { - Image, - StyleSheet, - Text, - View, - ix, -} = React; - -var ImageCapInsetsExample = React.createClass({ - render: function() { - return ( - - - - capInsets: none - - - - - - capInsets: 15 - - - - - ); - } -}); - -var styles = StyleSheet.create({ - background: { - backgroundColor: '#F6F6F6', - justifyContent: 'center', - alignItems: 'center', - }, - horizontal: { - flexDirection: 'row', - }, - storyBackground: { - width: 250, - height: 150, - borderWidth: 1, - resizeMode: Image.resizeMode.stretch, - }, - text: { - fontSize: 13.5, - } -}); - -module.exports = ImageCapInsetsExample; diff --git a/Examples/UIExplorer/ImageExample.js b/Examples/UIExplorer/ImageExample.js deleted file mode 100644 index 00a8b39e675..00000000000 --- a/Examples/UIExplorer/ImageExample.js +++ /dev/null @@ -1,305 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ImageExample - */ -'use strict'; - -var React = require('react-native'); -var { - Image, - StyleSheet, - Text, - View, - ix, -} = React; - -var ImageCapInsetsExample = require('./ImageCapInsetsExample'); - -exports.framework = 'React'; -exports.title = ''; -exports.description = 'Base component for displaying different types of images.'; - -exports.examples = [ - { - title: 'Plain Network Image', - description: 'If the `source` prop `uri` property is prefixed with ' + - '"http", then it will be downloaded from the network.', - render: function() { - return ( - - ); - }, - }, - { - title: 'Plain Static Image', - description: 'Static assets must be referenced with the `ix` wrapper and ' + - 'located in the app bundle.', - render: function() { - return ( - - - - - - - ); - }, - }, - { - title: 'Border Color', - render: function() { - return ( - - - - ); - }, - }, - { - title: 'Border Width', - render: function() { - return ( - - - - ); - }, - }, - { - title: 'Border Radius', - render: function() { - return ( - - - - - ); - }, - }, - { - title: 'Background Color', - render: function() { - return ( - - - - - - - ); - }, - }, - { - title: 'Opacity', - render: function() { - return ( - - - - - - - - - ); - }, - }, - { - title: 'Nesting', - render: function() { - return ( - - - React - - - ); - }, - }, - { - title: 'Tint Color', - description: 'The `tintColor` style prop changes all the non-alpha ' + - 'pixels to the tint color.', - render: function() { - return ( - - - - - - - ); - }, - }, - { - title: 'Resize Mode', - description: 'The `resizeMode` style prop controls how the image is ' + - 'rendered within the frame.', - render: function() { - return ( - - - - Contain - - - - - - Cover - - - - - - Stretch - - - - - ); - }, - }, - { - title: 'Cap Insets', - description: - '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.', - render: function() { - return ; - }, - }, -]; - -var fullImage = {uri: 'http://facebook.github.io/react/img/logo_og.png'}; -var smallImage = {uri: 'http://facebook.github.io/react/img/logo_small.png'}; - -var styles = StyleSheet.create({ - base: { - width: 38, - height: 38, - }, - leftMargin: { - marginLeft: 10, - }, - background: { - backgroundColor: '#222222' - }, - nestedText: { - marginLeft: 12, - marginTop: 20, - backgroundColor: 'transparent', - color: 'white' - }, - resizeMode: { - width: 90, - height: 60, - borderWidth: 0.5, - borderColor: 'black' - }, - resizeModeText: { - fontSize: 11, - marginBottom: 3, - }, - icon: { - width: 15, - height: 15, - }, - horizontal: { - flexDirection: 'row', - } -}); diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 413d60e76d0..00000000000 --- a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "images" : [ - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "uie_icon@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "uie_icon@2x-1.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "uie_icon@2x-2.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "uie_icon@2x-3.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "uie_icon@2x-5.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "uie_icon@2x-4.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-1.png b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-1.png deleted file mode 100644 index 08a42699daa9ca2149e641e7236b63bf74bdb5f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31759 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 diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-2.png b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-2.png deleted file mode 100644 index 08a42699daa9ca2149e641e7236b63bf74bdb5f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31759 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 diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-3.png b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-3.png deleted file mode 100644 index 08a42699daa9ca2149e641e7236b63bf74bdb5f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31759 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 diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-4.png b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-4.png deleted file mode 100644 index 08a42699daa9ca2149e641e7236b63bf74bdb5f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31759 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 diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-5.png b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x-5.png deleted file mode 100644 index 08a42699daa9ca2149e641e7236b63bf74bdb5f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31759 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 diff --git a/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x.png b/Examples/UIExplorer/Images.xcassets/AppIcon.appiconset/uie_icon@2x.png deleted file mode 100644 index 08a42699daa9ca2149e641e7236b63bf74bdb5f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31759 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 diff --git a/Examples/UIExplorer/Images.xcassets/story-background.imageset/Contents.json b/Examples/UIExplorer/Images.xcassets/story-background.imageset/Contents.json deleted file mode 100644 index 65917726fa7..00000000000 --- a/Examples/UIExplorer/Images.xcassets/story-background.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x", - "filename" : "story-background.png" - }, - { - "idiom" : "universal", - "scale" : "2x", - "filename" : "story-background@2x.png" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/UIExplorer/Images.xcassets/story-background.imageset/story-background.png b/Examples/UIExplorer/Images.xcassets/story-background.imageset/story-background.png deleted file mode 100644 index cbb77db62d94da5b60ade84b57d539cb3066f197..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8f+emICBgY=CFO}lsSE{q>B&W< z#TgEzo}Yn|zdT(WLo)8Yy=BPPVIVD)_Is~Wcpcf zMOnnOR^z835eJ)Cxy5uM3Z6Y!JWu3-_Y#IvK0$xJcyax6TCKX7ImG_Mk_TKXj9IQ< z)YaU+ave>8(yDz*Fwn2?~$M4v4=H5TguFp z=P;H`HJqJb5HBsMT`Z(w*GbU;&e^N+TF-^-uh+uHP3f5+pp ztGZTRG~U8lriXPK8&2Y)So zna;LuV*dSd=X2^0^$hPnPXFGpTlu*-pPktj+XugR%WBj9KG6PgLaXj&vwSJA0hDuU>alaboFyt=akR{0J@tTlmGw# diff --git a/Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/Contents.json b/Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/Contents.json deleted file mode 100644 index e1ccff627e5..00000000000 --- a/Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x", - "filename" : "uie_comment_highlighted@2x.png" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/uie_comment_highlighted@2x.png b/Examples/UIExplorer/Images.xcassets/uie_comment_highlighted.imageset/uie_comment_highlighted@2x.png deleted file mode 100644 index b33726757ed46498e7da512385e6708961b815e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^N3j#jV-?mT=R~x z?qG_S5?46a-)zXcG1-6R+i#oC& zzvJE7cl6ywiMQb_vU3WSbIt9ztM)A8M5}1dx3CTO&WkBXEz_K2dYbpTst&{ou;2CIke`}<=m|S8gDPI6x5@=C);^Q3R#*ykgOCne9>D-nJd7pV!zCT)dC(t9N{Y0^mVs6FiMWuKAPnVn5 z?Roq5^S-ybKUY7x%Gdom?!Pgg^PVLYGoSvP^7X90$F9F6)BVq1GT+}VV6SOECsk~d s;zPy!yeaoLEZjKh?$rl^Fz^0*#@%wFGV)>p%W{yAr>mdKI;Vst00SMV4*&oF diff --git a/Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/Contents.json b/Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/Contents.json deleted file mode 100644 index 6f75231d5e6..00000000000 --- a/Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x", - "filename" : "uie_comment_normal@2x.png" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/uie_comment_normal@2x.png b/Examples/UIExplorer/Images.xcassets/uie_comment_normal.imageset/uie_comment_normal@2x.png deleted file mode 100644 index 6491689fbbc88bfd4289d4ffee2e4262097ddaae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 420 zcmeAS@N?(olHy`uVBq!ia0vp^N(}fc;mYo{*7tr)BX@!Dy91&-83Z-YtleIPcr8Uv_SS zB@dn6-gzW;tJ>(;OP33+-dm?0)!n+i*HW^mOg^<&ep#>llC!ZBc;qTixW|2(-FD`% z#q@)-rkzySWbjEtzOw$4%N`9qmHThj_V1ZH{hH<1O;v%1mfn!N(pR)u+V0bY{ykPl zOgU$+y&U8%mm1114>INQdNxH4M-Hcd$sKb$@_I5oq#qxdxk2h;-=4R&J?FYl>bI)Q zSA6zo<^;P>o8C>Ge)Xa0`SR{7FPXRA}Dqm^*J1K@i9DFtHPqf+7+UU0N#S%Cew$ zlW*c89TGx1CB$I+e7@UztbK`-;1u)}G!*m*J^*|JB#=y$@Q@-cGv{4Y6&FAy05^!;5Ah}#_ z*>ZeQvr%58is{&LS7rx-nb(~_@bDlK^Fsk(-w|-uAgMazqPh1nQe*c};Ag{lzCLvj ztz%NrjzHkB)dn3!?~d0LTQ98pQ!UmwM6p<0Qy{zheGtPi?kZ22I7kcvi!oiPIo0mb z^moMe8pnk~A+2CFrG^>aI1ribQh5Uk^UMu)B}hA}lR69DDNyMvN@>kw&ehK#mmHKu zN}G=$o*2&_LCc<6&@ot`-5O~N-aHW1nrq0w*g3Z~t;o4_-0%`-enA#WnWtN&hi2XT zYJqq7jaIY^3dG}k0^0c$zVCp+bpWbUsWA|YE%pucW^?oLdff2hR-KX5@hlWjdS}Nh zfN7l|1P1Lx9BD_x1@2VOc1#}z zkE;&bHX@vx(bcBG$$vg_^`=T*I6wtizj0ijC)CA8Otv|TO|#d^*mW#Pqz z!ByMYZll*BgCPEHz{N`tPPDx!7BzY4ZgpCM-3E^6c^Ls-djCy7@BnX=T zNOYede1EAYG&Tj0aR2B>v(^3>gooQf5Zsv<2>lyCAOu1n1VSJLLLdY}AOu1n1VSJL c@{fc30h_?_Xm?+0KL7v#07*qoM6N<$g3xSt9RL6T diff --git a/Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/Contents.json b/Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/Contents.json deleted file mode 100644 index a00a3dc54d0..00000000000 --- a/Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x", - "filename" : "uie_thumb_selected@2x.png" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/uie_thumb_selected@2x.png b/Examples/UIExplorer/Images.xcassets/uie_thumb_selected.imageset/uie_thumb_selected@2x.png deleted file mode 100644 index 79eb69cf92b3638954dd11b045006803abe6d904..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1110 zcmV-c1gZOpP)5AvWIw6 zQBjmADu|kc9`b`XF-IW;B%ml>LOcnIkb^hLO-R6>gLn=i8YGK{TnssgQ9OlU#O%5| zU7v^Up6QvL*`0BdWe-(Q%rI1SJ>UENRWo#VY=#QqcxNEjK%WSbv`wX0sr;`>|KDM_>N% zYmiUF{koUsnakgO{N69$f3{qM`j!N%@{Y^G3!*xb?zAjBy7$@RCr8B1tp)l0hqGNt zu#mw*4q1R@#gTiTI&52=zHVj+S%IvWLC6Z2*=-L$dF-xRp1wmF!$uKVK$K7-LUTK3 zCXJ8(1=4~L06uf%%x)5p0EvJLE}>k$c6BJFZyv}HgaB~Q{SUn@0U{w15aHtAmo9#B ztyxRbhHA{3f)_Rcp#$$Pz8H$)ElH3FsXC%$ym0y3Qx3p}vd3F>#!1EoCXDj=h|TQ+ zMgV&CopVogW_N#1$t(nz2_Qf^Sa#2~s;x$V5J1@+?e0FROlyo4y-Yjw?)k@yUGra3 zHZRK&vJPY!9FEvsLAkPgqbyfeD`Q*R9VO`J|N8CX(QiIIc%@b*y1R!VOKl8DY@YVo ziN)uO9k-taIV%NNR=`3AP=LoOMvOba0CfP^4`0$ZMGSrw}_0cJT=L$K1j zU1w_#k0`-##8Ti&ywK{<1By5Rngv*vg9^R2>9IuYt~MYrGgua278<8d(F_1MFWo4w z@2?f|QN6~^gb*@hS&onw)o18Q?e6X-!o;d>80z{l$*fZw@qtd5y>H#hI=HF!h!ZZ3 zSu=$kPDDB)Vj1Xh__Cz6AgC;6WqD(Ldrj|mPBBG@_y<@yaO%x_eqQ$)&@`@5vTnR) z{Yg52I4gxi8#XopT63?cC} z;?-jlDAJd`Nlo|R7!hQGq^a^YR!Z;t@yee|8(tNwcCG>Wt61!NCHV92_%6e ckgXa20ii_@% diff --git a/Examples/UIExplorer/Info.plist b/Examples/UIExplorer/Info.plist deleted file mode 100644 index 245054621e5..00000000000 --- a/Examples/UIExplorer/Info.plist +++ /dev/null @@ -1,42 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.facebook.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSLocationWhenInUseUsageDescription - You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! - UIViewControllerBasedStatusBarAppearance - - - diff --git a/Examples/UIExplorer/LayoutExample.js b/Examples/UIExplorer/LayoutExample.js deleted file mode 100644 index 746ef0ac6a2..00000000000 --- a/Examples/UIExplorer/LayoutExample.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule LayoutExample - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -var UIExplorerBlock = require('./UIExplorerBlock'); -var UIExplorerPage = require('./UIExplorerPage'); - -var Circle = React.createClass({ - render: function() { - var size = this.props.size || 20; - return ( - - ); - } -}); - -var CircleBlock = React.createClass({ - render: function() { - var circleStyle = { - flexDirection: 'row', - backgroundColor: '#f6f7f8', - borderWidth: 0.5, - borderColor: '#d6d7da', - marginBottom: 2, - }; - return ( - - {this.props.children} - - ); - } -}); - -var LayoutExample = React.createClass({ - statics: { - title: 'Layout - Flexbox', - description: 'Examples of using the flexbox API to layout views.' - }, - render: function() { - return ( - - - row - - - - column - - - - - {'top: 15, left: 160'} - - - - - flex-start - - - - center - - - - flex-end - - - - space-between - - - - space-around - - - - - - flex-start - - - - - - - - - center - - - - - - - - - flex-end - - - - - - - - - - - - {'oooooooooooooooo'.split('').map((char, i) => )} - - - - ); - } -}); - -var styles = StyleSheet.create({ - overlay: { - backgroundColor: '#aaccff', - borderRadius: 10, - borderWidth: 0.5, - opacity: 0.5, - padding: 5, - }, -}); - -module.exports = LayoutExample; diff --git a/Examples/UIExplorer/ListViewPagingExample.js b/Examples/UIExplorer/ListViewPagingExample.js deleted file mode 100644 index c74795eb5a1..00000000000 --- a/Examples/UIExplorer/ListViewPagingExample.js +++ /dev/null @@ -1,249 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ListViewPagingExample - * @flow - */ -'use strict'; - -var React = require('react-native'); -var { - Image, - LayoutAnimation, - ListView, - StyleSheet, - Text, - TouchableOpacity, - View, -} = React; - -var PAGE_SIZE = 4; -var THUMB_URLS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png']; -var NUM_SECTIONS = 100; -var NUM_ROWS_PER_SECTION = 10; - -var Thumb = React.createClass({ - getInitialState: function() { - return {thumbIndex: this._getThumbIdx(), dir: 'row'}; - }, - _getThumbIdx: function() { - return Math.floor(Math.random() * THUMB_URLS.length); - }, - _onPressThumb: function() { - var config = layoutAnimationConfigs[this.state.thumbIndex % layoutAnimationConfigs.length]; - LayoutAnimation.configureNext(config); - this.setState({ - thumbIndex: this._getThumbIdx(), - dir: this.state.dir === 'row' ? 'column' : 'row', - }); - }, - render: function() { - return ( - - - - - - {this.state.dir === 'column' ? - - Oooo, look at this new text! So awesome it may just be crazy. - Let me keep typing here so it wraps at least one line. - : - - } - - - ); - } -}); - -var ListViewPagingExample = React.createClass({ - statics: { - title: ' - Paging', - description: 'Floating headers & layout animations.' - }, - - getInitialState: function() { - var getSectionData = (dataBlob, sectionID) => { - return dataBlob[sectionID]; - }; - var getRowData = (dataBlob, sectionID, rowID) => { - return dataBlob[rowID]; - }; - - var dataSource = new ListView.DataSource({ - getRowData: getRowData, - getSectionHeaderData: getSectionData, - rowHasChanged: (row1, row2) => row1 !== row2, - sectionHeaderHasChanged: (s1, s2) => s1 !== s2, - }); - - var dataBlob = {}; - var sectionIDs = []; - var rowIDs = []; - for (var ii = 0; ii < NUM_SECTIONS; ii++) { - var sectionName = 'Section ' + ii; - sectionIDs.push(sectionName); - dataBlob[sectionName] = sectionName; - rowIDs[ii] = []; - - for (var jj = 0; jj < NUM_ROWS_PER_SECTION; jj++) { - var rowName = 'S' + ii + ', R' + jj; - rowIDs[ii].push(rowName); - dataBlob[rowName] = rowName; - } - } - return { - dataSource: dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs), - headerPressCount: 0, - }; - }, - - renderRow: function(rowData, sectionID, rowID) { - return (); - }, - - renderSectionHeader: function(sectionData, sectionID) { - return ( - - - {sectionData} - - - ); - }, - - renderHeader: function() { - var headerLikeText = this.state.headerPressCount % 2 ? - 1 Like : - null; - return ( - - - {headerLikeText} - - - Table Header (click me) - - - - - ); - }, - - renderFooter: function() { - return ( - - console.log('Footer!')} style={styles.text}> - Table Footer - - - ); - }, - - render: function() { - return ( - console.log({visibleRows, changedRows})} - renderHeader={this.renderHeader} - renderFooter={this.renderFooter} - renderSectionHeader={this.renderSectionHeader} - renderRow={this.renderRow} - initialListSize={10} - pageSize={PAGE_SIZE} - scrollRenderAheadDistance={2000} - /> - ); - }, - - _onPressHeader: function() { - var config = layoutAnimationConfigs[Math.floor(this.state.headerPressCount / 2) % layoutAnimationConfigs.length]; - LayoutAnimation.configureNext(config); - this.setState({headerPressCount: this.state.headerPressCount + 1}); - }, - -}); - -var styles = StyleSheet.create({ - listview: { - backgroundColor: '#B0C4DE', - }, - header: { - height: 40, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#3B5998', - flexDirection: 'row', - }, - text: { - color: 'white', - paddingHorizontal: 8, - }, - rowText: { - color: '#888888', - }, - thumbText: { - fontSize: 20, - color: '#888888', - }, - buttonContents: { - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - marginHorizontal: 5, - marginVertical: 3, - padding: 5, - backgroundColor: '#EAEAEA', - borderRadius: 3, - paddingVertical: 10, - }, - img: { - width: 64, - height: 64, - marginHorizontal: 10, - }, - section: { - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'flex-start', - padding: 6, - backgroundColor: '#5890ff', - }, -}); - -var animations = { - layout: { - spring: { - duration: 0.75, - create: { - duration: 0.3, - type: LayoutAnimation.Types.easeInEaseOut, - property: LayoutAnimation.Properties.opacity, - }, - update: { - type: LayoutAnimation.Types.spring, - springDamping: 0.4, - }, - }, - easeInEaseOut: { - duration: 0.3, - create: { - type: LayoutAnimation.Types.easeInEaseOut, - property: LayoutAnimation.Properties.scaleXY, - }, - update: { - delay: 0.1, - type: LayoutAnimation.Types.easeInEaseOut, - }, - }, - }, -}; - -var layoutAnimationConfigs = [ - animations.layout.spring, - animations.layout.easeInEaseOut, -]; - -module.exports = ListViewPagingExample; diff --git a/Examples/UIExplorer/ListViewSimpleExample.js b/Examples/UIExplorer/ListViewSimpleExample.js deleted file mode 100644 index c6b158f0337..00000000000 --- a/Examples/UIExplorer/ListViewSimpleExample.js +++ /dev/null @@ -1,120 +0,0 @@ -/** -* Copyright 2004-present Facebook. All Rights Reserved. -* -* @provides ListViewSimpleExample -*/ -'use strict'; - -var React = require('react-native'); -var { - Image, - ListView, - TouchableHighlight, - StyleSheet, - Text, - View, -} = React; - -var UIExplorerPage = require('./UIExplorerPage'); - -var ListViewSimpleExample = React.createClass({ - statics: { - title: ' - Simple', - description: 'Performant, scrollable list of data.' - }, - - getInitialState: function() { - var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); - return { - dataSource: ds.cloneWithRows(this._genRows({})), - }; - }, - - componentWillMount: function() { - this._pressData = {}; - }, - - render: function() { - return ( - - Simple'} - noSpacer={true} - noScroll={true}> - - - ); - }, - - _renderRow: function(rowData, sectionID, rowID) { - var rowHash = Math.abs(hashCode(rowData)); - var imgSource = { - uri: THUMB_URLS[rowHash % THUMB_URLS.length], - }; - return ( - this._pressRow(rowID)}> - - - - - {rowData + ' - ' + LOREM_IPSUM.substr(0, rowHash % 301 + 10)} - - - - - - ); - }, - - _genRows: function(pressData) { - var dataBlob = []; - for (var ii = 0; ii < 100; ii++) { - var pressedText = pressData[ii] ? ' (pressed)' : ''; - dataBlob.push('Row ' + ii + pressedText); - } - return dataBlob; - }, - - _pressRow: function(rowID) { - this._pressData[rowID] = !this._pressData[rowID]; - this.setState({dataSource: this.state.dataSource.cloneWithRows( - this._genRows(this._pressData) - )}); - }, -}); - -var THUMB_URLS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png']; -var LOREM_IPSUM = 'Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud modus, putant invidunt reprehendunt ne qui.'; - -/* eslint no-bitwise: 0 */ -var hashCode = function(str) { - var hash = 15; - for (var ii = str.length - 1; ii >= 0; ii--) { - hash = ((hash << 5) - hash) + str.charCodeAt(ii); - } - return hash; -}; - -var styles = StyleSheet.create({ - row: { - flexDirection: 'row', - justifyContent: 'center', - padding: 10, - backgroundColor: '#F6F6F6', - }, - separator: { - height: 1, - backgroundColor: '#CCCCCC', - }, - thumb: { - width: 64, - height: 64, - }, - text: { - flex: 1, - }, -}); - -module.exports = ListViewSimpleExample; diff --git a/Examples/UIExplorer/NavigatorIOSExample.js b/Examples/UIExplorer/NavigatorIOSExample.js deleted file mode 100644 index fa998528f04..00000000000 --- a/Examples/UIExplorer/NavigatorIOSExample.js +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule NavigatorIOSExample - */ -'use strict'; - -var React = require('react-native/addons'); -var ViewExample = require('./ViewExample'); -var { - PixelRatio, - ScrollView, - StyleSheet, - Text, - TouchableHighlight, - View, -} = React; - -var EmptyPage = React.createClass({ - - render: function() { - return ( - - - {this.props.text} - - - ); - }, - -}); - -var NavigatorIOSExample = React.createClass({ - - statics: { - title: '', - description: 'iOS navigation capabilities', - }, - - render: function() { - var recurseTitle = 'Recurse Navigation'; - if (!this.props.topExampleRoute) { - recurseTitle += ' - more examples here'; - } - return ( - - - - - - See <UIExplorerApp> for top-level usage. - - - - - - - - {this._renderRow(recurseTitle, () => { - this.props.navigator.push({ - title: NavigatorIOSExample.title, - component: NavigatorIOSExample, - backButtonTitle: 'Custom Back', - passProps: {topExampleRoute: this.props.topExampleRoute || this.props.route}, - }); - })} - {this._renderRow('Push View Example', () => { - this.props.navigator.push({ - title: 'Very Long Custom View Example Title', - component: ViewExample, - }); - })} - {this._renderRow('Custom Right Button', () => { - this.props.navigator.push({ - title: NavigatorIOSExample.title, - component: EmptyPage, - rightButtonTitle: 'Cancel', - onRightButtonPress: () => this.props.navigator.pop(), - passProps: { - text: 'This page has a right button in the nav bar', - } - }); - })} - {this._renderRow('Pop', () => { - this.props.navigator.pop(); - })} - {this._renderRow('Pop to top', () => { - this.props.navigator.popToTop(); - })} - {this._renderRow('Replace here', () => { - var prevRoute = this.props.route; - this.props.navigator.replace({ - title: 'New Navigation', - component: EmptyPage, - rightButtonTitle: 'Undo', - onRightButtonPress: () => this.props.navigator.replace(prevRoute), - passProps: { - text: 'The component is replaced, but there is currently no ' + - 'way to change the right button or title of the current route', - } - }); - })} - {this._renderReplacePrevious()} - {this._renderReplacePreviousAndPop()} - {this._renderPopToTopNavExample()} - - - - ); - }, - - _renderPopToTopNavExample: function() { - if (!this.props.topExampleRoute) { - return null; - } - return this._renderRow('Pop to top NavigatorIOSExample', () => { - this.props.navigator.popToRoute(this.props.topExampleRoute); - }); - }, - - _renderReplacePrevious: function() { - if (!this.props.topExampleRoute) { - // this is to avoid replacing the UIExplorerList at the top of the stack - return null; - } - return this._renderRow('Replace previous', () => { - this.props.navigator.replacePrevious({ - title: 'Replaced', - component: EmptyPage, - passProps: { - text: 'This is a replaced "previous" page', - }, - wrapperStyle: styles.customWrapperStyle, - }); - }); - }, - - _renderReplacePreviousAndPop: function() { - if (!this.props.topExampleRoute) { - // this is to avoid replacing the UIExplorerList at the top of the stack - return null; - } - return this._renderRow('Replace previous and pop', () => { - this.props.navigator.replacePreviousAndPop({ - title: 'Replaced and Popped', - component: EmptyPage, - passProps: { - text: 'This is a replaced "previous" page', - }, - wrapperStyle: styles.customWrapperStyle, - }); - }); - }, - - _renderRow: function(title, onPress) { - return ( - - - - - {title} - - - - - - ); - }, -}); - -var styles = StyleSheet.create({ - customWrapperStyle: { - backgroundColor: '#bbdddd', - }, - emptyPage: { - flex: 1, - paddingTop: 64, - }, - emptyPageText: { - margin: 10, - }, - list: { - backgroundColor: '#eeeeee', - marginTop: 10, - }, - group: { - backgroundColor: 'white', - }, - groupSpace: { - height: 15, - }, - line: { - backgroundColor: '#bbbbbb', - height: 1 / PixelRatio.get(), - }, - row: { - backgroundColor: 'white', - justifyContent: 'center', - paddingHorizontal: 15, - paddingVertical: 15, - }, - separator: { - height: 1 / PixelRatio.get(), - backgroundColor: '#bbbbbb', - marginLeft: 15, - }, - rowNote: { - fontSize: 17, - }, - rowText: { - fontSize: 17, - fontWeight: 'bold', - }, -}); - -module.exports = NavigatorIOSExample; diff --git a/Examples/UIExplorer/PointerEventsExample.js b/Examples/UIExplorer/PointerEventsExample.js deleted file mode 100644 index 10600d54dd7..00000000000 --- a/Examples/UIExplorer/PointerEventsExample.js +++ /dev/null @@ -1,239 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule PointerEventsExample - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -var ExampleBox = React.createClass({ - getInitialState: function() { - return { - log: [], - }; - }, - handleLog: function(msg) { - this.state.log = this.state.log.concat([msg]); - }, - flushReactChanges: function() { - this.forceUpdate(); - }, - /** - * Capture phase of bubbling to append separator before any of the bubbling - * happens. - */ - handleTouchCapture: function() { - this.state.log = this.state.log.concat(['---']); - }, - render: function() { - return ( - - - - - - - {this.state.log.join('\n')} - - - - ); - } -}); - - -var NoneExample = React.createClass({ - render: function() { - return ( - this.props.onLog('A unspecified touched')} - style={styles.box}> - - A: unspecified - - this.props.onLog('B none touched')} - style={[styles.box, styles.boxPassedThrough]}> - - B: none - - this.props.onLog('C unspecified touched')} - style={[styles.box, styles.boxPassedThrough]}> - - C: unspecified - - - - - ); - } -}); - -/** - * Special demo text that makes itself untouchable so that it doesn't destroy - * the experiment and confuse the output. - */ -var DemoText = React.createClass({ - render: function() { - return ( - - - {this.props.children} - - - ); - } -}); - -var BoxNoneExample = React.createClass({ - render: function() { - return ( - this.props.onLog('A unspecified touched')} - style={styles.box}> - - A: unspecified - - this.props.onLog('B box-none touched')} - style={[styles.box, styles.boxPassedThrough]}> - - B: box-none - - this.props.onLog('C unspecified touched')} - style={styles.box}> - - C: unspecified - - - this.props.onLog('C explicitly unspecified touched')} - style={[styles.box]}> - - C: explicitly unspecified - - - - - ); - } -}); - -var BoxOnlyExample = React.createClass({ - render: function() { - return ( - this.props.onLog('A unspecified touched')} - style={styles.box}> - - A: unspecified - - this.props.onLog('B box-only touched')} - style={styles.box}> - - B: box-only - - this.props.onLog('C unspecified touched')} - style={[styles.box, styles.boxPassedThrough]}> - - C: unspecified - - - this.props.onLog('C explicitly unspecified touched')} - style={[styles.box, styles.boxPassedThrough]}> - - C: explicitly unspecified - - - - - ); - } -}); - -var exampleClasses = [ - { - Component: NoneExample, - title: '`none`', - description: '`none` causes touch events on the container and its child components to pass through to the parent container.', - }, - { - Component: BoxNoneExample, - title: '`box-none`', - description: '`box-none` causes touch events on the container to pass through and will only detect touch events on its child components.', - }, - { - Component: BoxOnlyExample, - title: '`box-only`', - description: '`box-only` causes touch events on the container\'s child components to pass through and will only detect touch events on the container itself.', - } -]; - -var infoToExample = (info) => { - return { - title: info.title, - description: info.description, - render: function() { - return ; - }, - }; -}; - -var styles = StyleSheet.create({ - text: { - fontSize: 10, - color: '#5577cc', - }, - textPassedThrough: { - color: '#88aadd', - }, - box: { - backgroundColor: '#aaccff', - borderWidth: 1, - borderColor: '#7799cc', - padding: 10, - margin: 5, - }, - boxPassedThrough: { - borderColor: '#99bbee', - }, - logText: { - fontSize: 9, - }, - logBox: { - padding: 20, - margin: 10, - borderWidth: 0.5, - borderColor: '#f0f0f0', - backgroundColor: '#f9f9f9', - }, - bottomSpacer: { - marginBottom: 100, - }, -}); - -exports.framework = 'React'; -exports.title = 'Pointer Events'; -exports.description = '`pointerEvents` is a prop of View that gives control ' + - 'of how touches should be handled.'; -exports.examples = exampleClasses.map(infoToExample); diff --git a/Examples/UIExplorer/ScrollViewExample.js b/Examples/UIExplorer/ScrollViewExample.js deleted file mode 100644 index 68df23b1d9c..00000000000 --- a/Examples/UIExplorer/ScrollViewExample.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ScrollViewExample - */ -'use strict'; - -var React = require('react-native'); -var { - ScrollView, - StyleSheet, - View, - Image -} = React; - -exports.title = ''; -exports.description = 'Component that enables scrolling through child components'; -exports.examples = [ -{ - title: '', - description: 'To make content scrollable, wrap it within a component', - render: function() { - return ( - { console.log('onScroll!'); }} - throttleScrollCallbackMS={200} - contentInset={{top: -50}} - style={styles.scrollView}> - {THUMBS.map(createThumbRow)} - - ); - } -}, { - title: ' (horizontal = true)', - description: 'You can display \'s child components horizontally rather than vertically', - render: function() { - return ( - - {THUMBS.map(createThumbRow)} - - ); - } -}]; - -var Thumb = React.createClass({ - shouldComponentUpdate: function(nextProps, nextState) { - return false; - }, - render: function() { - return ( - - - - ); - } -}); - -var THUMBS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png']; -THUMBS = THUMBS.concat(THUMBS); // double length of THUMBS -var createThumbRow = (uri, i) => ; - -var styles = StyleSheet.create({ - scrollView: { - backgroundColor: '#6A85B1', - height: 300, - }, - horizontalScrollView: { - height: 120, - }, - containerPage: { - height: 50, - width: 50, - backgroundColor: '#527FE4', - padding: 5, - }, - text: { - fontSize: 20, - color: '#888888', - left: 80, - top: 20, - height: 40, - }, - button: { - margin: 7, - padding: 5, - alignItems: 'center', - backgroundColor: '#eaeaea', - borderRadius: 3, - }, - buttonContents: { - flexDirection: 'row', - width: 64, - height: 64, - }, - img: { - width: 64, - height: 64, - } -}); diff --git a/Examples/UIExplorer/SliderExample.js b/Examples/UIExplorer/SliderExample.js deleted file mode 100644 index 0ff4f6713fb..00000000000 --- a/Examples/UIExplorer/SliderExample.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule SliderExample - */ -'use strict'; - -var React = require('react-native'); -var { - Slider, - Text, - StyleSheet, - View, -} = React; - -var SliderExample = React.createClass({ - getInitialState() { - return { - value: 0, - }; - }, - - render() { - return ( - - - {this.state.value} - - this.setState({value: value})} /> - - ); - } -}); - -var styles = StyleSheet.create({ - slider: { - height: 10, - margin: 10, - }, - text: { - fontSize: 14, - textAlign: 'center', - fontWeight: 'bold', - margin: 10, - }, -}); - -exports.title = ''; -exports.description = 'Slider input for numeric values'; -exports.examples = [ - { - title: 'Slider', - render() { return ; } - } -]; diff --git a/Examples/UIExplorer/StatusBarIOSExample.js b/Examples/UIExplorer/StatusBarIOSExample.js deleted file mode 100644 index 1ee83419a71..00000000000 --- a/Examples/UIExplorer/StatusBarIOSExample.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule StatusBarIOSExample - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - View, - Text, - TouchableHighlight, - StatusBarIOS, -} = React; - -exports.framework = 'React'; -exports.title = 'StatusBarIOS'; -exports.description = 'Module for controlling iOS status bar'; -exports.examples = [{ - title: 'Status Bar Style', - render() { - return ( - - {Object.keys(StatusBarIOS.Style).map((key) => - StatusBarIOS.setStyle(StatusBarIOS.Style[key])}> - - setStyle(StatusBarIOS.Style.{key}) - - - )} - - ); - }, -}, { - title: 'Status Bar Style Animated', - render() { - return ( - - {Object.keys(StatusBarIOS.Style).map((key) => - StatusBarIOS.setStyle(StatusBarIOS.Style[key], true)}> - - setStyle(StatusBarIOS.Style.{key}, true) - - - )} - - ); - }, -}, { - title: 'Status Bar Hidden', - render() { - return ( - - {Object.keys(StatusBarIOS.Animation).map((key) => - - StatusBarIOS.setHidden(true, StatusBarIOS.Animation[key])}> - - setHidden(true, StatusBarIOS.Animation.{key}) - - - StatusBarIOS.setHidden(false, StatusBarIOS.Animation[key])}> - - setHidden(false, StatusBarIOS.Animation.{key}) - - - - )} - - ); - }, -}]; - -var styles = StyleSheet.create({ - wrapper: { - borderRadius: 5, - marginBottom: 5, - }, - button: { - backgroundColor: '#eeeeee', - padding: 10, - }, -}); diff --git a/Examples/UIExplorer/SwitchExample.js b/Examples/UIExplorer/SwitchExample.js deleted file mode 100644 index 9aa63833f65..00000000000 --- a/Examples/UIExplorer/SwitchExample.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule SwitchExample - */ -'use strict'; - -var React = require('react-native'); -var { - SwitchIOS, - Text, - View -} = React; - -var BasicSwitchExample = React.createClass({ - getInitialState() { - return { - trueSwitchIsOn: true, - falseSwitchIsOn: false, - }; - }, - render() { - return ( - - this.setState({falseSwitchIsOn: value})} - style={{marginBottom: 10}} - value={this.state.falseSwitchIsOn} /> - this.setState({trueSwitchIsOn: value})} - value={this.state.trueSwitchIsOn} /> - - ); - } -}); - -var DisabledSwitchExample = React.createClass({ - render() { - return ( - - - - - ); - }, -}); - -var ColorSwitchExample = React.createClass({ - getInitialState() { - return { - colorTrueSwitchIsOn: true, - colorFalseSwitchIsOn: false, - }; - }, - render() { - return ( - - this.setState({colorFalseSwitchIsOn: value})} - onTintColor="#00ff00" - style={{marginBottom: 10}} - thumbTintColor="#0000ff" - tintColor="#ff0000" - value={this.state.colorFalseSwitchIsOn} /> - this.setState({colorTrueSwitchIsOn: value})} - onTintColor="#00ff00" - thumbTintColor="#0000ff" - tintColor="#ff0000" - value={this.state.colorTrueSwitchIsOn} /> - - ); - }, -}); - -var EventSwitchExample = React.createClass({ - getInitialState() { - return { - eventSwitchIsOn: false, - eventSwitchRegressionIsOn: true, - }; - }, - render() { - return ( - - - this.setState({eventSwitchIsOn: value})} - style={{marginBottom: 10}} - value={this.state.eventSwitchIsOn} /> - this.setState({eventSwitchIsOn: value})} - style={{marginBottom: 10}} - value={this.state.eventSwitchIsOn} /> - {this.state.eventSwitchIsOn ? "On" : "Off"} - - - this.setState({eventSwitchRegressionIsOn: value})} - style={{marginBottom: 10}} - value={this.state.eventSwitchRegressionIsOn} /> - this.setState({eventSwitchRegressionIsOn: value})} - style={{marginBottom: 10}} - value={this.state.eventSwitchRegressionIsOn} /> - {this.state.eventSwitchRegressionIsOn ? "On" : "Off"} - - - ); - } -}); - -exports.title = ''; -exports.description = 'Native boolean input'; -exports.examples = [ - { - title: 'Switches can be set to true or false', - render() { return ; } - }, - { - title: 'Switches can be disabled', - render() { return ; } - }, - { - title: 'Custom colors can be provided', - render() { return ; } - }, - { - title: 'Change events can be detected', - render() { return ; } - }, - { - title: 'Switches are controlled components', - render() { return ; } - } -]; diff --git a/Examples/UIExplorer/TabBarExample.js b/Examples/UIExplorer/TabBarExample.js deleted file mode 100644 index 22dc86a8b86..00000000000 --- a/Examples/UIExplorer/TabBarExample.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TabBarExample - */ -'use strict'; - -var React = require('React'); -var TabBarIOS = require('TabBarIOS'); -var TabBarItemIOS = require('TabBarItemIOS'); -var StyleSheet = require('StyleSheet'); -var Text = require('Text'); -var View = require('View'); - -var ix = require('ix'); - -var TabBarExample = React.createClass({ - - statics: { - title: '', - description: 'Tab-based navigation.' - }, - - getInitialState: function() { - return { - selectedTab: 'redTab', - notifCount: 0, - presses: 0, - }; - }, - - _renderContent: function(color, pageText) { - return ( - - {pageText} - {this.state.presses} re-renders of this tab - - ); - }, - - render: function() { - return ( - - { - this.setState({ - selectedTab: 'blueTab', - }); - }}> - {this._renderContent('#414A8C', 'Blue Tab')} - - { - this.setState({ - selectedTab: 'redTab', - notifCount: this.state.notifCount + 1, - }); - }}> - {this._renderContent('#783E33', 'Red Tab')} - - { - this.setState({ - selectedTab: 'greenTab', - presses: this.state.presses + 1 - }); - }}> - {this._renderContent('#21551C', 'Green Tab')} - - - ); - }, - -}); - -var styles = StyleSheet.create({ - tabContent: { - flex: 1, - alignItems: 'center', - }, - tabText: { - color: 'white', - margin: 50, - }, -}); - -module.exports = TabBarExample; diff --git a/Examples/UIExplorer/TextExample.ios.js b/Examples/UIExplorer/TextExample.ios.js deleted file mode 100644 index a0d5eba3302..00000000000 --- a/Examples/UIExplorer/TextExample.ios.js +++ /dev/null @@ -1,279 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TextExample - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -var Entity = React.createClass({ - render: function() { - return ( - - {this.props.children} - - ); - } -}); - -var AttributeToggler = React.createClass({ - getInitialState: function() { - return {fontWeight: 'bold', fontSize: 15}; - }, - increaseSize: function() { - this.setState({ - fontSize: this.state.fontSize + 1 - }); - }, - render: function() { - var curStyle = {fontSize: this.state.fontSize}; - return ( - - - Tap the controls below to change attributes. - - - See how it will even work on{' '} - - this nested text - - - {'>> Increase Size <<'} - - - - ); - } -}); - -exports.title = ''; -exports.description = 'Base component for rendering styled text.'; -exports.examples = [ -{ - title: 'Wrap', - render: function() { - return ( - - The text should wrap if it goes on multiple lines. See, this is going to - the next line. - - ); - }, -}, { - title: 'Font Family', - render: function() { - return ( - - - Cochin - - - Cochin bold - - - Helvetica - - - Helvetica bold - - - Verdana - - - Verdana bold - - - ); - }, -}, { - title: 'Font Size', - render: function() { - return ( - - - Size 23 - - - Size 8 - - - ); - }, -}, { - title: 'Color', - render: function() { - return ( - - - Red color - - - Blue color - - - ); - }, -}, { - title: 'Font Weight', - render: function() { - return ( - - Move fast and be bold - - ); - }, -}, { - title: 'Nested', - description: 'Nested text components will inherit the styles of their ' + - 'parents (only backgroundColor is inherited from non-Text parents). ' + - ' only supports other and raw text (strings) as children.', - render: function() { - return ( - - - (Normal text, - - (and bold - - (and tiny inherited bold blue) - - ) - - ) - - - Entity Name - - - ); - }, -}, { - title: 'Text Align', - render: function() { - return ( - - - left left left left left left left left left left left left left left left - - - center center center center center center center center center center center - - - right right right right right right right right right right right right right - - - ); - }, -}, { - title: 'Spaces', - render: function() { - return ( - - A {'generated'} {' '} {'string'} and some     spaces - - ); - }, -}, { - title: 'Line Height', - render: function() { - return ( - - - A lot of space between the lines of this long passage that should - wrap once. - - - ); - }, -}, { - title: 'Empty Text', - description: 'It\'s ok to have Text with zero or null children.', - render: function() { - return ( - - ); - }, -}, { - title: 'Toggling Attributes', - render: function() { - return ; - }, -}, { - title: 'backgroundColor attribute', - description: 'backgroundColor is inherited from all types of views.', - render: function() { - return ( - - - Yellow background inherited from View parent, - - {' '}red background, - - {' '}blue background, - - {' '}inherited blue background, - - {' '}nested green background. - - - - - - - ); - }, -}, { - title: 'containerBackgroundColor attribute', - render: function() { - return ( - - - - - - - Default containerBackgroundColor (inherited) + backgroundColor wash - - - {"containerBackgroundColor: 'transparent' + backgroundColor wash"} - - - ); - }, -}, { - title: 'numberOfLines attribute', - render: function() { - return ( - - - Maximum of one line no matter now much I write here. If I keep writing it{"'"}ll just truncate after one line - - - Maximum of two lines no matter now much I write here. If I keep writing it{"'"}ll just truncate after two lines - - - No maximum lines specified no matter now much I write here. If I keep writing it{"'"}ll just keep going and going - - - ); - }, -}]; - -var styles = StyleSheet.create({ - backgroundColorText: { - left: 5, - backgroundColor: 'rgba(100, 100, 100, 0.3)' - }, - entity: { - fontWeight: 'bold', - color: '#527fe4', - }, -}); diff --git a/Examples/UIExplorer/TextInputExample.js b/Examples/UIExplorer/TextInputExample.js deleted file mode 100644 index e1f28895be1..00000000000 --- a/Examples/UIExplorer/TextInputExample.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TextInputExample - */ -'use strict'; - -var React = require('react-native'); -var { - Text, - TextInput, - View, - StyleSheet, -} = React; - -var WithLabel = React.createClass({ - render: function() { - return ( - - - {this.props.label} - - {this.props.children} - - ); - } -}); - -var TextEventsExample = React.createClass({ - getInitialState: function() { - return { - curText: '', - prevText: '', - }; - }, - - updateText: function(text) { - this.setState({ - curText: text, - prevText: this.state.curText, - }); - }, - - render: function() { - return ( - - this.updateText('onFocus')} - onBlur={() => this.updateText('onBlur')} - onChange={(event) => this.updateText( - 'onChange text: ' + event.nativeEvent.text - )} - onEndEditing={(event) => this.updateText( - 'onEndEditing text: ' + event.nativeEvent.text - )} - onSubmitEditing={(event) => this.updateText( - 'onSubmitEditing text: ' + event.nativeEvent.text - )} - style={styles.default} - /> - - {this.state.curText}{'\n'} - (prev: {this.state.prevText}) - - - ); - } -}); - -var styles = StyleSheet.create({ - page: { - paddingBottom: 300, - }, - default: { - height: 26, - borderWidth: 0.5, - borderColor: '#0f0f0f', - padding: 4, - flex: 1, - fontSize: 13, - }, - multiline: { - borderWidth: 0.5, - borderColor: '#0f0f0f', - flex: 1, - fontSize: 13, - height: 50, - }, - eventLabel: { - margin: 3, - fontSize: 12, - }, - labelContainer: { - flexDirection: 'row', - marginVertical: 2, - flex: 1, - }, - label: { - width: 80, - justifyContent: 'flex-end', - flexDirection: 'row', - marginRight: 10, - paddingTop: 2, - }, -}); - -exports.title = ''; -exports.description = 'Single-line text inputs.'; -exports.examples = [ - { - title: 'Auto-focus', - render: function() { - return ; - } - }, - { - title: 'Auto-capitalize', - render: function() { - return ( - - - - - - - - - - - - - - - ); - } - }, - { - title: 'Auto-correct', - render: function() { - return ( - - - - - - - - - ); - } - }, - { - title: 'Event handling', - render: () => , - }, - { - title: 'Colored input text', - render: function() { - return ( - - - - - ); - } - }, - { - title: 'Clear button mode', - render: function () { - return ( - - - - - - - - - - - - - - - ); - } - }, -]; diff --git a/Examples/UIExplorer/TouchableExample.js b/Examples/UIExplorer/TouchableExample.js deleted file mode 100644 index 66a919a3cdd..00000000000 --- a/Examples/UIExplorer/TouchableExample.js +++ /dev/null @@ -1,188 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TouchableExample - */ -'use strict'; - -var React = require('react-native'); -var { - PixelRatio, - Image, - StyleSheet, - Text, - TouchableHighlight, - TouchableOpacity, - View, -} = React; - -exports.title = ' and onPress'; -exports.examples = [ -{ - title: '', - description: 'TouchableHighlight works by adding an extra view with a ' + - 'black background under the single child view. This works best when the ' + - 'child view is fully opaque, although it can be made to work as a simple ' + - 'background color change as well with the activeOpacity and ' + - 'underlayColor props.', - render: function() { - return ( - - - console.log('stock THW image - highlight')}> - - - console.log('custom THW text - hightlight')}> - - - Tap Here For Custom Highlight! - - - - - - ); - }, -}, { - title: ' with highlight', - render: function() { - return ; - }, -}, { - title: 'Touchable feedback events', - description: ' components accept onPress, onPressIn, ' + - 'onPressOut, and onLongPress as props.', - render: function() { - return ; - }, -}]; - -var TextOnPressBox = React.createClass({ - getInitialState: function() { - return { - timesPressed: 0, - }; - }, - textOnPress: function() { - this.setState({ - timesPressed: this.state.timesPressed + 1, - }); - }, - render: function() { - var textLog = ''; - if (this.state.timesPressed > 1) { - textLog = this.state.timesPressed + 'x text onPress'; - } else if (this.state.timesPressed > 0) { - textLog = 'text onPress'; - } - - return ( - - - Text has built-in onPress handling - - - - {textLog} - - - - ); - } -}); - -var TouchableFeedbackEvents = React.createClass({ - getInitialState: function() { - return { - eventLog: [], - }; - }, - render: function() { - return ( - - - this._appendEvent('press')} - onPressIn={() => this._appendEvent('pressIn')} - onPressOut={() => this._appendEvent('pressOut')} - onLongPress={() => this._appendEvent('longPress')}> - - Press Me - - - - - {this.state.eventLog.map((e, ii) => {e})} - - - ); - }, - _appendEvent: function(eventName) { - var limit = 6; - var eventLog = this.state.eventLog.slice(0, limit - 1); - eventLog.unshift(eventName); - this.setState({eventLog}); - }, -}); - -var heartImage = {uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small'}; - -var styles = StyleSheet.create({ - row: { - justifyContent: 'center', - flexDirection: 'row', - }, - icon: { - width: 24, - height: 24, - }, - image: { - width: 50, - height: 50, - }, - text: { - fontSize: 16, - }, - button: { - color: '#007AFF', - }, - wrapper: { - borderRadius: 8, - }, - wrapperCustom: { - borderRadius: 8, - padding: 6, - }, - logBox: { - padding: 20, - margin: 10, - borderWidth: 1 / PixelRatio.get(), - borderColor: '#f0f0f0', - backgroundColor: '#f9f9f9', - }, - eventLogBox: { - padding: 10, - margin: 10, - height: 120, - borderWidth: 1 / PixelRatio.get(), - borderColor: '#f0f0f0', - backgroundColor: '#f9f9f9', - }, - textBlock: { - fontWeight: 'bold', - color: 'blue', - }, -}); diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj deleted file mode 100644 index ea13d28e3ac..00000000000 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj +++ /dev/null @@ -1,459 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; }; - 134180011AA9153C003F314A /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; }; - 134180021AA9153C003F314A /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FFF1AA91531003F314A /* libReactKit.a */; }; - 1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; }; - 134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; - 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 13417FE71AA91428003F314A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5115D1A9E6B3D00147676; - remoteInfo = RCTImage; - }; - 13417FEE1AA914B8003F314A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5119B1A9E6C1200147676; - remoteInfo = RCTText; - }; - 13417FFE1AA91531003F314A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; - remoteInfo = ReactKit; - }; - 1341802A1AA91779003F314A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B511DB1A9E6C8500147676; - remoteInfo = RCTNetwork; - }; - 134A8A241AACED6A00945AAE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTGeolocation; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; }; - 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = ""; }; - 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = ""; }; - 134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = ""; }; - 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */, - 1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */, - 134180011AA9153C003F314A /* libRCTText.a in Frameworks */, - 134180021AA9153C003F314A /* libReactKit.a in Frameworks */, - 13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 1316A21D1AA397F400C0188E /* Libraries */ = { - isa = PBXGroup; - children = ( - 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */, - 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */, - 134180261AA91779003F314A /* RCTNetwork.xcodeproj */, - 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */, - 13417FE31AA91428003F314A /* RCTImage.xcodeproj */, - ); - name = Libraries; - sourceTree = ""; - }; - 13417FE41AA91428003F314A /* Products */ = { - isa = PBXGroup; - children = ( - 13417FE81AA91428003F314A /* libRCTImage.a */, - ); - name = Products; - sourceTree = ""; - }; - 13417FEB1AA914B8003F314A /* Products */ = { - isa = PBXGroup; - children = ( - 13417FEF1AA914B8003F314A /* libRCTText.a */, - ); - name = Products; - sourceTree = ""; - }; - 13417FFB1AA91531003F314A /* Products */ = { - isa = PBXGroup; - children = ( - 13417FFF1AA91531003F314A /* libReactKit.a */, - ); - name = Products; - sourceTree = ""; - }; - 134180271AA91779003F314A /* Products */ = { - isa = PBXGroup; - children = ( - 1341802B1AA91779003F314A /* libRCTNetwork.a */, - ); - name = Products; - sourceTree = ""; - }; - 134A8A211AACED6A00945AAE /* Products */ = { - isa = PBXGroup; - children = ( - 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */, - ); - name = Products; - sourceTree = ""; - }; - 13B07FAE1A68108700A75B9A /* UIExplorer */ = { - isa = PBXGroup; - children = ( - 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.m */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, - 13B07FB61A68108700A75B9A /* Info.plist */, - 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, - 13B07FB71A68108700A75B9A /* main.m */, - ); - name = UIExplorer; - sourceTree = ""; - }; - 83CBB9F61A601CBA00E9B192 = { - isa = PBXGroup; - children = ( - 13B07FAE1A68108700A75B9A /* UIExplorer */, - 1316A21D1AA397F400C0188E /* Libraries */, - 83CBBA001A601CBA00E9B192 /* Products */, - ); - sourceTree = ""; - }; - 83CBBA001A601CBA00E9B192 /* Products */ = { - isa = PBXGroup; - children = ( - 13B07F961A680F5B00A75B9A /* UIExplorer.app */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 13B07F861A680F5B00A75B9A /* UIExplorer */ = { - isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "UIExplorer" */; - buildPhases = ( - 13B07F871A680F5B00A75B9A /* Sources */, - 13B07F8C1A680F5B00A75B9A /* Frameworks */, - 13B07F8E1A680F5B00A75B9A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = UIExplorer; - productName = "Hello World"; - productReference = 13B07F961A680F5B00A75B9A /* UIExplorer.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83CBB9F71A601CBA00E9B192 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83CBB9F61A601CBA00E9B192; - productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 134A8A211AACED6A00945AAE /* Products */; - ProjectRef = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */; - }, - { - ProductGroup = 13417FE41AA91428003F314A /* Products */; - ProjectRef = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */; - }, - { - ProductGroup = 134180271AA91779003F314A /* Products */; - ProjectRef = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */; - }, - { - ProductGroup = 13417FEB1AA914B8003F314A /* Products */; - ProjectRef = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */; - }, - { - ProductGroup = 13417FFB1AA91531003F314A /* Products */; - ProjectRef = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 13B07F861A680F5B00A75B9A /* UIExplorer */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 13417FE81AA91428003F314A /* libRCTImage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTImage.a; - remoteRef = 13417FE71AA91428003F314A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 13417FEF1AA914B8003F314A /* libRCTText.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTText.a; - remoteRef = 13417FEE1AA914B8003F314A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 13417FFF1AA91531003F314A /* libReactKit.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReactKit.a; - remoteRef = 13417FFE1AA91531003F314A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1341802B1AA91779003F314A /* libRCTNetwork.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTNetwork.a; - remoteRef = 1341802A1AA91779003F314A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTGeolocation.a; - remoteRef = 134A8A241AACED6A00945AAE /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 13B07F8E1A680F5B00A75B9A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, - 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 13B07F871A680F5B00A75B9A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 13B07FB21A68108700A75B9A /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 13B07F941A680F5B00A75B9A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = UIExplorer; - }; - name = Debug; - }; - 13B07F951A680F5B00A75B9A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = UIExplorer; - }; - name = Release; - }; - 83CBBA201A601CBA00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 83CBBA211A601CBA00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "UIExplorer" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 13B07F941A680F5B00A75B9A /* Debug */, - 13B07F951A680F5B00A75B9A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug */, - 83CBBA211A601CBA00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; -} diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index e668abba37c..00000000000 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme b/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme deleted file mode 100644 index 403b11e6f8e..00000000000 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/UIExplorer/UIExplorerApp.js b/Examples/UIExplorer/UIExplorerApp.js deleted file mode 100644 index 7c73d4ee30b..00000000000 --- a/Examples/UIExplorer/UIExplorerApp.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule UIExplorerApp - */ -'use strict'; - -var React = require('react-native/addons'); -var UIExplorerList = require('./UIExplorerList'); - -var { - AppRegistry, - NavigatorIOS, - StyleSheet, -} = React; - - -var UIExplorerApp = React.createClass({ - render: function() { - return ( - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - flex: 1, - }, - itemWrapper: { - backgroundColor: '#eaeaea', - }, -}); - -AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp); - -module.exports = UIExplorerApp; diff --git a/Examples/UIExplorer/UIExplorerBlock.js b/Examples/UIExplorer/UIExplorerBlock.js deleted file mode 100644 index 4c96ce86d5e..00000000000 --- a/Examples/UIExplorer/UIExplorerBlock.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule UIExplorerBlock - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -var UIExplorerBlock = React.createClass({ - propTypes: { - title: React.PropTypes.string, - description: React.PropTypes.string, - }, - - getInitialState: function() { - return {description: null}; - }, - - render: function() { - var description; - if (this.props.description) { - description = - - {this.props.description} - ; - } - - return ( - - - - {this.props.title} - - {description} - - - {this.props.children} - - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - borderRadius: 3, - borderWidth: 0.5, - borderColor: '#d6d7da', - backgroundColor: '#ffffff', - margin: 10, - marginVertical: 5, - overflow: 'hidden', - }, - titleContainer: { - borderWidth: 0.5, - borderColor: '#d6d7da', - backgroundColor: '#f6f7f8', - paddingHorizontal: 10, - paddingVertical: 5, - }, - titleRow: { - flexDirection: 'row', - justifyContent: 'space-between', - }, - titleText: { - fontSize: 14, - fontWeight: 'bold', - }, - descriptionText: { - fontSize: 14, - }, - disclosure: { - position: 'absolute', - top: 0, - right: 0, - padding: 10, - }, - disclosureIcon: { - width: 12, - height: 8, - }, - children: { - padding: 10, - } -}); - -module.exports = UIExplorerBlock; diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js deleted file mode 100644 index e04edcab671..00000000000 --- a/Examples/UIExplorer/UIExplorerList.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - */ -'use strict'; - -var React = require('react-native/addons'); -var { - PixelRatio, - ScrollView, - StyleSheet, - Text, - TouchableHighlight, - View, - invariant, -} = React; - -var createExamplePage = require('./createExamplePage'); - -var EXAMPLES = [ - require('./ViewExample'), - require('./LayoutExample'), - require('./TextExample.ios'), - require('./TextInputExample'), - require('./ExpandingTextExample'), - require('./ImageExample'), - require('./ListViewSimpleExample'), - require('./ListViewPagingExample'), - require('./NavigatorIOSExample'), - require('./StatusBarIOSExample'), - require('./PointerEventsExample'), - require('./TouchableExample'), - require('./ActivityIndicatorExample'), - require('./ScrollViewExample'), - require('./DatePickerExample'), - require('./GeolocationExample'), - require('./TabBarExample'), - require('./SwitchExample'), - require('./SliderExample'), -]; - -var UIExplorerList = React.createClass({ - render: function() { - return ( - - - - {EXAMPLES.map(this._renderRow)} - - - - ); - }, - - _renderRow: function(example, i) { - invariant(example.title, 'Example must provide a title.'); - return ( - - this._onPressRow(example)}> - - - {example.title} - - - {example.description} - - - - - - ); - }, - - _onPressRow: function(example) { - var Component = example.examples ? - createExamplePage(null, example) : - example; - this.props.navigator.push({ - title: Component.title, - component: Component, - }); - }, -}); - -var styles = StyleSheet.create({ - list: { - backgroundColor: '#eeeeee', - }, - group: { - backgroundColor: 'white', - marginVertical: 25, - }, - line: { - backgroundColor: '#bbbbbb', - height: 1 / PixelRatio.get(), - }, - row: { - backgroundColor: 'white', - justifyContent: 'center', - paddingHorizontal: 15, - paddingVertical: 8, - }, - separator: { - height: 1 / PixelRatio.get(), - backgroundColor: '#bbbbbb', - marginLeft: 15, - }, - rowTitleText: { - fontSize: 17, - fontWeight: 'bold', - }, - rowDetailText: { - fontSize: 15, - color: '#888888', - lineHeight: 20, - }, -}); - -module.exports = UIExplorerList; diff --git a/Examples/UIExplorer/UIExplorerPage.js b/Examples/UIExplorer/UIExplorerPage.js deleted file mode 100644 index 5d619dcec80..00000000000 --- a/Examples/UIExplorer/UIExplorerPage.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule UIExplorerPage - */ -'use strict'; - -var React = require('react-native'); -var { - ScrollView, - StyleSheet, - View, -} = React; - -var UIExplorerTitle = require('./UIExplorerTitle'); - -var UIExplorerPage = React.createClass({ - - propTypes: { - keyboardShouldPersistTaps: React.PropTypes.bool, - noScroll: React.PropTypes.bool, - noSpacer: React.PropTypes.bool, - }, - - render: function() { - var ContentWrapper; - var wrapperProps = {}; - if (this.props.noScroll) { - ContentWrapper = View; - } else { - ContentWrapper = ScrollView; - wrapperProps.keyboardShouldPeristTaps = true; - wrapperProps.keyboardDismissMode = 'interactive'; - } - var title = this.props.title ? - : - null; - var spacer = this.props.noSpacer ? null : ; - return ( - - {title} - - {this.props.children} - {spacer} - - - ); - }, -}); - -var styles = StyleSheet.create({ - container: { - backgroundColor: '#e9eaed', - paddingTop: 15, - flex: 1, - }, - spacer: { - height: 270, - }, - wrapper: { - flex: 1, - }, -}); - -module.exports = UIExplorerPage; diff --git a/Examples/UIExplorer/UIExplorerTitle.js b/Examples/UIExplorer/UIExplorerTitle.js deleted file mode 100644 index a8fb4ba8dda..00000000000 --- a/Examples/UIExplorer/UIExplorerTitle.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule UIExplorerTitle - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -var UIExplorerTitle = React.createClass({ - render: function() { - return ( - - - {this.props.title} - - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - borderRadius: 4, - borderWidth: 0.5, - borderColor: '#d6d7da', - margin: 10, - height: 45, - padding: 10, - backgroundColor: 'white', - }, - text: { - fontSize: 19, - fontWeight: 'bold', - }, -}); - -module.exports = UIExplorerTitle; diff --git a/Examples/UIExplorer/ViewExample.js b/Examples/UIExplorer/ViewExample.js deleted file mode 100644 index 660c191bb26..00000000000 --- a/Examples/UIExplorer/ViewExample.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ViewExample - */ -'use strict'; - -var React = require('react-native'); -var { - StyleSheet, - Text, - View, -} = React; - -var UIExplorerBlock = require('./UIExplorerBlock'); -var UIExplorerPage = require('./UIExplorerPage'); - -var ViewExample = React.createClass({ - statics: { - title: '', - description: 'Basic building block of all UI.' - }, - getInitialState: function() { - return { - textBorderExampleHeight: 20, - }; - }, - - render: function() { - return ( - '}> - - - - Blue background - - - - - - 5px blue border - - - - - - 5px padding - - - 5px margin - - - - 5px margin and padding, - - - widthAutonomous=true - - - - - - - - Too much use of `borderRadius` (especially large radii) on - anything which is scrolling may result in dropped frames. - Use sparingly. - - - - - - - - - - - Overflow hidden - - - - - Overflow visible - - - - - - Opacity 0 - Opacity 0.1 - Opacity 0.3 - Opacity 0.5 - Opacity 0.7 - Opacity 0.9 - Opacity 1 - - - ); - }, - - updateHeight: function() { - var height = this.state.textBorderExampleHeight === 50 ? 20 : 50; - this.setState({textBorderExampleHeight: height}); - }, -}); - -var styles = StyleSheet.create({ - box: { - backgroundColor: '#527FE4', - borderColor: '#000033', - borderWidth: 1, - } -}); - -module.exports = ViewExample; diff --git a/Examples/UIExplorer/createExamplePage.js b/Examples/UIExplorer/createExamplePage.js deleted file mode 100644 index 39ed81133c3..00000000000 --- a/Examples/UIExplorer/createExamplePage.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule createExamplePage - */ -'use strict'; - -var React = require('react-native'); -var UIExplorerBlock = require('./UIExplorerBlock'); -var UIExplorerPage = require('./UIExplorerPage'); - -var invariant = require('invariant'); - -var createExamplePage = function(title, exampleModule) { - invariant(!!exampleModule.examples, 'The module must have examples'); - - var ExamplePage = React.createClass({ - statics: { - title: exampleModule.title, - description: exampleModule.description, - }, - - getBlock: function(example, i) { - // Hack warning: This is a hack because the www UI explorer requires - // renderComponent to be called. - var originalRenderComponent = React.renderComponent; - var originalRender = React.render; - var renderedComponent; - React.render = React.renderComponent = function(element, container) { - renderedComponent = element; - }; - var result = example.render(null); - if (result) { - renderedComponent = result; - } - React.renderComponent = originalRenderComponent; - React.render = originalRender; - return ( - - {renderedComponent} - - ); - }, - - render: function() { - return ( - - {exampleModule.examples.map(this.getBlock)} - - ); - } - }); - - return ExamplePage; -}; - -module.exports = createExamplePage; diff --git a/Examples/UIExplorer/main.m b/Examples/UIExplorer/main.m deleted file mode 100644 index 357a233b128..00000000000 --- a/Examples/UIExplorer/main.m +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 56a1131ca07..00000000000 --- a/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) 2015, Facebook, Inc. All rights reserved. - * - * React Native software is currently provided by Facebook to you for - * non-commercial testing and evaluation purposes only. Facebook reserves all - * rights not expressly granted. An open source version of this software will - * be provided at a later date. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ diff --git a/Libraries/Animation/LayoutAnimation.js b/Libraries/Animation/LayoutAnimation.js deleted file mode 100644 index 5ce5648b30a..00000000000 --- a/Libraries/Animation/LayoutAnimation.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule LayoutAnimation - */ -'use strict'; - -var PropTypes = require('ReactPropTypes'); -var RKUIManager = require('NativeModules').RKUIManager; - -var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker'); -var keyMirror = require('keyMirror'); - -var Types = keyMirror({ - spring: true, - linear: true, - easeInEaseOut: true, - easeIn: true, - easeOut: true, -}); - -var Properties = keyMirror({ - opacity: true, - scaleXY: true, -}); - -var animChecker = createStrictShapeTypeChecker({ - duration: PropTypes.number, - delay: PropTypes.number, - springDamping: PropTypes.number, - initialVelocity: PropTypes.number, - type: PropTypes.oneOf( - Object.keys(Types) - ), - property: PropTypes.oneOf( // Only applies to create/delete - Object.keys(Properties) - ), -}); - -var configChecker = createStrictShapeTypeChecker({ - duration: PropTypes.number.isRequired, - create: animChecker, - update: animChecker, - delete: animChecker, -}); - -var LayoutAnimation = { - configureNext(config, onAnimationDidEnd, onError) { - configChecker({config}, 'config', 'LayoutAnimation.configureNext'); - RKUIManager.configureNextLayoutAnimation(config, onAnimationDidEnd, onError); - }, - create(duration, type, creationProp) { - return { - duration, - create: { - type, - property: creationProp, - }, - update: { - type, - }, - }; - }, - Types: Types, - Properties: Properties, - configChecker: configChecker, -}; - -LayoutAnimation.Presets = { - easeInEaseOut: LayoutAnimation.create( - 0.3, Types.easeInEaseOut, Properties.opacity - ), - linear: LayoutAnimation.create( - 0.5, Types.linear, Properties.opacity - ), - spring: { - duration: 0.7, - create: { - type: Types.linear, - property: Properties.opacity, - }, - update: { - type: Types.spring, - springDamping: 0.4, - }, - }, -}; - -module.exports = LayoutAnimation; diff --git a/Libraries/Animation/POPAnimationMixin.js b/Libraries/Animation/POPAnimationMixin.js deleted file mode 100644 index a3f4b7defeb..00000000000 --- a/Libraries/Animation/POPAnimationMixin.js +++ /dev/null @@ -1,250 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule POPAnimationMixin - * @flow - */ -'use strict'; - -var POPAnimation = require('POPAnimation'); -if (!POPAnimation) { - // POP animation isn't available in the OSS fork - this is a temporary - // workaround to enable its availability to be determined at runtime. - module.exports = null; -} else { - -var invariant = require('invariant'); -var warning = require('warning'); - -var POPAnimationMixin = { - /** - * Different ways to interpolate between beginning and end states - * of properties during animation, such as spring, linear, and decay. - */ - AnimationTypes: POPAnimation.Types, - AnimationProperties: POPAnimation.Properties, - - getInitialState: function(): Object { - return { - _currentAnimationsByNodeHandle: {}, - }; - }, - - _ensureBookkeepingSetup: function(nodeHandle: any) { - if (!this.state._currentAnimationsByNodeHandle[nodeHandle]) { - this.state._currentAnimationsByNodeHandle[nodeHandle] = []; - } - }, - - /** - * Start animating the View with ref `refKey`. - * - * @param {key} refKey The key to reference the View to be animated. - * - * @param {number|Object} anim Either the identifier returned by - * POPAnimation.create* or an object defining all the necessary - * properties of the animation you wish to start (including type, matching - * an entry in AnimationTypes). - * - * @param {func} doneCallback A callback fired when the animation is done, and - * is passed a `finished` param that indicates whether the animation - * completely finished, or was interrupted. - */ - startAnimation: function( - refKey: string, - anim: number | {type: number; property: number;}, - doneCallback: (finished: bool) => void - ) { - var animID: number = 0; - if (typeof anim === 'number') { - animID = anim; - } else { - invariant( - anim instanceof Object && - anim.type !== undefined && - anim.property !== undefined, - 'Animation definitions must specify a type of animation and a ' + - 'property to animate.' - ); - animID = POPAnimation.createAnimation(anim.type, anim); - } - invariant( - this.refs[refKey], - 'Invalid refKey ' + refKey + ' for anim:\n' + JSON.stringify(anim) + - '\nvalid refs: ' + JSON.stringify(Object.keys(this.refs)) - ); - var refNodeHandle = this.refs[refKey].getNodeHandle(); - this.startAnimationWithNodeHandle(refNodeHandle, animID, doneCallback); - }, - - /** - * Starts an animation on a native node. - * - * @param {NodeHandle} nodeHandle Handle to underlying native node. - * @see `startAnimation`. - */ - startAnimationWithNodeHandle: function( - nodeHandle: any, - animID: number, - doneCallback: (finished: bool) => void - ) { - this._ensureBookkeepingSetup(nodeHandle); - var animations = this.state._currentAnimationsByNodeHandle[nodeHandle]; - var animIndex = animations.length; - animations.push(animID); - var cleanupWrapper = (finished) => { - if (!this.isMounted()) { - return; - } - animations[animIndex] = 0; // zero it out so we don't try to stop it - var allDone = true; - for (var ii = 0; ii < animations.length; ii++) { - if (animations[ii]) { - allDone = false; - break; - } - } - if (allDone) { - this.state._currentAnimationsByNodeHandle[nodeHandle] = undefined; - } - doneCallback && doneCallback(finished); - }; - POPAnimation.addAnimation(nodeHandle, animID, cleanupWrapper); - }, - - /** - * Starts multiple animations with one shared callback that is called when all - * animations complete. - * - * @param {Array(Object} animations Array of objects defining all the - * animations to start, each with shape `{ref|nodeHandle, anim}`. - * @param {func} onSuccess A callback fired when all animations have returned, - * and is passed a finished arg that is true if all animations finished - * completely. - * @param {func} onFailure Not supported yet. - */ - startAnimations: function( - animations: Array, - onSuccess: (finished: boolean) => void, - onFailure: () => void - ) { - var numReturned = 0; - var numFinished = 0; - var numAnimations = animations.length; - var metaCallback = (finished) => { - if (finished) { - ++numFinished; - } - if (++numReturned === numAnimations) { - onSuccess && onSuccess(numFinished === numAnimations); - } - }; - animations.forEach((anim) => { - warning( - anim.ref != null || anim.nodeHandle != null && - !anim.ref !== !anim.nodeHandle, - 'Animations must be specified with either ref xor nodeHandle' - ); - if (anim.ref) { - this.startAnimation(anim.ref, anim.anim, metaCallback); - } else if (anim.nodeHandle) { - this.startAnimationWithNodeHandle(anim.nodeHandle, anim.anim, metaCallback); - } - }); - }, - - /** - * Stop any and all animations operating on the View with native node handle - * `nodeHandle`. - * - * @param {NodeHandle} component The instance to stop animations - * on. Do not pass a composite component. - */ - stopNodeHandleAnimations: function(nodeHandle: any) { - if (!this.state._currentAnimationsByNodeHandle[nodeHandle]) { - return; - } - var anims = this.state._currentAnimationsByNodeHandle[nodeHandle]; - for (var i = 0; i < anims.length; i++) { - var anim = anims[i]; - if (anim) { - // Note: Converting the string key to a number `nodeHandle`. - POPAnimation.removeAnimation(+nodeHandle, anim); - } - } - this.state._currentAnimationsByNodeHandle[nodeHandle] = undefined; - }, - - /** - * Stop any and all animations operating on the View with ref `refKey`. - * - * @param {key} refKey The key to reference the View to be animated. - */ - stopAnimations: function(refKey: string) { - invariant(this.refs[refKey], 'invalid ref'); - this.stopNodeHandleAnimations(this.refs[refKey].getNodeHandle()); - }, - - /** - * Stop any and all animations created by this component on itself and - * subviews. - */ - stopAllAnimations: function() { - for (var nodeHandle in this.state._currentAnimationsByNodeHandle) { - this.stopNodeHandleAnimations(nodeHandle); - } - }, - - /** - * Animates size and position of a view referenced by `refKey` to a specific - * frame. - * - * @param {key} refKey ref key for view to animate. - * @param {Object} frame The frame to animate the view to, specified as {left, - * top, width, height}. - * @param {const} type What type of interpolation to use, selected from - * `inperpolationTypes`. - * @param {Object} event Event encapsulating synthetic and native data that - * may have triggered this animation. Velocity is extracted from it if - * possible and applied to the animation. - * @param {func} doneCallback A callback fired when the animation is done, and - * is passed a `finished` param that indicates whether the animation - * completely finished, or was interrupted. - */ - animateToFrame: function( - refKey: string, - frame: {left: number; top: number; width: number; height: number;}, - type: number, - velocity: number, - doneCallback: (finished: boolean) => void - ) { - var animFrame = { // Animations use a centered coordinate system. - x: frame.left + frame.width / 2, - y: frame.top + frame.height / 2, - w: frame.width, - h: frame.height - }; - frame = undefined; - var velocity = velocity || [0, 0]; - var posAnim = POPAnimation.createAnimation(type, { - property: POPAnimation.Properties.position, - toValue: [animFrame.x, animFrame.y], - velocity: velocity, - }); - var sizeAnim = POPAnimation.createAnimation(type, { - property: POPAnimation.Properties.size, - toValue: [animFrame.w, animFrame.h] - }); - this.startAnimation(refKey, posAnim, doneCallback); - this.startAnimation(refKey, sizeAnim); - }, - - // Cleanup any potentially leaked animations. - componentWillUnmount: function() { - this.stopAllAnimations(); - } -}; - -module.exports = POPAnimationMixin; - -} diff --git a/Libraries/AppRegistry/AppRegistry.js b/Libraries/AppRegistry/AppRegistry.js deleted file mode 100644 index a11f5d49416..00000000000 --- a/Libraries/AppRegistry/AppRegistry.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule AppRegistry - */ -'use strict'; - -var invariant = require('invariant'); -var renderApplication = require('renderApplication'); - -if (__DEV__) { - // In order to use Cmd+P to record/dump perf data, we need to make sure - // this module is available in the bundle - require('RCTRenderingPerf'); -} - -var runnables = {}; - -/** - * `AppRegistry` is the JS entry point to running all React Native apps. App - * root components should register themselves with - * `AppRegistry.registerComponent`, then the native system can load the bundle - * for the app and then actually run the app when it's ready by invoking - * `AppRegistry.runApplication`. - * - * `AppRegistry` should be `require`d early in the `require` sequence to make - * sure the JS execution environment is setup before other modules are - * `require`d. - */ -var AppRegistry = { - registerConfig: function(config) { - for (var i = 0; i < config.length; ++i) { - if (config[i].run) { - AppRegistry.registerRunnable(config[i].appKey, config[i].run); - } else { - AppRegistry.registerComponent(config[i].appKey, config[i].component); - } - } - }, - - registerComponent: function(appKey, getComponentFunc) { - runnables[appKey] = { - run: (appParameters) => - renderApplication(getComponentFunc(), appParameters.initialProps, appParameters.rootTag) - }; - return appKey; - }, - - registerRunnable: function(appKey, func) { - runnables[appKey] = {run: func}; - return appKey; - }, - - runApplication: function(appKey, appParameters) { - console.log( - 'Running application "' + appKey + '" with appParams: ', - appParameters - ); - - invariant( - runnables[appKey] && runnables[appKey].run, - 'Application ' + appKey + ' has not been registered.' - ); - runnables[appKey].run(appParameters); - }, -}; - -module.exports = AppRegistry; diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js b/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js deleted file mode 100644 index 68052857544..00000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule NativeModules - */ -'use strict'; - -var NativeModules = require('BatchedBridge').RemoteModules; - -// Dirty hack to support old (RK) and new (RCT) native module name conventions -Object.keys(NativeModules).forEach((moduleName) => { - var rkModuleName = moduleName.replace(/^RCT/, 'RK'); - NativeModules[rkModuleName] = NativeModules[moduleName]; -}); - -module.exports = NativeModules; diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/NativeModulesDeprecated.js b/Libraries/BatchedBridge/BatchedBridgedModules/NativeModulesDeprecated.js deleted file mode 100644 index 2d83d6f9a56..00000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/NativeModulesDeprecated.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule NativeModulesDeprecated - */ -'use strict'; - -var RemoteModulesDeprecated = require('BatchedBridge').RemoteModulesDeprecated; - -// Dirty hack to support old (RK) and new (RCT) native module name conventions -Object.keys(RemoteModulesDeprecated).forEach((moduleName) => { - var rkModuleName = moduleName.replace(/^RCT/, 'RK'); - RemoteModulesDeprecated[rkModuleName] = RemoteModulesDeprecated[moduleName]; -}); - -module.exports = RemoteModulesDeprecated; diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/POPAnimation.js b/Libraries/BatchedBridge/BatchedBridgedModules/POPAnimation.js deleted file mode 100644 index 8ec0bd62fb7..00000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/POPAnimation.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule POPAnimation - */ -'use strict'; - -var RKPOPAnimationManager = require('NativeModulesDeprecated').RKPOPAnimationManager; -if (!RKPOPAnimationManager) { - // POP animation isn't available in the OSS fork - this is a temporary - // workaround to enable its availability to be determined at runtime. - module.exports = null; -} else { - -var ReactPropTypes = require('ReactPropTypes'); -var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker'); -var getObjectValues = require('getObjectValues'); -var invariant = require('invariant'); -var merge = require('merge'); - -var RKTypes = RKPOPAnimationManager.Types; -var RKProperties = RKPOPAnimationManager.Properties; - -var Properties = { - bounds: RKProperties.bounds, - opacity: RKProperties.opacity, - position: RKProperties.position, - positionX: RKProperties.positionX, - positionY: RKProperties.positionY, - zPosition: RKProperties.zPosition, - rotation: RKProperties.rotation, - rotationX: RKProperties.rotationX, - rotationY: RKProperties.rotationY, - scaleX: RKProperties.scaleX, - scaleXY: RKProperties.scaleXY, - scaleY: RKProperties.scaleY, - shadowColor: RKProperties.shadowColor, - shadowOffset: RKProperties.shadowOffset, - shadowOpacity: RKProperties.shadowOpacity, - shadowRadius: RKProperties.shadowRadius, - size: RKProperties.size, - subscaleXY: RKProperties.subscaleXY, - subtranslationX: RKProperties.subtranslationX, - subtranslationXY: RKProperties.subtranslationXY, - subtranslationY: RKProperties.subtranslationY, - subtranslationZ: RKProperties.subtranslationZ, - translationX: RKProperties.translationX, - translationXY: RKProperties.translationXY, - translationY: RKProperties.translationY, - translationZ: RKProperties.translationZ, -}; - -var Types = { - decay: RKTypes.decay, - easeIn: RKTypes.easeIn, - easeInEaseOut: RKTypes.easeInEaseOut, - easeOut: RKTypes.easeOut, - linear: RKTypes.linear, - spring: RKTypes.spring, -}; - -var POPAnimation = { - Types: Types, - Properties: Properties, - - attributeChecker: createStrictShapeTypeChecker({ - type: ReactPropTypes.oneOf(getObjectValues(Types)), - property: ReactPropTypes.oneOf(getObjectValues(Properties)), - fromValue: ReactPropTypes.any, - toValue: ReactPropTypes.any, - duration: ReactPropTypes.any, - velocity: ReactPropTypes.any, - deceleration: ReactPropTypes.any, - springBounciness: ReactPropTypes.any, - dynamicsFriction: ReactPropTypes.any, - dynamicsMass: ReactPropTypes.any, - dynamicsTension: ReactPropTypes.any, - }), - - lastUsedTag: 0, - allocateTagForAnimation: function() { - return ++this.lastUsedTag; - }, - - createAnimation: function(typeName, attrs) { - var tag = this.allocateTagForAnimation(); - - if (__DEV__) { - POPAnimation.attributeChecker( - {attrs}, - 'attrs', - 'POPAnimation.createAnimation' - ); - POPAnimation.attributeChecker( - {attrs: {type: typeName}}, - 'attrs', - 'POPAnimation.createAnimation' - ); - } - - RKPOPAnimationManager.createAnimationInternal(tag, typeName, attrs); - return tag; - }, - - createSpringAnimation: function(attrs) { - return this.createAnimation(this.Types.spring, attrs); - }, - - createDecayAnimation: function(attrs) { - return this.createAnimation(this.Types.decay, attrs); - }, - - createLinearAnimation: function(attrs) { - return this.createAnimation(this.Types.linear, attrs); - }, - - createEaseInAnimation: function(attrs) { - return this.createAnimation(this.Types.easeIn, attrs); - }, - - createEaseOutAnimation: function(attrs) { - return this.createAnimation(this.Types.easeOut, attrs); - }, - - createEaseInEaseOutAnimation: function(attrs) { - return this.createAnimation(this.Types.easeInEaseOut, attrs); - }, - - addAnimation: function(nodeHandle, anim, callback) { - RKPOPAnimationManager.addAnimation(nodeHandle, anim, callback); - }, - - removeAnimation: function(nodeHandle, anim) { - RKPOPAnimationManager.removeAnimation(nodeHandle, anim); - }, -}; - -// Make sure that we correctly propagate RKPOPAnimationManager constants -// to POPAnimation -if (__DEV__) { - var allProperties = merge( - RKPOPAnimationManager.Properties, - RKPOPAnimationManager.Properties - ); - for (var key in allProperties) { - invariant( - POPAnimation.Properties[key] === RKPOPAnimationManager.Properties[key], - 'POPAnimation doesn\'t copy property ' + key + ' correctly' - ); - } - - var allTypes = merge( - RKPOPAnimationManager.Types, - RKPOPAnimationManager.Types - ); - for (var key in allTypes) { - invariant( - POPAnimation.Types[key] === RKPOPAnimationManager.Types[key], - 'POPAnimation doesn\'t copy type ' + key + ' correctly' - ); - } -} - -module.exports = POPAnimation; - -} diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/RCTEventEmitter.js b/Libraries/BatchedBridge/BatchedBridgedModules/RCTEventEmitter.js deleted file mode 100644 index 9ef7d965fc7..00000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/RCTEventEmitter.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule RCTEventEmitter - */ -'use strict'; - -var ReactIOSEventEmitter = require('ReactIOSEventEmitter'); - -// Completely locally implemented - no native hooks. -module.exports = ReactIOSEventEmitter; diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js b/Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js deleted file mode 100644 index 68b5118ff63..00000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule RCTJSTimers - */ -'use strict'; - -var JSTimersExecution = require('JSTimersExecution'); - -var RCTJSTimers = JSTimersExecution; - -module.exports = RCTJSTimers; diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/RKAlertManager.ios.js b/Libraries/BatchedBridge/BatchedBridgedModules/RKAlertManager.ios.js deleted file mode 100644 index 39d3cbc2792..00000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/RKAlertManager.ios.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule RKAlertManager - */ -'use strict'; - -var RKAlertManager = require('NativeModulesDeprecated').RKAlertManager; - -module.exports = RKAlertManager; diff --git a/Libraries/BatchedBridge/BatchingImplementation/BatchedBridge.js b/Libraries/BatchedBridge/BatchingImplementation/BatchedBridge.js deleted file mode 100644 index b5ceec184ae..00000000000 --- a/Libraries/BatchedBridge/BatchingImplementation/BatchedBridge.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule BatchedBridge - */ -'use strict'; - -var BatchedBridgeFactory = require('BatchedBridgeFactory'); -var MessageQueue = require('MessageQueue'); - -/** - * Signature that matches the native IOS modules/methods that are exposed. We - * indicate which ones accept a callback. The order of modules and methods - * within them implicitly define their numerical *ID* that will be used to - * describe method calls across the wire. This is so that memory is used - * efficiently and we do not need to copy strings in native land - or across any - * wire. - */ - -var remoteModulesConfig = __fbBatchedBridgeConfig.remoteModuleConfig; -var localModulesConfig = __fbBatchedBridgeConfig.localModulesConfig; - - -var BatchedBridge = BatchedBridgeFactory.create( - MessageQueue, - remoteModulesConfig, - localModulesConfig -); - -BatchedBridge._config = remoteModulesConfig; - -module.exports = BatchedBridge; diff --git a/Libraries/BatchedBridge/BatchingImplementation/BatchedBridgeFactory.js b/Libraries/BatchedBridge/BatchingImplementation/BatchedBridgeFactory.js deleted file mode 100644 index d6c7f5f3f6b..00000000000 --- a/Libraries/BatchedBridge/BatchingImplementation/BatchedBridgeFactory.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule BatchedBridgeFactory - */ -'use strict'; - -var invariant = require('invariant'); -var keyMirror = require('keyMirror'); -var mapObject = require('mapObject'); -var warning = require('warning'); - -var slice = Array.prototype.slice; - -var MethodTypes = keyMirror({ - remote: null, - local: null, -}); - -/** - * Creates remotely invokable modules. - */ -var BatchedBridgeFactory = { - MethodTypes: MethodTypes, - /** - * @deprecated: Remove callsites and delete this method. - * - * @param {MessageQueue} messageQueue Message queue that has been created with - * the `moduleConfig` (among others perhaps). - * @param {object} moduleConfig Configuration of module names/method - * names to callback types. - * @return {object} Remote representation of configured module. - */ - _createDeprecatedBridgedModule: function(messageQueue, moduleConfig, moduleName) { - var remoteModule = mapObject(moduleConfig.methods, function(methodConfig, memberName) { - return methodConfig.type === MethodTypes.local ? null : function() { - var lastArg = arguments.length ? arguments[arguments.length - 1] : null; - var hasCB = - typeof lastArg == 'function'; - var args = slice.call(arguments, 0, arguments.length - (hasCB ? 1 : 0)); - var cb = hasCB ? lastArg : null; - return messageQueue.callDeprecated(moduleName, memberName, args, cb); - }; - }); - for (var constName in moduleConfig.constants) { - warning(!remoteModule[constName], 'saw constant and method named %s', constName); - remoteModule[constName] = moduleConfig.constants[constName]; - } - return remoteModule; - }, - - /** - * @param {MessageQueue} messageQueue Message queue that has been created with - * the `moduleConfig` (among others perhaps). - * @param {object} moduleConfig Configuration of module names/method - * names to callback types. - * @return {object} Remote representation of configured module. - */ - _createBridgedModule: function(messageQueue, moduleConfig, moduleName) { - var remoteModule = mapObject(moduleConfig.methods, function(methodConfig, memberName) { - return methodConfig.type === MethodTypes.local ? null : function() { - var lastArg = arguments.length > 0 ? arguments[arguments.length - 1] : null; - var secondLastArg = arguments.length > 1 ? arguments[arguments.length - 2] : null; - var hasSuccCB = typeof lastArg === 'function'; - var hasErrorCB = typeof secondLastArg === 'function'; - var hasCBs = hasSuccCB; - invariant( - (hasSuccCB && hasErrorCB) || (!hasSuccCB && !hasErrorCB), - 'You must supply error callbacks and success callbacks or neither' - ); - var args = slice.call(arguments, 0, arguments.length - (hasCBs ? 2 : 0)); - var onSucc = hasCBs ? lastArg : null; - var onFail = hasCBs ? secondLastArg : null; - return messageQueue.call(moduleName, memberName, args, onFail, onSucc); - }; - }); - for (var constName in moduleConfig.constants) { - warning(!remoteModule[constName], 'saw constant and method named %s', constName); - remoteModule[constName] = moduleConfig.constants[constName]; - } - return remoteModule; - }, - - - create: function(MessageQueue, modulesConfig, localModulesConfig) { - var messageQueue = new MessageQueue(modulesConfig, localModulesConfig); - return { - callFunction: messageQueue.callFunction.bind(messageQueue), - callFunctionReturnFlushedQueue: - messageQueue.callFunctionReturnFlushedQueue.bind(messageQueue), - invokeCallback: messageQueue.invokeCallback.bind(messageQueue), - invokeCallbackAndReturnFlushedQueue: - messageQueue.invokeCallbackAndReturnFlushedQueue.bind(messageQueue), - flushedQueue: messageQueue.flushedQueue.bind(messageQueue), - // These deprecated modules do not accept an error callback. - RemoteModulesDeprecated: mapObject(modulesConfig, this._createDeprecatedBridgedModule.bind(this, messageQueue)), - RemoteModules: mapObject(modulesConfig, this._createBridgedModule.bind(this, messageQueue)), - setLoggingEnabled: messageQueue.setLoggingEnabled.bind(messageQueue), - getLoggedOutgoingItems: messageQueue.getLoggedOutgoingItems.bind(messageQueue), - getLoggedIncomingItems: messageQueue.getLoggedIncomingItems.bind(messageQueue), - replayPreviousLog: messageQueue.replayPreviousLog.bind(messageQueue) - }; - } -}; - -module.exports = BatchedBridgeFactory; diff --git a/Libraries/Components/ActivityIndicatorIOS/ActivityIndicatorIOS.ios.js b/Libraries/Components/ActivityIndicatorIOS/ActivityIndicatorIOS.ios.js deleted file mode 100644 index df762c5ee3d..00000000000 --- a/Libraries/Components/ActivityIndicatorIOS/ActivityIndicatorIOS.ios.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ActivityIndicatorIOS - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var NativeModules = require('NativeModules'); -var PropTypes = require('ReactPropTypes'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); -var View = require('View'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); -var keyMirror = require('keyMirror'); -var merge = require('merge'); - -var SpinnerSize = keyMirror({ - large: null, - small: null, -}); - -var GRAY = '#999999'; - -var ActivityIndicatorIOS = React.createClass({ - mixins: [NativeMethodsMixin], - - propTypes: { - /** - * 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: PropTypes.string, - - size: PropTypes.oneOf([ - 'small', // default - 'large', - ]), - }, - - getDefaultProps: function() { - return { - animating: true, - size: SpinnerSize.small, - color: GRAY, - }; - }, - - render: function() { - var style = styles.sizeSmall; - var NativeConstants = NativeModules.RKUIManager.UIActivityIndicatorView.Constants; - var activityIndicatorViewStyle = NativeConstants.StyleWhite; - if (this.props.size === 'large') { - style = styles.sizeLarge; - activityIndicatorViewStyle = NativeConstants.StyleWhiteLarge; - } - return ( - - - - ); - } -}); - -var styles = StyleSheet.create({ - container: { - alignItems: 'center', - justifyContent: 'center', - }, - sizeSmall: { - height: 20, - }, - sizeLarge: { - height: 36, - } -}); - -var UIActivityIndicatorView = createReactIOSNativeComponentClass({ - validAttributes: merge( - ReactIOSViewAttributes.UIView, { - activityIndicatorViewStyle: true, // UIActivityIndicatorViewStyle=UIActivityIndicatorViewStyleWhite - animating: true, - color: true, - }), - uiViewClassName: 'UIActivityIndicatorView', -}); - -module.exports = ActivityIndicatorIOS; diff --git a/Libraries/Components/DatePicker/DatePickerIOS.ios.js b/Libraries/Components/DatePicker/DatePickerIOS.ios.js deleted file mode 100644 index b4a6d5bb14f..00000000000 --- a/Libraries/Components/DatePicker/DatePickerIOS.ios.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule DatePickerIOS - * - * This is a controlled component version of RKDatePickerIOS - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var PropTypes = require('ReactPropTypes'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var RKDatePickerIOSConsts = require('NativeModules').RKUIManager.RCTDatePicker.Constants; -var StyleSheet = require('StyleSheet'); -var View = require('View'); - -var createReactIOSNativeComponentClass = - require('createReactIOSNativeComponentClass'); -var merge = require('merge'); - -var DATEPICKER = 'datepicker'; - -/** - * Use `DatePickerIOS` to render a date/time picker (selector) on iOS. This is - * a controlled component, so you must hook in to the `onDateChange` callback - * and update the `date` prop in order for the component to update, otherwise - * the user's change will be reverted immediately to reflect `props.date` as the - * source of truth. - */ -var DatePickerIOS = React.createClass({ - mixins: [NativeMethodsMixin], - - propTypes: { - /** - * The currently selected date. - */ - date: PropTypes.instanceOf(Date).isRequired, - - /** - * Date change handler. - * - * This is called when the user changes the date or time in the UI. - * The first and only argument is a Date object representing the new - * date and time. - */ - onDateChange: PropTypes.func.isRequired, - - /** - * Maximum date. - * - * Restricts the range of possible date/time values. - */ - maximumDate: PropTypes.instanceOf(Date), - - /** - * Minimum date. - * - * Restricts the range of possible date/time values. - */ - minimumDate: PropTypes.instanceOf(Date), - - /** - * The date picker mode. - * - * Valid modes on iOS are: 'date', 'time', 'datetime'. - */ - mode: PropTypes.oneOf(Object.keys(RKDatePickerIOSConsts.DatePickerModes)), - - /** - * The interval at which minutes can be selected. - */ - minuteInterval: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30]), - - /** - * Timezone offset in seconds. - * - * By default, the date picker will use the device's timezone. With this - * parameter, it is possible to force a certain timezone offset. For - * instance, to show times in Pacific Standard Time, pass -7 * 60. - */ - timeZoneOffsetInMinutes: PropTypes.number, - }, - - getDefaultProps: function() { - return { - mode: 'datetime', - }; - }, - - _onChange: function(event) { - var nativeTimeStamp = event.nativeEvent.timestamp; - this.props.onDateChange && this.props.onDateChange( - new Date(nativeTimeStamp) - ); - this.props.onChange && this.props.onChange(event); - - // We expect the onChange* handlers to be in charge of updating our `date` - // prop. That way they can also disallow/undo/mutate the selection of - // certain values. In other words, the embedder of this component should - // be the source of truth, not the native component. - var propsTimeStamp = this.props.date.getTime(); - if (nativeTimeStamp !== propsTimeStamp) { - this.refs[DATEPICKER].setNativeProps({ - date: propsTimeStamp, - }); - } - }, - - render: function() { - var props = this.props; - return ( - - - - ); - } -}); - -var styles = StyleSheet.create({ - rkDatePickerIOS: { - height: RKDatePickerIOSConsts.ComponentHeight, - width: RKDatePickerIOSConsts.ComponentWidth, - }, -}); - -var rkDatePickerIOSAttributes = merge(ReactIOSViewAttributes.UIView, { - date: true, - maximumDate: true, - minimumDate: true, - mode: true, - minuteInterval: true, - timeZoneOffsetInMinutes: true, -}); - -var RKDatePickerIOS = createReactIOSNativeComponentClass({ - validAttributes: rkDatePickerIOSAttributes, - uiViewClassName: 'RCTDatePicker', -}); - -module.exports = DatePickerIOS; diff --git a/Libraries/Components/ListView/ListView.js b/Libraries/Components/ListView/ListView.js deleted file mode 100644 index 1eb7eef5d0f..00000000000 --- a/Libraries/Components/ListView/ListView.js +++ /dev/null @@ -1,475 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ListView - */ -'use strict'; - -var ListViewDataSource = require('ListViewDataSource'); -var React = require('React'); -var RKUIManager = require('NativeModules').RKUIManager; -var ScrollView = require('ScrollView'); -var ScrollResponder = require('ScrollResponder'); -var StaticRenderer = require('StaticRenderer'); -var TimerMixin = require('TimerMixin'); - -var logError = require('logError'); -var merge = require('merge'); -var isEmpty = require('isEmpty'); - -var PropTypes = React.PropTypes; - -var DEFAULT_PAGE_SIZE = 1; -var DEFAULT_INITIAL_ROWS = 10; -var DEFAULT_SCROLL_RENDER_AHEAD = 1000; -var DEFAULT_END_REACHED_THRESHOLD = 1000; -var DEFAULT_SCROLL_CALLBACK_THROTTLE = 50; -var RENDER_INTERVAL = 20; -var SCROLLVIEW_REF = 'listviewscroll'; - - -/** - * ListView - A core component designed for efficient display of vertically - * scrolling lists of changing data. The minimal API is to create a - * `ListView.DataSource`, populate it with a simple array of data blobs, and - * instantiate a `ListView` component with that data source and a `renderRow` - * callback which takes a blob from the data array and returns a renderable - * component. - * - * Minimal example: - * - * ``` - * getInitialState: function() { - * var ds = new ListViewDataSource({rowHasChanged: (r1, r2) => r1 !== r2}); - * return { - * dataSource: ds.cloneWithRows(['row 1', 'row 2']), - * }; - * }, - * - * render: function() { - * return ( - * {rowData}} - * /> - * ); - * }, - * ``` - * - * ListView also supports more advanced features, including sections with sticky - * section headers, header and footer support, callbacks on reaching the end of - * the available data (`onEndReached`) and on the set of rows that are visible - * in the device viewport change (`onChangeVisibleRows`), and several - * performance optimizations. - * - * There are a few performance operations designed to make ListView scroll - * smoothly while dynamically loading potentially very large (or conceptually - * infinite) data sets: - * - * * Only re-render changed rows - the hasRowChanged function provided to the - * data source tells the ListView if it needs to re-render a row because the - * source data has changed - see ListViewDataSource for more details. - * - * * Rate-limited row rendering - By default, only one row is rendered per - * event-loop (customizable with the `pageSize` prop). This breaks up the - * work into smaller chunks to reduce the chance of dropping frames while - * rendering rows. - */ - -var ListView = React.createClass({ - mixins: [ScrollResponder.Mixin, TimerMixin], - - statics: { - DataSource: ListViewDataSource, - }, - - /** - * You must provide a renderRow function. If you omit any of the other render - * functions, ListView will simply skip rendering them. - * - * - renderRow(rowData, sectionID, rowID); - * - renderSectionHeader(sectionData, sectionID); - */ - propTypes: { - ...ScrollView.propTypes, - - dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired, - /** - * (rowData, sectionID, rowID) => renderable - * Takes a data entry from the data source and its ids and should return - * a renderable component to be rendered as the row. By default the data - * is exactly what was put into the data source, but it's also possible to - * provide custom extractors. - */ - renderRow: PropTypes.func.isRequired, - /** - * How many rows to render on initial component mount. Use this to make - * it so that the first screen worth of data apears at one time instead of - * over the course of multiple frames. - */ - initialListSize: PropTypes.number, - /** - * Called when all rows have been rendered and the list has been scrolled - * to within onEndReachedThreshold of the bottom. The native scroll - * event is provided. - */ - onEndReached: PropTypes.func, - /** - * Threshold in pixels for onEndReached. - */ - onEndReachedThreshold: PropTypes.number, - /** - * Number of rows to render per event loop. - */ - pageSize: PropTypes.number, - /** - * () => renderable - * - * The header and footer are always rendered (if these props are provided) - * on every render pass. If they are expensive to re-render, wrap them - * in StaticContainer or other mechanism as appropriate. Footer is always - * at the bottom of the list, and header at the top, on every render pass. - */ - renderFooter: PropTypes.func, - renderHeader: PropTypes.func, - /** - * (sectionData, sectionID) => renderable - * - * If provided, a sticky header is rendered for this section. The sticky - * behavior means that it will scroll with the content at the top of the - * section until it reaches the top of the screen, at which point it will - * stick to the top until it is pushed off the screen by the next section - * header. - */ - renderSectionHeader: PropTypes.func, - /** - * How early to start rendering rows before they come on screen, in - * pixels. - */ - scrollRenderAheadDistance: React.PropTypes.number, - /** - * (visibleRows, changedRows) => void - * - * Called when the set of visible rows changes. `visibleRows` maps - * { sectionID: { rowID: true }} for all the visible rows, and - * `changedRows` maps { sectionID: { rowID: true | false }} for the rows - * that have changed their visibility, with true indicating visible, and - * false indicating the view has moved out of view. - */ - onChangeVisibleRows: React.PropTypes.func, - /** - * An experimental performance optimization for improving scroll perf of - * large lists, used in conjunction with overflow: 'hidden' on the row - * containers. Use at your own risk. - */ - removeClippedSubviews: React.PropTypes.bool, - }, - - /** - * Exports some data, e.g. for perf investigations or analytics. - */ - getMetrics: function() { - return { - contentHeight: this.scrollProperties.contentHeight, - totalRows: this.props.dataSource.getRowCount(), - renderedRows: this.state.curRenderedRowsCount, - visibleRows: Object.keys(this._visibleRows).length, - }; - }, - - /** - * Provides a handle to the underlying scroll responder to support operations - * such as scrollTo. - */ - getScrollResponder: function() { - return this.refs[SCROLLVIEW_REF]; - }, - - setNativeProps: function(props) { - this.refs[SCROLLVIEW_REF].setNativeProps(props); - }, - - /** - * React life cycle hooks. - */ - - getDefaultProps: function() { - return { - initialListSize: DEFAULT_INITIAL_ROWS, - pageSize: DEFAULT_PAGE_SIZE, - scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD, - onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD, - }; - }, - - getInitialState: function() { - return { - curRenderedRowsCount: this.props.initialListSize, - prevRenderedRowsCount: 0, - }; - }, - - componentWillMount: function() { - // this data should never trigger a render pass, so don't put in state - this.scrollProperties = { - visibleHeight: null, - contentHeight: null, - offsetY: 0 - }; - this._childFrames = []; - this._visibleRows = {}; - }, - - componentDidMount: function() { - // do this in animation frame until componentDidMount actually runs after - // the component is laid out - this.requestAnimationFrame(() => { - this._measureAndUpdateScrollProps(); - this.setInterval(this._renderMoreRowsIfNeeded, RENDER_INTERVAL); - }); - }, - - componentWillReceiveProps: function(nextProps) { - if (this.props.dataSource !== nextProps.dataSource) { - this.setState({prevRenderedRowsCount: 0}); - } - }, - - render: function() { - var bodyComponents = []; - - var dataSource = this.props.dataSource; - var allRowIDs = dataSource.rowIdentities; - var rowCount = 0; - var sectionHeaderIndices = []; - - var header = this.props.renderHeader && this.props.renderHeader(); - var footer = this.props.renderFooter && this.props.renderFooter(); - var totalIndex = header ? 1 : 0; - - for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) { - var sectionID = dataSource.sectionIdentities[sectionIdx]; - var rowIDs = allRowIDs[sectionIdx]; - if (rowIDs.length === 0) { - continue; - } - - if (this.props.renderSectionHeader) { - var shouldUpdateHeader = rowCount >= this.state.prevRenderedRowsCount && - dataSource.sectionHeaderShouldUpdate(sectionIdx); - bodyComponents.push( - - ); - sectionHeaderIndices.push(totalIndex++); - } - - for (var rowIdx = 0; rowIdx < rowIDs.length; rowIdx++) { - var rowID = rowIDs[rowIdx]; - var comboID = sectionID + rowID; - var shouldUpdateRow = rowCount >= this.state.prevRenderedRowsCount && - dataSource.rowShouldUpdate(sectionIdx, rowIdx); - var row = - ; - bodyComponents.push(row); - totalIndex++; - if (++rowCount === this.state.curRenderedRowsCount) { - break; - } - } - if (rowCount >= this.state.curRenderedRowsCount) { - break; - } - } - - var props = merge( - this.props, { - onScroll: this._onScroll, - stickyHeaderIndices: sectionHeaderIndices, - } - ); - if (!props.throttleScrollCallbackMS) { - props.throttleScrollCallbackMS = DEFAULT_SCROLL_CALLBACK_THROTTLE; - } - - return ( - - {header} - {bodyComponents} - {footer} - - ); - }, - - /** - * Private methods - */ - - _measureAndUpdateScrollProps: function() { - RKUIManager.measureLayout( - this.refs[SCROLLVIEW_REF].getInnerViewNode(), - this.refs[SCROLLVIEW_REF].getNodeHandle(), - logError, - this._setScrollContentHeight - ); - RKUIManager.measureLayoutRelativeToParent( - this.refs[SCROLLVIEW_REF].getNodeHandle(), - logError, - this._setScrollVisibleHeight - ); - }, - - _setScrollContentHeight: function(left, top, width, height) { - this.scrollProperties.contentHeight = height; - }, - - _setScrollVisibleHeight: function(left, top, width, height) { - this.scrollProperties.visibleHeight = height; - this._updateVisibleRows(); - }, - - _renderMoreRowsIfNeeded: function() { - if (this.scrollProperties.contentHeight === null || - this.scrollProperties.visibleHeight === null || - this.state.curRenderedRowsCount === this.props.dataSource.getRowCount()) { - return; - } - - var distanceFromEnd = this._getDistanceFromEnd(this.scrollProperties); - if (distanceFromEnd < this.props.scrollRenderAheadDistance) { - this._pageInNewRows(); - } - }, - - _pageInNewRows: function() { - var rowsToRender = Math.min( - this.state.curRenderedRowsCount + this.props.pageSize, - this.props.dataSource.getRowCount() - ); - this.setState( - { - prevRenderedRowsCount: this.state.curRenderedRowsCount, - curRenderedRowsCount: rowsToRender - }, - () => { - this._measureAndUpdateScrollProps(); - this.setState({ - prevRenderedRowsCount: this.state.curRenderedRowsCount, - }); - } - ); - }, - - _getDistanceFromEnd: function(scrollProperties) { - return scrollProperties.contentHeight - - scrollProperties.visibleHeight - - scrollProperties.offsetY; - }, - - _updateVisibleRows: function(e) { - if (!this.props.onChangeVisibleRows) { - return; // No need to compute visible rows if there is no callback - } - var updatedFrames = e && e.nativeEvent.updatedChildFrames; - if (updatedFrames) { - updatedFrames.forEach((frame) => { - this._childFrames[frame.index] = merge(frame); - }); - } - var dataSource = this.props.dataSource; - var visibleTop = this.scrollProperties.offsetY; - var visibleBottom = visibleTop + this.scrollProperties.visibleHeight; - var allRowIDs = dataSource.rowIdentities; - - var header = this.props.renderHeader && this.props.renderHeader(); - var totalIndex = header ? 1 : 0; - var visibilityChanged = false; - var changedRows = {}; - for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) { - var rowIDs = allRowIDs[sectionIdx]; - if (rowIDs.length === 0) { - continue; - } - var sectionID = dataSource.sectionIdentities[sectionIdx]; - if (this.props.renderSectionHeader) { - totalIndex++; - } - var visibleSection = this._visibleRows[sectionID]; - if (!visibleSection) { - visibleSection = {}; - } - for (var rowIdx = 0; rowIdx < rowIDs.length; rowIdx++) { - var rowID = rowIDs[rowIdx]; - var frame = this._childFrames[totalIndex]; - totalIndex++; - if (!frame) { - break; - } - var rowVisible = visibleSection[rowID]; - var top = frame.y; - var bottom = top + frame.height; - if (top > visibleBottom || bottom < visibleTop) { - if (rowVisible) { - visibilityChanged = true; - delete visibleSection[rowID]; - if (!changedRows[sectionID]) { - changedRows[sectionID] = {}; - } - changedRows[sectionID][rowID] = false; - } - } else if (!rowVisible) { - visibilityChanged = true; - visibleSection[rowID] = true; - if (!changedRows[sectionID]) { - changedRows[sectionID] = {}; - } - changedRows[sectionID][rowID] = true; - } - } - if (!isEmpty(visibleSection)) { - this._visibleRows[sectionID] = visibleSection; - } else if (this._visibleRows[sectionID]) { - delete this._visibleRows[sectionID]; - } - } - visibilityChanged && this.props.onChangeVisibleRows(this._visibleRows, changedRows); - }, - - _onScroll: function(e) { - this.scrollProperties.visibleHeight = e.nativeEvent.layoutMeasurement.height; - this.scrollProperties.contentHeight = e.nativeEvent.contentSize.height; - this.scrollProperties.offsetY = e.nativeEvent.contentOffset.y; - this._updateVisibleRows(e); - var nearEnd = this._getDistanceFromEnd(this.scrollProperties) < this.props.onEndReachedThreshold; - if (nearEnd && - this.props.onEndReached && - this.scrollProperties.contentHeight !== this._sentEndForContentHeight && - this.state.curRenderedRowsCount === this.props.dataSource.getRowCount()) { - this._sentEndForContentHeight = this.scrollProperties.contentHeight; - this.props.onEndReached(e); - } else { - this._renderMoreRowsIfNeeded(); - } - - this.props.onScroll && this.props.onScroll(e); - }, -}); - -module.exports = ListView; diff --git a/Libraries/Components/ListView/ListViewDataSource.js b/Libraries/Components/ListView/ListViewDataSource.js deleted file mode 100644 index 3be10944321..00000000000 --- a/Libraries/Components/ListView/ListViewDataSource.js +++ /dev/null @@ -1,379 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ListViewDataSource - * @typechecks - * @flow - */ -'use strict'; - -var invariant = require('invariant'); -var isEmpty = require('isEmpty'); -var warning = require('warning'); - -/** - * ListViewDataSource - Provides efficient data processing and access to the - * ListView component. A ListViewDataSource is created with functions for - * extracting data from the input blob, and comparing elements (with default - * implementations for convenience). The input blob can be as simple as an - * array of strings, or an object with rows nested inside section objects. - * - * To update the data in the datasource, use `cloneWithRows` (or - * `cloneWithRowsAndSections` if you care about sections). The data in the - * data source is immutable, so you can't modify it directly. The clone methods - * suck in the new data and compute a diff for each row so ListView knows - * whether to re-render it or not. - * - * In this example, a component receives data in chunks, handled by - * `_onDataArrived`, which concats the new data onto the old data and updates the - * data source. We use `concat` to create a new array - mutating `this._data`, - * e.g. with `this._data.push(newRowData)`, would be an error. `_rowHasChanged` - * understands the shape of the row data and knows how to efficiently compare - * it. - * - * getInitialState: function() { - * var ds = new ListViewDataSource({rowHasChanged: this._rowHasChanged}); - * return {ds}; - * }, - * _onDataArrived(newData) { - * this._data = this._data.concat(newData); - * this.setState({ - * ds: this.state.ds.cloneWithRows(this._data) - * }); - * } - */ - -function defaultGetRowData( - dataBlob: any, - sectionID: number | string, - rowID: number | string -): any { - return dataBlob[sectionID][rowID]; -} - -function defaultGetSectionHeaderData( - dataBlob: any, - sectionID: number | string -): any { - return dataBlob[sectionID]; -} - -type differType = (data1: any, data2: any) => bool; - -type ParamType = { - rowHasChanged: differType; - getRowData: ?typeof defaultGetRowData; - sectionHeaderHasChanged: ?differType; - getSectionHeaderData: ?typeof defaultGetSectionHeaderData; -} - -class ListViewDataSource { - - /** - * @param {ParamType} params - * - * You can provide custom extraction and 'hasChanged' functions for section - * headers and rows. If absent, data will be extracted with the - * `defaultGetRowData` and `defaultGetSectionHeaderData` functions. - * - * - getRowData(dataBlob, sectionID, rowID); - * - getSectionHeaderData(dataBlob, sectionID); - * - rowHasChanged(prevRowData, nextRowData); - * - sectionHeaderHasChanged(prevSectionData, nextSectionData); - */ - constructor(params: ParamType) { - invariant( - params && typeof params.rowHasChanged === 'function', - 'Must provide a rowHasChanged function.' - ); - this._rowHasChanged = params.rowHasChanged; - this._getRowData = params.getRowData || defaultGetRowData; - this._sectionHeaderHasChanged = params.sectionHeaderHasChanged; - this._getSectionHeaderData = - params.getSectionHeaderData || defaultGetSectionHeaderData; - - this._dataBlob = null; - this._dirtyRows = []; - this._dirtySections = []; - this._cachedRowCount = 0; - - // These two private variables are accessed by outsiders because ListView - // uses them to iterate over the data in this class. - this.rowIdentities = []; - this.sectionIdentities = []; - } - - /** - * @param {object} dataBlob -- This is an arbitrary blob of data. An extractor - * function was defined at construction time. The default extractor assumes - * the data is a plain array or keyed object. - */ - cloneWithRows( - dataBlob: Array | {[key: string]: any}, - rowIdentities: ?Array - ): ListViewDataSource { - var rowIds = rowIdentities ? [rowIdentities] : null; - if (!this._sectionHeaderHasChanged) { - this._sectionHeaderHasChanged = () => false; - } - return this.cloneWithRowsAndSections({s1: dataBlob}, ['s1'], rowIds); - } - - /** - * @param {object} dataBlob -- This is an arbitrary blob of data. An extractor - * function was defined at construction time. The default extractor assumes - * the data is a nested array or keyed object of the form: - * - * { sectionID_1: { rowID_1: , ... }, ... } - * - * or - * - * [ [ , , ... ], ... ] - * - * @param {array} sectionIdentities -- This is an array of identifiers for - * sections. ie. ['s1', 's2', ...]. If not provided, it's assumed that the - * keys of dataBlob are the section identities. - * @param {array} rowIdentities -- This is a 2D array of identifiers for rows. - * ie. [['a1', 'a2'], ['b1', 'b2', 'b3'], ...]. If not provided, it's - * assumed that the keys of the section data are the row identities. - * - * Note: this returns a new object! - */ - cloneWithRowsAndSections( - dataBlob: any, - sectionIdentities: ?Array, - rowIdentities: ?Array> - ): ListViewDataSource { - invariant( - typeof this._sectionHeaderHasChanged === 'function', - 'Must provide a sectionHeaderHasChanged function with section data.' - ); - var newSource = new ListViewDataSource({ - getRowData: this._getRowData, - getSectionHeaderData: this._getSectionHeaderData, - rowHasChanged: this._rowHasChanged, - sectionHeaderHasChanged: this._sectionHeaderHasChanged, - }); - newSource._dataBlob = dataBlob; - if (sectionIdentities) { - newSource.sectionIdentities = sectionIdentities; - } else { - newSource.sectionIdentities = Object.keys(dataBlob); - } - if (rowIdentities) { - newSource.rowIdentities = rowIdentities; - } else { - newSource.rowIdentities = []; - newSource.sectionIdentities.forEach((sectionID) => { - newSource.rowIdentities.push(Object.keys(dataBlob[sectionID])); - }); - } - newSource._cachedRowCount = countRows(newSource.rowIdentities); - - newSource._calculateDirtyArrays( - this._dataBlob, - this.sectionIdentities, - this.rowIdentities - ); - - return newSource; - } - - getRowCount(): number { - return this._cachedRowCount; - } - - /** - * @param {number} sectionIndex - * @param {number} rowIndex - * - * Returns if the row is dirtied and needs to be rerendered - */ - rowShouldUpdate(sectionIndex: number, rowIndex: number): bool { - var needsUpdate = this._dirtyRows[sectionIndex][rowIndex]; - warning(needsUpdate !== undefined, - 'missing dirtyBit for section, row: ' + sectionIndex + ', ' + rowIndex); - return needsUpdate; - } - - /** - * @param {number} sectionIndex - * @param {number} rowIndex - * - * Gets the data required to render the row. - */ - getRowData(sectionIndex: number, rowIndex: number): any { - var sectionID = this.sectionIdentities[sectionIndex]; - var rowID = this.rowIdentities[sectionIndex][rowIndex]; - warning( - sectionID !== undefined && rowID !== undefined, - 'rendering invalid section, row: ' + sectionIndex + ', ' + rowIndex - ); - return this._getRowData(this._dataBlob, sectionID, rowID); - } - - /** - * @param {number} index - * - * Gets the rowID at index provided if the dataSource arrays were flattened - */ - getRowIDForFlatIndex(index: number): string { - var accessIndex = index; - for (var ii = 0; ii < this.sectionIdentities.length; ii++) { - if (accessIndex >= this.rowIdentities[ii].length) { - accessIndex -= this.rowIdentities[ii].length; - } else { - return this.rowIdentities[ii][accessIndex]; - } - } - } - - /** - * @param {number} index - * - * Gets the sectionID at index provided if the dataSource arrays were flattened - */ - getSectionIDForFlatIndex(index: number): string { - var accessIndex = index; - for (var ii = 0; ii < this.sectionIdentities.length; ii++) { - if (accessIndex >= this.rowIdentities[ii].length) { - accessIndex -= this.rowIdentities[ii].length; - } else { - return this.sectionIdentities[ii]; - } - } - } - - /** - * Returns an array containing the number of rows in each section - */ - getSectionLengths(): Array { - var results = []; - for (var ii = 0; ii < this.sectionIdentities.length; ii++) { - results.push(this.rowIdentities[ii].length); - } - return results; - } - - /** - * @param {number} sectionIndex - * - * Returns if the section header is dirtied and needs to be rerendered - */ - sectionHeaderShouldUpdate(sectionIndex: number): bool { - var needsUpdate = this._dirtySections[sectionIndex]; - warning(needsUpdate !== undefined, - 'missing dirtyBit for section: ' + sectionIndex); - return needsUpdate; - } - - /** - * @param {number} sectionIndex - * - * Gets the data required to render the section header - */ - getSectionHeaderData(sectionIndex: number): any { - if (!this._getSectionHeaderData) { - return null; - } - var sectionID = this.sectionIdentities[sectionIndex]; - warning(sectionID !== undefined, - 'renderSection called on invalid section: ' + sectionIndex); - return this._getSectionHeaderData(this._dataBlob, sectionID); - } - - /** - * Private members and methods. - */ - - _getRowData: typeof defaultGetRowData; - _getSectionHeaderData: typeof defaultGetSectionHeaderData; - _rowHasChanged: differType; - _sectionHeaderHasChanged: ?differType; - - _dataBlob: any; - _dirtyRows: Array>; - _dirtySections: Array; - _cachedRowCount: number; - - // These two 'protected' variables are accessed by ListView to iterate over - // the data in this class. - rowIdentities: Array>; - sectionIdentities: Array; - - _calculateDirtyArrays( - prevDataBlob: any, - prevSectionIDs: Array, - prevRowIDs: Array> - ): void { - // construct a hashmap of the existing (old) id arrays - var prevSectionsHash = keyedDictionaryFromArray(prevSectionIDs); - var prevRowsHash = {}; - for (var ii = 0; ii < prevRowIDs.length; ii++) { - var sectionID = prevSectionIDs[ii]; - warning( - !prevRowsHash[sectionID], - 'SectionID appears more than once: ' + sectionID - ); - prevRowsHash[sectionID] = keyedDictionaryFromArray(prevRowIDs[ii]); - } - - // compare the 2 identity array and get the dirtied rows - this._dirtySections = []; - this._dirtyRows = []; - - var dirty; - for (var sIndex = 0; sIndex < this.sectionIdentities.length; sIndex++) { - var sectionID = this.sectionIdentities[sIndex]; - // dirty if the sectionHeader is new or _sectionHasChanged is true - dirty = !prevSectionsHash[sectionID]; - var sectionHeaderHasChanged = this._sectionHeaderHasChanged; - if (!dirty && sectionHeaderHasChanged) { - dirty = sectionHeaderHasChanged( - this._getSectionHeaderData(prevDataBlob, sectionID), - this._getSectionHeaderData(this._dataBlob, sectionID) - ); - } - this._dirtySections.push(!!dirty); - - this._dirtyRows[sIndex] = []; - for (var rIndex = 0; rIndex < this.rowIdentities[sIndex].length; rIndex++) { - var rowID = this.rowIdentities[sIndex][rIndex]; - // dirty if the section is new, row is new or _rowHasChanged is true - dirty = - !prevSectionsHash[sectionID] || - !prevRowsHash[sectionID][rowID] || - this._rowHasChanged( - this._getRowData(prevDataBlob, sectionID, rowID), - this._getRowData(this._dataBlob, sectionID, rowID) - ); - this._dirtyRows[sIndex].push(!!dirty); - } - } - } -} - -function countRows(allRowIDs) { - var totalRows = 0; - for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) { - var rowIDs = allRowIDs[sectionIdx]; - totalRows += rowIDs.length; - } - return totalRows; -} - -function keyedDictionaryFromArray(arr) { - if (isEmpty(arr)) { - return {}; - } - var result = {}; - for (var ii = 0; ii < arr.length; ii++) { - var key = arr[ii]; - warning(!result[key], 'Value appears more than once in array: ' + key); - result[key] = true; - } - return result; -} - - -module.exports = ListViewDataSource; diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js deleted file mode 100644 index ded8ce8d966..00000000000 --- a/Libraries/Components/Navigation/NavigatorIOS.ios.js +++ /dev/null @@ -1,566 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule NavigatorIOS - */ -'use strict'; - -var EventEmitter = require('EventEmitter'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var { RKNavigatorManager } = require('NativeModules'); -var StyleSheet = require('StyleSheet'); -var StaticContainer = require('StaticContainer.react'); -var View = require('View'); - -var createReactIOSNativeComponentClass = - require('createReactIOSNativeComponentClass'); -var invariant = require('invariant'); -var logError = require('logError'); -var merge = require('merge'); - -var TRANSITIONER_REF = 'transitionerRef'; - -var PropTypes = React.PropTypes; - -var __uid = 0; -function getuid() { - return __uid++; -} - -var RKNavigator = createReactIOSNativeComponentClass({ - validAttributes: merge(ReactIOSViewAttributes.UIView, { - requestedTopOfStack: true - }), - uiViewClassName: 'RCTNavigator', -}); - -var RKNavigatorItem = createReactIOSNativeComponentClass({ - validAttributes: { - // TODO: Remove or fix the attributes that are not fully functional. - // NavigatorIOS does not use them all, because some are problematic - title: true, - barTintColor: true, - rightButtonTitle: true, - onNavRightButtonTap: true, - tintColor: true, - backButtonTitle: true, - titleTextColor: true, - style: true, - }, - uiViewClassName: 'RCTNavItem', -}); - -var NavigatorTransitionerIOS = React.createClass({ - requestSchedulingNavigation: function(cb) { - RKNavigatorManager.requestSchedulingJavaScriptNavigation( - this.getNodeHandle(), - logError, - cb - ); - }, - - render: function() { - return ( - - ); - }, -}); - - -/** - * Think of `` as simply a component that renders an - * `RKNavigator`, and moves the `RKNavigator`'s `requestedTopOfStack` pointer - * forward and backward. The `RKNavigator` interprets changes in - * `requestedTopOfStack` to be pushes and pops of children that are rendered. - * `` always ensures that whenever the `requestedTopOfStack` - * pointer is moved, that we've also rendered enough children so that the - * `RKNavigator` can carry out the push/pop with those children. - * `` also removes children that will no longer be needed - * (after the pop of a child has been fully completed/animated out). - */ - -/** - * NavigatorIOS wraps UIKit navigation and allows you to add back-swipe - * functionality across your app. - * - * #### Routes - * A route is an object used to describe each page in the navigator. The first - * route is provided to NavigatorIOS as `initialRoute`: - * - * ``` - * render: function() { - * return ( - * - * ); - * }, - * ``` - * - * Now MyView will be rendered by the navigator. It will recieve the route - * object in the `route` prop, a navigator, and all of the props specified in - * `passProps`. - * - * See the initialRoute propType for a complete definition of a route. - * - * #### Navigator - * - * A `navigator` is an object of navigation functions that a view can call. It - * is passed as a prop to any component rendered by NavigatorIOS. - * - * ``` - * var MyView = React.createClass({ - * _handleBackButtonPress: function() { - * this.props.navigator.pop(); - * }, - * _handleNextButtonPress: function() { - * this.props.navigator.push(nextRoute); - * }, - * ... - * }); - * ``` - * - * A navigation object contains the following functions: - * - * - `push(route)` - Navigate forward to a new route - * - `pop()` - Go back one page - * - `popN(n)` - Go back N pages at once. When N=1, behavior matches `pop()` - * - `replace(route)` - Replace the route for the current page and immediately - * load the view for the new route - * - `replacePrevious(route)` - Replace the route/view for the previous page - * - `replacePreviousAndPop(route)` - Replaces the previous route/view and - * transitions back to it - * - `resetTo(route)` - Replaces the top item and popToTop - * - `popToRoute(route)` - Go back to the item for a particular route object - * - `popToTop()` - Go back to the top item - * - * Navigator functions are also available on the NavigatorIOS component: - * - * ``` - * var MyView = React.createClass({ - * _handleNavigationRequest: function() { - * this.refs.nav.push(otherRoute); - * }, - * render: () => ( - * - * ), - * }); - * ``` - * - */ -var NavigatorIOS = React.createClass({ - - propTypes: { - - /** - * NavigatorIOS uses "route" objects to identify child views, their props, - * and navigation bar configuration. "push" and all the other navigation - * operations expect routes to be like this: - */ - initialRoute: PropTypes.shape({ - /** - * The React Class to render for this route - */ - component: PropTypes.func.isRequired, - - /** - * The title displayed in the nav bar and back button for this route - */ - title: PropTypes.string.isRequired, - - /** - * Specify additional props passed to the component. NavigatorIOS will - * automatically provide "route" and "navigator" components - */ - passProps: PropTypes.object, - - /** - * If set, the left header button will appear with this name. Note that - * this doesn't apply for the header of the current view, but the ones - * of the views that are pushed afterward. - */ - backButtonTitle: PropTypes.string, - - /** - * If set, the right header button will appear with this name - */ - rightButtonTitle: PropTypes.string, - - /** - * Called when the right header button is pressed - */ - onRightButtonPress: PropTypes.func, - - /** - * Styles for the navigation item containing the component - */ - wrapperStyle: View.propTypes.style, - - }).isRequired, - - /** - * The default wrapper style for components in the navigator. - * A common use case is to set the backgroundColor for every page - */ - itemWrapperStyle: View.propTypes.style, - - /** - * The color used for buttons in the navigation bar - */ - tintColor: PropTypes.string, - - }, - - componentWillMount: function() { - // Precompute a pack of callbacks that's frequently generated and passed to - // instances. - this.navigator = { - push: this.push, - pop: this.pop, - popN: this.popN, - replace: this.replace, - replacePrevious: this.replacePrevious, - replacePreviousAndPop: this.replacePreviousAndPop, - resetTo: this.resetTo, - popToRoute: this.popToRoute, - popToTop: this.popToTop, - }; - }, - - getInitialState: function() { - return { - idStack: [getuid()], - routeStack: [this.props.initialRoute], - // The navigation index that we wish to push/pop to. - requestedTopOfStack: 0, - // The last index that native has sent confirmation of completed push/pop - // for. At this point, we can discard any views that are beyond the - // `requestedTopOfStack`. A value of `null` means we have not received - // any confirmation, ever. We may receive an `observedTopOfStack` without - // ever requesting it - native can instigate pops of its own with the - // backswipe gesture. - observedTopOfStack: 0, - progress: 1, - fromIndex: 0, - toIndex: 0, - // Whether or not we are making a navigator request to push/pop. (Used - // for performance optimization). - makingNavigatorRequest: false, - // Whether or not we are updating children of navigator and if so (not - // `null`) which index marks the beginning of all updates. Used for - // performance optimization. - updatingAllIndicesAtOrBeyond: 0, - }; - }, - - _handleFocusRequest: function(item) { - if (this.state.makingNavigatorRequest) { - this._toFocusOnNavigationComplete = item; - } else { - this._getFocusEmitter().emit('focus', item); - } - }, - - _getFocusEmitter: function() { - if (!this._focusEmitter) { - this._focusEmitter = new EventEmitter(); - } - return this._focusEmitter; - }, - - getChildContext: function() { - return { - onFocusRequested: this._handleFocusRequest, - focusEmitter: this._getFocusEmitter(), - }; - }, - - childContextTypes: { - onFocusRequested: React.PropTypes.func, - focusEmitter: React.PropTypes.instanceOf(EventEmitter), - }, - - _tryLockNavigator: function(cb) { - this.refs[TRANSITIONER_REF].requestSchedulingNavigation( - (acquiredLock) => acquiredLock && cb() - ); - }, - - _handleNavigatorStackChanged: function(e) { - var newObservedTopOfStack = e.nativeEvent.stackLength - 1; - invariant( - newObservedTopOfStack <= this.state.requestedTopOfStack, - 'No navigator item should be pushed without JS knowing about it %s %s', newObservedTopOfStack, this.state.requestedTopOfStack - ); - var wasWaitingForConfirmation = - this.state.requestedTopOfStack !== this.state.observedTopOfStack; - if (wasWaitingForConfirmation) { - invariant( - newObservedTopOfStack === this.state.requestedTopOfStack, - 'If waiting for observedTopOfStack to reach requestedTopOfStack, ' + - 'the only valid observedTopOfStack should be requestedTopOfStack.' - ); - } - // Mark the most recent observation regardless of if we can lock the - // navigator. `observedTopOfStack` merely represents what we've observed - // and this first `setState` is only executed to update debugging - // overlays/navigation bar. - // Also reset progress, toIndex, and fromIndex as they might not end - // in the correct states for a two possible reasons: - // Progress isn't always 0 or 1 at the end, the system rounds - // If the Navigator is offscreen these values won't be updated - // TOOD: Revisit this decision when no longer relying on native navigator. - var nextState = { - observedTopOfStack: newObservedTopOfStack, - makingNavigatorRequest: false, - updatingAllIndicesAtOrBeyond: null, - progress: 1, - toIndex: newObservedTopOfStack, - fromIndex: newObservedTopOfStack, - }; - this.setState(nextState, this._eliminateUnneededChildren); - }, - - _eliminateUnneededChildren: function() { - // Updating the indices that we're deleting and that's all. (Truth: Nothing - // even uses the indices in this case, but let's make this describe the - // truth anyways). - var updatingAllIndicesAtOrBeyond = - this.state.routeStack.length > this.state.observedTopOfStack + 1 ? - this.state.observedTopOfStack + 1 : - null; - this.setState({ - idStack: this.state.idStack.slice(0, this.state.observedTopOfStack + 1), - routeStack: this.state.routeStack.slice(0, this.state.observedTopOfStack + 1), - // Now we rerequest the top of stack that we observed. - requestedTopOfStack: this.state.observedTopOfStack, - makingNavigatorRequest: true, - updatingAllIndicesAtOrBeyond: updatingAllIndicesAtOrBeyond, - }); - }, - - push: function(route) { - invariant(!!route, 'Must supply route to push'); - // Make sure all previous requests are caught up first. Otherwise reject. - if (this.state.requestedTopOfStack === this.state.observedTopOfStack) { - this._tryLockNavigator(() => { - var nextStack = this.state.routeStack.concat([route]); - var nextIDStack = this.state.idStack.concat([getuid()]); - this.setState({ - // We have to make sure that we've also supplied enough views to - // satisfy our request to adjust the `requestedTopOfStack`. - idStack: nextIDStack, - routeStack: nextStack, - requestedTopOfStack: nextStack.length - 1, - makingNavigatorRequest: true, - updatingAllIndicesAtOrBeyond: nextStack.length - 1, - }); - }); - } - }, - - popN: function(n) { - if (n === 0) { - return; - } - // Make sure all previous requests are caught up first. Otherwise reject. - if (this.state.requestedTopOfStack === this.state.observedTopOfStack) { - if (this.state.requestedTopOfStack > 0) { - this._tryLockNavigator(() => { - invariant( - this.state.requestedTopOfStack - n >= 0, - 'Cannot pop below 0' - ); - this.setState({ - requestedTopOfStack: this.state.requestedTopOfStack - n, - makingNavigatorRequest: true, - // Not actually updating the indices yet until we get the native - // `onNavigationComplete`. - updatingAllIndicesAtOrBeyond: null, - }); - }); - } - } - }, - - pop: function() { - this.popN(1); - }, - - /** - * Replace a route in the navigation stack. - * - * `index` specifies the route in the stack that should be replaced. - * If it's negative, it counts from the back. - */ - replaceAtIndex: function(route, index) { - invariant(!!route, 'Must supply route to replace'); - if (index < 0) { - index += this.state.routeStack.length; - } - - if (this.state.routeStack.length <= index) { - return; - } - - // I don't believe we need to lock for a replace since there's no - // navigation actually happening - var nextIDStack = this.state.idStack.slice(); - var nextRouteStack = this.state.routeStack.slice(); - nextIDStack[index] = getuid(); - nextRouteStack[index] = route; - - this.setState({ - idStack: nextIDStack, - routeStack: nextRouteStack, - makingNavigatorRequest: false, - updatingAllIndicesAtOrBeyond: index, - }); - }, - - /** - * Replaces the top of the navigation stack. - */ - replace: function(route) { - this.replaceAtIndex(route, -1); - }, - - /** - * Replace the current route's parent. - */ - replacePrevious: function(route) { - this.replaceAtIndex(route, -2); - }, - - popToTop: function() { - this.popToRoute(this.state.routeStack[0]); - }, - - popToRoute: function(route) { - var indexOfRoute = this.state.routeStack.indexOf(route); - invariant( - indexOfRoute !== -1, - 'Calling pop to route for a route that doesn\'t exist!' - ); - var numToPop = this.state.routeStack.length - indexOfRoute - 1; - this.popN(numToPop); - }, - - replacePreviousAndPop: function(route) { - // Make sure all previous requests are caught up first. Otherwise reject. - if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) { - return; - } - if (this.state.routeStack.length < 2) { - return; - } - this._tryLockNavigator(() => { - this.replacePrevious(route); - this.setState({ - requestedTopOfStack: this.state.requestedTopOfStack - 1, - makingNavigatorRequest: true, - }); - }); - }, - - resetTo: function(route) { - invariant(!!route, 'Must supply route to push'); - // Make sure all previous requests are caught up first. Otherwise reject. - if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) { - return; - } - this.replaceAtIndex(route, 0); - this.popToRoute(route); - }, - - handleNavigationComplete: function(e) { - if (this._toFocusOnNavigationComplete) { - this._getFocusEmitter().emit('focus', this._toFocusOnNavigationComplete); - this._toFocusOnNavigationComplete = null; - } - this._handleNavigatorStackChanged(e); - }, - - _routeToStackItem: function(route, i) { - var Component = route.component; - var shouldUpdateChild = this.state.updatingAllIndicesAtOrBeyond !== null && - this.state.updatingAllIndicesAtOrBeyond >= i; - - return ( - - - - - - ); - }, - - renderNavigationStackItems: function() { - var shouldRecurseToNavigator = - this.state.makingNavigatorRequest || - this.state.updatingAllIndicesAtOrBeyond !== null; - // If not recursing update to navigator at all, may as well avoid - // computation of navigator children. - var items = shouldRecurseToNavigator ? - this.state.routeStack.map(this._routeToStackItem) : null; - return ( - - - {items} - - - ); - }, - - render: function() { - return ( - - {this.renderNavigationStackItems()} - - ); - } -}); - -var styles = StyleSheet.create({ - stackItem: { - backgroundColor: 'white', - overflow: 'hidden', - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - }, - transitioner: { - flex: 1, - }, -}); - -module.exports = NavigatorIOS; diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js deleted file mode 100644 index 4221722bd4b..00000000000 --- a/Libraries/Components/ScrollResponder.js +++ /dev/null @@ -1,458 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ScrollResponder - */ -'use strict'; - -var NativeModules = require('NativeModules'); -var NativeModulesDeprecated = require('NativeModulesDeprecated'); -var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); -var Subscribable = require('Subscribable'); -var TextInputState = require('TextInputState'); - -var RKUIManager = NativeModules.RKUIManager; -var RKUIManagerDeprecated = NativeModulesDeprecated.RKUIManager; -var RKScrollViewConsts = RKUIManager.RCTScrollView.Constants; - -var warning = require('warning'); - -/** - * Mixin that can be integrated in order to handle scrolling that plays well - * with `ResponderEventPlugin`. Integrate with your platform specific scroll - * views, or even your custom built (every-frame animating) scroll views so that - * all of these systems play well with the `ResponderEventPlugin`. - * - * iOS scroll event timing nuances: - * =============================== - * - * - * Scrolling without bouncing, if you touch down: - * ------------------------------- - * - * 1. `onMomentumScrollBegin` (when animation begins after letting up) - * ... physical touch starts ... - * 2. `onTouchStartCapture` (when you press down to stop the scroll) - * 3. `onTouchStart` (same, but bubble phase) - * 4. `onResponderRelease` (when lifting up - you could pause forever before * lifting) - * 5. `onMomentumScrollEnd` - * - * - * Scrolling with bouncing, if you touch down: - * ------------------------------- - * - * 1. `onMomentumScrollBegin` (when animation begins after letting up) - * ... bounce begins ... - * ... some time elapses ... - * ... physical touch during bounce ... - * 2. `onMomentumScrollEnd` (Makes no sense why this occurs first during bounce) - * 3. `onTouchStartCapture` (immediately after `onMomentumScrollEnd`) - * 4. `onTouchStart` (same, but bubble phase) - * 5. `onTouchEnd` (You could hold the touch start for a long time) - * 6. `onMomentumScrollBegin` (When releasing the view starts bouncing back) - * - * So when we receive an `onTouchStart`, how can we tell if we are touching - * *during* an animation (which then causes the animation to stop)? The only way - * to tell is if the `touchStart` occurred immediately after the - * `onMomentumScrollEnd`. - * - * This is abstracted out for you, so you can just call this.scrollResponderIsAnimating() if - * necessary - * - * `ScrollResponder` also includes logic for blurring a currently focused input - * if one is focused while scrolling. The `ScrollResponder` is a natural place - * to put this logic since it can support not dismissing the keyboard while - * scrolling, unless a recognized "tap"-like gesture has occurred. - * - * The public lifecycle API includes events for keyboard interaction, responder - * interaction, and scrolling (among others). The keyboard callbacks - * `onKeyboardWill/Did/*` are *global* events, but are invoked on scroll - * responder's props so that you can guarantee that the scroll responder's - * internal state has been updated accordingly (and deterministically) by - * the time the props callbacks are invoke. Otherwise, you would always wonder - * if the scroll responder is currently in a state where it recognizes new - * keyboard positions etc. If coordinating scrolling with keyboard movement, - * *always* use these hooks instead of listening to your own global keyboard - * events. - * - * Public keyboard lifecycle API: (props callbacks) - * - * Standard Keyboard Appearance Sequence: - * - * this.props.onKeyboardWillShow - * this.props.onKeyboardDidShow - * - * `onScrollResponderKeyboardDismissed` will be invoked if an appropriate - * tap inside the scroll responder's scrollable region was responsible - * for the dismissal of the keyboard. There are other reasons why the - * keyboard could be dismissed. - * - * this.props.onScrollResponderKeyboardDismissed - * - * Standard Keyboard Hide Sequence: - * - * this.props.onKeyboardWillHide - * this.props.onKeyboardDidHide - */ - -var IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16; - -var ScrollResponderMixin = { - mixins: [Subscribable.Mixin], - statics: RKScrollViewConsts, - scrollResponderMixinGetInitialState: function() { - return { - isTouching: false, - lastMomentumScrollBeginTime: 0, - lastMomentumScrollEndTime: 0, - - // Reset to false every time becomes responder. This is used to: - // - Determine if the scroll view has been scrolled and therefore should - // refuse to give up its responder lock. - // - Determine if releasing should dismiss the keyboard when we are in - // tap-to-dismiss mode (!this.props.keyboardShouldPersistTaps). - observedScrollSinceBecomingResponder: false, - becameResponderWhileAnimating: false, - }; - }, - - /** - * Invoke this from an `onScroll` event. - */ - scrollResponderHandleScrollShouldSetResponder: function() { - return this.state.isTouching; - }, - - /** - * Merely touch starting is not sufficient for a scroll view to become the - * responder. Being the "responder" means that the very next touch move/end - * event will result in an action/movement. - * - * Invoke this from an `onStartShouldSetResponder` event. - * - * `onStartShouldSetResponder` is used when the next move/end will trigger - * some UI movement/action, but when you want to yield priority to views - * nested inside of the view. - * - * There may be some cases where scroll views actually should return `true` - * from `onStartShouldSetResponder`: Any time we are detecting a standard tap - * that gives priority to nested views. - * - * - If a single tap on the scroll view triggers an action such as - * recentering a map style view yet wants to give priority to interaction - * views inside (such as dropped pins or labels), then we would return true - * from this method when there is a single touch. - * - * - Similar to the previous case, if a two finger "tap" should trigger a - * zoom, we would check the `touches` count, and if `>= 2`, we would return - * true. - * - */ - scrollResponderHandleStartShouldSetResponder: function() { - return false; - }, - - /** - * There are times when the scroll view wants to become the responder - * (meaning respond to the next immediate `touchStart/touchEnd`), in a way - * that *doesn't* give priority to nested views (hence the capture phase): - * - * - Currently animating. - * - Tapping anywhere that is not the focused input, while the keyboard is - * up (which should dismiss the keyboard). - * - * Invoke this from an `onStartShouldSetResponderCapture` event. - */ - scrollResponderHandleStartShouldSetResponderCapture: function(e) { - // First see if we want to eat taps while the keyboard is up - var currentlyFocusedTextInput = TextInputState.currentlyFocusedField(); - if (!this.props.keyboardShouldPersistTaps && - currentlyFocusedTextInput != null && - e.target != currentlyFocusedTextInput) { - return true; - } - return this.scrollResponderIsAnimating(); - }, - - /** - * Invoke this from an `onResponderReject` event. - * - * Some other element is not yielding its role as responder. Normally, we'd - * just disable the `UIScrollView`, but a touch has already began on it, the - * `UIScrollView` will not accept being disabled after that. The easiest - * solution for now is to accept the limitation of disallowing this - * altogether. To improve this, find a way to disable the `UIScrollView` after - * a touch has already started. - */ - scrollResponderHandleResponderReject: function() { - warning(false, "ScrollView doesn't take rejection well - scrolls anyway"); - }, - - /** - * We will allow the scroll view to give up its lock iff it acquired the lock - * during an animation. This is a very useful default that happens to satisfy - * many common user experiences. - * - * - Stop a scroll on the left edge, then turn that into an outer view's - * backswipe. - * - Stop a scroll mid-bounce at the top, continue pulling to have the outer - * view dismiss. - * - However, without catching the scroll view mid-bounce (while it is - * motionless), if you drag far enough for the scroll view to become - * responder (and therefore drag the scroll view a bit), any backswipe - * navigation of a swipe gesture higher in the view hierarchy, should be - * rejected. - */ - scrollResponderHandleTerminationRequest: function() { - return !this.state.observedScrollSinceBecomingResponder; - }, - - /** - * Invoke this from an `onTouchEnd` event. - * - * @param {SyntheticEvent} e Event. - */ - scrollResponderHandleTouchEnd: function(e) { - var nativeEvent = e.nativeEvent; - this.state.isTouching = nativeEvent.touches.length !== 0; - this.props.onTouchEnd && this.props.onTouchEnd(e); - }, - - /** - * Invoke this from an `onResponderRelease` event. - */ - scrollResponderHandleResponderRelease: function(e) { - this.props.onResponderRelease && this.props.onResponderRelease(e); - - // By default scroll views will unfocus a textField - // if another touch occurs outside of it - var currentlyFocusedTextInput = TextInputState.currentlyFocusedField(); - if (!this.props.keyboardShouldPersistTaps && - currentlyFocusedTextInput != null && - e.target != currentlyFocusedTextInput && - !this.state.observedScrollSinceBecomingResponder && - !this.state.becameResponderWhileAnimating) { - this.props.onScrollResponderKeyboardDismissed && - this.props.onScrollResponderKeyboardDismissed(e); - TextInputState.blurTextInput(currentlyFocusedTextInput); - } - }, - - scrollResponderHandleScroll: function(e) { - this.state.observedScrollSinceBecomingResponder = true; - this.props.onScroll && this.props.onScroll(e); - }, - - /** - * Invoke this from an `onResponderGrant` event. - */ - scrollResponderHandleResponderGrant: function(e) { - this.state.observedScrollSinceBecomingResponder = false; - this.props.onResponderGrant && this.props.onResponderGrant(e); - this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating(); - }, - - /** - * Unfortunately, `onScrollBeginDrag` also fires when *stopping* the scroll - * animation, and there's not an easy way to distinguish a drag vs. stopping - * momentum. - * - * Invoke this from an `onScrollBeginDrag` event. - */ - scrollResponderHandleScrollBeginDrag: function(e) { - this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); - }, - - /** - * Invoke this from an `onScrollEndDrag` event. - */ - scrollResponderHandleScrollEndDrag: function(e) { - this.props.onScrollEndDrag && this.props.onScrollEndDrag(e); - }, - - /** - * Invoke this from an `onMomentumScrollBegin` event. - */ - scrollResponderHandleMomentumScrollBegin: function(e) { - this.state.lastMomentumScrollBeginTime = Date.now(); - this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e); - }, - - /** - * Invoke this from an `onMomentumScrollEnd` event. - */ - scrollResponderHandleMomentumScrollEnd: function(e) { - this.state.lastMomentumScrollEndTime = Date.now(); - this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e); - }, - - /** - * Invoke this from an `onTouchStart` event. - * - * Since we know that the `SimpleEventPlugin` occurs later in the plugin - * order, after `ResponderEventPlugin`, we can detect that we were *not* - * permitted to be the responder (presumably because a contained view became - * responder). The `onResponderReject` won't fire in that case - it only - * fires when a *current* responder rejects our request. - * - * @param {SyntheticEvent} e Touch Start event. - */ - scrollResponderHandleTouchStart: function(e) { - this.state.isTouching = true; - this.props.onTouchStart && this.props.onTouchStart(e); - }, - - /** - * Invoke this from an `onTouchMove` event. - * - * Since we know that the `SimpleEventPlugin` occurs later in the plugin - * order, after `ResponderEventPlugin`, we can detect that we were *not* - * permitted to be the responder (presumably because a contained view became - * responder). The `onResponderReject` won't fire in that case - it only - * fires when a *current* responder rejects our request. - * - * @param {SyntheticEvent} e Touch Start event. - */ - scrollResponderHandleTouchMove: function(e) { - this.props.onTouchMove && this.props.onTouchMove(e); - }, - - /** - * A helper function for this class that lets us quickly determine if the - * view is currently animating. This is particularly useful to know when - * a touch has just started or ended. - */ - scrollResponderIsAnimating: function() { - var now = Date.now(); - var timeSinceLastMomentumScrollEnd = now - this.state.lastMomentumScrollEndTime; - var isAnimating = timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS || - this.state.lastMomentumScrollEndTime < this.state.lastMomentumScrollBeginTime; - return isAnimating; - }, - - /** - * A helper function to scroll to a specific point in the scrollview. - * This is currently used to help focus on child textview's, but this - * can also be used to quickly scroll to any element we want to focus - */ - scrollResponderScrollTo: function(offsetX, offsetY) { - RKUIManagerDeprecated.scrollTo(this.getNodeHandle(), offsetX, offsetY); - }, - - /** - * A helper function to zoom to a specific rect in the scrollview. - * @param {object} rect Should have shape {x, y, w, h} - */ - scrollResponderZoomTo: function(rect) { - RKUIManagerDeprecated.zoomToRect(this.getNodeHandle(), rect); - }, - - /** - * This method should be used as the callback to onFocus in a TextInputs' - * parent view. Note that any module using this mixin needs to return - * the parent view's ref in getScrollViewRef() in order to use this method - */ - scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle, additionalOffset) { - this.additionalScrollOffset = additionalOffset || 0; - RKUIManager.measureLayout( - nodeHandle, - this.getNodeHandle(), - this.scrollResponderTextInputFocusError, - this.scrollResponderInputMeasureAndScrollToKeyboard - ); - }, - - /** - * The calculations performed here assume the scroll view takes up the entire - * screen - even if has some content inset. We then measure the offsets of the - * keyboard, and compensate both for the scroll view's "contentInset". - * - * @param {number} left Position of input w.r.t. table view. - * @param {number} top Position of input w.r.t. table view. - * @param {number} width Width of the text input. - * @param {number} height Height of the text input. - */ - scrollResponderInputMeasureAndScrollToKeyboard: function(left, top, width, height) { - if (this.keyboardWillOpenTo) { - var scrollOffsetY = - top - this.keyboardWillOpenTo.endCoordinates.screenY + height + - this.additionalScrollOffset; - this.scrollResponderScrollTo(0, scrollOffsetY); - } - this.additionalOffset = 0; - }, - - scrollResponderTextInputFocusError: function(e) { - console.error('Error measuring text field: ', e); - }, - - /** - * `componentWillMount` is the closest thing to a standard "constructor" for - * React components. - * - * The `keyboardWillShow` is called before input focus. - */ - componentWillMount: function() { - this.keyboardWillOpenTo = null; - this.additionalScrollOffset = 0; - this.addListenerOn(RCTDeviceEventEmitter, 'keyboardWillShow', this.scrollResponderKeyboardWillShow); - this.addListenerOn(RCTDeviceEventEmitter, 'keyboardWillHide', this.scrollResponderKeyboardWillHide); - this.addListenerOn(RCTDeviceEventEmitter, 'keyboardDidShow', this.scrollResponderKeyboardDidShow); - this.addListenerOn(RCTDeviceEventEmitter, 'keyboardDidHide', this.scrollResponderKeyboardDidHide); - }, - - /** - * Warning, this may be called several times for a single keyboard opening. - * It's best to store the information in this method and then take any action - * at a later point (either in `keyboardDidShow` or other). - * - * Here's the order that events occur in: - * - focus - * - willShow {startCoordinates, endCoordinates} several times - * - didShow several times - * - blur - * - willHide {startCoordinates, endCoordinates} several times - * - didHide several times - * - * The `ScrollResponder` providesModule callbacks for each of these events. - * Even though any user could have easily listened to keyboard events - * themselves, using these `props` callbacks ensures that ordering of events - * is consistent - and not dependent on the order that the keyboard events are - * subscribed to. This matters when telling the scroll view to scroll to where - * the keyboard is headed - the scroll responder better have been notified of - * the keyboard destination before being instructed to scroll to where the - * keyboard will be. Stick to the `ScrollResponder` callbacks, and everything - * will work. - * - * WARNING: These callbacks will fire even if a keyboard is displayed in a - * different navigation pane. Filter out the events to determine if they are - * relevant to you. (For example, only if you receive these callbacks after - * you had explicitly focused a node etc). - */ - scrollResponderKeyboardWillShow: function(e) { - this.keyboardWillOpenTo = e; - this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e); - }, - - scrollResponderKeyboardWillHide: function(e) { - this.keyboardWillOpenTo = null; - this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e); - }, - - scrollResponderKeyboardDidShow: function() { - this.keyboardWillOpenTo = null; - this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(); - }, - - scrollResponderKeyboardDidHide: function() { - this.keyboardWillOpenTo = null; - this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(); - } - -}; - -var ScrollResponder = { - Mixin: ScrollResponderMixin, -}; - -module.exports = ScrollResponder; diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js deleted file mode 100644 index 09f7b94d651..00000000000 --- a/Libraries/Components/ScrollView/ScrollView.js +++ /dev/null @@ -1,349 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ScrollView - */ -'use strict'; - -var EdgeInsetsPropType = require('EdgeInsetsPropType'); -var Platform = require('Platform'); -var PointPropType = require('PointPropType'); -var RCTScrollView = require('NativeModules').RKUIManager.RCTScrollView; -var RCTScrollViewConsts = RCTScrollView.Constants; -var React = require('React'); -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; -var ScrollResponder = require('ScrollResponder'); -var StyleSheet = require('StyleSheet'); -var StyleSheetPropType = require('StyleSheetPropType'); -var View = require('View'); -var ViewStylePropTypes = require('ViewStylePropTypes'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); -var deepDiffer = require('deepDiffer'); -var flattenStyle = require('flattenStyle'); -var insetsDiffer = require('insetsDiffer'); -var invariant = require('invariant'); -var pointsDiffer = require('pointsDiffer'); - -var PropTypes = React.PropTypes; - -var SCROLLVIEW = 'ScrollView'; -var INNERVIEW = 'InnerScrollView'; - -var keyboardDismissModeConstants = { - 'none': RCTScrollViewConsts.KeyboardDismissMode.None, // default - 'interactive': RCTScrollViewConsts.KeyboardDismissMode.Interactive, - 'onDrag': RCTScrollViewConsts.KeyboardDismissMode.OnDrag, -}; - -/** - * Component that wraps platform ScrollView while providing - * integration with touch locking "responder" system. - * - * Doesn't yet support other contained responders from blocking this scroll - * view from becoming the responder. - */ - -var ScrollView = React.createClass({ - - // Only for compatibility with Android which is not yet up to date, - // DO NOT ADD NEW CALL SITES! - statics: { - keyboardDismissMode: { - None: 'none', - Interactive: 'interactive', - OnDrag: 'onDrag', - }, - }, - - propTypes: { - automaticallyAdjustContentInsets: PropTypes.bool, // true - contentInset: EdgeInsetsPropType, // zeros - contentOffset: PointPropType, // zeros - onScroll: PropTypes.func, - onScrollAnimationEnd: PropTypes.func, - scrollEnabled: PropTypes.bool, // tre - scrollIndicatorInsets: EdgeInsetsPropType, // zeros - showsHorizontalScrollIndicator: PropTypes.bool, - showsVerticalScrollIndicator: PropTypes.bool, - style: StyleSheetPropType(ViewStylePropTypes), - throttleScrollCallbackMS: PropTypes.number, // null - - /** - * 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. - */ - alwaysBounceHorizontal: PropTypes.bool, - /** - * 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. - */ - alwaysBounceVertical: PropTypes.bool, - /** - * 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. - */ - centerContent: PropTypes.bool, - /** - * These styles will be applied to the scroll view content container which - * wraps all of the child views. Example: - * - * return ( - * - * - * ); - * ... - * var styles = StyleSheet.create({ - * contentContainer: { - * paddingVertical: 20 - * } - * }); - */ - contentContainerStyle: StyleSheetPropType(ViewStylePropTypes), - /** - * A floating-point number that determines how quickly the scroll view - * decelerates after the user lifts their finger. Reasonable choices include - * - Normal: 0.998 (the default) - * - Fast: 0.9 - */ - decelerationRate: PropTypes.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: PropTypes.bool, - /** - * Determines whether the keyboard gets dismissed in response to a drag. - * - 'none' (the default), drags do not dismiss the keyboard. - * - 'onDrag', the keyboard is dismissed when a drag begins. - * - 'interactive', the keyboard is dismissed interactively with the drag - * and moves in synchrony with the touch; dragging upwards cancels the - * dismissal. - */ - keyboardDismissMode: PropTypes.oneOf([ - 'none', // default - 'interactive', - 'onDrag', - ]), - /** - * When false, tapping outside of the focused text input when the keyboard - * is up dismisses the keyboard. When true, the scroll view will not catch - * taps, and the keyboard will not dismiss automatically. The default value - * is false. - */ - keyboardShouldPersistTaps: PropTypes.bool, - /** - * The maximum allowed zoom scale. The default value is 1.0. - */ - maximumZoomScale: PropTypes.number, - /** - * The minimum allowed zoom scale. The default value is 1.0. - */ - minimumZoomScale: PropTypes.number, - /** - * 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. - */ - pagingEnabled: PropTypes.bool, - /** - * When true, the scroll view scrolls to top when the status bar is tapped. - * The default value is true. - */ - scrollsToTop: PropTypes.bool, - /** - * 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: PropTypes.arrayOf(PropTypes.number), - /** - * Experimental: When true, offscreen child views (whose `overflow` value is - * `hidden`) are removed from their native backing superview when offscreen. - * This canimprove scrolling performance on long lists. The default value is - * false. - */ - removeClippedSubviews: PropTypes.bool, - /** - * The current scale of the scroll view content. The default value is 1.0. - */ - zoomScale: PropTypes.number, - }, - - mixins: [ScrollResponder.Mixin], - - getInitialState: function() { - return this.scrollResponderMixinGetInitialState(); - }, - - setNativeProps: function(props) { - this.refs[SCROLLVIEW].setNativeProps(props); - }, - - getInnerViewNode: function() { - return this.refs[INNERVIEW].getNodeHandle(); - }, - - scrollTo: function(destY, destX) { - RKUIManager.scrollTo( - ReactIOSTagHandles.rootNodeIDToTag[this._rootNodeID], - destX || 0, - destY || 0 - ); - }, - - render: function() { - var contentContainerStyle = [ - this.props.horizontal && styles.contentContainerHorizontal, - this.props.contentContainerStyle, - ]; - if (__DEV__ && this.props.style) { - var style = flattenStyle(this.props.style); - var childLayoutProps = ['alignItems', 'justifyContent'] - .filter((prop) => style[prop] !== undefined); - invariant( - childLayoutProps.length === 0, - 'ScrollView child layout (' + JSON.stringify(childLayoutProps) + - ') must by applied through the contentContainerStyle prop.' - ); - } - if (__DEV__) { - if (this.props.onScroll && !this.props.throttleScrollCallbackMS) { - var onScroll = this.props.onScroll; - this.props.onScroll = function() { - console.log( - 'You specified `onScroll` on a but not ' + - '`throttleScrollCallbackMS`. 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.' - ); - onScroll.apply(this, arguments); - }; - } - } - - var contentContainer = - - {this.props.children} - ; - - var alwaysBounceHorizontal = - this.props.alwaysBounceHorizontal !== undefined ? - this.props.alwaysBounceHorizontal : - this.props.horizontal; - - var alwaysBounceVertical = - this.props.alwaysBounceVertical !== undefined ? - this.props.alwaysBounceVertical : - !this.props.horizontal; - - var props = { - ...this.props, - alwaysBounceHorizontal, - alwaysBounceVertical, - keyboardDismissMode: this.props.keyboardDismissMode ? - keyboardDismissModeConstants[this.props.keyboardDismissMode] : - undefined, - style: [styles.base, this.props.style], - onTouchStart: this.scrollResponderHandleTouchStart, - onTouchMove: this.scrollResponderHandleTouchMove, - onTouchEnd: this.scrollResponderHandleTouchEnd, - onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag, - onScrollEndDrag: this.scrollResponderHandleScrollEndDrag, - onMomentumScrollBegin: this.scrollResponderHandleMomentumScrollBegin, - onMomentumScrollEnd: this.scrollResponderHandleMomentumScrollEnd, - onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder, - onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture, - onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder, - onScroll: this.scrollResponderHandleScroll, - onResponderGrant: this.scrollResponderHandleResponderGrant, - onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest, - onResponderTerminate: this.scrollResponderHandleTerminate, - onResponderRelease: this.scrollResponderHandleResponderRelease, - onResponderReject: this.scrollResponderHandleResponderReject, - }; - - var ScrollViewClass; - if (Platform.OS === 'ios') { - ScrollViewClass = RCTScrollView; - } else if (Platform.OS === 'android') { - if (this.props.horizontal) { - ScrollViewClass = AndroidHorizontalScrollView; - } else { - ScrollViewClass = AndroidScrollView; - } - } - - return ( - - {contentContainer} - - ); - } -}); - -var styles = StyleSheet.create({ - base: { - flex: 1, - }, - contentContainerHorizontal: { - alignSelf: 'flex-start', - flexDirection: 'row', - }, -}); - -var validAttributes = { - ...ReactIOSViewAttributes.UIView, - alwaysBounceHorizontal: true, - alwaysBounceVertical: true, - automaticallyAdjustContentInsets: true, - centerContent: true, - contentInset: insetsDiffer, - contentOffset: pointsDiffer, - decelerationRate: true, - horizontal: true, - keyboardDismissMode: true, - keyboardShouldPersistTaps: true, - maximumZoomScale: true, - minimumZoomScale: true, - pagingEnabled: true, - removeClippedSubviews: true, - scrollEnabled: true, - scrollIndicatorInsets: insetsDiffer, - scrollsToTop: true, - showsHorizontalScrollIndicator: true, - showsVerticalScrollIndicator: true, - stickyHeaderIndices: deepDiffer, - throttleScrollCallbackMS: true, - zoomScale: true, -}; - -if (Platform.OS === 'android') { - var AndroidScrollView = createReactIOSNativeComponentClass({ - validAttributes: validAttributes, - uiViewClassName: 'AndroidScrollView', - }); - var AndroidHorizontalScrollView = createReactIOSNativeComponentClass({ - validAttributes: validAttributes, - uiViewClassName: 'AndroidHorizontalScrollView', - }); -} else if (Platform.OS === 'ios') { - var RCTScrollView = createReactIOSNativeComponentClass({ - validAttributes: validAttributes, - uiViewClassName: 'RCTScrollView', - }); -} - -module.exports = ScrollView; diff --git a/Libraries/Components/Slider/Slider.js b/Libraries/Components/Slider/Slider.js deleted file mode 100644 index 80f631c456f..00000000000 --- a/Libraries/Components/Slider/Slider.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule Slider - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var PropTypes = require('ReactPropTypes'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); -var View = require('View'); - -var createReactIOSNativeComponentClass = - require('createReactIOSNativeComponentClass'); -var merge = require('merge'); - -var Slider = React.createClass({ - mixins: [NativeMethodsMixin], - - propTypes: { - /** - * Used to style and layout the `Slider`. See `StyleSheet.js` and - * `ViewStylePropTypes.js` for more info. - */ - style: View.propTypes.style, - - /** - * Initial value of the slider. The value should be between 0 and 1. - * Default value is 0. - * - * *This is not a controlled component*, e.g. if you don't update - * the value, the component won't be reseted to it's inital value. - */ - value: PropTypes.number, - - /** - * Callback continuously called while the user is dragging the slider. - */ - onValueChange: PropTypes.func, - - /** - * Callback called when the user finishes changing the value (e.g. when - * the slider is released). - */ - onSlidingComplete: PropTypes.func, - }, - - _onValueChange: function(event) { - this.props.onChange && this.props.onChange(event); - if (event.nativeEvent.continuous) { - this.props.onValueChange && - this.props.onValueChange(event.nativeEvent.value); - } else { - this.props.onSlidingComplete && event.nativeEvent.value !== undefined && - this.props.onSlidingComplete(event.nativeEvent.value); - } - }, - - render: function() { - return ( - - ); - } -}); - -var styles = StyleSheet.create({ - slider: { - height: 40, - }, -}); - -var RKSlider = createReactIOSNativeComponentClass({ - validAttributes: merge(ReactIOSViewAttributes.UIView, {value: true}), - uiViewClassName: 'RCTSlider', -}); - -module.exports = Slider; diff --git a/Libraries/Components/StaticRenderer.js b/Libraries/Components/StaticRenderer.js deleted file mode 100644 index b749895c2b1..00000000000 --- a/Libraries/Components/StaticRenderer.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @provides StaticRenderer - */ -'use strict'; - -var React = require('React'); - -var StaticRenderer = React.createClass({ - propTypes: { - shouldUpdate: React.PropTypes.bool.isRequired, - render: React.PropTypes.func.isRequired, - }, - - shouldComponentUpdate: function(nextProps) { - return nextProps.shouldUpdate; - }, - - render: function() { - return this.props.render(); - }, -}); - -module.exports = StaticRenderer; diff --git a/Libraries/Components/StatusBar/StatusBarIOS.ios.js b/Libraries/Components/StatusBar/StatusBarIOS.ios.js deleted file mode 100644 index eaea1cc7acc..00000000000 --- a/Libraries/Components/StatusBar/StatusBarIOS.ios.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule StatusBarIOS - * @flow - */ -'use strict'; - -var { RKStatusBarManager } = require('NativeModules'); - -var StatusBarIOS = { - - Style: { - default: RKStatusBarManager.Style.default, - lightContent: RKStatusBarManager.Style.lightContent - }, - - Animation: { - none: RKStatusBarManager.Animation.none, - fade: RKStatusBarManager.Animation.fade, - slide: RKStatusBarManager.Animation.slide, - }, - - setStyle(style: number, animated: boolean) { - animated = animated || false; - RKStatusBarManager.setStyle(style, animated); - }, - - setHidden(hidden: boolean, animation: number) { - animation = animation || StatusBarIOS.Animation.none; - RKStatusBarManager.setHidden(hidden, animation); - }, -}; - -module.exports = StatusBarIOS; diff --git a/Libraries/Components/Subscribable.js b/Libraries/Components/Subscribable.js deleted file mode 100644 index 8c4bbe82359..00000000000 --- a/Libraries/Components/Subscribable.js +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule Subscribable - */ -'use strict'; - -/** - * Subscribable wraps EventEmitter in a clean interface, and provides a mixin - * so components can easily subscribe to events and not worry about cleanup on - * unmount. - * - * Also acts as a basic store because it records the last data that it emitted, - * and provides a way to populate the initial data. The most recent data can be - * fetched from the Subscribable by calling `get()` - * - * Advantages over EventEmitter + Subscibable.Mixin.addListenerOn: - * - Cleaner usage: no strings to identify the event - * - Lifespan pattern enforces cleanup - * - More logical: Subscribable.Mixin now uses a Subscribable class - * - Subscribable saves the last data and makes it available with `.get()` - * - * Legacy Subscribable.Mixin.addListenerOn allowed automatic subscription to - * EventEmitters. Now we should avoid EventEmitters and wrap with Subscribable - * instead: - * - * ``` - * AppState.networkReachability = new Subscribable( - * RCTDeviceEventEmitter, - * 'reachabilityDidChange', - * (resp) => resp.network_reachability, - * RKReachability.getCurrentReachability - * ); - * - * var myComponent = React.createClass({ - * mixins: [Subscribable.Mixin], - * getInitialState: function() { - * return { - * isConnected: AppState.networkReachability.get() !== 'none' - * }; - * }, - * componentDidMount: function() { - * this._reachSubscription = this.subscribeTo( - * AppState.networkReachability, - * (reachability) => { - * this.setState({ isConnected: reachability !== 'none' }) - * } - * ); - * }, - * render: function() { - * return ( - * - * {this.state.isConnected ? 'Network Connected' : 'No network'} - * - * this._reachSubscription.remove()}> - * End reachability subscription - * - * ); - * } - * }); - * ``` - */ - -var EventEmitter = require('EventEmitter'); - -var invariant = require('invariant'); -var logError = require('logError'); - -var SUBSCRIBABLE_INTERNAL_EVENT = 'subscriptionEvent'; - - -class Subscribable { - /** - * Creates a new Subscribable object - * - * @param {EventEmitter} eventEmitter Emitter to trigger subscription events. - * @param {string} eventName Name of emitted event that triggers subscription - * events. - * @param {function} eventMapping (optional) Function to convert the output - * of the eventEmitter to the subscription output. - * @param {function} getInitData (optional) Async function to grab the initial - * data to publish. Signature `function(successCallback, errorCallback)`. - * The resolved data will be transformed with the eventMapping before it - * gets emitted. - */ - constructor(eventEmitter, eventName, eventMapping, getInitData) { - - this._internalEmitter = new EventEmitter(); - this._eventMapping = eventMapping || (data => data); - - this._upstreamSubscription = eventEmitter.addListener( - eventName, - this._handleEmit, - this - ); - - // Asyncronously get the initial data, if provided - getInitData && getInitData(this._handleInitData.bind(this), logError); - } - - /** - * Returns the last data emitted from the Subscribable, or undefined - */ - get() { - return this._lastData; - } - - /** - * Unsubscribe from the upstream EventEmitter - */ - cleanup() { - this._upstreamSubscription && this._upstreamSubscription.remove(); - } - - /** - * Add a new listener to the subscribable. This should almost never be used - * directly, and instead through Subscribable.Mixin.subscribeTo - * - * @param {object} lifespan Object with `addUnmountCallback` that accepts - * a handler to be called when the component unmounts. This is required and - * desirable because it enforces cleanup. There is no easy way to leave the - * subsciption hanging - * { - * addUnmountCallback: function(newUnmountHanlder) {...}, - * } - * @param {function} callback Handler to call when Subscribable has data - * updates - * @param {object} context Object to bind the handler on, as "this" - * - * @return {object} the subscription object: - * { - * remove: function() {...}, - * } - * Call `remove` to terminate the subscription before unmounting - */ - subscribe(lifespan, callback, context) { - invariant( - typeof lifespan.addUnmountCallback === 'function', - 'Must provide a valid lifespan, which provides a way to add a ' + - 'callback for when subscription can be cleaned up. This is used ' + - 'automatically by Subscribable.Mixin' - ); - invariant( - typeof callback === 'function', - 'Must provide a valid subscription handler.' - ); - - // Add a listener to the internal EventEmitter - var subscription = this._internalEmitter.addListener( - SUBSCRIBABLE_INTERNAL_EVENT, - callback, - context - ); - - // Clean up subscription upon the lifespan unmount callback - lifespan.addUnmountCallback(() => { - subscription.remove(); - }); - - return subscription; - } - - /** - * Callback for the initial data resolution. Currently behaves the same as - * `_handleEmit`, but we may eventually want to keep track of the difference - */ - _handleInitData(dataInput) { - var emitData = this._eventMapping(dataInput); - this._lastData = emitData; - this._internalEmitter.emit(SUBSCRIBABLE_INTERNAL_EVENT, emitData); - } - - /** - * Handle new data emissions. Pass the data through our eventMapping - * transformation, store it for later `get()`ing, and emit it for subscribers - */ - _handleEmit(dataInput) { - var emitData = this._eventMapping(dataInput); - this._lastData = emitData; - this._internalEmitter.emit(SUBSCRIBABLE_INTERNAL_EVENT, emitData); - } -} - - -Subscribable.Mixin = { - - /** - * @return {object} lifespan Object with `addUnmountCallback` that accepts - * a handler to be called when the component unmounts - * { - * addUnmountCallback: function(newUnmountHanlder) {...}, - * } - */ - _getSubscribableLifespan: function() { - if (!this._subscribableLifespan) { - this._subscribableLifespan = { - addUnmountCallback: (cb) => { - this._endSubscribableLifespanCallbacks.push(cb); - }, - }; - } - return this._subscribableLifespan; - }, - - _endSubscribableLifespan: function() { - this._endSubscribableLifespanCallbacks.forEach(cb => cb()); - }, - - /** - * Components use `subscribeTo` for listening to Subscribable stores. Cleanup - * is automatic on component unmount. - * - * To stop listening to the subscribable and end the subscription early, - * components should store the returned subscription object and invoke the - * `remove()` function on it - * - * @param {Subscribable} subscription to subscribe to. - * @param {function} listener Function to invoke when event occurs. - * @param {object} context Object to bind the handler on, as "this" - * - * @return {object} the subscription object: - * { - * remove: function() {...}, - * } - * Call `remove` to terminate the subscription before unmounting - */ - subscribeTo: function(subscribable, handler, context) { - invariant( - subscribable instanceof Subscribable, - 'Must provide a Subscribable' - ); - return subscribable.subscribe( - this._getSubscribableLifespan(), - handler, - context - ); - }, - - /** - * Gets a Subscribable store, scoped to the component, that can be passed to - * children. The component will automatically clean up the subscribable's - * subscription to the eventEmitter when unmounting. - * - * `provideSubscribable` will always return the same Subscribable for any - * particular emitter/eventName combo, so it can be called directly from - * render, and it will never create duplicate Subscribables. - * - * @param {EventEmitter} eventEmitter Emitter to trigger subscription events. - * @param {string} eventName Name of emitted event that triggers subscription - * events. - * @param {function} eventMapping (optional) Function to convert the output - * of the eventEmitter to the subscription output. - * @param {function} getInitData (optional) Async function to grab the initial - * data to publish. Signature `function(successCallback, errorCallback)`. - * The resolved data will be transformed with the eventMapping before it - * gets emitted. - */ - provideSubscribable: function(eventEmitter, eventName, eventMapping, getInitData) { - this._localSubscribables = this._localSubscribables || {}; - this._localSubscribables[eventEmitter] = - this._localSubscribables[eventEmitter] || {}; - if (!this._localSubscribables[eventEmitter][eventName]) { - this._localSubscribables[eventEmitter][eventName] = - new Subscribable(eventEmitter, eventName, eventMapping, getInitData); - } - return this._localSubscribables[eventEmitter][eventName]; - }, - - /** - * Removes any local Subscribables created with `provideSubscribable`, so the - * component can unmount without leaving any dangling listeners on - * eventEmitters - */ - _cleanupLocalSubscribables: function() { - if (!this._localSubscribables) { - return; - } - var emitterSubscribables; - Object.keys(this._localSubscribables).forEach((eventEmitter) => { - emitterSubscribables = this._localSubscribables[eventEmitter]; - Object.keys(emitterSubscribables).forEach((eventName) => { - emitterSubscribables[eventName].cleanup(); - }); - }); - this._localSubscribables = null; - }, - - componentWillMount: function() { - this._endSubscribableLifespanCallbacks = []; - - // DEPRECATED addListenerOn* usage: - this._subscribableSubscriptions = []; - }, - - componentWillUnmount: function() { - // Resolve the lifespan, which will cause Subscribable to clean any - // remaining subscriptions - this._endSubscribableLifespan && this._endSubscribableLifespan(); - - this._cleanupLocalSubscribables(); - - // DEPRECATED addListenerOn* usage uses _subscribableSubscriptions array - // instead of lifespan - this._subscribableSubscriptions.forEach( - (subscription) => subscription.remove() - ); - this._subscribableSubscriptions = null; - }, - - /** - * DEPRECATED - Use `Subscribable` and `Mixin.subscribeTo` instead. - * `addListenerOn` subscribes the component to an `EventEmitter`. - * - * Special form of calling `addListener` that *guarantees* that a - * subscription *must* be tied to a component instance, and therefore will - * be cleaned up when the component is unmounted. It is impossible to create - * the subscription and pass it in - this method must be the one to create - * the subscription and therefore can guarantee it is retained in a way that - * will be cleaned up. - * - * @param {EventEmitter} eventEmitter emitter to subscribe to. - * @param {string} eventType Type of event to listen to. - * @param {function} listener Function to invoke when event occurs. - * @param {object} context Object to use as listener context. - */ - addListenerOn: function(eventEmitter, eventType, listener, context) { - this._subscribableSubscriptions.push( - eventEmitter.addListener(eventType, listener, context) - ); - } -}; - -module.exports = Subscribable; diff --git a/Libraries/Components/SwitchIOS/SwitchIOS.android.js b/Libraries/Components/SwitchIOS/SwitchIOS.android.js deleted file mode 100644 index 72c24fa2894..00000000000 --- a/Libraries/Components/SwitchIOS/SwitchIOS.android.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule SwitchIOS - */ - -'use strict'; - -var React = require('React'); -var StyleSheet = require('StyleSheet'); -var Text = require('Text'); -var View = require('View'); - -var DummySwitchIOS = React.createClass({ - render: function() { - return ( - - SwitchIOS is not supported on this platform! - - ); - }, -}); - -var styles = StyleSheet.create({ - dummySwitchIOS: { - width: 120, - height: 50, - backgroundColor: '#ffbcbc', - borderWidth: 1, - borderColor: 'red', - alignItems: 'center', - justifyContent: 'center', - }, - text: { - color: '#333333', - margin: 5, - fontSize: 10, - } -}); - -module.exports = DummySwitchIOS; diff --git a/Libraries/Components/SwitchIOS/SwitchIOS.ios.js b/Libraries/Components/SwitchIOS/SwitchIOS.ios.js deleted file mode 100644 index 391b4da3a66..00000000000 --- a/Libraries/Components/SwitchIOS/SwitchIOS.ios.js +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule SwitchIOS - * - * This is a controlled component version of RKSwitch. - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var PropTypes = require('ReactPropTypes'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); -var merge = require('merge'); - -var SWITCH = 'switch'; - -/** - * Use `SwitchIOS` to render a boolean input on iOS. This is - * a controlled component, so you must hook in to the `onValueChange` callback - * and update the `value` prop in order for the component to update, otherwise - * the user's change will be reverted immediately to reflect `props.value` as the - * source of truth. - */ -var SwitchIOS = React.createClass({ - mixins: [NativeMethodsMixin], - - propTypes: { - /** - * 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, - - /** - * Callback that is called when the user toggles the switch. - */ - onValueChange: PropTypes.func, - - /** - * Background color when the switch is turned on. - */ - onTintColor: PropTypes.string, - - /** - * Background color for the switch round button. - */ - thumbTintColor: PropTypes.string, - - /** - * Background color when the switch is turned off. - */ - tintColor: PropTypes.string, - }, - - getDefaultProps: function() { - return { - value: false, - disabled: false, - }; - }, - - _onChange: function(event) { - this.props.onChange && this.props.onChange(event); - this.props.onValueChange && this.props.onValueChange(event.nativeEvent.value); - - // The underlying switch might have changed, but we're controlled, - // and so want to ensure it represents our value. - this.refs[SWITCH].setNativeProps({on: this.props.value}); - }, - - render: function() { - return ( - - ); - } -}); - -var styles = StyleSheet.create({ - rkSwitch: { - height: 31, - width: 51, - }, -}); - -var rkSwitchAttributes = merge(ReactIOSViewAttributes.UIView, { - onTintColor: true, - tintColor: true, - thumbTintColor: true, - on: true, - enabled: true, -}); - -var RKSwitch = createReactIOSNativeComponentClass({ - validAttributes: rkSwitchAttributes, - uiViewClassName: 'RCTSwitch', -}); - -module.exports = SwitchIOS; diff --git a/Libraries/Components/TabBarIOS/TabBarIOS.android.js b/Libraries/Components/TabBarIOS/TabBarIOS.android.js deleted file mode 100644 index 7bddc1e92cf..00000000000 --- a/Libraries/Components/TabBarIOS/TabBarIOS.android.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TabBarIOS - */ - -'use strict'; - -var React = require('React'); -var View = require('View'); -var StyleSheet = require('StyleSheet'); - -var DummyTabBarIOS = React.createClass({ - render: function() { - return ( - - {this.props.children} - - ); - } -}); - -var styles = StyleSheet.create({ - tabGroup: { - flex: 1, - } -}); - -module.exports = DummyTabBarIOS; diff --git a/Libraries/Components/TabBarIOS/TabBarIOS.ios.js b/Libraries/Components/TabBarIOS/TabBarIOS.ios.js deleted file mode 100644 index e3021b9b794..00000000000 --- a/Libraries/Components/TabBarIOS/TabBarIOS.ios.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TabBarIOS - */ -'use strict'; - -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); - -var TabBarIOS = React.createClass({ - render: function() { - return ( - - {this.props.children} - - ); - } -}); - -var styles = StyleSheet.create({ - tabGroup: { - flex: 1, - } -}); - -var config = { - validAttributes: ReactIOSViewAttributes.UIView, - uiViewClassName: 'RCTTabBar', -}; -var RKTabBar = createReactIOSNativeComponentClass(config); - -module.exports = TabBarIOS; diff --git a/Libraries/Components/TabBarIOS/TabBarItemIOS.android.js b/Libraries/Components/TabBarIOS/TabBarItemIOS.android.js deleted file mode 100644 index 634cc06c431..00000000000 --- a/Libraries/Components/TabBarIOS/TabBarItemIOS.android.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TabBarItemIOS - */ - -'use strict'; - -var Dimensions = require('Dimensions'); -var React = require('React'); -var View = require('View'); -var StyleSheet = require('StyleSheet'); - -var DummyTab = React.createClass({ - render: function() { - 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', - width: Dimensions.get('window').width, - height: Dimensions.get('window').height, - borderColor: 'red', - borderWidth: 1, - } -}); - -module.exports = DummyTab; diff --git a/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js b/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js deleted file mode 100644 index 763be743811..00000000000 --- a/Libraries/Components/TabBarIOS/TabBarItemIOS.ios.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TabBarItemIOS - */ -'use strict'; - -var Image = require('Image'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var Dimensions = require('Dimensions'); -var StaticContainer = require('StaticContainer.react'); -var StyleSheet = require('StyleSheet'); -var View = require('View'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); -var merge = require('merge'); - -var TabBarItemIOS = React.createClass({ - propTypes: { - icon: Image.propTypes.source.isRequired, - onPress: React.PropTypes.func.isRequired, - selected: React.PropTypes.bool.isRequired, - badgeValue: React.PropTypes.string, - title: React.PropTypes.string, - style: View.propTypes.style, - }, - - getInitialState: function() { - return { - hasBeenSelected: false, - }; - }, - - componentWillMount: function() { - if (this.props.selected) { - this.setState({hasBeenSelected: true}); - } - }, - - componentWillReceiveProps: function(nextProps) { - if (this.state.hasBeenSelected || nextProps.selected) { - this.setState({hasBeenSelected: true}); - } - }, - - render: function() { - var tabContents = null; - // if the tab has already been shown once, always continue to show it so we - // preserve state between tab transitions - if (this.state.hasBeenSelected) { - tabContents = - - {this.props.children} - ; - } else { - tabContents = ; - } - - return ( - - {tabContents} - - ); - } -}); - -var styles = StyleSheet.create({ - tab: { - position: 'absolute', - width: Dimensions.get('window').width, - height: Dimensions.get('window').height, - } -}); - -var RKTabBarItem = createReactIOSNativeComponentClass({ - validAttributes: merge(ReactIOSViewAttributes.UIView, { - title: true, - icon: true, - selectedIcon: true, - selected: true, - badgeValue: true, - }), - uiViewClassName: 'RCTTabBarItem', -}); - -module.exports = TabBarItemIOS; diff --git a/Libraries/Components/TextInput/TextInput.ios.js b/Libraries/Components/TextInput/TextInput.ios.js deleted file mode 100644 index 20eda688b82..00000000000 --- a/Libraries/Components/TextInput/TextInput.ios.js +++ /dev/null @@ -1,435 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TextInput - */ -'use strict'; - -var DocumentSelectionState = require('DocumentSelectionState'); -var EventEmitter = require('EventEmitter'); -var NativeMethodsMixin = require('NativeMethodsMixin'); -var RKUIManager = require('NativeModules').RKUIManager; -var PropTypes = require('ReactPropTypes'); -var React = require('React'); -var ReactChildren = require('ReactChildren'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); -var Subscribable = require('Subscribable'); -var Text = require('Text'); -var TextInputState = require('TextInputState'); -var TimerMixin = require('TimerMixin'); -var TouchableWithoutFeedback = require('TouchableWithoutFeedback'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); -var emptyFunction = require('emptyFunction'); -var getObjectValues = require('getObjectValues'); -var invariant = require('invariant'); -var merge = require('merge'); - -var autoCapitalizeConsts = RKUIManager.UIText.AutocapitalizationType; -var clearButtonModeConsts = RKUIManager.UITextField.clearButtonMode; - -var RKTextViewAttributes = merge(ReactIOSViewAttributes.UIView, { - autoCorrect: true, - autoCapitalize: true, - color: true, - editable: true, - fontSize: true, - fontWeight: true, - keyboardType: true, - mostRecentEventCounter: true, - placeholder: true, - placeholderTextColor: true, - text: true, -}); - -var RKTextFieldAttributes = merge(RKTextViewAttributes, { - caretHidden: true, - enabled: true, - clearButtonMode: true, -}); - -var onlyMultiline = { - onSelectionChange: true, - onTextInput: true, - children: true, -}; - -var notMultiline = { - onSubmitEditing: true, -}; - -/** - * 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: - * - * ``` - * - * this.setState({input: text})} - * /> - * {'user input: ' + this.state.input} - * - * ``` - * - * The `value` prop can be used to set the value of the input in order to make - * the state of the component clear, but does not behave as a true - * controlled component by default because all operations are asynchronous. - * Setting `value` once is like setting the default value, but you can change it - * continuously based on `onChangeText` events as well. If you really want to - * force the component to always revert to the value you are setting, you can - * set `controlled={true}`. - * - * The `multiline` prop is not supported in all releases, and some props are - * multiline only. - */ - -var TextInput = React.createClass({ - propTypes: { - /** - * 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. Default value is true. - */ - autoCorrect: PropTypes.bool, - /** - * If true, focuses the input on componentDidMount. Default value is false. - */ - autoFocus: PropTypes.bool, - /** - * If false, text is not editable. Default value is true. - */ - editable: PropTypes.bool, - /** - * Determines which keyboard to open, e.g.`numeric`. - */ - keyboardType: PropTypes.oneOf([ - 'default', - 'numeric', - ]), - /** - * If true, the text input can be multiple lines. Default value is false. - */ - multiline: PropTypes.bool, - /** - * 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, - /** - * (text: string) => void - * - * Callback that is called when the text input's text changes. - */ - onChangeText: PropTypes.func, - - onEndEditing: PropTypes.func, - onSubmitEditing: PropTypes.func, - /** - * The string that will be rendered before text input has been entered - */ - placeholder: PropTypes.string, - /** - * The text color of the placeholder string - */ - placeholderTextColor: PropTypes.string, - /** - * See DocumentSelectionState.js, some state that is responsible for - * maintaining selection information for a document - */ - selectionState: PropTypes.instanceOf(DocumentSelectionState), - /** - * The default value for the text input - */ - value: PropTypes.string, - /** - * This helps avoid drops characters due to race conditions between JS and - * the native text input. The default should be fine, but if you're - * potentially doing very slow operations on every keystroke then you may - * want to try increasing this. - */ - bufferDelay: PropTypes.number, - /** - * If you really want this to behave as a controlled component, you can set - * this true, but you will probably see flickering, dropped keystrokes, - * and/or laggy typing, depending on how you process onChange events. - */ - controlled: PropTypes.bool, - /** - * When the clear button should appear on the right side of the text view - */ - clearButtonMode: PropTypes.oneOf([ - 'never', - 'while-editing', - 'unless-editing', - 'always', - ]), - - style: Text.propTypes.style, - }, - - /** - * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We - * make `this` look like an actual native component class. - */ - mixins: [NativeMethodsMixin, TimerMixin, Subscribable.Mixin], - - viewConfig: { - uiViewClassName: 'RCTTextField', - validAttributes: RKTextFieldAttributes, - }, - - isFocused: function() { - return TextInputState.currentlyFocusedField() === - this.refs.input.getNativeNode(); - }, - - getDefaultProps: function() { - return { - bufferDelay: 100, - }; - }, - - getInitialState: function() { - return { - mostRecentEventCounter: 0, - bufferedValue: this.props.value, - }; - }, - - contextTypes: { - onFocusRequested: React.PropTypes.func, - focusEmitter: React.PropTypes.instanceOf(EventEmitter), - }, - - componentDidMount: function() { - if (!this.context.focusEmitter) { - if (this.props.autoFocus) { - this.requestAnimationFrame(this.focus); - } - return; - } - this.addListenerOn(this.context.focusEmitter, 'focus', (el) => { - if (this === el) { - this.requestAnimationFrame(this.focus); - } else if (this.isFocused()) { - this.blur(); - } - }); - if (this.props.autoFocus) { - this.context.onFocusRequested(this); - } - }, - - componentWillReceiveProps: function(newProps) { - if (newProps.value !== this.props.value) { - if (!this.isFocused()) { - // Set the value immediately if the input is not focused since that - // means there is no risk of the user typing immediately. - this.setState({bufferedValue: newProps.value}); - } else { - // The following clear and setTimeout buffers the value such that if more - // characters are typed in quick succession, generating new values, the - // out of date values will get cancelled before they are ever sent to - // native. - // - // If we don't do this, it's likely the out of date values will blow - // away recently typed characters in the native input that JS was not - // yet aware of (since it is informed asynchronously), then the next - // character will be appended to the older value, dropping the - // characters in between. Here is a potential sequence of events - // (recall we have multiple independently serial, interleaved queues): - // - // 1) User types 'R' => send 'R' to JS queue. - // 2) User types 'e' => send 'Re' to JS queue. - // 3) JS processes 'R' and sends 'R' back to native. - // 4) Native recieves 'R' and changes input from 'Re' back to 'R'. - // 5) User types 'a' => send 'Ra' to JS queue. - // 6) JS processes 'Re' and sends 'Re' back to native. - // 7) Native recieves 'Re' and changes input from 'R' back to 'Re'. - // 8) JS processes 'Ra' and sends 'Ra' back to native. - // 9) Native recieves final 'Ra' from JS - 'e' has been dropped! - // - // This isn't 100% foolproop (e.g. if it takes longer than - // `props.bufferDelay` ms to process one keystroke), and there are of - // course other potential algorithms to deal with this, but this is a - // simple solution that seems to reduce the chance of dropped characters - // drastically without compromising native input responsiveness (e.g. by - // introducing delay from a synchronization protocol). - this.clearTimeout(this._bufferTimeout); - this._bufferTimeout = this.setTimeout( - () => this.setState({bufferedValue: newProps.value}), - this.props.bufferDelay - ); - } - } - }, - - render: function() { - var textContainer; - - var autoCapitalize = autoCapitalizeConsts[this.props.autoCapitalize]; - var clearButtonMode = clearButtonModeConsts[this.props.clearButtonMode]; - - if (!this.props.multiline) { - for (var propKey in onlyMultiline) { - if (this.props[propKey]) { - throw new Error( - 'TextInput prop `' + propKey + '` is only supported with multiline.' - ); - } - } - textContainer = - true} - placeholder={this.props.placeholder} - text={this.state.bufferedValue} - autoCapitalize={autoCapitalize} - autoCorrect={this.props.autoCorrect} - clearButtonMode={clearButtonMode} - />; - } else { - for (var propKey in notMultiline) { - if (this.props[propKey]) { - throw new Error( - 'TextInput prop `' + propKey + '` cannot be used with multiline.' - ); - } - } - - var children = this.props.children; - var childCount = 0; - ReactChildren.forEach(children, () => ++childCount); - invariant( - !(this.props.value && childCount), - 'Cannot specify both value and children.' - ); - if (childCount > 1) { - children = {children}; - } - if (this.props.inputView) { - children = [children, this.props.inputView]; - } - textContainer = - ; - } - - return ( - - {textContainer} - - ); - }, - - _onFocus: function(event) { - if (this.props.onFocus) { - this.props.onFocus(event); - } - }, - - _onPress: function(event) { - this.focus(); - }, - - _onChange: function(event) { - if (this.props.controlled && event.nativeEvent.text !== this.props.value) { - this.refs.input.setNativeProps({text: this.props.value}); - } - this.props.onChange && this.props.onChange(event); - this.props.onChangeText && this.props.onChangeText(event.nativeEvent.text); - }, - - _onBlur: function(event) { - this.blur(); - if (this.props.onBlur) { - this.props.onBlur(event); - } - }, - - _onSelectionChange: function(event) { - if (this.props.selectionState) { - var selection = event.nativeEvent.selection; - this.props.selectionState.update(selection.start, selection.end); - } - this.props.onSelectionChange && this.props.onSelectionChange(event); - }, - - _onTextInput: function(event) { - this.props.onTextInput && this.props.onTextInput(event); - var counter = event.nativeEvent.eventCounter; - if (counter > this.state.mostRecentEventCounter) { - this.setState({mostRecentEventCounter: counter}); - } - }, -}); - -var styles = StyleSheet.create({ - input: { - alignSelf: 'stretch', - }, -}); - -var RKTextView = createReactIOSNativeComponentClass({ - validAttributes: RKTextViewAttributes, - uiViewClassName: 'RCTTextView', -}); - -var RKTextField = createReactIOSNativeComponentClass({ - validAttributes: RKTextFieldAttributes, - uiViewClassName: 'RCTTextField', -}); - -module.exports = TextInput; diff --git a/Libraries/Components/TextInput/TextInputState.js b/Libraries/Components/TextInput/TextInputState.js deleted file mode 100644 index a8c80ee66e6..00000000000 --- a/Libraries/Components/TextInput/TextInputState.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TextInputState - * - * This class is responsible for coordinating the "focused" - * state for TextInputs. All calls relating to the keyboard - * should be funneled through here - */ -'use strict'; - -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; - -var TextInputState = { - /** - * Internal state - */ - _currentlyFocusedID: null, - - /** - * Returns the ID of the currently focused text field, if one exists - * If no text field is focused it returns null - */ - currentlyFocusedField: function() { - return this._currentlyFocusedID; - }, - - /** - * @param {string} TextInputID id of the text field to focus - * Focuses the specified text field - * noop if the text field was already focused - */ - focusTextInput: function(textFieldID) { - if (this._currentlyFocusedID != textFieldID && textFieldID != null) { - this._currentlyFocusedID = textFieldID; - RKUIManager.focus(textFieldID); - } - }, - - /** - * @param {string} textFieldID id of the text field to focus - * Unfocuses the specified text field - * noop if it wasn't focused - */ - blurTextInput: function(textFieldID) { - if (this._currentlyFocusedID == textFieldID && textFieldID != null) { - this._currentlyFocusedID = null; - RKUIManager.blur(textFieldID); - } - } -}; - -module.exports = TextInputState; diff --git a/Libraries/Components/Touchable/TouchableFeedbackPropType.js b/Libraries/Components/Touchable/TouchableFeedbackPropType.js deleted file mode 100644 index 336b091c629..00000000000 --- a/Libraries/Components/Touchable/TouchableFeedbackPropType.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TouchableFeedbackPropType - * @flow - */ -'use strict'; - -var { PropTypes } = require('React'); - -var TouchableFeedbackPropType = { - /** - * Called when the touch is released, but not if cancelled (e.g. by a scroll - * that steals the responder lock). - */ - onPress: PropTypes.func, - onPressIn: PropTypes.func, - onPressOut: PropTypes.func, - onLongPress: PropTypes.func, -}; - -module.exports = TouchableFeedbackPropType; diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js deleted file mode 100644 index a48e2f29951..00000000000 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TouchableHighlight - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); -var TimerMixin = require('TimerMixin'); -var Touchable = require('Touchable'); -var TouchableFeedbackPropType = require('TouchableFeedbackPropType'); -var View = require('View'); - -var cloneWithProps = require('cloneWithProps'); -var ensureComponentIsNative = require('ensureComponentIsNative'); -var keyOf = require('keyOf'); -var merge = require('merge'); -var onlyChild = require('onlyChild'); - -var DEFAULT_PROPS = { - activeOpacity: 0.8, - underlayColor: 'black', -}; - -/** - * A wrapper for making views respond properly to touches. - * On press down, the opacity of the wrapped view is decreased, which allows - * the underlay color to show through, darkening or tinting the view. The - * underlay comes from adding a view to the view hierarchy, which can sometimes - * cause unwanted visual artifacts if not used correctly, for example if the - * backgroundColor of the wrapped view isn't explicitly set to an opaque color. - * - * Example: - * - * ``` - * renderButton: function() { - * return ( - * - * - * - * ); - * }, - * ``` - */ - -var TouchableHighlight = React.createClass({ - propTypes: { - ...TouchableFeedbackPropType, - /** - * Called when the touch is released, but not if cancelled (e.g. by - * a scroll that steals the responder lock). - */ - onPress: React.PropTypes.func.isRequired, - /** - * Determines what the opacity of the wrapped view should be when touch is - * active. - */ - activeOpacity: React.PropTypes.number, - /** - * The color of the underlay that will show through when the touch is - * active. - */ - underlayColor: React.PropTypes.string, - style: View.propTypes.style, - }, - - mixins: [NativeMethodsMixin, TimerMixin, Touchable.Mixin], - - getDefaultProps: () => DEFAULT_PROPS, - - // Performance optimization to avoid constantly re-generating these objects. - computeSyntheticState: function(props) { - return { - activeProps: { - style: { - opacity: props.activeOpacity, - } - }, - activeUnderlayProps: { - style: { - backgroundColor: props.underlayColor, - } - }, - underlayStyle: [ - INACTIVE_UNDERLAY_PROPS.style, - props.style, - ] - }; - }, - - getInitialState: function() { - return merge( - this.touchableGetInitialState(), this.computeSyntheticState(this.props) - ); - }, - - componentDidMount: function() { - ensureComponentIsNative(this.refs[CHILD_REF]); - }, - - componentDidUpdate: function() { - ensureComponentIsNative(this.refs[CHILD_REF]); - }, - - componentWillReceiveProps: function(nextProps) { - if (nextProps.activeOpacity !== this.props.activeOpacity || - nextProps.underlayColor !== this.props.underlayColor || - nextProps.style !== this.props.style) { - this.setState(this.computeSyntheticState(nextProps)); - } - }, - - viewConfig: { - uiViewClassName: 'RCTView', - validAttributes: ReactIOSViewAttributes.RKView - }, - - /** - * `Touchable.Mixin` self callbacks. The mixin will invoke these if they are - * defined on your component. - */ - touchableHandleActivePressIn: function() { - this.clearTimeout(this._hideTimeout); - this._hideTimeout = null; - this._showUnderlay(); - this.props.onPressIn && this.props.onPressIn(); - }, - - touchableHandleActivePressOut: function() { - if (!this._hideTimeout) { - this._hideUnderlay(); - } - this.props.onPressOut && this.props.onPressOut(); - }, - - touchableHandlePress: function() { - this.clearTimeout(this._hideTimeout); - this._showUnderlay(); - this._hideTimeout = this.setTimeout(this._hideUnderlay, 100); - this.props.onPress && this.props.onPress(); - }, - - touchableHandleLongPress: function() { - this.props.onLongPress && this.props.onLongPress(); - }, - - touchableGetPressRectOffset: function() { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! - }, - - _showUnderlay: function() { - this.refs[UNDERLAY_REF].setNativeProps(this.state.activeUnderlayProps); - this.refs[CHILD_REF].setNativeProps(this.state.activeProps); - }, - - _hideUnderlay: function() { - this.clearTimeout(this._hideTimeout); - this._hideTimeout = null; - if (this.refs[UNDERLAY_REF]) { - this.refs[CHILD_REF].setNativeProps(INACTIVE_CHILD_PROPS); - this.refs[UNDERLAY_REF].setNativeProps(INACTIVE_UNDERLAY_PROPS); - } - }, - - render: function() { - return ( - - {cloneWithProps( - onlyChild(this.props.children), - { - ref: CHILD_REF, - accessible: true, - testID: this.props.testID, - } - )} - - ); - } -}); - -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; -var CHILD_REF = keyOf({childRef: null}); -var UNDERLAY_REF = keyOf({underlayRef: null}); -var INACTIVE_CHILD_PROPS = { - style: StyleSheet.create({x: {opacity: 1.0}}).x, -}; -var INACTIVE_UNDERLAY_PROPS = { - style: StyleSheet.create({x: {backgroundColor: 'transparent'}}).x, -}; - -module.exports = TouchableHighlight; diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js deleted file mode 100644 index 1b2f3898fd3..00000000000 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TouchableOpacity - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var POPAnimationMixin = require('POPAnimationMixin'); -var React = require('React'); -var Touchable = require('Touchable'); -var TouchableFeedbackPropType = require('TouchableFeedbackPropType'); - -var cloneWithProps = require('cloneWithProps'); -var ensureComponentIsNative = require('ensureComponentIsNative'); -var keyOf = require('keyOf'); -var onlyChild = require('onlyChild'); - -/** - * A wrapper for making views respond properly to touches. - * On press down, the opacity of the wrapped view is decreased, dimming it. - * This is done without actually changing the view hierarchy, and in general is - * easy to add to an app without weird side-effects. - * - * Example: - * - * ``` - * renderButton: function() { - * return ( - * - * - * - * ); - * }, - * ``` - */ - -var TouchableOpacity = React.createClass({ - mixins: [Touchable.Mixin, NativeMethodsMixin, POPAnimationMixin], - - propTypes: { - ...TouchableFeedbackPropType, - /** - * Determines what the opacity of the wrapped view should be when touch is - * active. - */ - activeOpacity: React.PropTypes.number, - }, - - getDefaultProps: function() { - return { - activeOpacity: 0.5, - }; - }, - - getInitialState: function() { - return this.touchableGetInitialState(); - }, - - componentDidMount: function() { - ensureComponentIsNative(this.refs[CHILD_REF]); - }, - - componentDidUpdate: function() { - ensureComponentIsNative(this.refs[CHILD_REF]); - }, - - setOpacityTo: function(value) { - if (POPAnimationMixin) { - // Reset with animation if POP is available - this.stopAllAnimations(); - var anim = { - type: this.AnimationTypes.linear, - property: this.AnimationProperties.opacity, - toValue: value, - }; - this.startAnimation(CHILD_REF, anim); - } else { - // Reset immediately if POP is unavailable - this.refs[CHILD_REF].setNativeProps({ - opacity: value - }); - } - }, - - /** - * `Touchable.Mixin` self callbacks. The mixin will invoke these if they are - * defined on your component. - */ - touchableHandleActivePressIn: function() { - this.refs[CHILD_REF].setNativeProps({ - opacity: this.props.activeOpacity - }); - this.props.onPressIn && this.props.onPressIn(); - }, - - touchableHandleActivePressOut: function() { - this.setOpacityTo(1.0); - this.props.onPressOut && this.props.onPressOut(); - }, - - touchableHandlePress: function() { - this.setOpacityTo(1.0); - this.props.onPress && this.props.onPress(); - }, - - touchableHandleLongPress: function() { - this.props.onLongPress && this.props.onLongPress(); - }, - - touchableGetPressRectOffset: function() { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! - }, - - touchableGetHighlightDelayMS: function() { - return 0; - }, - - render: function() { - return cloneWithProps(onlyChild(this.props.children), { - ref: CHILD_REF, - accessible: true, - testID: this.props.testID, - onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder, - onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest, - onResponderGrant: this.touchableHandleResponderGrant, - onResponderMove: this.touchableHandleResponderMove, - onResponderRelease: this.touchableHandleResponderRelease, - onResponderTerminate: this.touchableHandleResponderTerminate, - }); - }, -}); - -/** - * When the scroll view is disabled, this defines how far your touch may move - * off of the button, before deactivating the button. Once deactivated, try - * moving it back and you'll see that the button is once again reactivated! - * Move it back and forth several times while the scroll view is disabled. - */ -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; - -var CHILD_REF = keyOf({childRef: null}); - -module.exports = TouchableOpacity; diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js deleted file mode 100644 index ccc784e6ad5..00000000000 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TouchableWithoutFeedback - */ -'use strict'; - -var React = require('React'); -var Touchable = require('Touchable'); -var TouchableFeedbackPropType = require('TouchableFeedbackPropType'); - -var onlyChild = require('onlyChild'); - -/** - * When the scroll view is disabled, this defines how far your touch may move - * off of the button, before deactivating the button. Once deactivated, try - * moving it back and you'll see that the button is once again reactivated! - * Move it back and forth several times while the scroll view is disabled. - */ -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; - - -/** - * Do not use unless you have a very good reason. All the elements that - * respond to press should have a visual feedback when touched. This is - * one of the primary reason a "web" app doesn't feel "native". - */ -var TouchableWithoutFeedback = React.createClass({ - mixins: [Touchable.Mixin], - - propTypes: TouchableFeedbackPropType, - - getInitialState: function() { - return this.touchableGetInitialState(); - }, - - /** - * `Touchable.Mixin` self callbacks. The mixin will invoke these if they are - * defined on your component. - */ - touchableHandlePress: function(e) { - this.props.onPress && this.props.onPress(e); - }, - - touchableHandleActivePressIn: function() { - this.props.onPressIn && this.props.onPressIn(); - }, - - touchableHandleActivePressOut: function() { - this.props.onPressOut && this.props.onPressOut(); - }, - - touchableHandleLongPress: function() { - this.props.onLongPress && this.props.onLongPress(); - }, - - touchableGetPressRectOffset: function() { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! - }, - - touchableGetHighlightDelayMS: function() { - return 0; - }, - - render: function() { - // Note(vjeux): use cloneWithProps once React has been upgraded - var child = onlyChild(this.props.children); - return React.cloneElement(child, { - accessible: true, - testID: this.props.testID, - onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder, - onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest, - onResponderGrant: this.touchableHandleResponderGrant, - onResponderMove: this.touchableHandleResponderMove, - onResponderRelease: this.touchableHandleResponderRelease, - onResponderTerminate: this.touchableHandleResponderTerminate - }); - } -}); - -module.exports = TouchableWithoutFeedback; diff --git a/Libraries/Components/Touchable/ensureComponentIsNative.js b/Libraries/Components/Touchable/ensureComponentIsNative.js deleted file mode 100644 index c16d93e3d27..00000000000 --- a/Libraries/Components/Touchable/ensureComponentIsNative.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ensureComponentIsNative - */ -'use strict'; - -var invariant = require('invariant'); - -var ensureComponentIsNative = function(component) { - invariant( - component && typeof component.setNativeProps === 'function', - 'Touchable child must either be native or forward setNativeProps to a ' + - 'native component' - ); -}; - -module.exports = ensureComponentIsNative; diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js deleted file mode 100644 index b75988f4a11..00000000000 --- a/Libraries/Components/View/View.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule View - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var PropTypes = require('ReactPropTypes'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheetPropType = require('StyleSheetPropType'); -var ViewStylePropTypes = require('ViewStylePropTypes'); - - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); - -var stylePropType = StyleSheetPropType(ViewStylePropTypes); - -/** - * The most fundamental component for building UI, `View` is a - * container that supports layout with flexbox, style, some touch handling, and - * accessibility controls, and is designed to be nested inside other views and - * to have 0 to many children of any type. `View` maps directly to the native - * view equivalent on whatever platform react is running on, whether that is a - * `UIView`, `
`, `android.view`, etc. This example creates a `View` that - * wraps two colored boxes and custom component in a row with padding. - * - * ``` - * - * - * - * - * - * ``` - * - * By default, `View`s have a primary flex direction of 'column', so children - * will stack up vertically by default. `View`s also expand to fill the parent - * in the direction of the parent's flex direction by default, so in the case of - * a default parent (flexDirection: 'column'), the children will fill the width, - * but not the height. - * - * Many library components can be treated like plain `Views` in many cases, for - * example passing them children, setting style, etc. - * - * `View`s are designed to be used with `StyleSheet`s for clarity and - * performance, although inline styles are also supported. It is common for - * `StyleSheet`s to be combined dynamically. See `StyleSheet.js` for more info. - */ -var View = React.createClass({ - mixins: [NativeMethodsMixin], - - /** - * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We - * make `this` look like an actual native component class. - */ - viewConfig: { - uiViewClassName: 'RCTView', - validAttributes: ReactIOSViewAttributes.RKView - }, - - propTypes: { - /** - * When true, indicates that the view is an accessibility element - */ - accessible: PropTypes.bool, - - /** - * Used to locate this view in end-to-end tests. - */ - testID: PropTypes.string, - - /** - * For most touch interactions, you'll simply want to wrap your component in - * `TouchableHighlight.js`. Check out `Touchable.js` and - * `ScrollResponder.js` for more discussion. - */ - onResponderGrant: PropTypes.func, - onResponderReject: PropTypes.func, - onResponderMove: PropTypes.func, - onResponderRelease: PropTypes.func, - onResponderTerminate: PropTypes.func, - onResponderTerminationRequest: PropTypes.func, - onMoveShouldSetResponder: PropTypes.func, - onStartShouldSetResponder: PropTypes.func, - onStartShouldSetResponderCapture: PropTypes.func, - - /** - * In the absence of `auto` property, `none` is much like `CSS`'s `none` - * value. `box-none` is as if you had applied the `CSS` class: - * - * .cantTouchThis * { - * pointer-events: auto; - * } - * .cantTouchThis { - * pointer-events: none; - * } - * - * But since `pointerEvents` does not affect layout/appearance, and we are - * already deviating from the spec by adding additional modes, we opt to not - * include `pointerEvents` on `style`. On some platforms, we would need to - * implement it as a `className` anyways. Using `style` or not is an - * implementation detail of the platform. - */ - pointerEvents: PropTypes.oneOf([ - 'box-none', - 'none', - 'box-only', - 'auto', - ]), - - /** - * Used to style and layout the `View`. See `StyleSheet.js` and - * `ViewStylePropTypes.js` for more info. - */ - style: stylePropType, - - /** - * This is a special performance property exposed by RKView and is useful - * for scrolling content when there are many subviews, most of which are - * offscreen. For this property to be effective, it must be applied to a - * view that contains many subviews that extend outside its bound. The - * subviews must also have overflow: hidden, as should the containing view - * (or one of its superviews). - */ - removeClippedSubviews: PropTypes.bool, - }, - - render: function() { - return ; - }, -}); - - -var RKView = createReactIOSNativeComponentClass({ - validAttributes: ReactIOSViewAttributes.RKView, - uiViewClassName: 'RCTView', -}); -RKView.propTypes = View.propTypes; - -var ViewToExport = RKView; -if (__DEV__) { - ViewToExport = View; -} - - -module.exports = ViewToExport; diff --git a/Libraries/Components/View/ViewStylePropTypes.js b/Libraries/Components/View/ViewStylePropTypes.js deleted file mode 100644 index c049c3d5367..00000000000 --- a/Libraries/Components/View/ViewStylePropTypes.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ViewStylePropTypes - */ -'use strict'; - -var LayoutPropTypes = require('LayoutPropTypes'); -var ReactPropTypes = require('ReactPropTypes'); - -var merge = require('merge'); - -/** - * Warning: Some of these properties may not be supported in all releases. - */ -var ViewStylePropTypes = merge( - LayoutPropTypes, { - backgroundColor: ReactPropTypes.string, - borderColor: ReactPropTypes.string, - borderTopColor: ReactPropTypes.string, - borderRightColor: ReactPropTypes.string, - borderBottomColor: ReactPropTypes.string, - borderLeftColor: ReactPropTypes.string, - borderRadius: ReactPropTypes.number, - opacity: ReactPropTypes.number, - overflow: ReactPropTypes.oneOf(['visible', 'hidden']), - shadowColor: ReactPropTypes.string, - shadowOffset: ReactPropTypes.shape( - {h: ReactPropTypes.number, w: ReactPropTypes.number} - ), - shadowOpacity: ReactPropTypes.number, - shadowRadius: ReactPropTypes.number, - transformMatrix: ReactPropTypes.arrayOf(ReactPropTypes.number), - rotation: ReactPropTypes.number, - scaleX: ReactPropTypes.number, - scaleY: ReactPropTypes.number, - translateX: ReactPropTypes.number, - translateY: ReactPropTypes.number, -}); - -module.exports = ViewStylePropTypes; diff --git a/Libraries/Device/RCTDeviceEventEmitter.js b/Libraries/Device/RCTDeviceEventEmitter.js deleted file mode 100644 index adb9d3498c8..00000000000 --- a/Libraries/Device/RCTDeviceEventEmitter.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule RCTDeviceEventEmitter - */ -'use strict'; - -var EventEmitter = require('EventEmitter'); - -var RCTDeviceEventEmitter = new EventEmitter(); - -module.exports = RCTDeviceEventEmitter; diff --git a/Libraries/Fetch/fetch.js b/Libraries/Fetch/fetch.js deleted file mode 100644 index 1ffa8c1f627..00000000000 --- a/Libraries/Fetch/fetch.js +++ /dev/null @@ -1,313 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * This is a third-party polyfill grabbed from: - * https://github.com/github/fetch - * - * @providesModule fetch - * @nolint - */ -'use strict'; - -var self = {}; - -/** - * Copyright (c) 2014 GitHub, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * @preserve-header - */ -(function() { - 'use strict'; - - if (self.fetch) { - return - } - - function Headers(headers) { - this.map = {} - - var self = this - if (headers instanceof Headers) { - headers.forEach(function(name, values) { - values.forEach(function(value) { - self.append(name, value) - }) - }) - - } else if (headers) { - Object.getOwnPropertyNames(headers).forEach(function(name) { - self.append(name, headers[name]) - }) - } - } - - Headers.prototype.append = function(name, value) { - name = name.toLowerCase() - var list = this.map[name] - if (!list) { - list = [] - this.map[name] = list - } - list.push(value) - } - - Headers.prototype['delete'] = function(name) { - delete this.map[name.toLowerCase()] - } - - Headers.prototype.get = function(name) { - var values = this.map[name.toLowerCase()] - return values ? values[0] : null - } - - Headers.prototype.getAll = function(name) { - return this.map[name.toLowerCase()] || [] - } - - Headers.prototype.has = function(name) { - return this.map.hasOwnProperty(name.toLowerCase()) - } - - Headers.prototype.set = function(name, value) { - this.map[name.toLowerCase()] = [value] - } - - // Instead of iterable for now. - Headers.prototype.forEach = function(callback) { - var self = this - Object.getOwnPropertyNames(this.map).forEach(function(name) { - callback(name, self.map[name]) - }) - } - - function consumed(body) { - if (body.bodyUsed) { - return Promise.reject(new TypeError('Already read')) - } - body.bodyUsed = true - } - - function fileReaderReady(reader) { - return new Promise(function(resolve, reject) { - reader.onload = function() { - resolve(reader.result) - } - reader.onerror = function() { - reject(reader.error) - } - }) - } - - function readBlobAsArrayBuffer(blob) { - var reader = new FileReader() - reader.readAsArrayBuffer(blob) - return fileReaderReady(reader) - } - - function readBlobAsText(blob) { - var reader = new FileReader() - reader.readAsText(blob) - return fileReaderReady(reader) - } - - var blobSupport = 'FileReader' in self && 'Blob' in self && (function() { - try { - new Blob(); - return true - } catch(e) { - return false - } - })(); - - function Body() { - this.bodyUsed = false - - if (blobSupport) { - this.blob = function() { - var rejected = consumed(this) - return rejected ? rejected : Promise.resolve(this._bodyBlob) - } - - this.arrayBuffer = function() { - return this.blob().then(readBlobAsArrayBuffer) - } - - this.text = function() { - return this.blob().then(readBlobAsText) - } - } else { - this.text = function() { - var rejected = consumed(this) - return rejected ? rejected : Promise.resolve(this._bodyText) - } - } - - if ('FormData' in self) { - this.formData = function() { - return this.text().then(decode) - } - } - - this.json = function() { - return this.text().then(JSON.parse) - } - - return this - } - - // HTTP methods whose capitalization should be normalized - var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] - - function normalizeMethod(method) { - var upcased = method.toUpperCase() - return (methods.indexOf(upcased) > -1) ? upcased : method - } - - function Request(url, options) { - options = options || {} - this.url = url - this._body = options.body - this.credentials = options.credentials || 'omit' - this.headers = new Headers(options.headers) - this.method = normalizeMethod(options.method || 'GET') - this.mode = options.mode || null - this.referrer = null - } - - function decode(body) { - var form = new FormData() - body.trim().split('&').forEach(function(bytes) { - if (bytes) { - var split = bytes.split('=') - var name = split.shift().replace(/\+/g, ' ') - var value = split.join('=').replace(/\+/g, ' ') - form.append(decodeURIComponent(name), decodeURIComponent(value)) - } - }) - return form - } - - function headers(xhr) { - var head = new Headers() - var pairs = xhr.getAllResponseHeaders().trim().split('\n') - pairs.forEach(function(header) { - var split = header.trim().split(':') - var key = split.shift().trim() - var value = split.join(':').trim() - head.append(key, value) - }) - return head - } - - Request.prototype.fetch = function() { - var self = this - - return new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest() - - function responseURL() { - if ('responseURL' in xhr) { - return xhr.responseURL - } - - // Avoid security warnings on getResponseHeader when not allowed by CORS - if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) { - return xhr.getResponseHeader('X-Request-URL') - } - - return; - } - - xhr.onload = function() { - var status = (xhr.status === 1223) ? 204 : xhr.status - if (status < 100 || status > 599) { - reject(new TypeError('Network request failed')) - return - } - var options = { - status: status, - statusText: xhr.statusText, - headers: headers(xhr), - url: responseURL() - } - var body = 'response' in xhr ? xhr.response : xhr.responseText; - resolve(new Response(body, options)) - } - - xhr.onerror = function() { - reject(new TypeError('Network request failed')) - } - - xhr.open(self.method, self.url) - if ('responseType' in xhr && blobSupport) { - xhr.responseType = 'blob' - } - - self.headers.forEach(function(name, values) { - values.forEach(function(value) { - xhr.setRequestHeader(name, value) - }) - }) - - xhr.send((self._body === undefined) ? null : self._body) - }) - } - - Body.call(Request.prototype) - - function Response(bodyInit, options) { - if (!options) { - options = {} - } - - if (blobSupport) { - if (typeof bodyInit === 'string') { - this._bodyBlob = new Blob([bodyInit]) - } else { - this._bodyBlob = bodyInit - } - } else { - this._bodyText = bodyInit - } - this.type = 'default' - this.url = null - this.status = options.status - this.statusText = options.statusText - this.headers = options.headers - this.url = options.url || '' - } - - Body.call(Response.prototype) - - self.Headers = Headers; - self.Request = Request; - self.Response = Response; - - self.fetch = function (url, options) { - return new Request(url, options).fetch() - } - self.fetch.polyfill = true -})(); - -/** End of the third-party code */ - -module.exports = self.fetch; diff --git a/Libraries/GeoLocation/Geolocation.ios.js b/Libraries/GeoLocation/Geolocation.ios.js deleted file mode 100644 index 1b57192120f..00000000000 --- a/Libraries/GeoLocation/Geolocation.ios.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule Geolocation - */ -'use strict'; - -var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); -var RCTLocationObserver = require('NativeModulesDeprecated').RKLocationObserver; - -var invariant = require('invariant'); -var logError = require('logError'); -var warning = require('warning'); - -var subscriptions = []; - -var updatesEnabled = false; - -/** - * /!\ ATTENTION /!\ - * You need to add NSLocationWhenInUseUsageDescription key - * in Info.plist to enable geolocation, otherwise it's going - * to *fail silently*! - * \!/ \!/ - * - * Geolocation follows the MDN specification: - * https://developer.mozilla.org/en-US/docs/Web/API/Geolocation - */ -var Geolocation = { - - getCurrentPosition: function(geo_success, geo_error, geo_options) { - invariant( - typeof geo_success === 'function', - 'Must provide a valid geo_success callback.' - ); - RCTLocationObserver.getCurrentPosition( - geo_success, - geo_error || logError, - geo_options || {} - ); - }, - - watchPosition: function(success, error, options) { - if (!updatesEnabled) { - RCTLocationObserver.startObserving(options || {}); - updatesEnabled = true; - } - var watchID = subscriptions.length; - subscriptions.push([ - RCTDeviceEventEmitter.addListener( - 'geolocationDidChange', - success - ), - error ? RCTDeviceEventEmitter.addListener( - 'geolocationError', - error - ) : null, - ]); - return watchID; - }, - - clearWatch: function(watchID) { - var sub = subscriptions[watchID]; - if (!sub) { - // Silently exit when the watchID is invalid or already cleared - // This is consistent with timers - return; - } - sub[0].remove(); - sub[1] && sub[1].remove(); - subscriptions[watchID] = undefined; - var noWatchers = true; - for (var ii = 0; ii < subscriptions.length; ii++) { - if (subscriptions[ii]) { - noWatchers = false; // still valid subscriptions - } - } - if (noWatchers) { - Geolocation.stopObserving(); - } - }, - - stopObserving: function() { - if (updatesEnabled) { - RCTLocationObserver.stopObserving(); - updatesEnabled = false; - for (var ii = 0; ii < subscriptions.length; ii++) { - if (subscriptions[ii]) { - warning('Called stopObserving with existing subscriptions.'); - subscriptions[ii].remove(); - } - } - subscriptions = []; - } - } -} - -module.exports = Geolocation; diff --git a/Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj b/Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj deleted file mode 100644 index 94f9c3f91af..00000000000 --- a/Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj +++ /dev/null @@ -1,256 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 134814061AA4E45400B7C361 /* RCTLocationObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 134814051AA4E45400B7C361 /* RCTLocationObserver.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 58B511D91A9E6C8500147676 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 134814041AA4E45400B7C361 /* RCTLocationObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTLocationObserver.h; sourceTree = ""; }; - 134814051AA4E45400B7C361 /* RCTLocationObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLocationObserver.m; sourceTree = ""; }; - 134814201AA4EA6300B7C361 /* libRCTGeolocation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTGeolocation.a; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 58B511D81A9E6C8500147676 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 134814211AA4EA7D00B7C361 /* Products */ = { - isa = PBXGroup; - children = ( - 134814201AA4EA6300B7C361 /* libRCTGeolocation.a */, - ); - name = Products; - sourceTree = ""; - }; - 58B511D21A9E6C8500147676 = { - isa = PBXGroup; - children = ( - 134814041AA4E45400B7C361 /* RCTLocationObserver.h */, - 134814051AA4E45400B7C361 /* RCTLocationObserver.m */, - 134814211AA4EA7D00B7C361 /* Products */, - ); - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 58B511DA1A9E6C8500147676 /* RCTGeolocation */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTGeolocation" */; - buildPhases = ( - 58B511D71A9E6C8500147676 /* Sources */, - 58B511D81A9E6C8500147676 /* Frameworks */, - 58B511D91A9E6C8500147676 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RCTGeolocation; - productName = RCTDataManager; - productReference = 134814201AA4EA6300B7C361 /* libRCTGeolocation.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 58B511D31A9E6C8500147676 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 58B511DA1A9E6C8500147676 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTGeolocation" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 58B511D21A9E6C8500147676; - productRefGroup = 58B511D21A9E6C8500147676; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 58B511DA1A9E6C8500147676 /* RCTGeolocation */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 58B511D71A9E6C8500147676 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 134814061AA4E45400B7C361 /* RCTLocationObserver.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 58B511ED1A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 58B511EE1A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 58B511F01A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTGeolocation; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 58B511F11A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTGeolocation; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTGeolocation" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511ED1A9E6C8500147676 /* Debug */, - 58B511EE1A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTGeolocation" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511F01A9E6C8500147676 /* Debug */, - 58B511F11A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 58B511D31A9E6C8500147676 /* Project object */; -} diff --git a/Libraries/GeoLocation/RCTLocationObserver.h b/Libraries/GeoLocation/RCTLocationObserver.h deleted file mode 100644 index ad3ba2ce29b..00000000000 --- a/Libraries/GeoLocation/RCTLocationObserver.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTBridgeModule.h" - -@interface RCTLocationObserver : NSObject - -@end diff --git a/Libraries/GeoLocation/RCTLocationObserver.m b/Libraries/GeoLocation/RCTLocationObserver.m deleted file mode 100644 index 0196536406f..00000000000 --- a/Libraries/GeoLocation/RCTLocationObserver.m +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTLocationObserver.h" - -#import -#import -#import - -#import "RCTAssert.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" - -typedef NS_ENUM(NSInteger, RCTPositionErrorCode) { - RCTPositionErrorDenied = 1, - RCTPositionErrorUnavailable, - RCTPositionErrorTimeout, -}; - -#define RCT_DEFAULT_LOCATION_ACCURACY kCLLocationAccuracyHundredMeters - -typedef struct { - NSTimeInterval timeout; - NSTimeInterval maximumAge; - CLLocationAccuracy accuracy; -} RCTLocationOptions; - -static RCTLocationOptions RCTLocationOptionsWithJSON(id json) -{ - NSDictionary *options = [RCTConvert NSDictionary:json]; - return (RCTLocationOptions){ - .timeout = [RCTConvert NSTimeInterval:options[@"timeout"]] ?: INFINITY, - .maximumAge = [RCTConvert NSTimeInterval:options[@"maximumAge"]] ?: INFINITY, - .accuracy = [RCTConvert BOOL:options[@"enableHighAccuracy"]] ? kCLLocationAccuracyBest : RCT_DEFAULT_LOCATION_ACCURACY - }; -} - -static NSDictionary *RCTPositionError(RCTPositionErrorCode code, NSString *msg /* nil for default */) -{ - if (!msg) { - switch (code) { - case RCTPositionErrorDenied: - msg = @"User denied access to location services."; - break; - case RCTPositionErrorUnavailable: - msg = @"Unable to retrieve location."; - break; - case RCTPositionErrorTimeout: - msg = @"The location request timed out."; - break; - } - } - - return @{ - @"code": @(code), - @"message": msg, - @"PERMISSION_DENIED": @(RCTPositionErrorDenied), - @"POSITION_UNAVAILABLE": @(RCTPositionErrorUnavailable), - @"TIMEOUT": @(RCTPositionErrorTimeout) - }; -} - -@interface RCTLocationRequest : NSObject - -@property (nonatomic, copy) RCTResponseSenderBlock successBlock; -@property (nonatomic, copy) RCTResponseSenderBlock errorBlock; -@property (nonatomic, assign) RCTLocationOptions options; -@property (nonatomic, strong) NSTimer *timeoutTimer; - -@end - -@implementation RCTLocationRequest - -- (void)dealloc -{ - [_timeoutTimer invalidate]; -} - -@end - -@interface RCTLocationObserver () - -@end - -@implementation RCTLocationObserver -{ - CLLocationManager *_locationManager; - NSDictionary *_lastLocationEvent; - NSMutableArray *_pendingRequests; - BOOL _observingLocation; - RCTLocationOptions _observerOptions; -} - -@synthesize bridge = _bridge; - -#pragma mark - Lifecycle - -- (instancetype)init -{ - if ((self = [super init])) { - - _locationManager = [[CLLocationManager alloc] init]; - _locationManager.distanceFilter = RCT_DEFAULT_LOCATION_ACCURACY; - _locationManager.delegate = self; - - _pendingRequests = [[NSMutableArray alloc] init]; - } - return self; -} - -- (void)dealloc -{ - [_locationManager stopUpdatingLocation]; -} - -#pragma mark - Private API - -- (void)beginLocationUpdates -{ - // Request location access permission - if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { - [_locationManager requestWhenInUseAuthorization]; - } - - // Start observing location - [_locationManager startUpdatingLocation]; -} - -#pragma mark - Timeout handler - -- (void)timeout:(NSTimer *)timer -{ - RCTLocationRequest *request = timer.userInfo; - NSString *message = [NSString stringWithFormat: @"Unable to fetch location within %zds.", (NSInteger)(timer.timeInterval * 1000.0)]; - request.errorBlock(@[RCTPositionError(RCTPositionErrorTimeout, message)]); - [_pendingRequests removeObject:request]; - - // Stop updating if no pending requests - if (_pendingRequests.count == 0 && !_observingLocation) { - [_locationManager stopUpdatingLocation]; - } -} - -#pragma mark - Public API - -- (void)startObserving:(NSDictionary *)optionsJSON -{ - RCT_EXPORT(); - - dispatch_async(dispatch_get_main_queue(), ^{ - - // Select best options - _observerOptions = RCTLocationOptionsWithJSON(optionsJSON); - for (RCTLocationRequest *request in _pendingRequests) { - _observerOptions.accuracy = MIN(_observerOptions.accuracy, request.options.accuracy); - } - - _locationManager.desiredAccuracy = _observerOptions.accuracy; - [self beginLocationUpdates]; - _observingLocation = YES; - - }); -} - -- (void)stopObserving -{ - RCT_EXPORT(); - - dispatch_async(dispatch_get_main_queue(), ^{ - - // Stop observing - _observingLocation = NO; - - // Stop updating if no pending requests - if (_pendingRequests.count == 0) { - [_locationManager stopUpdatingLocation]; - } - - }); -} - -- (void)getCurrentPosition:(RCTResponseSenderBlock)successBlock - withErrorCallback:(RCTResponseSenderBlock)errorBlock - options:(NSDictionary *)optionsJSON -{ - RCT_EXPORT(); - - if (!successBlock) { - RCTLogError(@"%@.getCurrentPosition called with nil success parameter.", [self class]); - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - - if (![CLLocationManager locationServicesEnabled]) { - if (errorBlock) { - errorBlock(@[ - RCTPositionError(RCTPositionErrorUnavailable, @"Location services disabled.") - ]); - return; - } - } - - if (![CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) { - if (errorBlock) { - errorBlock(@[ - RCTPositionError(RCTPositionErrorDenied, nil) - ]); - return; - } - } - - // Get options - RCTLocationOptions options = RCTLocationOptionsWithJSON(optionsJSON); - - // Check if previous recorded location exists and is good enough - if (_lastLocationEvent && - CFAbsoluteTimeGetCurrent() - [RCTConvert NSTimeInterval:_lastLocationEvent[@"timestamp"]] < options.maximumAge && - [_lastLocationEvent[@"coords"][@"accuracy"] doubleValue] >= options.accuracy) { - - // Call success block with most recent known location - successBlock(@[_lastLocationEvent]); - return; - } - - // Create request - RCTLocationRequest *request = [[RCTLocationRequest alloc] init]; - request.successBlock = successBlock; - request.errorBlock = errorBlock ?: ^(NSArray *args){}; - request.options = options; - request.timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:options.timeout - target:self - selector:@selector(timeout:) - userInfo:request - repeats:NO]; - [_pendingRequests addObject:request]; - - // Configure location manager and begin updating location - _locationManager.desiredAccuracy = MIN(_locationManager.desiredAccuracy, options.accuracy); - [self beginLocationUpdates]; - - }); -} - -#pragma mark - CLLocationManagerDelegate - -- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations -{ - // Create event - CLLocation *location = [locations lastObject]; - _lastLocationEvent = @{ - @"coords": @{ - @"latitude": @(location.coordinate.latitude), - @"longitude": @(location.coordinate.longitude), - @"altitude": @(location.altitude), - @"accuracy": @(location.horizontalAccuracy), - @"altitudeAccuracy": @(location.verticalAccuracy), - @"heading": @(location.course), - @"speed": @(location.speed), - }, - @"timestamp": @(CFAbsoluteTimeGetCurrent() * 1000.0) // in ms - }; - - // Send event - if (_observingLocation) { - [_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationDidChange" - body:_lastLocationEvent]; - } - - // Fire all queued callbacks - for (RCTLocationRequest *request in _pendingRequests) { - request.successBlock(@[_lastLocationEvent]); - } - [_pendingRequests removeAllObjects]; - - // Stop updating if not not observing - if (!_observingLocation) { - [_locationManager stopUpdatingLocation]; - } - - // Reset location accuracy - _locationManager.desiredAccuracy = RCT_DEFAULT_LOCATION_ACCURACY; -} - -- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error -{ - // Check error type - NSDictionary *jsError = nil; - switch (error.code) { - case kCLErrorDenied: - jsError = RCTPositionError(RCTPositionErrorDenied, nil); - break; - case kCLErrorNetwork: - jsError = RCTPositionError(RCTPositionErrorUnavailable, @"Unable to retrieve location due to a network failure"); - break; - case kCLErrorLocationUnknown: - default: - jsError = RCTPositionError(RCTPositionErrorUnavailable, nil); - break; - } - - // Send event - if (_observingLocation) { - [_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationError" - body:jsError]; - } - - // Fire all queued error callbacks - for (RCTLocationRequest *request in _pendingRequests) { - request.errorBlock(@[jsError]); - } - [_pendingRequests removeAllObjects]; - - // Reset location accuracy - _locationManager.desiredAccuracy = RCT_DEFAULT_LOCATION_ACCURACY; -} - -@end diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js deleted file mode 100644 index f8ab583a9ea..00000000000 --- a/Libraries/Image/Image.ios.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule Image - */ -'use strict'; - -var EdgeInsetsPropType = require('EdgeInsetsPropType'); -var NativeMethodsMixin = require('NativeMethodsMixin'); -var NativeModulesDeprecated = require('NativeModulesDeprecated'); -var PropTypes = require('ReactPropTypes'); -var ImageResizeMode = require('ImageResizeMode'); -var ImageStylePropTypes = require('ImageStylePropTypes'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheet = require('StyleSheet'); -var StyleSheetPropType = require('StyleSheetPropType'); - -var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); -var flattenStyle = require('flattenStyle'); -var insetsDiffer = require('insetsDiffer'); -var invariant = require('invariant'); -var merge = require('merge'); -var warning = require('warning'); - -/** - * 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. - * - * Example usage: - * - * ``` - * renderImages: function() { - * return ( - * - * - * - * - * ); - * }, - * ``` - */ - -var Image = React.createClass({ - propTypes: { - source: PropTypes.shape({ - /** - * A string representing the resource identifier for the image, which - * could be an http address, a local file path, or the name of a static image - * resource (which should be wrapped in the `ix` function). - */ - uri: PropTypes.string, - }).isRequired, - /** - * accessible - Whether this element should be revealed as an accessible - * element. - */ - accessible: PropTypes.bool, - /** - * accessibilityLabel - Custom string to display for accessibility. - */ - accessibilityLabel: PropTypes.string, - /** - * capInsets - 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: - * - * https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/index.html#//apple_ref/occ/instm/UIImage/resizableImageWithCapInsets: - */ - capInsets: EdgeInsetsPropType, - style: StyleSheetPropType(ImageStylePropTypes), - /** - * testID - A unique identifier for this element to be used in UI Automation - * testing scripts. - */ - testID: PropTypes.string, - }, - - statics: { - resizeMode: ImageResizeMode, - }, - - mixins: [NativeMethodsMixin], - - /** - * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We - * make `this` look like an actual native component class. - */ - viewConfig: { - uiViewClassName: 'UIView', - validAttributes: ReactIOSViewAttributes.UIView - }, - - render: function() { - var style = flattenStyle([styles.base, this.props.style]); - var source = this.props.source; - var isNetwork = source.uri && source.uri.match(/^https?:/); - invariant( - !(isNetwork && source.isStatic), - 'static image uris cannot start with "http": "' + source.uri + '"' - ); - var isStored = !source.isStatic && !isNetwork; - var RawImage = isNetwork ? RKNetworkImage : RKStaticImage; - - if (this.props.style && this.props.style.tintColor) { - warning(RawImage === RKStaticImage, 'tintColor style only supported on static images.'); - } - - var contentModes = NativeModulesDeprecated.RKUIManager.UIView.ContentMode; - var resizeMode; - if (style.resizeMode === ImageResizeMode.stretch) { - resizeMode = contentModes.ScaleToFill; - } else if (style.resizeMode === ImageResizeMode.contain) { - resizeMode = contentModes.ScaleAspectFit; - } else { // ImageResizeMode.cover or undefined - resizeMode = contentModes.ScaleAspectFill; - } - - var nativeProps = merge(this.props, { - style, - resizeMode, - tintColor: style.tintColor, - }); - - if (isStored) { - nativeProps.imageTag = source.uri; - } else { - nativeProps.src = source.uri; - } - return ; - } -}); - -var styles = StyleSheet.create({ - base: { - overflow: 'hidden', - }, -}); - -var CommonImageViewAttributes = merge(ReactIOSViewAttributes.UIView, { - accessible: true, - accessibilityLabel: true, - capInsets: {diff: insetsDiffer}, // UIEdgeInsets=UIEdgeInsetsZero - imageTag: true, - resizeMode: true, - src: true, - testID: PropTypes.string, -}); - -var RKStaticImage = createReactIOSNativeComponentClass({ - validAttributes: merge(CommonImageViewAttributes, { tintColor: true }), - uiViewClassName: 'RCTStaticImage', -}); - -var RKNetworkImage = createReactIOSNativeComponentClass({ - validAttributes: merge(CommonImageViewAttributes, { defaultImageSrc: true }), - uiViewClassName: 'RCTNetworkImageView', -}); - -module.exports = Image; diff --git a/Libraries/Image/ImageResizeMode.js b/Libraries/Image/ImageResizeMode.js deleted file mode 100644 index 813e7016e8d..00000000000 --- a/Libraries/Image/ImageResizeMode.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ImageResizeMode - */ -'use strict'; - -var keyMirror = require('keyMirror'); - -/** - * ImageResizeMode - Enum for different image resizing modes, set via - * `resizeMode` style property on `` components. - */ -var ImageResizeMode = keyMirror({ - /** - * contain - The image will be resized such that it will be completely - * visible, contained within the frame of the View. - */ - contain: null, - /** - * cover - The image will be resized such that the entire area of the view - * is covered by the image, potentially clipping parts of the image. - */ - cover: null, - /** - * stretch - The image will be stretched to fill the entire frame of the - * view without clipping. This may change the aspect ratio of the image, - * distoring it. Only supported on iOS. - */ - stretch: null, -}); - -module.exports = ImageResizeMode; diff --git a/Libraries/Image/ImageStylePropTypes.js b/Libraries/Image/ImageStylePropTypes.js deleted file mode 100644 index 3c67a77958b..00000000000 --- a/Libraries/Image/ImageStylePropTypes.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ImageStylePropTypes - */ -'use strict'; - -var ImageResizeMode = require('ImageResizeMode'); -var LayoutPropTypes = require('LayoutPropTypes'); -var ReactPropTypes = require('ReactPropTypes'); - -var merge = require('merge'); - -var ImageStylePropTypes = merge( - LayoutPropTypes, - { - resizeMode: ReactPropTypes.oneOf(Object.keys(ImageResizeMode)), - backgroundColor: ReactPropTypes.string, - borderColor: ReactPropTypes.string, - borderWidth: ReactPropTypes.number, - borderRadius: ReactPropTypes.number, - - // iOS-Specific style to "tint" an image. - // It changes the color of all the non-transparent pixels to the tintColor - tintColor: ReactPropTypes.string, - opacity: ReactPropTypes.number, - } -); - -// Image doesn't support padding correctly (#4841912) -var unsupportedProps = Object.keys({ - padding: null, - paddingTop: null, - paddingLeft: null, - paddingRight: null, - paddingBottom: null, - paddingVertical: null, - paddingHorizontal: null, -}); - -for (var key in unsupportedProps) { - delete ImageStylePropTypes[key]; -} - -module.exports = ImageStylePropTypes; diff --git a/Libraries/Image/RCTGIFImage.h b/Libraries/Image/RCTGIFImage.h deleted file mode 100644 index 38f2904621a..00000000000 --- a/Libraries/Image/RCTGIFImage.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import -#import -#import - -extern CAKeyframeAnimation *RCTGIFImageWithData(NSData *data); -extern CAKeyframeAnimation *RCTGIFImageWithFileURL(NSURL *URL); diff --git a/Libraries/Image/RCTGIFImage.m b/Libraries/Image/RCTGIFImage.m deleted file mode 100644 index 8fe49f6bc70..00000000000 --- a/Libraries/Image/RCTGIFImage.m +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTGIFImage.h" - -#import "RCTLog.h" - -static CAKeyframeAnimation *RCTGIFImageWithImageSource(CGImageSourceRef imageSource) -{ - if (!UTTypeConformsTo(CGImageSourceGetType(imageSource), kUTTypeGIF)) { - CFRelease(imageSource); - return nil; - } - - NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(imageSource, NULL); - NSUInteger loopCount = [properties[(id)kCGImagePropertyGIFDictionary][(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue]; - - size_t imageCount = CGImageSourceGetCount(imageSource); - NSTimeInterval duration = 0; - NSMutableArray *delays = [NSMutableArray arrayWithCapacity:imageCount]; - NSMutableArray *images = [NSMutableArray arrayWithCapacity:imageCount]; - for (size_t i = 0; i < imageCount; i++) { - CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, i, NULL); - NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imageSource, i, NULL); - NSDictionary *frameGIFProperties = frameProperties[(id)kCGImagePropertyGIFDictionary]; - - const NSTimeInterval kDelayTimeIntervalDefault = 0.1; - NSNumber *delayTime = frameGIFProperties[(id)kCGImagePropertyGIFUnclampedDelayTime] ?: frameGIFProperties[(id)kCGImagePropertyGIFDelayTime]; - if (delayTime == nil) { - if (i == 0) { - delayTime = @(kDelayTimeIntervalDefault); - } else { - delayTime = delays[i - 1]; - } - } - - const NSTimeInterval kDelayTimeIntervalMinimum = 0.02; - if (delayTime.floatValue < (float)kDelayTimeIntervalMinimum - FLT_EPSILON) { - delayTime = @(kDelayTimeIntervalDefault); - } - - duration += delayTime.doubleValue; - delays[i] = delayTime; - images[i] = (__bridge_transfer id)image; - } - - NSMutableArray *keyTimes = [NSMutableArray arrayWithCapacity:delays.count]; - NSTimeInterval runningDuration = 0; - for (NSNumber *delayNumber in delays) { - [keyTimes addObject:@(runningDuration / duration)]; - runningDuration += delayNumber.doubleValue; - } - - [keyTimes addObject:@1.0]; - - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; - animation.calculationMode = kCAAnimationDiscrete; - animation.repeatCount = loopCount == 0 ? HUGE_VALF : loopCount; - animation.keyTimes = keyTimes; - animation.values = images; - animation.duration = duration; - return animation; -} - -CAKeyframeAnimation *RCTGIFImageWithData(NSData *data) -{ - if (data.length == 0) { - return nil; - } - - CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)data, NULL); - CAKeyframeAnimation *animation = RCTGIFImageWithImageSource(imageSource); - CFRelease(imageSource); - return animation; -} - -CAKeyframeAnimation *RCTGIFImageWithFileURL(NSURL *URL) -{ - if (!URL) { - return nil; - } - - if (![URL isFileURL]) { - RCTLogError(@"Loading remote image URLs synchronously is a really bad idea."); - return nil; - } - - CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)URL, NULL); - CAKeyframeAnimation *animation = RCTGIFImageWithImageSource(imageSource); - CFRelease(imageSource); - return animation; -} diff --git a/Libraries/Image/RCTImage.xcodeproj/project.pbxproj b/Libraries/Image/RCTImage.xcodeproj/project.pbxproj deleted file mode 100644 index 409d61d32a9..00000000000 --- a/Libraries/Image/RCTImage.xcodeproj/project.pbxproj +++ /dev/null @@ -1,286 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1304D5AB1AA8C4A30002E2BE /* RCTStaticImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5A81AA8C4A30002E2BE /* RCTStaticImage.m */; }; - 1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */; }; - 1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */; }; - 58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */; }; - 58B511901A9E6BD600147676 /* RCTNetworkImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118C1A9E6BD600147676 /* RCTNetworkImageView.m */; }; - 58B511911A9E6BD600147676 /* RCTNetworkImageViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5118E1A9E6BD600147676 /* RCTNetworkImageViewManager.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 58B5115B1A9E6B3D00147676 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1304D5A71AA8C4A30002E2BE /* RCTStaticImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTStaticImage.h; sourceTree = ""; }; - 1304D5A81AA8C4A30002E2BE /* RCTStaticImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTStaticImage.m; sourceTree = ""; }; - 1304D5A91AA8C4A30002E2BE /* RCTStaticImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTStaticImageManager.h; sourceTree = ""; }; - 1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTStaticImageManager.m; sourceTree = ""; }; - 1304D5B01AA8C50D0002E2BE /* RCTGIFImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTGIFImage.h; sourceTree = ""; }; - 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTGIFImage.m; sourceTree = ""; }; - 58B5115D1A9E6B3D00147676 /* libRCTImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 58B511891A9E6BD600147676 /* RCTImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageDownloader.h; sourceTree = ""; }; - 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageDownloader.m; sourceTree = ""; }; - 58B5118B1A9E6BD600147676 /* RCTNetworkImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNetworkImageView.h; sourceTree = ""; }; - 58B5118C1A9E6BD600147676 /* RCTNetworkImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNetworkImageView.m; sourceTree = ""; }; - 58B5118D1A9E6BD600147676 /* RCTNetworkImageViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNetworkImageViewManager.h; sourceTree = ""; }; - 58B5118E1A9E6BD600147676 /* RCTNetworkImageViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNetworkImageViewManager.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 58B5115A1A9E6B3D00147676 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 58B511541A9E6B3D00147676 = { - isa = PBXGroup; - children = ( - 1304D5B01AA8C50D0002E2BE /* RCTGIFImage.h */, - 1304D5B11AA8C50D0002E2BE /* RCTGIFImage.m */, - 58B511891A9E6BD600147676 /* RCTImageDownloader.h */, - 58B5118A1A9E6BD600147676 /* RCTImageDownloader.m */, - 58B5118B1A9E6BD600147676 /* RCTNetworkImageView.h */, - 58B5118C1A9E6BD600147676 /* RCTNetworkImageView.m */, - 58B5118D1A9E6BD600147676 /* RCTNetworkImageViewManager.h */, - 58B5118E1A9E6BD600147676 /* RCTNetworkImageViewManager.m */, - 1304D5A71AA8C4A30002E2BE /* RCTStaticImage.h */, - 1304D5A81AA8C4A30002E2BE /* RCTStaticImage.m */, - 1304D5A91AA8C4A30002E2BE /* RCTStaticImageManager.h */, - 1304D5AA1AA8C4A30002E2BE /* RCTStaticImageManager.m */, - 58B5115E1A9E6B3D00147676 /* Products */, - ); - sourceTree = ""; - }; - 58B5115E1A9E6B3D00147676 /* Products */ = { - isa = PBXGroup; - children = ( - 58B5115D1A9E6B3D00147676 /* libRCTImage.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 58B5115C1A9E6B3D00147676 /* RCTImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58B511711A9E6B3D00147676 /* Build configuration list for PBXNativeTarget "RCTImage" */; - buildPhases = ( - 58B511591A9E6B3D00147676 /* Sources */, - 58B5115A1A9E6B3D00147676 /* Frameworks */, - 58B5115B1A9E6B3D00147676 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RCTImage; - productName = RCTNetworkImage; - productReference = 58B5115D1A9E6B3D00147676 /* libRCTImage.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 58B511551A9E6B3D00147676 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 58B5115C1A9E6B3D00147676 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 58B511581A9E6B3D00147676 /* Build configuration list for PBXProject "RCTImage" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 58B511541A9E6B3D00147676; - productRefGroup = 58B5115E1A9E6B3D00147676 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 58B5115C1A9E6B3D00147676 /* RCTImage */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 58B511591A9E6B3D00147676 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 58B5118F1A9E6BD600147676 /* RCTImageDownloader.m in Sources */, - 58B511911A9E6BD600147676 /* RCTNetworkImageViewManager.m in Sources */, - 1304D5AC1AA8C4A30002E2BE /* RCTStaticImageManager.m in Sources */, - 58B511901A9E6BD600147676 /* RCTNetworkImageView.m in Sources */, - 1304D5B21AA8C50D0002E2BE /* RCTGIFImage.m in Sources */, - 1304D5AB1AA8C4A30002E2BE /* RCTStaticImage.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 58B5116F1A9E6B3D00147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 58B511701A9E6B3D00147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 58B511721A9E6B3D00147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/UIExplorer-gjaibsjtheitasdxdtcvxxqavkvy/Build/Products/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTImage; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 58B511731A9E6B3D00147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/UIExplorer-gjaibsjtheitasdxdtcvxxqavkvy/Build/Products/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTImage; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 58B511581A9E6B3D00147676 /* Build configuration list for PBXProject "RCTImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B5116F1A9E6B3D00147676 /* Debug */, - 58B511701A9E6B3D00147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511711A9E6B3D00147676 /* Build configuration list for PBXNativeTarget "RCTImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511721A9E6B3D00147676 /* Debug */, - 58B511731A9E6B3D00147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 58B511551A9E6B3D00147676 /* Project object */; -} diff --git a/Libraries/Image/RCTImageDownloader.h b/Libraries/Image/RCTImageDownloader.h deleted file mode 100644 index b525ea1a776..00000000000 --- a/Libraries/Image/RCTImageDownloader.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -typedef void (^RCTDataDownloadBlock)(NSData *data, NSError *error); -typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error); - -@interface RCTImageDownloader : NSObject - -+ (instancetype)sharedInstance; - -- (id)downloadDataForURL:(NSURL *)url - block:(RCTDataDownloadBlock)block; - -- (id)downloadImageForURL:(NSURL *)url - size:(CGSize)size - scale:(CGFloat)scale - block:(RCTImageDownloadBlock)block; - -- (void)cancelDownload:(id)downloadToken; - -@end diff --git a/Libraries/Image/RCTImageDownloader.m b/Libraries/Image/RCTImageDownloader.m deleted file mode 100644 index ea801dea74d..00000000000 --- a/Libraries/Image/RCTImageDownloader.m +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTImageDownloader.h" - -#import "RCTCache.h" -#import "RCTUtils.h" - -// TODO: something a bit more sophisticated - -typedef void (^RCTCachedDataDownloadBlock)(BOOL cached, NSData *data, NSError *error); - -@implementation RCTImageDownloader -{ - RCTCache *_cache; - NSMutableDictionary *_pendingBlocks; -} - -+ (instancetype)sharedInstance -{ - RCTAssertMainThread(); - static RCTImageDownloader *sharedInstance; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedInstance = [[self alloc] init]; - }); - return sharedInstance; -} - -- (instancetype)init -{ - if ((self = [super init])) { - _cache = [[RCTCache alloc] initWithName:@"RCTImageDownloader"]; - _pendingBlocks = [NSMutableDictionary dictionary]; - } - return self; -} - -- (NSString *)cacheKeyForURL:(NSURL *)url -{ - return url.absoluteString; -} - -- (id)_downloadDataForURL:(NSURL *)url block:(RCTCachedDataDownloadBlock)block -{ - NSString *cacheKey = [self cacheKeyForURL:url]; - - __block BOOL cancelled = NO; - __block NSURLSessionDataTask *task = nil; - dispatch_block_t cancel = ^{ - cancelled = YES; - - NSMutableArray *pendingBlocks = _pendingBlocks[cacheKey]; - [pendingBlocks removeObject:block]; - - if (task) { - [task cancel]; - task = nil; - } - }; - - NSMutableArray *pendingBlocks = _pendingBlocks[cacheKey]; - if (pendingBlocks) { - [pendingBlocks addObject:block]; - } else { - _pendingBlocks[cacheKey] = [NSMutableArray arrayWithObject:block]; - - __weak RCTImageDownloader *weakSelf = self; - RCTCachedDataDownloadBlock runBlocks = ^(BOOL cached, NSData *data, NSError *error) { - RCTImageDownloader *strongSelf = weakSelf; - NSArray *blocks = strongSelf->_pendingBlocks[cacheKey]; - [strongSelf->_pendingBlocks removeObjectForKey:cacheKey]; - - for (RCTCachedDataDownloadBlock block in blocks) { - block(cached, data, error); - } - }; - - if ([_cache hasDataForKey:cacheKey]) { - [_cache fetchDataForKey:cacheKey completionHandler:^(NSData *data) { - if (!cancelled) runBlocks(YES, data, nil); - }]; - } else { - task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if (!cancelled) runBlocks(NO, data, error); - }]; - - [task resume]; - } - } - - return [cancel copy]; -} - -- (id)downloadDataForURL:(NSURL *)url block:(RCTDataDownloadBlock)block -{ - NSString *cacheKey = [self cacheKeyForURL:url]; - __weak RCTImageDownloader *weakSelf = self; - return [self _downloadDataForURL:url block:^(BOOL cached, NSData *data, NSError *error) { - if (!cached) { - RCTImageDownloader *strongSelf = weakSelf; - [strongSelf->_cache setData:data forKey:cacheKey]; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - block(data, error); - }); - }]; -} - -- (id)downloadImageForURL:(NSURL *)url size:(CGSize)size scale:(CGFloat)scale block:(RCTImageDownloadBlock)block -{ - return [self downloadDataForURL:url block:^(NSData *data, NSError *error) { - - UIImage *image = [UIImage imageWithData:data scale:scale]; - if (image) { - - // Resize (TODO: should we take aspect ratio into account?) - CGSize imageSize = size; - if (CGSizeEqualToSize(imageSize, CGSizeZero)) { - imageSize = image.size; - } else { - imageSize = (CGSize){ - MIN(size.width, image.size.width), - MIN(size.height, image.size.height) - }; - } - - // Rescale image if required size is smaller - CGFloat imageScale = scale; - if (imageScale == 0 || imageScale < image.scale) { - imageScale = image.scale; - } - - // Decompress image at required size - UIGraphicsBeginImageContextWithOptions(imageSize, NO, imageScale); - [image drawInRect:(CGRect){{0, 0}, imageSize}]; - image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - } - - // TODO: should we cache the decompressed image? - - dispatch_async(dispatch_get_main_queue(), ^{ - block(image, nil); - }); - }]; -} - -- (void)cancelDownload:(id)downloadToken -{ - if (downloadToken) { - dispatch_block_t block = (id)downloadToken; - block(); - } -} - -@end diff --git a/Libraries/Image/RCTNetworkImage.podspec b/Libraries/Image/RCTNetworkImage.podspec deleted file mode 100644 index 47eb0e5f6cc..00000000000 --- a/Libraries/Image/RCTNetworkImage.podspec +++ /dev/null @@ -1,28 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'RCTNetworkImage' - spec.version = '0.0.1' - spec.summary = 'Provides basic Text capabilities in ReactNative apps.' - spec.description = <<-DESC - Text can be rendered in ReactNative apps with the component using this module. - DESC - spec.homepage = 'https://facebook.github.io/react-native/' - spec.license = { :type => 'BSD' } - spec.author = 'Facebook' - spec.platform = :ios, '7.0' - spec.requires_arc = true - spec.source_files = '**/*.{h,m,c}' - spec.dependency "ReactKit", "~> 0.0.1" - - # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - # - # Link your library with frameworks, or libraries. Libraries do not include - # the lib prefix of their name. - # - - # s.framework = "SomeFramework" - # s.frameworks = "SomeFramework", "AnotherFramework" - - # s.library = "iconv" - #spec.libraries = "RCTNetworkImage", "ReactKit" - -end diff --git a/Libraries/Image/RCTNetworkImageView.h b/Libraries/Image/RCTNetworkImageView.h deleted file mode 100644 index 920bf705c5f..00000000000 --- a/Libraries/Image/RCTNetworkImageView.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@class RCTImageDownloader; - -@interface RCTNetworkImageView : UIView - -- (instancetype)initWithFrame:(CGRect)frame - imageDownloader:(RCTImageDownloader *)imageDownloader NS_DESIGNATED_INITIALIZER; - -/** - * An image that will appear while the view is loading the image from the network, - * or when imageURL is nil. Defaults to nil. - */ -@property (nonatomic, strong) UIImage *defaultImage; - -/** - * Specify a URL for an image. The image will be asynchronously loaded and displayed. - */ -@property (nonatomic, strong) NSURL *imageURL; - -/** - * By default, changing imageURL will reset whatever existing image was present - * and revert to defaultImage while the new image loads. In certain obscure cases you - * may want to disable this behavior and instead keep displaying the previous image - * while the new one loads. In this case, pass NO for resetToDefaultImageWhileLoading. - * (If you set imageURL to nil, however, resetToDefaultImageWhileLoading is ignored; - * that will always reset to the default image.) - */ -- (void)setImageURL:(NSURL *)imageURL resetToDefaultImageWhileLoading:(BOOL)reset; - -@end diff --git a/Libraries/Image/RCTNetworkImageView.m b/Libraries/Image/RCTNetworkImageView.m deleted file mode 100644 index 1b19dfe1901..00000000000 --- a/Libraries/Image/RCTNetworkImageView.m +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTNetworkImageView.h" - -#import "RCTConvert.h" -#import "RCTGIFImage.h" -#import "RCTImageDownloader.h" -#import "RCTUtils.h" - -@implementation RCTNetworkImageView -{ - BOOL _deferred; - NSURL *_imageURL; - NSURL *_deferredImageURL; - NSUInteger _deferSentinel; - RCTImageDownloader *_imageDownloader; - id _downloadToken; -} - -- (instancetype)initWithFrame:(CGRect)frame imageDownloader:(RCTImageDownloader *)imageDownloader -{ - self = [super initWithFrame:frame]; - if (self) { - _deferSentinel = 0; - _imageDownloader = imageDownloader; - self.userInteractionEnabled = NO; - } - return self; -} - -- (NSURL *)imageURL -{ - // We clear our backing layer's imageURL when we are not in a window for a while, - // to make sure we don't consume network resources while offscreen. - // However we don't want to expose this hackery externally. - return _deferred ? _deferredImageURL : _imageURL; -} - -- (void)setImageURL:(NSURL *)imageURL resetToDefaultImageWhileLoading:(BOOL)reset -{ - if (_deferred) { - _deferredImageURL = imageURL; - } else { - if (_downloadToken) { - [_imageDownloader cancelDownload:_downloadToken]; - _downloadToken = nil; - } - if (reset) { - self.layer.contentsScale = _defaultImage.scale; - self.layer.contents = (__bridge id)_defaultImage.CGImage; - self.layer.minificationFilter = kCAFilterTrilinear; - self.layer.magnificationFilter = kCAFilterTrilinear; - } - if ([imageURL.pathExtension caseInsensitiveCompare:@"gif"] == NSOrderedSame) { - _downloadToken = [_imageDownloader downloadDataForURL:imageURL block:^(NSData *data, NSError *error) { - if (data) { - CAKeyframeAnimation *animation = RCTGIFImageWithData(data); - CGImageRef firstFrame = (__bridge CGImageRef)animation.values.firstObject; - self.layer.bounds = CGRectMake(0, 0, CGImageGetWidth(firstFrame), CGImageGetHeight(firstFrame)); - self.layer.contentsScale = 1.0; - self.layer.contentsGravity = kCAGravityResizeAspect; - self.layer.minificationFilter = kCAFilterLinear; - self.layer.magnificationFilter = kCAFilterLinear; - [self.layer addAnimation:animation forKey:@"contents"]; - } - // TODO: handle errors - }]; - } else { - _downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() block:^(UIImage *image, NSError *error) { - if (image) { - self.layer.contentsScale = image.scale; - self.layer.contents = (__bridge id)image.CGImage; - } - // TODO: handle errors - }]; - } - } -} - -- (void)setImageURL:(NSURL *)imageURL -{ - [self setImageURL:imageURL resetToDefaultImageWhileLoading:YES]; -} - -- (void)willMoveToWindow:(UIWindow *)newWindow -{ - [super willMoveToWindow:newWindow]; - if (newWindow != nil && _deferredImageURL) { - // Immediately exit deferred mode and restore the imageURL that we saved when we went offscreen. - [self setImageURL:_deferredImageURL resetToDefaultImageWhileLoading:YES]; - _deferredImageURL = nil; - } -} - -- (void)_enterDeferredModeIfNeededForSentinel:(NSUInteger)sentinel -{ - if (self.window == nil && _deferSentinel == sentinel) { - _deferred = YES; - [_imageDownloader cancelDownload:_downloadToken]; - _downloadToken = nil; - _deferredImageURL = _imageURL; - _imageURL = nil; - } -} - -- (void)didMoveToWindow -{ - [super didMoveToWindow]; - if (self.window == nil) { - __weak RCTNetworkImageView *weakSelf = self; - NSUInteger sentinelAtDispatchTime = ++_deferSentinel; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){ - [weakSelf _enterDeferredModeIfNeededForSentinel:sentinelAtDispatchTime]; - }); - } -} - -@end diff --git a/Libraries/Image/RCTNetworkImageViewManager.h b/Libraries/Image/RCTNetworkImageViewManager.h deleted file mode 100644 index 5b34e60602a..00000000000 --- a/Libraries/Image/RCTNetworkImageViewManager.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTNetworkImageViewManager : RCTViewManager - -@end - diff --git a/Libraries/Image/RCTNetworkImageViewManager.m b/Libraries/Image/RCTNetworkImageViewManager.m deleted file mode 100644 index 96d09c0cd8e..00000000000 --- a/Libraries/Image/RCTNetworkImageViewManager.m +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTNetworkImageViewManager.h" - -#import "RCTNetworkImageView.h" - -#import "RCTConvert.h" -#import "RCTUtils.h" - -#import "RCTImageDownloader.h" - -@implementation RCTNetworkImageViewManager - -- (UIView *)view -{ - RCTNetworkImageView *view = [[RCTNetworkImageView alloc] initWithFrame:CGRectZero imageDownloader:[RCTImageDownloader sharedInstance]]; - view.contentMode = UIViewContentModeScaleAspectFill; - return view; -} - -RCT_REMAP_VIEW_PROPERTY(defaultImageSrc, defaultImage) -RCT_REMAP_VIEW_PROPERTY(src, imageURL) -RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode) - -@end diff --git a/Libraries/Image/RCTStaticImage.h b/Libraries/Image/RCTStaticImage.h deleted file mode 100644 index 75906be39bb..00000000000 --- a/Libraries/Image/RCTStaticImage.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface RCTStaticImage : UIImageView - -@property (nonatomic, assign) UIEdgeInsets capInsets; -@property (nonatomic, assign) UIImageRenderingMode renderingMode; - -@end diff --git a/Libraries/Image/RCTStaticImage.m b/Libraries/Image/RCTStaticImage.m deleted file mode 100644 index b57b763ed5e..00000000000 --- a/Libraries/Image/RCTStaticImage.m +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTStaticImage.h" - -@implementation RCTStaticImage - -- (void)_updateImage -{ - UIImage *image = self.image; - if (!image) { - return; - } - - // Apply rendering mode - if (_renderingMode != image.renderingMode) { - image = [image imageWithRenderingMode:_renderingMode]; - } - - // Applying capInsets of 0 will switch the "resizingMode" of the image to "tile" which is undesired - if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, _capInsets)) { - image = [image resizableImageWithCapInsets:_capInsets resizingMode:UIImageResizingModeStretch]; - } - - // Apply trilinear filtering to smooth out mis-sized images - self.layer.minificationFilter = kCAFilterTrilinear; - self.layer.magnificationFilter = kCAFilterTrilinear; - - super.image = image; -} - -- (void)setImage:(UIImage *)image -{ - if (image != super.image) { - super.image = image; - [self _updateImage]; - } -} - -- (void)setCapInsets:(UIEdgeInsets)capInsets -{ - if (!UIEdgeInsetsEqualToEdgeInsets(_capInsets, capInsets)) { - _capInsets = capInsets; - [self _updateImage]; - } -} - -- (void)setRenderingMode:(UIImageRenderingMode)renderingMode -{ - if (_renderingMode != renderingMode) { - _renderingMode = renderingMode; - [self _updateImage]; - } -} - -@end diff --git a/Libraries/Image/RCTStaticImageManager.h b/Libraries/Image/RCTStaticImageManager.h deleted file mode 100644 index ab89cb96b8a..00000000000 --- a/Libraries/Image/RCTStaticImageManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTStaticImageManager : RCTViewManager - -@end diff --git a/Libraries/Image/RCTStaticImageManager.m b/Libraries/Image/RCTStaticImageManager.m deleted file mode 100644 index b83d8c42b67..00000000000 --- a/Libraries/Image/RCTStaticImageManager.m +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTStaticImageManager.h" - -#import - -#import "RCTConvert.h" -#import "RCTGIFImage.h" -#import "RCTStaticImage.h" - -@implementation RCTStaticImageManager - -- (UIView *)view -{ - return [[RCTStaticImage alloc] init]; -} - -RCT_EXPORT_VIEW_PROPERTY(capInsets) -RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode) -RCT_CUSTOM_VIEW_PROPERTY(src, RCTStaticImage *) -{ - if (json) { - if ([[[json description] pathExtension] caseInsensitiveCompare:@"gif"] == NSOrderedSame) { - [view.layer addAnimation:RCTGIFImageWithFileURL([RCTConvert NSURL:json]) forKey:@"contents"]; - } else { - view.image = [RCTConvert UIImage:json]; - } - } else { - view.image = defaultView.image; - } -} -RCT_CUSTOM_VIEW_PROPERTY(tintColor, RCTStaticImage *) -{ - if (json) { - view.renderingMode = UIImageRenderingModeAlwaysTemplate; - view.tintColor = [RCTConvert UIColor:json]; - } else { - view.renderingMode = defaultView.renderingMode; - view.tintColor = defaultView.tintColor; - } -} - -@end diff --git a/Libraries/Image/ix.js b/Libraries/Image/ix.js deleted file mode 100644 index 52cbbc4e2ac..00000000000 --- a/Libraries/Image/ix.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ix - */ -'use strict'; - -/** - * This function is used to mark string literals that are image paths. The - * return value is a blob of data that core image components understand how to - * render. - * - * The arguments to ix() must be string literals so that they can be parsed - * statically. - * - * @param string Image path to render - * @return object Data blob to be used by core UI components - */ -function ix(path) { - return { - uri: path, - isStatic: true, - }; -} - -module.exports = ix; diff --git a/Libraries/Interaction/InteractionManager.js b/Libraries/Interaction/InteractionManager.js deleted file mode 100644 index 3e895f3b061..00000000000 --- a/Libraries/Interaction/InteractionManager.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule InteractionManager - */ -'use strict'; - -var ErrorUtils = require('ErrorUtils'); -var EventEmitter = require('EventEmitter'); -var Set = require('Set'); - -var invariant = require('invariant'); -var keyMirror = require('keyMirror'); -var setImmediate = require('setImmediate'); - -/** - * InteractionManager allows long-running work to be scheduled after any - * interactions/animations have completed. In particular, this allows JavaScript - * animations to run smoothly. - * - * Applications can schedule tasks to run after interactions with the following: - * - * InteractionManager.runAfterInteractions(() => { - * // ...long-running synchronous task... - * }); - * - * Compare this to other scheduling alternatives: - * - requestAnimationFrame(): for code that animates a view over time. - * - setImmediate/setTimeout(): run code later, note this may delay animations. - * - runAfterInteractions(): run code later, without delaying active animations. - * - * The touch handling system considers one or more active touches to be an - * 'interaction' and will delay `runAfterInteractions()` callbacks until all - * touches have ended or been cancelled. - * - * InteractionManager also allows applications to register animations by - * creating an interaction 'handle' on animation start, and clearing it upon - * completion: - * - * var handle = InteractionManager.createInteractionHandle(); - * // run animation... (`runAfterInteractions` tasks are queued) - * // later, on animation completion: - * InteractionManager.clearInteractionHandle(handle); - * // queued tasks run if all handles were cleared - */ - -var _emitter = new EventEmitter(); -var _interactionSet = new Set(); -var _addInteractionSet = new Set(); -var _deleteInteractionSet = new Set(); -var _nextUpdateHandle = null; -var _queue = []; -var _inc = 0; - -var InteractionManager = { - Events: keyMirror({ - interactionStart: true, - interactionComplete: true, - }), - - /** - * Notify manager that an interaction has started. - */ - createInteractionHandle() { - scheduleUpdate(); - var handle = ++_inc; - _addInteractionSet.add(handle); - return handle; - }, - - /** - * Notify manager that an interaction has completed. - */ - clearInteractionHandle(handle) { - invariant( - !!handle, - 'Must provide a handle to clear.' - ); - scheduleUpdate(); - _addInteractionSet.delete(handle); - _deleteInteractionSet.add(handle); - }, - - /** - * Schedule a function to run after all interactions have completed. - * - * @param {function} callback - */ - runAfterInteractions(callback) { - invariant( - typeof callback === 'function', - 'Must specify a function to schedule.' - ); - scheduleUpdate(); - _queue.push(callback); - }, - - addListener: _emitter.addListener.bind(_emitter), -}; - -/** - * Schedule an asynchronous update to the interaction state. - */ -function scheduleUpdate() { - if (!_nextUpdateHandle) { - _nextUpdateHandle = setImmediate(processUpdate); - } -} - -/** - * Notify listeners, process queue, etc - */ -function processUpdate() { - var interactionCount = _interactionSet.size; - _addInteractionSet.forEach(handle => - _interactionSet.add(handle) - ); - _deleteInteractionSet.forEach(handle => - _interactionSet.delete(handle) - ); - var nextInteractionCount = _interactionSet.size; - - if (interactionCount !== 0 && nextInteractionCount === 0) { - // transition from 1+ --> 0 interactions - _emitter.emit(InteractionManager.Events.interactionComplete); - } else if (interactionCount === 0 && nextInteractionCount !== 0) { - // transition from 0 --> 1+ interactions - _emitter.emit(InteractionManager.Events.interactionStart); - } - - // process the queue regardless of a transition - if (nextInteractionCount === 0) { - _queue.forEach(callback => { - ErrorUtils.applyWithGuard(callback); - }); - _queue = []; - } - _nextUpdateHandle = null; - _addInteractionSet.clear(); - _deleteInteractionSet.clear(); -} - -module.exports = InteractionManager; diff --git a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js deleted file mode 100644 index 422447d4693..00000000000 --- a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * Sets up global variables typical in most JavaScript environments. - * - * 1. Global timers (via `setTimeout` etc). - * 2. Global console object. - * 3. Hooks for printing stack traces with source maps. - * - * Leaves enough room in the environment for implementing your own: - * 1. Require system. - * 2. Bridged modules. - * - * @providesModule InitializeJavaScriptAppEngine - */ - -/* eslint global-strict: 0 */ -/* globals GLOBAL: true, window: true */ - -// Just to make sure the JS gets packaged up. -require('RCTDeviceEventEmitter'); - -if (typeof GLOBAL === 'undefined') { - GLOBAL = this; -} - -if (typeof window === 'undefined') { - window = GLOBAL; -} - -/** - * The document must be shimmed before anything else that might define the - * `ExecutionEnvironment` module (which checks for `document.createElement`). - */ -function setupDocumentShim() { - // The browser defines Text and Image globals by default. If you forget to - // require them, then the error message is very confusing. - function getInvalidGlobalUseError(name) { - return new Error( - 'You are trying to render the global ' + name + ' variable as a ' + - 'React element. You probably forgot to require ' + name + '.' - ); - } - GLOBAL.Text = { - get defaultProps() { - throw getInvalidGlobalUseError('Text'); - } - }; - GLOBAL.Image = { - get defaultProps() { - throw getInvalidGlobalUseError('Image'); - } - }; - // Force `ExecutionEnvironment.canUseDOM` to be false. - if (GLOBAL.document) { - GLOBAL.document.createElement = null; - } -} - -function handleErrorWithRedBox(e) { - var RKExceptionsManager = require('NativeModules').RKExceptionsManager; - var errorToString = require('errorToString'); - var loadSourceMap = require('loadSourceMap'); - - GLOBAL.console.error( - 'Error: ' + - '\n stack: \n' + e.stack + - '\n URL: ' + e.sourceURL + - '\n line: ' + e.line + - '\n message: ' + e.message - ); - - if (RKExceptionsManager) { - RKExceptionsManager.reportUnhandledException(e.message, errorToString(e)); - if (__DEV__) { - try { - var sourceMapInstance = loadSourceMap(); - var prettyStack = errorToString(e, sourceMapInstance); - RKExceptionsManager.updateExceptionMessage(e.message, prettyStack); - } catch (ee) { - GLOBAL.console.error('#CLOWNTOWN (error while displaying error): ' + ee.message); - } - } - } -} - -function setupRedBoxErrorHandler() { - var ErrorUtils = require('ErrorUtils'); - ErrorUtils.setGlobalHandler(handleErrorWithRedBox); -} - -/** - * Sets up a set of window environment wrappers that ensure that the - * BatchedBridge is flushed after each tick. In both the case of the - * `UIWebView` based `RKJavaScriptCaller` and `RKContextCaller`, we - * implement our own custom timing bridge that should be immune to - * unexplainably dropped timing signals. - */ -function setupTimers() { - var JSTimers = require('JSTimers'); - GLOBAL.setTimeout = JSTimers.setTimeout; - GLOBAL.setInterval = JSTimers.setInterval; - GLOBAL.setImmediate = JSTimers.setImmediate; - GLOBAL.clearTimeout = JSTimers.clearTimeout; - GLOBAL.clearInterval = JSTimers.clearInterval; - GLOBAL.clearImmediate = JSTimers.clearImmediate; - GLOBAL.cancelAnimationFrame = JSTimers.clearInterval; - GLOBAL.requestAnimationFrame = function(cb) { - /*requestAnimationFrame() { [native code] };*/ // Trick scroller library - return JSTimers.requestAnimationFrame(cb); // into thinking it's native - }; -} - -function setupAlert() { - var RKAlertManager = require('RKAlertManager'); - if (!GLOBAL.alert) { - GLOBAL.alert = function(text) { - var alertOpts = { - title: 'Alert', - message: '' + text, - buttons: [{'cancel': 'Okay'}], - }; - RKAlertManager.alertWithArgs(alertOpts, null); - }; - } -} - -function setupPromise() { - // The native Promise implementation throws the following error: - // ERROR: Event loop not supported. - GLOBAL.Promise = require('Promise'); -} - -function setupXHR() { - // The native XMLHttpRequest in Chrome dev tools is CORS aware and won't - // let you fetch anything from the internet - GLOBAL.XMLHttpRequest = require('XMLHttpRequest'); - GLOBAL.fetch = require('fetch'); -} - -function setupGeolocation() { - GLOBAL.navigator = GLOBAL.navigator || {}; - GLOBAL.navigator.geolocation = require('Geolocation'); -} - -setupDocumentShim(); -setupRedBoxErrorHandler(); -setupTimers(); -setupAlert(); -setupPromise(); -setupXHR(); -setupGeolocation(); diff --git a/Libraries/JavaScriptAppEngine/Initialization/SourceMap.js b/Libraries/JavaScriptAppEngine/Initialization/SourceMap.js deleted file mode 100644 index 75fe5de247d..00000000000 --- a/Libraries/JavaScriptAppEngine/Initialization/SourceMap.js +++ /dev/null @@ -1,1958 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule SourceMap - * @generated - * - * This module was generated from `node_modules/source-map` by running - * - * $ npm install dryice - * $ node Makefile.dryice.js - * $ cat dist/source-map.js - * - * and wrapping resulting file into `wrapper` function. - * - */ - -var scope = {}; -wrapper.call(scope); - -module.exports = scope.sourceMap; - -function wrapper() { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ - -/** - * Define a module along with a payload. - * @param {string} moduleName Name for the payload - * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec - * @param {function} payload Function with (require, exports, module) params - */ -function define(moduleName, deps, payload) { - if (typeof moduleName != "string") { - throw new TypeError('Expected string, got: ' + moduleName); - } - - if (arguments.length == 2) { - payload = deps; - } - - if (moduleName in define.modules) { - throw new Error("Module already defined: " + moduleName); - } - define.modules[moduleName] = payload; -}; - -/** - * The global store of un-instantiated modules - */ -define.modules = {}; - - -/** - * We invoke require() in the context of a Domain so we can have multiple - * sets of modules running separate from each other. - * This contrasts with JSMs which are singletons, Domains allows us to - * optionally load a CommonJS module twice with separate data each time. - * Perhaps you want 2 command lines with a different set of commands in each, - * for example. - */ -function Domain() { - this.modules = {}; - this._currentModule = null; -} - -(function () { - - /** - * Lookup module names and resolve them by calling the definition function if - * needed. - * There are 2 ways to call this, either with an array of dependencies and a - * callback to call when the dependencies are found (which can happen - * asynchronously in an in-page context) or with a single string an no callback - * where the dependency is resolved synchronously and returned. - * The API is designed to be compatible with the CommonJS AMD spec and - * RequireJS. - * @param {string[]|string} deps A name, or names for the payload - * @param {function|undefined} callback Function to call when the dependencies - * are resolved - * @return {undefined|object} The module required or undefined for - * array/callback method - */ - Domain.prototype.require = function(deps, callback) { - if (Array.isArray(deps)) { - var params = deps.map(function(dep) { - return this.lookup(dep); - }, this); - if (callback) { - callback.apply(null, params); - } - return undefined; - } - else { - return this.lookup(deps); - } - }; - - function normalize(path) { - var bits = path.split('/'); - var i = 1; - while (i < bits.length) { - if (bits[i] === '..') { - bits.splice(i-1, 1); - } else if (bits[i] === '.') { - bits.splice(i, 1); - } else { - i++; - } - } - return bits.join('/'); - } - - function join(a, b) { - a = a.trim(); - b = b.trim(); - if (/^\//.test(b)) { - return b; - } else { - return a.replace(/\/*$/, '/') + b; - } - } - - function dirname(path) { - var bits = path.split('/'); - bits.pop(); - return bits.join('/'); - } - - /** - * Lookup module names and resolve them by calling the definition function if - * needed. - * @param {string} moduleName A name for the payload to lookup - * @return {object} The module specified by aModuleName or null if not found. - */ - Domain.prototype.lookup = function(moduleName) { - if (/^\./.test(moduleName)) { - moduleName = normalize(join(dirname(this._currentModule), moduleName)); - } - - if (moduleName in this.modules) { - var module = this.modules[moduleName]; - return module; - } - - if (!(moduleName in define.modules)) { - throw new Error("Module not defined: " + moduleName); - } - - var module = define.modules[moduleName]; - - if (typeof module == "function") { - var exports = {}; - var previousModule = this._currentModule; - this._currentModule = moduleName; - module(this.require.bind(this), exports, { id: moduleName, uri: "" }); - this._currentModule = previousModule; - module = exports; - } - - // cache the resulting module object for next time - this.modules[moduleName] = module; - - return module; - }; - -}()); - -define.Domain = Domain; -define.globalDomain = new Domain(); -var require = define.globalDomain.require.bind(define.globalDomain); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/source-map-generator', ['require', 'exports', 'module' , 'source-map/base64-vlq', 'source-map/util', 'source-map/array-set'], function(require, exports, module) { - - var base64VLQ = require('./base64-vlq'); - var util = require('./util'); - var ArraySet = require('./array-set').ArraySet; - - /** - * An instance of the SourceMapGenerator represents a source map which is - * being built incrementally. To create a new one, you must pass an object - * with the following properties: - * - * - file: The filename of the generated source. - * - sourceRoot: An optional root for all URLs in this source map. - */ - function SourceMapGenerator(aArgs) { - this._file = util.getArg(aArgs, 'file'); - this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); - this._sources = new ArraySet(); - this._names = new ArraySet(); - this._mappings = []; - this._sourcesContents = null; - } - - SourceMapGenerator.prototype._version = 3; - - /** - * Creates a new SourceMapGenerator based on a SourceMapConsumer - * - * @param aSourceMapConsumer The SourceMap. - */ - SourceMapGenerator.fromSourceMap = - function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { - var sourceRoot = aSourceMapConsumer.sourceRoot; - var generator = new SourceMapGenerator({ - file: aSourceMapConsumer.file, - sourceRoot: sourceRoot - }); - aSourceMapConsumer.eachMapping(function (mapping) { - var newMapping = { - generated: { - line: mapping.generatedLine, - column: mapping.generatedColumn - } - }; - - if (mapping.source) { - newMapping.source = mapping.source; - if (sourceRoot) { - newMapping.source = util.relative(sourceRoot, newMapping.source); - } - - newMapping.original = { - line: mapping.originalLine, - column: mapping.originalColumn - }; - - if (mapping.name) { - newMapping.name = mapping.name; - } - } - - generator.addMapping(newMapping); - }); - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content) { - generator.setSourceContent(sourceFile, content); - } - }); - return generator; - }; - - /** - * Add a single mapping from original source line and column to the generated - * source's line and column for this source map being created. The mapping - * object should have the following properties: - * - * - generated: An object with the generated line and column positions. - * - original: An object with the original line and column positions. - * - source: The original source file (relative to the sourceRoot). - * - name: An optional original token name for this mapping. - */ - SourceMapGenerator.prototype.addMapping = - function SourceMapGenerator_addMapping(aArgs) { - var generated = util.getArg(aArgs, 'generated'); - var original = util.getArg(aArgs, 'original', null); - var source = util.getArg(aArgs, 'source', null); - var name = util.getArg(aArgs, 'name', null); - - this._validateMapping(generated, original, source, name); - - if (source && !this._sources.has(source)) { - this._sources.add(source); - } - - if (name && !this._names.has(name)) { - this._names.add(name); - } - - this._mappings.push({ - generatedLine: generated.line, - generatedColumn: generated.column, - originalLine: original != null && original.line, - originalColumn: original != null && original.column, - source: source, - name: name - }); - }; - - /** - * Set the source content for a source file. - */ - SourceMapGenerator.prototype.setSourceContent = - function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { - var source = aSourceFile; - if (this._sourceRoot) { - source = util.relative(this._sourceRoot, source); - } - - if (aSourceContent !== null) { - // Add the source content to the _sourcesContents map. - // Create a new _sourcesContents map if the property is null. - if (!this._sourcesContents) { - this._sourcesContents = {}; - } - this._sourcesContents[util.toSetString(source)] = aSourceContent; - } else { - // Remove the source file from the _sourcesContents map. - // If the _sourcesContents map is empty, set the property to null. - delete this._sourcesContents[util.toSetString(source)]; - if (Object.keys(this._sourcesContents).length === 0) { - this._sourcesContents = null; - } - } - }; - - /** - * Applies the mappings of a sub-source-map for a specific source file to the - * source map being generated. Each mapping to the supplied source file is - * rewritten using the supplied source map. Note: The resolution for the - * resulting mappings is the minimium of this map and the supplied map. - * - * @param aSourceMapConsumer The source map to be applied. - * @param aSourceFile Optional. The filename of the source file. - * If omitted, SourceMapConsumer's file property will be used. - */ - SourceMapGenerator.prototype.applySourceMap = - function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { - // If aSourceFile is omitted, we will use the file property of the SourceMap - if (!aSourceFile) { - aSourceFile = aSourceMapConsumer.file; - } - var sourceRoot = this._sourceRoot; - // Make "aSourceFile" relative if an absolute Url is passed. - if (sourceRoot) { - aSourceFile = util.relative(sourceRoot, aSourceFile); - } - // Applying the SourceMap can add and remove items from the sources and - // the names array. - var newSources = new ArraySet(); - var newNames = new ArraySet(); - - // Find mappings for the "aSourceFile" - this._mappings.forEach(function (mapping) { - if (mapping.source === aSourceFile && mapping.originalLine) { - // Check if it can be mapped by the source map, then update the mapping. - var original = aSourceMapConsumer.originalPositionFor({ - line: mapping.originalLine, - column: mapping.originalColumn - }); - if (original.source !== null) { - // Copy mapping - if (sourceRoot) { - mapping.source = util.relative(sourceRoot, original.source); - } else { - mapping.source = original.source; - } - mapping.originalLine = original.line; - mapping.originalColumn = original.column; - if (original.name !== null && mapping.name !== null) { - // Only use the identifier name if it's an identifier - // in both SourceMaps - mapping.name = original.name; - } - } - } - - var source = mapping.source; - if (source && !newSources.has(source)) { - newSources.add(source); - } - - var name = mapping.name; - if (name && !newNames.has(name)) { - newNames.add(name); - } - - }, this); - this._sources = newSources; - this._names = newNames; - - // Copy sourcesContents of applied map. - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content) { - if (sourceRoot) { - sourceFile = util.relative(sourceRoot, sourceFile); - } - this.setSourceContent(sourceFile, content); - } - }, this); - }; - - /** - * A mapping can have one of the three levels of data: - * - * 1. Just the generated position. - * 2. The Generated position, original position, and original source. - * 3. Generated and original position, original source, as well as a name - * token. - * - * To maintain consistency, we validate that any new mapping being added falls - * in to one of these categories. - */ - SourceMapGenerator.prototype._validateMapping = - function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, - aName) { - if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aGenerated.line > 0 && aGenerated.column >= 0 - && !aOriginal && !aSource && !aName) { - // Case 1. - return; - } - else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aOriginal && 'line' in aOriginal && 'column' in aOriginal - && aGenerated.line > 0 && aGenerated.column >= 0 - && aOriginal.line > 0 && aOriginal.column >= 0 - && aSource) { - // Cases 2 and 3. - return; - } - else { - throw new Error('Invalid mapping: ' + JSON.stringify({ - generated: aGenerated, - source: aSource, - orginal: aOriginal, - name: aName - })); - } - }; - - /** - * Serialize the accumulated mappings in to the stream of base 64 VLQs - * specified by the source map format. - */ - SourceMapGenerator.prototype._serializeMappings = - function SourceMapGenerator_serializeMappings() { - var previousGeneratedColumn = 0; - var previousGeneratedLine = 1; - var previousOriginalColumn = 0; - var previousOriginalLine = 0; - var previousName = 0; - var previousSource = 0; - var result = ''; - var mapping; - - // The mappings must be guaranteed to be in sorted order before we start - // serializing them or else the generated line numbers (which are defined - // via the ';' separators) will be all messed up. Note: it might be more - // performant to maintain the sorting as we insert them, rather than as we - // serialize them, but the big O is the same either way. - this._mappings.sort(util.compareByGeneratedPositions); - - for (var i = 0, len = this._mappings.length; i < len; i++) { - mapping = this._mappings[i]; - - if (mapping.generatedLine !== previousGeneratedLine) { - previousGeneratedColumn = 0; - while (mapping.generatedLine !== previousGeneratedLine) { - result += ';'; - previousGeneratedLine++; - } - } - else { - if (i > 0) { - if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) { - continue; - } - result += ','; - } - } - - result += base64VLQ.encode(mapping.generatedColumn - - previousGeneratedColumn); - previousGeneratedColumn = mapping.generatedColumn; - - if (mapping.source) { - result += base64VLQ.encode(this._sources.indexOf(mapping.source) - - previousSource); - previousSource = this._sources.indexOf(mapping.source); - - // lines are stored 0-based in SourceMap spec version 3 - result += base64VLQ.encode(mapping.originalLine - 1 - - previousOriginalLine); - previousOriginalLine = mapping.originalLine - 1; - - result += base64VLQ.encode(mapping.originalColumn - - previousOriginalColumn); - previousOriginalColumn = mapping.originalColumn; - - if (mapping.name) { - result += base64VLQ.encode(this._names.indexOf(mapping.name) - - previousName); - previousName = this._names.indexOf(mapping.name); - } - } - } - - return result; - }; - - SourceMapGenerator.prototype._generateSourcesContent = - function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { - return aSources.map(function (source) { - if (!this._sourcesContents) { - return null; - } - if (aSourceRoot) { - source = util.relative(aSourceRoot, source); - } - var key = util.toSetString(source); - return Object.prototype.hasOwnProperty.call(this._sourcesContents, - key) - ? this._sourcesContents[key] - : null; - }, this); - }; - - /** - * Externalize the source map. - */ - SourceMapGenerator.prototype.toJSON = - function SourceMapGenerator_toJSON() { - var map = { - version: this._version, - file: this._file, - sources: this._sources.toArray(), - names: this._names.toArray(), - mappings: this._serializeMappings() - }; - if (this._sourceRoot) { - map.sourceRoot = this._sourceRoot; - } - if (this._sourcesContents) { - map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); - } - - return map; - }; - - /** - * Render the source map being generated to a string. - */ - SourceMapGenerator.prototype.toString = - function SourceMapGenerator_toString() { - return JSON.stringify(this); - }; - - exports.SourceMapGenerator = SourceMapGenerator; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - * - * Based on the Base 64 VLQ implementation in Closure Compiler: - * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java - * - * Copyright 2011 The Closure Compiler Authors. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -define('source-map/base64-vlq', ['require', 'exports', 'module' , 'source-map/base64'], function(require, exports, module) { - - var base64 = require('./base64'); - - // A single base 64 digit can contain 6 bits of data. For the base 64 variable - // length quantities we use in the source map spec, the first bit is the sign, - // the next four bits are the actual value, and the 6th bit is the - // continuation bit. The continuation bit tells us whether there are more - // digits in this value following this digit. - // - // Continuation - // | Sign - // | | - // V V - // 101011 - - var VLQ_BASE_SHIFT = 5; - - // binary: 100000 - var VLQ_BASE = 1 << VLQ_BASE_SHIFT; - - // binary: 011111 - var VLQ_BASE_MASK = VLQ_BASE - 1; - - // binary: 100000 - var VLQ_CONTINUATION_BIT = VLQ_BASE; - - /** - * Converts from a two-complement value to a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - */ - function toVLQSigned(aValue) { - return aValue < 0 - ? ((-aValue) << 1) + 1 - : (aValue << 1) + 0; - } - - /** - * Converts to a two-complement value from a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - */ - function fromVLQSigned(aValue) { - var isNegative = (aValue & 1) === 1; - var shifted = aValue >> 1; - return isNegative - ? -shifted - : shifted; - } - - /** - * Returns the base 64 VLQ encoded value. - */ - exports.encode = function base64VLQ_encode(aValue) { - var encoded = ""; - var digit; - - var vlq = toVLQSigned(aValue); - - do { - digit = vlq & VLQ_BASE_MASK; - vlq >>>= VLQ_BASE_SHIFT; - if (vlq > 0) { - // There are still more digits in this value, so we must make sure the - // continuation bit is marked. - digit |= VLQ_CONTINUATION_BIT; - } - encoded += base64.encode(digit); - } while (vlq > 0); - - return encoded; - }; - - /** - * Decodes the next base 64 VLQ value from the given string and returns the - * value and the rest of the string. - */ - exports.decode = function base64VLQ_decode(aStr) { - var i = 0; - var strLen = aStr.length; - var result = 0; - var shift = 0; - var continuation, digit; - - do { - if (i >= strLen) { - throw new Error("Expected more digits in base 64 VLQ value."); - } - digit = base64.decode(aStr.charAt(i++)); - continuation = !!(digit & VLQ_CONTINUATION_BIT); - digit &= VLQ_BASE_MASK; - result = result + (digit << shift); - shift += VLQ_BASE_SHIFT; - } while (continuation); - - return { - value: fromVLQSigned(result), - rest: aStr.slice(i) - }; - }; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/base64', ['require', 'exports', 'module' , ], function(require, exports, module) { - - var charToIntMap = {}; - var intToCharMap = {}; - - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - .split('') - .forEach(function (ch, index) { - charToIntMap[ch] = index; - intToCharMap[index] = ch; - }); - - /** - * Encode an integer in the range of 0 to 63 to a single base 64 digit. - */ - exports.encode = function base64_encode(aNumber) { - if (aNumber in intToCharMap) { - return intToCharMap[aNumber]; - } - throw new TypeError("Must be between 0 and 63: " + aNumber); - }; - - /** - * Decode a single base 64 digit to an integer. - */ - exports.decode = function base64_decode(aChar) { - if (aChar in charToIntMap) { - return charToIntMap[aChar]; - } - throw new TypeError("Not a valid base 64 digit: " + aChar); - }; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) { - - /** - * This is a helper function for getting values from parameter/options - * objects. - * - * @param args The object we are extracting values from - * @param name The name of the property we are getting. - * @param defaultValue An optional value to return if the property is missing - * from the object. If this is not specified and the property is missing, an - * error will be thrown. - */ - function getArg(aArgs, aName, aDefaultValue) { - if (aName in aArgs) { - return aArgs[aName]; - } else if (arguments.length === 3) { - return aDefaultValue; - } else { - throw new Error('"' + aName + '" is a required argument.'); - } - } - exports.getArg = getArg; - - var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; - var dataUrlRegexp = /^data:.+\,.+/; - - function urlParse(aUrl) { - var match = aUrl.match(urlRegexp); - if (!match) { - return null; - } - return { - scheme: match[1], - auth: match[3], - host: match[4], - port: match[6], - path: match[7] - }; - } - exports.urlParse = urlParse; - - function urlGenerate(aParsedUrl) { - var url = aParsedUrl.scheme + "://"; - if (aParsedUrl.auth) { - url += aParsedUrl.auth + "@" - } - if (aParsedUrl.host) { - url += aParsedUrl.host; - } - if (aParsedUrl.port) { - url += ":" + aParsedUrl.port - } - if (aParsedUrl.path) { - url += aParsedUrl.path; - } - return url; - } - exports.urlGenerate = urlGenerate; - - function join(aRoot, aPath) { - var url; - - if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) { - return aPath; - } - - if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { - url.path = aPath; - return urlGenerate(url); - } - - return aRoot.replace(/\/$/, '') + '/' + aPath; - } - exports.join = join; - - /** - * Because behavior goes wacky when you set `__proto__` on objects, we - * have to prefix all the strings in our set with an arbitrary character. - * - * See https://github.com/mozilla/source-map/pull/31 and - * https://github.com/mozilla/source-map/issues/30 - * - * @param String aStr - */ - function toSetString(aStr) { - return '$' + aStr; - } - exports.toSetString = toSetString; - - function fromSetString(aStr) { - return aStr.substr(1); - } - exports.fromSetString = fromSetString; - - function relative(aRoot, aPath) { - aRoot = aRoot.replace(/\/$/, ''); - - var url = urlParse(aRoot); - if (aPath.charAt(0) == "/" && url && url.path == "/") { - return aPath.slice(1); - } - - return aPath.indexOf(aRoot + '/') === 0 - ? aPath.substr(aRoot.length + 1) - : aPath; - } - exports.relative = relative; - - function strcmp(aStr1, aStr2) { - var s1 = aStr1 || ""; - var s2 = aStr2 || ""; - return (s1 > s2) - (s1 < s2); - } - - /** - * Comparator between two mappings where the original positions are compared. - * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same original source/line/column, but different generated - * line and column the same. Useful when searching for a mapping with a - * stubbed out mapping. - */ - function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { - var cmp; - - cmp = strcmp(mappingA.source, mappingB.source); - if (cmp) { - return cmp; - } - - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp) { - return cmp; - } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp || onlyCompareOriginal) { - return cmp; - } - - cmp = strcmp(mappingA.name, mappingB.name); - if (cmp) { - return cmp; - } - - cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp) { - return cmp; - } - - return mappingA.generatedColumn - mappingB.generatedColumn; - }; - exports.compareByOriginalPositions = compareByOriginalPositions; - - /** - * Comparator between two mappings where the generated positions are - * compared. - * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same generated line and column, but different - * source/name/original line and column the same. Useful when searching for a - * mapping with a stubbed out mapping. - */ - function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { - var cmp; - - cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp) { - return cmp; - } - - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp || onlyCompareGenerated) { - return cmp; - } - - cmp = strcmp(mappingA.source, mappingB.source); - if (cmp) { - return cmp; - } - - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp) { - return cmp; - } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp) { - return cmp; - } - - return strcmp(mappingA.name, mappingB.name); - }; - exports.compareByGeneratedPositions = compareByGeneratedPositions; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/array-set', ['require', 'exports', 'module' , 'source-map/util'], function(require, exports, module) { - - var util = require('./util'); - - /** - * A data structure which is a combination of an array and a set. Adding a new - * member is O(1), testing for membership is O(1), and finding the index of an - * element is O(1). Removing elements from the set is not supported. Only - * strings are supported for membership. - */ - function ArraySet() { - this._array = []; - this._set = {}; - } - - /** - * Static method for creating ArraySet instances from an existing array. - */ - ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { - var set = new ArraySet(); - for (var i = 0, len = aArray.length; i < len; i++) { - set.add(aArray[i], aAllowDuplicates); - } - return set; - }; - - /** - * Add the given string to this set. - * - * @param String aStr - */ - ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { - var isDuplicate = this.has(aStr); - var idx = this._array.length; - if (!isDuplicate || aAllowDuplicates) { - this._array.push(aStr); - } - if (!isDuplicate) { - this._set[util.toSetString(aStr)] = idx; - } - }; - - /** - * Is the given string a member of this set? - * - * @param String aStr - */ - ArraySet.prototype.has = function ArraySet_has(aStr) { - return Object.prototype.hasOwnProperty.call(this._set, - util.toSetString(aStr)); - }; - - /** - * What is the index of the given string in the array? - * - * @param String aStr - */ - ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { - if (this.has(aStr)) { - return this._set[util.toSetString(aStr)]; - } - throw new Error('"' + aStr + '" is not in the set.'); - }; - - /** - * What is the element at the given index? - * - * @param Number aIdx - */ - ArraySet.prototype.at = function ArraySet_at(aIdx) { - if (aIdx >= 0 && aIdx < this._array.length) { - return this._array[aIdx]; - } - throw new Error('No element indexed by ' + aIdx); - }; - - /** - * Returns the array representation of this set (which has the proper indices - * indicated by indexOf). Note that this is a copy of the internal array used - * for storing the members so that no one can mess with internal state. - */ - ArraySet.prototype.toArray = function ArraySet_toArray() { - return this._array.slice(); - }; - - exports.ArraySet = ArraySet; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/source-map-consumer', ['require', 'exports', 'module' , 'source-map/util', 'source-map/binary-search', 'source-map/array-set', 'source-map/base64-vlq'], function(require, exports, module) { - - var util = require('./util'); - var binarySearch = require('./binary-search'); - var ArraySet = require('./array-set').ArraySet; - var base64VLQ = require('./base64-vlq'); - - /** - * A SourceMapConsumer instance represents a parsed source map which we can - * query for information about the original file positions by giving it a file - * position in the generated source. - * - * The only parameter is the raw source map (either as a JSON string, or - * already parsed to an object). According to the spec, source maps have the - * following attributes: - * - * - version: Which version of the source map spec this map is following. - * - sources: An array of URLs to the original source files. - * - names: An array of identifiers which can be referrenced by individual mappings. - * - sourceRoot: Optional. The URL root from which all sources are relative. - * - sourcesContent: Optional. An array of contents of the original source files. - * - mappings: A string of base64 VLQs which contain the actual mappings. - * - file: The generated file this source map is associated with. - * - * Here is an example source map, taken from the source map spec[0]: - * - * { - * version : 3, - * file: "out.js", - * sourceRoot : "", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AA,AB;;ABCDE;" - * } - * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# - */ - function SourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } - - var version = util.getArg(sourceMap, 'version'); - var sources = util.getArg(sourceMap, 'sources'); - // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which - // requires the array) to play nice here. - var names = util.getArg(sourceMap, 'names', []); - var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); - var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); - var mappings = util.getArg(sourceMap, 'mappings'); - var file = util.getArg(sourceMap, 'file', null); - - // Once again, Sass deviates from the spec and supplies the version as a - // string rather than a number, so we use loose equality checking here. - if (version != this._version) { - throw new Error('Unsupported version: ' + version); - } - - // Pass `true` below to allow duplicate names and sources. While source maps - // are intended to be compressed and deduplicated, the TypeScript compiler - // sometimes generates source maps with duplicates in them. See Github issue - // #72 and bugzil.la/889492. - this._names = ArraySet.fromArray(names, true); - this._sources = ArraySet.fromArray(sources, true); - - this.sourceRoot = sourceRoot; - this.sourcesContent = sourcesContent; - this._mappings = mappings; - this.file = file; - } - - /** - * Create a SourceMapConsumer from a SourceMapGenerator. - * - * @param SourceMapGenerator aSourceMap - * The source map that will be consumed. - * @returns SourceMapConsumer - */ - SourceMapConsumer.fromSourceMap = - function SourceMapConsumer_fromSourceMap(aSourceMap) { - var smc = Object.create(SourceMapConsumer.prototype); - - smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); - smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); - smc.sourceRoot = aSourceMap._sourceRoot; - smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), - smc.sourceRoot); - smc.file = aSourceMap._file; - - smc.__generatedMappings = aSourceMap._mappings.slice() - .sort(util.compareByGeneratedPositions); - smc.__originalMappings = aSourceMap._mappings.slice() - .sort(util.compareByOriginalPositions); - - return smc; - }; - - /** - * The version of the source mapping spec that we are consuming. - */ - SourceMapConsumer.prototype._version = 3; - - /** - * The list of original sources. - */ - Object.defineProperty(SourceMapConsumer.prototype, 'sources', { - get: function () { - return this._sources.toArray().map(function (s) { - return this.sourceRoot ? util.join(this.sourceRoot, s) : s; - }, this); - } - }); - - // `__generatedMappings` and `__originalMappings` are arrays that hold the - // parsed mapping coordinates from the source map's "mappings" attribute. They - // are lazily instantiated, accessed via the `_generatedMappings` and - // `_originalMappings` getters respectively, and we only parse the mappings - // and create these arrays once queried for a source location. We jump through - // these hoops because there can be many thousands of mappings, and parsing - // them is expensive, so we only want to do it if we must. - // - // Each object in the arrays is of the form: - // - // { - // generatedLine: The line number in the generated code, - // generatedColumn: The column number in the generated code, - // source: The path to the original source file that generated this - // chunk of code, - // originalLine: The line number in the original source that - // corresponds to this chunk of generated code, - // originalColumn: The column number in the original source that - // corresponds to this chunk of generated code, - // name: The name of the original symbol which generated this chunk of - // code. - // } - // - // All properties except for `generatedLine` and `generatedColumn` can be - // `null`. - // - // `_generatedMappings` is ordered by the generated positions. - // - // `_originalMappings` is ordered by the original positions. - - SourceMapConsumer.prototype.__generatedMappings = null; - Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { - get: function () { - if (!this.__generatedMappings) { - this.__generatedMappings = []; - this.__originalMappings = []; - this._parseMappings(this._mappings, this.sourceRoot); - } - - return this.__generatedMappings; - } - }); - - SourceMapConsumer.prototype.__originalMappings = null; - Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { - get: function () { - if (!this.__originalMappings) { - this.__generatedMappings = []; - this.__originalMappings = []; - this._parseMappings(this._mappings, this.sourceRoot); - } - - return this.__originalMappings; - } - }); - - /** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). - */ - SourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - var generatedLine = 1; - var previousGeneratedColumn = 0; - var previousOriginalLine = 0; - var previousOriginalColumn = 0; - var previousSource = 0; - var previousName = 0; - var mappingSeparator = /^[,;]/; - var str = aStr; - var mapping; - var temp; - - while (str.length > 0) { - if (str.charAt(0) === ';') { - generatedLine++; - str = str.slice(1); - previousGeneratedColumn = 0; - } - else if (str.charAt(0) === ',') { - str = str.slice(1); - } - else { - mapping = {}; - mapping.generatedLine = generatedLine; - - // Generated column. - temp = base64VLQ.decode(str); - mapping.generatedColumn = previousGeneratedColumn + temp.value; - previousGeneratedColumn = mapping.generatedColumn; - str = temp.rest; - - if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { - // Original source. - temp = base64VLQ.decode(str); - mapping.source = this._sources.at(previousSource + temp.value); - previousSource += temp.value; - str = temp.rest; - if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { - throw new Error('Found a source, but no line and column'); - } - - // Original line. - temp = base64VLQ.decode(str); - mapping.originalLine = previousOriginalLine + temp.value; - previousOriginalLine = mapping.originalLine; - // Lines are stored 0-based - mapping.originalLine += 1; - str = temp.rest; - if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { - throw new Error('Found a source and line, but no column'); - } - - // Original column. - temp = base64VLQ.decode(str); - mapping.originalColumn = previousOriginalColumn + temp.value; - previousOriginalColumn = mapping.originalColumn; - str = temp.rest; - - if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { - // Original name. - temp = base64VLQ.decode(str); - mapping.name = this._names.at(previousName + temp.value); - previousName += temp.value; - str = temp.rest; - } - } - - this.__generatedMappings.push(mapping); - if (typeof mapping.originalLine === 'number') { - this.__originalMappings.push(mapping); - } - } - } - - this.__originalMappings.sort(util.compareByOriginalPositions); - }; - - /** - * Find the mapping that best matches the hypothetical "needle" mapping that - * we are searching for in the given "haystack" of mappings. - */ - SourceMapConsumer.prototype._findMapping = - function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, - aColumnName, aComparator) { - // To return the position we are searching for, we must first find the - // mapping for the given position and then return the opposite position it - // points to. Because the mappings are sorted, we can use binary search to - // find the best mapping. - - if (aNeedle[aLineName] <= 0) { - throw new TypeError('Line must be greater than or equal to 1, got ' - + aNeedle[aLineName]); - } - if (aNeedle[aColumnName] < 0) { - throw new TypeError('Column must be greater than or equal to 0, got ' - + aNeedle[aColumnName]); - } - - return binarySearch.search(aNeedle, aMappings, aComparator); - }; - - /** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: - * - * - line: The line number in the generated source. - * - column: The column number in the generated source. - * - * and an object is returned with the following properties: - * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. - */ - SourceMapConsumer.prototype.originalPositionFor = - function SourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; - - var mapping = this._findMapping(needle, - this._generatedMappings, - "generatedLine", - "generatedColumn", - util.compareByGeneratedPositions); - - if (mapping) { - var source = util.getArg(mapping, 'source', null); - if (source && this.sourceRoot) { - source = util.join(this.sourceRoot, source); - } - return { - source: source, - line: util.getArg(mapping, 'originalLine', null), - column: util.getArg(mapping, 'originalColumn', null), - name: util.getArg(mapping, 'name', null) - }; - } - - return { - source: null, - line: null, - column: null, - name: null - }; - }; - - /** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * availible. - */ - SourceMapConsumer.prototype.sourceContentFor = - function SourceMapConsumer_sourceContentFor(aSource) { - if (!this.sourcesContent) { - return null; - } - - if (this.sourceRoot) { - aSource = util.relative(this.sourceRoot, aSource); - } - - if (this._sources.has(aSource)) { - return this.sourcesContent[this._sources.indexOf(aSource)]; - } - - var url; - if (this.sourceRoot - && (url = util.urlParse(this.sourceRoot))) { - // XXX: file:// URIs and absolute paths lead to unexpected behavior for - // many users. We can help them out when they expect file:// URIs to - // behave like it would if they were running a local HTTP server. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. - var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); - if (url.scheme == "file" - && this._sources.has(fileUriAbsPath)) { - return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] - } - - if ((!url.path || url.path == "/") - && this._sources.has("/" + aSource)) { - return this.sourcesContent[this._sources.indexOf("/" + aSource)]; - } - } - - throw new Error('"' + aSource + '" is not in the SourceMap.'); - }; - - /** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - * and an object is returned with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. - */ - SourceMapConsumer.prototype.generatedPositionFor = - function SourceMapConsumer_generatedPositionFor(aArgs) { - var needle = { - source: util.getArg(aArgs, 'source'), - originalLine: util.getArg(aArgs, 'line'), - originalColumn: util.getArg(aArgs, 'column') - }; - - if (this.sourceRoot) { - needle.source = util.relative(this.sourceRoot, needle.source); - } - - var mapping = this._findMapping(needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions); - - if (mapping) { - return { - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null) - }; - } - - return { - line: null, - column: null - }; - }; - - SourceMapConsumer.GENERATED_ORDER = 1; - SourceMapConsumer.ORIGINAL_ORDER = 2; - - /** - * Iterate over each mapping between an original source/line/column and a - * generated line/column in this source map. - * - * @param Function aCallback - * The function that is called with each mapping. - * @param Object aContext - * Optional. If specified, this object will be the value of `this` every - * time that `aCallback` is called. - * @param aOrder - * Either `SourceMapConsumer.GENERATED_ORDER` or - * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to - * iterate over the mappings sorted by the generated file's line/column - * order or the original's source/line/column order, respectively. Defaults to - * `SourceMapConsumer.GENERATED_ORDER`. - */ - SourceMapConsumer.prototype.eachMapping = - function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { - var context = aContext || null; - var order = aOrder || SourceMapConsumer.GENERATED_ORDER; - - var mappings; - switch (order) { - case SourceMapConsumer.GENERATED_ORDER: - mappings = this._generatedMappings; - break; - case SourceMapConsumer.ORIGINAL_ORDER: - mappings = this._originalMappings; - break; - default: - throw new Error("Unknown order of iteration."); - } - - var sourceRoot = this.sourceRoot; - mappings.map(function (mapping) { - var source = mapping.source; - if (source && sourceRoot) { - source = util.join(sourceRoot, source); - } - return { - source: source, - generatedLine: mapping.generatedLine, - generatedColumn: mapping.generatedColumn, - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: mapping.name - }; - }).forEach(aCallback, context); - }; - - exports.SourceMapConsumer = SourceMapConsumer; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/binary-search', ['require', 'exports', 'module' , ], function(require, exports, module) { - - /** - * Recursive implementation of binary search. - * - * @param aLow Indices here and lower do not contain the needle. - * @param aHigh Indices here and higher do not contain the needle. - * @param aNeedle The element being searched for. - * @param aHaystack The non-empty array being searched. - * @param aCompare Function which takes two elements and returns -1, 0, or 1. - */ - function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { - // This function terminates when one of the following is true: - // - // 1. We find the exact element we are looking for. - // - // 2. We did not find the exact element, but we can return the next - // closest element that is less than that element. - // - // 3. We did not find the exact element, and there is no next-closest - // element which is less than the one we are searching for, so we - // return null. - var mid = Math.floor((aHigh - aLow) / 2) + aLow; - var cmp = aCompare(aNeedle, aHaystack[mid], true); - if (cmp === 0) { - // Found the element we are looking for. - return aHaystack[mid]; - } - else if (cmp > 0) { - // aHaystack[mid] is greater than our needle. - if (aHigh - mid > 1) { - // The element is in the upper half. - return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); - } - // We did not find an exact match, return the next closest one - // (termination case 2). - return aHaystack[mid]; - } - else { - // aHaystack[mid] is less than our needle. - if (mid - aLow > 1) { - // The element is in the lower half. - return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); - } - // The exact needle element was not found in this haystack. Determine if - // we are in termination case (2) or (3) and return the appropriate thing. - return aLow < 0 - ? null - : aHaystack[aLow]; - } - } - - /** - * This is an implementation of binary search which will always try and return - * the next lowest value checked if there is no exact hit. This is because - * mappings between original and generated line/col pairs are single points, - * and there is an implicit region between each of them, so a miss just means - * that you aren't on the very start of a region. - * - * @param aNeedle The element you are looking for. - * @param aHaystack The array that is being searched. - * @param aCompare A function which takes the needle and an element in the - * array and returns -1, 0, or 1 depending on whether the needle is less - * than, equal to, or greater than the element, respectively. - */ - exports.search = function search(aNeedle, aHaystack, aCompare) { - return aHaystack.length > 0 - ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) - : null; - }; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -define('source-map/source-node', ['require', 'exports', 'module' , 'source-map/source-map-generator', 'source-map/util'], function(require, exports, module) { - - var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; - var util = require('./util'); - - /** - * SourceNodes provide a way to abstract over interpolating/concatenating - * snippets of generated JavaScript source code while maintaining the line and - * column information associated with the original source code. - * - * @param aLine The original line number. - * @param aColumn The original column number. - * @param aSource The original source's filename. - * @param aChunks Optional. An array of strings which are snippets of - * generated JS, or other SourceNodes. - * @param aName The original identifier. - */ - function SourceNode(aLine, aColumn, aSource, aChunks, aName) { - this.children = []; - this.sourceContents = {}; - this.line = aLine === undefined ? null : aLine; - this.column = aColumn === undefined ? null : aColumn; - this.source = aSource === undefined ? null : aSource; - this.name = aName === undefined ? null : aName; - if (aChunks != null) this.add(aChunks); - } - - /** - * Creates a SourceNode from generated code and a SourceMapConsumer. - * - * @param aGeneratedCode The generated code - * @param aSourceMapConsumer The SourceMap for the generated code - */ - SourceNode.fromStringWithSourceMap = - function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { - // The SourceNode we want to fill with the generated code - // and the SourceMap - var node = new SourceNode(); - - // The generated code - // Processed fragments are removed from this array. - var remainingLines = aGeneratedCode.split('\n'); - - // We need to remember the position of "remainingLines" - var lastGeneratedLine = 1, lastGeneratedColumn = 0; - - // The generate SourceNodes we need a code range. - // To extract it current and last mapping is used. - // Here we store the last mapping. - var lastMapping = null; - - aSourceMapConsumer.eachMapping(function (mapping) { - if (lastMapping === null) { - // We add the generated code until the first mapping - // to the SourceNode without any mapping. - // Each line is added as separate string. - while (lastGeneratedLine < mapping.generatedLine) { - node.add(remainingLines.shift() + "\n"); - lastGeneratedLine++; - } - if (lastGeneratedColumn < mapping.generatedColumn) { - var nextLine = remainingLines[0]; - node.add(nextLine.substr(0, mapping.generatedColumn)); - remainingLines[0] = nextLine.substr(mapping.generatedColumn); - lastGeneratedColumn = mapping.generatedColumn; - } - } else { - // We add the code from "lastMapping" to "mapping": - // First check if there is a new line in between. - if (lastGeneratedLine < mapping.generatedLine) { - var code = ""; - // Associate full lines with "lastMapping" - do { - code += remainingLines.shift() + "\n"; - lastGeneratedLine++; - lastGeneratedColumn = 0; - } while (lastGeneratedLine < mapping.generatedLine); - // When we reached the correct line, we add code until we - // reach the correct column too. - if (lastGeneratedColumn < mapping.generatedColumn) { - var nextLine = remainingLines[0]; - code += nextLine.substr(0, mapping.generatedColumn); - remainingLines[0] = nextLine.substr(mapping.generatedColumn); - lastGeneratedColumn = mapping.generatedColumn; - } - // Create the SourceNode. - addMappingWithCode(lastMapping, code); - } else { - // There is no new line in between. - // Associate the code between "lastGeneratedColumn" and - // "mapping.generatedColumn" with "lastMapping" - var nextLine = remainingLines[0]; - var code = nextLine.substr(0, mapping.generatedColumn - - lastGeneratedColumn); - remainingLines[0] = nextLine.substr(mapping.generatedColumn - - lastGeneratedColumn); - lastGeneratedColumn = mapping.generatedColumn; - addMappingWithCode(lastMapping, code); - } - } - lastMapping = mapping; - }, this); - // We have processed all mappings. - // Associate the remaining code in the current line with "lastMapping" - // and add the remaining lines without any mapping - addMappingWithCode(lastMapping, remainingLines.join("\n")); - - // Copy sourcesContent into SourceNode - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content) { - node.setSourceContent(sourceFile, content); - } - }); - - return node; - - function addMappingWithCode(mapping, code) { - if (mapping === null || mapping.source === undefined) { - node.add(code); - } else { - node.add(new SourceNode(mapping.originalLine, - mapping.originalColumn, - mapping.source, - code, - mapping.name)); - } - } - }; - - /** - * Add a chunk of generated JS to this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ - SourceNode.prototype.add = function SourceNode_add(aChunk) { - if (Array.isArray(aChunk)) { - aChunk.forEach(function (chunk) { - this.add(chunk); - }, this); - } - else if (aChunk instanceof SourceNode || typeof aChunk === "string") { - if (aChunk) { - this.children.push(aChunk); - } - } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); - } - return this; - }; - - /** - * Add a chunk of generated JS to the beginning of this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ - SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { - if (Array.isArray(aChunk)) { - for (var i = aChunk.length-1; i >= 0; i--) { - this.prepend(aChunk[i]); - } - } - else if (aChunk instanceof SourceNode || typeof aChunk === "string") { - this.children.unshift(aChunk); - } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); - } - return this; - }; - - /** - * Walk over the tree of JS snippets in this node and its children. The - * walking function is called once for each snippet of JS and is passed that - * snippet and the its original associated source's line/column location. - * - * @param aFn The traversal function. - */ - SourceNode.prototype.walk = function SourceNode_walk(aFn) { - var chunk; - for (var i = 0, len = this.children.length; i < len; i++) { - chunk = this.children[i]; - if (chunk instanceof SourceNode) { - chunk.walk(aFn); - } - else { - if (chunk !== '') { - aFn(chunk, { source: this.source, - line: this.line, - column: this.column, - name: this.name }); - } - } - } - }; - - /** - * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between - * each of `this.children`. - * - * @param aSep The separator. - */ - SourceNode.prototype.join = function SourceNode_join(aSep) { - var newChildren; - var i; - var len = this.children.length; - if (len > 0) { - newChildren = []; - for (i = 0; i < len-1; i++) { - newChildren.push(this.children[i]); - newChildren.push(aSep); - } - newChildren.push(this.children[i]); - this.children = newChildren; - } - return this; - }; - - /** - * Call String.prototype.replace on the very right-most source snippet. Useful - * for trimming whitespace from the end of a source node, etc. - * - * @param aPattern The pattern to replace. - * @param aReplacement The thing to replace the pattern with. - */ - SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { - var lastChild = this.children[this.children.length - 1]; - if (lastChild instanceof SourceNode) { - lastChild.replaceRight(aPattern, aReplacement); - } - else if (typeof lastChild === 'string') { - this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); - } - else { - this.children.push(''.replace(aPattern, aReplacement)); - } - return this; - }; - - /** - * Set the source content for a source file. This will be added to the SourceMapGenerator - * in the sourcesContent field. - * - * @param aSourceFile The filename of the source file - * @param aSourceContent The content of the source file - */ - SourceNode.prototype.setSourceContent = - function SourceNode_setSourceContent(aSourceFile, aSourceContent) { - this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; - }; - - /** - * Walk over the tree of SourceNodes. The walking function is called for each - * source file content and is passed the filename and source content. - * - * @param aFn The traversal function. - */ - SourceNode.prototype.walkSourceContents = - function SourceNode_walkSourceContents(aFn) { - for (var i = 0, len = this.children.length; i < len; i++) { - if (this.children[i] instanceof SourceNode) { - this.children[i].walkSourceContents(aFn); - } - } - - var sources = Object.keys(this.sourceContents); - for (var i = 0, len = sources.length; i < len; i++) { - aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); - } - }; - - /** - * Return the string representation of this source node. Walks over the tree - * and concatenates all the various snippets together to one string. - */ - SourceNode.prototype.toString = function SourceNode_toString() { - var str = ""; - this.walk(function (chunk) { - str += chunk; - }); - return str; - }; - - /** - * Returns the string representation of this source node along with a source - * map. - */ - SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { - var generated = { - code: "", - line: 1, - column: 0 - }; - var map = new SourceMapGenerator(aArgs); - var sourceMappingActive = false; - var lastOriginalSource = null; - var lastOriginalLine = null; - var lastOriginalColumn = null; - var lastOriginalName = null; - this.walk(function (chunk, original) { - generated.code += chunk; - if (original.source !== null - && original.line !== null - && original.column !== null) { - if(lastOriginalSource !== original.source - || lastOriginalLine !== original.line - || lastOriginalColumn !== original.column - || lastOriginalName !== original.name) { - map.addMapping({ - source: original.source, - original: { - line: original.line, - column: original.column - }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); - } - lastOriginalSource = original.source; - lastOriginalLine = original.line; - lastOriginalColumn = original.column; - lastOriginalName = original.name; - sourceMappingActive = true; - } else if (sourceMappingActive) { - map.addMapping({ - generated: { - line: generated.line, - column: generated.column - } - }); - lastOriginalSource = null; - sourceMappingActive = false; - } - chunk.split('').forEach(function (ch) { - if (ch === '\n') { - generated.line++; - generated.column = 0; - } else { - generated.column++; - } - }); - }); - this.walkSourceContents(function (sourceFile, sourceContent) { - map.setSourceContent(sourceFile, sourceContent); - }); - - return { code: generated.code, map: map }; - }; - - exports.SourceNode = SourceNode; - -}); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/////////////////////////////////////////////////////////////////////////////// - -this.sourceMap = { - SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, - SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, - SourceNode: require('source-map/source-node').SourceNode -}; - -} diff --git a/Libraries/JavaScriptAppEngine/Initialization/errorToString.js b/Libraries/JavaScriptAppEngine/Initialization/errorToString.js deleted file mode 100644 index 652d6c2aff9..00000000000 --- a/Libraries/JavaScriptAppEngine/Initialization/errorToString.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule errorToString - */ -'use strict'; - -var Platform = require('Platform'); - -var stacktraceParser = require('stacktrace-parser'); - -function stackFrameToString(stackFrame) { - var fileNameParts = stackFrame.file.split('/'); - var fileName = fileNameParts[fileNameParts.length - 1]; - - return stackFrame.methodName + '\n in ' + fileName + ':' + stackFrame.lineNumber + '\n'; -} - -function resolveSourceMaps(sourceMapInstance, stackFrame) { - try { - var orig = sourceMapInstance.originalPositionFor({ - line: stackFrame.lineNumber, - column: stackFrame.column, - }); - if (orig) { - stackFrame.file = orig.source; - stackFrame.lineNumber = orig.line; - stackFrame.column = orig.column; - } - } catch (innerEx) { - } -} - -function errorToString(e, sourceMapInstance) { - var stack = stacktraceParser.parse(e.stack); - - var framesToPop = e.framesToPop || 0; - while (framesToPop--) { - stack.shift(); - } - - if (sourceMapInstance) { - stack.forEach(resolveSourceMaps.bind(null, sourceMapInstance)); - } - - // HACK(frantic) Android currently expects stack trace to be a string #5920439 - if (Platform.OS === 'android') { - return stack.map(stackFrameToString).join('\n'); - } else { - return stack; - } -} - -module.exports = errorToString; diff --git a/Libraries/JavaScriptAppEngine/Initialization/loadSourceMap.js b/Libraries/JavaScriptAppEngine/Initialization/loadSourceMap.js deleted file mode 100644 index 076f9fa5c14..00000000000 --- a/Libraries/JavaScriptAppEngine/Initialization/loadSourceMap.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule loadSourceMap - */ - -'use strict'; - -var SourceMapConsumer = require('SourceMap').SourceMapConsumer; - -var sourceMapInstance; - -function loadSourceMap() { - if (sourceMapInstance !== undefined) { - return sourceMapInstance; - } - if (!global.RAW_SOURCE_MAP) { - return null; - } - sourceMapInstance = new SourceMapConsumer(global.RAW_SOURCE_MAP); - return sourceMapInstance; -} - -module.exports = loadSourceMap; diff --git a/Libraries/JavaScriptAppEngine/System/JSTimers/JSTimers.js b/Libraries/JavaScriptAppEngine/System/JSTimers/JSTimers.js deleted file mode 100644 index 13297ef0090..00000000000 --- a/Libraries/JavaScriptAppEngine/System/JSTimers/JSTimers.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule JSTimers - */ -'use strict'; - -// Note that the module JSTimers is split into two in order to solve a cycle -// in dependencies. NativeModules > BatchedBridge > MessageQueue > JSTimersExecution -var RKTiming = require('NativeModules').RKTiming; -var JSTimersExecution = require('JSTimersExecution'); - -/** - * JS implementation of timer functions. Must be completely driven by an - * external clock signal, all that's stored here is timerID, timer type, and - * callback. - */ -var JSTimers = { - Types: JSTimersExecution.Types, - - /** - * Returns a free index if one is available, and the next consecutive index - * otherwise. - */ - _getFreeIndex: function() { - var freeIndex = JSTimersExecution.timerIDs.indexOf(null); - if (freeIndex === -1) { - freeIndex = JSTimersExecution.timerIDs.length; - } - return freeIndex; - }, - - /** - * @param {function} func Callback to be invoked after `duration` ms. - * @param {number} duration Number of milliseconds. - */ - setTimeout: function(func, duration, ...args) { - var newID = JSTimersExecution.GUID++; - var freeIndex = JSTimers._getFreeIndex(); - JSTimersExecution.timerIDs[freeIndex] = newID; - JSTimersExecution.callbacks[freeIndex] = func; - JSTimersExecution.callbacks[freeIndex] = function() { - return func.apply(undefined, args); - }; - JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.setTimeout; - RKTiming.createTimer(newID, duration, Date.now(), /** recurring */ false); - return newID; - }, - - /** - * @param {function} func Callback to be invoked every `duration` ms. - * @param {number} duration Number of milliseconds. - */ - setInterval: function(func, duration, ...args) { - var newID = JSTimersExecution.GUID++; - var freeIndex = JSTimers._getFreeIndex(); - JSTimersExecution.timerIDs[freeIndex] = newID; - JSTimersExecution.callbacks[freeIndex] = func; - JSTimersExecution.callbacks[freeIndex] = function() { - return func.apply(undefined, args); - }; - JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.setInterval; - RKTiming.createTimer(newID, duration, Date.now(), /** recurring */ true); - return newID; - }, - - /** - * @param {function} func Callback to be invoked before the end of the - * current JavaScript execution loop. - */ - setImmediate: function(func, ...args) { - var newID = JSTimersExecution.GUID++; - var freeIndex = JSTimers._getFreeIndex(); - JSTimersExecution.timerIDs[freeIndex] = newID; - JSTimersExecution.callbacks[freeIndex] = func; - JSTimersExecution.callbacks[freeIndex] = function() { - return func.apply(undefined, args); - }; - JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.setImmediate; - JSTimersExecution.immediates.push(newID); - return newID; - }, - - /** - * @param {function} func Callback to be invoked every frame. - */ - requestAnimationFrame: function(func) { - var newID = JSTimersExecution.GUID++; - var freeIndex = JSTimers._getFreeIndex(); - JSTimersExecution.timerIDs[freeIndex] = newID; - JSTimersExecution.callbacks[freeIndex] = func; - JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.requestAnimationFrame; - RKTiming.createTimer(newID, 0, Date.now(), /** recurring */ false); - return newID; - }, - - clearTimeout: function(timerID) { - JSTimers._clearTimerID(timerID); - }, - - clearInterval: function(timerID) { - JSTimers._clearTimerID(timerID); - }, - - clearImmediate: function(timerID) { - JSTimers._clearTimerID(timerID); - JSTimersExecution.immediates.splice( - JSTimersExecution.immediates.indexOf(timerID), - 1 - ); - }, - - cancelAnimationFrame: function(timerID) { - JSTimers._clearTimerID(timerID); - }, - - _clearTimerID: function(timerID) { - // JSTimersExecution.timerIDs contains nulls after timers have been removed; - // ignore nulls upfront so indexOf doesn't find them - if (timerID == null) { - return; - } - - var index = JSTimersExecution.timerIDs.indexOf(timerID); - // See corresponding comment in `callTimers` for reasoning behind this - if (index !== -1) { - JSTimersExecution._clearIndex(index); - if (JSTimersExecution.types[index] !== JSTimersExecution.Type.setImmediate) { - RKTiming.deleteTimer(timerID); - } - } - }, -}; - -module.exports = JSTimers; diff --git a/Libraries/JavaScriptAppEngine/System/JSTimers/JSTimersExecution.js b/Libraries/JavaScriptAppEngine/System/JSTimers/JSTimersExecution.js deleted file mode 100644 index ee86472b3f8..00000000000 --- a/Libraries/JavaScriptAppEngine/System/JSTimers/JSTimersExecution.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule JSTimersExecution - */ -'use strict'; - -var invariant = require('invariant'); -var keyMirror = require('keyMirror'); -var performanceNow = require('performanceNow'); -var warning = require('warning'); - -/** - * JS implementation of timer functions. Must be completely driven by an - * external clock signal, all that's stored here is timerID, timer type, and - * callback. - */ -var JSTimersExecution = { - GUID: 1, - Type: keyMirror({ - setTimeout: null, - setInterval: null, - requestAnimationFrame: null, - setImmediate: null, - }), - - // Parallel arrays: - callbacks: [], - types: [], - timerIDs: [], - immediates: [], - - /** - * Calls the callback associated with the ID. Also unregister that callback - * if it was a one time timer (setTimeout), and not unregister it if it was - * recurring (setInterval). - */ - callTimer: function(timerID) { - warning(timerID <= JSTimersExecution.GUID, 'Tried to call timer with ID ' + timerID + ' but no such timer exists'); - var timerIndex = JSTimersExecution.timerIDs.indexOf(timerID); - // timerIndex of -1 means that no timer with that ID exists. There are - // two situations when this happens, when a garbage timer ID was given - // and when a previously existing timer was deleted before this callback - // fired. In both cases we want to ignore the timer id, but in the former - // case we warn as well. - if (timerIndex === -1) { - return; - } - var type = JSTimersExecution.types[timerIndex]; - var callback = JSTimersExecution.callbacks[timerIndex]; - - // Clear the metadata - if (type === JSTimersExecution.Type.setTimeout || - type === JSTimersExecution.Type.setImmediate || - type === JSTimersExecution.Type.requestAnimationFrame) { - JSTimersExecution._clearIndex(timerIndex); - } - - try { - if (type === JSTimersExecution.Type.setTimeout || - type === JSTimersExecution.Type.setInterval || - type === JSTimersExecution.Type.setImmediate) { - callback(); - } else if (type === JSTimersExecution.Type.requestAnimationFrame) { - var currentTime = performanceNow(); - callback(currentTime); - } else { - console.error('Tried to call a callback with invalid type: ' + type); - return; - } - } catch (e) { - // Don't rethrow so that we can run every other timer. - JSTimersExecution.errors = JSTimersExecution.errors || []; - JSTimersExecution.errors.push(e); - } - }, - - /** - * This is called from the native side. We are passed an array of timerIDs, - * and - */ - callTimers: function(timerIDs) { - invariant(timerIDs.length !== 0, 'Probably shouldn\'t call "callTimers" with no timerIDs'); - - JSTimersExecution.errors = null; - timerIDs.forEach(JSTimersExecution.callTimer); - - var errors = JSTimersExecution.errors; - if (errors) { - var errorCount = errors.length; - if (errorCount > 1) { - // Throw all the other errors in a setTimeout, which will throw each - // error one at a time - for (var ii = 1; ii < errorCount; ii++) { - require('JSTimers').setTimeout( - ((error) => { throw error; }).bind(null, errors[ii]), - 0 - ); - } - } - throw errors[0]; - } - }, - - /** - * This is called after we execute any command we receive from native but - * before we hand control back to native. - */ - callImmediates: function() { - JSTimersExecution.errors = null; - while (JSTimersExecution.immediates.length !== 0) { - JSTimersExecution.callTimer(JSTimersExecution.immediates.shift()); - } - if (JSTimersExecution.errors) { - JSTimersExecution.errors.forEach((error) => - require('JSTimers').setTimeout(() => { throw error; }, 0) - ); - } - }, - - _clearIndex: function(i) { - JSTimersExecution.timerIDs[i] = null; - JSTimersExecution.callbacks[i] = null; - JSTimersExecution.types[i] = null; - }, -}; - -module.exports = JSTimersExecution; diff --git a/Libraries/Network/RCTDataManager.h b/Libraries/Network/RCTDataManager.h deleted file mode 100644 index 47f80ba1cef..00000000000 --- a/Libraries/Network/RCTDataManager.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridgeModule.h" - -@interface RCTDataManager : NSObject - -@end - diff --git a/Libraries/Network/RCTDataManager.m b/Libraries/Network/RCTDataManager.m deleted file mode 100644 index 4ffe5f975a7..00000000000 --- a/Libraries/Network/RCTDataManager.m +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTDataManager.h" - -#import "RCTAssert.h" -#import "RCTLog.h" -#import "RCTUtils.h" - -@implementation RCTDataManager - -/** - * Executes a network request. - * The responseSender block won't be called on same thread as called. - */ -- (void)executeQuery:(NSString *)queryType - query:(id)query - queryHash:(__unused NSString *)queryHash - responseSender:(RCTResponseSenderBlock)responseSender -{ - RCT_EXPORT(queryData); - - if ([queryType isEqualToString:@"http"]) { - - // Parse query - NSDictionary *queryDict = query; - if ([query isKindOfClass:[NSString class]]) { - // TODO: it would be more efficient just to send a dictionary - queryDict = RCTJSONParse(query, NULL); - } - - // Build request - NSURL *url = [NSURL URLWithString:queryDict[@"url"]]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - request.HTTPMethod = queryDict[@"method"] ?: @"GET"; - request.allHTTPHeaderFields = queryDict[@"headers"]; - if ([queryDict[@"data"] isKindOfClass:[NSString class]]) { - request.HTTPBody = [queryDict[@"data"] dataUsingEncoding:NSUTF8StringEncoding]; - } - - // Build data task - NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) { - - // Build response - NSDictionary *responseJSON; - if (connectionError == nil) { - NSStringEncoding encoding; - if (response.textEncodingName) { - CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName); - encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); - } else { - encoding = NSUTF8StringEncoding; - } - NSString *returnData = [[NSString alloc] initWithData:data encoding:encoding]; - responseJSON = @{@"status": @200, @"responseText": returnData}; - } else { - responseJSON = @{@"status": @0, @"responseText": [connectionError localizedDescription]}; - } - - // Send response (won't be sent on same thread as caller) - responseSender(@[RCTJSONStringify(responseJSON, NULL)]); - - }]; - - [task resume]; - - } else { - - RCTLogError(@"unsupported query type %@", queryType); - } -} - -@end diff --git a/Libraries/Network/RCTDataManager.podspec b/Libraries/Network/RCTDataManager.podspec deleted file mode 100644 index 84df787b857..00000000000 --- a/Libraries/Network/RCTDataManager.podspec +++ /dev/null @@ -1,28 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'RCTDataManager' - spec.version = '0.0.1' - spec.summary = 'Provides basic networking capabilities in ReactNative apps.' - spec.description = <<-DESC - Use XMLHttpRequest to fetch data over the network. - DESC - spec.homepage = 'https://facebook.github.io/react-native/' - spec.license = { :type => 'BSD' } - spec.author = 'Facebook' - spec.platform = :ios, '7.0' - spec.requires_arc = true - spec.source_files = '**/*.{h,m,c}' - spec.dependency "ReactKit", "~> 0.0.1" - - # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - # - # Link your library with frameworks, or libraries. Libraries do not include - # the lib prefix of their name. - # - - # s.framework = "SomeFramework" - # s.frameworks = "SomeFramework", "AnotherFramework" - - # s.library = "iconv" - #spec.libraries = "RCTDataManager", "ReactKit" - -end diff --git a/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj b/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj deleted file mode 100644 index bfaa0413dc4..00000000000 --- a/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj +++ /dev/null @@ -1,256 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 58B512081A9E6CE300147676 /* RCTDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B512071A9E6CE300147676 /* RCTDataManager.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 58B511D91A9E6C8500147676 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 58B511DB1A9E6C8500147676 /* libRCTNetwork.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTNetwork.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 58B512061A9E6CE300147676 /* RCTDataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDataManager.h; sourceTree = ""; }; - 58B512071A9E6CE300147676 /* RCTDataManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDataManager.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 58B511D81A9E6C8500147676 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 58B511D21A9E6C8500147676 = { - isa = PBXGroup; - children = ( - 58B512061A9E6CE300147676 /* RCTDataManager.h */, - 58B512071A9E6CE300147676 /* RCTDataManager.m */, - 58B511DC1A9E6C8500147676 /* Products */, - ); - sourceTree = ""; - }; - 58B511DC1A9E6C8500147676 /* Products */ = { - isa = PBXGroup; - children = ( - 58B511DB1A9E6C8500147676 /* libRCTNetwork.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 58B511DA1A9E6C8500147676 /* RCTNetwork */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTNetwork" */; - buildPhases = ( - 58B511D71A9E6C8500147676 /* Sources */, - 58B511D81A9E6C8500147676 /* Frameworks */, - 58B511D91A9E6C8500147676 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RCTNetwork; - productName = RCTDataManager; - productReference = 58B511DB1A9E6C8500147676 /* libRCTNetwork.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 58B511D31A9E6C8500147676 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 58B511DA1A9E6C8500147676 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTNetwork" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 58B511D21A9E6C8500147676; - productRefGroup = 58B511DC1A9E6C8500147676 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 58B511DA1A9E6C8500147676 /* RCTNetwork */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 58B511D71A9E6C8500147676 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 58B512081A9E6CE300147676 /* RCTDataManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 58B511ED1A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 58B511EE1A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 58B511F01A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTNetwork; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 58B511F11A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RCTNetwork; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTNetwork" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511ED1A9E6C8500147676 /* Debug */, - 58B511EE1A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTNetwork" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511F01A9E6C8500147676 /* Debug */, - 58B511F11A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 58B511D31A9E6C8500147676 /* Project object */; -} diff --git a/Libraries/Network/XMLHttpRequest.ios.js b/Libraries/Network/XMLHttpRequest.ios.js deleted file mode 100644 index 042cbe4b93f..00000000000 --- a/Libraries/Network/XMLHttpRequest.ios.js +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule XMLHttpRequest - * @flow - */ -'use strict'; - -var RKDataManager = require('NativeModulesDeprecated').RKDataManager; - -var crc32 = require('crc32'); - -class XMLHttpRequest { - - UNSENT: number; - OPENED: number; - HEADERS_RECEIVED: number; - LOADING: number; - DONE: number; - - onreadystatechange: ?Function; - onload: ?Function; - upload: any; - readyState: number; - responseHeaders: ?Object; - responseText: ?string; - status: ?string; - - _method: ?string; - _url: ?string; - _headers: Object; - _sent: boolean; - _aborted: boolean; - - constructor() { - this.UNSENT = 0; - this.OPENED = 1; - this.HEADERS_RECEIVED = 2; - this.LOADING = 3; - this.DONE = 4; - - this.onreadystatechange = undefined; - this.upload = undefined; /* Upload not supported */ - this.readyState = this.UNSENT; - this.responseHeaders = undefined; - this.responseText = undefined; - this.status = undefined; - - this._method = null; - this._url = null; - this._headers = {}; - this._sent = false; - this._aborted = false; - } - - getAllResponseHeaders(): ?string { - /* Stub */ - return ''; - } - - getResponseHeader(header: string): ?string { - /* Stub */ - return ''; - } - - setRequestHeader(header: string, value: any): void { - this._headers[header] = value; - } - - open(method: string, url: string, async: ?boolean): void { - /* Other optional arguments are not supported */ - if (this.readyState !== this.UNSENT) { - throw new Error('Cannot open, already sending'); - } - if (async !== undefined && !async) { - // async is default - throw new Error('Synchronous http requests are not supported'); - } - this._method = method; - this._url = url; - this._aborted = false; - this._setReadyState(this.OPENED); - } - - send(data: any): void { - if (this.readyState !== this.OPENED) { - throw new Error('Request has not been opened'); - } - if (this._sent) { - throw new Error('Request has already been sent'); - } - this._sent = true; - - RKDataManager.queryData( - 'http', - JSON.stringify({ - method: this._method, - url: this._url, - data: data, - headers: this._headers, - }), - 'h' + crc32(this._method + '|' + this._url + '|' + data), - (result) => { - result = JSON.parse(result); - this._callback(result.status, result.responseHeaders, result.responseText); - } - ); - } - - abort(): void { - console.warn( - 'XMLHttpRequest: abort() cancels JS callbacks ' + - 'but not native HTTP request.' - ); - // only call onreadystatechange if there is something to abort, - // below logic is per spec - if (!(this.readyState === this.UNSENT || - (this.readyState === this.OPENED && !this._sent) || - this.readyState === this.DONE)) { - this._sent = false; - this._setReadyState(this.DONE); - } - if (this.readyState === this.DONE) { - this._sendLoad(); - } - this.readyState = this.UNSENT; - this._aborted = true; - } - - _setReadyState(newState: number): void { - this.readyState = newState; - // TODO: workaround flow bug with nullable function checks - var onreadystatechange = this.onreadystatechange; - if (onreadystatechange) { - // We should send an event to handler, but since we don't process that - // event anywhere, let's leave it empty - onreadystatechange(null); - } - } - - _sendLoad(): void { - // TODO: workaround flow bug with nullable function checks - var onload = this.onload; - if (onload) { - // We should send an event to handler, but since we don't process that - // event anywhere, let's leave it empty - onload(null); - } - } - - _callback(status: string, responseHeaders: ?Object, responseText: string): void { - if (this._aborted) { - return; - } - this.status = status; - this.responseHeaders = responseHeaders; - this.responseText = responseText; - this._setReadyState(this.DONE); - this._sendLoad(); - } -} - -module.exports = XMLHttpRequest; diff --git a/Libraries/RKBackendNode/queryLayoutByID.js b/Libraries/RKBackendNode/queryLayoutByID.js deleted file mode 100644 index 7dcd2487ef5..00000000000 --- a/Libraries/RKBackendNode/queryLayoutByID.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule queryLayoutByID - */ -'use strict'; - -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; - -/** - * Queries the layout of a view. The layout does not reflect the element as - * seen by the user, rather it reflects the position within the layout system, - * before any transforms are applied. - * - * The only other requirement is that the `pageX, pageY` values be in the same - * coordinate system that events' `pageX/Y` are reported. That means that for - * the web, `pageXOffset/pageYOffset` should be added to to - * getBoundingClientRect to make consistent with touches. - * - * var pageXOffset = window.pageXOffset; - * var pageYOffset = window.pageYOffset; - * - * This is an IOS specific implementation. - * - * @param {string} rootNodeID ID of the platform specific node to be measured. - * @param {function} onError `func(error)` - * @param {function} onSuccess `func(left, top, width, height, pageX, pageY)` - */ -var queryLayoutByID = function(rootNodeID, onError, onSuccess) { - // Native bridge doesn't *yet* surface errors. - RKUIManager.measure( - ReactIOSTagHandles.rootNodeIDToTag[rootNodeID], - onSuccess - ); -}; - -module.exports = queryLayoutByID; - diff --git a/Libraries/ReactIOS/IOSDefaultEventPluginOrder.js b/Libraries/ReactIOS/IOSDefaultEventPluginOrder.js deleted file mode 100644 index 51c951719bb..00000000000 --- a/Libraries/ReactIOS/IOSDefaultEventPluginOrder.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule IOSDefaultEventPluginOrder - */ -'use strict'; - -var IOSDefaultEventPluginOrder = [ - 'ResponderEventPlugin', - 'IOSNativeBridgeEventPlugin' -]; - -module.exports = IOSDefaultEventPluginOrder; diff --git a/Libraries/ReactIOS/IOSNativeBridgeEventPlugin.js b/Libraries/ReactIOS/IOSNativeBridgeEventPlugin.js deleted file mode 100644 index e698ad19673..00000000000 --- a/Libraries/ReactIOS/IOSNativeBridgeEventPlugin.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule IOSNativeBridgeEventPlugin - */ - -"use strict"; - -var EventPropagators = require('EventPropagators'); -var NativeModulesDeprecated = require('NativeModulesDeprecated'); -var SyntheticEvent = require('SyntheticEvent'); - -var merge = require('merge'); -var warning = require('warning'); - -var RKUIManager = NativeModulesDeprecated.RKUIManager; - -var customBubblingEventTypes = RKUIManager.customBubblingEventTypes; -var customDirectEventTypes = RKUIManager.customDirectEventTypes; - -var allTypesByEventName = {}; - -for (var bubblingTypeName in customBubblingEventTypes) { - allTypesByEventName[bubblingTypeName] = customBubblingEventTypes[bubblingTypeName]; -} - -for (var directTypeName in customDirectEventTypes) { - warning( - !customBubblingEventTypes[directTypeName], - "Event cannot be both direct and bubbling: %s", - directTypeName - ); - allTypesByEventName[directTypeName] = customDirectEventTypes[directTypeName]; -} - -var IOSNativeBridgeEventPlugin = { - - eventTypes: merge(customBubblingEventTypes, customDirectEventTypes), - - /** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of synthetic events. - * @see {EventPluginHub.extractEvents} - */ - extractEvents: function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; - var directDispatchConfig = customDirectEventTypes[topLevelType]; - var event = SyntheticEvent.getPooled( - bubbleDispatchConfig || directDispatchConfig, - topLevelTargetID, - nativeEvent - ); - if (bubbleDispatchConfig) { - EventPropagators.accumulateTwoPhaseDispatches(event); - } else if (directDispatchConfig) { - EventPropagators.accumulateDirectDispatches(event); - } else { - return null; - } - return event; - } -}; - -module.exports = IOSNativeBridgeEventPlugin; - diff --git a/Libraries/ReactIOS/NativeMethodsMixin.js b/Libraries/ReactIOS/NativeMethodsMixin.js deleted file mode 100644 index ebfc246f0a7..00000000000 --- a/Libraries/ReactIOS/NativeMethodsMixin.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule NativeMethodsMixin - */ -'use strict'; - -var NativeModules = require('NativeModules'); -var NativeModulesDeprecated = require('NativeModulesDeprecated'); -var RKUIManager = NativeModules.RKUIManager; -var RKUIManagerDeprecated = NativeModulesDeprecated.RKUIManager; -var RKPOPAnimationManagerDeprecated = NativeModulesDeprecated.RKPOPAnimationManager; -var TextInputState = require('TextInputState'); - -var flattenStyle = require('flattenStyle'); -var invariant = require('invariant'); -var mergeFast = require('mergeFast'); - -var animationIDInvariant = function(funcName, anim) { - invariant( - anim, - funcName + ' must be called with a valid animation ID returned from' + - ' POPAnimation.createAnimation, received: "' + anim + '"' - ); -}; - -var NativeMethodsMixin = { - addAnimation: function(anim, callback) { - animationIDInvariant('addAnimation', anim); - RKPOPAnimationManagerDeprecated.addAnimation(this.getNodeHandle(), anim, callback); - }, - - removeAnimation: function(anim) { - animationIDInvariant('removeAnimation', anim); - RKPOPAnimationManagerDeprecated.removeAnimation(this.getNodeHandle(), anim); - }, - - measure: function(callback) { - RKUIManagerDeprecated.measure(this.getNodeHandle(), callback); - }, - - measureLayout: function(relativeToNativeNode, onSuccess, onFail) { - RKUIManager.measureLayout( - this.getNodeHandle(), - relativeToNativeNode, - onFail, - onSuccess - ); - }, - - /** - * This function sends props straight to native. They will not participate - * in future diff process, this means that if you do not include them in the - * next render, they will remain active. - */ - setNativeProps: function(nativeProps) { - // nativeProps contains a style attribute that's going to be flattened - // and all the attributes expanded in place. In order to make this - // process do as few allocations and copies as possible, we return - // one if the other is empty. Only if both have values then we create - // a new object and merge. - var hasOnlyStyle = true; - for (var key in nativeProps) { - if (key !== 'style') { - hasOnlyStyle = false; - break; - } - } - var style = flattenStyle(nativeProps.style); - - var props = null; - if (hasOnlyStyle) { - props = style; - } else if (!style) { - props = nativeProps; - } else { - props = mergeFast(nativeProps, style); - } - - RKUIManagerDeprecated.updateView( - this.getNodeHandle(), - this.viewConfig.uiViewClassName, - props - ); - }, - - focus: function() { - TextInputState.focusTextInput(this.getNodeHandle()); - }, - - blur: function() { - TextInputState.blurTextInput(this.getNodeHandle()); - } -}; - -function throwOnStylesProp(component, props) { - if (props.styles !== undefined) { - var owner = component._owner || null; - var name = component.constructor.displayName; - var msg = '`styles` is not a supported property of `' + name + '`, did ' + - 'you mean `style` (singular)?'; - if (owner && owner.constructor && owner.constructor.displayName) { - msg += '\n\nCheck the `' + owner.constructor.displayName + '` parent ' + - ' component.'; - } - throw new Error(msg); - } -} -if (__DEV__) { - invariant( - !NativeMethodsMixin.componentWillMount && - !NativeMethodsMixin.componentWillReceiveProps, - 'Do not override existing functions.' - ); - NativeMethodsMixin.componentWillMount = function () { - throwOnStylesProp(this, this.props); - }; - NativeMethodsMixin.componentWillReceiveProps = function (newProps) { - throwOnStylesProp(this, newProps); - }; -} - -module.exports = NativeMethodsMixin; diff --git a/Libraries/ReactIOS/React.js b/Libraries/ReactIOS/React.js deleted file mode 100644 index 63de6d84caf..00000000000 --- a/Libraries/ReactIOS/React.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule React - */ - -"use strict"; - -module.exports = require('ReactIOS'); diff --git a/Libraries/ReactIOS/ReactIOS.js b/Libraries/ReactIOS/ReactIOS.js deleted file mode 100644 index 4b4b19db02c..00000000000 --- a/Libraries/ReactIOS/ReactIOS.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOS - */ - -"use strict"; - -var ReactChildren = require('ReactChildren'); -var ReactClass = require('ReactClass'); -var ReactComponent = require('ReactComponent'); -var ReactContext = require('ReactContext'); -var ReactCurrentOwner = require('ReactCurrentOwner'); -var ReactElement = require('ReactElement'); -var ReactElementValidator = require('ReactElementValidator'); -var ReactInstanceHandles = require('ReactInstanceHandles'); -var ReactIOSDefaultInjection = require('ReactIOSDefaultInjection'); -var ReactIOSMount = require('ReactIOSMount'); -var ReactPropTypes = require('ReactPropTypes'); - -var deprecated = require('deprecated'); -var invariant = require('invariant'); -var onlyChild = require('onlyChild'); - -ReactIOSDefaultInjection.inject(); - -var createElement = ReactElement.createElement; -var createFactory = ReactElement.createFactory; -var cloneElement = ReactElement.cloneElement; - -if (__DEV__) { - createElement = ReactElementValidator.createElement; - createFactory = ReactElementValidator.createFactory; - cloneElement = ReactElementValidator.cloneElement; -} - -var resolveDefaultProps = function(element) { - // Could be optimized, but not currently in heavy use. - var defaultProps = element.type.defaultProps; - var props = element.props; - for (var propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } - } -}; - -// Experimental optimized element creation -var augmentElement = function(element) { - if (__DEV__) { - invariant( - false, - 'This optimized path should never be used in DEV mode because ' + - 'it does not provide validation. Check your JSX transform.' - ); - } - element._owner = ReactCurrentOwner.current; - element._context = ReactContext.current; - if (element.type.defaultProps) { - resolveDefaultProps(element); - } - return element; -}; - -var render = function(component, mountInto) { - ReactIOSMount.renderComponent(component, mountInto); -}; - -var ReactIOS = { - hasReactIOSInitialized: false, - Children: { - map: ReactChildren.map, - forEach: ReactChildren.forEach, - count: ReactChildren.count, - only: onlyChild - }, - PropTypes: ReactPropTypes, - createClass: ReactClass.createClass, - createElement: createElement, - createFactory: createFactory, - cloneElement: cloneElement, - _augmentElement: augmentElement, - render: render, - unmountComponentAtNode: ReactIOSMount.unmountComponentAtNode, - /** - * Used by the debugger. - */ - __internals: { - Component: ReactComponent, - CurrentOwner: ReactCurrentOwner, - InstanceHandles: ReactInstanceHandles, - Mount: ReactIOSMount, - }, - - // Hook for JSX spread, don't use this for anything else. - __spread: Object.assign, - - unmountComponentAtNodeAndRemoveContainer: ReactIOSMount.unmountComponentAtNodeAndRemoveContainer, - isValidClass: ReactElement.isValidFactory, - isValidElement: ReactElement.isValidElement, - - // Deprecations (remove for 0.13) - renderComponent: deprecated( - 'React', - 'renderComponent', - 'render', - this, - render - ), - isValidComponent: deprecated( - 'React', - 'isValidComponent', - 'isValidElement', - this, - ReactElement.isValidElement - ) -}; - -module.exports = ReactIOS; diff --git a/Libraries/ReactIOS/ReactIOSComponentEnvironment.js b/Libraries/ReactIOS/ReactIOSComponentEnvironment.js deleted file mode 100644 index ac67a7580e4..00000000000 --- a/Libraries/ReactIOS/ReactIOSComponentEnvironment.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSComponentEnvironment - */ -'use strict'; -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; - -var ReactIOSDOMIDOperations = require('ReactIOSDOMIDOperations'); -var ReactIOSReconcileTransaction = require('ReactIOSReconcileTransaction'); -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var ReactPerf = require('ReactPerf'); - -var ReactIOSComponentEnvironment = { - - processChildrenUpdates: ReactIOSDOMIDOperations.dangerouslyProcessChildrenUpdates, - - replaceNodeWithMarkupByID: ReactIOSDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID, - - /** - * Nothing to do for UIKit bridge. - * - * @private - */ - unmountIDFromEnvironment: function(/*rootNodeID*/) { - - }, - - /** - * @param {DOMElement} Element to clear. - */ - clearNode: function(/*containerView*/) { - - }, - - ReactReconcileTransaction: ReactIOSReconcileTransaction, -}; - -module.exports = ReactIOSComponentEnvironment; diff --git a/Libraries/ReactIOS/ReactIOSComponentMixin.js b/Libraries/ReactIOS/ReactIOSComponentMixin.js deleted file mode 100644 index f9ddde2c208..00000000000 --- a/Libraries/ReactIOS/ReactIOSComponentMixin.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSComponentMixin - */ -'use strict'; - -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var ReactInstanceMap = require('ReactInstanceMap'); - -/** - * ReactNative vs ReactWeb - * ----------------------- - * React treats some pieces of data opaquely. This means that the information - * is first class (it can be passed around), but cannot be inspected. This - * allows us to build infrastructure that reasons about resources, without - * making assumptions about the nature of those resources, and this allows that - * infra to be shared across multiple platforms, where the resources are very - * different. General infra (such as `ReactMultiChild`) reasons opaquely about - * the data, but platform specific code (such as `ReactIOSNativeComponent`) can - * make assumptions about the data. - * - * - * `rootNodeID`, uniquely identifies a position in the generated native view - * tree. Many layers of composite components (created with `React.createClass`) - * can all share the same `rootNodeID`. - * - * `nodeHandle`: A sufficiently unambiguous way to refer to a lower level - * resource (dom node, native view etc). The `rootNodeID` is sufficient for web - * `nodeHandle`s, because the position in a tree is always enough to uniquely - * identify a DOM node (we never have nodes in some bank outside of the - * document). The same would be true for `ReactNative`, but we must maintain a - * mapping that we can send efficiently serializable - * strings across native boundaries. - * - * Opaque name TodaysWebReact FutureWebWorkerReact ReactNative - * ---------------------------------------------------------------------------- - * nodeHandle N/A rootNodeID tag - * - * - * `mountImage`: A way to represent the potential to create lower level - * resources whos `nodeHandle` can be discovered immediately by knowing the - * `rootNodeID`. Today's web react represents this with `innerHTML` annotated - * with DOM ids that match the `rootNodeID`. - * - * Opaque name TodaysWebReact FutureWebWorkerReact ReactNative - * ---------------------------------------------------------------------------- - * mountImage innerHTML innerHTML {rootNodeID, tag} - * - */ -var ReactIOSComponentMixin = { - /** - * This has no particular meaning in ReactIOS. If this were in the DOM, this - * would return the DOM node. There should be nothing that invokes this - * method. Any current callers of this are mistaken - they should be invoking - * `getNodeHandle`. - */ - getNativeNode: function() { - // TODO (balpert): Wrap iOS native components in a composite wrapper, then - // ReactInstanceMap.get here will always succeed - return ReactIOSTagHandles.rootNodeIDToTag[ - (ReactInstanceMap.get(this) || this)._rootNodeID - ]; - }, - - getNodeHandle: function() { - return ReactIOSTagHandles.rootNodeIDToTag[ - (ReactInstanceMap.get(this) || this)._rootNodeID - ]; - } -}; - -module.exports = ReactIOSComponentMixin; diff --git a/Libraries/ReactIOS/ReactIOSDOMIDOperations.js b/Libraries/ReactIOS/ReactIOSDOMIDOperations.js deleted file mode 100644 index 51a52015570..00000000000 --- a/Libraries/ReactIOS/ReactIOSDOMIDOperations.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSDOMIDOperations - * @typechecks static-only - */ - -"use strict"; - -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var ReactMultiChildUpdateTypes = require('ReactMultiChildUpdateTypes'); -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; -var ReactPerf = require('ReactPerf'); - -/** - * Updates a component's children by processing a series of updates. - * For each of the update/create commands, the `fromIndex` refers to the index - * that the item existed at *before* any of the updates are applied, and the - * `toIndex` refers to the index after *all* of the updates are applied - * (including deletes/moves). TODO: refactor so this can be shared with - * DOMChildrenOperations. - * - * @param {array} updates List of update configurations. - * @param {array} markup List of markup strings - in the case of React - * IOS, the ids of new components assumed to be already created. - */ -var dangerouslyProcessChildrenUpdates = function(childrenUpdates, markupList) { - if (!childrenUpdates.length) { - return; - } - var byContainerTag = {}; - // Group by parent ID - send them across the bridge in separate commands per - // containerID. - for (var i = 0; i < childrenUpdates.length; i++) { - var update = childrenUpdates[i]; - var containerTag = ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(update.parentID); - var updates = byContainerTag[containerTag] || (byContainerTag[containerTag] = {}); - if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING) { - (updates.moveFromIndices || (updates.moveFromIndices = [])).push(update.fromIndex); - (updates.moveToIndices || (updates.moveToIndices = [])).push(update.toIndex); - } else if (update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { - (updates.removeAtIndices || (updates.removeAtIndices = [])).push(update.fromIndex); - } else if (update.type === ReactMultiChildUpdateTypes.INSERT_MARKUP) { - var mountImage = markupList[update.markupIndex]; - var tag = mountImage.tag; - var rootNodeID = mountImage.rootNodeID; - ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle(rootNodeID, tag); - (updates.addAtIndices || (updates.addAtIndices = [])).push(update.toIndex); - (updates.addChildTags || (updates.addChildTags = [])).push(tag); - } - } - // Note this enumeration order will be different on V8! Move `byContainerTag` - // to a sparse array as soon as we confirm there are not horrible perf - // penalties. - for (var updateParentTagString in byContainerTag) { - var updateParentTagNumber = +updateParentTagString; - var childUpdatesToSend = byContainerTag[updateParentTagNumber]; - RKUIManager.manageChildren( - updateParentTagNumber, - childUpdatesToSend.moveFromIndices, - childUpdatesToSend.moveToIndices, - childUpdatesToSend.addChildTags, - childUpdatesToSend.addAtIndices, - childUpdatesToSend.removeAtIndices - ); - } -}; - -/** - * Operations used to process updates to DOM nodes. This is made injectable via - * `ReactComponent.DOMIDOperations`. - */ -var ReactIOSDOMIDOperations = { - dangerouslyProcessChildrenUpdates: ReactPerf.measure( - // FIXME(frantic): #4441289 Hack to avoid modifying react-tools - 'ReactDOMIDOperations', - 'dangerouslyProcessChildrenUpdates', - dangerouslyProcessChildrenUpdates - ), - - /** - * Replaces a view that exists in the document with markup. - * - * @param {string} id ID of child to be replaced. - * @param {string} markup Mount image to replace child with id. - */ - dangerouslyReplaceNodeWithMarkupByID: ReactPerf.measure( - 'ReactDOMIDOperations', - 'dangerouslyReplaceNodeWithMarkupByID', - function(id, mountImage) { - var oldTag = ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(id); - RKUIManager.replaceExistingNonRootView(oldTag, mountImage.tag); - ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle(id, mountImage.tag); - } - ), -}; - -module.exports = ReactIOSDOMIDOperations; diff --git a/Libraries/ReactIOS/ReactIOSDefaultInjection.js b/Libraries/ReactIOS/ReactIOSDefaultInjection.js deleted file mode 100644 index 09dc9ea0a54..00000000000 --- a/Libraries/ReactIOS/ReactIOSDefaultInjection.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSDefaultInjection - */ - -"use strict"; - -/** - * Make sure `setTimeout`/`setInterval` are patched correctly. - */ -require('InitializeJavaScriptAppEngine'); -var EventPluginHub = require('EventPluginHub'); -var EventPluginUtils = require('EventPluginUtils'); -var IOSDefaultEventPluginOrder = require('IOSDefaultEventPluginOrder'); -var IOSNativeBridgeEventPlugin = require('IOSNativeBridgeEventPlugin'); -var NodeHandle = require('NodeHandle'); -var ReactClass = require('ReactClass'); -var ReactComponentEnvironment = require('ReactComponentEnvironment'); -var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy'); -var ReactInstanceHandles = require('ReactInstanceHandles'); -var ReactIOSComponentEnvironment = require('ReactIOSComponentEnvironment'); -var ReactIOSComponentMixin = require('ReactIOSComponentMixin'); -var ReactIOSGlobalInteractionHandler = require('ReactIOSGlobalInteractionHandler'); -var ReactIOSGlobalResponderHandler = require('ReactIOSGlobalResponderHandler'); -var ReactIOSMount = require('ReactIOSMount'); -var ReactIOSTextComponent = require('ReactIOSTextComponent'); -var ReactNativeComponent = require('ReactNativeComponent'); -var ReactUpdates = require('ReactUpdates'); -var ResponderEventPlugin = require('ResponderEventPlugin'); -var UniversalWorkerNodeHandle = require('UniversalWorkerNodeHandle'); - -// Just to ensure this gets packaged, since its only caller is from Native. -require('RCTEventEmitter'); -require('RCTLog'); -require('RCTJSTimers'); - -function inject() { - /** - * Inject module for resolving DOM hierarchy and plugin ordering. - */ - EventPluginHub.injection.injectEventPluginOrder(IOSDefaultEventPluginOrder); - EventPluginHub.injection.injectInstanceHandle(ReactInstanceHandles); - - ResponderEventPlugin.injection.injectGlobalResponderHandler( - ReactIOSGlobalResponderHandler - ); - - ResponderEventPlugin.injection.injectGlobalInteractionHandler( - ReactIOSGlobalInteractionHandler - ); - - /** - * Some important event plugins included by default (without having to require - * them). - */ - EventPluginHub.injection.injectEventPluginsByName({ - 'ResponderEventPlugin': ResponderEventPlugin, - 'IOSNativeBridgeEventPlugin': IOSNativeBridgeEventPlugin - }); - - ReactUpdates.injection.injectReconcileTransaction( - ReactIOSComponentEnvironment.ReactReconcileTransaction - ); - - ReactUpdates.injection.injectBatchingStrategy( - ReactDefaultBatchingStrategy - ); - - ReactComponentEnvironment.injection.injectEnvironment( - ReactIOSComponentEnvironment - ); - - EventPluginUtils.injection.injectMount(ReactIOSMount); - - ReactClass.injection.injectMixin(ReactIOSComponentMixin); - - ReactNativeComponent.injection.injectTextComponentClass( - ReactIOSTextComponent - ); - - NodeHandle.injection.injectImplementation(UniversalWorkerNodeHandle); -} - -module.exports = { - inject: inject, -}; diff --git a/Libraries/ReactIOS/ReactIOSEventEmitter.js b/Libraries/ReactIOS/ReactIOSEventEmitter.js deleted file mode 100644 index ab768c92771..00000000000 --- a/Libraries/ReactIOS/ReactIOSEventEmitter.js +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSEventEmitter - * @typechecks static-only - */ - -"use strict"; - -var EventPluginHub = require('EventPluginHub'); -var ReactEventEmitterMixin = require('ReactEventEmitterMixin'); -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var NodeHandle = require('NodeHandle'); -var EventConstants = require('EventConstants'); - -var merge = require('merge'); -var warning = require('warning'); - -var topLevelTypes = EventConstants.topLevelTypes; - -/** - * Version of `ReactBrowserEventEmitter` that works on the receiving side of a - * serialized worker boundary. - */ - -// Shared default empty native event - conserve memory. -var EMPTY_NATIVE_EVENT = {}; - -/** - * Selects a subsequence of `Touch`es, without destroying `touches`. - * - * @param {Array} touches Deserialized touch objects. - * @param {Array} indices Indices by which to pull subsequence. - * @return {Array} Subsequence of touch objects. - */ -var touchSubsequence = function(touches, indices) { - var ret = []; - for (var i = 0; i < indices.length; i++) { - ret.push(touches[indices[i]]); - } - return ret; -}; - -/** - * TODO: Pool all of this. - * - * Destroys `touches` by removing touch objects at indices `indices`. This is - * to maintain compatibility with W3C touch "end" events, where the active - * touches don't include the set that has just been "ended". - * - * @param {Array} touches Deserialized touch objects. - * @param {Array} indices Indices to remove from `touches`. - * @return {Array} Subsequence of removed touch objects. - */ -var removeTouchesAtIndices = function(touches, indices) { - var rippedOut = []; - for (var i = 0; i < indices.length; i++) { - var index = indices[i]; - rippedOut.push(touches[index]); - touches[index] = null; - } - var fillAt = 0; - for (var j = 0; j < touches.length; j++) { - var cur = touches[j]; - if (cur !== null) { - touches[fillAt++] = cur; - } - } - touches.length = fillAt; - return rippedOut; -}; - -/** - * `ReactIOSEventEmitter` is used to attach top-level event listeners. For example: - * - * ReactIOSEventEmitter.putListener('myID', 'onClick', myFunction); - * - * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'. - * - * @internal - */ -var ReactIOSEventEmitter = merge(ReactEventEmitterMixin, { - - registrationNames: EventPluginHub.registrationNameModules, - - putListener: EventPluginHub.putListener, - - getListener: EventPluginHub.getListener, - - deleteListener: EventPluginHub.deleteListener, - - deleteAllListeners: EventPluginHub.deleteAllListeners, - - /** - * Internal version of `receiveEvent` in terms of normalized (non-tag) - * `rootNodeID`. - * - * @see receiveEvent. - * - * @param {rootNodeID} rootNodeID React root node ID that event occured on. - * @param {TopLevelType} topLevelType Top level type of event. - * @param {object} nativeEventParam Object passed from native. - */ - _receiveRootNodeIDEvent: function(rootNodeID, topLevelType, nativeEventParam) { - var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT; - ReactIOSEventEmitter.handleTopLevel( - topLevelType, - rootNodeID, - rootNodeID, - nativeEvent - ); - }, - - /** - * Publically exposed method on module for native objc to invoke when a top - * level event is extracted. - * @param {rootNodeID} rootNodeID React root node ID that event occured on. - * @param {TopLevelType} topLevelType Top level type of event. - * @param {object} nativeEventParam Object passed from native. - */ - receiveEvent: function(tag, topLevelType, nativeEventParam) { - var rootNodeID = ReactIOSTagHandles.tagToRootNodeID[tag]; - ReactIOSEventEmitter._receiveRootNodeIDEvent( - rootNodeID, - topLevelType, - nativeEventParam - ); - }, - - /** - * Simple multi-wrapper around `receiveEvent` that is intended to receive an - * efficient representation of `Touch` objects, and other information that - * can be used to construct W3C compliant `Event` and `Touch` lists. - * - * This may create dispatch behavior that differs than web touch handling. We - * loop through each of the changed touches and receive it as a single event. - * So two `touchStart`/`touchMove`s that occur simultaneously are received as - * two separate touch event dispatches - when they arguably should be one. - * - * This implementation reuses the `Touch` objects themselves as the `Event`s - * since we dispatch an event for each touch (though that might not be spec - * compliant). The main purpose of reusing them is to save allocations. - * - * TODO: Dispatch multiple changed touches in one event. The bubble path - * could be the first common ancestor of all the `changedTouches`. - * - * One difference between this behavior and W3C spec: cancelled touches will - * not appear in `.touches`, or in any future `.touches`, though they may - * still be "actively touching the surface". - * - * Web desktop polyfills only need to construct a fake touch event with - * identifier 0, also abandoning traditional click handlers. - */ - receiveTouches: function(eventTopLevelType, touches, changedIndices) { - var changedTouches = - eventTopLevelType === topLevelTypes.topTouchEnd || - eventTopLevelType === topLevelTypes.topTouchCancel ? - removeTouchesAtIndices(touches, changedIndices) : - touchSubsequence(touches, changedIndices); - - for (var jj = 0; jj < changedTouches.length; jj++) { - var touch = changedTouches[jj]; - // Touch objects can fullfill the role of `DOM` `Event` objects if we set - // the `changedTouches`/`touches`. This saves allocations. - touch.changedTouches = changedTouches; - touch.touches = touches; - var nativeEvent = touch; - var rootNodeID = null; - var target = nativeEvent.target; - if (target !== null && target !== undefined) { - if (target < ReactIOSTagHandles.tagsStartAt) { - if (__DEV__) { - warning( - false, - 'A view is reporting that a touch occured on tag zero.' - ); - } - } else { - rootNodeID = NodeHandle.getRootNodeID(target); - } - } - ReactIOSEventEmitter._receiveRootNodeIDEvent( - rootNodeID, - eventTopLevelType, - nativeEvent - ); - } - } -}); - -module.exports = ReactIOSEventEmitter; diff --git a/Libraries/ReactIOS/ReactIOSGlobalInteractionHandler.js b/Libraries/ReactIOS/ReactIOSGlobalInteractionHandler.js deleted file mode 100644 index 2b9c994ac3d..00000000000 --- a/Libraries/ReactIOS/ReactIOSGlobalInteractionHandler.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @providesModule ReactIOSGlobalInteractionHandler - */ -'use strict'; - -var InteractionManager = require('InteractionManager'); - -// Interaction handle is created/cleared when responder is granted or -// released/terminated. -var interactionHandle = null; - -var ReactIOSGlobalInteractionHandler = { - onChange: function(numberActiveTouches) { - if (numberActiveTouches === 0) { - if (interactionHandle) { - InteractionManager.clearInteractionHandle(interactionHandle); - interactionHandle = null; - } - } else if (!interactionHandle) { - interactionHandle = InteractionManager.createInteractionHandle(); - } - } -}; - -module.exports = ReactIOSGlobalInteractionHandler; diff --git a/Libraries/ReactIOS/ReactIOSGlobalResponderHandler.js b/Libraries/ReactIOS/ReactIOSGlobalResponderHandler.js deleted file mode 100644 index 4a9c944109e..00000000000 --- a/Libraries/ReactIOS/ReactIOSGlobalResponderHandler.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @providesModule ReactIOSGlobalResponderHandler - */ -'use strict'; - -var RKUIManager = require('NativeModules').RKUIManager; -var ReactIOSTagHandles = require('ReactIOSTagHandles'); - -var ReactIOSGlobalResponderHandler = { - onChange: function(from, to) { - if (to !== null) { - RKUIManager.setJSResponder( - ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(to) - ); - } else { - RKUIManager.clearJSResponder(); - } - } -}; - -module.exports = ReactIOSGlobalResponderHandler; diff --git a/Libraries/ReactIOS/ReactIOSMount.js b/Libraries/ReactIOS/ReactIOSMount.js deleted file mode 100644 index 23691143a7d..00000000000 --- a/Libraries/ReactIOS/ReactIOSMount.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSMount - */ -'use strict'; - -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; - -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var ReactPerf = require('ReactPerf'); -var ReactReconciler = require('ReactReconciler'); -var ReactUpdates = require('ReactUpdates'); - -var emptyObject = require('emptyObject'); -var instantiateReactComponent = require('instantiateReactComponent'); -var invariant = require('invariant'); - -var TOP_ROOT_NODE_IDS = {}; - -function instanceNumberToChildRootID(rootNodeID, instanceNumber) { - return rootNodeID + '[' + instanceNumber + ']'; -} - -/** - * Mounts this component and inserts it into the DOM. - * - * @param {ReactComponent} componentInstance The instance to mount. - * @param {number} rootID ID of the root node. - * @param {number} container container element to mount into. - * @param {ReactReconcileTransaction} transaction - */ -function mountComponentIntoNode( - componentInstance, - rootID, - container, - transaction) { - var markup = ReactReconciler.mountComponent( - componentInstance, rootID, transaction, emptyObject - ); - componentInstance._isTopLevel = true; - ReactIOSMount._mountImageIntoNode(markup, container); -} - -/** - * Batched mount. - * - * @param {ReactComponent} componentInstance The instance to mount. - * @param {number} rootID ID of the root node. - * @param {number} container container element to mount into. - */ -function batchedMountComponentIntoNode( - componentInstance, - rootID, - container) { - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); - transaction.perform( - mountComponentIntoNode, - null, - componentInstance, - rootID, - container, - transaction - ); - ReactUpdates.ReactReconcileTransaction.release(transaction); -} - -/** - * As soon as `ReactMount` is refactored to not rely on the DOM, we can share - * code between the two. For now, we'll hard code the ID logic. - */ -var ReactIOSMount = { - instanceCount: 0, - - _instancesByContainerID: {}, - - /** - * @param {ReactComponent} instance Instance to render. - * @param {containerTag} containerView Handle to native view tag - */ - renderComponent: function(descriptor, containerTag) { - var instance = instantiateReactComponent(descriptor); - - if (!ReactIOSTagHandles.reactTagIsNativeTopRootID(containerTag)) { - console.error('You cannot render into anything but a top root'); - return; - } - - var topRootNodeID = ReactIOSTagHandles.allocateRootNodeIDForTag(containerTag); - ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle( - topRootNodeID, - containerTag - ); - TOP_ROOT_NODE_IDS[topRootNodeID] = true; - - var childRootNodeID = instanceNumberToChildRootID( - topRootNodeID, - ReactIOSMount.instanceCount++ - ); - ReactIOSMount._instancesByContainerID[topRootNodeID] = instance; - - // The initial render is synchronous but any updates that happen during - // rendering, in componentWillMount or componentDidMount, will be batched - // according to the current batching strategy. - - ReactUpdates.batchedUpdates( - batchedMountComponentIntoNode, - instance, - childRootNodeID, - topRootNodeID - ); - }, - - /** - * @param {View} view View tree image. - * @param {number} containerViewID View to insert sub-view into. - */ - _mountImageIntoNode: ReactPerf.measure( - // FIXME(frantic): #4441289 Hack to avoid modifying react-tools - 'ReactComponentBrowserEnvironment', - 'mountImageIntoNode', - function(mountImage, containerID) { - // Since we now know that the `mountImage` has been mounted, we can - // mark it as such. - ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle( - mountImage.rootNodeID, - mountImage.tag - ); - var addChildTags = [mountImage.tag]; - var addAtIndices = [0]; - RKUIManager.manageChildren( - ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID), - null, // moveFromIndices - null, // moveToIndices - addChildTags, - addAtIndices, - null // removeAtIndices - ); - } - ), - - /** - * Standard unmounting of the component that is rendered into `containerID`, - * but will also execute a command to remove the actual container view - * itself. This is useful when a client is cleaning up a React tree, and also - * knows that the container will no longer be needed. When executing - * asynchronously, it's easier to just have this method be the one that calls - * for removal of the view. - */ - unmountComponentAtNodeAndRemoveContainer: function(containerTag) { - ReactIOSMount.unmountComponentAtNode(containerTag); - // call back into native to remove all of the subviews from this container - RKUIManager.removeRootView(containerTag); - }, - - /** - * Unmount component at container ID by iterating through each child component - * that has been rendered and unmounting it. There should just be one child - * component at this time. - */ - unmountComponentAtNode: function(containerTag) { - var containerID = ReactIOSTagHandles.tagToRootNodeID[containerTag]; - - invariant( - TOP_ROOT_NODE_IDS[containerID], - 'We only currently support removing components from the root node' - ); - var instance = ReactIOSMount._instancesByContainerID[containerID]; - if (!instance) { - console.error('Tried to unmount a component that does not exist'); - return false; - } - ReactIOSMount.unmountComponentFromNode(instance, containerID); - delete ReactIOSMount._instancesByContainerID[containerID]; - delete TOP_ROOT_NODE_IDS[containerID]; - return true; - }, - - /** - * Unmounts a component and sends messages back to iOS to remove its subviews. - * - * @param {ReactComponent} instance React component instance. - * @param {int} containerID ID of container we're removing from. - * @final - * @internal - * @see {ReactIOSMount.unmountComponentAtNode} - */ - unmountComponentFromNode: function(instance, containerID) { - // call back into native to remove all of the subviews from this container - instance.unmountComponent(); - var containerTag = - ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID); - RKUIManager.removeSubviewsFromContainerWithID(containerTag); - }, - - getNode: function(id) { - return id; - } -}; - -ReactIOSMount.renderComponent = ReactPerf.measure( - 'ReactMount', - '_renderNewRootComponent', - ReactIOSMount.renderComponent -); - -module.exports = ReactIOSMount; diff --git a/Libraries/ReactIOS/ReactIOSNativeComponent.js b/Libraries/ReactIOS/ReactIOSNativeComponent.js deleted file mode 100644 index df8b5983308..00000000000 --- a/Libraries/ReactIOS/ReactIOSNativeComponent.js +++ /dev/null @@ -1,268 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSNativeComponent - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var ReactIOSComponentMixin = require('ReactIOSComponentMixin'); -var ReactIOSEventEmitter = require('ReactIOSEventEmitter'); -var ReactIOSStyleAttributes = require('ReactIOSStyleAttributes'); -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var ReactMultiChild = require('ReactMultiChild'); -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; - -var styleDiffer = require('styleDiffer'); -var deepFreezeAndThrowOnMutationInDev = require('deepFreezeAndThrowOnMutationInDev'); -var diffRawProperties = require('diffRawProperties'); -var flattenStyle = require('flattenStyle'); -var warning = require('warning'); - -var registrationNames = ReactIOSEventEmitter.registrationNames; -var putListener = ReactIOSEventEmitter.putListener; -var deleteAllListeners = ReactIOSEventEmitter.deleteAllListeners; - -/** - * @constructor ReactIOSNativeComponent - * @extends ReactComponent - * @extends ReactMultiChild - * @param {!object} UIKit View Configuration. - */ -var ReactIOSNativeComponent = function(viewConfig) { - this.viewConfig = viewConfig; -}; - -/** - * Generates and caches arrays of the form: - * - * [0, 1, 2, 3] - * [0, 1, 2, 3, 4] - * [0, 1] - * - * @param {number} size Size of array to generate. - * @return {Array} Array with values that mirror the index. - */ -var cachedIndexArray = function(size) { - var cachedResult = cachedIndexArray._cache[size]; - if (!cachedResult) { - var arr = []; - for (var i = 0; i < size; i++) { - arr[i] = i; - } - return cachedIndexArray._cache[size] = arr; - } else { - return cachedResult; - } -}; -cachedIndexArray._cache = {}; - -/** - * Mixin for containers that contain UIViews. NOTE: markup is rendered markup - * which is a `viewID` ... see the return value for `mountComponent` ! - */ -ReactIOSNativeComponent.Mixin = { - getPublicInstance: function() { - // TODO: This should probably use a composite wrapper - return this; - }, - - construct: function(element) { - this._currentElement = element; - }, - - unmountComponent: function() { - deleteAllListeners(this._rootNodeID); - this.unmountChildren(); - this._rootNodeID = null; - }, - - /** - * Every native component is responsible for allocating its own `tag`, and - * issuing the native `createView` command. But it is not responsible for - * recording the fact that its own `rootNodeID` is associated with a - * `nodeHandle`. Only the code that actually adds its `nodeHandle` (`tag`) as - * a child of a container can confidently record that in - * `ReactIOSTagHandles`. - */ - initializeChildren: function(children, containerTag, transaction, context) { - var mountImages = this.mountChildren(children, transaction, context); - // In a well balanced tree, half of the nodes are in the bottom row and have - // no children - let's avoid calling out to the native bridge for a large - // portion of the children. - if (mountImages.length) { - var indexes = cachedIndexArray(mountImages.length); - // TODO: Pool these per platform view class. Reusing the `mountImages` - // array would likely be a jit deopt. - var createdTags = []; - for (var i = 0; i < mountImages.length; i++) { - var mountImage = mountImages[i]; - var childTag = mountImage.tag; - var childID = mountImage.rootNodeID; - warning( - mountImage && mountImage.rootNodeID && mountImage.tag, - 'Mount image returned does not have required data' - ); - ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle( - childID, - childTag - ); - createdTags[i] = mountImage.tag; - } - RKUIManager - .manageChildren(containerTag, null, null, createdTags, indexes, null); - } - }, - - - /** - * Beware, this function has side effect to store this.previousFlattenedStyle! - * - * @param {!object} prevProps Previous properties - * @param {!object} nextProps Next properties - * @param {!object} validAttributes Set of valid attributes and how they - * should be diffed - */ - computeUpdatedProperties: function(prevProps, nextProps, validAttributes) { - if (__DEV__) { - for (var key in nextProps) { - if (nextProps.hasOwnProperty(key) && - nextProps[key] && - validAttributes[key]) { - deepFreezeAndThrowOnMutationInDev(nextProps[key]); - } - } - } - - var updatePayload = diffRawProperties( - null, // updatePayload - prevProps, - nextProps, - validAttributes - ); - - // The style property is a deeply nested element which includes numbers - // to represent static objects. Most of the time, it doesn't change across - // renders, so it's faster to spend the time checking if it is different - // before actually doing the expensive flattening operation in order to - // compute the diff. - if (styleDiffer(nextProps.style, prevProps.style)) { - var nextFlattenedStyle = flattenStyle(nextProps.style); - updatePayload = diffRawProperties( - updatePayload, - this.previousFlattenedStyle, - nextFlattenedStyle, - ReactIOSStyleAttributes - ); - this.previousFlattenedStyle = nextFlattenedStyle; - } - - return updatePayload; - }, - - - /** - * Updates the component's currently mounted representation. - * - * @param {object} nextElement - * @param {ReactReconcileTransaction} transaction - * @param {object} context - * @internal - */ - receiveComponent: function(nextElement, transaction, context) { - var prevElement = this._currentElement; - this._currentElement = nextElement; - - var updatePayload = this.computeUpdatedProperties( - prevElement.props, - nextElement.props, - this.viewConfig.validAttributes - ); - - if (updatePayload) { - RKUIManager.updateView( - ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(this._rootNodeID), - this.viewConfig.uiViewClassName, - updatePayload - ); - } - - this._reconcileListenersUponUpdate( - prevElement.props, - nextElement.props - ); - this.updateChildren(nextElement.props.children, transaction, context); - }, - - /** - * @param {object} initialProps Native component props. - */ - _registerListenersUponCreation: function(initialProps) { - for (var key in initialProps) { - // NOTE: The check for `!props[key]`, is only possible because this method - // registers listeners the *first* time a component is created. - if (registrationNames[key] && initialProps[key]) { - var listener = initialProps[key]; - putListener(this._rootNodeID, key, listener); - } - } - }, - - /** - * Reconciles event listeners, adding or removing if necessary. - * @param {object} prevProps Native component props including events. - * @param {object} nextProps Next native component props including events. - */ - _reconcileListenersUponUpdate: function(prevProps, nextProps) { - for (var key in nextProps) { - if (registrationNames[key] && (nextProps[key] != prevProps[key])) { - putListener(this._rootNodeID, key, nextProps[key]); - } - } - }, - - /** - * @param {string} rootID Root ID of this subtree. - * @param {Transaction} transaction For creating/updating. - * @return {string} Unique iOS view tag. - */ - mountComponent: function(rootID, transaction, context) { - this._rootNodeID = rootID; - - var tag = ReactIOSTagHandles.allocateTag(); - - this.previousFlattenedStyle = {}; - var updatePayload = this.computeUpdatedProperties( - {}, // previous props - this._currentElement.props, // next props - this.viewConfig.validAttributes - ); - RKUIManager.createView(tag, this.viewConfig.uiViewClassName, updatePayload); - - this._registerListenersUponCreation(this._currentElement.props); - this.initializeChildren( - this._currentElement.props.children, - tag, - transaction, - context - ); - return { - rootNodeID: rootID, - tag: tag - }; - } -}; - -/** - * Order of mixins is important. ReactIOSNativeComponent overrides methods in - * ReactMultiChild. - */ -Object.assign( - ReactIOSNativeComponent.prototype, - ReactMultiChild.Mixin, - ReactIOSNativeComponent.Mixin, - NativeMethodsMixin, - ReactIOSComponentMixin -); - -module.exports = ReactIOSNativeComponent; diff --git a/Libraries/ReactIOS/ReactIOSReconcileTransaction.js b/Libraries/ReactIOS/ReactIOSReconcileTransaction.js deleted file mode 100644 index 0c23d00e15b..00000000000 --- a/Libraries/ReactIOS/ReactIOSReconcileTransaction.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSReconcileTransaction - * @typechecks static-only - */ - -"use strict"; - -var CallbackQueue = require('CallbackQueue'); -var PooledClass = require('PooledClass'); -var Transaction = require('Transaction'); - -/** - * Provides a `CallbackQueue` queue for collecting `onDOMReady` callbacks during - * the performing of the transaction. - */ -var ON_DOM_READY_QUEUEING = { - /** - * Initializes the internal `onDOMReady` queue. - */ - initialize: function() { - this.reactMountReady.reset(); - }, - - /** - * After DOM is flushed, invoke all registered `onDOMReady` callbacks. - */ - close: function() { - this.reactMountReady.notifyAll(); - } -}; - -/** - * Executed within the scope of the `Transaction` instance. Consider these as - * being member methods, but with an implied ordering while being isolated from - * each other. - */ -var TRANSACTION_WRAPPERS = [ON_DOM_READY_QUEUEING]; - -/** - * Currently: - * - The order that these are listed in the transaction is critical: - * - Suppresses events. - * - Restores selection range. - * - * Future: - * - Restore document/overflow scroll positions that were unintentionally - * modified via DOM insertions above the top viewport boundary. - * - Implement/integrate with customized constraint based layout system and keep - * track of which dimensions must be remeasured. - * - * @class ReactIOSReconcileTransaction - */ -function ReactIOSReconcileTransaction() { - this.reinitializeTransaction(); - this.reactMountReady = CallbackQueue.getPooled(null); -} - -var Mixin = { - /** - * @see Transaction - * @abstract - * @final - * @return {array} List of operation wrap proceedures. - * TODO: convert to array - */ - getTransactionWrappers: function() { - return TRANSACTION_WRAPPERS; - }, - - /** - * @return {object} The queue to collect `onDOMReady` callbacks with. - * TODO: convert to ReactMountReady - */ - getReactMountReady: function() { - return this.reactMountReady; - }, - - /** - * `PooledClass` looks for this, and will invoke this before allowing this - * instance to be resused. - */ - destructor: function() { - CallbackQueue.release(this.reactMountReady); - this.reactMountReady = null; - } -}; - -Object.assign( - ReactIOSReconcileTransaction.prototype, - Transaction.Mixin, - ReactIOSReconcileTransaction, - Mixin -); - -PooledClass.addPoolingTo(ReactIOSReconcileTransaction); - -module.exports = ReactIOSReconcileTransaction; diff --git a/Libraries/ReactIOS/ReactIOSStyleAttributes.js b/Libraries/ReactIOS/ReactIOSStyleAttributes.js deleted file mode 100644 index 9c9a220baa8..00000000000 --- a/Libraries/ReactIOS/ReactIOSStyleAttributes.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSStyleAttributes - */ - -"use strict"; - -var TextStylePropTypes = require('TextStylePropTypes'); -var ViewStylePropTypes = require('ViewStylePropTypes'); - -var deepDiffer = require('deepDiffer'); -var keyMirror = require('keyMirror'); -var matricesDiffer = require('matricesDiffer'); -var merge = require('merge'); - -var ReactIOSStyleAttributes = merge( - keyMirror(ViewStylePropTypes), - keyMirror(TextStylePropTypes) -); - -ReactIOSStyleAttributes.transformMatrix = { diff: matricesDiffer }; -ReactIOSStyleAttributes.shadowOffset = { diff: deepDiffer }; - -module.exports = ReactIOSStyleAttributes; diff --git a/Libraries/ReactIOS/ReactIOSTagHandles.js b/Libraries/ReactIOS/ReactIOSTagHandles.js deleted file mode 100644 index a22b45ff63a..00000000000 --- a/Libraries/ReactIOS/ReactIOSTagHandles.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSTagHandles - */ -'use strict'; - -var invariant = require('invariant'); -var warning = require('warning'); - -/** - * Keeps track of allocating and associating native "tags" which are numeric, - * unique view IDs. All the native tags are negative numbers, to avoid - * collisions, but in the JS we keep track of them as positive integers to store - * them effectively in Arrays. So we must refer to them as "inverses" of the - * native tags (that are * normally negative). - * - * It *must* be the case that every `rootNodeID` always maps to the exact same - * `tag` forever. The easiest way to accomplish this is to never delete - * anything from this table. - * Why: Because `dangerouslyReplaceNodeWithMarkupByID` relies on being able to - * unmount a component with a `rootNodeID`, then mount a new one in its place, - */ -var INITIAL_TAG_COUNT = 1; -var ReactIOSTagHandles = { - tagsStartAt: INITIAL_TAG_COUNT, - tagCount: INITIAL_TAG_COUNT, - - allocateTag: function() { - // Skip over root IDs as those are reserved for native - while (this.reactTagIsNativeTopRootID(ReactIOSTagHandles.tagCount)) { - ReactIOSTagHandles.tagCount++; - } - var tag = ReactIOSTagHandles.tagCount; - ReactIOSTagHandles.tagCount++; - return tag; - }, - - /** - * This associates the *last* observed *native* mounting between `rootNodeID` - * and some `tag`. This association doesn't imply that `rootNodeID` is still - * natively mounted as `tag`. The only reason why we don't clear the - * association when the `rootNodeID` is unmounted, is that we don't have a - * convenient time to disassociate them (otherwise we would). - * `unmountComponent` isn't the correct time because that doesn't imply that - * the native node has been natively unmounted. - */ - associateRootNodeIDWithMountedNodeHandle: function(rootNodeID, tag) { - warning(rootNodeID && tag, 'Root node or tag is null when associating'); - ReactIOSTagHandles.tagToRootNodeID[tag] = rootNodeID; - ReactIOSTagHandles.rootNodeIDToTag[rootNodeID] = tag; - }, - - allocateRootNodeIDForTag: function(tag) { - invariant( - this.reactTagIsNativeTopRootID(tag), - 'Expect a native root tag, instead got ', tag - ); - return '.r[' + tag + ']{TOP_LEVEL}'; - }, - - reactTagIsNativeTopRootID: function(reactTag) { - // We reserve all tags that are 1 mod 10 for native root views - return reactTag % 10 === 1; - }, - - /** - * Returns the native `nodeHandle` (`tag`) that was most recently *natively* - * mounted at the `rootNodeID`. Just because a React component has been - * mounted, that doesn't mean that its native node has been mounted. The - * native node is mounted when we actually make the call to insert the - * `nodeHandle` (`tag`) into the native hierarchy. - * - * @param {string} rootNodeID Root node ID to find most recently mounted tag - * for. Again, this doesn't imply that it is still currently mounted. - * @return {number} Tag ID of native view for most recent mounting of - * `rootNodeID`. - */ - mostRecentMountedNodeHandleForRootNodeID: function(rootNodeID) { - return ReactIOSTagHandles.rootNodeIDToTag[rootNodeID]; - }, - - tagToRootNodeID: [], - - rootNodeIDToTag: {} -}; - -module.exports = ReactIOSTagHandles; diff --git a/Libraries/ReactIOS/ReactIOSTextComponent.js b/Libraries/ReactIOS/ReactIOSTextComponent.js deleted file mode 100644 index 4ec0c7a1aeb..00000000000 --- a/Libraries/ReactIOS/ReactIOSTextComponent.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSTextComponent - */ - -'use strict'; - -var ReactIOSTagHandles = require('ReactIOSTagHandles'); -var RKUIManager = require('NativeModulesDeprecated').RKUIManager; - -var assign = require('Object.assign'); - -var ReactIOSTextComponent = function(props) { - // This constructor and its argument is currently used by mocks. -}; - -assign(ReactIOSTextComponent.prototype, { - - construct: function(text) { - // This is really a ReactText (ReactNode), not a ReactElement - this._currentElement = text; - this._stringText = '' + text; - this._rootNodeID = null; - }, - - mountComponent: function(rootID, transaction, context) { - this._rootNodeID = rootID; - var tag = ReactIOSTagHandles.allocateTag(); - RKUIManager.createView(tag, 'RCTRawText', {text: this._stringText}); - return { - rootNodeID: rootID, - tag: tag, - }; - }, - - receiveComponent: function(nextText, transaction, context) { - if (nextText !== this._currentElement) { - this._currentElement = nextText; - var nextStringText = '' + nextText; - if (nextStringText !== this._stringText) { - this._stringText = nextStringText; - RKUIManager.updateView( - ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID( - this._rootNodeID - ), - 'RCTRawText', - {text: this._stringText} - ); - } - } - }, - - unmountComponent: function() { - this._currentElement = null; - this._stringText = null; - this._rootNodeID = null; - } - -}); - -module.exports = ReactIOSTextComponent; diff --git a/Libraries/ReactIOS/ReactIOSViewAttributes.js b/Libraries/ReactIOS/ReactIOSViewAttributes.js deleted file mode 100644 index df5dfb24992..00000000000 --- a/Libraries/ReactIOS/ReactIOSViewAttributes.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ReactIOSViewAttributes - */ - -"use strict"; - -var merge = require('merge'); - -var ReactIOSViewAttributes = {}; - -ReactIOSViewAttributes.UIView = { - pointerEvents: true, - accessible: true, - accessibilityLabel: true, - testID: true, -}; - -ReactIOSViewAttributes.RKView = merge( - ReactIOSViewAttributes.UIView, { - - // This is a special performance property exposed by RKView and useful for - // scrolling content when there are many subviews, most of which are offscreen. - // For this property to be effective, it must be applied to a view that contains - // many subviews that extend outside its bound. The subviews must also have - // overflow: hidden, as should the containing view (or one of its superviews). - removeClippedSubviews: true -}); - -module.exports = ReactIOSViewAttributes; diff --git a/Libraries/ReactIOS/createReactIOSNativeComponentClass.js b/Libraries/ReactIOS/createReactIOSNativeComponentClass.js deleted file mode 100644 index 465b26ba48f..00000000000 --- a/Libraries/ReactIOS/createReactIOSNativeComponentClass.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule createReactIOSNativeComponentClass - */ - -"use strict"; - -var ReactElement = require('ReactElement'); -var ReactIOSNativeComponent = require('ReactIOSNativeComponent'); - -/** - * @param {string} config iOS View configuration. - * @private - */ -var createReactIOSNativeComponentClass = function(viewConfig) { - var Constructor = function(element) { - this._currentElement = element; - - this._rootNodeID = null; - this._renderedChildren = null; - this.previousFlattenedStyle = null; - }; - Constructor.displayName = viewConfig.uiViewClassName; - Constructor.prototype = new ReactIOSNativeComponent(viewConfig); - - return Constructor; -}; - -module.exports = createReactIOSNativeComponentClass; diff --git a/Libraries/ReactIOS/diffRawProperties.js b/Libraries/ReactIOS/diffRawProperties.js deleted file mode 100644 index 3f1e9a758de..00000000000 --- a/Libraries/ReactIOS/diffRawProperties.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule diffRawProperties - */ -'use strict'; - -/** - * diffRawProperties takes two sets of props and a set of valid attributes - * and write to updatePayload the values that changed or were deleted - * - * @param {?object} updatePayload Overriden with the props that changed. - * @param {!object} prevProps Previous properties to diff against current - * properties. These properties are as supplied to component construction. - * @param {!object} prevProps Next "current" properties to diff against - * previous. These properties are as supplied to component construction. - * @return {?object} - */ -function diffRawProperties(updatePayload, prevProps, nextProps, validAttributes) { - var validAttributeConfig; - var nextProp; - var prevProp; - var isScalar; - var shouldUpdate; - - for (var propKey in nextProps) { - validAttributeConfig = validAttributes[propKey]; - if (!validAttributeConfig) { - continue; // not a valid native prop - } - prevProp = prevProps && prevProps[propKey]; - nextProp = nextProps[propKey]; - if (prevProp !== nextProp) { - // If you want a property's diff to be detected, you must configure it - // to be so - *or* it must be a scalar property. For now, we'll allow - // creation with any attribute that is not scalar, but we should - // eventually even reject those unless they are properly configured. - isScalar = typeof nextProp !== 'object' || nextProp === null; - shouldUpdate = isScalar || - !prevProp || - validAttributeConfig.diff && - validAttributeConfig.diff(prevProp, nextProp); - - if (shouldUpdate) { - updatePayload = updatePayload || {}; - updatePayload[propKey] = nextProp; - } - } - } - - // Also iterate through all the previous props to catch any that have been - // removed and make sure native gets the signal so it can reset them to the - // default. - for (var propKey in prevProps) { - validAttributeConfig = validAttributes[propKey]; - if (!validAttributeConfig) { - continue; // not a valid native prop - } - if (updatePayload && updatePayload[propKey] !== undefined) { - continue; // Prop already specified - } - prevProp = prevProps[propKey]; - nextProp = nextProps && nextProps[propKey]; - if (prevProp !== nextProp) { - if (nextProp === undefined) { - nextProp = null; // null is a sentinel we explicitly send to native - } - // If you want a property's diff to be detected, you must configure it - // to be so - *or* it must be a scalar property. For now, we'll allow - // creation with any attribute that is not scalar, but we should - // eventually even reject those unless they are properly configured. - isScalar = typeof nextProp !== 'object' || nextProp === null; - shouldUpdate = isScalar && prevProp !== nextProp || - validAttributeConfig.diff && - validAttributeConfig.diff(prevProp, nextProp); - if (shouldUpdate) { - updatePayload = updatePayload || {}; - updatePayload[propKey] = nextProp; - } - } - } - return updatePayload; -} - -module.exports = diffRawProperties; diff --git a/Libraries/ReactIOS/renderApplication.ios.js b/Libraries/ReactIOS/renderApplication.ios.js deleted file mode 100644 index 05d694c093b..00000000000 --- a/Libraries/ReactIOS/renderApplication.ios.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule renderApplication - */ -'use strict'; - -var React = require('React'); - -var invariant = require('invariant'); - -function renderApplication(RootComponent, initialProps, rootTag) { - invariant( - rootTag, - 'Expect to have a valid rootTag, instead got ', rootTag - ); - React.render(, rootTag); -} - -module.exports = renderApplication; diff --git a/Libraries/StyleSheet/EdgeInsetsPropType.js b/Libraries/StyleSheet/EdgeInsetsPropType.js deleted file mode 100644 index a57abcaf8f3..00000000000 --- a/Libraries/StyleSheet/EdgeInsetsPropType.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule EdgeInsetsPropType - */ -'use strict' - -var PropTypes = require('ReactPropTypes'); - -var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker'); -var insetsDiffer = require('insetsDiffer'); - -var EdgeInsetsPropType = createStrictShapeTypeChecker({ - top: PropTypes.number, - left: PropTypes.number, - bottom: PropTypes.number, - right: PropTypes.number, -}); - -module.exports = EdgeInsetsPropType; diff --git a/Libraries/StyleSheet/LayoutPropTypes.js b/Libraries/StyleSheet/LayoutPropTypes.js deleted file mode 100644 index 1e88df58186..00000000000 --- a/Libraries/StyleSheet/LayoutPropTypes.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule LayoutPropTypes - */ -'use strict'; - -var ReactPropTypes = require('ReactPropTypes'); - -/** - * These properties are a subset of our styles that are consumed by the layout - * algorithm and affect the positioning and sizing of views. - */ - -var LayoutPropTypes = { - width: ReactPropTypes.number, - height: ReactPropTypes.number, - top: ReactPropTypes.number, - left: ReactPropTypes.number, - right: ReactPropTypes.number, - bottom: ReactPropTypes.number, - margin: ReactPropTypes.number, - marginVertical: ReactPropTypes.number, - marginHorizontal: ReactPropTypes.number, - marginTop: ReactPropTypes.number, - marginBottom: ReactPropTypes.number, - marginLeft: ReactPropTypes.number, - marginRight: ReactPropTypes.number, - padding: ReactPropTypes.number, - paddingVertical: ReactPropTypes.number, - paddingHorizontal: ReactPropTypes.number, - paddingTop: ReactPropTypes.number, - paddingBottom: ReactPropTypes.number, - paddingLeft: ReactPropTypes.number, - paddingRight: ReactPropTypes.number, - borderWidth: ReactPropTypes.number, - borderTopWidth: ReactPropTypes.number, - borderRightWidth: ReactPropTypes.number, - borderBottomWidth: ReactPropTypes.number, - borderLeftWidth: ReactPropTypes.number, - - position: ReactPropTypes.oneOf([ - 'absolute', - 'relative' - ]), - - // https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction - flexDirection: ReactPropTypes.oneOf([ - 'row', - 'column' - ]), - - // https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap - flexWrap: ReactPropTypes.oneOf([ - 'wrap', - 'nowrap' - ]), - - // How to align children in the main direction - // https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content - justifyContent: ReactPropTypes.oneOf([ - 'flex-start', - 'flex-end', - 'center', - 'space-between', - 'space-around' - ]), - - // How to align children in the cross direction - // https://developer.mozilla.org/en-US/docs/Web/CSS/align-items - alignItems: ReactPropTypes.oneOf([ - 'flex-start', - 'flex-end', - 'center', - 'stretch' - ]), - - // How to align the element in the cross direction - // https://developer.mozilla.org/en-US/docs/Web/CSS/align-items - alignSelf: ReactPropTypes.oneOf([ - 'auto', - 'flex-start', - 'flex-end', - 'center', - 'stretch' - ]), - - // https://developer.mozilla.org/en-US/docs/Web/CSS/flex - flex: ReactPropTypes.number, -}; - -module.exports = LayoutPropTypes; diff --git a/Libraries/StyleSheet/PointPropType.js b/Libraries/StyleSheet/PointPropType.js deleted file mode 100644 index c409bd660a2..00000000000 --- a/Libraries/StyleSheet/PointPropType.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule PointPropType - */ -'use strict' - -var PropTypes = require('ReactPropTypes'); - -var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker'); -var pointsDiffer = require('pointsDiffer'); - -var PointPropType = createStrictShapeTypeChecker({ - x: PropTypes.number, - y: PropTypes.number, -}); - -module.exports = PointPropType; diff --git a/Libraries/StyleSheet/StyleSheet.js b/Libraries/StyleSheet/StyleSheet.js deleted file mode 100644 index cca0f87dacb..00000000000 --- a/Libraries/StyleSheet/StyleSheet.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule StyleSheet - */ -'use strict'; - -var ImageStylePropTypes = require('ImageStylePropTypes'); -var ReactPropTypeLocations = require('ReactPropTypeLocations'); -var StyleSheetRegistry = require('StyleSheetRegistry'); -var TextStylePropTypes = require('TextStylePropTypes'); -var ViewStylePropTypes = require('ViewStylePropTypes'); - -var invariant = require('invariant'); - -/** - * A StyleSheet is an abstraction similar to CSS StyleSheets - * - * Create a new StyleSheet: - * - * var styles = StyleSheet.create({ - * container: { - * borderRadius: 4, - * borderWidth: 0.5, - * borderColor: '#d6d7da', - * }, - * title: { - * fontSize: 19, - * fontWeight: 'bold', - * }, - * activeTitle: { - * color: 'red', - * }, - * }) - * - * Use a StyleSheet: - * - * - * - * - * - * Code quality: - * - By moving styles away from the render function, you're making the code - * code easier to understand. - * - Naming the styles is a good way to add meaning to the low level components - * in the render function. - * - * Performance: - * - Making a stylesheet from a style object makes it possible to refer to it - * by ID instead of creating a new style object every time. - * - It also allows to send the style only once through the bridge. All - * subsequent uses are going to refer an id (not implemented yet). - */ -class StyleSheet { - static create(obj) { - var result = {}; - for (var key in obj) { - StyleSheet.validateStyle(key, obj); - result[key] = StyleSheetRegistry.registerStyle(obj[key]); - } - return result; - } - - static validateStyleProp(prop, style, caller) { - if (!__DEV__) { - return; - } - if (allStylePropTypes[prop] === undefined) { - var message1 = '"' + prop + '" is not a valid style property.'; - var message2 = '\nValid style props: ' + - JSON.stringify(Object.keys(allStylePropTypes), null, ' '); - styleError(message1, style, caller, message2); - } - var error = allStylePropTypes[prop]( - style, - prop, - caller, - ReactPropTypeLocations.prop - ); - if (error) { - styleError(error.message, style, caller); - } - } - - static validateStyle(name, styles) { - if (!__DEV__) { - return; - } - for (var prop in styles[name]) { - StyleSheet.validateStyleProp(prop, styles[name], 'StyleSheet ' + name); - } - } - - static addValidStylePropTypes(stylePropTypes) { - for (var key in stylePropTypes) { - invariant( - allStylePropTypes[key] === undefined || - allStylePropTypes[key] === stylePropTypes[key], - 'Attemped to redefine existing style prop type "' + key + '".' - ); - allStylePropTypes[key] = stylePropTypes[key]; - } - } -} - -var styleError = function(message1, style, caller, message2) { - invariant( - false, - message1 + '\n' + (caller || '<>') + ': ' + - JSON.stringify(style, null, ' ') + (message2 || '') - ); -}; - -var allStylePropTypes = {}; - -StyleSheet.addValidStylePropTypes(ImageStylePropTypes); -StyleSheet.addValidStylePropTypes(TextStylePropTypes); -StyleSheet.addValidStylePropTypes(ViewStylePropTypes); - -module.exports = StyleSheet; diff --git a/Libraries/StyleSheet/StyleSheetPropType.js b/Libraries/StyleSheet/StyleSheetPropType.js deleted file mode 100644 index f12245416d7..00000000000 --- a/Libraries/StyleSheet/StyleSheetPropType.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule StyleSheetPropType - */ -'use strict'; - -var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker'); -var flattenStyle = require('flattenStyle'); - -function StyleSheetPropType(shape) { - var shapePropType = createStrictShapeTypeChecker(shape); - return function(props, propName, componentName, location) { - var newProps = props; - if (props[propName]) { - // Just make a dummy prop object with only the flattened style - newProps = {}; - newProps[propName] = flattenStyle(props[propName]); - } - return shapePropType(newProps, propName, componentName, location); - }; -} - -module.exports = StyleSheetPropType; diff --git a/Libraries/StyleSheet/StyleSheetRegistry.js b/Libraries/StyleSheet/StyleSheetRegistry.js deleted file mode 100644 index d165f44ae66..00000000000 --- a/Libraries/StyleSheet/StyleSheetRegistry.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule StyleSheetRegistry - */ -'use strict'; - -var styles = {}; -var uniqueID = 1; -var emptyStyle = {}; - -class StyleSheetRegistry { - static registerStyle(style) { - var id = ++uniqueID; - if (__DEV__) { - Object.freeze(style); - } - styles[id] = style; - return id; - } - - static getStyleByID(id) { - if (!id) { - // Used in the style={[condition && id]} pattern, - // we want it to be a no-op when the value is false or null - return emptyStyle; - } - - var style = styles[id]; - if (!style) { - console.warn('Invalid style with id `' + id + '`. Skipping ...'); - return emptyStyle; - } - return style; - } -} - -module.exports = StyleSheetRegistry; diff --git a/Libraries/StyleSheet/flattenStyle.js b/Libraries/StyleSheet/flattenStyle.js deleted file mode 100644 index 44b6a26d57d..00000000000 --- a/Libraries/StyleSheet/flattenStyle.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule flattenStyle - */ -'use strict'; - -var StyleSheetRegistry = require('StyleSheetRegistry'); -var mergeIntoFast = require('mergeIntoFast'); - -function getStyle(style) { - if (typeof style === 'number') { - return StyleSheetRegistry.getStyleByID(style); - } - return style; -} - -function flattenStyle(style) { - if (!style) { - return undefined; - } - - if (!Array.isArray(style)) { - return getStyle(style); - } - - var result = {}; - for (var i = 0; i < style.length; ++i) { - var computedStyle = flattenStyle(style[i]); - if (computedStyle) { - mergeIntoFast(result, computedStyle); - } - } - return result; -} - -module.exports = flattenStyle; diff --git a/Libraries/StyleSheet/styleDiffer.js b/Libraries/StyleSheet/styleDiffer.js deleted file mode 100644 index e73d4c68744..00000000000 --- a/Libraries/StyleSheet/styleDiffer.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule styleDiffer - */ -'use strict'; - -var deepDiffer = require('deepDiffer'); - -function styleDiffer(a, b) { - return !styleEqual(a, b); -} - -function styleEqual(a, b) { - if (!a) { - return !b; - } - if (!b) { - return !a; - } - if (typeof a !== typeof b) { - return false; - } - if (typeof a === 'number') { - return a === b; - } - - if (Array.isArray(a)) { - if (!Array.isArray(b) || a.length !== b.length) { - return false; - } - for (var i = 0; i < a.length; ++i) { - if (!styleEqual(a[i], b[i])) { - return false; - } - } - return true; - } - - for (var key in a) { - if (deepDiffer(a[key], b[key])) { - return false; - } - } - - for (var key in b) { - if (!a.hasOwnProperty(key)) { - return false; - } - } - - return true; -} - -module.exports = styleDiffer; diff --git a/Libraries/Text/ExpandingText.js b/Libraries/Text/ExpandingText.js deleted file mode 100644 index 181e0a2b8f9..00000000000 --- a/Libraries/Text/ExpandingText.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ExpandingText - */ -'use strict'; - -var React = require('React'); -var StyleSheet = require('StyleSheet'); -var Text = require('Text'); -var TouchableWithoutFeedback = require('TouchableWithoutFeedback'); -var View = require('View'); - -var truncate = require('truncate'); - -var styles = StyleSheet.create({ - boldText: { - fontWeight: 'bold', - }, -}); - -/** - * A react component for displaying text which supports truncating - * based on a set truncLength. - * - * In the following example, the text will truncate - * to show only the first 17 characters plus '...' with a See More button to - * expand the text to its full length. - * - * ``` - * render: function() { - * return ; - * }, - * ``` - */ -var ExpandingText = React.createClass({ - propTypes: { - /** - * Text to be displayed. It will be truncated if the character length - * is greater than the `truncLength` property. - */ - text: React.PropTypes.string, - /** - * The styles that will be applied to the text (both truncated and - * expanded). - */ - textStyle: Text.propTypes.style, - /** - * The styles that will be applied to the See More button. Default - * is bold. - */ - seeMoreStyle: Text.propTypes.style, - /** - * The caption that will be appended at the end, by default it is - * `'See More'`. - */ - seeMoreText: React.PropTypes.string, - /** - * The maximum character length for the text that will - * be displayed by default. Note that ... will be - * appended to the truncated text which is counted towards - * the total truncLength of the default displayed string. - * The default is 130. - */ - truncLength: React.PropTypes.number, - }, - - getDefaultProps: function() { - return { - truncLength: 130, - seeMoreText: 'See More', - seeMoreStyle: styles.boldText, - }; - }, - - getInitialState: function() { - return { - truncated: true, - }; - }, - - onTapSeeMore: function() { - this.setState({ - truncated: !this.state.truncated, - }); - }, - - isTruncated: function() { - return ( - this.props.text.length > this.props.truncLength && - this.state.truncated - ); - }, - - getText: function() { - var text = this.props.text; - if (!this.isTruncated()) { - return text; - } - - return truncate(text, this.props.truncLength) + ' '; - }, - - renderSeeMore: function() { - if (!this.isTruncated()) { - return null; - } - - return ( - - {this.props.seeMoreText} - - ); - }, - - render: function() { - return ( - - - - {this.getText()} - {this.renderSeeMore()} - - - - ); - } -}); - -module.exports = ExpandingText; diff --git a/Libraries/Text/RCTRawTextManager.h b/Libraries/Text/RCTRawTextManager.h deleted file mode 100644 index 4c67fd32853..00000000000 --- a/Libraries/Text/RCTRawTextManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTRawTextManager : RCTViewManager - -@end diff --git a/Libraries/Text/RCTRawTextManager.m b/Libraries/Text/RCTRawTextManager.m deleted file mode 100644 index 57ee7520417..00000000000 --- a/Libraries/Text/RCTRawTextManager.m +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTRawTextManager.h" - -#import "RCTShadowRawText.h" - -@implementation RCTRawTextManager - -- (UIView *)view -{ - return [[UIView alloc] init]; -} - -- (RCTShadowView *)shadowView -{ - return [[RCTShadowRawText alloc] init]; -} - -@end - diff --git a/Libraries/Text/RCTShadowRawText.h b/Libraries/Text/RCTShadowRawText.h deleted file mode 100644 index d1bdc7d7253..00000000000 --- a/Libraries/Text/RCTShadowRawText.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTShadowView.h" - -@interface RCTShadowRawText : RCTShadowView - -@property (nonatomic, copy) NSString *text; - -@end diff --git a/Libraries/Text/RCTShadowRawText.m b/Libraries/Text/RCTShadowRawText.m deleted file mode 100644 index 370c066955f..00000000000 --- a/Libraries/Text/RCTShadowRawText.m +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTShadowRawText.h" - -@implementation RCTShadowRawText - -- (void)setText:(NSString *)text -{ - if (_text != text) { - _text = [text copy]; - [self dirtyLayout]; - [self dirtyText]; - } -} - -@end diff --git a/Libraries/Text/RCTShadowText.h b/Libraries/Text/RCTShadowText.h deleted file mode 100644 index ddaf2ebe7f4..00000000000 --- a/Libraries/Text/RCTShadowText.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTShadowView.h" - -extern NSString *const RCTIsHighlightedAttributeName; -extern NSString *const RCTReactTagAttributeName; - -@interface RCTShadowText : RCTShadowView - -@property (nonatomic, assign) NSWritingDirection writingDirection; -@property (nonatomic, strong) UIColor *textBackgroundColor; -@property (nonatomic, strong) UIColor *color; -@property (nonatomic, strong) UIFont *font; -@property (nonatomic, copy) NSString *fontFamily; -@property (nonatomic, assign) CGFloat fontSize; -@property (nonatomic, copy) NSString *fontWeight; -@property (nonatomic, assign) BOOL isHighlighted; -@property (nonatomic, assign) CGFloat lineHeight; -@property (nonatomic, assign) NSInteger maxNumberOfLines; -@property (nonatomic, assign) CGSize shadowOffset; -@property (nonatomic, assign) NSTextAlignment textAlign; -@property (nonatomic, assign) NSLineBreakMode truncationMode; - -- (NSAttributedString *)attributedString; - -@end diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m deleted file mode 100644 index ce6ff244e40..00000000000 --- a/Libraries/Text/RCTShadowText.m +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTShadowText.h" - -#import "RCTConvert.h" -#import "RCTLog.h" - -#import "RCTShadowRawText.h" -#import "RCTUtils.h" - -NSString *const RCTIsHighlightedAttributeName = @"IsHighlightedAttributeName"; -NSString *const RCTReactTagAttributeName = @"ReactTagAttributeName"; - -static css_dim_t RCTMeasure(void *context, float width) -{ - RCTShadowText *shadowText = (__bridge RCTShadowText *)context; - CGSize computedSize = [[shadowText attributedString] boundingRectWithSize:(CGSize){isnan(width) ? CGFLOAT_MAX : width, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin context:nil].size; - - css_dim_t result; - result.dimensions[CSS_WIDTH] = RCTCeilPixelValue(computedSize.width); - result.dimensions[CSS_HEIGHT] = RCTCeilPixelValue(computedSize.height); - return result; -} - -@implementation RCTShadowText -{ - NSAttributedString *_cachedAttributedString; - UIFont *_font; -} - -- (instancetype)init -{ - if ((self = [super init])) { - _fontSize = NAN; - _isHighlighted = NO; - } - return self; -} - -- (NSAttributedString *)attributedString -{ - return [self _attributedStringWithFontFamily:nil - fontSize:0 - fontWeight:nil]; -} - -- (NSAttributedString *)_attributedStringWithFontFamily:(NSString *)fontFamily - fontSize:(CGFloat)fontSize - fontWeight:(NSString *)fontWeight -{ - if (![self isTextDirty] && _cachedAttributedString) { - return _cachedAttributedString; - } - - if (_fontSize && !isnan(_fontSize)) { - fontSize = _fontSize; - } - if (_fontWeight) { - fontWeight = _fontWeight; - } - if (_fontFamily) { - fontFamily = _fontFamily; - } - - NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init]; - for (RCTShadowView *child in [self reactSubviews]) { - if ([child isKindOfClass:[RCTShadowText class]]) { - RCTShadowText *shadowText = (RCTShadowText *)child; - [attributedString appendAttributedString:[shadowText _attributedStringWithFontFamily:fontFamily fontSize:fontSize fontWeight:fontWeight]]; - } else if ([child isKindOfClass:[RCTShadowRawText class]]) { - RCTShadowRawText *shadowRawText = (RCTShadowRawText *)child; - [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:[shadowRawText text] ?: @""]]; - } else { - RCTLogError(@" can't have any children except or raw strings"); - } - - [child setTextComputed]; - } - - if (_color) { - [self _addAttribute:NSForegroundColorAttributeName withValue:self.color toAttributedString:attributedString]; - } - if (_isHighlighted) { - [self _addAttribute:RCTIsHighlightedAttributeName withValue:@YES toAttributedString:attributedString]; - } - if (_textBackgroundColor) { - [self _addAttribute:NSBackgroundColorAttributeName withValue:self.textBackgroundColor toAttributedString:attributedString]; - } - - _font = [RCTConvert UIFont:nil withFamily:fontFamily size:@(fontSize) weight:fontWeight]; - [self _addAttribute:NSFontAttributeName withValue:_font toAttributedString:attributedString]; - [self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString]; - [self _setParagraphStyleOnAttributedString:attributedString]; - - // create a non-mutable attributedString for use by the Text system which avoids copies down the line - _cachedAttributedString = [[NSAttributedString alloc] initWithAttributedString:attributedString]; - [self dirtyLayout]; - - return _cachedAttributedString; -} - -- (UIFont *)font -{ - return _font ?: [RCTConvert UIFont:nil withFamily:_fontFamily size:@(_fontSize) weight:_fontWeight]; -} - -- (void)_addAttribute:(NSString *)attribute withValue:(id)attributeValue toAttributedString:(NSMutableAttributedString *)attributedString -{ - [attributedString enumerateAttribute:attribute inRange:NSMakeRange(0, [attributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) { - if (!value) { - [attributedString addAttribute:attribute value:attributeValue range:range]; - } - }]; -} - -/* - * LineHeight works the same way line-height works in the web: if children and self have - * varying lineHeights, we simply take the max. - */ -- (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attributedString -{ - // check if we have lineHeight set on self - __block BOOL hasParagraphStyle = NO; - if (_lineHeight || _textAlign) { - hasParagraphStyle = YES; - } - - if (!_lineHeight) { - self.lineHeight = 0.0; - } - - // check for lineHeight on each of our children, update the max as we go (in self.lineHeight) - [attributedString enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, [attributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) { - if (value) { - NSParagraphStyle *paragraphStyle = (NSParagraphStyle *)value; - if ([paragraphStyle maximumLineHeight] > _lineHeight) { - self.lineHeight = [paragraphStyle maximumLineHeight]; - } - hasParagraphStyle = YES; - } - }]; - - // TODO: umm, these can'e be null, so we're mapping left to natural - is that right? - self.textAlign = _textAlign ?: NSTextAlignmentNatural; - self.writingDirection = _writingDirection ?: NSWritingDirectionNatural; - - // if we found anything, set it :D - if (hasParagraphStyle) { - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.alignment = _textAlign; - paragraphStyle.baseWritingDirection = _writingDirection; - paragraphStyle.minimumLineHeight = _lineHeight; - paragraphStyle.maximumLineHeight = _lineHeight; - [attributedString addAttribute:NSParagraphStyleAttributeName - value:paragraphStyle - range:(NSRange){0, attributedString.length}]; - } -} - -- (void)fillCSSNode:(css_node_t *)node -{ - [super fillCSSNode:node]; - node->measure = RCTMeasure; - node->children_count = 0; -} - -- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex -{ - [super insertReactSubview:subview atIndex:atIndex]; - [self cssNode]->children_count = 0; -} - -- (void)removeReactSubview:(RCTShadowView *)subview -{ - [super removeReactSubview:subview]; - [self cssNode]->children_count = 0; -} - -#define RCT_TEXT_PROPERTY(setProp, ivar, type) \ -- (void)set##setProp:(type)value; \ -{ \ - ivar = value; \ - [self dirtyText]; \ -} - -RCT_TEXT_PROPERTY(TextBackgroundColor, _textBackgroundColor, UIColor *); -RCT_TEXT_PROPERTY(Color, _color, UIColor *); -RCT_TEXT_PROPERTY(FontFamily, _fontFamily, NSString *); -RCT_TEXT_PROPERTY(FontSize, _fontSize, CGFloat); -RCT_TEXT_PROPERTY(FontWeight, _fontWeight, NSString *); -RCT_TEXT_PROPERTY(LineHeight, _lineHeight, CGFloat); -RCT_TEXT_PROPERTY(MaxNumberOfLines, _maxNumberOfLines, NSInteger); -RCT_TEXT_PROPERTY(ShadowOffset, _shadowOffset, CGSize); -RCT_TEXT_PROPERTY(TextAlign, _textAlign, NSTextAlignment); -RCT_TEXT_PROPERTY(TruncationMode, _truncationMode, NSLineBreakMode); -RCT_TEXT_PROPERTY(IsHighlighted, _isHighlighted, BOOL); -RCT_TEXT_PROPERTY(Font, _font, UIFont *); - -@end diff --git a/Libraries/Text/RCTText.h b/Libraries/Text/RCTText.h deleted file mode 100644 index 80ba3f23415..00000000000 --- a/Libraries/Text/RCTText.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface RCTText : UIView - -@property (nonatomic, copy) NSAttributedString *attributedText; -@property (nonatomic, assign) NSLineBreakMode lineBreakMode; -@property (nonatomic, assign) NSUInteger numberOfLines; - -- (NSNumber *)reactTagAtPoint:(CGPoint)point; - -@end diff --git a/Libraries/Text/RCTText.m b/Libraries/Text/RCTText.m deleted file mode 100644 index f0b91387996..00000000000 --- a/Libraries/Text/RCTText.m +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTText.h" - -#import "RCTShadowText.h" -#import "RCTUtils.h" -#import "UIView+ReactKit.h" - -@implementation RCTText -{ - NSLayoutManager *_layoutManager; - NSTextStorage *_textStorage; - NSTextContainer *_textContainer; -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - if ((self = [super initWithFrame:frame])) { - _textContainer = [[NSTextContainer alloc] init]; - _textContainer.lineBreakMode = NSLineBreakByTruncatingTail; - _textContainer.lineFragmentPadding = 0.0; - - _layoutManager = [[NSLayoutManager alloc] init]; - [_layoutManager addTextContainer:_textContainer]; - - _textStorage = [[NSTextStorage alloc] init]; - [_textStorage addLayoutManager:_layoutManager]; - - self.contentMode = UIViewContentModeRedraw; - } - - return self; -} - -- (NSAttributedString *)attributedText -{ - return [_textStorage copy]; -} - -- (void)setAttributedText:(NSAttributedString *)attributedText -{ - [_textStorage setAttributedString:attributedText]; - [self setNeedsDisplay]; -} - -- (NSUInteger)numberOfLines -{ - return _textContainer.maximumNumberOfLines; -} - -- (void)setNumberOfLines:(NSUInteger)numberOfLines -{ - _textContainer.maximumNumberOfLines = numberOfLines; - [self setNeedsDisplay]; -} - -- (NSLineBreakMode)lineBreakMode -{ - return _textContainer.lineBreakMode; -} - -- (void)setLineBreakMode:(NSLineBreakMode)lineBreakMode -{ - _textContainer.lineBreakMode = lineBreakMode; - [self setNeedsDisplay]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - // The header comment for `size` says that a height of 0.0 should be enough, - // but it isn't. - _textContainer.size = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX); -} - -- (void)drawRect:(CGRect)rect -{ - NSRange glyphRange = [_layoutManager glyphRangeForTextContainer:_textContainer]; - [_layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:CGPointZero]; - [_layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:CGPointZero]; -} - -- (NSNumber *)reactTagAtPoint:(CGPoint)point -{ - CGFloat fraction; - NSUInteger characterIndex = [_layoutManager characterIndexForPoint:point inTextContainer:_textContainer fractionOfDistanceBetweenInsertionPoints:&fraction]; - - NSNumber *reactTag = nil; - - // If the point is not before (fraction == 0.0) the first character and not - // after (fraction == 1.0) the last character, then the attribute is valid. - if (_textStorage.length > 0 && (fraction > 0 || characterIndex > 0) && (fraction < 1 || characterIndex < _textStorage.length - 1)) { - reactTag = [_textStorage attribute:RCTReactTagAttributeName atIndex:characterIndex effectiveRange:NULL]; - } - - return reactTag ?: self.reactTag; -} - -@end diff --git a/Libraries/Text/RCTText.podspec b/Libraries/Text/RCTText.podspec deleted file mode 100644 index 656e0ee74f9..00000000000 --- a/Libraries/Text/RCTText.podspec +++ /dev/null @@ -1,28 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'RCTText' - spec.version = '0.0.1' - spec.summary = 'Provides basic Text capabilities in ReactNative apps.' - spec.description = <<-DESC - Text can be rendered in ReactNative apps with the component using this module. - DESC - spec.homepage = 'https://facebook.github.io/react-native/' - spec.license = { :type => 'BSD' } - spec.author = 'Facebook' - spec.platform = :ios, '7.0' - spec.requires_arc = true - spec.source_files = '**/*.{h,m,c}' - spec.dependency "ReactKit", "~> 0.0.1" - - # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - # - # Link your library with frameworks, or libraries. Libraries do not include - # the lib prefix of their name. - # - - # s.framework = "SomeFramework" - # s.frameworks = "SomeFramework", "AnotherFramework" - - # s.library = "iconv" - #spec.libraries = "RCTText", "ReactKit" - -end diff --git a/Libraries/Text/RCTText.xcodeproj/project.pbxproj b/Libraries/Text/RCTText.xcodeproj/project.pbxproj deleted file mode 100644 index 240d7c51b3f..00000000000 --- a/Libraries/Text/RCTText.xcodeproj/project.pbxproj +++ /dev/null @@ -1,272 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 58B511CE1A9E6C5C00147676 /* RCTRawTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */; }; - 58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */; }; - 58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */; }; - 58B511D11A9E6C5C00147676 /* RCTTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */; }; - 58B512161A9E6EFF00147676 /* RCTText.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B512141A9E6EFF00147676 /* RCTText.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 58B511991A9E6C1200147676 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 58B5119B1A9E6C1200147676 /* libRCTText.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTText.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 58B511C61A9E6C5C00147676 /* RCTRawTextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRawTextManager.h; sourceTree = ""; }; - 58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRawTextManager.m; sourceTree = ""; }; - 58B511C81A9E6C5C00147676 /* RCTShadowRawText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowRawText.h; sourceTree = ""; }; - 58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowRawText.m; sourceTree = ""; }; - 58B511CA1A9E6C5C00147676 /* RCTShadowText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowText.h; sourceTree = ""; }; - 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowText.m; sourceTree = ""; }; - 58B511CC1A9E6C5C00147676 /* RCTTextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTextManager.h; sourceTree = ""; }; - 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTextManager.m; sourceTree = ""; }; - 58B512141A9E6EFF00147676 /* RCTText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTText.m; sourceTree = ""; }; - 58B512151A9E6EFF00147676 /* RCTText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTText.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 58B511981A9E6C1200147676 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 58B511921A9E6C1200147676 = { - isa = PBXGroup; - children = ( - 58B511C61A9E6C5C00147676 /* RCTRawTextManager.h */, - 58B511C71A9E6C5C00147676 /* RCTRawTextManager.m */, - 58B511C81A9E6C5C00147676 /* RCTShadowRawText.h */, - 58B511C91A9E6C5C00147676 /* RCTShadowRawText.m */, - 58B511CA1A9E6C5C00147676 /* RCTShadowText.h */, - 58B511CB1A9E6C5C00147676 /* RCTShadowText.m */, - 58B512151A9E6EFF00147676 /* RCTText.h */, - 58B512141A9E6EFF00147676 /* RCTText.m */, - 58B511CC1A9E6C5C00147676 /* RCTTextManager.h */, - 58B511CD1A9E6C5C00147676 /* RCTTextManager.m */, - 58B5119C1A9E6C1200147676 /* Products */, - ); - sourceTree = ""; - }; - 58B5119C1A9E6C1200147676 /* Products */ = { - isa = PBXGroup; - children = ( - 58B5119B1A9E6C1200147676 /* libRCTText.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 58B5119A1A9E6C1200147676 /* RCTText */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58B511AF1A9E6C1300147676 /* Build configuration list for PBXNativeTarget "RCTText" */; - buildPhases = ( - 58B511971A9E6C1200147676 /* Sources */, - 58B511981A9E6C1200147676 /* Frameworks */, - 58B511991A9E6C1200147676 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RCTText; - productName = RCTText; - productReference = 58B5119B1A9E6C1200147676 /* libRCTText.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 58B511931A9E6C1200147676 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 58B5119A1A9E6C1200147676 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 58B511961A9E6C1200147676 /* Build configuration list for PBXProject "RCTText" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 58B511921A9E6C1200147676; - productRefGroup = 58B5119C1A9E6C1200147676 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 58B5119A1A9E6C1200147676 /* RCTText */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 58B511971A9E6C1200147676 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 58B511D11A9E6C5C00147676 /* RCTTextManager.m in Sources */, - 58B511CE1A9E6C5C00147676 /* RCTRawTextManager.m in Sources */, - 58B512161A9E6EFF00147676 /* RCTText.m in Sources */, - 58B511CF1A9E6C5C00147676 /* RCTShadowRawText.m in Sources */, - 58B511D01A9E6C5C00147676 /* RCTShadowText.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 58B511AD1A9E6C1300147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 58B511AE1A9E6C1300147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 58B511B01A9E6C1300147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 58B511B11A9E6C1300147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../ReactKit/**", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 58B511961A9E6C1200147676 /* Build configuration list for PBXProject "RCTText" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511AD1A9E6C1300147676 /* Debug */, - 58B511AE1A9E6C1300147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511AF1A9E6C1300147676 /* Build configuration list for PBXNativeTarget "RCTText" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511B01A9E6C1300147676 /* Debug */, - 58B511B11A9E6C1300147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 58B511931A9E6C1200147676 /* Project object */; -} diff --git a/Libraries/Text/RCTTextManager.h b/Libraries/Text/RCTTextManager.h deleted file mode 100644 index 0359cce4093..00000000000 --- a/Libraries/Text/RCTTextManager.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTTextManager : RCTViewManager - -@end - diff --git a/Libraries/Text/RCTTextManager.m b/Libraries/Text/RCTTextManager.m deleted file mode 100644 index ffe0d8b1e30..00000000000 --- a/Libraries/Text/RCTTextManager.m +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTextManager.h" - -#import "RCTAssert.h" -#import "RCTConvert.h" -#import "RCTLog.h" -#import "RCTShadowRawText.h" -#import "RCTShadowText.h" -#import "RCTSparseArray.h" -#import "RCTText.h" -#import "UIView+ReactKit.h" - -@implementation RCTTextManager - -- (UIView *)view -{ - return [[RCTText alloc] init]; -} - -- (RCTShadowView *)shadowView -{ - return [[RCTShadowText alloc] init]; -} - -RCT_REMAP_VIEW_PROPERTY(containerBackgroundColor, backgroundColor) -RCT_CUSTOM_VIEW_PROPERTY(numberOfLines, RCTText *) -{ - NSLineBreakMode truncationMode = NSLineBreakByClipping; - view.numberOfLines = json ? [RCTConvert NSInteger:json] : defaultView.numberOfLines; - if (view.numberOfLines > 0) { - truncationMode = NSLineBreakByTruncatingTail; - } - view.lineBreakMode = truncationMode; -} - -RCT_CUSTOM_SHADOW_PROPERTY(backgroundColor, RCTShadowText *) -{ - view.textBackgroundColor = json ? [RCTConvert UIColor:json] : defaultView.textBackgroundColor; -} -RCT_CUSTOM_SHADOW_PROPERTY(containerBackgroundColor, RCTShadowText *) -{ - view.backgroundColor = json ? [RCTConvert UIColor:json] : defaultView.backgroundColor; - view.isBGColorExplicitlySet = json ? YES : defaultView.isBGColorExplicitlySet; -} -RCT_CUSTOM_SHADOW_PROPERTY(numberOfLines, RCTShadowText *) -{ - NSLineBreakMode truncationMode = NSLineBreakByClipping; - view.maxNumberOfLines = json ? [RCTConvert NSInteger:json] : defaultView.maxNumberOfLines; - if (view.maxNumberOfLines > 0) { - truncationMode = NSLineBreakByTruncatingTail; - } - view.truncationMode = truncationMode; -} -RCT_CUSTOM_SHADOW_PROPERTY(textAlign, RCTShadowText *) -{ - view.textAlign = json ? [RCTConvert NSTextAlignment:json] : defaultView.textAlign; -} - -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowText *)shadowView -{ - //TODO: This could be a cleaner replacement for uiBlockToAmendWithShadowViewRegistry - return nil; -} - -// TODO: the purpose of this block is effectively just to copy properties from the shadow views -// to their equivalent UIViews. In this case, the property being copied is the attributed text, -// but the same principle could be used to copy any property. The implementation is really ugly tho -// because the RCTViewManager doesn't retain a reference to the views that it manages, so it basically -// has to search the entire view hierarchy for relevant views. Not awesome. This seems like something -// where we could introduce a generic solution - perhaps a method on RCTShadowView that is called after -// layout to copy its properties across? -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry -{ - NSMutableArray *uiBlocks = [NSMutableArray new]; - - // TODO: are modules global, or specific to a given rootView? - for (RCTShadowView *rootView in shadowViewRegistry.allObjects) { - if (![rootView isReactRootView]) { - // This isn't a root view - continue; - } - - if (![rootView isTextDirty]) { - // No text processing to be done - continue; - } - - // TODO: this is a slightly weird way to do this - a recursive approach would be cleaner - RCTSparseArray *reactTaggedAttributedStrings = [[RCTSparseArray alloc] init]; - NSMutableArray *queue = [NSMutableArray arrayWithObject:rootView]; - for (NSInteger i = 0; i < [queue count]; i++) { - RCTShadowView *shadowView = queue[i]; - RCTAssert([shadowView isTextDirty], @"Don't process any nodes that don't have dirty text"); - - if ([shadowView isKindOfClass:[RCTShadowText class]]) { - RCTShadowText *shadowText = (RCTShadowText *)shadowView; - reactTaggedAttributedStrings[shadowText.reactTag] = [shadowText attributedString]; - } else if ([shadowView isKindOfClass:[RCTShadowRawText class]]) { - RCTLogError(@"Raw text cannot be used outside of a tag. Not rendering string: '%@'", [(RCTShadowRawText *)shadowView text]); - } else { - for (RCTShadowView *child in [shadowView reactSubviews]) { - if ([child isTextDirty]) { - [queue addObject:child]; - } - } - } - - [shadowView setTextComputed]; - } - - [uiBlocks addObject:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - [reactTaggedAttributedStrings enumerateObjectsUsingBlock:^(NSAttributedString *attributedString, NSNumber *reactTag, BOOL *stop) { - RCTText *text = viewRegistry[reactTag]; - text.attributedText = attributedString; - }]; - }]; - } - - return ^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - for (RCTViewManagerUIBlock shadowBlock in uiBlocks) { - shadowBlock(uiManager, viewRegistry); - } - }; -} - -@end diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js deleted file mode 100644 index 6171ecbde9e..00000000000 --- a/Libraries/Text/Text.js +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule Text - * @typechecks static-only - */ -'use strict'; - -var NativeMethodsMixin = require('NativeMethodsMixin'); -var React = require('React'); -var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); -var StyleSheetPropType = require('StyleSheetPropType'); -var TextStylePropTypes = require('TextStylePropTypes'); -var Touchable = require('Touchable'); - -var createReactIOSNativeComponentClass = - require('createReactIOSNativeComponentClass'); -var merge = require('merge'); - -var stylePropType = StyleSheetPropType(TextStylePropTypes); - -var viewConfig = { - validAttributes: merge(ReactIOSViewAttributes.UIView, { - isHighlighted: true, - numberOfLines: true, - }), - uiViewClassName: 'RCTText', -}; - -/** - * A react component for displaying text which supports nesting, - * styling, and touch handling. In the following example, the nested title and - * body text will inherit the `fontFamily` from `styles.baseText`, but the title - * provides its own additional styles. The title and body will stack on top of - * each other on account of the literal newlines: - * - * ``` - * renderText: function() { - * return ( - * - * - * {this.state.titleText + '\n\n'} - * - * - * {this.state.bodyText} - * - * - * ); - * }, - * ... - * var styles = StyleSheet.create({ - * baseText: { - * fontFamily: 'Cochin', - * }, - * titleText: { - * fontSize: 20, - * fontWeight: 'bold', - * }, - * }; - * ``` - */ - -var Text = React.createClass({ - - mixins: [Touchable.Mixin, NativeMethodsMixin], - - propTypes: { - /** - * Used to truncate the text with an elipsis after computing the text - * layout, including line wrapping, such that the total number of lines does - * not exceed this number. - */ - numberOfLines: React.PropTypes.number, - /** - * This function is called on press. Text intrinsically supports press - * handling with a default highlight state (which can be disabled with - * `suppressHighlighting`). - */ - onPress: React.PropTypes.func, - /** - * When true, no visual change is made when text is pressed down. By - * default, a gray oval highlights the text on press down. - */ - suppressHighlighting: React.PropTypes.bool, - style: stylePropType, - /** - * Used to locate this view in end-to-end tests. - */ - testID: React.PropTypes.string, - }, - - viewConfig: viewConfig, - - getInitialState: function() { - return merge(this.touchableGetInitialState(), { - isHighlighted: false, - }); - }, - - onStartShouldSetResponder: function() { - var shouldSetFromProps = this.props.onStartShouldSetResponder && - this.props.onStartShouldSetResponder(); - return shouldSetFromProps || !!this.props.onPress; - }, - - /* - * Returns true to allow responder termination - */ - handleResponderTerminationRequest: function() { - // Allow touchable or props.onResponderTerminationRequest to deny - // the request - var allowTermination = this.touchableHandleResponderTerminationRequest(); - if (allowTermination && this.props.onResponderTerminationRequest) { - allowTermination = this.props.onResponderTerminationRequest(); - } - return allowTermination; - }, - - handleResponderGrant: function(e, dispatchID) { - this.touchableHandleResponderGrant(e, dispatchID); - this.props.onResponderGrant && - this.props.onResponderGrant.apply(this, arguments); - }, - - handleResponderMove: function(e) { - this.touchableHandleResponderMove(e); - this.props.onResponderMove && - this.props.onResponderMove.apply(this, arguments); - }, - - handleResponderRelease: function(e) { - this.touchableHandleResponderRelease(e); - this.props.onResponderRelease && - this.props.onResponderRelease.apply(this, arguments); - }, - - handleResponderTerminate: function(e) { - this.touchableHandleResponderTerminate(e); - this.props.onResponderTerminate && - this.props.onResponderTerminate.apply(this, arguments); - }, - - touchableHandleActivePressIn: function() { - if (this.props.suppressHighlighting || !this.props.onPress) { - return; - } - this.setState({ - isHighlighted: true, - }); - }, - - touchableHandleActivePressOut: function() { - if (this.props.suppressHighlighting || !this.props.onPress) { - return; - } - this.setState({ - isHighlighted: false, - }); - }, - - touchableHandlePress: function() { - this.props.onPress && this.props.onPress(); - }, - - touchableGetPressRectOffset: function() { - return PRESS_RECT_OFFSET; - }, - - render: function() { - var props = {}; - for (var key in this.props) { - props[key] = this.props[key]; - } - props.ref = this.getNodeHandle(); - // Text is accessible by default - if (props.accessible !== false) { - props.accessible = true; - } - props.isHighlighted = this.state.isHighlighted; - props.onStartShouldSetResponder = this.onStartShouldSetResponder; - props.onResponderTerminationRequest = - this.handleResponderTerminationRequest; - props.onResponderGrant = this.handleResponderGrant; - props.onResponderMove = this.handleResponderMove; - props.onResponderRelease = this.handleResponderRelease; - props.onResponderTerminate = this.handleResponderTerminate; - return ; - }, -}); - -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; - -var RKText = createReactIOSNativeComponentClass(viewConfig); - -module.exports = Text; diff --git a/Libraries/Text/TextStylePropTypes.js b/Libraries/Text/TextStylePropTypes.js deleted file mode 100644 index 0421794d2fd..00000000000 --- a/Libraries/Text/TextStylePropTypes.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TextStylePropTypes - */ -'use strict'; - -var ReactPropTypes = require('ReactPropTypes'); -var ViewStylePropTypes = require('ViewStylePropTypes'); - -var merge = require('merge'); - -var TextStylePropTypes = merge( - ViewStylePropTypes, { - fontFamily: ReactPropTypes.string, - fontSize: ReactPropTypes.number, - fontWeight: ReactPropTypes.oneOf(['normal' /*default*/, 'bold']), - fontStyle: ReactPropTypes.oneOf(['normal', 'italic']), - lineHeight: ReactPropTypes.number, - color: ReactPropTypes.string, - containerBackgroundColor: ReactPropTypes.string, - textAlign: ReactPropTypes.oneOf( - ['auto' /*default*/, 'left', 'right', 'center'] - ), - writingDirection: ReactPropTypes.oneOf( - ['auto' /*default*/, 'ltr', 'rtl'] - ), - } -); - -// Text doesn't support padding correctly (#4841912) -var unsupportedProps = Object.keys({ - padding: null, - paddingTop: null, - paddingLeft: null, - paddingRight: null, - paddingBottom: null, - paddingVertical: null, - paddingHorizontal: null, -}); - -for (var key in unsupportedProps) { - delete TextStylePropTypes[key]; -} - -module.exports = TextStylePropTypes; diff --git a/Libraries/Utilities/Dimensions.js b/Libraries/Utilities/Dimensions.js deleted file mode 100644 index 97e8d2d017d..00000000000 --- a/Libraries/Utilities/Dimensions.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule Dimensions - */ -'use strict'; - -var NativeModules = require('NativeModules'); - -var invariant = require('invariant'); - -var dimensions = NativeModules.RKUIManager.Dimensions; - -class Dimensions { - /** - * This should only be called from native code. - * - * @param {object} dims Simple string-keyed object of dimensions to set - */ - static set(dims) { - Object.assign(dimensions, dims); - return true; - } - - /** - * Initial dimensions are set before `runApplication` is called so they should - * be available before any other require's are run, but may be updated later. - * - * Note: Although dimensions are available immediately, they may change (e.g - * due to device rotation) so any rendering logic or styles that depend on - * these constants should try to call this function on every render, rather - * than caching the value (for example, using inline styles rather than - * setting a value in a `StyleSheet`). - * - * @param {string} dim Name of dimension as defined when calling `set`. - * @returns {Object?} Value for the dimension. - */ - static get(dim) { - invariant(dimensions[dim], 'No dimension set for key ' + dim); - return dimensions[dim]; - } -} - -module.exports = Dimensions; diff --git a/Libraries/Utilities/ErrorUtils.js b/Libraries/Utilities/ErrorUtils.js deleted file mode 100644 index 3b8ffe4858f..00000000000 --- a/Libraries/Utilities/ErrorUtils.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule ErrorUtils - */ - -var GLOBAL = this; - -/** - * The particular require runtime that we are using looks for a global - * `ErrorUtils` object and if it exists, then it requires modules with the - * error handler specified via ErrorUtils.setGlobalHandler by calling the - * require function with applyWithGuard. Since the require module is loaded - * before any of the modules, this ErrorUtils must be defined (and the handler - * set) globally before requiring anything. - * - * However, we still want to treat ErrorUtils as a module so that other modules - * that use it aren't just using a global variable, so simply export the global - * variable here. ErrorUtils is original defined in a file named error-guard.js. - */ -module.exports = GLOBAL.ErrorUtils; diff --git a/Libraries/Utilities/MessageQueue.js b/Libraries/Utilities/MessageQueue.js deleted file mode 100644 index c5cba052501..00000000000 --- a/Libraries/Utilities/MessageQueue.js +++ /dev/null @@ -1,476 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule MessageQueue - */ -'use strict'; -var ErrorUtils = require('ErrorUtils'); - -var invariant = require('invariant'); -var warning = require('warning'); - -var JSTimersExecution = require('JSTimersExecution'); - -var INTERNAL_ERROR = 'Error in MessageQueue implementation'; - -/** - * So as not to confuse static build system. - */ -var requireFunc = require; - -/** - * @param {Object!} module Module instance, must be loaded. - * @param {string} methodName Name of method in `module`. - * @param {array<*>} params Arguments to method. - * @returns {*} Return value of method invocation. - */ -var jsCall = function(module, methodName, params) { - return module[methodName].apply(module, params); -}; - -/** - * A utility for aggregating "work" to be done, and potentially transferring - * that work to another thread. Each instance of `MessageQueue` has the notion - * of a "target" thread - the thread that the work will be sent to. - * - * TODO: Long running callback results, and streaming callback results (ability - * for a callback to be invoked multiple times). - * - * @param {object} moduleNameToID Used to translate module/method names into - * efficient numeric IDs. - * @class MessageQueue - */ -var MessageQueue = function(remoteModulesConfig, localModulesConfig, customRequire) { - this._requireFunc = customRequire || requireFunc; - this._initBookeeping(); - this._initNamingMap(remoteModulesConfig, localModulesConfig); -}; - -// REQUEST: Parallell arrays: -var REQUEST_MODULE_IDS = 0; -var REQUEST_METHOD_IDS = 1; -var REQUEST_PARAMSS = 2; -// RESPONSE: Parallell arrays: -var RESPONSE_CBIDS = 3; -var RESPONSE_RETURN_VALUES = 4; - -/** - * Utility to catch errors and prevent having to bind, or execute a bound - * function, while catching errors in a process and returning a resulting - * return value. This ensures that even if a process fails, we can still return - * *some* values (from `_flushedQueueUnguarded` for example). Glorified - * try/catch/finally that invokes the global `onerror`. - * - * @param {function} operation Function to execute, likely populates the - * message buffer. - * @param {Array<*>} operationArguments Arguments passed to `operation`. - * @param {function} getReturnValue Returns a return value - will be invoked - * even if the `operation` fails half way through completing its task. - * @return {object} Return value returned from `getReturnValue`. - */ -var guardReturn = function(operation, operationArguments, getReturnValue, context) { - if (operation) { - ErrorUtils.applyWithGuard(operation, context, operationArguments); - } - if (getReturnValue) { - return ErrorUtils.applyWithGuard(getReturnValue, context, null); - } - return null; -}; - -/** - * Bookkeeping logic for callbackIDs. We ensure that success and error - * callbacks are numerically adjacent. - * - * We could have also stored the association between success cbID and errorCBID - * in a map without relying on this adjacency, but the bookkeeping here avoids - * an additional two maps to associate in each direction, and avoids growing - * dictionaries (new fields). Instead, we compute pairs of callback IDs, by - * populating the `res` argument to `allocateCallbackIDs` (in conjunction with - * pooling). Behind this bookeeping API, we ensure that error and success - * callback IDs are always adjacent so that when one is invoked, we always know - * how to free the memory of the other. By using this API, it is impossible to - * create malformed callbackIDs that are not adjacent. - */ -var createBookkeeping = function() { - return { - /** - * Incrementing callback ID. Must start at 1 - otherwise converted null - * values which become zero are not distinguishable from a GUID of zero. - */ - GUID: 1, - errorCallbackIDForSuccessCallbackID: function(successID) { - return successID + 1; - }, - successCallbackIDForErrorCallbackID: function(errorID) { - return errorID - 1; - }, - allocateCallbackIDs: function(res) { - res.successCallbackID = this.GUID++; - res.errorCallbackID = this.GUID++; - }, - isSuccessCallback: function(id) { - return id % 2 === 1; - } - }; -}; - -var MessageQueueMixin = { - /** - * Creates an efficient wire protocol for communicating across a bridge. - * Avoids allocating strings. - * - * @param {object} remoteModulesConfig Configuration of modules and their - * methods. - */ - _initNamingMap: function(remoteModulesConfig, localModulesConfig) { - this._remoteModuleNameToModuleID = {}; - this._remoteModuleIDToModuleName = {}; // Reverse - - this._remoteModuleNameToMethodNameToID = {}; - this._remoteModuleNameToMethodIDToName = {}; // Reverse - - this._localModuleNameToModuleID = {}; - this._localModuleIDToModuleName = {}; // Reverse - - this._localModuleNameToMethodNameToID = {}; - this._localModuleNameToMethodIDToName = {}; // Reverse - - function fillMappings( - modulesConfig, - moduleNameToModuleID, - moduleIDToModuleName, - moduleNameToMethodNameToID, - moduleNameToMethodIDToName - ) { - for (var moduleName in modulesConfig) { - var moduleConfig = modulesConfig[moduleName]; - var moduleID = moduleConfig.moduleID; - moduleNameToModuleID[moduleName] = moduleID; - moduleIDToModuleName[moduleID] = moduleName; // Reverse - - moduleNameToMethodNameToID[moduleName] = {}; - moduleNameToMethodIDToName[moduleName] = {}; // Reverse - var methods = moduleConfig.methods; - for (var methodName in methods) { - var methodID = methods[methodName].methodID; - moduleNameToMethodNameToID[moduleName][methodName] = - methodID; - moduleNameToMethodIDToName[moduleName][methodID] = - methodName; // Reverse - } - } - } - fillMappings( - remoteModulesConfig, - this._remoteModuleNameToModuleID, - this._remoteModuleIDToModuleName, - this._remoteModuleNameToMethodNameToID, - this._remoteModuleNameToMethodIDToName - ); - - fillMappings( - localModulesConfig, - this._localModuleNameToModuleID, - this._localModuleIDToModuleName, - this._localModuleNameToMethodNameToID, - this._localModuleNameToMethodIDToName - ); - - }, - - _initBookeeping: function() { - this._POOLED_CBIDS = {errorCallbackID: null, successCallbackID: null}; - this._bookkeeping = createBookkeeping(); - - /** - * Stores callbacks so that we may simulate asynchronous return values from - * other threads. Remote invocations in other threads can pass return values - * back asynchronously to the requesting thread. - */ - this._threadLocalCallbacksByID = []; - this._threadLocalScopesByID = []; - - /** - * Memory efficient parallel arrays. Each index cuts through the three - * arrays and forms a remote invocation of methodName(params) whos return - * value will be reported back to the other thread by way of the - * corresponding id in cbIDs. Each entry (A-D in the graphic below), - * represents a work item of the following form: - * - moduleID: ID of module to invoke method from. - * - methodID: ID of method in module to invoke. - * - params: List of params to pass to method. - * - cbID: ID to respond back to originating thread with. - * - * TODO: We can make this even more efficient (memory) by creating a single - * array, that is always pushed `n` elements as a time. - */ - this._outgoingItems = [ - /*REQUEST_MODULE_IDS: */ [/* +-+ +-+ +-+ +-+ */], - /*REQUEST_METHOD_IDS: */ [/* |A| |B| |C| |D| */], - /*REQUEST_PARAMSS: */ [/* |-| |-| |-| |-| */], - - /*RESPONSE_CBIDS: */ [/* +-+ +-+ +-+ +-+ */], - /* |E| |F| |G| |H| */ - /*RESPONSE_RETURN_VALUES: */ [/* +-+ +-+ +-+ +-+ */] - ]; - - /** - * Used to allow returning the buffer, while at the same time clearing it in - * a memory efficient manner. - */ - this._outgoingItemsSwap = [[], [], [], [], []]; - }, - - invokeCallback: function(cbID, args) { - return guardReturn(this._invokeCallback, [cbID, args], null, this); - }, - - _invokeCallback: function(cbID, args) { - try { - var cb = this._threadLocalCallbacksByID[cbID]; - var scope = this._threadLocalScopesByID[cbID]; - warning( - cb, - 'Cannot find callback with CBID %s. Native module may have invoked ' + - 'both the success callback and the error callback.', - cbID - ); - cb.apply(scope, args); - } catch(ie_requires_catch) { - throw ie_requires_catch; - } finally { - // Clear out the memory regardless of success or failure. - this._freeResourcesForCallbackID(cbID); - } - }, - - invokeCallbackAndReturnFlushedQueue: function(cbID, args) { - if (this._enableLogging) { - this._loggedIncomingItems.push([new Date().getTime(), cbID, args]); - } - return guardReturn( - this._invokeCallback, - [cbID, args], - this._flushedQueueUnguarded, - this - ); - }, - - callFunction: function(moduleID, methodID, params) { - return guardReturn(this._callFunction, [moduleID, methodID, params], null, this); - }, - - _callFunction: function(moduleID, methodID, params) { - var moduleName = this._localModuleIDToModuleName[moduleID]; - - var methodName = this._localModuleNameToMethodIDToName[moduleName][methodID]; - var ret = jsCall(this._requireFunc(moduleName), methodName, params); - - return ret; - }, - - callFunctionReturnFlushedQueue: function(moduleID, methodID, params) { - if (this._enableLogging) { - this._loggedIncomingItems.push([new Date().getTime(), moduleID, methodID, params]); - } - return guardReturn( - this._callFunction, - [moduleID, methodID, params], - this._flushedQueueUnguarded, - this - ); - }, - - setLoggingEnabled: function(enabled) { - this._enableLogging = enabled; - this._loggedIncomingItems = []; - this._loggedOutgoingItems = [[], [], [], [], []]; - }, - - getLoggedIncomingItems: function() { - return this._loggedIncomingItems; - }, - - getLoggedOutgoingItems: function() { - return this._loggedOutgoingItems; - }, - - replayPreviousLog: function(previousLog) { - this._outgoingItems = previousLog; - }, - - /** - * Simple helpers for clearing the queues. This doesn't handle the fact that - * memory in the current buffer is leaked until the next frame or update - but - * that will typically be on the order of < 500ms. - */ - _swapAndReinitializeBuffer: function() { - // Outgoing requests - var currentOutgoingItems = this._outgoingItems; - var nextOutgoingItems = this._outgoingItemsSwap; - - nextOutgoingItems[REQUEST_MODULE_IDS].length = 0; - nextOutgoingItems[REQUEST_METHOD_IDS].length = 0; - nextOutgoingItems[REQUEST_PARAMSS].length = 0; - - // Outgoing responses - nextOutgoingItems[RESPONSE_CBIDS].length = 0; - nextOutgoingItems[RESPONSE_RETURN_VALUES].length = 0; - - this._outgoingItemsSwap = currentOutgoingItems; - this._outgoingItems = nextOutgoingItems; - }, - - /** - * @param {string} moduleID JS module name. - * @param {methodName} methodName Method in module to invoke. - * @param {array<*>?} params Array representing arguments to method. - * @param {string} cbID Unique ID to pass back in potential response. - */ - _pushRequestToOutgoingItems: function(moduleID, methodName, params) { - this._outgoingItems[REQUEST_MODULE_IDS].push(moduleID); - this._outgoingItems[REQUEST_METHOD_IDS].push(methodName); - this._outgoingItems[REQUEST_PARAMSS].push(params); - - if (this._enableLogging) { - this._loggedOutgoingItems[REQUEST_MODULE_IDS].push(moduleID); - this._loggedOutgoingItems[REQUEST_METHOD_IDS].push(methodName); - this._loggedOutgoingItems[REQUEST_PARAMSS].push(params); - } - }, - - /** - * @param {string} cbID Unique ID that other side of bridge has remembered. - * @param {*} returnValue Return value to pass to callback on other side of - * bridge. - */ - _pushResponseToOutgoingItems: function(cbID, returnValue) { - this._outgoingItems[RESPONSE_CBIDS].push(cbID); - this._outgoingItems[RESPONSE_RETURN_VALUES].push(returnValue); - }, - - _freeResourcesForCallbackID: function(cbID) { - var correspondingCBID = this._bookkeeping.isSuccessCallback(cbID) ? - this._bookkeeping.errorCallbackIDForSuccessCallbackID(cbID) : - this._bookkeeping.successCallbackIDForErrorCallbackID(cbID); - this._threadLocalCallbacksByID[cbID] = null; - this._threadLocalScopesByID[cbID] = null; - if (this._threadLocalCallbacksByID[correspondingCBID]) { - this._threadLocalCallbacksByID[correspondingCBID] = null; - this._threadLocalScopesByID[correspondingCBID] = null; - } - }, - - /** - * @param {Function} onFail Function to store in current thread for later - * lookup, when request fails. - * @param {Function} onSucc Function to store in current thread for later - * lookup, when request succeeds. - * @param {Object?=} scope Scope to invoke `cb` with. - * @param {Object?=} res Resulting callback ids. Use `this._POOLED_CBIDS`. - */ - _storeCallbacksInCurrentThread: function(onFail, onSucc, scope) { - invariant(onFail || onSucc, INTERNAL_ERROR); - this._bookkeeping.allocateCallbackIDs(this._POOLED_CBIDS); - var succCBID = this._POOLED_CBIDS.successCallbackID; - var errorCBID = this._POOLED_CBIDS.errorCallbackID; - this._threadLocalCallbacksByID[errorCBID] = onFail; - this._threadLocalCallbacksByID[succCBID] = onSucc; - this._threadLocalScopesByID[errorCBID] = scope; - this._threadLocalScopesByID[succCBID] = scope; - }, - - - /** - * IMPORTANT: There is possibly a timing issue with this form of flushing. We - * are currently not seeing any problems but the potential issue to look out - * for is: - * - While flushing this._outgoingItems contains the work for the other thread - * to perform. - * - To mitigate this, we never allow enqueueing messages if the queue is - * already reserved - as long as it is reserved, it could be in the midst of - * a flush. - * - * If this ever occurs we can easily eliminate the race condition. We can - * completely solve any ambiguity by sending messages such that we'll never - * try to reserve the queue when already reserved. Here's the pseudocode: - * - * var defensiveCopy = efficientDefensiveCopy(this._outgoingItems); - * this._swapAndReinitializeBuffer(); - */ - flushedQueue: function() { - return guardReturn(null, null, this._flushedQueueUnguarded, this); - }, - - _flushedQueueUnguarded: function() { - // Call the functions registred via setImmediate - JSTimersExecution.callImmediates(); - - var currentOutgoingItems = this._outgoingItems; - this._swapAndReinitializeBuffer(); - var ret = currentOutgoingItems[REQUEST_MODULE_IDS].length || - currentOutgoingItems[RESPONSE_RETURN_VALUES].length ? currentOutgoingItems : null; - - return ret; - }, - - callDeprecated: function(moduleName, methodName, params, cb, scope) { - invariant( - !cb || typeof cb === 'function', - 'Last argument (callback) must be function' - ); - // Store callback _before_ sending the request, just in case the MailBox - // returns the response in a blocking manner - if (cb) { - this._storeCallbacksInCurrentThread(null, cb, scope, this._POOLED_CBIDS); - params.push(this._POOLED_CBIDS.successCallbackID); - } - var moduleID = this._remoteModuleNameToModuleID[moduleName]; - if (moduleID === undefined || moduleID === null) { - throw new Error('Unrecognized module name:' + moduleName); - } - var methodID = this._remoteModuleNameToMethodNameToID[moduleName][methodName]; - if (methodID === undefined || moduleID === null) { - throw new Error('Unrecognized method name:' + methodName); - } - this._pushRequestToOutgoingItems(moduleID, methodID, params); - }, - - call: function(moduleName, methodName, params, onFail, onSucc, scope) { - invariant( - (!onFail || typeof onFail === 'function') && - (!onSucc || typeof onSucc === 'function'), - 'Callbacks must be functions' - ); - // Store callback _before_ sending the request, just in case the MailBox - // returns the response in a blocking manner. - if (onFail || onSucc) { - this._storeCallbacksInCurrentThread(onFail, onSucc, scope, this._POOLED_CBIDS); - params.push(this._POOLED_CBIDS.errorCallbackID); - params.push(this._POOLED_CBIDS.successCallbackID); - } - var moduleID = this._remoteModuleNameToModuleID[moduleName]; - if (moduleID === undefined || moduleID === null) { - throw new Error('Unrecognized module name:' + moduleName); - } - var methodID = this._remoteModuleNameToMethodNameToID[moduleName][methodName]; - if (methodID === undefined || moduleID === null) { - throw new Error('Unrecognized method name:' + methodName); - } - this._pushRequestToOutgoingItems(moduleID, methodID, params); - }, - __numPendingCallbacksOnlyUseMeInTestCases: function() { - var callbacks = this._threadLocalCallbacksByID; - var total = 0; - for (var i = 0; i < callbacks.length; i++) { - if (callbacks[i]) { - total++; - } - } - return total; - } -}; - -Object.assign(MessageQueue.prototype, MessageQueueMixin); -module.exports = MessageQueue; diff --git a/Libraries/Utilities/PixelRatio.js b/Libraries/Utilities/PixelRatio.js deleted file mode 100644 index 0eeb074c686..00000000000 --- a/Libraries/Utilities/PixelRatio.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule PixelRatio - */ -'use strict'; - -var Dimensions = require('Dimensions'); - -/** - * PixelRatio class gives access to the device pixel density. - * - * Some examples: - * - PixelRatio.get() === 2 - * - iPhone 4, 4S - * - iPhone 5, 5c, 5s - * - iPhone 6 - * - * - PixelRatio.get() === 3 - * - iPhone 6 plus - * - * There are a few use cases for using PixelRatio: - * - * == Displaying a line that's as thin as the device permits - * - * A width of 1 is actually pretty thick on an iPhone 4+, we can do one that's - * thinner using a width of 1 / PixelRatio.get(). It's a technique that works - * on all the devices independent of their pixel density. - * - * style={{ borderWidth: 1 / PixelRatio.get() }} - * - * == Fetching a correctly sized image - * - * You should get a higher resolution image if you are on a high pixel density - * device. A good rule of thumb is to multiply the size of the image you display - * by the pixel ratio. - * - * var image = getImage({ - * width: 200 * PixelRatio.get(), - * height: 100 * PixelRatio.get() - * }); - * - */ -class PixelRatio { - static get() { - return Dimensions.get('window').scale; - } - - static startDetecting() { - // no-op for iOS, but this is useful for other platforms - } -}; - -module.exports = PixelRatio; diff --git a/Libraries/Utilities/Platform.ios.js b/Libraries/Utilities/Platform.ios.js deleted file mode 100644 index ef61a47deec..00000000000 --- a/Libraries/Utilities/Platform.ios.js +++ /dev/null @@ -1,11 +0,0 @@ -/** -* @providesModule Platform -*/ - -'use strict'; - -var Platform = { - OS: 'ios', -}; - -module.exports = Platform; diff --git a/Libraries/Utilities/RCTLog.js b/Libraries/Utilities/RCTLog.js deleted file mode 100644 index ab648098a4c..00000000000 --- a/Libraries/Utilities/RCTLog.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule RCTLog - */ - /* globals nativeLoggingHook */ -'use strict'; - -var invariant = require('invariant'); - -var levelsMap = { - log: 'log', - info: 'info', - warn: 'warn', - error: 'error', - mustfix: 'error', -}; - -class RCTLog { - // level one of log, info, warn, error, mustfix - static logIfNoNativeHook() { - var args = Array.prototype.slice.call(arguments); - var level = args.shift(); - var logFn = levelsMap[level]; - invariant( - logFn, - 'Level "' + level + '" not one of ' + Object.keys(levelsMap) - ); - if (typeof nativeLoggingHook === 'undefined') { - // We already printed in xcode, so only log here if using a js debugger - console[logFn].apply(console, args); - } - return true; - } -} - -module.exports = RCTLog; diff --git a/Libraries/Utilities/RCTRenderingPerf.js b/Libraries/Utilities/RCTRenderingPerf.js deleted file mode 100644 index cdc44aaa6a4..00000000000 --- a/Libraries/Utilities/RCTRenderingPerf.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule RCTRenderingPerf - */ -'use strict'; - -var ReactDefaultPerf = require('ReactDefaultPerf'); -var ReactPerf = require('ReactPerf'); - -var invariant = require('invariant'); - -var perfModules = []; -var enabled = false; - -var RCTRenderingPerf = { - // Once perf is enabled, it stays enabled - toggle: function() { - console.log('Render perfomance measurements enabled'); - enabled = true; - }, - - start: function() { - if (!enabled) { - return; - } - - ReactDefaultPerf.start(); - perfModules.forEach((module) => module.start()); - }, - - stop: function() { - if (!enabled) { - return; - } - - ReactDefaultPerf.stop(); - ReactDefaultPerf.printInclusive(); - ReactDefaultPerf.printWasted(); - perfModules.forEach((module) => module.stop()); - }, - - register: function(module) { - invariant( - typeof module.start === 'function', - 'Perf module should have start() function' - ); - invariant( - typeof module.stop === 'function', - 'Perf module should have stop() function' - ); - perfModules.push(module); - } -}; - -module.exports = RCTRenderingPerf; diff --git a/Libraries/Utilities/TimerMixin.js b/Libraries/Utilities/TimerMixin.js deleted file mode 100644 index eb2c286396a..00000000000 --- a/Libraries/Utilities/TimerMixin.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule TimerMixin - */ -'use strict'; - -/** - * Using bare setTimeout, setInterval, setImmediate and - * requestAnimationFrame calls is very dangerous because if you forget to cancel - * the request before the component is unmounted, you risk the callback throwing - * an exception. - * - * If you include TimerMixin, then you can replace your calls - * to `setTimeout(fn, 500)` - * with `this.setTimeout(fn, 500)` (just prepend `this.`) - * and everything will be properly cleaned up for you. - * - * Example: - * - * var Component = React.createClass({ - * mixins: [TimerMixin], - * componentDidMount: function() { - * this.setTimeout( - * () => { console.log('I do not leak!'); }, - * 500 - * ); - * } - * }); - */ - - var setter = function(setter, clearer, array) { - return function(callback, delta) { - var id = setter(() => { - clearer.call(this, id); - callback.apply(this, arguments); - }, delta); - - if (!this[array]) { - this[array] = [id]; - } else { - this[array].push(id); - } - return id; - }; - }; - - var clearer = function(clearer, array) { - return function(id) { - if (this[array]) { - var index = this[array].indexOf(id); - if (index !== -1) { - this[array].splice(index, 1); - } - } - clearer(id); - }; - }; - - var _timeouts = 'TimerMixin_timeouts'; - var _clearTimeout = clearer(clearTimeout, _timeouts); - var _setTimeout = setter(setTimeout, _clearTimeout, _timeouts); - - var _intervals = 'TimerMixin_intervals'; - var _clearInterval = clearer(clearInterval, _intervals); - var _setInterval = setter(setInterval, () => {/* noop */}, _intervals); - - var _immediates = 'TimerMixin_immediates'; - var _clearImmediate = clearer(clearImmediate, _immediates); - var _setImmediate = setter(setImmediate, _clearImmediate, _immediates); - - var _rafs = 'TimerMixin_rafs'; - var _cancelAnimationFrame = clearer(cancelAnimationFrame, _rafs); - var _requestAnimationFrame = setter(requestAnimationFrame, _cancelAnimationFrame, _rafs); - -var TimerMixin = { - componentWillUnmount: function() { - this[_timeouts] && this[_timeouts].forEach(this.clearTimeout); - this[_intervals] && this[_intervals].forEach(this.clearInterval); - this[_immediates] && this[_immediates].forEach(this.clearImmediate); - this[_rafs] && this[_rafs].forEach(this.cancelAnimationFrame); - }, - - setTimeout: _setTimeout, - clearTimeout: _clearTimeout, - - setInterval: _setInterval, - clearInterval: _clearInterval, - - setImmediate: _setImmediate, - clearImmediate: _clearImmediate, - - requestAnimationFrame: _requestAnimationFrame, - cancelAnimationFrame: _cancelAnimationFrame, -}; - -module.exports = TimerMixin; diff --git a/Libraries/Utilities/createStrictShapeTypeChecker.js b/Libraries/Utilities/createStrictShapeTypeChecker.js deleted file mode 100644 index daaacb9b42b..00000000000 --- a/Libraries/Utilities/createStrictShapeTypeChecker.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule createStrictShapeTypeChecker - */ -'use strict'; - -var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames'); - -var invariant = require('invariant'); -var merge = require('merge'); - -function createStrictShapeTypeChecker(shapeTypes) { - function checkType(isRequired, props, propName, componentName, location) { - if (!props[propName]) { - if (isRequired) { - invariant( - false, - `Required object \`${propName}\` was not specified in `+ - `\`${componentName}\`.` - ); - } - return; - } - var propValue = props[propName]; - var propType = typeof propValue; - var locationName = ReactPropTypeLocationNames[location]; - if (propType !== 'object') { - invariant( - false, - `Invalid ${locationName} \`${propName}\` of type \`${propType}\` ` + - `supplied to \`${componentName}\`, expected \`object\`.` - ); - } - // We need to check all keys in case some are required but missing from - // props. - var allKeys = merge(props[propName], shapeTypes); - for (var key in allKeys) { - var checker = shapeTypes[key]; - if (!checker) { - invariant( - false, - `Invalid props.${propName} key \`${key}\` supplied to \`${componentName}\`.` + - `\nBad object: ` + JSON.stringify(props[propName], null, ' ') + - `\nValid keys: ` + JSON.stringify(Object.keys(shapeTypes), null, ' ') - ); - } - var error = checker(propValue, key, componentName, location); - if (error) { - invariant( - false, - error.message + - `\nBad object: ` + JSON.stringify(props[propName], null, ' ') - ); - return error; - } - } - } - var chainedCheckType = checkType.bind(null, false); - chainedCheckType.isRequired = checkType.bind(null, true); - return chainedCheckType; -} - -module.exports = createStrictShapeTypeChecker; diff --git a/Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.js b/Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.js deleted file mode 100644 index 3610461d331..00000000000 --- a/Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule deepFreezeAndThrowOnMutationInDev - */ - -/** - * If your application is accepting different values for the same field over - * time and is doing a diff on them, you can either (1) create a copy or - * (2) ensure that those values are not mutated behind two passes. - * This function helps you with (2) by freezing the object and throwing if - * the user subsequently modifies the value. - * - * There are two caveats with this function: - * - If the call site is not in strict mode, it will only throw when - * mutating existing fields, adding a new one - * will unfortunately fail silently :( - * - If the object is already frozen or sealed, it will not continue the - * deep traversal and will leave leaf nodes unfrozen. - * - * Freezing the object and adding the throw mechanism is expensive and will - * only be used in DEV. - */ -function deepFreezeAndThrowOnMutationInDev(object) { - if (__DEV__) { - if (typeof object !== 'object' || - object === null || - Object.isFrozen(object) || - Object.isSealed(object)) { - return; - } - - for (var key in object) { - if (object.hasOwnProperty(key)) { - object.__defineGetter__(key, identity.bind(null, object[key])); - object.__defineSetter__(key, throwOnImmutableMutation.bind(null, key)); - deepFreezeAndThrowOnMutationInDev(object[key]); - } - } - Object.freeze(object); - Object.seal(object); - } -} - -function throwOnImmutableMutation(key, value) { - throw Error( - 'You attempted to set the key `' + key + '` with the value `' + - JSON.stringify(value) + '` on an object that is meant to be immutable ' + - 'and has been frozen.' - ); -} - -function identity(value) { - return value; -} - -module.exports = deepFreezeAndThrowOnMutationInDev; diff --git a/Libraries/Utilities/differ/deepDiffer.js b/Libraries/Utilities/differ/deepDiffer.js deleted file mode 100644 index 97c3f516fe0..00000000000 --- a/Libraries/Utilities/differ/deepDiffer.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule deepDiffer - * @flow - */ -'use strict'; - -/* - * @returns {bool} true if different, false if equal - */ -var deepDiffer = function(one: any, two: any): bool { - if (one === two) { - // Short circuit on identical object references instead of traversing them. - return false; - } - if ((typeof one === 'function') && (typeof two === 'function')) { - // We consider all functions equal - return false; - } - if ((typeof one !== 'object') || (one === null)) { - // Primitives can be directly compared - return one !== two; - } - if ((typeof two !== 'object') || (two === null)) { - // We know they are different because the previous case would have triggered - // otherwise. - return true; - } - if (one.constructor !== two.constructor) { - return true; - } - for (var key in one) { - if (deepDiffer(one[key], two[key])) { - return true; - } - } - for (var twoKey in two) { - // The only case we haven't checked yet is keys that are in two but aren't - // in one, which means they are different. - if (one[twoKey] === undefined) { - return true; - } - } - return false; -}; - -module.exports = deepDiffer; diff --git a/Libraries/Utilities/differ/insetsDiffer.js b/Libraries/Utilities/differ/insetsDiffer.js deleted file mode 100644 index 07b8c08ab41..00000000000 --- a/Libraries/Utilities/differ/insetsDiffer.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule insetsDiffer - */ -'use strict'; - -var dummyInsets = { - top: undefined, - left: undefined, - right: undefined, - bottom: undefined, -}; - -var insetsDiffer = function(one, two) { - one = one || dummyInsets; - two = two || dummyInsets; - return one !== two && ( - one.top !== two.top || - one.left !== two.left || - one.right !== two.right || - one.bottom !== two.bottom - ); -}; - -module.exports = insetsDiffer; diff --git a/Libraries/Utilities/differ/matricesDiffer.js b/Libraries/Utilities/differ/matricesDiffer.js deleted file mode 100644 index c4d1109e7de..00000000000 --- a/Libraries/Utilities/differ/matricesDiffer.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule matricesDiffer - */ -'use strict'; - -/** - * Unrolls an array comparison specially for matrices. Prioritizes - * checking of indices that are most likely to change so that the comparison - * bails as early as possible. - * - * @param {MatrixMath.Matrix} one First matrix. - * @param {MatrixMath.Matrix} two Second matrix. - * @return {boolean} Whether or not the two matrices differ. - */ -var matricesDiffer = function(one, two) { - if (one === two) { - return false; - } - return !one || !two || - one[12] !== two[12] || - one[13] !== two[13] || - one[14] !== two[14] || - one[5] !== two[5] || - one[10] !== two[10] || - one[1] !== two[1] || - one[2] !== two[2] || - one[3] !== two[3] || - one[4] !== two[4] || - one[6] !== two[6] || - one[7] !== two[7] || - one[8] !== two[8] || - one[9] !== two[9] || - one[11] !== two[11] || - one[15] !== two[15]; -}; - -module.exports = matricesDiffer; diff --git a/Libraries/Utilities/differ/pointsDiffer.js b/Libraries/Utilities/differ/pointsDiffer.js deleted file mode 100644 index 76eff60ba81..00000000000 --- a/Libraries/Utilities/differ/pointsDiffer.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule pointsDiffer - */ -'use strict'; - -var dummyPoint = {x: undefined, y: undefined}; - -var pointsDiffer = function(one, two) { - one = one || dummyPoint; - two = two || dummyPoint; - return one !== two && ( - one.x !== two.x || - one.y !== two.y - ); -}; - -module.exports = pointsDiffer; diff --git a/Libraries/Utilities/logError.js b/Libraries/Utilities/logError.js deleted file mode 100644 index 8f14c4995c9..00000000000 --- a/Libraries/Utilities/logError.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule logError - */ -'use strict'; - -/** - * Small utility that can be used as an error handler. You cannot just pass - * `console.error` as a failure callback - it's not properly bound. If passes an - * `Error` object, it will print the message and stack. - */ -var logError = function() { - if (arguments.length === 1 && arguments[0] instanceof Error) { - var err = arguments[0]; - console.error('Error: "' + err.message + '". Stack:\n' + err.stack); - } else { - console.error.apply(console, arguments); - } -}; - -module.exports = logError; diff --git a/Libraries/Utilities/mergeFast.js b/Libraries/Utilities/mergeFast.js deleted file mode 100644 index 2d6a82a528c..00000000000 --- a/Libraries/Utilities/mergeFast.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule mergeFast - */ -'use strict'; - -/** - * Faster version of `merge` that doesn't check its arguments and - * also merges prototye inherited properties. - * - * @param {object} one Any non-null object. - * @param {object} two Any non-null object. - * @return {object} Merging of two objects, including prototype - * inherited properties. - */ -var mergeFast = function(one, two) { - var ret = {}; - for (var keyOne in one) { - ret[keyOne] = one[keyOne]; - } - for (var keyTwo in two) { - ret[keyTwo] = two[keyTwo]; - } - return ret; -}; - -module.exports = mergeFast; diff --git a/Libraries/Utilities/mergeIntoFast.js b/Libraries/Utilities/mergeIntoFast.js deleted file mode 100644 index d3788a4e743..00000000000 --- a/Libraries/Utilities/mergeIntoFast.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule mergeIntoFast - */ -'use strict'; - -/** - * Faster version of `mergeInto` that doesn't check its arguments and - * also copies over prototye inherited properties. - * - * @param {object} one Object to assign to. - * @param {object} two Object to assign from. - */ -var mergeIntoFast = function(one, two) { - for (var keyTwo in two) { - one[keyTwo] = two[keyTwo]; - } -}; - -module.exports = mergeIntoFast; diff --git a/Libraries/Utilities/truncate.js b/Libraries/Utilities/truncate.js deleted file mode 100644 index 2ffcfe10aa5..00000000000 --- a/Libraries/Utilities/truncate.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @providesModule truncate - */ -'use strict'; - -var merge = require('merge'); - -var defaultOptions = { - breakOnWords: true, - minDelta: 10, // Prevents truncating a tiny bit off the end - elipsis: '...', -}; - -// maxChars (including elipsis) -var truncate = function(str, maxChars, options) { - options = merge(defaultOptions, options); - if (str && str.length && - str.length - options.minDelta + options.elipsis.length >= maxChars) { - str = str.slice(0, maxChars - options.elipsis.length + 1); - if (options.breakOnWords) { - var ii = Math.max(str.lastIndexOf(' '), str.lastIndexOf('\n')); - str = str.slice(0, ii); - } - str = str.trim() + options.elipsis; - } - return str; -}; - -module.exports = truncate; - diff --git a/Libraries/react-native/addons.js b/Libraries/react-native/addons.js deleted file mode 100644 index fcef285e223..00000000000 --- a/Libraries/react-native/addons.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @flow - */ -'use strict'; - -var LinkedStateMixin = require('LinkedStateMixin'); -var ReactComponentWithPureRenderMixin = require('ReactComponentWithPureRenderMixin'); -var ReactNative = require('react-native'); -var ReactUpdates = require('ReactUpdates'); - -var cloneWithProps = require('cloneWithProps'); -var update = require('update'); - -var addons = { - LinkedStateMixin: LinkedStateMixin, - PureRenderMixin: ReactComponentWithPureRenderMixin, - batchedUpdates: ReactUpdates.batchedUpdates, - cloneWithProps: cloneWithProps, - update: update, -}; - -if (__DEV__) { - addons.Perf = require('ReactDefaultPerf'); - addons.TestUtils = require('ReactTestUtils'); -} - -var ReactNativeWithAddons = { - ...ReactNative, - addons: addons, -}; - -module.exports = ReactNativeWithAddons; diff --git a/Libraries/react-native/package.json b/Libraries/react-native/package.json deleted file mode 100644 index e8306d48583..00000000000 --- a/Libraries/react-native/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "react-native", - "main": "react-native.js", - "directories": {".": ""} -} diff --git a/Libraries/react-native/react-native-interface.js b/Libraries/react-native/react-native-interface.js deleted file mode 100644 index c37bbe68572..00000000000 --- a/Libraries/react-native/react-native-interface.js +++ /dev/null @@ -1,36 +0,0 @@ -declare module "react-native" { - declare class ListViewDataSource { - constructor(params: Object): void; - } - - declare var AppRegistry: ReactClass; - declare var ExpandingText: ReactClass; - declare var Image: ReactClass; - declare var ListView: ReactClass; - declare var NavigatorIOS: ReactClass; - declare var NavigatorItemIOS: ReactClass; - declare var PixelRatio: ReactClass; - declare var ScrollView: ReactClass; - declare var ActivityIndicatorIOS: ReactClass; - declare var StyleSheet: ReactClass; - declare var Text: ReactClass; - declare var TextInput: ReactClass; - declare var TimerMixin: ReactClass; - declare var TouchableHighlight: ReactClass; - declare var TouchableWithoutFeedback: ReactClass; - declare var View: ReactClass; - declare var invariant: Function; - declare var ix: Function; -} - -declare module "addons" { - declare var NavigatorIOS: ReactClass; - declare var NavigatorItemIOS: ReactClass; - declare var StyleSheet: ReactClass; -} - -declare var __DEV__: boolean; - -declare module "fetch" { - declare function exports(url: string, options?: Object): Object; -} diff --git a/Libraries/react-native/react-native.js b/Libraries/react-native/react-native.js deleted file mode 100644 index 7f7edaf7275..00000000000 --- a/Libraries/react-native/react-native.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * @flow - */ -'use strict'; - -var ReactNative = { - ...require('React'), - AppRegistry: require('AppRegistry'), - DatePickerIOS: require('DatePickerIOS'), - ExpandingText: require('ExpandingText'), - Image: require('Image'), - LayoutAnimation: require('LayoutAnimation'), - ListView: require('ListView'), - ListViewDataSource: require('ListViewDataSource'), - NavigatorIOS: require('NavigatorIOS'), - PixelRatio: require('PixelRatio'), - ScrollView: require('ScrollView'), - ActivityIndicatorIOS: require('ActivityIndicatorIOS'), - Slider: require('Slider'), - StatusBarIOS: require('StatusBarIOS'), - StyleSheet: require('StyleSheet'), - SwitchIOS: require('SwitchIOS'), - Text: require('Text'), - TextInput: require('TextInput'), - TimerMixin: require('TimerMixin'), - TouchableHighlight: require('TouchableHighlight'), - TouchableOpacity: require('TouchableOpacity'), - TouchableWithoutFeedback: require('TouchableWithoutFeedback'), - View: require('View'), - invariant: require('invariant'), - ix: require('ix'), -}; - -module.exports = ReactNative; diff --git a/Libraries/vendor/core/ES6Promise.js b/Libraries/vendor/core/ES6Promise.js deleted file mode 100644 index acbf02773f5..00000000000 --- a/Libraries/vendor/core/ES6Promise.js +++ /dev/null @@ -1,364 +0,0 @@ -/** - * @generated SignedSource<> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule ES6Promise - * - * This module implements the minimum functionality necessary to comply - * with chapter 25.4 of the ES6 specification. Any extensions to Promise - * or Promise.prototype should be added in the Promise module. - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-objects - */ - -module.exports = (function(global, undefined) { - 'use strict'; - - var setImmediate = require('setImmediate'); - - // These are the possible values for slots(promise).state. - var PENDING_STATE = 'pending'; - var FULFILLED_STATE = 'fulfilled'; - var REJECTED_STATE = 'rejected'; - - // The ES6 specification makes heavy use of a notion of internal slots. - // Some of these slots are best implemented as closure variables, such - // as the alreadySettled variable in createResolvingFunctions, which - // corresponds to the resolve.[[AlreadyResolved]].value property in the - // specification. Other slots are best implemented as properties of a - // slots object attached to the host object by a pseudo-private - // property. The latter kind of slots may be accessed by passing the - // host object (such as a Promise or a resolve/reject function object) - // to the slots function; e.g., the slots(promise).state slot, which - // corresponds to promise.[[PromiseState]] in the specification. - var slotsKey = '__slots$' + Math.random().toString(36).slice(2); - function slots(obj) { - var result = obj[slotsKey]; - if (!result) { - // In ES5+ environments, this property will be safely non-writable, - // non-configurable, and non-enumerable. This implementation does - // not logically rely on those niceties, however, so this code works - // just fine in pre-ES5 environments, too. - obj[slotsKey] = result = {}; - if (Object.defineProperty) try { - Object.defineProperty(obj, slotsKey, { value: result }); - } catch (definePropertyIsBrokenInIE8) {} - } - return result; - } - - // Reusable callback functions. The identify function is the default - // when onFulfilled is undefined or null, and the raise function is the - // default when onRejected is undefined or null. - function identity(x) { return x; } - function raise(x) { throw x; } - - /** - * When the Promise function is called with argument executor, the - * following steps are taken: - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise - * - * The executor argument must be a function object. It is called for - * initiating and reporting completion of the possibly deferred action - * represented by this Promise object. The executor is called with two - * arguments: resolve and reject. These are functions that may be used - * by the executor function to report eventual completion or failure of - * the deferred computation. Returning from the executor function does - * not mean that the deferred action has been completed, but only that - * the request to eventually perform the deferred action has been - * accepted. - * - * The resolve function that is passed to an executor function accepts a - * single argument. The executor code may eventually call the resolve - * function to indicate that it wishes to resolve the associated Promise - * object. The argument passed to the resolve function represents the - * eventual value of the deferred action and can be either the actual - * fulfillment value or another Promise object which will provide the - * value if it is fullfilled. - * - * The reject function that is passed to an executor function accepts a - * single argument. The executor code may eventually call the reject - * function to indicate that the associated Promise is rejected and will - * never be fulfilled. The argument passed to the reject function is - * used as the rejection value of the promise. Typically it will be an - * Error object. - * - * When Promise is called as a function rather than as a constructor, it - * initializes its this value with the internal state necessary to - * support the Promise.prototype methods. - * - * The Promise constructor is designed to be subclassable. It may be - * used as the value in an extends clause of a class - * definition. Subclass constructors that intend to inherit the - * specified Promise behaviour must include a super call to Promise, - * e.g. by invoking Promise.call(this, executor). - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-constructor - */ - function Promise(executor) { - var promiseSlots = slots(this); - promiseSlots.state = PENDING_STATE; - promiseSlots.fulfillReactions = []; - promiseSlots.rejectReactions = []; - - var resolvingFunctions = createResolvingFunctions(this); - var reject = resolvingFunctions.reject; - - try { - executor(resolvingFunctions.resolve, reject); - } catch (err) { - reject(err); - } - } - - function createResolvingFunctions(promise) { - var alreadySettled = false; - - return { - resolve: function(resolution) { - if (!alreadySettled) { - alreadySettled = true; - - if (resolution === promise) { - return settlePromise( - promise, - REJECTED_STATE, - new TypeError('Cannot resolve promise with itself') - ); - } - - // To be treated as a Promise-like object, the resolution only - // needs to be an object with a callable .then method. - if (!resolution || - typeof resolution !== "object" || - typeof resolution.then !== "function") { - return settlePromise(promise, FULFILLED_STATE, resolution); - } - - var resolvingFunctions = createResolvingFunctions(promise); - var reject = resolvingFunctions.reject; - - try { - resolution.then(resolvingFunctions.resolve, reject); - } catch (err) { - reject(err); - } - } - }, - - reject: function(reason) { - if (!alreadySettled) { - alreadySettled = true; - settlePromise(promise, REJECTED_STATE, reason); - } - } - }; - } - - // This function unifies the FulfillPromise and RejectPromise functions - // defined in the ES6 specification. - function settlePromise(promise, state, result) { - var promiseSlots = slots(promise); - if (promiseSlots.state !== PENDING_STATE) { - throw new Error('Settling a ' + promiseSlots.state + ' promise'); - } - - var reactions; - if (state === FULFILLED_STATE) { - reactions = promiseSlots.fulfillReactions; - } else if (state === REJECTED_STATE) { - reactions = promiseSlots.rejectReactions; - } - - promiseSlots.result = result; - promiseSlots.fulfillReactions = undefined; - promiseSlots.rejectReactions = undefined; - promiseSlots.state = state; - - var count = reactions.length; - count && setImmediate(function() { - for (var i = 0; i < count; ++i) { - reactions[i](promiseSlots.result); - } - }); - } - - /** - * The Promise.all function returns a new promise which is fulfilled - * with an array of fulfillment values for the passed promises, or - * rejects with the reason of the first passed promise that rejects. It - * resoves all elements of the passed iterable to promises as it runs - * this algorithm. - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.all - */ - Promise.all = function(array) { - var Promise = this; - return new Promise(function(resolve, reject) { - var results = []; - var remaining = 0; - array.forEach(function(element, index) { - ++remaining; // Array might be sparse. - Promise.resolve(element).then(function(result) { - if (!results.hasOwnProperty(index)) { - results[index] = result; - --remaining || resolve(results); - } - }, reject); - }); - remaining || resolve(results); - }); - }; - - /** - * The Promise.race function returns a new promise which is settled in - * the same way as the first passed promise to settle. It resolves all - * elements of the passed iterable to promises as it runs this - * algorithm. - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.race - */ - Promise.race = function(array) { - var Promise = this; - return new Promise(function(resolve, reject) { - array.forEach(function(element) { - Promise.resolve(element).then(resolve, reject); - }); - }); - }; - - /** - * The Promise.resolve function returns either a new promise resolved - * with the passed argument, or the argument itself if the argument a - * promise produced by this construtor. - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.resolve - */ - Promise.resolve = function(x) { - return x instanceof Promise && x.constructor === this - ? x // Refuse to create promises for promises. - : new this(function(resolve) { resolve(x); }); - }; - - /** - * The Promise.reject function returns a new promise rejected with the - * passed argument. - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.reject - */ - Promise.reject = function(r) { - return new this(function(_, reject) { reject(r); }); - }; - - var Pp = Promise.prototype; - - /** - * When the .then method is called with arguments onFulfilled and - * onRejected, the following steps are taken: - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.prototype.then - */ - Pp.then = function(onFulfilled, onRejected) { - var capabilityResolve; - var capabilityReject; - var capabilityPromise = new this.constructor(function(resolve, reject) { - capabilityResolve = resolve; - capabilityReject = reject; - }); - - if (typeof capabilityResolve !== "function") { - throw new TypeError('Uncallable Promise resolve function'); - } - - if (typeof capabilityReject !== "function") { - throw new TypeError('Uncallable Promise reject function'); - } - - if (onFulfilled === undefined || onFulfilled === null) { - onFulfilled = identity; - } - - if (onRejected === undefined || onRejected === null) { - onRejected = raise; - } - - var promiseSlots = slots(this); - var state = promiseSlots.state; - if (state === PENDING_STATE) { - promiseSlots.fulfillReactions.push(makeReaction( - capabilityResolve, - capabilityReject, - onFulfilled - )); - - promiseSlots.rejectReactions.push(makeReaction( - capabilityResolve, - capabilityReject, - onRejected - )); - - } else if (state === FULFILLED_STATE || state === REJECTED_STATE) { - setImmediate(makeReaction( - capabilityResolve, - capabilityReject, - state === FULFILLED_STATE ? onFulfilled : onRejected, - promiseSlots.result - )); - } - - return capabilityPromise; - }; - - function makeReaction(resolve, reject, handler, argument) { - var hasArgument = arguments.length > 3; - return function(result) { - try { - result = handler(hasArgument ? argument : result); - } catch (err) { - reject(err); - return; - } - resolve(result); - }; - } - - /** - * When the .catch method is called with argument onRejected, the - * following steps are taken: - * - * people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.prototype.catch - */ - Pp['catch'] = function(onRejected) { - return this.then(undefined, onRejected); - }; - - Pp.toString = function() { - return '[object Promise]'; - }; - - return Promise; -}(/* jslint evil: true */ Function('return this')())); diff --git a/Libraries/vendor/core/Map.js b/Libraries/vendor/core/Map.js deleted file mode 100644 index 114add77b30..00000000000 --- a/Libraries/vendor/core/Map.js +++ /dev/null @@ -1,626 +0,0 @@ -/** - * @generated SignedSource<<375749f44ce7c0f681fc1297943eaf74>> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright 2013-2014 Facebook, Inc. - * @providesModule Map - * @preventMunge - * @typechecks - */ - -var guid = require('guid'); -var isNode = require('isNode'); -var toIterator = require('toIterator'); -var _shouldPolyfillES6Collection = require('_shouldPolyfillES6Collection'); - -module.exports = (function(global, undefined) { - // Since our implementation is spec-compliant for the most part we can safely - // delegate to a built-in version if exists and is implemented correctly. - // Firefox had gotten a few implementation details wrong across different - // versions so we guard against that. - if (!_shouldPolyfillES6Collection('Map')) { - return global.Map; - } - - /** - * == ES6 Map Collection == - * - * This module is meant to implement a Map collection as described in chapter - * 23.1 of the ES6 specification. - * - * Map objects are collections of key/value pairs where both the keys and - * values may be arbitrary ECMAScript language values. A distinct key value - * may only occur in one key/value pair within the Map's collection. - * - * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-objects - * - * There only two -- rather small -- diviations from the spec: - * - * 1. The use of frozen objects as keys. - * We decided not to allow and simply throw an error. The reason being is - * we store a "hash" on the object for fast access to it's place in the - * internal map entries. - * If this turns out to be a popular use case it's possible to implement by - * overiding `Object.freeze` to store a "hash" property on the object - * for later use with the map. - * - * 2. The `size` property on a map object is a regular property and not a - * computed property on the prototype as described by the spec. - * The reason being is that we simply want to support ES3 environments - * which doesn't implement computed properties. - * - * == Usage == - * - * var map = new Map(iterable); - * - * map.set(key, value); - * map.get(key); // value - * map.has(key); // true - * map.delete(key); // true - * - * var iterator = map.keys(); - * iterator.next(); // {value: key, done: false} - * - * var iterator = map.values(); - * iterator.next(); // {value: value, done: false} - * - * var iterator = map.entries(); - * iterator.next(); // {value: [key, value], done: false} - * - * map.forEach(function(value, key){ this === thisArg }, thisArg); - * - * map.clear(); // resets map. - */ - - /** - * Constants - */ - - // Kinds of map iterations 23.1.5.3 - var KIND_KEY = 'key'; - var KIND_VALUE = 'value'; - var KIND_KEY_VALUE = 'key+value'; - - // In older browsers we can't create a null-prototype object so we have to - // defend against key collisions with built-in methods. - var KEY_PREFIX = '$map_'; - - // This property will be used as the internal size variable to disallow - // writing and to issue warnings for writings in development. - var SECRET_SIZE_PROP; - if (__DEV__) { - SECRET_SIZE_PROP = '$size' + guid(); - } - - // In oldIE we use the DOM Node `uniqueID` property to get create the hash. - var OLD_IE_HASH_PREFIX = 'IE_HASH_'; - - class Map { - - /** - * 23.1.1.1 - * Takes an `iterable` which is basically any object that implements a - * Symbol.iterator (@@iterator) method. The iterable is expected to be a - * collection of pairs. Each pair is a key/value pair that will be used - * to instantiate the map. - * - * @param {*} iterable - */ - constructor(iterable) { - if (!isObject(this)) { - throw new TypeError('Wrong map object type.'); - } - - initMap(this); - - if (iterable != null) { - var it = toIterator(iterable); - var next; - while (!(next = it.next()).done) { - if (!isObject(next.value)) { - throw new TypeError('Expected iterable items to be pair objects.'); - } - this.set(next.value[0], next.value[1]); - } - } - } - - /** - * 23.1.3.1 - * Clears the map from all keys and values. - */ - clear() { - initMap(this); - } - - /** - * 23.1.3.7 - * Check if a key exists in the collection. - * - * @param {*} key - * @return {boolean} - */ - has(key) { - var index = getIndex(this, key); - return !!(index != null && this._mapData[index]); - } - - /** - * 23.1.3.9 - * Adds a key/value pair to the collection. - * - * @param {*} key - * @param {*} value - * @return {map} - */ - set(key, value) { - var index = getIndex(this, key); - - if (index != null && this._mapData[index]) { - this._mapData[index][1] = value; - } else { - index = this._mapData.push([ - key, - value - ]) - 1; - setIndex(this, key, index); - if (__DEV__) { - this[SECRET_SIZE_PROP] += 1; - } else { - this.size += 1; - } - } - - return this; - } - - /** - * 23.1.3.6 - * Gets a value associated with a key in the collection. - * - * @param {*} key - * @return {*} - */ - get(key) { - var index = getIndex(this, key); - if (index == null) { - return undefined; - } else { - return this._mapData[index][1]; - } - } - - - /** - * 23.1.3.3 - * Delete a key/value from the collection. - * - * @param {*} key - * @return {boolean} Whether the key was found and deleted. - */ - delete(key) { - var index = getIndex(this, key); - if (index != null && this._mapData[index]) { - setIndex(this, key, undefined); - this._mapData[index] = undefined; - if (__DEV__) { - this[SECRET_SIZE_PROP] -= 1; - } else { - this.size -= 1; - } - return true; - } else { - return false; - } - } - - /** - * 23.1.3.4 - * Returns an iterator over the key/value pairs (in the form of an Array) in - * the collection. - * - * @return {MapIterator} - */ - entries() { - return new MapIterator(this, KIND_KEY_VALUE); - } - - /** - * 23.1.3.8 - * Returns an iterator over the keys in the collection. - * - * @return {MapIterator} - */ - keys() { - return new MapIterator(this, KIND_KEY); - } - - /** - * 23.1.3.11 - * Returns an iterator over the values pairs in the collection. - * - * @return {MapIterator} - */ - values() { - return new MapIterator(this, KIND_VALUE); - } - - /** - * 23.1.3.5 - * Iterates over the key/value pairs in the collection calling `callback` - * with [value, key, map]. An optional `thisArg` can be passed to set the - * context when `callback` is called. - * - * @param {function} callback - * @param {?object} thisArg - */ - forEach(callback, thisArg) { - if (typeof callback !== 'function') { - throw new TypeError('Callback must be callable.'); - } - - var boundCallback = callback.bind(thisArg || undefined); - var mapData = this._mapData; - - // Note that `mapData.length` should be computed on each iteration to - // support iterating over new items in the map that were added after the - // start of the iteration. - for (var i = 0; i < mapData.length; i++) { - var entry = mapData[i]; - if (entry != null) { - boundCallback(entry[1], entry[0], this); - } - } - } - } - - // 23.1.3.12 - Map.prototype[toIterator.ITERATOR_SYMBOL] = Map.prototype.entries; - - class MapIterator { - - /** - * 23.1.5.1 - * Create a `MapIterator` for a given `map`. While this class is private it - * will create objects that will be passed around publicily. - * - * @param {map} map - * @param {string} kind - */ - constructor(map, kind) { - if (!(isObject(map) && map['_mapData'])) { - throw new TypeError('Object is not a map.'); - } - - if ([KIND_KEY, KIND_KEY_VALUE, KIND_VALUE].indexOf(kind) === -1) { - throw new Error('Invalid iteration kind.'); - } - - this._map = map; - this._nextIndex = 0; - this._kind = kind; - } - - /** - * 23.1.5.2.1 - * Get the next iteration. - * - * @return {object} - */ - next() { - if (!this instanceof Map) { - throw new TypeError('Expected to be called on a MapIterator.'); - } - - var map = this._map; - var index = this._nextIndex; - var kind = this._kind; - - if (map == null) { - return createIterResultObject(undefined, true); - } - - var entries = map['_mapData']; - - while (index < entries.length) { - var record = entries[index]; - - index += 1; - this._nextIndex = index; - - if (record) { - if (kind === KIND_KEY) { - return createIterResultObject(record[0], false); - } else if (kind === KIND_VALUE) { - return createIterResultObject(record[1], false); - } else if (kind) { - return createIterResultObject(record, false); - } - } - } - - this._map = undefined; - - return createIterResultObject(undefined, true); - } - } - - // We can put this in the class definition once we have computed props - // transform. - // 23.1.5.2.2 - MapIterator.prototype[toIterator.ITERATOR_SYMBOL] = function() { - return this; - } - - /** - * Helper Functions. - */ - - /** - * Return an index to map.[[MapData]] array for a given Key. - * - * @param {map} map - * @param {*} key - * @return {?number} - */ - function getIndex(map, key) { - if (isObject(key)) { - var hash = getHash(key); - return map._objectIndex[hash]; - } else { - var prefixedKey = KEY_PREFIX + key; - if (typeof key === 'string') { - return map._stringIndex[prefixedKey]; - } else { - return map._otherIndex[prefixedKey]; - } - } - } - - /** - * Setup an index that refer to the key's location in map.[[MapData]]. - * - * @param {map} map - * @param {*} key - */ - function setIndex(map, key, index) { - var shouldDelete = index == null; - - if (isObject(key)) { - var hash = getHash(key); - if (shouldDelete) { - delete map._objectIndex[hash]; - } else { - map._objectIndex[hash] = index; - } - } else { - var prefixedKey = KEY_PREFIX + key; - if (typeof key === 'string') { - if (shouldDelete) { - delete map._stringIndex[prefixedKey]; - } else { - map._stringIndex[prefixedKey] = index; - } - } else { - if (shouldDelete) { - delete map._otherIndex[prefixedKey]; - } else { - map._otherIndex[prefixedKey] = index; - } - } - } - } - - /** - * Instantiate a map with internal slots. - * - * @param {map} map - */ - function initMap(map) { - // Data structure design inspired by Traceur's Map implementation. - // We maintain an internal array for all the entries. The array is needed - // to remember order. However, to have a reasonable HashMap performance - // i.e. O(1) for insertion, deletion, and retrieval. We maintain indices - // in objects for fast look ups. Indices are split up according to data - // types to avoid collisions. - map._mapData = []; - - // Object index maps from an object "hash" to index. The hash being a unique - // property of our choosing that we associate with the object. Association - // is done by ways of keeping a non-enumerable property on the object. - // Ideally these would be `Object.create(null)` objects but since we're - // trying to support ES3 we'll have to gaurd against collisions using - // prefixes on the keys rather than rely on null prototype objects. - map._objectIndex = {}; - - // String index maps from strings to index. - map._stringIndex = {}; - - // Numbers, booleans, undefined, and null. - map._otherIndex = {}; - - // Unfortunately we have to support ES3 and cannot have `Map.prototype.size` - // be a getter method but just a regular method. The biggest problem with - // this is safety. Clients can change the size property easily and possibly - // without noticing (e.g. `if (map.size = 1) {..}` kind of typo). What we - // can do to mitigate use getters and setters in development to disallow - // and issue a warning for changing the `size` property. - if (__DEV__) { - if (isES5) { - // If the `SECRET_SIZE_PROP` property is already defined then we're not - // in the first call to `initMap` (e.g. coming from `map.clear()`) so - // all we need to do is reset the size without defining the properties. - if (map.hasOwnProperty(SECRET_SIZE_PROP)) { - map[SECRET_SIZE_PROP] = 0; - } else { - Object.defineProperty(map, SECRET_SIZE_PROP, { - value: 0, - writable: true - }); - Object.defineProperty(map, 'size', { - set: (v) => { - console.error( - 'PLEASE FIX ME: You are changing the map size property which ' + - 'should not be writable and will break in production.' - ); - throw new Error('The map size property is not writable.'); - }, - get: () => map[SECRET_SIZE_PROP] - }); - } - - // NOTE: Early return to implement immutable `.size` in DEV. - return; - } - } - - // This is a diviation from the spec. `size` should be a getter on - // `Map.prototype`. However, we have to support IE8. - map.size = 0; - } - - /** - * Check if something is an object. - * - * @param {*} o - * @return {boolean} - */ - function isObject(o) { - return o != null && (typeof o === 'object' || typeof o === 'function'); - } - - /** - * Create an iteration object. - * - * @param {*} value - * @param {boolean} done - * @return {object} - */ - function createIterResultObject(value, done) { - return {value, done}; - } - - // Are we in a legit ES5 environment. Spoiler alert: that doesn't include IE8. - var isES5 = (function() { - try { - Object.defineProperty({}, 'x', {}); - return true; - } catch(e) { - return false; - } - })(); - - /** - * Check if an object can be extended. - * - * @param {object|array|function|regexp} o - * @return {boolean} - */ - function isExtensible(o) { - if (!isES5) { - return true; - } else { - return Object.isExtensible(o); - } - } - - /** - * IE has a `uniqueID` set on every DOM node. So we construct the hash from - * this uniqueID to avoid memory leaks and the IE cloneNode bug where it - * clones properties in addition to the attributes. - * - * @param {object} node - * @return {?string} - */ - function getIENodeHash(node) { - var uniqueID; - switch (node.nodeType) { - case 1: // Element - uniqueID = node.uniqueID; - break; - case 9: // Document - uniqueID = node.documentElement.uniqueID; - break; - default: - return null; - } - - if (uniqueID) { - return OLD_IE_HASH_PREFIX + uniqueID; - } else { - return null; - } - } - - var getHash = (function() { - var propIsEnumerable = Object.prototype.propertyIsEnumerable; - var hashProperty = guid(); - var hashCounter = 0; - - /** - * Get the "hash" associated with an object. - * - * @param {object|array|function|regexp} o - * @return {number} - */ - return function getHash(o) { - if (o[hashProperty]) { - return o[hashProperty]; - } else if (!isES5 && - o.propertyIsEnumerable && - o.propertyIsEnumerable[hashProperty]) { - return o.propertyIsEnumerable[hashProperty]; - } else if (!isES5 && - isNode(o) && - getIENodeHash(o)) { - return getIENodeHash(o); - } else if (!isES5 && o[hashProperty]) { - return o[hashProperty]; - } - - if (isExtensible(o)) { - hashCounter += 1; - if (isES5) { - Object.defineProperty(o, hashProperty, { - enumerable: false, - writable: false, - configurable: false, - value: hashCounter - }); - } else if (o.propertyIsEnumerable) { - // Since we can't define a non-enumerable property on the object - // we'll hijack one of the less-used non-enumerable properties to - // save our hash on it. Addiotionally, since this is a function it - // will not show up in `JSON.stringify` which is what we want. - o.propertyIsEnumerable = function() { - return propIsEnumerable.apply(this, arguments); - }; - o.propertyIsEnumerable[hashProperty] = hashCounter; - } else if (isNode(o)) { - // At this point we couldn't get the IE `uniqueID` to use as a hash - // and we couldn't use a non-enumerable property to exploit the - // dontEnum bug so we simply add the `hashProperty` on the node - // itself. - o[hashProperty] = hashCounter; - } else { - throw new Error('Unable to set a non-enumerable property on object.'); - } - return hashCounter; - } else { - throw new Error('Non-extensible objects are not allowed as keys.'); - } - }; - })(); - - return Map; -})(/* jslint evil: true */ Function('return this')()); diff --git a/Libraries/vendor/core/Promise.js b/Libraries/vendor/core/Promise.js deleted file mode 100644 index 1593c0fd255..00000000000 --- a/Libraries/vendor/core/Promise.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @generated SignedSource<> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule Promise - * - * This module wraps and augments the minimally ES6-compliant Promise - * implementation provided by the ES6Promise module. - */ - -var Promise = require('ES6Promise'); -var Pp = Promise.prototype; - -var invariant = require('invariant'); -var setImmediate = require('setImmediate'); -var throwImmediate = require('throwImmediate'); - -/** - * Handle either fulfillment or rejection with the same callback. - */ -Pp.finally = function(onSettled) { - return this.then(onSettled, onSettled); -}; - -/** - * Throw any unhandled error in a separate tick of the event loop. - */ -Pp.done = function(onFulfilled, onRejected) { - this.then(onFulfilled, onRejected).then(null, throwImmediate); -}; - -/** - * This function takes an object with promises as keys and returns a promise. - * The returned promise is resolved when all promises from the object are - * resolved and gets rejected when the first promise is rejected. - * - * EXAMPLE: - * var promisedMuffin = Promise.allObject({ - * dough: promisedDough, - * frosting: promisedFrosting - * }).then(function(results) { - * return combine(results.dough, results.frosting); - * }); - */ -Promise.allObject = function(/*object*/ promises) { - // Throw instead of warn here to make sure people use this only with object. - invariant( - !Array.isArray(promises), - 'expected an object, got an array instead' - ); - - var keys = Object.keys(promises); - return Promise.all(keys.map(function(key) { - return promises[key]; - })).then(function(values) { - var answers = {}; - values.forEach(function(value, i) { - answers[keys[i]] = value; - }); - return answers; - }); -}; - -module.exports = Promise; diff --git a/Libraries/vendor/core/Set.js b/Libraries/vendor/core/Set.js deleted file mode 100644 index 3bd019aeaa0..00000000000 --- a/Libraries/vendor/core/Set.js +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @generated SignedSource<<1fe20877e83ba5d4d0ea68ab240df21c>> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright 2013-2014 Facebook, Inc. - * @providesModule Set - * @preventMunge - * @typechecks - */ - -var Map = require('Map'); -var toIterator = require('toIterator'); -var _shouldPolyfillES6Collection = require('_shouldPolyfillES6Collection'); - -module.exports = (function(global, undefined) { - // Since our implementation is spec-compliant for the most part we can safely - // delegate to a built-in version if exists and is implemented correctly. - // Firefox had gotten a few implementation details wrong across different - // versions so we guard against that. - // These checks are adapted from es6-shim https://fburl.com/34437854 - if (!_shouldPolyfillES6Collection('Set')) { - return global.Set; - } - - /** - * == ES6 Set Collection == - * - * This module is meant to implement a Set collection as described in chapter - * 23.2 of the ES6 specification. - * - * Set objects are collections of unique values. Where values can be any - * JavaScript value. - * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-objects - * - * There only two -- rather small -- diviations from the spec: - * - * 1. The use of frozen objects as keys. @see Map module for more on this. - * - * 2. The `size` property on a map object is a regular property and not a - * computed property on the prototype as described by the spec. - * The reason being is that we simply want to support ES3 environments - * which doesn't implement computed properties. - * - * == Usage == - * - * var set = new set(iterable); - * - * set.set(value); - * set.has(value); // true - * set.delete(value); // true - * - * var iterator = set.keys(); - * iterator.next(); // {value: value, done: false} - * - * var iterator = set.values(); - * iterator.next(); // {value: value, done: false} - * - * var iterator = set.entries(); - * iterator.next(); // {value: [value, value], done: false} - * - * set.forEach(function(value, value){ this === thisArg }, thisArg); - * - * set.clear(); // resets set. - */ - - class Set { - - /** - * 23.2.1.1 - * - * Takes an optional `iterable` (which is basically any object that - * implements a Symbol.iterator (@@iterator) method). That is a collection - * of values used to instantiate the set. - * - * @param {*} iterable - */ - constructor(iterable) { - if (this == null || - (typeof this !== 'object' && typeof this !== 'function')) { - throw new TypeError('Wrong set object type.'); - } - - initSet(this); - - if (iterable != null) { - var it = toIterator(iterable); - var next; - while (!(next = it.next()).done) { - this.add(next.value); - } - } - } - - /** - * 23.2.3.1 - * - * If it doesn't already exist in the collection a `value` is added. - * - * @param {*} value - * @return {set} - */ - add(value) { - this._map.set(value, value); - this.size = this._map.size; - return this; - } - - /** - * 23.2.3.2 - * - * Clears the set. - */ - clear() { - initSet(this); - } - - /** - * 23.2.3.4 - * - * Deletes a `value` from the collection if it exists. - * Returns true if the value was found and deleted and false otherwise. - * - * @param {*} value - * @return {boolean} - */ - delete(value) { - var ret = this._map.delete(value); - this.size = this._map.size; - return ret; - } - - /** - * 23.2.3.5 - * - * Returns an iterator over a collection of [value, value] tuples. - */ - entries() { - return this._map.entries(); - } - - /** - * 23.2.3.6 - * - * Iterate over the collection calling `callback` with (value, value, set). - * - * @param {function} callback - */ - forEach(callback) { - var thisArg = arguments[1]; - var it = this._map.keys(); - var next; - while (!(next = it.next()).done) { - callback.call(thisArg, next.value, next.value, this); - } - } - - /** - * 23.2.3.7 - * - * Iterate over the collection calling `callback` with (value, value, set). - * - * @param {*} value - * @return {boolean} - */ - has(value) { - return this._map.has(value); - } - - /** - * 23.2.3.7 - * - * Returns an iterator over the colleciton of values. - */ - values() { - return this._map.values(); - } - } - - // 23.2.3.11 - Set.prototype[toIterator.ITERATOR_SYMBOL] = Set.prototype.values; - - // 23.2.3.7 - Set.prototype.keys = Set.prototype.values; - - function initSet(set) { - set._map = new Map(); - set.size = set._map.size; - } - - return Set; -})(/* jslint evil: true */ Function('return this')()); diff --git a/Libraries/vendor/core/_shouldPolyfillES6Collection.js b/Libraries/vendor/core/_shouldPolyfillES6Collection.js deleted file mode 100644 index a96c001044f..00000000000 --- a/Libraries/vendor/core/_shouldPolyfillES6Collection.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @generated SignedSource<<6c1a82d2f5918f03f3f0e5825e1f32f3>> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright 2013-2014 Facebook, Inc. - * @providesModule _shouldPolyfillES6Collection - * @preventMunge - * @typechecks - */ - -/** - * Given a collection class name (Map or Set) return whether it's safe to use - * the native polyfill. - * - * @param {string} collectionName - */ -function shouldPolyfillES6Collection(collectionName) { - var Collection = global[collectionName]; - if (Collection == null) { - return true; - } - - var proto = Collection.prototype; - - // These checks are adapted from es6-shim https://fburl.com/34437854 - return Collection == null || - typeof Collection !== 'function' || - typeof proto.clear !== 'function' || - new Collection().size !== 0 || - typeof proto.keys !== 'function' || - typeof proto.forEach !== 'function' || - isCallableWithoutNew(Collection) || - !supportsSubclassing(Collection); -} - -/** - * Given a class can we subclass it? - * - * @param {function} Collection - */ -function supportsSubclassing(Collection) { - class SubCollection extends Collection {} - try { - var s = (new SubCollection([])); - // Firefox 32 will throw a type error when any operation is called on a - // subclass. - s.size; - return s instanceof Collection; - } catch (e) { - return false; - } -} - -/** - * Given a constructor can we call it without `new`? - * - * @param {function} Collection - */ -function isCallableWithoutNew(Collection) { - try { - Collection(); - } catch (e) { - return false; - } - return true; -} - -module.exports = shouldPolyfillES6Collection; diff --git a/Libraries/vendor/core/copyProperties.js b/Libraries/vendor/core/copyProperties.js deleted file mode 100644 index e5a2638d961..00000000000 --- a/Libraries/vendor/core/copyProperties.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @generated SignedSource<> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * @providesModule copyProperties - */ - -/** - * Copy properties from one or more objects (up to 5) into the first object. - * This is a shallow copy. It mutates the first object and also returns it. - * - * NOTE: `arguments` has a very significant performance penalty, which is why - * we don't support unlimited arguments. - */ -function copyProperties(obj, a, b, c, d, e, f) { - obj = obj || {}; - - if (__DEV__) { - if (f) { - throw new Error('Too many arguments passed to copyProperties'); - } - } - - var args = [a, b, c, d, e]; - var ii = 0, v; - while (args[ii]) { - v = args[ii++]; - for (var k in v) { - obj[k] = v[k]; - } - - // IE ignores toString in object iteration.. See: - // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html - if (v.hasOwnProperty && v.hasOwnProperty('toString') && - (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { - obj.toString = v.toString; - } - } - - return obj; -} - -module.exports = copyProperties; diff --git a/Libraries/vendor/core/getObjectValues.js b/Libraries/vendor/core/getObjectValues.js deleted file mode 100644 index a7c9448bd4b..00000000000 --- a/Libraries/vendor/core/getObjectValues.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @generated SignedSource<> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * @providesModule getObjectValues - * @typechecks - */ - -/** - * Retrieve an object's values as an array. - * - * If you are looking for a function that creates an Array instance based - * on an "Array-like" object, use createArrayFrom instead. - * - * @param {object} obj An object. - * @return {array} The object's values. - */ -function getObjectValues(obj) { - var values = []; - for (var key in obj) { - values.push(obj[key]); - } - return values; -} - -module.exports = getObjectValues; diff --git a/Libraries/vendor/core/guid.js b/Libraries/vendor/core/guid.js deleted file mode 100644 index 7f66e64da70..00000000000 --- a/Libraries/vendor/core/guid.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @generated SignedSource<<4425c6f5a34b56ee4707e090f43fd075>> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright 2004-present Facebook. All Rights Reserved. - * - * Module that provides a function for creating a unique identifier. - * The returned value does not conform to the GUID standard, but should - * be globally unique in the context of the browser. - * - * @providesModule guid - * - */ - -/*jshint bitwise: false*/ - -function guid() { - return 'f' + (Math.random() * (1 << 30)).toString(16).replace('.', ''); -} - -module.exports = guid; diff --git a/Libraries/vendor/core/immediate/setImmediate.js b/Libraries/vendor/core/immediate/setImmediate.js deleted file mode 100644 index 1040712aada..00000000000 --- a/Libraries/vendor/core/immediate/setImmediate.js +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @generated SignedSource<<57d0446bbd1186485d372efe6b323dca>> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in of a static_upstream project! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Use `fjs use-upstream` to temporarily replace this with !! - * !! the latest version from upstream. !! - * !! 2) Make your changes, test them, etc. !! - * !! 3) Use `fjs push-upstream` to copy your changes back to !! - * !! static_upstream. !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic - * Denicola - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * @preserve-header - * @providesModule ImmediateImplementation - */ - -(function(global, undefined) { - "use strict"; - - var nextHandle = 1; // Spec says greater than zero - var tasksByHandle = {}; - var queueHead = {}; - var queueTail = queueHead; - var currentlyRunningATask = false; - var doc = global.document; - var setImmediate; - - function addFromSetImmediateArguments(args) { - var handler = args[0]; - args = Array.prototype.slice.call(args, 1); - tasksByHandle[nextHandle] = function() { - handler.apply(undefined, args); - }; - queueTail = (queueTail.next = { handle: nextHandle++ }); - return queueTail.handle; - } - - function flushQueue() { - var next, task; - while (!currentlyRunningATask && (next = queueHead.next)) { - queueHead = next; // If this task fails, don't retry it. - if ((task = tasksByHandle[next.handle])) { - currentlyRunningATask = true; - try { - task(); - currentlyRunningATask = false; - } finally { - clearImmediate(next.handle); - if (currentlyRunningATask) { - currentlyRunningATask = false; - // The call to task() must have thrown an - // exception if we reach this point, so, just in - // case there are tasks remaining to be executed, - // we schedule another flushQueue in a later tick - // of the event loop, and let the exception - // propagate uncaught. - if (queueHead.next) { - setImmediate(flushQueue); - } - } - } - } - } - } - - function clearImmediate(handle) { - delete tasksByHandle[handle]; - } - - function canUsePostMessage() { - // The test against `importScripts` prevents this implementation from being installed inside a web worker, - // where `global.postMessage` means something completely different and can't be used for this purpose. - if (global.postMessage && !global.importScripts) { - var postMessageIsAsynchronous = true; - - var onMessage = function() { - postMessageIsAsynchronous = false; - if (global.removeEventListener) { - global.removeEventListener("message", onMessage, false); - } else { - global.detachEvent("onmessage", onMessage); - } - }; - - if (global.addEventListener) { - global.addEventListener("message", onMessage, false); - } else if (global.attachEvent) { - global.attachEvent("onmessage", onMessage); - } else { - return false; - } - - global.postMessage("", "*"); - return postMessageIsAsynchronous; - } - } - - function installPostMessageImplementation() { - // Installs an event handler on `global` for the `message` event: see - // * https://developer.mozilla.org/en/DOM/window.postMessage - var messagePrefix = "setImmediate$" + Math.random() + "$"; - var onGlobalMessage = function(event) { - if (event.source === global && - typeof event.data === "string" && - event.data.indexOf(messagePrefix) === 0) { - flushQueue(); - } - }; - - if (global.addEventListener) { - global.addEventListener("message", onGlobalMessage, false); - } else { - global.attachEvent("onmessage", onGlobalMessage); - } - - setImmediate = function() { - var handle = addFromSetImmediateArguments(arguments); - global.postMessage(messagePrefix + handle, "*"); - return handle; - }; - } - - function installMessageChannelImplementation() { - var channel = new MessageChannel(); - channel.port1.onmessage = flushQueue; - setImmediate = function() { - var handle = addFromSetImmediateArguments(arguments); - channel.port2.postMessage(handle); - return handle; - }; - } - - function installReadyStateChangeImplementation() { - var html = doc.documentElement; - setImmediate = function() { - var handle = addFromSetImmediateArguments(arguments); - // Create a ", - script - ]; - [_webView loadHTMLString:runScript baseURL:url]; -} - -/** - * In order to avoid `UIWebView` thread locks, all JS executions should be - * performed outside of the event loop that notifies the `UIWebViewDelegate` - * that the page has loaded. This is only an issue with the remote debug mode of - * `UIWebView`. For a production `UIWebView` deployment, this delay is - * unnecessary and possibly harmful (or helpful?) - * - * The delay might not be needed as soon as the following change lands into - * iOS7. (Review the patch linked here and search for "crash" - * https://bugs.webkit.org/show_bug.cgi?id=125746). - */ -- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block -{ - dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC); - - dispatch_after(when, dispatch_get_main_queue(), ^{ - RCTAssertMainThread(); - block(); - }); -} - -/** - * `UIWebViewDelegate` methods. Handle application script load. - */ -- (void)webViewDidFinishLoad:(UIWebView *)webView -{ - RCTAssertMainThread(); - if (_onApplicationScriptLoaded) { - _onApplicationScriptLoaded(nil); // TODO(frantic): how to fetch error from UIWebView? - } - _onApplicationScriptLoaded = nil; -} - -- (void)injectJSONText:(NSString *)script - asGlobalObjectNamed:(NSString *)objectName - callback:(RCTJavaScriptCompleteBlock)onComplete -{ - RCTAssert(!_objectsToInject[objectName], @"already injected object named %@", _objectsToInject[objectName]); - _objectsToInject[objectName] = script; - onComplete(nil); -} -@end diff --git a/ReactKit/Layout/Layout.c b/ReactKit/Layout/Layout.c deleted file mode 100644 index 21dec570ac3..00000000000 --- a/ReactKit/Layout/Layout.c +++ /dev/null @@ -1,817 +0,0 @@ -/** - * @generated SignedSource<> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in from github! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Go to https://github.com/facebook/css-layout !! - * !! 2) Make a pull request and get it merged !! - * !! 3) Execute ./import.sh to pull in the latest version !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright (c) 2014, 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. - */ - -#include -#include -#include -#include -#include - -#include "Layout.h" - -bool isUndefined(float value) { - return isnan(value); -} - -static bool eq(float a, float b) { - if (isUndefined(a)) { - return isUndefined(b); - } - return fabs(a - b) < 0.0001; -} - -void init_css_node(css_node_t *node) { - node->style.align_items = CSS_ALIGN_STRETCH; - - // Some of the fields default to undefined and not 0 - node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; - - node->style.position[CSS_LEFT] = CSS_UNDEFINED; - node->style.position[CSS_TOP] = CSS_UNDEFINED; - node->style.position[CSS_RIGHT] = CSS_UNDEFINED; - node->style.position[CSS_BOTTOM] = CSS_UNDEFINED; - - node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; - - // Such that the comparison is always going to be false - node->layout.last_requested_dimensions[CSS_WIDTH] = -1; - node->layout.last_requested_dimensions[CSS_HEIGHT] = -1; - node->layout.last_parent_max_width = -1; - node->layout.should_update = true; -} - -css_node_t *new_css_node() { - css_node_t *node = calloc(1, sizeof(*node)); - init_css_node(node); - return node; -} - -void free_css_node(css_node_t *node) { - free(node); -} - -static void indent(int n) { - for (int i = 0; i < n; ++i) { - printf(" "); - } -} - -static void print_number_0(const char *str, float number) { - if (!eq(number, 0)) { - printf("%s: %g, ", str, number); - } -} - -static void print_number_nan(const char *str, float number) { - if (!isnan(number)) { - printf("%s: %g, ", str, number); - } -} - -static bool four_equal(float four[4]) { - return - eq(four[0], four[1]) && - eq(four[0], four[2]) && - eq(four[0], four[3]); -} - - -static void print_css_node_rec( - css_node_t *node, - css_print_options_t options, - int level -) { - indent(level); - printf("{"); - - if (node->print) { - node->print(node->context); - } - - if (options & CSS_PRINT_LAYOUT) { - printf("layout: {"); - printf("width: %g, ", node->layout.dimensions[CSS_WIDTH]); - printf("height: %g, ", node->layout.dimensions[CSS_HEIGHT]); - printf("top: %g, ", node->layout.position[CSS_TOP]); - printf("left: %g", node->layout.position[CSS_LEFT]); - printf("}, "); - } - - if (options & CSS_PRINT_STYLE) { - if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) { - printf("flexDirection: 'row', "); - } - - if (node->style.justify_content == CSS_JUSTIFY_CENTER) { - printf("justifyContent: 'center', "); - } else if (node->style.justify_content == CSS_JUSTIFY_FLEX_END) { - printf("justifyContent: 'flex-end', "); - } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_AROUND) { - printf("justifyContent: 'space-around', "); - } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_BETWEEN) { - printf("justifyContent: 'space-between', "); - } - - if (node->style.align_items == CSS_ALIGN_CENTER) { - printf("alignItems: 'center', "); - } else if (node->style.align_items == CSS_ALIGN_FLEX_END) { - printf("alignItems: 'flex-end', "); - } else if (node->style.align_items == CSS_ALIGN_STRETCH) { - printf("alignItems: 'stretch', "); - } - - if (node->style.align_self == CSS_ALIGN_FLEX_START) { - printf("alignSelf: 'flex-start', "); - } else if (node->style.align_self == CSS_ALIGN_CENTER) { - printf("alignSelf: 'center', "); - } else if (node->style.align_self == CSS_ALIGN_FLEX_END) { - printf("alignSelf: 'flex-end', "); - } else if (node->style.align_self == CSS_ALIGN_STRETCH) { - printf("alignSelf: 'stretch', "); - } - - print_number_nan("flex", node->style.flex); - - if (four_equal(node->style.margin)) { - print_number_0("margin", node->style.margin[CSS_LEFT]); - } else { - print_number_0("marginLeft", node->style.margin[CSS_LEFT]); - print_number_0("marginRight", node->style.margin[CSS_RIGHT]); - print_number_0("marginTop", node->style.margin[CSS_TOP]); - print_number_0("marginBottom", node->style.margin[CSS_BOTTOM]); - } - - if (four_equal(node->style.padding)) { - print_number_0("padding", node->style.margin[CSS_LEFT]); - } else { - print_number_0("paddingLeft", node->style.padding[CSS_LEFT]); - print_number_0("paddingRight", node->style.padding[CSS_RIGHT]); - print_number_0("paddingTop", node->style.padding[CSS_TOP]); - print_number_0("paddingBottom", node->style.padding[CSS_BOTTOM]); - } - - if (four_equal(node->style.border)) { - print_number_0("borderWidth", node->style.border[CSS_LEFT]); - } else { - print_number_0("borderLeftWidth", node->style.border[CSS_LEFT]); - print_number_0("borderRightWidth", node->style.border[CSS_RIGHT]); - print_number_0("borderTopWidth", node->style.border[CSS_TOP]); - print_number_0("borderBottomWidth", node->style.border[CSS_BOTTOM]); - } - - print_number_nan("width", node->style.dimensions[CSS_WIDTH]); - print_number_nan("height", node->style.dimensions[CSS_HEIGHT]); - - if (node->style.position_type == CSS_POSITION_ABSOLUTE) { - printf("position: 'absolute', "); - } - - print_number_nan("left", node->style.position[CSS_LEFT]); - print_number_nan("right", node->style.position[CSS_RIGHT]); - print_number_nan("top", node->style.position[CSS_TOP]); - print_number_nan("bottom", node->style.position[CSS_BOTTOM]); - } - - if (options & CSS_PRINT_CHILDREN && node->children_count > 0) { - printf("children: [\n"); - for (int i = 0; i < node->children_count; ++i) { - print_css_node_rec(node->get_child(node->context, i), options, level + 1); - } - indent(level); - printf("]},\n"); - } else { - printf("},\n"); - } -} - -void print_css_node(css_node_t *node, css_print_options_t options) { - print_css_node_rec(node, options, 0); -} - - -static css_position_t leading[2] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT -}; -static css_position_t trailing[2] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT -}; -static css_position_t pos[2] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT -}; -static css_dimension_t dim[2] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH -}; - - - -static float getMargin(css_node_t *node, int location) { - return node->style.margin[location]; -} - -static float getPadding(css_node_t *node, int location) { - if (node->style.padding[location] >= 0) { - return node->style.padding[location]; - } - return 0; -} - -static float getBorder(css_node_t *node, int location) { - if (node->style.border[location] >= 0) { - return node->style.border[location]; - } - return 0; -} - -static float getPaddingAndBorder(css_node_t *node, int location) { - return getPadding(node, location) + getBorder(node, location); -} - -static float getMarginAxis(css_node_t *node, css_flex_direction_t axis) { - return getMargin(node, leading[axis]) + getMargin(node, trailing[axis]); -} - -static float getPaddingAndBorderAxis(css_node_t *node, css_flex_direction_t axis) { - return getPaddingAndBorder(node, leading[axis]) + getPaddingAndBorder(node, trailing[axis]); -} - -static css_position_type_t getPositionType(css_node_t *node) { - return node->style.position_type; -} - -static css_justify_t getJustifyContent(css_node_t *node) { - return node->style.justify_content; -} - -static css_align_t getAlignItem(css_node_t *node, css_node_t *child) { - if (child->style.align_self != CSS_ALIGN_AUTO) { - return child->style.align_self; - } - return node->style.align_items; -} - -static css_flex_direction_t getFlexDirection(css_node_t *node) { - return node->style.flex_direction; -} - -static float getFlex(css_node_t *node) { - return node->style.flex; -} - -static bool isFlex(css_node_t *node) { - return ( - getPositionType(node) == CSS_POSITION_RELATIVE && - getFlex(node) > 0 - ); -} - -static bool isFlexWrap(css_node_t *node) { - return node->style.flex_wrap == CSS_WRAP; -} - -static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) { - return node->layout.dimensions[dim[axis]] + - getMargin(node, leading[axis]) + - getMargin(node, trailing[axis]); -} - -static bool isDimDefined(css_node_t *node, css_flex_direction_t axis) { - return !isUndefined(node->style.dimensions[dim[axis]]); -} - -static bool isPosDefined(css_node_t *node, css_position_t position) { - return !isUndefined(node->style.position[position]); -} - -static bool isMeasureDefined(css_node_t *node) { - return node->measure; -} - -static float getPosition(css_node_t *node, css_position_t position) { - float result = node->style.position[position]; - if (!isUndefined(result)) { - return result; - } - return 0; -} - -// When the user specifically sets a value for width or height -static void setDimensionFromStyle(css_node_t *node, css_flex_direction_t axis) { - // The parent already computed us a width or height. We just skip it - if (!isUndefined(node->layout.dimensions[dim[axis]])) { - return; - } - // We only run if there's a width or height defined - if (!isDimDefined(node, axis)) { - return; - } - - // The dimensions can never be smaller than the padding and border - node->layout.dimensions[dim[axis]] = fmaxf( - node->style.dimensions[dim[axis]], - getPaddingAndBorderAxis(node, axis) - ); -} - -// If both left and right are defined, then use left. Otherwise return -// +left or -right depending on which is defined. -static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) { - float lead = node->style.position[leading[axis]]; - if (!isUndefined(lead)) { - return lead; - } - return -getPosition(node, trailing[axis]); -} - -static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) { - /** START_GENERATED **/ - css_flex_direction_t mainAxis = getFlexDirection(node); - css_flex_direction_t crossAxis = mainAxis == CSS_FLEX_DIRECTION_ROW ? - CSS_FLEX_DIRECTION_COLUMN : - CSS_FLEX_DIRECTION_ROW; - - // Handle width and height style attributes - setDimensionFromStyle(node, mainAxis); - setDimensionFromStyle(node, crossAxis); - - // The position is set by the parent, but we need to complete it with a - // delta composed of the margin and left/top/right/bottom - node->layout.position[leading[mainAxis]] += getMargin(node, leading[mainAxis]) + - getRelativePosition(node, mainAxis); - node->layout.position[leading[crossAxis]] += getMargin(node, leading[crossAxis]) + - getRelativePosition(node, crossAxis); - - if (isMeasureDefined(node)) { - float width = CSS_UNDEFINED; - if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) { - width = node->style.dimensions[CSS_WIDTH]; - } else if (!isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]])) { - width = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]]; - } else { - width = parentMaxWidth - - getMarginAxis(node, CSS_FLEX_DIRECTION_ROW); - } - width -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - - // We only need to give a dimension for the text if we haven't got any - // for it computed yet. It can either be from the style attribute or because - // the element is flexible. - bool isRowUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_ROW) && - isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]]); - bool isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && - isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]); - - // Let's not measure the text if we already know both dimensions - if (isRowUndefined || isColumnUndefined) { - css_dim_t measure_dim = node->measure( - node->context, - width - ); - if (isRowUndefined) { - node->layout.dimensions[CSS_WIDTH] = measure_dim.dimensions[CSS_WIDTH] + - getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - } - if (isColumnUndefined) { - node->layout.dimensions[CSS_HEIGHT] = measure_dim.dimensions[CSS_HEIGHT] + - getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); - } - } - return; - } - - // Pre-fill some dimensions straight from the parent - for (int i = 0; i < node->children_count; ++i) { - css_node_t* child = node->get_child(node->context, i); - // Pre-fill cross axis dimensions when the child is using stretch before - // we call the recursive layout pass - if (getAlignItem(node, child) == CSS_ALIGN_STRETCH && - getPositionType(child) == CSS_POSITION_RELATIVE && - !isUndefined(node->layout.dimensions[dim[crossAxis]]) && - !isDimDefined(child, crossAxis)) { - child->layout.dimensions[dim[crossAxis]] = fmaxf( - node->layout.dimensions[dim[crossAxis]] - - getPaddingAndBorderAxis(node, crossAxis) - - getMarginAxis(child, crossAxis), - // You never want to go smaller than padding - getPaddingAndBorderAxis(child, crossAxis) - ); - } else if (getPositionType(child) == CSS_POSITION_ABSOLUTE) { - // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both - // left and right or top and bottom). - for (int ii = 0; ii < 2; ii++) { - css_flex_direction_t axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (!isUndefined(node->layout.dimensions[dim[axis]]) && - !isDimDefined(child, axis) && - isPosDefined(child, leading[axis]) && - isPosDefined(child, trailing[axis])) { - child->layout.dimensions[dim[axis]] = fmaxf( - node->layout.dimensions[dim[axis]] - - getPaddingAndBorderAxis(node, axis) - - getMarginAxis(child, axis) - - getPosition(child, leading[axis]) - - getPosition(child, trailing[axis]), - // You never want to go smaller than padding - getPaddingAndBorderAxis(child, axis) - ); - } - } - } - } - - float definedMainDim = CSS_UNDEFINED; - if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) { - definedMainDim = node->layout.dimensions[dim[mainAxis]] - - getPaddingAndBorderAxis(node, mainAxis); - } - - // We want to execute the next two loops one per line with flex-wrap - int startLine = 0; - int endLine = 0; - int nextLine = 0; - // We aggregate the total dimensions of the container in those two variables - float linesCrossDim = 0; - float linesMainDim = 0; - while (endLine != node->children_count) { - // Layout non flexible children and count children by type - - // mainContentDim is accumulation of the dimensions and margin of all the - // non flexible children. This will be used in order to either set the - // dimensions of the node if none already exist, or to compute the - // remaining space left for the flexible children. - float mainContentDim = 0; - - // There are three kind of children, non flexible, flexible and absolute. - // We need to know how many there are in order to distribute the space. - int flexibleChildrenCount = 0; - float totalFlexible = 0; - int nonFlexibleChildrenCount = 0; - for (int i = startLine; i < node->children_count; ++i) { - css_node_t* child = node->get_child(node->context, i); - float nextContentDim = 0; - - // It only makes sense to consider a child flexible if we have a computed - // dimension for the node-> - if (!isUndefined(node->layout.dimensions[dim[mainAxis]]) && isFlex(child)) { - flexibleChildrenCount++; - totalFlexible += getFlex(child); - - // Even if we don't know its exact size yet, we already know the padding, - // border and margin. We'll use this partial information to compute the - // remaining space. - nextContentDim = getPaddingAndBorderAxis(child, mainAxis) + - getMarginAxis(child, mainAxis); - - } else { - float maxWidth = CSS_UNDEFINED; - if (mainAxis == CSS_FLEX_DIRECTION_ROW) { - // do nothing - } else if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) { - maxWidth = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] - - getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - } else { - maxWidth = parentMaxWidth - - getMarginAxis(node, CSS_FLEX_DIRECTION_ROW) - - getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - } - - // This is the main recursive call. We layout non flexible children. - if (nextLine == 0) { - layoutNode(child, maxWidth); - } - - // Absolute positioned elements do not take part of the layout, so we - // don't use them to compute mainContentDim - if (getPositionType(child) == CSS_POSITION_RELATIVE) { - nonFlexibleChildrenCount++; - // At this point we know the final size and margin of the element. - nextContentDim = getDimWithMargin(child, mainAxis); - } - } - - // The element we are about to add would make us go to the next line - if (isFlexWrap(node) && - !isUndefined(node->layout.dimensions[dim[mainAxis]]) && - mainContentDim + nextContentDim > definedMainDim) { - nextLine = i + 1; - break; - } - nextLine = 0; - mainContentDim += nextContentDim; - endLine = i + 1; - } - - // Layout flexible children and allocate empty space - - // In order to position the elements in the main axis, we have two - // controls. The space between the beginning and the first element - // and the space between each two elements. - float leadingMainDim = 0; - float betweenMainDim = 0; - - // The remaining available space that needs to be allocated - float remainingMainDim = 0; - if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) { - remainingMainDim = definedMainDim - mainContentDim; - } else { - remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim; - } - - // If there are flexible children in the mix, they are going to fill the - // remaining space - if (flexibleChildrenCount != 0) { - float flexibleMainDim = remainingMainDim / totalFlexible; - - // The non flexible children can overflow the container, in this case - // we should just assume that there is no space available. - if (flexibleMainDim < 0) { - flexibleMainDim = 0; - } - // We iterate over the full array and only apply the action on flexible - // children. This is faster than actually allocating a new array that - // contains only flexible children. - for (int i = startLine; i < endLine; ++i) { - css_node_t* child = node->get_child(node->context, i); - if (isFlex(child)) { - // At this point we know the final size of the element in the main - // dimension - child->layout.dimensions[dim[mainAxis]] = flexibleMainDim * getFlex(child) + - getPaddingAndBorderAxis(child, mainAxis); - - float maxWidth = CSS_UNDEFINED; - if (mainAxis == CSS_FLEX_DIRECTION_ROW) { - // do nothing - } else if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) { - maxWidth = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] - - getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - } else { - maxWidth = parentMaxWidth - - getMarginAxis(node, CSS_FLEX_DIRECTION_ROW) - - getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - } - - // And we recursively call the layout algorithm for this child - layoutNode(child, maxWidth); - } - } - - // We use justifyContent to figure out how to allocate the remaining - // space available - } else { - css_justify_t justifyContent = getJustifyContent(node); - if (justifyContent == CSS_JUSTIFY_FLEX_START) { - // Do nothing - } else if (justifyContent == CSS_JUSTIFY_CENTER) { - leadingMainDim = remainingMainDim / 2; - } else if (justifyContent == CSS_JUSTIFY_FLEX_END) { - leadingMainDim = remainingMainDim; - } else if (justifyContent == CSS_JUSTIFY_SPACE_BETWEEN) { - remainingMainDim = fmaxf(remainingMainDim, 0); - if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 != 0) { - betweenMainDim = remainingMainDim / - (flexibleChildrenCount + nonFlexibleChildrenCount - 1); - } else { - betweenMainDim = 0; - } - } else if (justifyContent == CSS_JUSTIFY_SPACE_AROUND) { - // Space on the edges is half of the space between elements - betweenMainDim = remainingMainDim / - (flexibleChildrenCount + nonFlexibleChildrenCount); - leadingMainDim = betweenMainDim / 2; - } - } - - // Position elements in the main axis and compute dimensions - - // At this point, all the children have their dimensions set. We need to - // find their position. In order to do that, we accumulate data in - // variables that are also useful to compute the total dimensions of the - // container! - float crossDim = 0; - float mainDim = leadingMainDim + - getPaddingAndBorder(node, leading[mainAxis]); - - for (int i = startLine; i < endLine; ++i) { - css_node_t* child = node->get_child(node->context, i); - - if (getPositionType(child) == CSS_POSITION_ABSOLUTE && - isPosDefined(child, leading[mainAxis])) { - // In case the child is position absolute and has left/top being - // defined, we override the position to whatever the user said - // (and margin/border). - child->layout.position[pos[mainAxis]] = getPosition(child, leading[mainAxis]) + - getBorder(node, leading[mainAxis]) + - getMargin(child, leading[mainAxis]); - } else { - // If the child is position absolute (without top/left) or relative, - // we put it at the current accumulated offset. - child->layout.position[pos[mainAxis]] += mainDim; - } - - // Now that we placed the element, we need to update the variables - // We only need to do that for relative elements. Absolute elements - // do not take part in that phase. - if (getPositionType(child) == CSS_POSITION_RELATIVE) { - // The main dimension is the sum of all the elements dimension plus - // the spacing. - mainDim += betweenMainDim + getDimWithMargin(child, mainAxis); - // The cross dimension is the max of the elements dimension since there - // can only be one element in that cross dimension. - crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis)); - } - } - - float containerMainAxis = node->layout.dimensions[dim[mainAxis]]; - // If the user didn't specify a width or height, and it has not been set - // by the container, then we set it via the children. - if (isUndefined(node->layout.dimensions[dim[mainAxis]])) { - containerMainAxis = fmaxf( - // We're missing the last padding at this point to get the final - // dimension - mainDim + getPaddingAndBorder(node, trailing[mainAxis]), - // We can never assign a width smaller than the padding and borders - getPaddingAndBorderAxis(node, mainAxis) - ); - } - - float containerCrossAxis = node->layout.dimensions[dim[crossAxis]]; - if (isUndefined(node->layout.dimensions[dim[crossAxis]])) { - containerCrossAxis = fmaxf( - // For the cross dim, we add both sides at the end because the value - // is aggregate via a max function. Intermediate negative values - // can mess this computation otherwise - crossDim + getPaddingAndBorderAxis(node, crossAxis), - getPaddingAndBorderAxis(node, crossAxis) - ); - } - - // Position elements in the cross axis - - for (int i = startLine; i < endLine; ++i) { - css_node_t* child = node->get_child(node->context, i); - - if (getPositionType(child) == CSS_POSITION_ABSOLUTE && - isPosDefined(child, leading[crossAxis])) { - // In case the child is absolutely positionned and has a - // top/left/bottom/right being set, we override all the previously - // computed positions to set it correctly. - child->layout.position[pos[crossAxis]] = getPosition(child, leading[crossAxis]) + - getBorder(node, leading[crossAxis]) + - getMargin(child, leading[crossAxis]); - - } else { - float leadingCrossDim = getPaddingAndBorder(node, leading[crossAxis]); - - // For a relative children, we're either using alignItems (parent) or - // alignSelf (child) in order to determine the position in the cross axis - if (getPositionType(child) == CSS_POSITION_RELATIVE) { - css_align_t alignItem = getAlignItem(node, child); - if (alignItem == CSS_ALIGN_FLEX_START) { - // Do nothing - } else if (alignItem == CSS_ALIGN_STRETCH) { - // You can only stretch if the dimension has not already been set - // previously. - if (!isDimDefined(child, crossAxis)) { - child->layout.dimensions[dim[crossAxis]] = fmaxf( - containerCrossAxis - - getPaddingAndBorderAxis(node, crossAxis) - - getMarginAxis(child, crossAxis), - // You never want to go smaller than padding - getPaddingAndBorderAxis(child, crossAxis) - ); - } - } else { - // The remaining space between the parent dimensions+padding and child - // dimensions+margin. - float remainingCrossDim = containerCrossAxis - - getPaddingAndBorderAxis(node, crossAxis) - - getDimWithMargin(child, crossAxis); - - if (alignItem == CSS_ALIGN_CENTER) { - leadingCrossDim += remainingCrossDim / 2; - } else { // CSS_ALIGN_FLEX_END - leadingCrossDim += remainingCrossDim; - } - } - } - - // And we apply the position - child->layout.position[pos[crossAxis]] += linesCrossDim + leadingCrossDim; - } - } - - linesCrossDim += crossDim; - linesMainDim = fmaxf(linesMainDim, mainDim); - startLine = endLine; - } - - // If the user didn't specify a width or height, and it has not been set - // by the container, then we set it via the children. - if (isUndefined(node->layout.dimensions[dim[mainAxis]])) { - node->layout.dimensions[dim[mainAxis]] = fmaxf( - // We're missing the last padding at this point to get the final - // dimension - linesMainDim + getPaddingAndBorder(node, trailing[mainAxis]), - // We can never assign a width smaller than the padding and borders - getPaddingAndBorderAxis(node, mainAxis) - ); - } - - if (isUndefined(node->layout.dimensions[dim[crossAxis]])) { - node->layout.dimensions[dim[crossAxis]] = fmaxf( - // For the cross dim, we add both sides at the end because the value - // is aggregate via a max function. Intermediate negative values - // can mess this computation otherwise - linesCrossDim + getPaddingAndBorderAxis(node, crossAxis), - getPaddingAndBorderAxis(node, crossAxis) - ); - } - - // Calculate dimensions for absolutely positioned elements - - for (int i = 0; i < node->children_count; ++i) { - css_node_t* child = node->get_child(node->context, i); - if (getPositionType(child) == CSS_POSITION_ABSOLUTE) { - // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both - // left and right or top and bottom). - for (int ii = 0; ii < 2; ii++) { - css_flex_direction_t axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (!isUndefined(node->layout.dimensions[dim[axis]]) && - !isDimDefined(child, axis) && - isPosDefined(child, leading[axis]) && - isPosDefined(child, trailing[axis])) { - child->layout.dimensions[dim[axis]] = fmaxf( - node->layout.dimensions[dim[axis]] - - getPaddingAndBorderAxis(node, axis) - - getMarginAxis(child, axis) - - getPosition(child, leading[axis]) - - getPosition(child, trailing[axis]), - // You never want to go smaller than padding - getPaddingAndBorderAxis(child, axis) - ); - } - } - for (int ii = 0; ii < 2; ii++) { - css_flex_direction_t axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (isPosDefined(child, trailing[axis]) && - !isPosDefined(child, leading[axis])) { - child->layout.position[leading[axis]] = - node->layout.dimensions[dim[axis]] - - child->layout.dimensions[dim[axis]] - - getPosition(child, trailing[axis]); - } - } - } - } - /** END_GENERATED **/ -} - -void layoutNode(css_node_t *node, float parentMaxWidth) { - css_layout_t *layout = &node->layout; - layout->should_update = true; - - bool skipLayout = - !node->is_dirty(node->context) && - eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) && - eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) && - eq(layout->last_parent_max_width, parentMaxWidth); - - if (skipLayout) { - layout->dimensions[CSS_WIDTH] = layout->last_dimensions[CSS_WIDTH]; - layout->dimensions[CSS_HEIGHT] = layout->last_dimensions[CSS_HEIGHT]; - layout->position[CSS_TOP] = layout->last_position[CSS_TOP]; - layout->position[CSS_LEFT] = layout->last_position[CSS_LEFT]; - } else { - layout->last_requested_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH]; - layout->last_requested_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT]; - layout->last_parent_max_width = parentMaxWidth; - - layoutNodeImpl(node, parentMaxWidth); - - layout->last_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH]; - layout->last_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT]; - layout->last_position[CSS_TOP] = layout->position[CSS_TOP]; - layout->last_position[CSS_LEFT] = layout->position[CSS_LEFT]; - } -} diff --git a/ReactKit/Layout/Layout.h b/ReactKit/Layout/Layout.h deleted file mode 100644 index 51f72493bb5..00000000000 --- a/ReactKit/Layout/Layout.h +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @generated SignedSource<<58298c7a8815a8675e970b0347dedfed>> - * - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !! This file is a check-in from github! !! - * !! !! - * !! You should not modify this file directly. Instead: !! - * !! 1) Go to https://github.com/facebook/css-layout !! - * !! 2) Make a pull request and get it merged !! - * !! 3) Execute ./import.sh to pull in the latest version !! - * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * Copyright (c) 2014, 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. - */ - -#ifndef __LAYOUT_H -#define __LAYOUT_H - -#include -#include -#define CSS_UNDEFINED NAN - -typedef enum { - CSS_FLEX_DIRECTION_COLUMN = 0, - CSS_FLEX_DIRECTION_ROW -} css_flex_direction_t; - -typedef enum { - CSS_JUSTIFY_FLEX_START = 0, - CSS_JUSTIFY_CENTER, - CSS_JUSTIFY_FLEX_END, - CSS_JUSTIFY_SPACE_BETWEEN, - CSS_JUSTIFY_SPACE_AROUND -} css_justify_t; - -// Note: auto is only a valid value for alignSelf. It is NOT a valid value for -// alignItems. -typedef enum { - CSS_ALIGN_AUTO = 0, - CSS_ALIGN_FLEX_START, - CSS_ALIGN_CENTER, - CSS_ALIGN_FLEX_END, - CSS_ALIGN_STRETCH -} css_align_t; - -typedef enum { - CSS_POSITION_RELATIVE = 0, - CSS_POSITION_ABSOLUTE -} css_position_type_t; - -typedef enum { - CSS_NOWRAP = 0, - CSS_WRAP -} css_wrap_type_t; - -// Note: left and top are shared between position[2] and position[4], so -// they have to be before right and bottom. -typedef enum { - CSS_LEFT = 0, - CSS_TOP, - CSS_RIGHT, - CSS_BOTTOM, - CSS_POSITION_COUNT -} css_position_t; - -typedef enum { - CSS_WIDTH = 0, - CSS_HEIGHT -} css_dimension_t; - -typedef struct { - float position[2]; - float dimensions[2]; - - // Instead of recomputing the entire layout every single time, we - // cache some information to break early when nothing changed - bool should_update; - float last_requested_dimensions[2]; - float last_parent_max_width; - float last_dimensions[2]; - float last_position[2]; -} css_layout_t; - -typedef struct { - float dimensions[2]; -} css_dim_t; - -typedef struct { - css_flex_direction_t flex_direction; - css_justify_t justify_content; - css_align_t align_items; - css_align_t align_self; - css_position_type_t position_type; - css_wrap_type_t flex_wrap; - float flex; - float margin[4]; - float position[4]; - /** - * You should skip all the rules that contain negative values for the - * following attributes. For example: - * {padding: 10, paddingLeft: -5} - * should output: - * {left: 10 ...} - * the following two are incorrect: - * {left: -5 ...} - * {left: 0 ...} - */ - float padding[4]; - float border[4]; - float dimensions[2]; -} css_style_t; - -typedef struct css_node { - css_style_t style; - css_layout_t layout; - int children_count; - - css_dim_t (*measure)(void *context, float width); - void (*print)(void *context); - struct css_node* (*get_child)(void *context, int i); - bool (*is_dirty)(void *context); - void *context; -} css_node_t; - - -// Lifecycle of nodes and children -css_node_t *new_css_node(void); -void init_css_node(css_node_t *node); -void free_css_node(css_node_t *node); - -// Print utilities -typedef enum { - CSS_PRINT_LAYOUT = 1, - CSS_PRINT_STYLE = 2, - CSS_PRINT_CHILDREN = 4, -} css_print_options_t; -void print_css_node(css_node_t *node, css_print_options_t options); - -// Function that computes the layout! -void layoutNode(css_node_t *node, float maxWidth); -bool isUndefined(float value); - -#endif diff --git a/ReactKit/Modules/RCTAlertManager.h b/ReactKit/Modules/RCTAlertManager.h deleted file mode 100644 index e24e0bc95c2..00000000000 --- a/ReactKit/Modules/RCTAlertManager.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridgeModule.h" - -@interface RCTAlertManager : NSObject - -@end diff --git a/ReactKit/Modules/RCTAlertManager.m b/ReactKit/Modules/RCTAlertManager.m deleted file mode 100644 index 97ca88f8604..00000000000 --- a/ReactKit/Modules/RCTAlertManager.m +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTAlertManager.h" - -#import "RCTLog.h" - -@interface RCTAlertManager() - -@end - -@implementation RCTAlertManager -{ - NSMutableArray *_alerts; - NSMutableArray *_alertCallbacks; - NSMutableArray *_alertButtonKeys; -} - -- (instancetype)init -{ - if ((self = [super init])) { - _alerts = [[NSMutableArray alloc] init]; - _alertCallbacks = [[NSMutableArray alloc] init]; - _alertButtonKeys = [[NSMutableArray alloc] init]; - } - return self; -} - -/** - * @param {NSDictionary} args Dictionary of the form - * - * @{ - * @"message": @"", - * @"buttons": @[ - * @{@"": @""}, - * @{@"": @""}, - * ] - * } - * The key from the `buttons` dictionary is passed back in the callback on click. - * Buttons are displayed in the order they are specified. If "cancel" is used as - * the button key, it will be differently highlighted, according to iOS UI conventions. - */ -- (void)alertWithArgs:(NSDictionary *)args callback:(RCTResponseSenderBlock)callback -{ - RCT_EXPORT(); - - NSString *title = args[@"title"]; - NSString *message = args[@"message"]; - NSArray *buttons = args[@"buttons"]; - - if (!title && !message) { - RCTLogError(@"Must specify either an alert title, or message, or both"); - return; - } else if (buttons.count == 0) { - RCTLogError(@"Must have at least one button."); - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title - message:message - delegate:self - cancelButtonTitle:nil - otherButtonTitles:nil]; - - NSMutableArray *buttonKeys = [[NSMutableArray alloc] initWithCapacity:buttons.count]; - - NSInteger index = 0; - for (NSDictionary *button in buttons) { - if (button.count != 1) { - RCTLogError(@"Button definitions should have exactly one key."); - } - NSString *buttonKey = [button.allKeys firstObject]; - NSString *buttonTitle = [button[buttonKey] description]; - [alertView addButtonWithTitle:buttonTitle]; - if ([buttonKey isEqualToString: @"cancel"]) { - alertView.cancelButtonIndex = index; - } - [buttonKeys addObject:buttonKey]; - index ++; - } - - [_alerts addObject:alertView]; - [_alertCallbacks addObject:callback ?: ^(id unused) {}]; - [_alertButtonKeys addObject:buttonKeys]; - - [alertView show]; - }); -} - -#pragma mark - UIAlertViewDelegate - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - NSUInteger index = [_alerts indexOfObject:alertView]; - RCTAssert(index != NSNotFound, @"Dismissed alert was not recognised"); - - RCTResponseSenderBlock callback = _alertCallbacks[index]; - NSArray *buttonKeys = _alertButtonKeys[index]; - callback(@[buttonKeys[buttonIndex]]); - - [_alerts removeObjectAtIndex:index]; - [_alertCallbacks removeObjectAtIndex:index]; - [_alertButtonKeys removeObjectAtIndex:index]; -} - -@end diff --git a/ReactKit/Modules/RCTExceptionsManager.h b/ReactKit/Modules/RCTExceptionsManager.h deleted file mode 100644 index 02ea3320267..00000000000 --- a/ReactKit/Modules/RCTExceptionsManager.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridgeModule.h" - -@interface RCTExceptionsManager : NSObject - -@end diff --git a/ReactKit/Modules/RCTExceptionsManager.m b/ReactKit/Modules/RCTExceptionsManager.m deleted file mode 100644 index 29cacf6c8a6..00000000000 --- a/ReactKit/Modules/RCTExceptionsManager.m +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTExceptionsManager.h" - -#import "RCTRedBox.h" - -@implementation RCTExceptionsManager - -- (void)reportUnhandledExceptionWithMessage:(NSString *)message stack:(NSArray *)stack -{ - RCT_EXPORT(reportUnhandledException); - - [[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack]; -} - -- (void)updateExceptionMessage:(NSString *)message stack:(NSArray *)stack -{ - RCT_EXPORT(updateExceptionMessage); - - [[RCTRedBox sharedInstance] updateErrorMessage:message withStack:stack]; -} - -@end diff --git a/ReactKit/Modules/RCTStatusBarManager.h b/ReactKit/Modules/RCTStatusBarManager.h deleted file mode 100644 index 83039352193..00000000000 --- a/ReactKit/Modules/RCTStatusBarManager.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridgeModule.h" - -@interface RCTStatusBarManager : NSObject - -@end diff --git a/ReactKit/Modules/RCTStatusBarManager.m b/ReactKit/Modules/RCTStatusBarManager.m deleted file mode 100644 index b391dc6bdc3..00000000000 --- a/ReactKit/Modules/RCTStatusBarManager.m +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTStatusBarManager.h" - -#import "RCTLog.h" - -@implementation RCTStatusBarManager - -static BOOL RCTViewControllerBasedStatusBarAppearance() -{ - static BOOL value; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - value = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"] boolValue]; - }); - - return value; -} - -- (void)setStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated -{ - RCT_EXPORT(); - - dispatch_async(dispatch_get_main_queue(), ^{ - - if (RCTViewControllerBasedStatusBarAppearance()) { - RCTLogError(@"RCTStatusBarManager module requires that the \ - UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO"); - } else { - [[UIApplication sharedApplication] setStatusBarStyle:statusBarStyle - animated:animated]; - } - }); -} - -- (void)setHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation -{ - RCT_EXPORT(); - - dispatch_async(dispatch_get_main_queue(), ^{ - - if (RCTViewControllerBasedStatusBarAppearance()) { - RCTLogError(@"RCTStatusBarManager module requires that the \ - UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO"); - } else { - [[UIApplication sharedApplication] setStatusBarHidden:hidden - withAnimation:animation]; - } - }); -} - -- (NSDictionary *)constantsToExport -{ - return @{ - @"Style": @{ - @"default": @(UIStatusBarStyleDefault), - @"lightContent": @(UIStatusBarStyleLightContent), - }, - @"Animation": @{ - @"none": @(UIStatusBarAnimationNone), - @"fade": @(UIStatusBarAnimationFade), - @"slide": @(UIStatusBarAnimationSlide), - }, - }; -} - -@end diff --git a/ReactKit/Modules/RCTTiming.h b/ReactKit/Modules/RCTTiming.h deleted file mode 100644 index aa55c25213c..00000000000 --- a/ReactKit/Modules/RCTTiming.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridgeModule.h" -#import "RCTInvalidating.h" - -@interface RCTTiming : NSObject - -@end diff --git a/ReactKit/Modules/RCTTiming.m b/ReactKit/Modules/RCTTiming.m deleted file mode 100644 index d008178b234..00000000000 --- a/ReactKit/Modules/RCTTiming.m +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTiming.h" - -#import "RCTAssert.h" -#import "RCTBridge.h" -#import "RCTLog.h" -#import "RCTSparseArray.h" -#import "RCTUtils.h" - -@interface RCTTimer : NSObject - -@property (nonatomic, strong, readonly) NSDate *target; -@property (nonatomic, assign, readonly) BOOL repeats; -@property (nonatomic, copy, readonly) NSNumber *callbackID; -@property (nonatomic, assign, readonly) NSTimeInterval interval; - -@end - -@implementation RCTTimer - -- (instancetype)initWithCallbackID:(NSNumber *)callbackID - interval:(NSTimeInterval)interval - targetTime:(NSTimeInterval)targetTime - repeats:(BOOL)repeats -{ - if ((self = [super init])) { - _interval = interval; - _repeats = repeats; - _callbackID = callbackID; - _target = [NSDate dateWithTimeIntervalSinceNow:targetTime]; - } - return self; -} - -/** - * Returns `YES` if we should invoke the JS callback. - */ -- (BOOL)updateFoundNeedsJSUpdate -{ - if (_target && _target.timeIntervalSinceNow <= 0) { - // The JS Timers will do fine grained calculating of expired timeouts. - _target = _repeats ? [NSDate dateWithTimeIntervalSinceNow:_interval] : nil; - return YES; - } - return NO; -} - -@end - -@implementation RCTTiming -{ - RCTSparseArray *_timers; - id _updateTimer; -} - -@synthesize bridge = _bridge; - -+ (NSArray *)JSMethods -{ - return @[@"RCTJSTimers.callTimers"]; -} - -- (instancetype)init -{ - if ((self = [super init])) { - - _timers = [[RCTSparseArray alloc] init]; - - for (NSString *name in @[UIApplicationWillResignActiveNotification, - UIApplicationDidEnterBackgroundNotification, - UIApplicationWillTerminateNotification]) { - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(stopTimers) - name:name - object:nil]; - } - - for (NSString *name in @[UIApplicationDidBecomeActiveNotification, - UIApplicationWillEnterForegroundNotification]) { - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(startTimers) - name:name - object:nil]; - } - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (BOOL)isValid -{ - return _bridge != nil; -} - -- (void)invalidate -{ - [self stopTimers]; - _bridge = nil; -} - -- (void)stopTimers -{ - [_updateTimer invalidate]; - _updateTimer = nil; -} - -- (void)startTimers -{ - RCTAssertMainThread(); - - if (![self isValid] || _updateTimer != nil || _timers.count == 0) { - return; - } - - _updateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)]; - if (_updateTimer) { - [_updateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; - } else { - RCTLogWarn(@"Failed to create a display link (probably on buildbot) - using an NSTimer for AppEngine instead."); - _updateTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60) - target:self - selector:@selector(update) - userInfo:nil - repeats:YES]; - } -} - -- (void)update -{ - RCTAssertMainThread(); - - NSMutableArray *timersToCall = [[NSMutableArray alloc] init]; - for (RCTTimer *timer in _timers.allObjects) { - if ([timer updateFoundNeedsJSUpdate]) { - [timersToCall addObject:timer.callbackID]; - } - if (!timer.target) { - _timers[timer.callbackID] = nil; - } - } - - // call timers that need to be called - if ([timersToCall count] > 0) { - [_bridge enqueueJSCall:@"RCTJSTimers.callTimers" args:@[timersToCall]]; - } -} - -/** - * There's a small difference between the time when we call - * setTimeout/setInterval/requestAnimation frame and the time it actually makes - * it here. This is important and needs to be taken into account when - * calculating the timer's target time. We calculate this by passing in - * Date.now() from JS and then subtracting that from the current time here. - */ -- (void)createTimer:(NSNumber *)callbackID - duration:(double)jsDuration - jsSchedulingTime:(double)jsSchedulingTime - repeats:(BOOL)repeats -{ - RCT_EXPORT(); - - NSTimeInterval interval = jsDuration / 1000; - NSTimeInterval jsCreationTimeSinceUnixEpoch = jsSchedulingTime / 1000; - NSTimeInterval currentTimeSinceUnixEpoch = [[NSDate date] timeIntervalSince1970]; - NSTimeInterval jsSchedulingOverhead = currentTimeSinceUnixEpoch - jsCreationTimeSinceUnixEpoch; - if (jsSchedulingOverhead < 0) { - RCTLogWarn(@"jsSchedulingOverhead (%ims) should be positive", (int)(jsSchedulingOverhead * 1000)); - } - - NSTimeInterval targetTime = interval - jsSchedulingOverhead; - if (interval < 0.018) { // Make sure short intervals run each frame - interval = 0; - } - - RCTTimer *timer = [[RCTTimer alloc] initWithCallbackID:callbackID - interval:interval - targetTime:targetTime - repeats:repeats]; - dispatch_async(dispatch_get_main_queue(), ^{ - _timers[callbackID] = timer; - [self startTimers]; - }); -} - -- (void)deleteTimer:(NSNumber *)timerID -{ - RCT_EXPORT(); - - if (timerID) { - dispatch_async(dispatch_get_main_queue(), ^{ - _timers[timerID] = nil; - if (_timers.count == 0) { - [self stopTimers]; - } - }); - } else { - RCTLogWarn(@"Called deleteTimer: with a nil timerID"); - } -} - -@end diff --git a/ReactKit/Modules/RCTUIManager.h b/ReactKit/Modules/RCTUIManager.h deleted file mode 100644 index 701c37f930a..00000000000 --- a/ReactKit/Modules/RCTUIManager.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridge.h" -#import "RCTBridgeModule.h" -#import "RCTInvalidating.h" -#import "RCTViewManager.h" - -@class RCTRootView; - -@protocol RCTScrollableProtocol; - -/** - * The RCTUIManager is the module responsible for updating the view hierarchy. - */ -@interface RCTUIManager : NSObject - -@property (nonatomic, weak) id mainScrollView; - -/** - * Allows native environment code to respond to "the main scroll view" events. - * see `RCTUIManager`'s `setMainScrollViewTag`. - */ -@property (nonatomic, readwrite, weak) id nativeMainScrollDelegate; - -/** - * Register a root view with the RCTUIManager. Theoretically, a single manager - * can support multiple root views, however this feature is not currently exposed - * and may eventually be removed. - */ -- (void)registerRootView:(RCTRootView *)rootView; - -/** - * Schedule a block to be executed on the UI thread. Useful if you need to execute - * view logic after all currently queued view updates have completed. - */ -- (void)addUIBlock:(RCTViewManagerUIBlock)block; - -/** - * The view that is currently first responder, according to the JS context. - */ -+ (UIView *)JSResponder; - -@end - -/** - * This category makes the current RCTUIManager instance available via the - * RCTBridge, which is useful for RCTBridgeModules or RCTViewManagers that - * need to access the RCTUIManager. - */ -@interface RCTBridge (RCTUIManager) - -@property (nonatomic, readonly) RCTUIManager *uiManager; - -@end diff --git a/ReactKit/Modules/RCTUIManager.m b/ReactKit/Modules/RCTUIManager.m deleted file mode 100644 index a22f2454051..00000000000 --- a/ReactKit/Modules/RCTUIManager.m +++ /dev/null @@ -1,1405 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTUIManager.h" - -#import -#import - -#import "Layout.h" -#import "RCTAnimationType.h" -#import "RCTAssert.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTRootView.h" -#import "RCTLog.h" -#import "RCTNavigator.h" -#import "RCTScrollableProtocol.h" -#import "RCTShadowView.h" -#import "RCTSparseArray.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "RCTViewNodeProtocol.h" -#import "RCTViewManager.h" -#import "UIView+ReactKit.h" - -typedef void (^react_view_node_block_t)(id); - -static void RCTTraverseViewNodes(id view, react_view_node_block_t block) -{ - if (view.reactTag) block(view); - for (id subview in view.reactSubviews) { - RCTTraverseViewNodes(subview, block); - } -} - -@interface RCTAnimation : NSObject - -@property (nonatomic, readonly) NSTimeInterval duration; -@property (nonatomic, readonly) NSTimeInterval delay; -@property (nonatomic, readonly, copy) NSString *property; -@property (nonatomic, readonly) id fromValue; -@property (nonatomic, readonly) id toValue; -@property (nonatomic, readonly) CGFloat springDamping; -@property (nonatomic, readonly) CGFloat initialVelocity; -@property (nonatomic, readonly) RCTAnimationType animationType; - -@end - -@implementation RCTAnimation - -UIViewAnimationCurve UIViewAnimationCurveFromRCTAnimationType(RCTAnimationType type) -{ - switch (type) { - case RCTAnimationTypeLinear: - return UIViewAnimationCurveLinear; - case RCTAnimationTypeEaseIn: - return UIViewAnimationCurveEaseIn; - case RCTAnimationTypeEaseOut: - return UIViewAnimationCurveEaseOut; - case RCTAnimationTypeEaseInEaseOut: - return UIViewAnimationCurveEaseInOut; - default: - RCTCAssert(NO, @"Unsupported animation type %zd", type); - return UIViewAnimationCurveEaseInOut; - } -} - -- (instancetype)initWithDuration:(NSTimeInterval)duration dictionary:(NSDictionary *)config -{ - if (!config) { - return nil; - } - - if ((self = [super init])) { - _property = [RCTConvert NSString:config[@"property"]]; - - // TODO: this should be provided in ms, not seconds - // (this will require changing all call sites to ms as well) - _duration = [RCTConvert NSTimeInterval:config[@"duration"]] * 1000.0 ?: duration; - _delay = [RCTConvert NSTimeInterval:config[@"delay"]] * 1000.0; - _animationType = [RCTConvert RCTAnimationType:config[@"type"]]; - if (_animationType == RCTAnimationTypeSpring) { - _springDamping = [RCTConvert CGFloat:config[@"springDamping"]]; - _initialVelocity = [RCTConvert CGFloat:config[@"initialVelocity"]]; - } - _fromValue = config[@"fromValue"]; - _toValue = config[@"toValue"]; - } - return self; -} - -- (void)performAnimations:(void (^)(void))animations - withCompletionBlock:(void (^)(BOOL completed))completionBlock -{ - if (_animationType == RCTAnimationTypeSpring) { - - [UIView animateWithDuration:_duration - delay:_delay - usingSpringWithDamping:_springDamping - initialSpringVelocity:_initialVelocity - options:UIViewAnimationOptionBeginFromCurrentState - animations:animations - completion:completionBlock]; - - } else { - - UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState | - UIViewAnimationCurveFromRCTAnimationType(_animationType); - - [UIView animateWithDuration:_duration - delay:_delay - options:options - animations:animations - completion:completionBlock]; - } -} - -@end - -@interface RCTLayoutAnimation : NSObject - -@property (nonatomic, strong) RCTAnimation *createAnimation; -@property (nonatomic, strong) RCTAnimation *updateAnimation; -@property (nonatomic, strong) RCTAnimation *deleteAnimation; -@property (nonatomic, strong) RCTResponseSenderBlock callback; - -@end - -@implementation RCTLayoutAnimation - -- (instancetype)initWithDictionary:(NSDictionary *)config callback:(RCTResponseSenderBlock)callback -{ - if (!config) { - return nil; - } - - if ((self = [super init])) { - - // TODO: this should be provided in ms, not seconds - // (this will require changing all call sites to ms as well) - NSTimeInterval duration = [RCTConvert NSTimeInterval:config[@"duration"]] * 1000.0; - - _createAnimation = [[RCTAnimation alloc] initWithDuration:duration dictionary:config[@"create"]]; - _updateAnimation = [[RCTAnimation alloc] initWithDuration:duration dictionary:config[@"update"]]; - _deleteAnimation = [[RCTAnimation alloc] initWithDuration:duration dictionary:config[@"delete"]]; - _callback = callback; - } - return self; -} - -@end - -@implementation RCTUIManager -{ - dispatch_queue_t _shadowQueue; - - // Root views are only mutated on the shadow queue - NSMutableSet *_rootViewTags; - NSMutableArray *_pendingUIBlocks; - NSLock *_pendingUIBlocksLock; - - // Animation - RCTLayoutAnimation *_nextLayoutAnimation; // RCT thread only - RCTLayoutAnimation *_layoutAnimation; // Main thread only - - // Keyed by viewName - NSMutableDictionary *_defaultShadowViews; // RCT thread only - NSMutableDictionary *_defaultViews; // Main thread only - NSDictionary *_viewManagers; - - // Keyed by React tag - RCTSparseArray *_viewManagerRegistry; // RCT thread only - RCTSparseArray *_shadowViewRegistry; // RCT thread only - RCTSparseArray *_viewRegistry; // Main thread only -} - -@synthesize bridge =_bridge; - -/** - * This function derives the view name automatically - * from the module name. - */ -static NSString *RCTViewNameForModuleName(NSString *moduleName) -{ - NSString *name = moduleName; - if ([name hasSuffix:@"Manager"]) { - name = [name substringToIndex:name.length - @"Manager".length]; - } - return name; -} - -/** - * This private constructor should only be called when creating - * isolated UIImanager instances for testing. Normal initialization - * is via -init:, which is called automatically by the bridge. - */ -- (instancetype)initWithShadowQueue:(dispatch_queue_t)shadowQueue -{ - if ((self = [self init])) { - _shadowQueue = shadowQueue; - _viewManagers = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (instancetype)init -{ - if ((self = [super init])) { - - _pendingUIBlocksLock = [[NSLock alloc] init]; - - _defaultShadowViews = [[NSMutableDictionary alloc] init]; - _defaultViews = [[NSMutableDictionary alloc] init]; - - _viewManagerRegistry = [[RCTSparseArray alloc] init]; - _shadowViewRegistry = [[RCTSparseArray alloc] init]; - _viewRegistry = [[RCTSparseArray alloc] init]; - - // Internal resources - _pendingUIBlocks = [[NSMutableArray alloc] init]; - _rootViewTags = [[NSMutableSet alloc] init]; - } - return self; -} - -- (void)dealloc -{ - RCTAssert(!self.valid, @"must call -invalidate before -dealloc"); -} - -- (void)setBridge:(RCTBridge *)bridge -{ - if (_bridge) { - - // Clear previous bridge data - [self invalidate]; - } - if (bridge) { - - _bridge = bridge; - _shadowQueue = _bridge.shadowQueue; - - // Get view managers from bridge - NSMutableDictionary *viewManagers = [[NSMutableDictionary alloc] init]; - [_bridge.modules enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, RCTViewManager *manager, BOOL *stop) { - if ([manager isKindOfClass:[RCTViewManager class]]) { - viewManagers[RCTViewNameForModuleName(moduleName)] = manager; - } - }]; - - _viewManagers = [viewManagers copy]; - } -} - -- (BOOL)isValid -{ - return _viewRegistry != nil; -} - -- (void)invalidate -{ - RCTAssertMainThread(); - - _viewRegistry = nil; - _shadowViewRegistry = nil; - _bridge = nil; - - [_pendingUIBlocksLock lock]; - _pendingUIBlocks = nil; - [_pendingUIBlocksLock unlock]; -} - -- (void)registerRootView:(RCTRootView *)rootView; -{ - RCTAssertMainThread(); - - NSNumber *reactTag = rootView.reactTag; - UIView *existingView = _viewRegistry[reactTag]; - RCTCAssert(existingView == nil || existingView == rootView, - @"Expect all root views to have unique tag. Added %@ twice", reactTag); - - // Register view - _viewRegistry[reactTag] = rootView; - CGRect frame = rootView.frame; - - // Register manager (TODO: should we do this, or leave it nil?) - _viewManagerRegistry[reactTag] = _viewManagers[@"View"]; - - // Register shadow view - dispatch_async(_shadowQueue, ^{ - - RCTShadowView *shadowView = [[RCTShadowView alloc] init]; - shadowView.reactTag = reactTag; - shadowView.frame = frame; - shadowView.backgroundColor = [UIColor whiteColor]; - shadowView.reactRootView = YES; // can this just be inferred from the fact that it has no superview? - _shadowViewRegistry[shadowView.reactTag] = shadowView; - - [_rootViewTags addObject:reactTag]; - }); -} - -/** - * Unregisters views from registries - */ -- (void)_purgeChildren:(NSArray *)children fromRegistry:(RCTSparseArray *)registry -{ - for (id child in children) { - RCTTraverseViewNodes(registry[child.reactTag], ^(id subview) { - RCTAssert(![subview isReactRootView], @"Root views should not be unregistered"); - if ([subview conformsToProtocol:@protocol(RCTInvalidating)]) { - [(id)subview invalidate]; - } - registry[subview.reactTag] = nil; - }); - } -} - -- (void)addUIBlock:(RCTViewManagerUIBlock)block -{ - RCTAssert(![NSThread isMainThread], @"This method should only be called on the shadow thread"); - - __weak RCTUIManager *weakViewManager = self; - __weak RCTSparseArray *weakViewRegistry = _viewRegistry; - dispatch_block_t outerBlock = ^{ - RCTUIManager *strongViewManager = weakViewManager; - RCTSparseArray *strongViewRegistry = weakViewRegistry; - if (strongViewManager && strongViewRegistry) { - block(strongViewManager, strongViewRegistry); - } - }; - - [_pendingUIBlocksLock lock]; - [_pendingUIBlocks addObject:outerBlock]; - [_pendingUIBlocksLock unlock]; -} - -- (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTShadowView *)rootShadowView -{ - RCTAssert(![NSThread isMainThread], @"This should never be executed on main thread."); - - NSMutableSet *viewsWithNewFrames = [NSMutableSet setWithCapacity:1]; - - // This is nuanced. In the JS thread, we create a new update buffer - // `frameTags`/`frames` that is created/mutated in the JS thread. We access - // these structures in the UI-thread block. `NSMutableArray` is not thread - // safe so we rely on the fact that we never mutate it after it's passed to - // the main thread. - [rootShadowView collectRootUpdatedFrames:viewsWithNewFrames - parentConstraint:(CGSize){CSS_UNDEFINED, CSS_UNDEFINED}]; - - // Parallel arrays - NSMutableArray *frameReactTags = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; - NSMutableArray *frames = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; - NSMutableArray *areNew = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; - NSMutableArray *parentsAreNew = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; - - for (RCTShadowView *shadowView in viewsWithNewFrames) { - [frameReactTags addObject:shadowView.reactTag]; - [frames addObject:[NSValue valueWithCGRect:shadowView.frame]]; - [areNew addObject:@(shadowView.isNewView)]; - [parentsAreNew addObject:@(shadowView.superview.isNewView)]; - } - - for (RCTShadowView *shadowView in viewsWithNewFrames) { - // We have to do this after we build the parentsAreNew array. - shadowView.newView = NO; - } - - NSMutableArray *updateBlocks = [[NSMutableArray alloc] init]; - for (RCTShadowView *shadowView in viewsWithNewFrames) { - RCTViewManager *manager = _viewManagerRegistry[shadowView.reactTag]; - RCTViewManagerUIBlock block = [manager uiBlockToAmendWithShadowView:shadowView]; - if (block) [updateBlocks addObject:block]; - } - - // Perform layout (possibly animated) - NSNumber *rootViewTag = rootShadowView.reactTag; - return ^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - for (NSUInteger ii = 0; ii < frames.count; ii++) { - NSNumber *reactTag = frameReactTags[ii]; - UIView *view = viewRegistry[reactTag]; - CGRect frame = [frames[ii] CGRectValue]; - - // These frames are in terms of anchorPoint = topLeft, but internally the - // views are anchorPoint = center for easier scale and rotation animations. - // Convert the frame so it works with anchorPoint = center. - CGPoint position = {CGRectGetMidX(frame), CGRectGetMidY(frame)}; - CGRect bounds = {0, 0, frame.size}; - - // Avoid crashes due to nan coords - if (isnan(position.x) || isnan(position.y) || - isnan(bounds.origin.x) || isnan(bounds.origin.y) || - isnan(bounds.size.width) || isnan(bounds.size.height)) { - RCTLogError(@"Invalid layout for (%@)%@. position: %@. bounds: %@", - [view reactTag], self, NSStringFromCGPoint(position), NSStringFromCGRect(bounds)); - continue; - } - - void (^completion)(BOOL finished) = ^(BOOL finished) { - if (self->_layoutAnimation.callback) { - self->_layoutAnimation.callback(@[@(finished)]); - } - }; - - // Animate view update - BOOL isNew = [areNew[ii] boolValue]; - RCTAnimation *updateAnimation = isNew ? nil: _layoutAnimation.updateAnimation; - if (updateAnimation) { - [updateAnimation performAnimations:^{ - view.layer.position = position; - view.layer.bounds = bounds; - for (RCTViewManagerUIBlock block in updateBlocks) { - block(self, _viewRegistry); - } - } withCompletionBlock:completion]; - } else { - view.layer.position = position; - view.layer.bounds = bounds; - for (RCTViewManagerUIBlock block in updateBlocks) { - block(self, _viewRegistry); - } - completion(YES); - } - - // Animate view creation - BOOL shouldAnimateCreation = isNew && ![parentsAreNew[ii] boolValue]; - RCTAnimation *createAnimation = _layoutAnimation.createAnimation; - if (shouldAnimateCreation && createAnimation) { - if ([createAnimation.property isEqualToString:@"scaleXY"]) { - view.layer.transform = CATransform3DMakeScale(0, 0, 0); - } else if ([createAnimation.property isEqualToString:@"opacity"]) { - view.layer.opacity = 0.0; - } - [createAnimation performAnimations:^{ - if ([createAnimation.property isEqual:@"scaleXY"]) { - view.layer.transform = CATransform3DIdentity; - } else if ([createAnimation.property isEqual:@"opacity"]) { - view.layer.opacity = 1.0; - } else { - RCTLogError(@"Unsupported layout animation createConfig property %@", - createAnimation.property); - } - for (RCTViewManagerUIBlock block in updateBlocks) { - block(self, _viewRegistry); - } - } withCompletionBlock:nil]; - } - } - - /** - * Enumerate all active (attached to a parent) views and call - * reactBridgeDidFinishTransaction on them if they implement it. - * TODO: this is quite inefficient. If this was handled via the - * ViewManager instead, it could be done more efficiently. - */ - RCTRootView *rootView = _viewRegistry[rootViewTag]; - RCTTraverseViewNodes(rootView, ^(id view) { - if ([view respondsToSelector:@selector(reactBridgeDidFinishTransaction)]) { - [view reactBridgeDidFinishTransaction]; - } - }); - }; -} - -- (void)_amendPendingUIBlocksWithStylePropagationUpdateForRootView:(RCTShadowView *)topView -{ - NSMutableSet *applierBlocks = [NSMutableSet setWithCapacity:1]; - [topView collectUpdatedProperties:applierBlocks parentProperties:@{}]; - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - for (RCTApplierBlock block in applierBlocks) { - block(viewRegistry); - } - }]; -} - -/** - * A method to be called from JS, which takes a container ID and then releases - * all subviews for that container upon receipt. - */ -- (void)removeSubviewsFromContainerWithID:(NSNumber *)containerID -{ - RCT_EXPORT(); - - id container = _viewRegistry[containerID]; - RCTAssert(container != nil, @"container view (for ID %@) not found", containerID); - - NSUInteger subviewsCount = [[container reactSubviews] count]; - NSMutableArray *indices = [[NSMutableArray alloc] initWithCapacity:subviewsCount]; - for (NSInteger childIndex = 0; childIndex < subviewsCount; childIndex++) { - [indices addObject:@(childIndex)]; - } - - [self manageChildren:containerID - moveFromIndices:nil - moveToIndices:nil - addChildReactTags:nil - addAtIndices:nil - removeAtIndices:indices]; -} - -/** - * Disassociates children from container. Doesn't remove from registries. - * TODO: use [NSArray getObjects:buffer] to reuse same fast buffer each time. - * - * @returns Array of removed items. - */ -- (NSArray *)_childrenToRemoveFromContainer:(id)container - atIndices:(NSArray *)atIndices -{ - // If there are no indices to move or the container has no subviews don't bother - // We support parents with nil subviews so long as they're all nil so this allows for this behavior - if ([atIndices count] == 0 || [[container reactSubviews] count] == 0) { - return nil; - } - // Construction of removed children must be done "up front", before indices are disturbed by removals. - NSMutableArray *removedChildren = [NSMutableArray arrayWithCapacity:atIndices.count]; - RCTCAssert(container != nil, @"container view (for ID %@) not found", container); - for (NSInteger i = 0; i < [atIndices count]; i++) { - NSInteger index = [atIndices[i] integerValue]; - if (index < [[container reactSubviews] count]) { - [removedChildren addObject:[container reactSubviews][index]]; - } - } - if (removedChildren.count != atIndices.count) { - RCTLogMustFix(@"removedChildren count (%tu) was not what we expected (%tu)", removedChildren.count, atIndices.count); - } - return removedChildren; -} - -- (void)_removeChildren:(NSArray *)children fromContainer:(id)container -{ - for (id removedChild in children) { - [container removeReactSubview:removedChild]; - } -} - -- (void)removeRootView:(NSNumber *)rootReactTag -{ - RCT_EXPORT(); - - RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag]; - RCTAssert(rootShadowView.superview == nil, @"root view cannot have superview (ID %@)", rootReactTag); - [self _purgeChildren:@[rootShadowView] fromRegistry:_shadowViewRegistry]; - [_rootViewTags removeObject:rootReactTag]; - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - RCTCAssertMainThread(); - UIView *rootView = viewRegistry[rootReactTag]; - [uiManager _purgeChildren:@[rootView] fromRegistry:viewRegistry]; - }]; -} - -- (void)replaceExistingNonRootView:(NSNumber *)reactTag withView:(NSNumber *)newReactTag -{ - RCT_EXPORT(); - - RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; - RCTAssert(shadowView != nil, @"shadowView (for ID %@) not found", reactTag); - - RCTShadowView *superShadowView = shadowView.superview; - RCTAssert(superShadowView != nil, @"shadowView super (of ID %@) not found", reactTag); - - NSUInteger indexOfView = [superShadowView.reactSubviews indexOfObject:shadowView]; - RCTAssert(indexOfView != NSNotFound, @"View's superview doesn't claim it as subview (id %@)", reactTag); - NSArray *removeAtIndices = @[@(indexOfView)]; - NSArray *addTags = @[newReactTag]; - [self manageChildren:superShadowView.reactTag - moveFromIndices:nil - moveToIndices:nil - addChildReactTags:addTags - addAtIndices:removeAtIndices - removeAtIndices:removeAtIndices]; -} - -- (void)manageChildren:(NSNumber *)containerReactTag - moveFromIndices:(NSArray *)moveFromIndices - moveToIndices:(NSArray *)moveToIndices - addChildReactTags:(NSArray *)addChildReactTags - addAtIndices:(NSArray *)addAtIndices - removeAtIndices:(NSArray *)removeAtIndices -{ - RCT_EXPORT(); - - [self _manageChildren:containerReactTag - moveFromIndices:moveFromIndices - moveToIndices:moveToIndices - addChildReactTags:addChildReactTags - addAtIndices:addAtIndices - removeAtIndices:removeAtIndices - registry:_shadowViewRegistry]; - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - - [uiManager _manageChildren:containerReactTag - moveFromIndices:moveFromIndices - moveToIndices:moveToIndices - addChildReactTags:addChildReactTags - addAtIndices:addAtIndices - removeAtIndices:removeAtIndices - registry:viewRegistry]; - }]; -} - -- (void)_manageChildren:(NSNumber *)containerReactTag - moveFromIndices:(NSArray *)moveFromIndices - moveToIndices:(NSArray *)moveToIndices - addChildReactTags:(NSArray *)addChildReactTags - addAtIndices:(NSArray *)addAtIndices - removeAtIndices:(NSArray *)removeAtIndices - registry:(RCTSparseArray *)registry -{ - id container = registry[containerReactTag]; - RCTAssert(moveFromIndices.count == moveToIndices.count, @"moveFromIndices had size %tu, moveToIndices had size %tu", moveFromIndices.count, moveToIndices.count); - RCTAssert(addChildReactTags.count == addAtIndices.count, @"there should be at least one react child to add"); - - // Removes (both permanent and temporary moves) are using "before" indices - NSArray *permanentlyRemovedChildren = [self _childrenToRemoveFromContainer:container atIndices:removeAtIndices]; - NSArray *temporarilyRemovedChildren = [self _childrenToRemoveFromContainer:container atIndices:moveFromIndices]; - [self _removeChildren:permanentlyRemovedChildren fromContainer:container]; - [self _removeChildren:temporarilyRemovedChildren fromContainer:container]; - - [self _purgeChildren:permanentlyRemovedChildren fromRegistry:registry]; - - // TODO (#5906496): optimize all these loops - constantly calling array.count is not efficient - - // Figure out what to insert - merge temporary inserts and adds - NSMutableDictionary *destinationsToChildrenToAdd = [NSMutableDictionary dictionary]; - for (NSInteger index = 0; index < temporarilyRemovedChildren.count; index++) { - destinationsToChildrenToAdd[moveToIndices[index]] = temporarilyRemovedChildren[index]; - } - for (NSInteger index = 0; index < addAtIndices.count; index++) { - id view = registry[addChildReactTags[index]]; - if (view) { - destinationsToChildrenToAdd[addAtIndices[index]] = view; - } - } - - NSArray *sortedIndices = [[destinationsToChildrenToAdd allKeys] sortedArrayUsingSelector:@selector(compare:)]; - for (NSNumber *reactIndex in sortedIndices) { - [container insertReactSubview:destinationsToChildrenToAdd[reactIndex] atIndex:[reactIndex integerValue]]; - } -} - -static BOOL RCTCallPropertySetter(SEL setter, id value, id view, id defaultView, RCTViewManager *manager) -{ - // TODO: cache respondsToSelector tests - if ([manager respondsToSelector:setter]) { - - if (value == [NSNull null]) { - value = nil; - } - - ((void (*)(id, SEL, id, id, id))objc_msgSend)(manager, setter, value, view, defaultView); - return YES; - } - return NO; -} - -static void RCTSetViewProps(NSDictionary *props, UIView *view, - UIView *defaultView, RCTViewManager *manager) -{ - [props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { - - SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set_%@:forView:withDefaultView:", key]); - - // For regular views we don't attempt to set properties - // unless the view property has been explicitly exported. - RCTCallPropertySetter(setter, obj, view, defaultView, manager); - }]; -} - -static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView, - RCTShadowView *defaultView, RCTViewManager *manager) -{ - [props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { - - SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set_%@:forShadowView:withDefaultView:", key]); - - // For shadow views we call any custom setter methods by default, - // but if none is specified, we attempt to set property anyway. - if (!RCTCallPropertySetter(setter, obj, shadowView, defaultView, manager)) { - - if (obj == [NSNull null]) { - // Copy property from default view to current - // Note: not just doing `[defaultView valueForKey:key]`, the - // key may not exist, in which case we'd get an exception. - RCTCopyProperty(shadowView, defaultView, key); - } else { - RCTSetProperty(shadowView, key, obj); - } - } - }]; - - // Update layout - [shadowView updateShadowViewLayout]; -} - -- (void)createAndRegisterViewWithReactTag:(NSNumber *)reactTag - viewName:(NSString *)viewName - props:(NSDictionary *)props -{ - RCT_EXPORT(createView); - - RCTViewManager *manager = _viewManagers[viewName]; - if (manager == nil) { - RCTLogWarn(@"No manager class found for view with module name \"%@\"", viewName); - manager = [[RCTViewManager alloc] init]; - } - - // Register manager - _viewManagerRegistry[reactTag] = manager; - - // Generate default view, used for resetting default props - if (!_defaultShadowViews[viewName]) { - _defaultShadowViews[viewName] = [manager shadowView]; - } - - RCTShadowView *shadowView = [manager shadowView]; - shadowView.moduleName = viewName; - shadowView.reactTag = reactTag; - RCTSetShadowViewProps(props, shadowView, _defaultShadowViews[viewName], manager); - _shadowViewRegistry[shadowView.reactTag] = shadowView; - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - RCTCAssertMainThread(); - - // Generate default view, used for resetting default props - if (!uiManager->_defaultViews[viewName]) { - // Note the default is setup after the props are read for the first time ever - // for this className - this is ok because we only use the default for restoring - // defaults, which never happens on first creation. - uiManager->_defaultViews[viewName] = [manager view]; - } - - UIView *view = [manager view]; - if (view) { - - // Set required properties - view.reactTag = reactTag; - view.multipleTouchEnabled = YES; - view.userInteractionEnabled = YES; // required for touch handling - view.layer.allowsGroupOpacity = YES; // required for touch handling - - // Set custom properties - RCTSetViewProps(props, view, uiManager->_defaultViews[viewName], manager); - } - viewRegistry[view.reactTag] = view; - }]; -} - -// TODO: remove viewName param as it isn't needed -- (void)updateView:(NSNumber *)reactTag viewName:(__unused NSString *)_ props:(NSDictionary *)props -{ - RCT_EXPORT(); - - RCTViewManager *viewManager = _viewManagerRegistry[reactTag]; - NSString *viewName = RCTViewNameForModuleName([[viewManager class] moduleName]); - - RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; - RCTSetShadowViewProps(props, shadowView, _defaultShadowViews[viewName], viewManager); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - UIView *view = uiManager->_viewRegistry[reactTag]; - RCTSetViewProps(props, view, uiManager->_defaultViews[viewName], viewManager); - }]; -} - -- (void)becomeResponder:(NSNumber *)reactTag -{ - RCT_EXPORT(focus); - - if (!reactTag) return; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - UIView *newResponder = viewRegistry[reactTag]; - [newResponder becomeFirstResponder]; - }]; -} - -- (void)resignResponder:(NSNumber *)reactTag -{ - RCT_EXPORT(blur); - - if (!reactTag) return; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - UIView *currentResponder = viewRegistry[reactTag]; - [currentResponder resignFirstResponder]; - }]; -} - -- (void)batchDidComplete -{ - // Gather blocks to be executed now that all view hierarchy manipulations have - // been completed (note that these may still take place before layout has finished) - for (RCTViewManager *manager in _viewManagers.allValues) { - RCTViewManagerUIBlock uiBlock = [manager uiBlockToAmendWithShadowViewRegistry:_shadowViewRegistry]; - if (uiBlock) { - [self addUIBlock:uiBlock]; - } - } - - // Set up next layout animation - if (_nextLayoutAnimation) { - RCTLayoutAnimation *layoutAnimation = _nextLayoutAnimation; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - uiManager->_layoutAnimation = layoutAnimation; - }]; - } - - // Perform layout - for (NSNumber *reactTag in _rootViewTags) { - RCTShadowView *rootView = _shadowViewRegistry[reactTag]; - [self addUIBlock:[self uiBlockWithLayoutUpdateForRootView:rootView]]; - [self _amendPendingUIBlocksWithStylePropagationUpdateForRootView:rootView]; - } - - // Clear layout animations - if (_nextLayoutAnimation) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - uiManager->_layoutAnimation = nil; - }]; - _nextLayoutAnimation = nil; - } - - // First copy the previous blocks into a temporary variable, then reset the - // pending blocks to a new array. This guards against mutation while - // processing the pending blocks in another thread. - [_pendingUIBlocksLock lock]; - NSArray *previousPendingUIBlocks = _pendingUIBlocks; - _pendingUIBlocks = [[NSMutableArray alloc] init]; - [_pendingUIBlocksLock unlock]; - - // Execute the previously queued UI blocks - dispatch_async(dispatch_get_main_queue(), ^{ - for (dispatch_block_t block in previousPendingUIBlocks) { - block(); - } - }); -} - -- (void)measure:(NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback -{ - RCT_EXPORT(); - - if (!callback) { - RCTLogError(@"Called measure with no callback"); - return; - } - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - UIView *view = viewRegistry[reactTag]; - if (!view) { - RCTLogError(@"measure cannot find view with tag %zd", reactTag); - return; - } - CGRect frame = view.frame; - - UIView *rootView = view; - while (rootView && ![rootView isReactRootView]) { - rootView = rootView.superview; - } - - RCTCAssert([rootView isReactRootView], @"React view not inside RCTRootView"); - - // By convention, all coordinates, whether they be touch coordinates, or - // measurement coordinates are with respect to the root view. - CGPoint pagePoint = [view.superview convertPoint:frame.origin toView:rootView]; - - callback(@[ - @(frame.origin.x), - @(frame.origin.y), - @(frame.size.width), - @(frame.size.height), - @(pagePoint.x), - @(pagePoint.y) - ]); - }]; -} - -/** - * TODO: This could be modified to accept any `RCTViewNodeProtocol`, if - * appropriate changes were made to that protocol to support `superview` - * traversal - which is possibly more difficult than it sounds since a - * `superview` is not a "react superview". - */ -+ (void)measureLayoutOnNodes:(RCTShadowView *)view - ancestor:(RCTShadowView *)ancestor - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(__unused RCTResponseSenderBlock)callback -{ - if (!view) { - RCTLogError(@"Attempting to measure view that does not exist"); - return; - } - if (!ancestor) { - RCTLogError(@"Attempting to measure relative to ancestor that does not exist"); - return; - } - CGRect result = [RCTShadowView measureLayout:view relativeTo:ancestor]; - if (CGRectIsNull(result)) { - RCTLogError(@"view %@ (tag #%@) is not a decendant of %@ (tag #%@)", - view, view.reactTag, ancestor, ancestor.reactTag); - return; - } - CGFloat leftOffset = result.origin.x; - CGFloat topOffset = result.origin.y; - CGFloat width = result.size.width; - CGFloat height = result.size.height; - if (isnan(leftOffset) || isnan(topOffset) || isnan(width) || isnan(height)) { - RCTLogError(@"Attempted to measure layout but offset or dimensions were NaN"); - return; - } - callback(@[@(topOffset), @(leftOffset), @(width), @(height)]); -} - -/** - * Returns the computed recursive offset layout in a dictionary form. The - * returned values are relative to the `ancestor` shadow view. Returns `nil`, if - * the `ancestor` shadow view is not actually an `ancestor`. Does not touch - * anything on the main UI thread. Invokes supplied callback with (x, y, width, - * height). - */ -- (void)measureLayout:(NSNumber *)reactTag - relativeTo:(NSNumber *)ancestorReactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(RCTResponseSenderBlock)callback -{ - RCT_EXPORT(); - - RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; - RCTShadowView *ancestorShadowView = _shadowViewRegistry[ancestorReactTag]; - [RCTUIManager measureLayoutOnNodes:shadowView ancestor:ancestorShadowView errorCallback:errorCallback callback:callback]; -} - -/** - * Returns the computed recursive offset layout in a dictionary form. The - * returned values are relative to the `ancestor` shadow view. Returns `nil`, if - * the `ancestor` shadow view is not actually an `ancestor`. Does not touch - * anything on the main UI thread. Invokes supplied callback with (x, y, width, - * height). - */ -- (void)measureLayoutRelativeToParent:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(RCTResponseSenderBlock)callback -{ - RCT_EXPORT(); - - RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; - [RCTUIManager measureLayoutOnNodes:shadowView ancestor:[shadowView superview] errorCallback:errorCallback callback:callback]; -} - -/** - * Returns an array of computed offset layouts in a dictionary form. The layouts are of any react subviews - * that are immediate descendants to the parent view found within a specified rect. The dictionary result - * contains left, top, width, height and an index. The index specifies the position among the other subviews. - * Only layouts for views that are within the rect passed in are returned. Invokes the error callback if the - * passed in parent view does not exist. Invokes the supplied callback with the array of computed layouts. - */ -- (void)measureViewsInRect:(NSDictionary *)rect - parentView:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(RCTResponseSenderBlock)callback -{ - RCT_EXPORT(); - - RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; - if (!shadowView) { - RCTLogError(@"Attempting to measure view that does not exist (tag #%@)", reactTag); - return; - } - NSArray *childShadowViews = [shadowView reactSubviews]; - NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:[childShadowViews count]]; - CGRect layoutRect = [RCTConvert CGRect:rect]; - - for (int ii = 0; ii < [childShadowViews count]; ii++) { - RCTShadowView *childShadowView = [childShadowViews objectAtIndex:ii]; - CGRect childLayout = [RCTShadowView measureLayout:childShadowView relativeTo:shadowView]; - if (CGRectIsNull(childLayout)) { - RCTLogError(@"View %@ (tag #%@) is not a decendant of %@ (tag #%@)", - childShadowView, childShadowView.reactTag, shadowView, shadowView.reactTag); - return; - } - - CGFloat leftOffset = childLayout.origin.x; - CGFloat topOffset = childLayout.origin.y; - CGFloat width = childLayout.size.width; - CGFloat height = childLayout.size.height; - - if (leftOffset <= layoutRect.origin.x + layoutRect.size.width && - leftOffset + width >= layoutRect.origin.x && - topOffset <= layoutRect.origin.y + layoutRect.size.height && - topOffset + height >= layoutRect.origin.y) { - // This view is within the layout rect - NSDictionary *result = @{@"index": @(ii), - @"left": @(leftOffset), - @"top": @(topOffset), - @"width": @(width), - @"height": @(height)}; - - [results addObject:result]; - } - } - callback(@[results]); -} - -- (void)setMainScrollViewTag:(NSNumber *)reactTag -{ - RCT_EXPORT(); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - // - There should be at most one designated "main scroll view" - // - There should be at most one designated "`nativeMainScrollDelegate`" - // - The one designated main scroll view should have the one designated - // `nativeMainScrollDelegate` set as its `nativeMainScrollDelegate`. - if (uiManager.mainScrollView) { - uiManager.mainScrollView.nativeMainScrollDelegate = nil; - } - if (reactTag) { - id rkObject = viewRegistry[reactTag]; - if ([rkObject conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - uiManager.mainScrollView = (id)rkObject; - ((id)rkObject).nativeMainScrollDelegate = uiManager.nativeMainScrollDelegate; - } else { - RCTCAssert(NO, @"Tag %@ does not conform to RCTScrollableProtocol", reactTag); - } - } else { - uiManager.mainScrollView = nil; - } - }]; -} - -- (void)scrollToOffsetWithView:(NSNumber *)reactTag scrollToOffsetX:(NSNumber *)offsetX offsetY:(NSNumber *)offsetY -{ - RCT_EXPORT(scrollTo); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - UIView *view = viewRegistry[reactTag]; - if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - [(id)view scrollToOffset:CGPointMake([offsetX floatValue], [offsetY floatValue])]; - } else { - RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag %@", view, reactTag); - } - }]; -} - -- (void)zoomToRectWithView:(NSNumber *)reactTag rect:(NSDictionary *)rectDict -{ - RCT_EXPORT(zoomToRect); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - UIView *view = viewRegistry[reactTag]; - if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - [(id)view zoomToRect:[RCTConvert CGRect:rectDict] animated:YES]; - } else { - RCTLogError(@"tried to zoomToRect: on non-RCTScrollableProtocol view %@ with tag %@", view, reactTag); - } - }]; -} - -- (void)getScrollViewContentSize:(NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback failCallback:(RCTResponseSenderBlock)failCallback -{ - RCT_EXPORT(); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - UIView *view = viewRegistry[reactTag]; - if (!view) { - NSString *error = [[NSString alloc] initWithFormat:@"cannot find view with tag %@", reactTag]; - RCTLogError(@"%@", error); - failCallback(@[@{@"error": error}]); - return; - } - - CGSize size = ((id)view).contentSize; - NSDictionary *dict = @{@"width" : @(size.width), @"height" : @(size.height)}; - callback(@[dict]); - }]; -} - -/** - * JS sets what *it* considers to be the responder. Later, scroll views can use - * this in order to determine if scrolling is appropriate. - */ -- (void)setJSResponder:(NSNumber *)reactTag -{ - RCT_EXPORT(); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - _jsResponder = viewRegistry[reactTag]; - if (!_jsResponder) { - RCTLogError(@"Invalid view set to be the JS responder - tag %zd", reactTag); - } - }]; -} - -- (void)clearJSResponder -{ - RCT_EXPORT(); - - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - _jsResponder = nil; - }]; -} - -// TODO: these event types should be distributed among the modules -// that declare them. Also, events should be registerable by any class -// that can call event handlers, not just UIViewManagers. This code -// also seems highly redundant - every event has the same properties. -- (NSDictionary *)customBubblingEventTypes -{ - NSMutableDictionary *customBubblingEventTypesConfigs = [@{ - // Bubble dispatched events - @"topTap": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onPress", - @"captured": @"onPressCapture" - } - }, - @"topVisibleCellsChange": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onVisibleCellsChange", - @"captured": @"onVisibleCellsChangeCapture" - } - }, - @"topNavigateBack": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onNavigationComplete", - @"captured": @"onNavigationCompleteCapture" - } - }, - @"topNavRightButtonTap": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onNavRightButtonTap", - @"captured": @"onNavRightButtonTapCapture" - } - }, - @"topChange": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onChange", - @"captured": @"onChangeCapture" - } - }, - @"topFocus": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onFocus", - @"captured": @"onFocusCapture" - } - }, - @"topBlur": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onBlur", - @"captured": @"onBlurCapture" - } - }, - @"topSubmitEditing": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onSubmitEditing", - @"captured": @"onSubmitEditingCapture" - } - }, - @"topEndEditing": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onEndEditing", - @"captured": @"onEndEditingCapture" - } - }, - @"topTextInput": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onTextInput", - @"captured": @"onTextInputCapture" - } - }, - @"topTouchStart": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onTouchStart", - @"captured": @"onTouchStartCapture" - } - }, - @"topTouchMove": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onTouchMove", - @"captured": @"onTouchMoveCapture" - } - }, - @"topTouchCancel": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onTouchCancel", - @"captured": @"onTouchCancelCapture" - } - }, - @"topTouchEnd": @{ - @"phasedRegistrationNames": @{ - @"bubbled": @"onTouchEnd", - @"captured": @"onTouchEndCapture" - } - }, - } mutableCopy]; - - [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) { - if (RCTClassOverridesClassMethod(cls, @selector(customBubblingEventTypes))) { - NSDictionary *eventTypes = [cls customBubblingEventTypes]; - for (NSString *eventName in eventTypes) { - RCTCAssert(!customBubblingEventTypesConfigs[eventName], - @"Event '%@' registered multiple times.", eventName); - } - [customBubblingEventTypesConfigs addEntriesFromDictionary:eventTypes]; - } - }]; - - return customBubblingEventTypesConfigs; -} - -- (NSDictionary *)customDirectEventTypes -{ - NSMutableDictionary *customDirectEventTypes = [@{ - @"topScrollBeginDrag": @{ - @"registrationName": @"onScrollBeginDrag" - }, - @"topScroll": @{ - @"registrationName": @"onScroll" - }, - @"topScrollEndDrag": @{ - @"registrationName": @"onScrollEndDrag" - }, - @"topScrollAnimationEnd": @{ - @"registrationName": @"onScrollAnimationEnd" - }, - @"topSelectionChange": @{ - @"registrationName": @"onSelectionChange" - }, - @"topMomentumScrollBegin": @{ - @"registrationName": @"onMomentumScrollBegin" - }, - @"topMomentumScrollEnd": @{ - @"registrationName": @"onMomentumScrollEnd" - }, - @"topPullToRefresh": @{ - @"registrationName": @"onPullToRefresh" - }, - @"topLoadingStart": @{ - @"registrationName": @"onLoadingStart" - }, - @"topLoadingFinish": @{ - @"registrationName": @"onLoadingFinish" - }, - @"topLoadingError": @{ - @"registrationName": @"onLoadingError" - }, - } mutableCopy]; - - [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) { - if (RCTClassOverridesClassMethod(cls, @selector(customDirectEventTypes))) { - NSDictionary *eventTypes = [cls customDirectEventTypes]; - for (NSString *eventName in eventTypes) { - RCTCAssert(!customDirectEventTypes[eventName], @"Event '%@' registered multiple times.", eventName); - } - [customDirectEventTypes addEntriesFromDictionary:eventTypes]; - } - }]; - - return customDirectEventTypes; -} - -- (NSDictionary *)constantsToExport -{ - NSMutableDictionary *allJSConstants = [@{ - @"customBubblingEventTypes": [self customBubblingEventTypes], - @"customDirectEventTypes": [self customDirectEventTypes], - @"NSTextAlignment": @{ - @"Left": @(NSTextAlignmentLeft), - @"Center": @(NSTextAlignmentCenter), - @"Right": @(NSTextAlignmentRight), - }, - @"Dimensions": @{ - @"window": @{ - @"width": @(RCTScreenSize().width), - @"height": @(RCTScreenSize().height), - @"scale": @(RCTScreenScale()), - }, - @"modalFullscreenView": @{ - @"width": @(RCTScreenSize().width), - @"height": @(RCTScreenSize().width), - }, - }, - @"StyleConstants": @{ - @"PointerEventsValues": @{ - @"none": @(RCTPointerEventsNone), - @"box-none": @(RCTPointerEventsBoxNone), - @"box-only": @(RCTPointerEventsBoxOnly), - @"auto": @(RCTPointerEventsUnspecified), - }, - }, - @"UIText": @{ - @"AutocapitalizationType": @{ - @"characters": @(UITextAutocapitalizationTypeAllCharacters), - @"sentences": @(UITextAutocapitalizationTypeSentences), - @"words": @(UITextAutocapitalizationTypeWords), - @"none": @(UITextAutocapitalizationTypeNone), - }, - }, - @"UITextField": @{ - @"clearButtonMode": @{ - @"never": @(UITextFieldViewModeNever), - @"while-editing": @(UITextFieldViewModeWhileEditing), - @"unless-editing": @(UITextFieldViewModeUnlessEditing), - @"always": @(UITextFieldViewModeAlways), - }, - }, - @"UIView": @{ - @"ContentMode": @{ - @"ScaleToFill": @(UIViewContentModeScaleToFill), - @"ScaleAspectFit": @(UIViewContentModeScaleAspectFit), - @"ScaleAspectFill": @(UIViewContentModeScaleAspectFill), - @"Redraw": @(UIViewContentModeRedraw), - @"Center": @(UIViewContentModeCenter), - @"Top": @(UIViewContentModeTop), - @"Bottom": @(UIViewContentModeBottom), - @"Left": @(UIViewContentModeLeft), - @"Right": @(UIViewContentModeRight), - @"TopLeft": @(UIViewContentModeTopLeft), - @"TopRight": @(UIViewContentModeTopRight), - @"BottomLeft": @(UIViewContentModeBottomLeft), - @"BottomRight": @(UIViewContentModeBottomRight), - }, - }, - } mutableCopy]; - - [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) { - // TODO: should these be inherited? - NSDictionary *constants = RCTClassOverridesClassMethod(cls, @selector(constantsToExport)) ? [cls constantsToExport] : nil; - if ([constants count]) { - NSMutableDictionary *constantsNamespace = [NSMutableDictionary dictionaryWithDictionary:allJSConstants[name]]; - RCTAssert(constantsNamespace[@"Constants"] == nil , @"Cannot redefine Constants in namespace: %@", name); - // add an additional 'Constants' namespace for each class - constantsNamespace[@"Constants"] = constants; - allJSConstants[name] = [constantsNamespace copy]; - } - }]; - - return allJSConstants; -} - -- (void)configureNextLayoutAnimation:(NSDictionary *)config - withCallback:(RCTResponseSenderBlock)callback - errorCallback:(RCTResponseSenderBlock)errorCallback -{ - RCT_EXPORT(); - - if (_nextLayoutAnimation) { - RCTLogWarn(@"Warning: Overriding previous layout animation with new one before the first began:\n%@ -> %@.", - _nextLayoutAnimation, config); - } - if (config[@"delete"] != nil) { - RCTLogError(@"LayoutAnimation only supports create and update right now. Config: %@", config); - } - _nextLayoutAnimation = [[RCTLayoutAnimation alloc] initWithDictionary:config callback:callback]; -} - -- (void)startOrResetInteractionTiming -{ - RCT_EXPORT(); - - NSSet *rootViewTags = [_rootViewTags copy]; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - for (NSNumber *reactTag in rootViewTags) { - RCTRootView *rootView = viewRegistry[reactTag]; - [rootView startOrResetInteractionTiming]; - } - }]; -} - -- (void)endAndResetInteractionTiming:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError -{ - RCT_EXPORT(); - - NSSet *rootViewTags = [_rootViewTags copy]; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - NSMutableDictionary *timingData = [[NSMutableDictionary alloc] init]; - for (NSNumber *reactTag in rootViewTags) { - RCTRootView *rootView = viewRegistry[reactTag]; - if (rootView) { - timingData[reactTag.stringValue] = [rootView endAndResetInteractionTiming]; - } - } - onSuccess(@[ timingData ]); - }]; -} - -static UIView *_jsResponder; - -+ (UIView *)JSResponder -{ - return _jsResponder; -} - -@end - -@implementation RCTBridge (RCTUIManager) - -- (RCTUIManager *)uiManager -{ - return self.modules[NSStringFromClass([RCTUIManager class])]; -} - -@end diff --git a/ReactKit/ReactKit.podspec b/ReactKit/ReactKit.podspec deleted file mode 100644 index 3e1a8a6e252..00000000000 --- a/ReactKit/ReactKit.podspec +++ /dev/null @@ -1,16 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'ReactKit' - spec.version = '0.0.1' - spec.summary = 'An implementation of React that targets UIKit for iOS' - spec.description = <<-DESC - Our first React Native implementation is ReactKit, targeting iOS. We are also working on an Android implementation which we will release later. ReactKit apps are built using the React JS framework, and render directly to native UIKit elements using a fully asynchronous architecture. There is no browser and no HTML. We have picked what we think is the best set of features from these and other technologies to build what we hope to become the best product development framework available, with an emphasis on iteration speed, developer delight, continuity of technology, and absolutely beautiful and fast products with no compromises in quality or capability. - DESC - spec.homepage = 'https://facebook.github.io/react-native/' - spec.license = { :type => 'BSD' } - spec.author = 'Facebook' - spec.platform = :ios, '7.0' - spec.requires_arc = true - spec.source_files = '**/*.{h,m,c}' - spec.public_header_files = "**/*.h" - #spec.library = "ReactKit" -end diff --git a/ReactKit/ReactKit.xcodeproj/project.pbxproj b/ReactKit/ReactKit.xcodeproj/project.pbxproj deleted file mode 100644 index 48cac5dedc9..00000000000 --- a/ReactKit/ReactKit.xcodeproj/project.pbxproj +++ /dev/null @@ -1,587 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 134FCB361A6D42D900051CC8 /* RCTSparseArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */; }; - 134FCB3D1A6E7F0800051CC8 /* RCTContextExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3A1A6E7F0800051CC8 /* RCTContextExecutor.m */; }; - 134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 134FCB3C1A6E7F0800051CC8 /* RCTWebViewExecutor.m */; }; - 13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */; }; - 137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E01AA5CF210034F82E /* RCTTabBar.m */; }; - 137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E21AA5CF210034F82E /* RCTTabBarItem.m */; }; - 137327E91AA5CF210034F82E /* RCTTabBarItemManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */; }; - 137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137327E61AA5CF210034F82E /* RCTTabBarManager.m */; }; - 13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; }; - 13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */; }; - 13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEA1A69327A00A75B9A /* RCTExceptionsManager.m */; }; - 13B07FF21A69327A00A75B9A /* RCTTiming.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEE1A69327A00A75B9A /* RCTTiming.m */; }; - 13B080051A6947C200A75B9A /* RCTScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FF71A6947C200A75B9A /* RCTScrollView.m */; }; - 13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FF91A6947C200A75B9A /* RCTScrollViewManager.m */; }; - 13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B0800D1A69489C00A75B9A /* RCTNavigator.m */; }; - 13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B0800F1A69489C00A75B9A /* RCTNavigatorManager.m */; }; - 13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080111A69489C00A75B9A /* RCTNavItem.m */; }; - 13B0801D1A69489C00A75B9A /* RCTNavItemManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080131A69489C00A75B9A /* RCTNavItemManager.m */; }; - 13B0801E1A69489C00A75B9A /* RCTTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080151A69489C00A75B9A /* RCTTextField.m */; }; - 13B0801F1A69489C00A75B9A /* RCTTextFieldManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080171A69489C00A75B9A /* RCTTextFieldManager.m */; }; - 13B080201A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080191A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.m */; }; - 13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */; }; - 13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067491A70F434002CDEE1 /* RCTUIManager.m */; }; - 13E067551A70F44B002CDEE1 /* RCTShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E0674C1A70F44B002CDEE1 /* RCTShadowView.m */; }; - 13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E0674E1A70F44B002CDEE1 /* RCTViewManager.m */; }; - 13E067571A70F44B002CDEE1 /* RCTView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067501A70F44B002CDEE1 /* RCTView.m */; }; - 13E067591A70F44B002CDEE1 /* UIView+ReactKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067541A70F44B002CDEE1 /* UIView+ReactKit.m */; }; - 58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */; }; - 14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; }; - 14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; }; - 14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */; }; - 830A229E1A66C68A008503DA /* RCTRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 830A229D1A66C68A008503DA /* RCTRootView.m */; }; - 830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 830BA4541A8E3BDA00D53203 /* RCTCache.m */; }; - 832348161A77A5AA00B55238 /* Layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FC71A68125100A75B9A /* Layout.c */; }; - 83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */; }; - 83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA4E1A601E3B00E9B192 /* RCTLog.m */; }; - 83CBBA531A601E3B00E9B192 /* RCTUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA501A601E3B00E9B192 /* RCTUtils.m */; }; - 83CBBA5A1A601E9000E9B192 /* RCTRedBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA591A601E9000E9B192 /* RCTRedBox.m */; }; - 83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA5F1A601EAA00E9B192 /* RCTBridge.m */; }; - 83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */; }; - 83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */; }; - 83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBACB1A6023D300E9B192 /* RCTConvert.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 83CBBA2C1A601D0E00E9B192 /* Copy Files */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - ); - name = "Copy Files"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 13442BF21AA90E0B0037E5B0 /* RCTAnimationType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationType.h; sourceTree = ""; }; - 13442BF31AA90E0B0037E5B0 /* RCTPointerEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPointerEvents.h; sourceTree = ""; }; - 13442BF41AA90E0B0037E5B0 /* RCTViewControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewControllerProtocol.h; sourceTree = ""; }; - 134FCB391A6E7F0800051CC8 /* RCTContextExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTContextExecutor.h; sourceTree = ""; }; - 134FCB3A1A6E7F0800051CC8 /* RCTContextExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTContextExecutor.m; sourceTree = ""; }; - 134FCB3B1A6E7F0800051CC8 /* RCTWebViewExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWebViewExecutor.h; sourceTree = ""; }; - 134FCB3C1A6E7F0800051CC8 /* RCTWebViewExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWebViewExecutor.m; sourceTree = ""; }; - 13723B4E1A82FD3C00F88898 /* RCTStatusBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTStatusBarManager.h; sourceTree = ""; }; - 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTStatusBarManager.m; sourceTree = ""; }; - 137327DF1AA5CF210034F82E /* RCTTabBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBar.h; sourceTree = ""; }; - 137327E01AA5CF210034F82E /* RCTTabBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBar.m; sourceTree = ""; }; - 137327E11AA5CF210034F82E /* RCTTabBarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBarItem.h; sourceTree = ""; }; - 137327E21AA5CF210034F82E /* RCTTabBarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarItem.m; sourceTree = ""; }; - 137327E31AA5CF210034F82E /* RCTTabBarItemManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBarItemManager.h; sourceTree = ""; }; - 137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarItemManager.m; sourceTree = ""; }; - 137327E51AA5CF210034F82E /* RCTTabBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTabBarManager.h; sourceTree = ""; }; - 137327E61AA5CF210034F82E /* RCTTabBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTabBarManager.m; sourceTree = ""; }; - 13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTKeyCommands.h; sourceTree = ""; }; - 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTKeyCommands.m; sourceTree = ""; }; - 13B07FC71A68125100A75B9A /* Layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Layout.c; sourceTree = ""; }; - 13B07FC81A68125100A75B9A /* Layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Layout.h; sourceTree = ""; }; - 13B07FE71A69327A00A75B9A /* RCTAlertManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAlertManager.h; sourceTree = ""; }; - 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAlertManager.m; sourceTree = ""; }; - 13B07FE91A69327A00A75B9A /* RCTExceptionsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTExceptionsManager.h; sourceTree = ""; }; - 13B07FEA1A69327A00A75B9A /* RCTExceptionsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTExceptionsManager.m; sourceTree = ""; }; - 13B07FED1A69327A00A75B9A /* RCTTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTiming.h; sourceTree = ""; }; - 13B07FEE1A69327A00A75B9A /* RCTTiming.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTiming.m; sourceTree = ""; }; - 13B07FF61A6947C200A75B9A /* RCTScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTScrollView.h; sourceTree = ""; }; - 13B07FF71A6947C200A75B9A /* RCTScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTScrollView.m; sourceTree = ""; }; - 13B07FF81A6947C200A75B9A /* RCTScrollViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTScrollViewManager.h; sourceTree = ""; }; - 13B07FF91A6947C200A75B9A /* RCTScrollViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTScrollViewManager.m; sourceTree = ""; }; - 13B0800C1A69489C00A75B9A /* RCTNavigator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNavigator.h; sourceTree = ""; }; - 13B0800D1A69489C00A75B9A /* RCTNavigator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNavigator.m; sourceTree = ""; }; - 13B0800E1A69489C00A75B9A /* RCTNavigatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNavigatorManager.h; sourceTree = ""; }; - 13B0800F1A69489C00A75B9A /* RCTNavigatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNavigatorManager.m; sourceTree = ""; }; - 13B080101A69489C00A75B9A /* RCTNavItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNavItem.h; sourceTree = ""; }; - 13B080111A69489C00A75B9A /* RCTNavItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNavItem.m; sourceTree = ""; }; - 13B080121A69489C00A75B9A /* RCTNavItemManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNavItemManager.h; sourceTree = ""; }; - 13B080131A69489C00A75B9A /* RCTNavItemManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNavItemManager.m; sourceTree = ""; }; - 13B080141A69489C00A75B9A /* RCTTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTextField.h; sourceTree = ""; }; - 13B080151A69489C00A75B9A /* RCTTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTextField.m; sourceTree = ""; }; - 13B080161A69489C00A75B9A /* RCTTextFieldManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTextFieldManager.h; sourceTree = ""; }; - 13B080171A69489C00A75B9A /* RCTTextFieldManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTextFieldManager.m; sourceTree = ""; }; - 13B080181A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTUIActivityIndicatorViewManager.h; sourceTree = ""; }; - 13B080191A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIActivityIndicatorViewManager.m; sourceTree = ""; }; - 13B080231A694A8400A75B9A /* RCTWrapperViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWrapperViewController.h; sourceTree = ""; }; - 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWrapperViewController.m; sourceTree = ""; }; - 13C325261AA63B6A0048765F /* RCTAutoInsetsProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAutoInsetsProtocol.h; sourceTree = ""; }; - 13C325271AA63B6A0048765F /* RCTScrollableProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTScrollableProtocol.h; sourceTree = ""; }; - 13C325281AA63B6A0048765F /* RCTViewNodeProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewNodeProtocol.h; sourceTree = ""; }; - 13E067481A70F434002CDEE1 /* RCTUIManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTUIManager.h; sourceTree = ""; }; - 13E067491A70F434002CDEE1 /* RCTUIManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManager.m; sourceTree = ""; }; - 13E0674B1A70F44B002CDEE1 /* RCTShadowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTShadowView.h; sourceTree = ""; }; - 13E0674C1A70F44B002CDEE1 /* RCTShadowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowView.m; sourceTree = ""; }; - 13E0674D1A70F44B002CDEE1 /* RCTViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewManager.h; sourceTree = ""; }; - 13E0674E1A70F44B002CDEE1 /* RCTViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTViewManager.m; sourceTree = ""; }; - 13E0674F1A70F44B002CDEE1 /* RCTView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTView.h; sourceTree = ""; }; - 13E067501A70F44B002CDEE1 /* RCTView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTView.m; sourceTree = ""; }; - 13E067531A70F44B002CDEE1 /* UIView+ReactKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+ReactKit.h"; sourceTree = ""; }; - 13E067541A70F44B002CDEE1 /* UIView+ReactKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+ReactKit.m"; sourceTree = ""; }; - 13EFFCCF1A98E6FE002607DC /* RCTJSMethodRegistrar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSMethodRegistrar.h; sourceTree = ""; }; - 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDatePickerManager.m; sourceTree = ""; }; - 58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDatePickerManager.h; sourceTree = ""; }; - 14F362071AABD06A001CE568 /* RCTSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitch.h; sourceTree = ""; }; - 14F362081AABD06A001CE568 /* RCTSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitch.m; sourceTree = ""; }; - 14F362091AABD06A001CE568 /* RCTSwitchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitchManager.h; sourceTree = ""; }; - 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitchManager.m; sourceTree = ""; }; - 14F484541AABFCE100FDF6B9 /* RCTSliderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSliderManager.h; sourceTree = ""; }; - 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSliderManager.m; sourceTree = ""; }; - 830213F31A654E0800B993E6 /* RCTBridgeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeModule.h; sourceTree = ""; }; - 830A229C1A66C68A008503DA /* RCTRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootView.h; sourceTree = ""; }; - 830A229D1A66C68A008503DA /* RCTRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootView.m; sourceTree = ""; }; - 830BA4531A8E3BDA00D53203 /* RCTCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCache.h; sourceTree = ""; }; - 830BA4541A8E3BDA00D53203 /* RCTCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCache.m; sourceTree = ""; }; - 83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSparseArray.h; sourceTree = ""; }; - 83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSparseArray.m; sourceTree = ""; }; - 83CBBA2E1A601D0E00E9B192 /* libReactKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAssert.h; sourceTree = ""; }; - 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAssert.m; sourceTree = ""; }; - 83CBBA4C1A601E3B00E9B192 /* RCTInvalidating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTInvalidating.h; sourceTree = ""; }; - 83CBBA4D1A601E3B00E9B192 /* RCTLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTLog.h; sourceTree = ""; }; - 83CBBA4E1A601E3B00E9B192 /* RCTLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLog.m; sourceTree = ""; }; - 83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTUtils.h; sourceTree = ""; }; - 83CBBA501A601E3B00E9B192 /* RCTUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUtils.m; sourceTree = ""; }; - 83CBBA581A601E9000E9B192 /* RCTRedBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRedBox.h; sourceTree = ""; }; - 83CBBA591A601E9000E9B192 /* RCTRedBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRedBox.m; sourceTree = ""; }; - 83CBBA5E1A601EAA00E9B192 /* RCTBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBridge.h; sourceTree = ""; }; - 83CBBA5F1A601EAA00E9B192 /* RCTBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBridge.m; sourceTree = ""; }; - 83CBBA631A601ECA00E9B192 /* RCTJavaScriptExecutor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptExecutor.h; sourceTree = ""; }; - 83CBBA651A601EF300E9B192 /* RCTEventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTEventDispatcher.h; sourceTree = ""; }; - 83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventDispatcher.m; sourceTree = ""; }; - 83CBBA961A6020BB00E9B192 /* RCTTouchHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTouchHandler.h; sourceTree = ""; }; - 83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTouchHandler.m; sourceTree = ""; }; - 83CBBACA1A6023D300E9B192 /* RCTConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTConvert.h; sourceTree = ""; }; - 83CBBACB1A6023D300E9B192 /* RCTConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 83CBBA2B1A601D0E00E9B192 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 134FCB381A6E7F0800051CC8 /* Executors */ = { - isa = PBXGroup; - children = ( - 134FCB391A6E7F0800051CC8 /* RCTContextExecutor.h */, - 134FCB3A1A6E7F0800051CC8 /* RCTContextExecutor.m */, - 134FCB3B1A6E7F0800051CC8 /* RCTWebViewExecutor.h */, - 134FCB3C1A6E7F0800051CC8 /* RCTWebViewExecutor.m */, - ); - path = Executors; - sourceTree = ""; - }; - 13B07FC41A68125100A75B9A /* Layout */ = { - isa = PBXGroup; - children = ( - 13B07FC71A68125100A75B9A /* Layout.c */, - 13B07FC81A68125100A75B9A /* Layout.h */, - ); - path = Layout; - sourceTree = ""; - }; - 13B07FE01A69315300A75B9A /* Modules */ = { - isa = PBXGroup; - children = ( - 13B07FE71A69327A00A75B9A /* RCTAlertManager.h */, - 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */, - 13B07FE91A69327A00A75B9A /* RCTExceptionsManager.h */, - 13B07FEA1A69327A00A75B9A /* RCTExceptionsManager.m */, - 13723B4E1A82FD3C00F88898 /* RCTStatusBarManager.h */, - 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */, - 13B07FED1A69327A00A75B9A /* RCTTiming.h */, - 13B07FEE1A69327A00A75B9A /* RCTTiming.m */, - 13E067481A70F434002CDEE1 /* RCTUIManager.h */, - 13E067491A70F434002CDEE1 /* RCTUIManager.m */, - ); - path = Modules; - sourceTree = ""; - }; - 13B07FF31A6947C200A75B9A /* Views */ = { - isa = PBXGroup; - children = ( - 14F362071AABD06A001CE568 /* RCTSwitch.h */, - 14F362081AABD06A001CE568 /* RCTSwitch.m */, - 14F362091AABD06A001CE568 /* RCTSwitchManager.h */, - 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */, - 14F484541AABFCE100FDF6B9 /* RCTSliderManager.h */, - 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */, - 13442BF21AA90E0B0037E5B0 /* RCTAnimationType.h */, - 58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */, - 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */, - 13442BF31AA90E0B0037E5B0 /* RCTPointerEvents.h */, - 13442BF41AA90E0B0037E5B0 /* RCTViewControllerProtocol.h */, - 13C325261AA63B6A0048765F /* RCTAutoInsetsProtocol.h */, - 13C325271AA63B6A0048765F /* RCTScrollableProtocol.h */, - 13C325281AA63B6A0048765F /* RCTViewNodeProtocol.h */, - 13B0800C1A69489C00A75B9A /* RCTNavigator.h */, - 13B0800D1A69489C00A75B9A /* RCTNavigator.m */, - 13B0800E1A69489C00A75B9A /* RCTNavigatorManager.h */, - 13B0800F1A69489C00A75B9A /* RCTNavigatorManager.m */, - 13B080101A69489C00A75B9A /* RCTNavItem.h */, - 13B080111A69489C00A75B9A /* RCTNavItem.m */, - 13B080121A69489C00A75B9A /* RCTNavItemManager.h */, - 13B080131A69489C00A75B9A /* RCTNavItemManager.m */, - 13B07FF61A6947C200A75B9A /* RCTScrollView.h */, - 13B07FF71A6947C200A75B9A /* RCTScrollView.m */, - 13B07FF81A6947C200A75B9A /* RCTScrollViewManager.h */, - 13B07FF91A6947C200A75B9A /* RCTScrollViewManager.m */, - 13E0674B1A70F44B002CDEE1 /* RCTShadowView.h */, - 13E0674C1A70F44B002CDEE1 /* RCTShadowView.m */, - 13B080141A69489C00A75B9A /* RCTTextField.h */, - 13B080151A69489C00A75B9A /* RCTTextField.m */, - 13B080161A69489C00A75B9A /* RCTTextFieldManager.h */, - 13B080171A69489C00A75B9A /* RCTTextFieldManager.m */, - 13B080181A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.h */, - 13B080191A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.m */, - 13E0674F1A70F44B002CDEE1 /* RCTView.h */, - 13E067501A70F44B002CDEE1 /* RCTView.m */, - 13E0674D1A70F44B002CDEE1 /* RCTViewManager.h */, - 13E0674E1A70F44B002CDEE1 /* RCTViewManager.m */, - 13B080231A694A8400A75B9A /* RCTWrapperViewController.h */, - 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */, - 137327DF1AA5CF210034F82E /* RCTTabBar.h */, - 137327E01AA5CF210034F82E /* RCTTabBar.m */, - 137327E11AA5CF210034F82E /* RCTTabBarItem.h */, - 137327E21AA5CF210034F82E /* RCTTabBarItem.m */, - 137327E31AA5CF210034F82E /* RCTTabBarItemManager.h */, - 137327E41AA5CF210034F82E /* RCTTabBarItemManager.m */, - 137327E51AA5CF210034F82E /* RCTTabBarManager.h */, - 137327E61AA5CF210034F82E /* RCTTabBarManager.m */, - 13E067531A70F44B002CDEE1 /* UIView+ReactKit.h */, - 13E067541A70F44B002CDEE1 /* UIView+ReactKit.m */, - ); - path = Views; - sourceTree = ""; - }; - 83CBB9F61A601CBA00E9B192 = { - isa = PBXGroup; - children = ( - 83CBBA2F1A601D0F00E9B192 /* ReactKit */, - 83CBBA001A601CBA00E9B192 /* Products */, - ); - sourceTree = ""; - }; - 83CBBA001A601CBA00E9B192 /* Products */ = { - isa = PBXGroup; - children = ( - 83CBBA2E1A601D0E00E9B192 /* libReactKit.a */, - ); - name = Products; - sourceTree = ""; - }; - 83CBBA2F1A601D0F00E9B192 /* ReactKit */ = { - isa = PBXGroup; - children = ( - 83CBBA491A601E3B00E9B192 /* Base */, - 134FCB381A6E7F0800051CC8 /* Executors */, - 13B07FC41A68125100A75B9A /* Layout */, - 13B07FE01A69315300A75B9A /* Modules */, - 13B07FF31A6947C200A75B9A /* Views */, - ); - name = ReactKit; - sourceTree = ""; - }; - 83CBBA491A601E3B00E9B192 /* Base */ = { - isa = PBXGroup; - children = ( - 83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */, - 83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */, - 83CBBA5E1A601EAA00E9B192 /* RCTBridge.h */, - 83CBBA5F1A601EAA00E9B192 /* RCTBridge.m */, - 830213F31A654E0800B993E6 /* RCTBridgeModule.h */, - 830BA4531A8E3BDA00D53203 /* RCTCache.h */, - 830BA4541A8E3BDA00D53203 /* RCTCache.m */, - 83CBBACA1A6023D300E9B192 /* RCTConvert.h */, - 83CBBACB1A6023D300E9B192 /* RCTConvert.m */, - 83CBBA651A601EF300E9B192 /* RCTEventDispatcher.h */, - 83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */, - 83CBBA4C1A601E3B00E9B192 /* RCTInvalidating.h */, - 83CBBA631A601ECA00E9B192 /* RCTJavaScriptExecutor.h */, - 13EFFCCF1A98E6FE002607DC /* RCTJSMethodRegistrar.h */, - 13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */, - 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */, - 83CBBA4D1A601E3B00E9B192 /* RCTLog.h */, - 83CBBA4E1A601E3B00E9B192 /* RCTLog.m */, - 83CBBA581A601E9000E9B192 /* RCTRedBox.h */, - 83CBBA591A601E9000E9B192 /* RCTRedBox.m */, - 830A229C1A66C68A008503DA /* RCTRootView.h */, - 830A229D1A66C68A008503DA /* RCTRootView.m */, - 83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */, - 83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */, - 83CBBA961A6020BB00E9B192 /* RCTTouchHandler.h */, - 83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */, - 83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */, - 83CBBA501A601E3B00E9B192 /* RCTUtils.m */, - ); - path = Base; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 83CBBA2D1A601D0E00E9B192 /* ReactKit */ = { - isa = PBXNativeTarget; - buildConfigurationList = 83CBBA3F1A601D0F00E9B192 /* Build configuration list for PBXNativeTarget "ReactKit" */; - buildPhases = ( - 006B79A01A781F38006873D1 /* ShellScript */, - 83CBBA2A1A601D0E00E9B192 /* Sources */, - 83CBBA2B1A601D0E00E9B192 /* Frameworks */, - 83CBBA2C1A601D0E00E9B192 /* Copy Files */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ReactKit; - productName = ReactKit; - productReference = 83CBBA2E1A601D0E00E9B192 /* libReactKit.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83CBB9F71A601CBA00E9B192 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 83CBBA2D1A601D0E00E9B192 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactKit" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83CBB9F61A601CBA00E9B192; - productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 83CBBA2D1A601D0E00E9B192 /* ReactKit */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXShellScriptBuildPhase section */ - 006B79A01A781F38006873D1 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "nc -w 5 -z localhost 8081 > /dev/null 2>&1 || open $SRCROOT/../packager/launchPackager.command || echo \"Can't start packager automatically\""; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 83CBBA2A1A601D0E00E9B192 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */, - 13B0801E1A69489C00A75B9A /* RCTTextField.m in Sources */, - 13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */, - 83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */, - 830A229E1A66C68A008503DA /* RCTRootView.m in Sources */, - 13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */, - 83CBBA5A1A601E9000E9B192 /* RCTRedBox.m in Sources */, - 83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */, - 832348161A77A5AA00B55238 /* Layout.c in Sources */, - 14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */, - 14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */, - 13B080201A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.m in Sources */, - 13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */, - 58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */, - 13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */, - 137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */, - 13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */, - 13B080051A6947C200A75B9A /* RCTScrollView.m in Sources */, - 13B07FF21A69327A00A75B9A /* RCTTiming.m in Sources */, - 13B0801F1A69489C00A75B9A /* RCTTextFieldManager.m in Sources */, - 134FCB3D1A6E7F0800051CC8 /* RCTContextExecutor.m in Sources */, - 13E067591A70F44B002CDEE1 /* UIView+ReactKit.m in Sources */, - 14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */, - 83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */, - 83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */, - 13B0801D1A69489C00A75B9A /* RCTNavItemManager.m in Sources */, - 13E067571A70F44B002CDEE1 /* RCTView.m in Sources */, - 137327E91AA5CF210034F82E /* RCTTabBarItemManager.m in Sources */, - 134FCB361A6D42D900051CC8 /* RCTSparseArray.m in Sources */, - 13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */, - 83CBBA531A601E3B00E9B192 /* RCTUtils.m in Sources */, - 83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */, - 137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */, - 13E067551A70F44B002CDEE1 /* RCTShadowView.m in Sources */, - 13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */, - 830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */, - 137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */, - 134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */, - 13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */, - 83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */, - 13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */, - 13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 83CBBA201A601CBA00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 83CBBA211A601CBA00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 83CBBA401A601D0F00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 83CBBA411A601D0F00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug */, - 83CBBA211A601CBA00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBBA3F1A601D0F00E9B192 /* Build configuration list for PBXNativeTarget "ReactKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA401A601D0F00E9B192 /* Debug */, - 83CBBA411A601D0F00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; -} diff --git a/ReactKit/Views/RCTAnimationType.h b/ReactKit/Views/RCTAnimationType.h deleted file mode 100644 index dae90b845f4..00000000000 --- a/ReactKit/Views/RCTAnimationType.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -typedef NS_ENUM(NSInteger, RCTAnimationType) { - RCTAnimationTypeSpring = 0, - RCTAnimationTypeLinear, - RCTAnimationTypeEaseIn, - RCTAnimationTypeEaseOut, - RCTAnimationTypeEaseInEaseOut, -}; diff --git a/ReactKit/Views/RCTAutoInsetsProtocol.h b/ReactKit/Views/RCTAutoInsetsProtocol.h deleted file mode 100644 index 4f1cd4ba20b..00000000000 --- a/ReactKit/Views/RCTAutoInsetsProtocol.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -/** - * Defines a View that wants to support auto insets adjustment - */ -@protocol RCTAutoInsetsProtocol - -@property (nonatomic, assign, readwrite) UIEdgeInsets contentInset; -@property (nonatomic, assign, readwrite) BOOL automaticallyAdjustContentInsets; - -@end diff --git a/ReactKit/Views/RCTDatePickerManager.h b/ReactKit/Views/RCTDatePickerManager.h deleted file mode 100644 index 65459b80cc4..00000000000 --- a/ReactKit/Views/RCTDatePickerManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTDatePickerManager : RCTViewManager - -@end diff --git a/ReactKit/Views/RCTDatePickerManager.m b/ReactKit/Views/RCTDatePickerManager.m deleted file mode 100644 index 39010214e79..00000000000 --- a/ReactKit/Views/RCTDatePickerManager.m +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTDatePickerManager.h" - -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "UIView+ReactKit.h" - -@implementation RCTDatePickerManager - -- (UIView *)view -{ - UIDatePicker *picker = [[UIDatePicker alloc] init]; - [picker addTarget:self - action:@selector(onChange:) - forControlEvents:UIControlEventValueChanged]; - return picker; -} - -RCT_EXPORT_VIEW_PROPERTY(date) -RCT_EXPORT_VIEW_PROPERTY(minimumDate) -RCT_EXPORT_VIEW_PROPERTY(maximumDate) -RCT_EXPORT_VIEW_PROPERTY(minuteInterval) -RCT_REMAP_VIEW_PROPERTY(mode, datePickerMode) -RCT_REMAP_VIEW_PROPERTY(timeZoneOffsetInMinutes, timeZone) - -- (void)onChange:(UIDatePicker *)sender -{ - NSDictionary *event = @{ - @"target": sender.reactTag, - @"timestamp": @([sender.date timeIntervalSince1970] * 1000.0) - }; - [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event]; -} - -- (NSDictionary *)constantsToExport -{ - UIDatePicker *dp = [[UIDatePicker alloc] init]; - return @{ - @"ComponentHeight": @(CGRectGetHeight(dp.frame)), - @"ComponentWidth": @(CGRectGetWidth(dp.frame)), - @"DatePickerModes": @{ - @"time": @(UIDatePickerModeTime), - @"date": @(UIDatePickerModeDate), - @"datetime": @(UIDatePickerModeDateAndTime), - } - }; -} - -@end diff --git a/ReactKit/Views/RCTNavItem.h b/ReactKit/Views/RCTNavItem.h deleted file mode 100644 index 68f12fd4560..00000000000 --- a/ReactKit/Views/RCTNavItem.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface RCTNavItem : UIView - -@property (nonatomic, copy) NSString *title; -@property (nonatomic, copy) NSString *rightButtonTitle; -@property (nonatomic, copy) NSString *backButtonTitle; -@property (nonatomic, copy) UIColor *tintColor; -@property (nonatomic, copy) UIColor *barTintColor; -@property (nonatomic, copy) UIColor *titleTextColor; - -@end diff --git a/ReactKit/Views/RCTNavItem.m b/ReactKit/Views/RCTNavItem.m deleted file mode 100644 index 191bfce1040..00000000000 --- a/ReactKit/Views/RCTNavItem.m +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTNavItem.h" - -@implementation RCTNavItem - -@end - diff --git a/ReactKit/Views/RCTNavItemManager.h b/ReactKit/Views/RCTNavItemManager.h deleted file mode 100644 index 3c2a3210571..00000000000 --- a/ReactKit/Views/RCTNavItemManager.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTNavItemManager : RCTViewManager - -@end - diff --git a/ReactKit/Views/RCTNavItemManager.m b/ReactKit/Views/RCTNavItemManager.m deleted file mode 100644 index 515b3437bda..00000000000 --- a/ReactKit/Views/RCTNavItemManager.m +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTNavItemManager.h" - -#import "RCTConvert.h" -#import "RCTNavItem.h" - -@implementation RCTNavItemManager - -- (UIView *)view -{ - return [[RCTNavItem alloc] init]; -} - -RCT_EXPORT_VIEW_PROPERTY(title) -RCT_EXPORT_VIEW_PROPERTY(rightButtonTitle); -RCT_EXPORT_VIEW_PROPERTY(backButtonTitle); -RCT_EXPORT_VIEW_PROPERTY(tintColor); -RCT_EXPORT_VIEW_PROPERTY(barTintColor); -RCT_EXPORT_VIEW_PROPERTY(titleTextColor); - -@end - diff --git a/ReactKit/Views/RCTNavigator.h b/ReactKit/Views/RCTNavigator.h deleted file mode 100644 index c9051c75387..00000000000 --- a/ReactKit/Views/RCTNavigator.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTInvalidating.h" - -@class RCTEventDispatcher; - -@interface RCTNavigator : UIView - -@property (nonatomic, strong) UIView *reactNavSuperviewLink; -@property (nonatomic, assign) NSInteger requestedTopOfStack; - -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; - -/** - * Schedules a JavaScript navigation and prevents `UIKit` from navigating until - * JavaScript has sent its scheduled navigation. - * - * @returns Whether or not a JavaScript driven navigation could be - * scheduled/reserved. If returning `NO`, JavaScript should usually just do - * nothing at all. - */ -- (BOOL)requestSchedulingJavaScriptNavigation; - -@end diff --git a/ReactKit/Views/RCTNavigator.m b/ReactKit/Views/RCTNavigator.m deleted file mode 100644 index 05306e809ce..00000000000 --- a/ReactKit/Views/RCTNavigator.m +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTNavigator.h" - -#import "RCTAssert.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTNavItem.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "RCTWrapperViewController.h" -#import "UIView+ReactKit.h" - -typedef NS_ENUM(NSUInteger, RCTNavigationLock) { - RCTNavigationLockNone, - RCTNavigationLockNative, - RCTNavigationLockJavaScript -}; - -NSInteger kNeverRequested = -1; -NSInteger kNeverProgressed = -10000; - - -@interface UINavigationController () - -// need to declare this since `UINavigationController` doesnt publicly declare the fact that it implements -// UINavigationBarDelegate :( -- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item; - -@end - -// http://stackoverflow.com/questions/5115135/uinavigationcontroller-how-to-cancel-the-back-button-event -// There's no other way to do this unfortunately :( -@interface RCTNavigationController : UINavigationController -{ - dispatch_block_t _scrollCallback; -} - -@property (nonatomic, assign) RCTNavigationLock navigationLock; - -@end - -/** - * In general, `RCTNavigator` examines `_currentViews` (which are React child - * views), and compares them to `_navigationController.viewControllers` (which - * are controlled by UIKit). - * - * It is possible for JavaScript (`_currentViews`) to "get ahead" of native - * (`navigationController.viewControllers`) and vice versa. JavaScript gets - * ahead by adding/removing React subviews. Native gets ahead by swiping back, - * or tapping the back button. In both cases, the other system is initially - * unaware. And in both cases, `RCTNavigator` helps the other side "catch up". - * - * If `RCTNavigator` sees the number of react children have changed, it - * pushes/pops accordingly. If `RCTNavigator` sees a `UIKit` driven push/pop, it - * notifies JavaScript that this has happened, and expects that JavaScript will - * eventually render more children to match `UIKit`. There's no rush for - * JavaScript to catch up. But if it does rener anything, it must catch up to - * UIKit. It cannot deviate. - * - * To implement this, we need a lock, which we store on the native thread. This - * lock allows one of the systems to push/pop views. Whoever wishes to - * "get ahead" must obtain the lock. Whoever wishes to "catch up" must obtain - * the lock. One thread may not "get ahead" or "catch up" when the other has - * the lock. Once a thread has the lock, it can only do the following: - * - * 1. If it is behind, it may only catch up. - * 2. If it is caught up or ahead, it may push or pop. - * - * - * ========= Acquiring The Lock ========== - * - * JavaScript asynchronously acquires the lock using a native hook. It might be - * rejected and receive the return value `false`. - * - * We acquire the native lock in `shouldPopItem`, which is called right before - * native tries to push/pop, but only if JavaScript doesn't already have the - * lock. - * - * ======== While JavaScript Has Lock ==== - * - * When JavaScript has the lock, we have to block all `UIKit` driven pops: - * - * 1. Block back button navigation: - * - Back button will invoke `shouldPopItem`, from which we return `NO` if - * JavaScript has the lock. - * - Back button will respect the return value `NO` and not permit - * navigation. - * - * 2. Block swipe-to-go-back navigation: - * - Swipe will trigger `shouldPopItem`, but swipe won't respect our `NO` - * return value so we must disable the gesture recognizer while JavaScript - * has the lock. - * - * ======== While Native Has Lock ======= - * - * We simply deny JavaScript the right to acquire the lock. - * - * - * ======== Releasing The Lock =========== - * - * Recall that the lock represents who has the right to either push/pop (or - * catch up). As soon as we recognize that the side that has locked has carried - * out what it scheduled to do, we can release the lock, but only after any - * possible animations are completed. - * - * *IF* a scheduled operation results in a push/pop (not all do), then we can - * only release the lock after the push/pop animation is complete because - * UIKit. `didMoveToNavigationController` is invoked when the view is done - * pushing/popping/animating. Native swipe-to-go-back interactions can be - * aborted, however, and you'll never see that method invoked. So just to cover - * that case, we also put an animation complete hook in - * `animateAlongsideTransition` to make sure we free the lock, in case the - * scheduled native push/pop never actually happened. - * - * For JavaScript: - * - When we see that JavaScript has "caught up" to `UIKit`, and no pushes/pops - * were needed, we can release the lock. - * - When we see that JavaScript requires *some* push/pop, it's not yet done - * carrying out what it scheduled to do. Just like with `UIKit` push/pops, we - * still have to wait for it to be done animating - * (`didMoveToNavigationController` is a suitable hook). - * - */ -@implementation RCTNavigationController - -/** - * @param callback Callback that is invoked when a "scroll" interaction begins - * so that `RCTNavigator` can notify `JavaScript`. - */ -- (instancetype)initWithScrollCallback:(dispatch_block_t)callback -{ - if ((self = [super initWithNibName:nil bundle:nil])) { - _scrollCallback = callback; - } - return self; -} - -/** - * Invoked when either a navigation item has been popped off, or when a - * swipe-back gesture has began. The swipe-back gesture doesn't respect the - * return value of this method. The back button does. That's why we have to - * completely disable the gesture recognizer for swipe-back while JS has the - * lock. - */ -- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item -{ - if (self.interactivePopGestureRecognizer.state == UIGestureRecognizerStateBegan) { - if (self.navigationLock == RCTNavigationLockNone) { - self.navigationLock = RCTNavigationLockNative; - if (_scrollCallback) { - _scrollCallback(); - } - } else if (self.navigationLock == RCTNavigationLockJavaScript) { - // This should never happen because we disable/enable the gesture - // recognizer when we lock the navigation. - RCTAssert(NO, @"Should never receive gesture start while JS locks navigator"); - } - } else { - if (self.navigationLock == RCTNavigationLockNone) { - // Must be coming from native interaction, lock it - it will be unlocked - // in `didMoveToNavigationController` - self.navigationLock = RCTNavigationLockNative; - if (_scrollCallback) { - _scrollCallback(); - } - } else if (self.navigationLock == RCTNavigationLockJavaScript) { - // This should only occur when JS has the lock, and - // - JS is driving the pop - // - Or the back button was pressed - // TODO: We actually want to disable the backbutton while JS has the - // lock, but it's not so easy. Even returning `NO` wont' work because it - // will also block JS driven pops. We simply need to disallow a standard - // back button, and instead use a custom one that tells JS to pop to - // length (`currentReactCount` - 1). - return [super navigationBar:navigationBar shouldPopItem:item]; - } - } - return [super navigationBar:navigationBar shouldPopItem:item]; -} - -@end - -@interface RCTNavigator() -{ - RCTEventDispatcher *_eventDispatcher; - NSInteger _numberOfViewControllerMovesToIgnore; -} - -@property (nonatomic, assign) NSInteger previousRequestedTopOfStack; - -// Previous views are only mainted in order to detect incorrect -// addition/removal of views below the `requestedTopOfStack` -@property (nonatomic, copy, readwrite) NSArray *previousViews; -@property (nonatomic, readwrite, strong) NSMutableArray *currentViews; -@property (nonatomic, readwrite, strong) RCTNavigationController *navigationController; -/** - * Display link is used to get high frequency sample rate during - * interaction/animation of view controller push/pop. - * - * - The run loop retains the displayLink. - * - `displayLink` retains its target. - * - We use `invalidate` to remove the `RCTNavigator`'s reference to the - * `displayLink` and remove the `displayLink` from the run loop. - * - * - * `displayLink`: - * -------------- - * - * - Even though we could implement the `displayLink` cleanup without the - * `invalidate` hook by adding and removing it from the run loop at the - * right times (begin/end animation), we need to account for the possibility - * that the view itself is destroyed mid-interaction. So we always keep it - * added to the run loop, but start/stop it with interactions/animations. We - * remove it from the run loop when the view will be destroyed by React. - * - * +----------+ +--------------+ - * | run loop o----strong--->| displayLink | - * +----------+ +--o-----------+ - * | ^ - * | | - * strong strong - * | | - * v | - * +---------o---+ - * | RCTNavigator | - * +-------------+ - * - * `dummyView`: - * ------------ - * There's no easy way to get a callback that fires when the position of a - * navigation item changes. The actual layers that are moved around during the - * navigation transition are private. Our only hope is to use - * `animateAlongsideTransition`, to set a dummy view's position to transition - * anywhere from -1.0 to 1.0. We later set up a `CADisplayLink` to poll the - * `presentationLayer` of that dummy view and report the value as a "progress" - * percentage. - * - * It was critical that we added the dummy view as a subview of the - * transitionCoordinator's `containerView`, otherwise the animations would not - * work correctly when reversing the gesture direction etc. This seems to be - * undocumented behavior/requirement. - * - */ -@property (nonatomic, readonly, assign) CGFloat mostRecentProgress; -@property (nonatomic, readwrite, strong) CADisplayLink *displayLink; -@property (nonatomic, readonly, strong) NSTimer *runTimer; -@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningFrom; -@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningTo; - -// Dummy view that we make animate with the same curve/interaction as the -// navigation animation/interaction. -@property (nonatomic, readonly, strong) UIView *dummyView; - -@end - -@implementation RCTNavigator - -- (id)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ - if ((self = [super initWithFrame:CGRectZero])) { - _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(reportNavigationProgress:)]; - _mostRecentProgress = kNeverProgressed; - _dummyView = [[UIView alloc] initWithFrame:CGRectZero]; - if (_displayLink) { - [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; - _displayLink.paused = YES; - } else { - // It's okay to leak this on a build bot. - RCTLogWarn(@"Failed to create a display link (probably on automated build system) - using an NSTimer for AppEngine instead."); - _runTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0) target:self selector:@selector(reportNavigationProgress:) userInfo:nil repeats:YES]; - } - _eventDispatcher = eventDispatcher; - _previousRequestedTopOfStack = kNeverRequested; // So that we initialize with a push. - _previousViews = @[]; - _currentViews = [[NSMutableArray alloc] initWithCapacity:0]; - __weak RCTNavigator *weakSelf = self; - _navigationController = [[RCTNavigationController alloc] initWithScrollCallback:^{ - [weakSelf dispatchFakeScrollEvent]; - }]; - _navigationController.delegate = self; - RCTAssert([self requestSchedulingJavaScriptNavigation], @"Could not acquire JS navigation lock on init"); - - [self addSubview:_navigationController.view]; - [_navigationController.view addSubview:_dummyView]; - } - return self; -} - -- (void)reportNavigationProgress:(CADisplayLink *)sender -{ - if (_currentlyTransitioningFrom != _currentlyTransitioningTo) { - UIView *topView = _dummyView; - id presentationLayer = [topView.layer presentationLayer]; - CGRect frame = [presentationLayer frame]; - CGFloat nextProgress = ABS(frame.origin.x); - // Don't want to spam the bridge, when the user holds their finger still mid-navigation. - if (nextProgress == _mostRecentProgress) { - return; - } - _mostRecentProgress = nextProgress; - [_eventDispatcher sendInputEventWithName:@"topNavigationProgress" body:@{ - @"fromIndex": @(_currentlyTransitioningFrom), - @"toIndex": @(_currentlyTransitioningTo), - @"progress": @(nextProgress), - @"target": self.reactTag - }]; - } -} - -- (void)dealloc -{ - _navigationController.delegate = nil; -} - -- (UIViewController *)backingViewController -{ - return _navigationController; -} - -/** - * See documentation about lock lifecycle. This is only here to clean up - * swipe-back abort interaction, which leaves us *no* other way to clean up - * locks aside from the animation complete hook. - */ -- (void)navigationController:(UINavigationController *)navigationController - willShowViewController:(UIViewController *)viewController - animated:(BOOL)animated -{ - id tc = - navigationController.topViewController.transitionCoordinator; - __weak RCTNavigator *weakSelf = self; - [tc.containerView addSubview: _dummyView]; - [tc animateAlongsideTransition: ^(id context) { - RCTWrapperViewController *fromController = - (RCTWrapperViewController *)[context viewControllerForKey:UITransitionContextFromViewControllerKey]; - RCTWrapperViewController *toController = - (RCTWrapperViewController *)[context viewControllerForKey:UITransitionContextToViewControllerKey]; - NSUInteger indexOfFrom = [_currentViews indexOfObject:fromController.navItem]; - NSUInteger indexOfTo = [_currentViews indexOfObject:toController.navItem]; - CGFloat destination = indexOfFrom < indexOfTo ? 1.0 : -1.0; - _dummyView.frame = (CGRect){{destination}}; - _currentlyTransitioningFrom = indexOfFrom; - _currentlyTransitioningTo = indexOfTo; - if (indexOfFrom != indexOfTo) { - _displayLink.paused = NO; - } - } - completion:^(id context) { - [weakSelf freeLock]; - _currentlyTransitioningFrom = 0; - _currentlyTransitioningTo = 0; - _dummyView.frame = CGRectZero; - _displayLink.paused = YES; - // Reset the parallel position tracker - }]; -} - -- (BOOL)requestSchedulingJavaScriptNavigation -{ - if (_navigationController.navigationLock == RCTNavigationLockNone) { - _navigationController.navigationLock = RCTNavigationLockJavaScript; - _navigationController.interactivePopGestureRecognizer.enabled = NO; - return YES; - } - return NO; -} - -- (void)freeLock -{ - _navigationController.navigationLock = RCTNavigationLockNone; - _navigationController.interactivePopGestureRecognizer.enabled = YES; -} - -/** - * A React subview can be inserted/removed at any time, however if the - * `requestedTopOfStack` changes, there had better be enough subviews present - * to satisfy the push/pop. - */ -- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex -{ - RCTAssert([view isKindOfClass:[RCTNavItem class]], @"RCTNavigator only accepts RCTNavItem subviews"); - RCTAssert( - _navigationController.navigationLock == RCTNavigationLockJavaScript, - @"Cannot change subviews from JS without first locking." - ); - [_currentViews insertObject:view atIndex:atIndex]; -} - -- (NSArray *)reactSubviews -{ - return _currentViews; -} - -- (BOOL)isValid -{ - return _displayLink != nil; -} - -- (void)invalidate -{ - // Prevent displayLink from retaining the navigator indefinitely - [_displayLink invalidate]; - _displayLink = nil; - _runTimer = nil; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - _navigationController.view.frame = self.bounds; -} - -- (void)removeReactSubview:(UIView *)subview -{ - if (_currentViews.count <= 0 || subview == _currentViews[0]) { - RCTLogError(@"Attempting to remove invalid RCT subview of RCTNavigator"); - return; - } - [_currentViews removeObject:subview]; -} - -- (void)handleTopOfStackChanged -{ - [_eventDispatcher sendInputEventWithName:@"topNavigateBack" body:@{ - @"target":self.reactTag, - @"stackLength":@(_navigationController.viewControllers.count) - }]; -} - -- (void)dispatchFakeScrollEvent -{ - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove - reactTag:self.reactTag - scrollView:nil - userData:nil]; -} - -/** - * Must be overridden because UIKit removes the view's superview when used - * as a navigator - it's considered outside the view hierarchy. - */ -- (UIView *)reactSuperview -{ - RCTAssert(self.superview != nil, @"put reactNavSuperviewLink back"); - return self.superview ? self.superview : self.reactNavSuperviewLink; -} - -- (void)reactBridgeDidFinishTransaction -{ - // we can't hook up the VC hierarchy in 'init' because the subviews aren't - // hooked up yet, so we do it on demand here - [self addControllerToClosestParent:_navigationController]; - - NSInteger viewControllerCount = _navigationController.viewControllers.count; - // The "react count" is the count of views that are visible on the navigation - // stack. There may be more beyond this - that aren't visible, and may be - // deleted/purged soon. - NSInteger previousReactCount = - _previousRequestedTopOfStack == kNeverRequested ? 0 : _previousRequestedTopOfStack + 1; - NSInteger currentReactCount = _requestedTopOfStack + 1; - - BOOL jsGettingAhead = - // ----- previously caught up ------ ------ no longer caught up ------- - viewControllerCount == previousReactCount && currentReactCount != viewControllerCount; - BOOL jsCatchingUp = - // --- previously not caught up ---- --------- now caught up ---------- - viewControllerCount != previousReactCount && currentReactCount == viewControllerCount; - BOOL jsMakingNoProgressButNeedsToCatchUp = - // --- previously not caught up ---- ------- still the same ----------- - viewControllerCount != previousReactCount && currentReactCount == previousReactCount; - BOOL jsMakingNoProgressAndDoesntNeedTo = - // --- previously caught up -------- ------- still caught up ---------- - viewControllerCount == previousReactCount && currentReactCount == previousReactCount; - - BOOL reactPushOne = jsGettingAhead && currentReactCount == previousReactCount + 1; - BOOL reactPopN = jsGettingAhead && currentReactCount < previousReactCount; - - // We can actually recover from this situation, but it would be nice to know - // when this error happens. This simply means that JS hasn't caught up to a - // back navigation before progressing. It's likely a bug in the JS code that - // catches up/schedules navigations. Eventually, let's recover from this - // error state, but in the mean time, let's get notified about any JS bugs. - RCTAssert( - jsGettingAhead || - jsCatchingUp || - jsMakingNoProgressButNeedsToCatchUp || - jsMakingNoProgressAndDoesntNeedTo, - @"JS has only made partial progress to catch up to UIKit" - ); - NSAssert( - currentReactCount <= _currentViews.count, - @"Cannot adjust current top of stack beyond available views" - ); - - // Views before the previous react count must not have changed. Views greater than previousReactCount - // up to currentReactCount may have changed. - for (NSInteger i = 0; i < MIN(_currentViews.count, MIN(_previousViews.count, previousReactCount)); i++) { - NSAssert(_currentViews[i] == _previousViews[i], @"current view should equal previous view"); - } - RCTAssert(currentReactCount >= 1, @"should be at least one current view"); - if (jsGettingAhead) { - if (reactPushOne) { - UIView *lastView = [_currentViews lastObject]; - RCTWrapperViewController *vc = [[RCTWrapperViewController alloc] initWithNavItem:(RCTNavItem *)lastView eventDispatcher:_eventDispatcher]; - vc.navigationListener = self; - _numberOfViewControllerMovesToIgnore = 1; - [_navigationController pushViewController:vc animated:(currentReactCount > 1)]; - } else if (reactPopN) { - UIViewController *viewControllerToPopTo = [[_navigationController viewControllers] objectAtIndex:(currentReactCount - 1)]; - _numberOfViewControllerMovesToIgnore = viewControllerCount - currentReactCount; - [_navigationController popToViewController:viewControllerToPopTo animated:YES]; - } else { - RCTAssert(NO, @"Pushing or popping more than one view at a time from JS"); - } - } else if (jsCatchingUp) { - [self freeLock]; // Nothing to push/pop - } else { - // Else, JS making no progress, could have been unrelated to anything nav. - return; - } - - _previousViews = [_currentViews copy]; - _previousRequestedTopOfStack = _requestedTopOfStack; -} - -// TODO: This will likely fail when performing multiple pushes/pops. We must -// free the lock only after the *last* push/pop. -- (void)wrapperViewController:(RCTWrapperViewController *)wrapperViewController -didMoveToNavigationController:(UINavigationController *)navigationController -{ - if (self.superview == nil) { - // If superview is nil, then a JS reload (Cmd+R) happened - // while a push/pop is in progress. - return; - } - - RCTAssert( - (navigationController == nil || [_navigationController.viewControllers containsObject:wrapperViewController]), - @"if navigation controller is not nil, it should container the wrapper view controller" - ); - RCTAssert(_navigationController.navigationLock == RCTNavigationLockJavaScript || - _numberOfViewControllerMovesToIgnore == 0, - @"If JS doesn't have the lock there should never be any pending transitions"); - /** - * When JS has the lock we want to keep track of when the request completes - * the pending transition count hitting 0 signifies this, and should always - * remain at 0 when JS does not have the lock - */ - if (_numberOfViewControllerMovesToIgnore > 0) { - _numberOfViewControllerMovesToIgnore -= 1; - } - if (_numberOfViewControllerMovesToIgnore == 0) { - [self handleTopOfStackChanged]; - [self freeLock]; - } -} - -@end diff --git a/ReactKit/Views/RCTNavigatorManager.h b/ReactKit/Views/RCTNavigatorManager.h deleted file mode 100644 index d32d21096e2..00000000000 --- a/ReactKit/Views/RCTNavigatorManager.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTNavigatorManager : RCTViewManager - -@end - diff --git a/ReactKit/Views/RCTNavigatorManager.m b/ReactKit/Views/RCTNavigatorManager.m deleted file mode 100644 index 85004471b1e..00000000000 --- a/ReactKit/Views/RCTNavigatorManager.m +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTNavigatorManager.h" - -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTNavigator.h" -#import "RCTSparseArray.h" -#import "RCTUIManager.h" - -@implementation RCTNavigatorManager - -- (UIView *)view -{ - return [[RCTNavigator alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; -} - -RCT_EXPORT_VIEW_PROPERTY(requestedTopOfStack) - -- (NSDictionary *)customDirectEventTypes -{ - return @{ - @"topNavigationProgress": @{ - @"registrationName": @"onNavigationProgress" - }, - }; -} - -// TODO: remove error callbacks -- (void)requestSchedulingJavaScriptNavigation:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(__unused RCTResponseSenderBlock)callback -{ - RCT_EXPORT(); - - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ - RCTNavigator *navigator = viewRegistry[reactTag]; - if ([navigator isKindOfClass:[RCTNavigator class]]) { - BOOL wasAcquired = [navigator requestSchedulingJavaScriptNavigation]; - callback(@[@(wasAcquired)]); - } else { - RCTLogError(@"Cannot set lock: %@ (tag #%@) is not an RCTNavigator", navigator, reactTag); - } - }]; -} - -@end diff --git a/ReactKit/Views/RCTPointerEvents.h b/ReactKit/Views/RCTPointerEvents.h deleted file mode 100644 index 522bcce4c46..00000000000 --- a/ReactKit/Views/RCTPointerEvents.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -typedef NS_ENUM(NSInteger, RCTPointerEvents) { - RCTPointerEventsUnspecified = 0, // Default - RCTPointerEventsNone, - RCTPointerEventsBoxNone, - RCTPointerEventsBoxOnly, -}; diff --git a/ReactKit/Views/RCTScrollView.h b/ReactKit/Views/RCTScrollView.h deleted file mode 100644 index 204ddf49414..00000000000 --- a/ReactKit/Views/RCTScrollView.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTAutoInsetsProtocol.h" -#import "RCTScrollableProtocol.h" -#import "RCTView.h" - -@protocol UIScrollViewDelegate; - -@class RCTEventDispatcher; - -@interface RCTScrollView : RCTView - -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; - -/** - * If the `contentSize` is not provided, then the `contentSize` will - * automatically be determined by the size of the `RKScrollView` subview. - * - * The `RCTScrollView` may have at most one single subview. This will ensure - * that the scroll view's `contentSize` will be efficiently set to the size of - * the single subview's frame. That frame size will be determined somewhat - * efficiently since it will have already been computed by the off-main-thread - * layout system. - */ -@property (nonatomic, readonly) UIScrollView *scrollView; -@property (nonatomic, readonly) UIView *contentView; - -@property (nonatomic, assign) CGSize contentSize; -@property (nonatomic, assign) UIEdgeInsets contentInset; -@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; -@property (nonatomic, assign) NSUInteger throttleScrollCallbackMS; -@property (nonatomic, assign) BOOL centerContent; -@property (nonatomic, copy) NSArray *stickyHeaderIndices; - -@end diff --git a/ReactKit/Views/RCTScrollView.m b/ReactKit/Views/RCTScrollView.m deleted file mode 100644 index bd03d45de9f..00000000000 --- a/ReactKit/Views/RCTScrollView.m +++ /dev/null @@ -1,592 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTScrollView.h" - -#import - -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTUIManager.h" -#import "RCTUtils.h" -#import "UIView+ReactKit.h" - -CGFloat const ZINDEX_DEFAULT = 0; -CGFloat const ZINDEX_STICKY_HEADER = 50; - -/** - * Include a custom scroll view subclass because we want to limit certain - * default UIKit behaviors such as textFields automatically scrolling - * scroll views that contain them and support sticky headers. - */ -@interface RCTCustomScrollView : UIScrollView - -@property (nonatomic, copy, readwrite) NSArray *stickyHeaderIndices; -@property (nonatomic, readwrite, assign) BOOL centerContent; - -@end - - -@implementation RCTCustomScrollView - -- (instancetype)initWithFrame:(CGRect)frame -{ - if ((self = [super initWithFrame:frame])) { - [self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)]; - } - return self; -} - -- (UIView *)contentView -{ - return ((RCTScrollView *)self.superview).contentView; -} - -/** - * @return Whether or not the scroll view interaction should be blocked because - * JS was found to be the responder. - */ -- (BOOL)_shouldDisableScrollInteraction -{ - // Since this may be called on every pan, we need to make sure to only climb - // the hierarchy on rare occasions. - UIView *JSResponder = [RCTUIManager JSResponder]; - if (JSResponder && JSResponder != self.superview) { - BOOL superviewHasResponder = [self isDescendantOfView:JSResponder]; - return superviewHasResponder; - } - return NO; -} - -- (void)handleCustomPan:(UIPanGestureRecognizer *)sender -{ - if ([self _shouldDisableScrollInteraction]) { - self.panGestureRecognizer.enabled = NO; - self.panGestureRecognizer.enabled = YES; - // TODO: If mid bounce, animate the scroll view to a non-bounced position - // while disabling (but only if `stopScrollInteractionIfJSHasResponder` was - // called *during* a `pan`. Currently, it will just snap into place which - // is not so bad either. - // Another approach: - // self.scrollEnabled = NO; - // self.scrollEnabled = YES; - } -} - -- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated -{ - // noop -} - -/** - * Returning `YES` cancels touches for the "inner" `view` and causes a scroll. - * Returning `NO` causes touches to be directed to that inner view and prevents - * the scroll view from scrolling. - * - * `YES` -> Allows scrolling. - * `NO` -> Doesn't allow scrolling. - * - * By default this returns NO for all views that are UIControls and YES for - * everything else. What that does is allows scroll views to scroll even when a - * touch started inside of a `UIControl` (`UIButton` etc). For React scroll - * views, we want the default to be the same behavior as `UIControl`s so we - * return `YES` by default. But there's one case where we want to block the - * scrolling no matter what: When JS believes it has its own responder lock on - * a view that is *above* the scroll view in the hierarchy. So we abuse this - * `touchesShouldCancelInContentView` API in order to stop the scroll view from - * scrolling in this case. - * - * We are not aware of *any* other solution to the problem because alternative - * approaches require that we disable the scrollview *before* touches begin or - * move. This approach (`touchesShouldCancelInContentView`) works even if the - * JS responder is set after touches start/move because - * `touchesShouldCancelInContentView` is called as soon as the scroll view has - * been touched and dragged *just* far enough to decide to begin the "drag" - * movement of the scroll interaction. Returning `NO`, will cause the drag - * operation to fail. - * - * `touchesShouldCancelInContentView` will stop the *initialization* of a - * scroll pan gesture and most of the time this is sufficient. On rare - * occasion, the scroll gesture would have already initialized right before JS - * notifies native of the JS responder being set. In order to recover from that - * timing issue we have a fallback that kills any ongoing pan gesture that - * occurs when native is notified of a JS responder. - * - * Note: Explicitly returning `YES`, instead of relying on the default fixes - * (at least) one bug where if you have a UIControl inside a UIScrollView and - * tap on the UIControl and then start dragging (to scroll), it won't scroll. - * Chat with andras for more details. - * - * In order to have this called, you must have delaysContentTouches set to NO - * (which is the not the `UIKit` default). - */ -- (BOOL)touchesShouldCancelInContentView:(UIView *)view -{ - //TODO: shouldn't this call super if _shouldDisableScrollInteraction returns NO? - return ![self _shouldDisableScrollInteraction]; -} - -/* - * Automatically centers the content such that if the content is smaller than the - * ScrollView, we force it to be centered, but when you zoom or the content otherwise - * becomes larger than the ScrollView, there is no padding around the content but it - * can still fill the whole view. - */ -- (void)setContentOffset:(CGPoint)contentOffset -{ - UIView *contentView = [self contentView]; - if (contentView && _centerContent) { - CGSize subviewSize = contentView.frame.size; - CGSize scrollViewSize = self.bounds.size; - if (subviewSize.width < scrollViewSize.width) { - contentOffset.x = -(scrollViewSize.width - subviewSize.width) / 2.0; - } - if (subviewSize.height < scrollViewSize.height) { - contentOffset.y = -(scrollViewSize.height - subviewSize.height) / 2.0; - } - } - [super setContentOffset:contentOffset]; -} - -- (void)setBounds:(CGRect)bounds -{ - [super setBounds:bounds]; - [self dockClosestSectionHeader]; -} - -- (void)dockClosestSectionHeader -{ - UIView *contentView = [self contentView]; - if (_stickyHeaderIndices.count == 0 || !contentView) { - return; - } - - // find the section header that needs to be docked - NSInteger firstIndexInView = [[_stickyHeaderIndices firstObject] integerValue] + 1; - CGRect scrollBounds = self.bounds; - scrollBounds.origin.x += self.contentInset.left; - scrollBounds.origin.y += self.contentInset.top; - - NSInteger i = 0; - for (UIView *subview in contentView.subviews) { - CGRect rowFrame = [RCTCustomScrollView _calculateUntransformedFrame:subview]; - if (CGRectIntersectsRect(scrollBounds, rowFrame)) { - firstIndexInView = i; - break; - } - i++; - } - NSInteger stickyHeaderii = 0; - for (NSNumber *stickyHeaderI in _stickyHeaderIndices) { - if ([stickyHeaderI integerValue] > firstIndexInView) { - break; - } - stickyHeaderii++; - } - stickyHeaderii = MAX(0, stickyHeaderii - 1); - - // Set up transforms for the various section headers - NSInteger currentlyDockedIndex = [_stickyHeaderIndices[stickyHeaderii] integerValue]; - NSInteger previouslyDockedIndex = stickyHeaderii > 0 ? [_stickyHeaderIndices[stickyHeaderii-1] integerValue] : -1; - NSInteger nextDockedIndex = (stickyHeaderii < _stickyHeaderIndices.count - 1) ? - [_stickyHeaderIndices[stickyHeaderii + 1] integerValue] : -1; - - UIView *currentHeader = contentView.subviews[currentlyDockedIndex]; - UIView *previousHeader = previouslyDockedIndex >= 0 ? contentView.subviews[previouslyDockedIndex] : nil; - CGRect curFrame = [RCTCustomScrollView _calculateUntransformedFrame:currentHeader]; - - if (previousHeader) { - // the previous header is offset to sit right above the currentlyDockedHeader's initial position - // (so it scrolls away nicely once the currentHeader locks into position) - CGRect previousFrame = [RCTCustomScrollView _calculateUntransformedFrame:previousHeader]; - CGFloat yOffset = curFrame.origin.y - previousFrame.origin.y - previousFrame.size.height; - previousHeader.transform = CGAffineTransformMakeTranslation(0, yOffset); - } - - UIView *nextHeader = nextDockedIndex >= 0 ? contentView.subviews[nextDockedIndex] : nil; - CGRect nextFrame = [RCTCustomScrollView _calculateUntransformedFrame:nextHeader]; - - if (curFrame.origin.y < scrollBounds.origin.y) { - // scrolled off (or being scrolled off) the top of the screen - CGFloat yOffset = 0; - if (nextHeader && nextFrame.origin.y < scrollBounds.origin.y + curFrame.size.height) { - // next frame is bumping me off if scrolling down (or i'm bumping the next one off if scrolling up) - yOffset = nextFrame.origin.y - curFrame.origin.y - curFrame.size.height; - } else { - // standard sticky header position - yOffset = scrollBounds.origin.y - curFrame.origin.y; - } - currentHeader.transform = CGAffineTransformMakeTranslation(0, yOffset); - currentHeader.layer.zPosition = ZINDEX_STICKY_HEADER; - } else { - // i'm the current header but in the viewport, so just scroll in normal position - currentHeader.transform = CGAffineTransformIdentity; - currentHeader.layer.zPosition = ZINDEX_DEFAULT; - } - - // in our setup, 'next header' will always just scroll with the page - if (nextHeader) { - nextHeader.transform = CGAffineTransformIdentity; - nextHeader.layer.zPosition = ZINDEX_DEFAULT; - } -} - -+ (CGRect)_calculateUntransformedFrame:(UIView *)view -{ - CGRect frame = CGRectNull; - if (view) { - frame.size = view.bounds.size; - frame.origin = CGPointMake(view.layer.position.x - view.bounds.size.width * view.layer.anchorPoint.x, view.layer.position.y - view.bounds.size.height * view.layer.anchorPoint.y); - } - return frame; -} - -@end - -@implementation RCTScrollView -{ - RCTEventDispatcher *_eventDispatcher; - BOOL _contentSizeManuallySet; - RCTCustomScrollView *_scrollView; - UIView *_contentView; - NSTimeInterval _lastScrollDispatchTime; - NSMutableArray *_cachedChildFrames; - BOOL _allowNextScrollNoMatterWhat; -} - -@synthesize nativeMainScrollDelegate = _nativeMainScrollDelegate; - -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ - if ((self = [super initWithFrame:CGRectZero])) { - - _eventDispatcher = eventDispatcher; - _scrollView = [[RCTCustomScrollView alloc] initWithFrame:CGRectZero]; - _scrollView.delegate = self; - _scrollView.delaysContentTouches = NO; - _automaticallyAdjustContentInsets = YES; - _contentInset = UIEdgeInsetsZero; - - _throttleScrollCallbackMS = 0; - _lastScrollDispatchTime = CACurrentMediaTime(); - _cachedChildFrames = [[NSMutableArray alloc] init]; - - [self addSubview:_scrollView]; - } - return self; -} - -- (void)setRemoveClippedSubviews:(__unused BOOL)removeClippedSubviews -{ - // Does nothing -} - -- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex -{ - RCTAssert(_contentView == nil, @"RCTScrollView may only contain a single subview"); - _contentView = view; - [_scrollView addSubview:view]; -} - -- (void)removeReactSubview:(UIView *)subview -{ - RCTAssert(_contentView == subview, @"Attempted to remove non-existent subview"); - _contentView = nil; - [subview removeFromSuperview]; -} - -- (NSArray *)reactSubviews -{ - return _contentView ? @[_contentView] : @[]; -} - -- (void)setCenterContent:(BOOL)centerContent -{ - _scrollView.centerContent = centerContent; -} - -- (void)setStickyHeaderIndices:(NSArray *)headerIndices -{ - RCTAssert(_scrollView.contentSize.width <= self.frame.size.width, - @"sticky headers are not supported with horizontal scrolled views"); - _scrollView.stickyHeaderIndices = headerIndices; -} - -/** - * Once you set the `contentSize`, it's assumed to be managed by you forever - * and we'll never automatically compute the size for you. - */ -- (void)setContentSize:(CGSize)contentSize -{ - _contentSize = contentSize; - _contentSizeManuallySet = YES; -} - -- (void)dealloc -{ - _scrollView.delegate = nil; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - RCTAssert(self.subviews.count == 1, @"we should only have exactly one subview"); - RCTAssert([self.subviews lastObject] == _scrollView, @"our only subview should be a scrollview"); - _scrollView.frame = self.bounds; - - [RCTView autoAdjustInsetsForView:self - withScrollView:_scrollView - updateOffset:YES]; -} - -- (void)setContentInset:(UIEdgeInsets)contentInset -{ - _contentInset = contentInset; - [RCTView autoAdjustInsetsForView:self - withScrollView:_scrollView - updateOffset:NO]; -} - -- (void)scrollToOffset:(CGPoint)offset -{ - [self scrollToOffset:offset animated:YES]; -} - -- (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated -{ - if (!CGPointEqualToPoint(_scrollView.contentOffset, offset)) { - [_scrollView setContentOffset:offset animated:animated]; - } -} - -- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated -{ - [_scrollView zoomToRect:rect animated:animated]; -} - -#pragma mark - ScrollView delegate - -#define RCT_SCROLL_EVENT_HANDLER(delegateMethod, eventName) \ -- (void)delegateMethod:(UIScrollView *)scrollView \ -{ \ - [_eventDispatcher sendScrollEventWithType:eventName reactTag:self.reactTag scrollView:scrollView userData:nil]; \ - if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \ - [_nativeMainScrollDelegate delegateMethod:scrollView]; \ - } \ -} - -#define RCT_FORWARD_SCROLL_EVENT(call) \ -if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \ - [_nativeMainScrollDelegate call]; \ -} - -RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndScrollingAnimation, RCTScrollEventTypeEndDeceleration) -RCT_SCROLL_EVENT_HANDLER(scrollViewWillBeginDecelerating, RCTScrollEventTypeStartDeceleration) -RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndDecelerating, RCTScrollEventTypeEndDeceleration) -RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove) - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - NSTimeInterval now = CACurrentMediaTime(); - NSTimeInterval throttleScrollCallbackSeconds = _throttleScrollCallbackMS / 1000.0; - - /** - * TODO: this logic looks wrong, and it may be because it is. Currently, if _throttleScrollCallbackMS - * is set to zero (the default), the "didScroll" event is only sent once per scroll, instead of repeatedly - * while scrolling as expected. However, if you "fix" that bug, ScrollView will generate repeated - * warnings, and behave strangely (ListView works fine however), so don't fix it unless you fix that too! - */ - if (_allowNextScrollNoMatterWhat || - (_throttleScrollCallbackMS != 0 && throttleScrollCallbackSeconds < (now - _lastScrollDispatchTime))) { - - // Calculate changed frames - NSMutableArray *updatedChildFrames = [[NSMutableArray alloc] init]; - [[_contentView reactSubviews] enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { - - // Check if new or changed - CGRect newFrame = subview.frame; - BOOL frameChanged = NO; - if (_cachedChildFrames.count <= idx) { - frameChanged = YES; - [_cachedChildFrames addObject:[NSValue valueWithCGRect:newFrame]]; - } else if (!CGRectEqualToRect(newFrame, [_cachedChildFrames[idx] CGRectValue])) { - frameChanged = YES; - _cachedChildFrames[idx] = [NSValue valueWithCGRect:newFrame]; - } - - // Create JS frame object - if (frameChanged) { - [updatedChildFrames addObject: @{ - @"index": @(idx), - @"x": @(newFrame.origin.x), - @"y": @(newFrame.origin.y), - @"width": @(newFrame.size.width), - @"height": @(newFrame.size.height), - }]; - } - - }]; - - // If there are new frames, add them to event data - NSDictionary *userData = nil; - if (updatedChildFrames.count > 0) { - userData = @{@"updatedChildFrames": updatedChildFrames}; - } - - // Dispatch event - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove - reactTag:self.reactTag - scrollView:scrollView - userData:userData]; - // Update dispatch time - _lastScrollDispatchTime = now; - _allowNextScrollNoMatterWhat = NO; - } - RCT_FORWARD_SCROLL_EVENT(scrollViewDidScroll:scrollView); -} - -- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView -{ - _allowNextScrollNoMatterWhat = YES; // Ensure next scroll event is recorded, regardless of throttle - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeStart reactTag:self.reactTag scrollView:scrollView userData:nil]; - RCT_FORWARD_SCROLL_EVENT(scrollViewWillBeginDragging:scrollView); -} - -- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset -{ - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil]; - RCT_FORWARD_SCROLL_EVENT(scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset); -} - -- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate -{ - RCT_FORWARD_SCROLL_EVENT(scrollViewDidEndDragging:scrollView willDecelerate:decelerate); -} - -- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view -{ - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeStart reactTag:self.reactTag scrollView:scrollView userData:nil]; - RCT_FORWARD_SCROLL_EVENT(scrollViewWillBeginZooming:scrollView withView:view); -} - -- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale -{ - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil]; - RCT_FORWARD_SCROLL_EVENT(scrollViewDidEndZooming:scrollView withView:view atScale:scale); -} - -- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView -{ - if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { - return [_nativeMainScrollDelegate scrollViewShouldScrollToTop:scrollView]; - } - return YES; -} - -- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView -{ - return _contentView; -} - -#pragma mark - Setters - -- (CGSize)_calculateViewportSize -{ - CGSize viewportSize = self.bounds.size; - if (_automaticallyAdjustContentInsets) { - UIEdgeInsets contentInsets = [RCTView contentInsetsForView:self]; - viewportSize = CGSizeMake(self.bounds.size.width - contentInsets.left - contentInsets.right, - self.bounds.size.height - contentInsets.top - contentInsets.bottom); - } - return viewportSize; -} - -- (CGPoint)calculateOffsetForContentSize:(CGSize)newContentSize -{ - CGPoint oldOffset = _scrollView.contentOffset; - CGPoint newOffset = oldOffset; - - CGSize oldContentSize = _scrollView.contentSize; - CGSize viewportSize = [self _calculateViewportSize]; - - BOOL fitsinViewportY = oldContentSize.height <= viewportSize.height && newContentSize.height <= viewportSize.height; - if (newContentSize.height < oldContentSize.height && !fitsinViewportY) { - CGFloat offsetHeight = oldOffset.y + viewportSize.height; - if (oldOffset.y < 0) { - // overscrolled on top, leave offset alone - } else if (offsetHeight > oldContentSize.height) { - // overscrolled on the bottom, preserve overscroll amount - newOffset.y = MAX(0, oldOffset.y - (oldContentSize.height - newContentSize.height)); - } else if (offsetHeight > newContentSize.height) { - // offset falls outside of bounds, scroll back to end of list - newOffset.y = MAX(0, newContentSize.height - viewportSize.height); - } - } - - BOOL fitsinViewportX = oldContentSize.width <= viewportSize.width && newContentSize.width <= viewportSize.width; - if (newContentSize.width < oldContentSize.width && !fitsinViewportX) { - CGFloat offsetHeight = oldOffset.x + viewportSize.width; - if (oldOffset.x < 0) { - // overscrolled at the beginning, leave offset alone - } else if (offsetHeight > oldContentSize.width && newContentSize.width > viewportSize.width) { - // overscrolled at the end, preserve overscroll amount as much as possible - newOffset.x = MAX(0, oldOffset.x - (oldContentSize.width - newContentSize.width)); - } else if (offsetHeight > newContentSize.width) { - // offset falls outside of bounds, scroll back to end - newOffset.x = MAX(0, newContentSize.width - viewportSize.width); - } - } - - // all other cases, offset doesn't change - return newOffset; -} - -- (void)reactBridgeDidFinishTransaction -{ - if (_contentSizeManuallySet) { - _scrollView.contentSize = _contentSize; - } else if (!_contentView) { - _scrollView.contentSize = CGSizeZero; - } else { - CGSize singleSubviewSize = _contentView.frame.size; - CGPoint singleSubviewPosition = _contentView.frame.origin; - CGSize fittedSize = { - singleSubviewSize.width + singleSubviewPosition.x, - singleSubviewSize.height + singleSubviewPosition.y - }; - if (!CGSizeEqualToSize(_scrollView.contentSize, fittedSize)) { - // When contentSize is set manually, ScrollView internals will reset contentOffset to 0,0. Since - // we potentially set contentSize whenever anything in the ScrollView updates, we workaround this - // issue by manually adjusting contentOffset whenever this happens - CGPoint newOffset = [self calculateOffsetForContentSize:fittedSize]; - _scrollView.contentSize = fittedSize; - _scrollView.contentOffset = newOffset; - } - [_scrollView dockClosestSectionHeader]; - } -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - if ([super respondsToSelector:aSelector]) { - return YES; - } - if ([NSStringFromSelector(aSelector) hasPrefix:@"set"]) { - return [_scrollView respondsToSelector:aSelector]; - } - return NO; -} - -- (void)setValue:(id)value forUndefinedKey:(NSString *)key -{ - // Pipe unrecognized properties to scrollview - [_scrollView setValue:value forKey:key]; -} - -- (id)valueForUndefinedKey:(NSString *)key -{ - // Pipe unrecognized properties from scrollview - return [_scrollView valueForKey:key]; -} - -@end diff --git a/ReactKit/Views/RCTScrollViewManager.h b/ReactKit/Views/RCTScrollViewManager.h deleted file mode 100644 index 835e1c3226a..00000000000 --- a/ReactKit/Views/RCTScrollViewManager.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTScrollViewManager : RCTViewManager - -@end - diff --git a/ReactKit/Views/RCTScrollViewManager.m b/ReactKit/Views/RCTScrollViewManager.m deleted file mode 100644 index 6247dadb688..00000000000 --- a/ReactKit/Views/RCTScrollViewManager.m +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTScrollViewManager.h" - -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTScrollView.h" - -@implementation RCTScrollViewManager - -- (UIView *)view -{ - return [[RCTScrollView alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; -} - -RCT_EXPORT_VIEW_PROPERTY(alwaysBounceHorizontal) -RCT_EXPORT_VIEW_PROPERTY(alwaysBounceVertical) -RCT_EXPORT_VIEW_PROPERTY(bounces) -RCT_EXPORT_VIEW_PROPERTY(bouncesZoom) -RCT_EXPORT_VIEW_PROPERTY(canCancelContentTouches) -RCT_EXPORT_VIEW_PROPERTY(centerContent) -RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets) -RCT_EXPORT_VIEW_PROPERTY(decelerationRate) -RCT_EXPORT_VIEW_PROPERTY(directionalLockEnabled) -RCT_EXPORT_VIEW_PROPERTY(keyboardDismissMode) -RCT_EXPORT_VIEW_PROPERTY(maximumZoomScale) -RCT_EXPORT_VIEW_PROPERTY(minimumZoomScale) -RCT_EXPORT_VIEW_PROPERTY(pagingEnabled) -RCT_EXPORT_VIEW_PROPERTY(scrollEnabled) -RCT_EXPORT_VIEW_PROPERTY(scrollsToTop) -RCT_EXPORT_VIEW_PROPERTY(showsHorizontalScrollIndicator) -RCT_EXPORT_VIEW_PROPERTY(showsVerticalScrollIndicator) -RCT_EXPORT_VIEW_PROPERTY(stickyHeaderIndices); -RCT_EXPORT_VIEW_PROPERTY(throttleScrollCallbackMS); -RCT_EXPORT_VIEW_PROPERTY(zoomScale); // TODO: this needs to be set first because it resets other props like contentOffset -RCT_EXPORT_VIEW_PROPERTY(contentInset); -RCT_EXPORT_VIEW_PROPERTY(scrollIndicatorInsets); -RCT_EXPORT_VIEW_PROPERTY(contentOffset); - -- (NSDictionary *)constantsToExport -{ - return @{ - @"DecelerationRate": @{ - @"Normal": @(UIScrollViewDecelerationRateNormal), - @"Fast": @(UIScrollViewDecelerationRateFast), - }, - @"KeyboardDismissMode": @{ - @"None": @(UIScrollViewKeyboardDismissModeNone), - @"Interactive": @(UIScrollViewKeyboardDismissModeInteractive), - @"OnDrag": @(UIScrollViewKeyboardDismissModeOnDrag), - }, - }; -} - -@end diff --git a/ReactKit/Views/RCTScrollableProtocol.h b/ReactKit/Views/RCTScrollableProtocol.h deleted file mode 100644 index a0ae7b6112e..00000000000 --- a/ReactKit/Views/RCTScrollableProtocol.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -/** - * Contains any methods related to scrolling. Any `RCTView` that has scrolling - * features should implement these methods. - */ -@protocol RCTScrollableProtocol - -@property (nonatomic, readwrite, weak) NSObject *nativeMainScrollDelegate; -@property (nonatomic, readonly) CGSize contentSize; - -- (void)scrollToOffset:(CGPoint)offset; -- (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated; -- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated; - -@end diff --git a/ReactKit/Views/RCTShadowView.h b/ReactKit/Views/RCTShadowView.h deleted file mode 100644 index f869ca614cc..00000000000 --- a/ReactKit/Views/RCTShadowView.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "Layout.h" -#import "RCTUIManager.h" -#import "RCTViewNodeProtocol.h" - -@class RCTSparseArray; - -typedef NS_ENUM(NSUInteger, RCTUpdateLifecycle) { - RCTUpdateLifecycleUninitialized = 0, - RCTUpdateLifecycleComputed, - RCTUpdateLifecycleDirtied, -}; - -// TODO: is this redundact now? -typedef void (^RCTApplierBlock)(RCTSparseArray *); - -/** - * ShadowView tree mirrors RCT view tree. Every node is highly stateful. - * 1. A node is in one of three lifecycles: uninitialized, computed, dirtied. - * 1. RCTBridge may call any of the padding/margin/width/height/top/left setters. A setter would dirty - * the node and all of its ancestors. - * 2. At the end of each Bridge transaction, we call collectUpdatedFrames:widthConstraint:heightConstraint - * at the root node to recursively lay out the entire hierarchy. - * 3. If a node is "computed" and the constraint passed from above is identical to the constraint used to - * perform the last computation, we skip laying out the subtree entirely. - */ -@interface RCTShadowView : NSObject - -@property (nonatomic, weak, readonly) RCTShadowView *superview; -@property (nonatomic, assign, readonly) css_node_t *cssNode; -@property (nonatomic, copy) NSString *moduleName; -@property (nonatomic, assign) BOOL isBGColorExplicitlySet; // Used to propagate to children -@property (nonatomic, strong) UIColor *backgroundColor; // Used to propagate to children -@property (nonatomic, assign) RCTUpdateLifecycle layoutLifecycle; - -/** - * isNewView - Used to track the first time the view is introduced into the hierarchy. It is initialized YES, then is - * set to NO in RCTUIManager after the layout pass is done and all frames have been extracted to be applied to the - * corresponding UIViews. - */ -@property (nonatomic, assign, getter=isNewView) BOOL newView; - -/** - * Is this the shadowView for an RCTRootView - */ -@property (nonatomic, assign, getter=isReactRootView) BOOL reactRootView; - -/** - * Position and dimensions. - * Defaults to { 0, 0, NAN, NAN }. - */ -@property (nonatomic, assign) CGFloat top; -@property (nonatomic, assign) CGFloat left; -@property (nonatomic, assign) CGFloat width; -@property (nonatomic, assign) CGFloat height; -@property (nonatomic, assign) CGRect frame; - -- (void)setTopLeft:(CGPoint)topLeft; -- (void)setSize:(CGSize)size; - -/** - * Border. Defaults to { 0, 0, 0, 0 }. - */ -@property (nonatomic, assign) CGFloat borderTop; -@property (nonatomic, assign) CGFloat borderLeft; -@property (nonatomic, assign) CGFloat borderWidth; -@property (nonatomic, assign) CGFloat borderHeight; - -- (void)setBorderWidth:(CGFloat)value; - -/** - * Margin. Defaults to { 0, 0, 0, 0 }. - */ -@property (nonatomic, assign) CGFloat marginTop; -@property (nonatomic, assign) CGFloat marginLeft; -@property (nonatomic, assign) CGFloat marginBottom; -@property (nonatomic, assign) CGFloat marginRight; - -- (void)setMargin:(CGFloat)margin; -- (void)setMarginVertical:(CGFloat)margin; -- (void)setMarginHorizontal:(CGFloat)margin; - -/** - * Padding. Defaults to { 0, 0, 0, 0 }. - */ -@property (nonatomic, assign) CGFloat paddingTop; -@property (nonatomic, assign) CGFloat paddingLeft; -@property (nonatomic, assign) CGFloat paddingBottom; -@property (nonatomic, assign) CGFloat paddingRight; - -- (void)setPadding:(CGFloat)padding; -- (void)setPaddingVertical:(CGFloat)padding; -- (void)setPaddingHorizontal:(CGFloat)padding; - -- (UIEdgeInsets)paddingAsInsets; - -/** - * Flexbox properties. All zero/disabled by default - */ -@property (nonatomic, assign) css_flex_direction_t flexDirection; -@property (nonatomic, assign) css_justify_t justifyContent; -@property (nonatomic, assign) css_align_t alignSelf; -@property (nonatomic, assign) css_align_t alignItems; -@property (nonatomic, assign) css_position_type_t positionType; -@property (nonatomic, assign) css_wrap_type_t flexWrap; -@property (nonatomic, assign) CGFloat flex; - -/** - * Calculate property changes that need to be propagated to the view. - * The applierBlocks set contains RCTApplierBlock functions that must be applied - * on the main thread in order to update the view. - */ -- (void)collectUpdatedProperties:(NSMutableSet *)applierBlocks parentProperties:(NSDictionary *)parentProperties; - -/** - * Calculate all views whose frame needs updating after layout has been calculated. - * The viewsWithNewFrame set contains the reactTags of the views that need updating. - */ -- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame parentConstraint:(CGSize)parentConstraint; - -/** - * The following are implementation details exposed to subclasses. Do not call them directly - */ -- (void)fillCSSNode:(css_node_t *)node; -- (void)dirtyLayout; -- (BOOL)isLayoutDirty; - -// TODO: is this still needed? -- (void)dirtyPropagation; -- (BOOL)isPropagationDirty; - -// TODO: move this to text node? -- (void)dirtyText; -- (BOOL)isTextDirty; -- (void)setTextComputed; - -/** - * Triggers a recalculation of the shadow view's layout. - */ -- (void)updateShadowViewLayout; - -/** - * Computes the recursive offset, meaning the sum of all descendant offsets - - * this is the sum of all positions inset from parents. This is not merely the - * sum of `top`/`left`s, as this function uses the *actual* positions of - * children, not the style specified positions - it computes this based on the - * resulting layout. It does not yet compensate for native scroll view insets or - * transforms or anchor points. Returns an array containing the `x, y, width, - * height` of the shadow view relative to the ancestor, or `nil` if the `view` - * is not a descendent of `ancestor`. - */ -+ (CGRect)measureLayout:(RCTShadowView *)view relativeTo:(RCTShadowView *)ancestor; - -@end diff --git a/ReactKit/Views/RCTShadowView.m b/ReactKit/Views/RCTShadowView.m deleted file mode 100644 index 62d38249e53..00000000000 --- a/ReactKit/Views/RCTShadowView.m +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTShadowView.h" - -#import "RCTConvert.h" -#import "RCTLog.h" -#import "RCTSparseArray.h" -#import "RCTUtils.h" - -typedef void (^RCTActionBlock)(RCTShadowView *shadowViewSelf, id value); -typedef void (^RCTResetActionBlock)(RCTShadowView *shadowViewSelf); - -#define MAX_TREE_DEPTH 30 - -const NSString *const RCTBackgroundColorProp = @"backgroundColor"; - -typedef enum { - META_PROP_LEFT, - META_PROP_TOP, - META_PROP_RIGHT, - META_PROP_BOTTOM, - META_PROP_HORIZONTAL, - META_PROP_VERTICAL, - META_PROP_ALL, - META_PROP_COUNT, -} meta_prop_t; - -@implementation RCTShadowView -{ - RCTUpdateLifecycle _propagationLifecycle; - RCTUpdateLifecycle _textLifecycle; - NSDictionary *_lastParentProperties; - NSMutableArray *_reactSubviews; - BOOL _recomputePadding; - BOOL _recomputeMargin; - float _paddingMetaProps[META_PROP_COUNT]; - float _marginMetaProps[META_PROP_COUNT]; -} - -@synthesize reactTag = _reactTag; - -// css_node api - -static void RCTPrint(void *context) -{ - RCTShadowView *shadowView = (__bridge RCTShadowView *)context; - printf("%s(%zd), ", [[shadowView moduleName] UTF8String], [[shadowView reactTag] integerValue]); -} - -static css_node_t *RCTGetChild(void *context, int i) -{ - RCTShadowView *shadowView = (__bridge RCTShadowView *)context; - RCTShadowView *child = [shadowView reactSubviews][i]; - return child->_cssNode; -} - -static bool RCTIsDirty(void *context) -{ - RCTShadowView *shadowView = (__bridge RCTShadowView *)context; - return [shadowView isLayoutDirty]; -} - -// Enforces precedence rules, e.g. marginLeft > marginHorizontal > margin. -static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float style[CSS_POSITION_COUNT]) { - style[CSS_LEFT] = !isUndefined(metaProps[META_PROP_LEFT]) ? metaProps[META_PROP_LEFT] - : !isUndefined(metaProps[META_PROP_HORIZONTAL]) ? metaProps[META_PROP_HORIZONTAL] - : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] - : 0; - style[CSS_RIGHT] = !isUndefined(metaProps[META_PROP_RIGHT]) ? metaProps[META_PROP_RIGHT] - : !isUndefined(metaProps[META_PROP_HORIZONTAL]) ? metaProps[META_PROP_HORIZONTAL] - : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] - : 0; - style[CSS_TOP] = !isUndefined(metaProps[META_PROP_TOP]) ? metaProps[META_PROP_TOP] - : !isUndefined(metaProps[META_PROP_VERTICAL]) ? metaProps[META_PROP_VERTICAL] - : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] - : 0; - style[CSS_BOTTOM] = !isUndefined(metaProps[META_PROP_BOTTOM]) ? metaProps[META_PROP_BOTTOM] - : !isUndefined(metaProps[META_PROP_VERTICAL]) ? metaProps[META_PROP_VERTICAL] - : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] - : 0; -} - -- (void)fillCSSNode:(css_node_t *)node -{ - node->children_count = (int)_reactSubviews.count; -} - -// The absolute stuff is so that we can take into account our absolute position when rounding in order to -// snap to the pixel grid. For example, say you have the following structure: -// -// +--------+---------+--------+ -// | |+-------+| | -// | || || | -// | |+-------+| | -// +--------+---------+--------+ -// -// Say the screen width is 320 pts so the three big views will get the following x bounds from our layout system: -// {0, 106.667}, {106.667, 213.333}, {213.333, 320} -// -// Assuming screen scale is 2, these numbers must be rounded to the nearest 0.5 to fit the pixel grid: -// {0, 106.5}, {106.5, 213.5}, {213.5, 320} -// You'll notice that the three widths are 106.5, 107, 106.5. -// -// This is great for the parent views but it gets trickier when we consider rounding for the subview. -// -// When we go to round the bounds for the subview in the middle, it's relative bounds are {0, 106.667} -// which gets rounded to {0, 106.5}. This will cause the subview to be one pixel smaller than it should be. -// this is why we need to pass in the absolute position in order to do the rounding relative to the screen's -// grid rather than the view's grid. -// -// After passing in the absolutePosition of {106.667, y}, we do the following calculations: -// absoluteLeft = round(absolutePosition.x + viewPosition.left) = round(106.667 + 0) = 106.5 -// absoluteRight = round(absolutePosition.x + viewPosition.left + viewSize.left) + round(106.667 + 0 + 106.667) = 213.5 -// width = 213.5 - 106.5 = 107 -// You'll notice that this is the same width we calculated for the parent view because we've taken its position into account. - -- (void)applyLayoutNode:(css_node_t *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition -{ - if (!node->layout.should_update) { - return; - } - node->layout.should_update = false; - _layoutLifecycle = RCTUpdateLifecycleComputed; - - CGPoint absoluteTopLeft = { - RCTRoundPixelValue(absolutePosition.x + node->layout.position[CSS_LEFT]), - RCTRoundPixelValue(absolutePosition.y + node->layout.position[CSS_TOP]) - }; - - CGPoint absoluteBottomRight = { - RCTRoundPixelValue(absolutePosition.x + node->layout.position[CSS_LEFT] + node->layout.dimensions[CSS_WIDTH]), - RCTRoundPixelValue(absolutePosition.y + node->layout.position[CSS_TOP] + node->layout.dimensions[CSS_HEIGHT]) - }; - - CGRect frame = { - RCTRoundPixelValue(node->layout.position[CSS_LEFT]), - RCTRoundPixelValue(node->layout.position[CSS_TOP]), - RCTRoundPixelValue(absoluteBottomRight.x - absoluteTopLeft.x), - RCTRoundPixelValue(absoluteBottomRight.y - absoluteTopLeft.y) - }; - - if (!CGRectEqualToRect(frame, _frame)) { - _frame = frame; - [viewsWithNewFrame addObject:self]; - } - - absolutePosition.x += node->layout.position[CSS_LEFT]; - absolutePosition.y += node->layout.position[CSS_TOP]; - - node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; - node->layout.position[CSS_LEFT] = 0; - node->layout.position[CSS_TOP] = 0; - - for (int i = 0; i < node->children_count; ++i) { - RCTShadowView *child = (RCTShadowView *)_reactSubviews[i]; - [child applyLayoutNode:node->get_child(node->context, i) viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition]; - } -} - -- (NSDictionary *)processBackgroundColor:(NSMutableSet *)applierBlocks parentProperties:(NSDictionary *)parentProperties -{ - if (!_isBGColorExplicitlySet) { - UIColor *parentBackgroundColor = parentProperties[RCTBackgroundColorProp]; - if (parentBackgroundColor && ![_backgroundColor isEqual:parentBackgroundColor]) { - _backgroundColor = parentBackgroundColor; - [applierBlocks addObject:^(RCTSparseArray *viewRegistry) { - UIView *view = viewRegistry[_reactTag]; - view.backgroundColor = parentBackgroundColor; - }]; - } - } - if (_isBGColorExplicitlySet) { - // Update parent properties for children - NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithDictionary:parentProperties]; - CGFloat alpha = CGColorGetAlpha(_backgroundColor.CGColor); - if (alpha < 1.0 && alpha > 0.0) { - // If we see partial transparency, start propagating full transparency - properties[RCTBackgroundColorProp] = [UIColor clearColor]; - } else { - properties[RCTBackgroundColorProp] = _backgroundColor; - } - return properties; - } - return parentProperties; -} - -- (void)collectUpdatedProperties:(NSMutableSet *)applierBlocks parentProperties:(NSDictionary *)parentProperties -{ - if (_propagationLifecycle == RCTUpdateLifecycleComputed && [parentProperties isEqualToDictionary:_lastParentProperties]) { - return; - } - _propagationLifecycle = RCTUpdateLifecycleComputed; - _lastParentProperties = parentProperties; - NSDictionary *nextProps = [self processBackgroundColor:applierBlocks parentProperties:parentProperties]; - for (RCTShadowView *child in _reactSubviews) { - [child collectUpdatedProperties:applierBlocks parentProperties:nextProps]; - } -} - -- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame parentConstraint:(CGSize)parentConstraint -{ - [self fillCSSNode:_cssNode]; - layoutNode(_cssNode, CSS_UNDEFINED); - [self applyLayoutNode:_cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:CGPointZero]; -} - -+ (CGRect)measureLayout:(RCTShadowView *)shadowView relativeTo:(RCTShadowView *)ancestor -{ - CGFloat totalOffsetTop = 0.0; - CGFloat totalOffsetLeft = 0.0; - CGSize size = shadowView.frame.size; - NSInteger depth = 0; - while (depth < MAX_TREE_DEPTH && shadowView && shadowView != ancestor) { - totalOffsetTop += shadowView.frame.origin.y; - totalOffsetLeft += shadowView.frame.origin.x; - shadowView = shadowView->_superview; - depth++; - } - if (ancestor != shadowView) { - return CGRectNull; - } - return (CGRect){{totalOffsetLeft, totalOffsetTop}, size}; -} - -- (instancetype)init -{ - if ((self = [super init])) { - - _frame = CGRectMake(0, 0, CSS_UNDEFINED, CSS_UNDEFINED); - - for (int ii = 0; ii < META_PROP_COUNT; ii++) { - _paddingMetaProps[ii] = CSS_UNDEFINED; - _marginMetaProps[ii] = CSS_UNDEFINED; - } - - _newView = YES; - _layoutLifecycle = RCTUpdateLifecycleUninitialized; - _propagationLifecycle = RCTUpdateLifecycleUninitialized; - _textLifecycle = RCTUpdateLifecycleUninitialized; - - _reactSubviews = [NSMutableArray array]; - - _cssNode = new_css_node(); - _cssNode->context = (__bridge void *)self; - _cssNode->print = RCTPrint; - _cssNode->get_child = RCTGetChild; - _cssNode->is_dirty = RCTIsDirty; - [self fillCSSNode:_cssNode]; - } - return self; -} - -- (void)dealloc -{ - free_css_node(_cssNode); -} - -- (void)dirtyLayout -{ - if (_layoutLifecycle != RCTUpdateLifecycleDirtied) { - _layoutLifecycle = RCTUpdateLifecycleDirtied; - [_superview dirtyLayout]; - } -} - -- (BOOL)isLayoutDirty -{ - return _layoutLifecycle != RCTUpdateLifecycleComputed; -} - -- (void)dirtyPropagation -{ - if (_propagationLifecycle != RCTUpdateLifecycleDirtied) { - _propagationLifecycle = RCTUpdateLifecycleDirtied; - [_superview dirtyPropagation]; - } -} - -- (BOOL)isPropagationDirty -{ - return _propagationLifecycle != RCTUpdateLifecycleComputed; -} - -- (void)dirtyText -{ - if (_textLifecycle != RCTUpdateLifecycleDirtied) { - _textLifecycle = RCTUpdateLifecycleDirtied; - [_superview dirtyText]; - } -} - -- (BOOL)isTextDirty -{ - return _textLifecycle != RCTUpdateLifecycleComputed; -} - -- (void)setTextComputed -{ - _textLifecycle = RCTUpdateLifecycleComputed; -} - -- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex -{ - [_reactSubviews insertObject:subview atIndex:atIndex]; - _cssNode->children_count = (int)[_reactSubviews count]; - subview->_superview = self; - [self dirtyText]; - [self dirtyLayout]; - [self dirtyPropagation]; -} - -- (void)removeReactSubview:(RCTShadowView *)subview -{ - [subview dirtyText]; - [subview dirtyLayout]; - [subview dirtyPropagation]; - subview->_superview = nil; - [_reactSubviews removeObject:subview]; - _cssNode->children_count = (int)[_reactSubviews count]; -} - -- (NSArray *)reactSubviews -{ - return _reactSubviews; -} - -- (RCTShadowView *)reactSuperview -{ - return _superview; -} - -- (NSNumber *)reactTagAtPoint:(CGPoint)point -{ - for (RCTShadowView *shadowView in _reactSubviews) { - if (CGRectContainsPoint(shadowView.frame, point)) { - CGPoint relativePoint = point; - CGPoint origin = shadowView.frame.origin; - relativePoint.x -= origin.x; - relativePoint.y -= origin.y; - return [shadowView reactTagAtPoint:relativePoint]; - } - } - return self.reactTag; -} - -// Margin - -#define RCT_MARGIN_PROPERTY(prop, metaProp) \ -- (void)setMargin##prop:(CGFloat)value \ -{ \ - _marginMetaProps[META_PROP_##metaProp] = value; \ - _recomputeMargin = YES; \ -} \ -- (CGFloat)margin##prop \ -{ \ - return _marginMetaProps[META_PROP_##metaProp]; \ -} - -RCT_MARGIN_PROPERTY(, ALL) -RCT_MARGIN_PROPERTY(Vertical, VERTICAL) -RCT_MARGIN_PROPERTY(Horizontal, HORIZONTAL) -RCT_MARGIN_PROPERTY(Top, TOP) -RCT_MARGIN_PROPERTY(Left, LEFT) -RCT_MARGIN_PROPERTY(Bottom, BOTTOM) -RCT_MARGIN_PROPERTY(Right, RIGHT) - -// Padding - -#define RCT_PADDING_PROPERTY(prop, metaProp) \ -- (void)setPadding##prop:(CGFloat)value \ -{ \ - _paddingMetaProps[META_PROP_##metaProp] = value; \ - _recomputePadding = YES; \ -} \ -- (CGFloat)padding##prop \ -{ \ - return _paddingMetaProps[META_PROP_##metaProp]; \ -} - -RCT_PADDING_PROPERTY(, ALL) -RCT_PADDING_PROPERTY(Vertical, VERTICAL) -RCT_PADDING_PROPERTY(Horizontal, HORIZONTAL) -RCT_PADDING_PROPERTY(Top, TOP) -RCT_PADDING_PROPERTY(Left, LEFT) -RCT_PADDING_PROPERTY(Bottom, BOTTOM) -RCT_PADDING_PROPERTY(Right, RIGHT) - -- (UIEdgeInsets)paddingAsInsets -{ - return (UIEdgeInsets){ - _cssNode->style.padding[CSS_TOP], - _cssNode->style.padding[CSS_LEFT], - _cssNode->style.padding[CSS_BOTTOM], - _cssNode->style.padding[CSS_RIGHT] - }; -} - -// Border - -#define RCT_BORDER_PROPERTY(prop, metaProp) \ -- (void)setBorder##prop:(CGFloat)value \ -{ \ - _cssNode->style.border[CSS_##metaProp] = value; \ - [self dirtyLayout]; \ -} \ -- (CGFloat)border##prop \ -{ \ - return _cssNode->style.border[META_PROP_##metaProp]; \ -} - -RCT_BORDER_PROPERTY(Top, TOP) -RCT_BORDER_PROPERTY(Left, LEFT) -RCT_BORDER_PROPERTY(Bottom, BOTTOM) -RCT_BORDER_PROPERTY(Right, RIGHT) - -- (void)setBorderWidth:(CGFloat)value -{ - for (int i = 0; i < 4; i++) { - _cssNode->style.border[i] = value; - } - [self dirtyLayout]; -} - -// Dimensions - -#define RCT_DIMENSIONS_PROPERTY(setProp, getProp, cssProp) \ -- (void)set##setProp:(CGFloat)value \ -{ \ - _cssNode->style.dimensions[CSS_##cssProp] = value; \ - [self dirtyLayout]; \ -} \ -- (CGFloat)getProp \ -{ \ - return _cssNode->style.dimensions[CSS_##cssProp]; \ -} - -RCT_DIMENSIONS_PROPERTY(Width, width, WIDTH) -RCT_DIMENSIONS_PROPERTY(Height, height, HEIGHT) - -// Position - -#define RCT_POSITION_PROPERTY(setProp, getProp, cssProp) \ -- (void)set##setProp:(CGFloat)value \ -{ \ - _cssNode->style.position[CSS_##cssProp] = value; \ - [self dirtyLayout]; \ -} \ -- (CGFloat)getProp \ -{ \ - return _cssNode->style.position[CSS_##cssProp]; \ -} - -RCT_POSITION_PROPERTY(Top, top, TOP) -RCT_POSITION_PROPERTY(Right, right, RIGHT) -RCT_POSITION_PROPERTY(Bottom, bottom, BOTTOM) -RCT_POSITION_PROPERTY(Left, left, LEFT) - -- (void)setFrame:(CGRect)frame -{ - _cssNode->style.position[CSS_LEFT] = CGRectGetMinX(frame); - _cssNode->style.position[CSS_TOP] = CGRectGetMinY(frame); - _cssNode->style.dimensions[CSS_WIDTH] = CGRectGetWidth(frame); - _cssNode->style.dimensions[CSS_HEIGHT] = CGRectGetHeight(frame); - [self dirtyLayout]; -} - -- (void)setTopLeft:(CGPoint)topLeft -{ - _cssNode->style.position[CSS_LEFT] = topLeft.x; - _cssNode->style.position[CSS_TOP] = topLeft.y; - [self dirtyLayout]; -} - -- (void)setSize:(CGSize)size -{ - _cssNode->style.dimensions[CSS_WIDTH] = size.width; - _cssNode->style.dimensions[CSS_HEIGHT] = size.height; - [self dirtyLayout]; -} - -// Flex - -#define RCT_STYLE_PROPERTY(setProp, getProp, cssProp, type) \ -- (void)set##setProp:(type)value \ -{ \ - _cssNode->style.cssProp = value; \ - [self dirtyLayout]; \ -} \ -- (type)getProp \ -{ \ - return _cssNode->style.cssProp; \ -} - -RCT_STYLE_PROPERTY(Flex, flex, flex, CGFloat) -RCT_STYLE_PROPERTY(FlexDirection, flexDirection, flex_direction, css_flex_direction_t) -RCT_STYLE_PROPERTY(JustifyContent, justifyContent, justify_content, css_justify_t) -RCT_STYLE_PROPERTY(AlignSelf, alignSelf, align_self, css_align_t) -RCT_STYLE_PROPERTY(AlignItems, alignItems, align_items, css_align_t) -RCT_STYLE_PROPERTY(PositionType, positionType, position_type, css_position_type_t) -RCT_STYLE_PROPERTY(FlexWrap, flexWrap, flex_wrap, css_wrap_type_t) - -- (void)setBackgroundColor:(UIColor *)color -{ - _backgroundColor = color; - [self dirtyPropagation]; -} - -- (void)updateShadowViewLayout -{ - if (_recomputePadding) { - RCTProcessMetaProps(_paddingMetaProps, _cssNode->style.padding); - } - if (_recomputeMargin) { - RCTProcessMetaProps(_marginMetaProps, _cssNode->style.margin); - } - if (_recomputePadding || _recomputeMargin) { - [self dirtyLayout]; - } - [self fillCSSNode:_cssNode]; - _recomputeMargin = NO; - _recomputePadding = NO; -} - -@end diff --git a/ReactKit/Views/RCTSliderManager.h b/ReactKit/Views/RCTSliderManager.h deleted file mode 100644 index 1088ec569cb..00000000000 --- a/ReactKit/Views/RCTSliderManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTSliderManager : RCTViewManager - -@end diff --git a/ReactKit/Views/RCTSliderManager.m b/ReactKit/Views/RCTSliderManager.m deleted file mode 100644 index 8561c0a9798..00000000000 --- a/ReactKit/Views/RCTSliderManager.m +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTSliderManager.h" - -#import "RCTBridge.h" -#import "RCTEventDispatcher.h" -#import "UIView+ReactKit.h" - -@implementation RCTSliderManager - -- (UIView *)view -{ - UISlider *slider = [[UISlider alloc] init]; - [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged]; - [slider addTarget:self action:@selector(sliderTouchEnd:) forControlEvents:UIControlEventTouchUpInside]; - return slider; -} - -- (void)sliderValueChanged:(UISlider *)sender -{ - NSDictionary *event = @{ - @"target": sender.reactTag, - @"value": @(sender.value), - @"continuous": @YES, - }; - - [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event]; -} - -- (void)sliderTouchEnd:(UISlider *)sender -{ - NSDictionary *event = @{ - @"target": sender.reactTag, - @"value": @(sender.value), - @"continuous": @NO, - }; - - [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:event]; -} - -RCT_EXPORT_VIEW_PROPERTY(value); - -@end diff --git a/ReactKit/Views/RCTSwitch.h b/ReactKit/Views/RCTSwitch.h deleted file mode 100644 index 7866eb8666a..00000000000 --- a/ReactKit/Views/RCTSwitch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - - -#import - -@interface RCTSwitch : UISwitch - -@property (nonatomic, assign) BOOL wasOn; - -@end diff --git a/ReactKit/Views/RCTSwitch.m b/ReactKit/Views/RCTSwitch.m deleted file mode 100644 index 70233fede4e..00000000000 --- a/ReactKit/Views/RCTSwitch.m +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTSwitch.h" - -#import "RCTEventDispatcher.h" -#import "UIView+ReactKit.h" - -@implementation RCTSwitch - -- (void)setOn:(BOOL)on animated:(BOOL)animated { - _wasOn = on; - [super setOn:on animated:animated]; -} - -@end diff --git a/ReactKit/Views/RCTSwitchManager.h b/ReactKit/Views/RCTSwitchManager.h deleted file mode 100644 index f6833d10635..00000000000 --- a/ReactKit/Views/RCTSwitchManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTSwitchManager : RCTViewManager - -@end diff --git a/ReactKit/Views/RCTSwitchManager.m b/ReactKit/Views/RCTSwitchManager.m deleted file mode 100644 index 61eab819963..00000000000 --- a/ReactKit/Views/RCTSwitchManager.m +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTSwitchManager.h" - -#import "RCTBridge.h" -#import "RCTEventDispatcher.h" -#import "RCTSwitch.h" -#import "UIView+ReactKit.h" - -@implementation RCTSwitchManager - -- (UIView *)view -{ - RCTSwitch *switcher = [[RCTSwitch alloc] init]; - [switcher addTarget:self - action:@selector(onChange:) - forControlEvents:UIControlEventValueChanged]; - return switcher; -} - -- (void)onChange:(RCTSwitch *)sender -{ - if (sender.wasOn != sender.on) { - [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:@{ - @"target": sender.reactTag, - @"value": @(sender.on) - }]; - - sender.wasOn = sender.on; - } -} - -RCT_EXPORT_VIEW_PROPERTY(onTintColor); -RCT_EXPORT_VIEW_PROPERTY(tintColor); -RCT_EXPORT_VIEW_PROPERTY(thumbTintColor); -RCT_EXPORT_VIEW_PROPERTY(on); -RCT_EXPORT_VIEW_PROPERTY(enabled); - -@end diff --git a/ReactKit/Views/RCTTabBar.h b/ReactKit/Views/RCTTabBar.h deleted file mode 100644 index 58da056a3f4..00000000000 --- a/ReactKit/Views/RCTTabBar.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@class RCTEventDispatcher; - -@interface RCTTabBar : UIView - -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; - -@end diff --git a/ReactKit/Views/RCTTabBar.m b/ReactKit/Views/RCTTabBar.m deleted file mode 100644 index 9f49fbcaf79..00000000000 --- a/ReactKit/Views/RCTTabBar.m +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTabBar.h" - -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTTabBarItem.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "RCTViewControllerProtocol.h" -#import "RCTWrapperViewController.h" -#import "UIView+ReactKit.h" - -@interface RKCustomTabBarController : UITabBarController - -@end - -@implementation RKCustomTabBarController - -@synthesize currentTopLayoutGuide = _currentTopLayoutGuide; -@synthesize currentBottomLayoutGuide = _currentBottomLayoutGuide; - -- (void)viewWillLayoutSubviews -{ - [super viewWillLayoutSubviews]; - _currentTopLayoutGuide = self.topLayoutGuide; - _currentBottomLayoutGuide = self.bottomLayoutGuide; -} - -@end - -@interface RCTTabBar() - -@end - -@implementation RCTTabBar -{ - BOOL _tabsChanged; - RCTEventDispatcher *_eventDispatcher; - UITabBarController *_tabController; - NSMutableArray *_tabViews; -} - -- (id)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ - if ((self = [super initWithFrame:CGRectZero])) { - _eventDispatcher = eventDispatcher; - _tabViews = [[NSMutableArray alloc] init]; - _tabController = [[RKCustomTabBarController alloc] init]; - _tabController.delegate = self; - [self addSubview:_tabController.view]; - } - return self; -} - -- (UIViewController *)backingViewController -{ - return _tabController; -} - -- (void)dealloc -{ - _tabController.delegate = nil; -} - -- (NSArray *)reactSubviews -{ - return _tabViews; -} - -- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex -{ - if (![view isKindOfClass:[RCTTabBarItem class]]) { - RCTLogError(@"subview should be of type RCTTabBarItem"); - return; - } - [_tabViews insertObject:view atIndex:atIndex]; - _tabsChanged = YES; -} - -- (void)removeReactSubview:(UIView *)subview -{ - if (_tabViews.count == 0) { - RCTLogError(@"should have at least one view to remove a subview"); - return; - } - [_tabViews removeObject:subview]; - _tabsChanged = YES; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - _tabController.view.frame = self.bounds; -} - -- (void)reactBridgeDidFinishTransaction -{ - // we can't hook up the VC hierarchy in 'init' because the subviews aren't - // hooked up yet, so we do it on demand here whenever a transaction has finished - [self addControllerToClosestParent:_tabController]; - //[RCTView addViewController:_tabController toBackingViewControllerForView:self]; - - if (_tabsChanged) { - - NSMutableArray *viewControllers = [NSMutableArray array]; - for (RCTTabBarItem *tab in [self reactSubviews]) { - UIViewController *controller = tab.backingViewController; - if (!controller) { - controller = [[RCTWrapperViewController alloc] initWithContentView:tab - eventDispatcher:_eventDispatcher]; - } - [viewControllers addObject:controller]; - } - - _tabController.viewControllers = viewControllers; - _tabsChanged = NO; - } - - [[self reactSubviews] enumerateObjectsUsingBlock:^(RCTTabBarItem *tab, NSUInteger index, BOOL *stop) { - UIViewController *controller = _tabController.viewControllers[index]; - controller.tabBarItem = tab.barItem; - if (tab.selected) { - _tabController.selectedViewController = controller; - } - }]; -} - -#pragma mark - UITabBarControllerDelegate - -- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController -{ - NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController]; - RCTTabBarItem *tab = [self reactSubviews][index]; - [_eventDispatcher sendInputEventWithName:@"topTap" body:@{@"target": tab.reactTag}]; - return NO; -} - -@end diff --git a/ReactKit/Views/RCTTabBarItem.h b/ReactKit/Views/RCTTabBarItem.h deleted file mode 100644 index 18b03f151b9..00000000000 --- a/ReactKit/Views/RCTTabBarItem.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@interface RCTTabBarItem : UIView - -@property (nonatomic, copy) NSString *icon; -@property (nonatomic, assign, getter=isSelected) BOOL selected; -@property (nonatomic, readonly) UITabBarItem *barItem; - -@end diff --git a/ReactKit/Views/RCTTabBarItem.m b/ReactKit/Views/RCTTabBarItem.m deleted file mode 100644 index cca0e518068..00000000000 --- a/ReactKit/Views/RCTTabBarItem.m +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTabBarItem.h" - -#import "RCTConvert.h" -#import "RCTLog.h" -#import "UIView+ReactKit.h" - -@implementation RCTTabBarItem - -@synthesize barItem = _barItem; - -- (UITabBarItem *)barItem -{ - if (!_barItem) { - _barItem = [[UITabBarItem alloc] init]; - } - return _barItem; -} - -- (void)setIcon:(NSString *)icon -{ - static NSDictionary *systemIcons; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - systemIcons = @{ - @"more": @(UITabBarSystemItemMore), - @"favorites": @(UITabBarSystemItemFavorites), - @"featured": @(UITabBarSystemItemFeatured), - @"topRated": @(UITabBarSystemItemTopRated), - @"recents": @(UITabBarSystemItemRecents), - @"contacts": @(UITabBarSystemItemContacts), - @"history": @(UITabBarSystemItemHistory), - @"bookmarks": @(UITabBarSystemItemBookmarks), - @"search": @(UITabBarSystemItemSearch), - @"downloads": @(UITabBarSystemItemDownloads), - @"mostRecent": @(UITabBarSystemItemMostRecent), - @"mostViewed": @(UITabBarSystemItemMostViewed), - }; - }); - - // Update icon - BOOL wasSystemIcon = (systemIcons[_icon] != nil); - _icon = [icon copy]; - - // Check if string matches any custom images first - UIImage *image = [RCTConvert UIImage:_icon]; - UITabBarItem *oldItem = _barItem; - if (image) { - - // Recreate barItem if previous item was a system icon - if (wasSystemIcon) { - _barItem = nil; - self.barItem.image = image; - } else { - self.barItem.image = image; - return; - } - - } else { - - // Not a custom image, may be a system item? - NSNumber *systemIcon = systemIcons[icon]; - if (!systemIcon) { - RCTLogError(@"The tab bar icon '%@' did not match any known image or system icon", icon); - return; - } - _barItem = [[UITabBarItem alloc] initWithTabBarSystemItem:[systemIcon integerValue] tag:oldItem.tag]; - } - - // Reapply previous properties - _barItem.title = oldItem.title; - _barItem.imageInsets = oldItem.imageInsets; - _barItem.selectedImage = oldItem.selectedImage; - _barItem.badgeValue = oldItem.badgeValue; -} - -- (UIViewController *)backingViewController -{ - return self.superview.backingViewController; -} - -@end diff --git a/ReactKit/Views/RCTTabBarItemManager.h b/ReactKit/Views/RCTTabBarItemManager.h deleted file mode 100644 index 62302076912..00000000000 --- a/ReactKit/Views/RCTTabBarItemManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTTabBarItemManager : RCTViewManager - -@end diff --git a/ReactKit/Views/RCTTabBarItemManager.m b/ReactKit/Views/RCTTabBarItemManager.m deleted file mode 100644 index f74bc09edfd..00000000000 --- a/ReactKit/Views/RCTTabBarItemManager.m +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTabBarItemManager.h" - -#import "RCTConvert.h" -#import "RCTTabBarItem.h" - -@implementation RCTTabBarItemManager - -- (UIView *)view -{ - return [[RCTTabBarItem alloc] init]; -} - -RCT_EXPORT_VIEW_PROPERTY(selected); -RCT_EXPORT_VIEW_PROPERTY(icon); -RCT_REMAP_VIEW_PROPERTY(selectedIcon, barItem.selectedImage); -RCT_REMAP_VIEW_PROPERTY(badgeValue, barItem.badgeValue); -RCT_CUSTOM_VIEW_PROPERTY(title, RCTTabBarItem *) -{ - view.barItem.title = json ? [RCTConvert NSString:json] : defaultView.barItem.title; - view.barItem.imageInsets = [view.barItem.title length] ? UIEdgeInsetsZero : (UIEdgeInsets){6, 0, -6, 0}; -} - -@end diff --git a/ReactKit/Views/RCTTabBarManager.h b/ReactKit/Views/RCTTabBarManager.h deleted file mode 100644 index 34f745e1cdf..00000000000 --- a/ReactKit/Views/RCTTabBarManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTTabBarManager : RCTViewManager - -@end diff --git a/ReactKit/Views/RCTTabBarManager.m b/ReactKit/Views/RCTTabBarManager.m deleted file mode 100644 index 70882bc1634..00000000000 --- a/ReactKit/Views/RCTTabBarManager.m +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTabBarManager.h" - -#import "RCTBridge.h" -#import "RCTTabBar.h" - -@implementation RCTTabBarManager - -@synthesize bridge = _bridge; - -- (UIView *)view -{ - return [[RCTTabBar alloc] initWithEventDispatcher:_bridge.eventDispatcher]; -} - -@end diff --git a/ReactKit/Views/RCTTextField.h b/ReactKit/Views/RCTTextField.h deleted file mode 100644 index 1688f8fdc0c..00000000000 --- a/ReactKit/Views/RCTTextField.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -@class RCTEventDispatcher; - -@interface RCTTextField : UITextField - -@property (nonatomic, assign) BOOL caretHidden; -@property (nonatomic, assign) BOOL autoCorrect; -@property (nonatomic, assign) UIEdgeInsets paddingEdgeInsets; // TODO: contentInset - -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; - -@end diff --git a/ReactKit/Views/RCTTextField.m b/ReactKit/Views/RCTTextField.m deleted file mode 100644 index b684517b358..00000000000 --- a/ReactKit/Views/RCTTextField.m +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTextField.h" - -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTUtils.h" -#import "UIView+ReactKit.h" - -@implementation RCTTextField -{ - RCTEventDispatcher *_eventDispatcher; - NSMutableArray *_reactSubviews; - BOOL _jsRequestingFirstResponder; -} - -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ - if ((self = [super initWithFrame:CGRectZero])) { - - _eventDispatcher = eventDispatcher; - [self addTarget:self action:@selector(_textFieldDidChange) forControlEvents:UIControlEventEditingChanged]; - [self addTarget:self action:@selector(_textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin]; - [self addTarget:self action:@selector(_textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd]; - [self addTarget:self action:@selector(_textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit]; - _reactSubviews = [[NSMutableArray alloc] init]; - self.returnKeyType = UIReturnKeyDone; - } - return self; -} - -- (NSArray *)reactSubviews -{ - // TODO: do we support subviews of textfield in React? - // In any case, we should have a better approach than manually - // maintaining array in each view subclass like this - return _reactSubviews; -} - -- (void)removeReactSubview:(UIView *)subview -{ - // TODO: this is a bit broken - if the TextField inserts any of - // it's own views below or between React's, the indices won't match - [_reactSubviews removeObject:subview]; - [subview removeFromSuperview]; -} - -- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex -{ - // TODO: this is a bit broken - if the TextField inserts any of - // it's own views below or between React's, the indices won't match - [_reactSubviews insertObject:view atIndex:atIndex]; - [super insertSubview:view atIndex:atIndex]; -} - -- (CGRect)caretRectForPosition:(UITextPosition *)position -{ - if (_caretHidden) { - return CGRectZero; - } - return [super caretRectForPosition:position]; -} - -- (CGRect)textRectForBounds:(CGRect)bounds -{ - CGRect rect = [super textRectForBounds:bounds]; - return UIEdgeInsetsInsetRect(rect, _paddingEdgeInsets); -} - -- (CGRect)editingRectForBounds:(CGRect)bounds -{ - return [self textRectForBounds:bounds]; -} - -- (void)setAutoCorrect:(BOOL)autoCorrect -{ - [super setAutocorrectionType:(autoCorrect ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo)]; -} - -- (BOOL)autoCorrect -{ - return self.autocorrectionType == UITextAutocorrectionTypeYes; -} - -#define RCT_TEXT_EVENT_HANDLER(delegateMethod, eventName) \ -- (void)delegateMethod \ -{ \ - [_eventDispatcher sendTextEventWithType:eventName \ - reactTag:self.reactTag \ - text:self.text]; \ -} - -RCT_TEXT_EVENT_HANDLER(_textFieldDidChange, RCTTextEventTypeChange) -RCT_TEXT_EVENT_HANDLER(_textFieldBeginEditing, RCTTextEventTypeFocus) -RCT_TEXT_EVENT_HANDLER(_textFieldEndEditing, RCTTextEventTypeEnd) -RCT_TEXT_EVENT_HANDLER(_textFieldSubmitEditing, RCTTextEventTypeSubmit) - -// TODO: we should support shouldChangeTextInRect (see UITextFieldDelegate) - -- (BOOL)becomeFirstResponder -{ - _jsRequestingFirstResponder = YES; // TODO: is this still needed? - BOOL result = [super becomeFirstResponder]; - _jsRequestingFirstResponder = NO; - return result; -} - -- (BOOL)resignFirstResponder -{ - BOOL result = [super resignFirstResponder]; - if (result) - { - [_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur - reactTag:self.reactTag - text:self.text]; - } - return result; -} - -// Prevent native from becoming first responder (TODO: why?) -- (BOOL)canBecomeFirstResponder -{ - return _jsRequestingFirstResponder; -} - -@end diff --git a/ReactKit/Views/RCTTextFieldManager.h b/ReactKit/Views/RCTTextFieldManager.h deleted file mode 100644 index 1f83a47d8f6..00000000000 --- a/ReactKit/Views/RCTTextFieldManager.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTTextFieldManager : RCTViewManager - -@end - diff --git a/ReactKit/Views/RCTTextFieldManager.m b/ReactKit/Views/RCTTextFieldManager.m deleted file mode 100644 index 4f46c0dff8e..00000000000 --- a/ReactKit/Views/RCTTextFieldManager.m +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTTextFieldManager.h" - -#import "RCTConvert.h" -#import "RCTShadowView.h" -#import "RCTSparseArray.h" -#import "RCTTextField.h" - -@implementation RCTTextFieldManager - -- (UIView *)view -{ - return [[RCTTextField alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; -} - -RCT_EXPORT_VIEW_PROPERTY(caretHidden) -RCT_EXPORT_VIEW_PROPERTY(autoCorrect) -RCT_REMAP_VIEW_PROPERTY(autoCapitalize, autocapitalizationType) -RCT_EXPORT_VIEW_PROPERTY(enabled) -RCT_EXPORT_VIEW_PROPERTY(placeholder) -RCT_EXPORT_VIEW_PROPERTY(text) -RCT_EXPORT_VIEW_PROPERTY(font) -RCT_EXPORT_VIEW_PROPERTY(clearButtonMode) -RCT_EXPORT_VIEW_PROPERTY(keyboardType) -RCT_REMAP_VIEW_PROPERTY(color, textColor) -RCT_CUSTOM_VIEW_PROPERTY(fontSize, RCTTextField *) -{ - view.font = [RCTConvert UIFont:view.font withSize:json ?: @(defaultView.font.pointSize)]; -} -RCT_CUSTOM_VIEW_PROPERTY(fontWeight, RCTTextField *) -{ - view.font = [RCTConvert UIFont:view.font withWeight:json]; // TODO -} -RCT_CUSTOM_VIEW_PROPERTY(fontFamily, RCTTextField *) -{ - view.font = [RCTConvert UIFont:view.font withFamily:json ?: defaultView.font.familyName]; -} - -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowView *)shadowView -{ - NSNumber *reactTag = shadowView.reactTag; - UIEdgeInsets padding = shadowView.paddingAsInsets; - return ^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - ((RCTTextField *)viewRegistry[reactTag]).paddingEdgeInsets = padding; - }; -} - -@end diff --git a/ReactKit/Views/RCTUIActivityIndicatorViewManager.h b/ReactKit/Views/RCTUIActivityIndicatorViewManager.h deleted file mode 100644 index d6766135907..00000000000 --- a/ReactKit/Views/RCTUIActivityIndicatorViewManager.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -@interface RCTUIActivityIndicatorViewManager : RCTViewManager - -@end diff --git a/ReactKit/Views/RCTUIActivityIndicatorViewManager.m b/ReactKit/Views/RCTUIActivityIndicatorViewManager.m deleted file mode 100644 index e56f0110682..00000000000 --- a/ReactKit/Views/RCTUIActivityIndicatorViewManager.m +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTUIActivityIndicatorViewManager.h" - -#import "RCTConvert.h" - -@implementation RCTUIActivityIndicatorViewManager - -- (UIView *)view -{ - return [[UIActivityIndicatorView alloc] init]; -} - -RCT_EXPORT_VIEW_PROPERTY(activityIndicatorViewStyle) -RCT_EXPORT_VIEW_PROPERTY(color) -RCT_CUSTOM_VIEW_PROPERTY(animating, UIActivityIndicatorView *) -{ - BOOL animating = json ? [json boolValue] : [defaultView isAnimating]; - if (animating != [view isAnimating]) { - if (animating) { - [view startAnimating]; - } else { - [view stopAnimating]; - } - } -} - -- (NSDictionary *)constantsToExport -{ - return - @{ - @"StyleWhite": @(UIActivityIndicatorViewStyleWhite), - @"StyleWhiteLarge": @(UIActivityIndicatorViewStyleWhiteLarge), - @"StyleGray": @(UIActivityIndicatorViewStyleGray), - }; -} - -@end diff --git a/ReactKit/Views/RCTView.h b/ReactKit/Views/RCTView.h deleted file mode 100644 index cf46eb9dfa2..00000000000 --- a/ReactKit/Views/RCTView.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTView.h" - -#import - -#import "RCTPointerEvents.h" - -@protocol RCTAutoInsetsProtocol; - -@interface RCTView : UIView - -/** - * Used to control how touch events are processed. - */ -@property (nonatomic, assign) RCTPointerEvents pointerEvents; - -+ (void)autoAdjustInsetsForView:(UIView *)parentView - withScrollView:(UIScrollView *)scrollView - updateOffset:(BOOL)updateOffset; - -/** - * Find the first view controller whose view, or any subview is the specified view. - */ -+ (UIEdgeInsets)contentInsetsForView:(UIView *)curView; - -@end diff --git a/ReactKit/Views/RCTView.m b/ReactKit/Views/RCTView.m deleted file mode 100644 index 9666e717bd1..00000000000 --- a/ReactKit/Views/RCTView.m +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTView.h" - -#import "RCTAutoInsetsProtocol.h" -#import "RCTConvert.h" -#import "RCTLog.h" -#import "UIView+ReactKit.h" - -static NSString *RCTRecursiveAccessibilityLabel(UIView *view) -{ - NSMutableString *str = [NSMutableString stringWithString:@""]; - for (UIView *subview in view.subviews) { - NSString *label = [subview accessibilityLabel]; - if (label) { - [str appendString:@" "]; - [str appendString:label]; - } else { - [str appendString:RCTRecursiveAccessibilityLabel(subview)]; - } - } - return str; -} - -@implementation RCTView - -- (NSString *)accessibilityLabel -{ - if (super.accessibilityLabel) { - return super.accessibilityLabel; - } - return RCTRecursiveAccessibilityLabel(self); -} - -- (void)setPointerEvents:(RCTPointerEvents)pointerEvents -{ - _pointerEvents = pointerEvents; - self.userInteractionEnabled = (pointerEvents != RCTPointerEventsNone); - if (pointerEvents == RCTPointerEventsBoxNone) { - self.accessibilityViewIsModal = NO; // TODO: find out what this is for - } -} - -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event -{ - switch (_pointerEvents) { - case RCTPointerEventsNone: - return nil; - case RCTPointerEventsUnspecified: - return [super hitTest:point withEvent:event]; - case RCTPointerEventsBoxOnly: - return [super hitTest:point withEvent:event] ? self: nil; - case RCTPointerEventsBoxNone: - for (UIView *subview in [self.subviews reverseObjectEnumerator]) { - if (!subview.isHidden && subview.isUserInteractionEnabled && subview.alpha > 0) { - CGPoint convertedPoint = [subview convertPoint:point fromView:self]; - UIView *subviewHitTestView = [subview hitTest:convertedPoint withEvent:event]; - if (subviewHitTestView != nil) { - return subviewHitTestView; - } - } - } - return nil; - default: - RCTLogError(@"Invalid pointer-events specified %zd on %@", _pointerEvents, self); - return [super hitTest:point withEvent:event]; - } -} - -#pragma mark - Statics for dealing with layoutGuides - -+ (void)autoAdjustInsetsForView:(UIView *)parentView - withScrollView:(UIScrollView *)scrollView - updateOffset:(BOOL)updateOffset -{ - UIEdgeInsets baseInset = parentView.contentInset; - CGFloat previousInsetTop = scrollView.contentInset.top; - CGPoint contentOffset = scrollView.contentOffset; - - if (parentView.automaticallyAdjustContentInsets) { - UIEdgeInsets autoInset = [self contentInsetsForView:parentView]; - baseInset.top += autoInset.top; - baseInset.bottom += autoInset.bottom; - baseInset.left += autoInset.left; - baseInset.right += autoInset.right; - } - [scrollView setContentInset:baseInset]; - [scrollView setScrollIndicatorInsets:baseInset]; - - if (updateOffset) { - // If we're adjusting the top inset, then let's also adjust the contentOffset so that the view - // elements above the top guide do not cover the content. - // This is generally only needed when your views are initially laid out, for - // manual changes to contentOffset, you can optionally disable this step - CGFloat currentInsetTop = scrollView.contentInset.top; - if (currentInsetTop != previousInsetTop) { - contentOffset.y -= (currentInsetTop - previousInsetTop); - scrollView.contentOffset = contentOffset; - } - } -} - -+ (UIEdgeInsets)contentInsetsForView:(UIView *)view -{ - while (view) { - UIViewController *controller = view.backingViewController; - if (controller) { - return (UIEdgeInsets){ - controller.topLayoutGuide.length, 0, - controller.bottomLayoutGuide.length, 0 - }; - } - view = view.superview; - } - return UIEdgeInsetsZero; -} - -@end diff --git a/ReactKit/Views/RCTViewControllerProtocol.h b/ReactKit/Views/RCTViewControllerProtocol.h deleted file mode 100644 index 2c82572c316..00000000000 --- a/ReactKit/Views/RCTViewControllerProtocol.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -/** - * A simple protocol that any React-managed ViewControllers should implement. - * We need all of our ViewControllers to cache layoutGuide changes so any View - * in our View hierarchy can access accurate layoutGuide info at any time. - */ -@protocol RCTViewControllerProtocol - -@property (nonatomic, readonly, strong) id currentTopLayoutGuide; -@property (nonatomic, readonly, strong) id currentBottomLayoutGuide; - -@end diff --git a/ReactKit/Views/RCTViewManager.h b/ReactKit/Views/RCTViewManager.h deleted file mode 100644 index b98fc34a3fa..00000000000 --- a/ReactKit/Views/RCTViewManager.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTBridgeModule.h" -#import "RCTConvert.h" -#import "RCTLog.h" - -@class RCTBridge; -@class RCTEventDispatcher; -@class RCTShadowView; -@class RCTSparseArray; -@class RCTUIManager; - -typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *viewRegistry); - -@interface RCTViewManager : NSObject - -/** - * The bridge can be used to access both the RCTUIIManager and the RCTEventDispatcher, - * allowing the manager (or the views that it manages) to manipulate the view - * hierarchy and send events back to the JS context. - */ -@property (nonatomic, strong) RCTBridge *bridge; - -/** - * The module name exposed to React JS. If omitted, this will be inferred - * automatically by using the view module's class name. It is better to not - * override this, and just follow standard naming conventions for your view - * module subclasses. - */ -+ (NSString *)moduleName; - -/** - * This method instantiates a native view to be managed by the module. Override - * this to return a custom view instance, which may be preconfigured with default - * properties, subviews, etc. This method will be called many times, and should - * return a fresh instance each time. The view module MUST NOT cache the returned - * view and return the same instance for subsequent calls. - */ -- (UIView *)view; - -/** - * This method instantiates a shadow view to be managed by the module. If omitted, - * an ordinary RCTShadowView instance will be created, which is typically fine for - * most view types. As with the -view method, the -shadowView method should return - * a fresh instance each time it is called. - */ -- (RCTShadowView *)shadowView; - -/** - * Returns a dictionary of config data passed to JS that defines eligible events - * that can be placed on native views. This should return bubbling - * directly-dispatched event types and specify what names should be used to - * subscribe to either form (bubbling/capturing). - * - * Returned dictionary should be of the form: @{ - * @"onTwirl": { - * @"phasedRegistrationNames": @{ - * @"bubbled": @"onTwirl", - * @"captured": @"onTwirlCaptured" - * } - * } - * } - * - * Note that this method is not inherited when you subclass a view module, and - * you should not call [super customBubblingEventTypes] when overriding it. - */ -+ (NSDictionary *)customBubblingEventTypes; - -/** - * Returns a dictionary of config data passed to JS that defines eligible events - * that can be placed on native views. This should return non-bubbling - * directly-dispatched event types. - * - * Returned dictionary should be of the form: @{ - * @"onTwirl": { - * @"registrationName": @"onTwirl" - * } - * } - * - * Note that this method is not inherited when you subclass a view module, and - * you should not call [super customDirectEventTypes] when overriding it. - */ -+ (NSDictionary *)customDirectEventTypes; - -/** - * Called to notify manager that layout has finished, in case any calculated - * properties need to be copied over from shadow view to view. - */ -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowView *)shadowView; - -/** - * Called after view hierarchy manipulation has finished, and all shadow props - * have been set, but before layout has been performed. Useful for performing - * custo layout logic or tasks that involve walking the view hierarchy. - * To be deprecated, hopefully. - */ -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry; - -/** - * This handles the simple case, where JS and native property names match - * And the type can be automatically inferred. - */ -#define RCT_EXPORT_VIEW_PROPERTY(name) \ -RCT_REMAP_VIEW_PROPERTY(name, name) - -/** - * This macro maps a named property on the module to an arbitrary key path - * within the view. - */ -#define RCT_REMAP_VIEW_PROPERTY(name, keypath) \ -- (void)set_##name:(id)json forView:(id)view withDefaultView:(id)defaultView { \ - if ((json && !RCTSetProperty(view, @#keypath, json)) || \ - (!json && !RCTCopyProperty(view, defaultView, @#keypath))) { \ - RCTLogError(@"%@ does not have setter for `%s` property", [view class], #name); \ - } \ -} - -/** - * These macros can be used when you need to provide custom logic for setting - * view properties. The macro should be followed by a method body, which can - * refer to "json", "view" and "defaultView" to implement the required logic. - */ -#define RCT_CUSTOM_VIEW_PROPERTY(name, viewType) \ -- (void)set_##name:(id)json forView:(viewType)view withDefaultView:(viewType)defaultView - -#define RCT_CUSTOM_SHADOW_PROPERTY(name, viewType) \ -- (void)set_##name:(id)json forShadowView:(viewType)view withDefaultView:(viewType)defaultView - -/** - * These are useful in cases where the module's superclass handles a - * property, but you wish to "unhandle" it, so it will be ignored. - */ -#define RCT_IGNORE_VIEW_PROPERTY(name) \ -- (void)set_##name:(id)value forView:(id)view withDefaultView:(id)defaultView {} - -#define RCT_IGNORE_SHADOW_PROPERTY(name) \ -- (void)set_##name:(id)value forShadowView:(id)view withDefaultView:(id)defaultView {} - -@end diff --git a/ReactKit/Views/RCTViewManager.m b/ReactKit/Views/RCTViewManager.m deleted file mode 100644 index 44bac521187..00000000000 --- a/ReactKit/Views/RCTViewManager.m +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTViewManager.h" - -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTShadowView.h" -#import "RCTUtils.h" -#import "RCTView.h" - -@implementation RCTViewManager - -@synthesize bridge = _bridge; - -+ (NSString *)moduleName -{ - // Default implementation, works in most cases - NSString *name = NSStringFromClass(self); - if ([name hasPrefix:@"RK"]) { - name = [name stringByReplacingCharactersInRange:(NSRange){0,@"RK".length} withString:@"RCT"]; - } - if ([name hasPrefix:@"RCTUI"]) { - name = [name substringFromIndex:@"RCT".length]; - } - return name; -} - -- (UIView *)view -{ - return [[RCTView alloc] init]; -} - -- (RCTShadowView *)shadowView -{ - return [[RCTShadowView alloc] init]; -} - -+ (NSDictionary *)customBubblingEventTypes -{ - return nil; -} - -+ (NSDictionary *)customDirectEventTypes -{ - return nil; -} - -- (NSDictionary *)constantsToExport -{ - return nil; -} - -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowView *)shadowView -{ - return nil; -} - -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry -{ - return nil; -} - -// View properties - -RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel) -RCT_EXPORT_VIEW_PROPERTY(hidden) -RCT_EXPORT_VIEW_PROPERTY(backgroundColor) -RCT_REMAP_VIEW_PROPERTY(accessible, isAccessibilityElement) -RCT_REMAP_VIEW_PROPERTY(testID, accessibilityIdentifier) -RCT_REMAP_VIEW_PROPERTY(opacity, alpha) -RCT_REMAP_VIEW_PROPERTY(shadowColor, layer.shadowColor); -RCT_REMAP_VIEW_PROPERTY(shadowOffset, layer.shadowOffset); -RCT_REMAP_VIEW_PROPERTY(shadowOpacity, layer.shadowOpacity) -RCT_REMAP_VIEW_PROPERTY(shadowRadius, layer.shadowRadius) -RCT_REMAP_VIEW_PROPERTY(borderColor, layer.borderColor); -RCT_REMAP_VIEW_PROPERTY(borderRadius, layer.cornerRadius) -RCT_REMAP_VIEW_PROPERTY(borderWidth, layer.borderWidth) -RCT_REMAP_VIEW_PROPERTY(transformMatrix, layer.transform) -RCT_CUSTOM_VIEW_PROPERTY(overflow, UIView *) -{ - view.clipsToBounds = json ? ![RCTConvert css_overflow:json] : defaultView.clipsToBounds; -} -RCT_CUSTOM_VIEW_PROPERTY(pointerEvents, RCTView *) -{ - if ([view respondsToSelector:@selector(setPointerEvents:)]) { - view.pointerEvents = json ? [RCTConvert RCTPointerEvents:json] : defaultView.pointerEvents; - return; - } - - if (!json) { - view.userInteractionEnabled = defaultView.userInteractionEnabled; - return; - } - - switch ([RCTConvert NSInteger:json]) { - case RCTPointerEventsUnspecified: - // Pointer events "unspecified" acts as if a stylesheet had not specified, - // which is different than "auto" in CSS (which cannot and will not be - // supported in `ReactKit`. "auto" may override a parent's "none". - // Unspecified values do not. - // This wouldn't override a container view's `userInteractionEnabled = NO` - view.userInteractionEnabled = YES; - case RCTPointerEventsNone: - view.userInteractionEnabled = NO; - break; - default: - RCTLogError(@"UIView base class does not support pointerEvent value: %@", json); - } -} - -// ShadowView properties - -RCT_CUSTOM_SHADOW_PROPERTY(backgroundColor, RCTShadowView *) -{ - view.backgroundColor = json ? [RCTConvert UIColor:json] : defaultView.backgroundColor; - view.isBGColorExplicitlySet = json ? YES : defaultView.isBGColorExplicitlySet; -} -RCT_CUSTOM_SHADOW_PROPERTY(flexDirection, RCTShadowView *) -{ - view.flexDirection = json? [RCTConvert css_flex_direction_t:json] : defaultView.flexDirection; -} -RCT_CUSTOM_SHADOW_PROPERTY(flexWrap, RCTShadowView *) -{ - view.flexWrap = json ? [RCTConvert css_wrap_type_t:json] : defaultView.flexWrap; -} -RCT_CUSTOM_SHADOW_PROPERTY(justifyContent, RCTShadowView *) -{ - view.justifyContent = json ? [RCTConvert css_justify_t:json] : defaultView.justifyContent; -} -RCT_CUSTOM_SHADOW_PROPERTY(alignItems, RCTShadowView *) -{ - view.alignItems = json ? [RCTConvert css_align_t:json] : defaultView.alignItems; -} -RCT_CUSTOM_SHADOW_PROPERTY(alignSelf, RCTShadowView *) -{ - view.alignSelf = json ? [RCTConvert css_align_t:json] : defaultView.alignSelf; -} -RCT_CUSTOM_SHADOW_PROPERTY(position, RCTShadowView *) -{ - view.positionType = json ? [RCTConvert css_position_type_t:json] : defaultView.positionType; -} - -@end diff --git a/ReactKit/Views/RCTViewNodeProtocol.h b/ReactKit/Views/RCTViewNodeProtocol.h deleted file mode 100644 index 71422b2c8af..00000000000 --- a/ReactKit/Views/RCTViewNodeProtocol.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -/** - * Logical node in a tree of application components. Both `ShadowView`s and - * `UIView+ReactKit`s conform to this. Allows us to write utilities that - * reason about trees generally. - */ -@protocol RCTViewNodeProtocol - -@property (nonatomic, copy) NSNumber *reactTag; - -- (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex; -- (void)removeReactSubview:(id)subview; -- (NSMutableArray *)reactSubviews; -- (id)reactSuperview; -- (NSNumber *)reactTagAtPoint:(CGPoint)point; - -// View is an RCTRootView -- (BOOL)isReactRootView; - -@optional - -// TODO: Deprecate this -// This method is called after layout has been performed for all views known -// to the RCTViewManager. It is only called on UIViews, not shadow views. -- (void)reactBridgeDidFinishTransaction; - -@end - -// TODO: this is kinda dumb - let's come up with a -// better way of identifying root react views please! -static inline BOOL RCTIsReactRootView(NSNumber *reactTag) { - return reactTag.integerValue % 10 == 1; -} diff --git a/ReactKit/Views/RCTWrapperViewController.h b/ReactKit/Views/RCTWrapperViewController.h deleted file mode 100644 index afe736430c2..00000000000 --- a/ReactKit/Views/RCTWrapperViewController.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTViewControllerProtocol.h" - -@class RCTEventDispatcher; -@class RCTNavItem; -@class RCTWrapperViewController; - -@protocol RCTWrapperViewControllerNavigationListener - -- (void)wrapperViewController:(RCTWrapperViewController *)wrapperViewController -didMoveToNavigationController:(UINavigationController *)navigationController; - -@end - -@interface RCTWrapperViewController : UIViewController - -- (instancetype)initWithContentView:(UIView *)contentView - eventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithNavItem:(RCTNavItem *)navItem - eventDispatcher:(RCTEventDispatcher *)eventDispatcher; - -@property (nonatomic, weak) id navigationListener; -@property (nonatomic, strong) RCTNavItem *navItem; - -@end diff --git a/ReactKit/Views/RCTWrapperViewController.m b/ReactKit/Views/RCTWrapperViewController.m deleted file mode 100644 index aff0f2e4fc3..00000000000 --- a/ReactKit/Views/RCTWrapperViewController.m +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "RCTWrapperViewController.h" - -#import - -#import "RCTEventDispatcher.h" -#import "RCTNavItem.h" -#import "RCTUtils.h" -#import "RCTViewControllerProtocol.h" -#import "UIView+ReactKit.h" - -@implementation RCTWrapperViewController -{ - UIView *_wrapperView; - UIView *_contentView; - RCTEventDispatcher *_eventDispatcher; - CGFloat _previousTopLayout; - CGFloat _previousBottomLayout; -} - -@synthesize currentTopLayoutGuide = _currentTopLayoutGuide; -@synthesize currentBottomLayoutGuide = _currentBottomLayoutGuide; - -- (instancetype)initWithContentView:(UIView *)contentView - eventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ - if (self = [super initWithNibName:nil bundle:nil]) { - _contentView = contentView; - _eventDispatcher = eventDispatcher; - self.automaticallyAdjustsScrollViewInsets = NO; - } - return self; -} - -- (instancetype)initWithNavItem:(RCTNavItem *)navItem - eventDispatcher:(RCTEventDispatcher *)eventDispatcher -{ - if (self = [self initWithContentView:navItem eventDispatcher:eventDispatcher]) { - _navItem = navItem; - } - return self; -} - -- (void)viewWillLayoutSubviews -{ - [super viewWillLayoutSubviews]; - - _currentTopLayoutGuide = self.topLayoutGuide; - _currentBottomLayoutGuide = self.bottomLayoutGuide; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - // TODO: find a way to make this less-tightly coupled to navigation controller - if ([self.parentViewController isKindOfClass:[UINavigationController class]]) - { - - [self.navigationController setNavigationBarHidden:!_navItem animated:animated]; - if (!_navItem) { - return; - } - - self.navigationItem.title = _navItem.title; - - UINavigationBar *bar = self.navigationController.navigationBar; - if (_navItem.barTintColor) { - bar.barTintColor = _navItem.barTintColor; - } - if (_navItem.tintColor) { - BOOL canSetTintColor = _navItem.barTintColor == nil; - if (canSetTintColor) { - bar.tintColor = _navItem.tintColor; - } - } - if (_navItem.titleTextColor) { - [bar setTitleTextAttributes:@{NSForegroundColorAttributeName : _navItem.titleTextColor}]; - } - - if (_navItem.rightButtonTitle.length > 0) { - self.navigationItem.rightBarButtonItem = - [[UIBarButtonItem alloc] initWithTitle:_navItem.rightButtonTitle - style:UIBarButtonItemStyleDone - target:self - action:@selector(handleNavRightButtonTapped)]; - } - - if (_navItem.backButtonTitle.length > 0) { - self.navigationItem.backBarButtonItem = - [[UIBarButtonItem alloc] initWithTitle:_navItem.backButtonTitle - style:UIBarButtonItemStylePlain - target:nil - action:nil]; - } - } -} - -- (void)loadView -{ - // add a wrapper so that UIViewControllerWrapperView (managed by the - // UINavigationController) doesn't end up resetting the frames for - //`contentView` which is a react-managed view. - _wrapperView = [[UIView alloc] initWithFrame:_contentView.bounds]; - [_wrapperView addSubview:_contentView]; - self.view = _wrapperView; -} - -- (void)handleNavRightButtonTapped -{ - [_eventDispatcher sendInputEventWithName:@"topNavRightButtonTap" - body:@{@"target":_navItem.reactTag}]; -} - -- (void)didMoveToParentViewController:(UIViewController *)parent -{ - // There's no clear setter for navigation controllers, but did move to parent - // view controller provides the desired effect. This is called after a pop - // finishes, be it a swipe to go back or a standard tap on the back button - [super didMoveToParentViewController:parent]; - if (parent == nil || [parent isKindOfClass:[UINavigationController class]]) { - [self.navigationListener wrapperViewController:self didMoveToNavigationController:(UINavigationController *)parent]; - } -} - -@end diff --git a/ReactKit/Views/UIView+ReactKit.h b/ReactKit/Views/UIView+ReactKit.h deleted file mode 100644 index 9f0213a6364..00000000000 --- a/ReactKit/Views/UIView+ReactKit.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import - -#import "RCTViewNodeProtocol.h" - -//TODO: let's try to eliminate this category if possible - -@interface UIView (ReactKit) - -/** - * This method finds and returns the containing view controller for the view. - */ -- (UIViewController *)backingViewController; - -/** - * This method attaches the specified controller as a child of the - * the owning view controller of this view. Returns NO if no view - * controller is found (which may happen if the view is not currently - * attached to the view hierarchy). - */ -- (void)addControllerToClosestParent:(UIViewController *)controller; - -@end diff --git a/ReactKit/Views/UIView+ReactKit.m b/ReactKit/Views/UIView+ReactKit.m deleted file mode 100644 index a9feb8eed99..00000000000 --- a/ReactKit/Views/UIView+ReactKit.m +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#import "UIView+ReactKit.h" - -#import - -#import "RCTAssert.h" -#import "RCTWrapperViewController.h" - -@implementation UIView (ReactKit) - -- (NSNumber *)reactTag -{ - return objc_getAssociatedObject(self, _cmd); -} - -- (void)setReactTag:(NSNumber *)reactTag -{ - objc_setAssociatedObject(self, @selector(reactTag), reactTag, OBJC_ASSOCIATION_COPY_NONATOMIC); -} - -- (BOOL)isReactRootView -{ - return RCTIsReactRootView(self.reactTag); -} - -- (NSNumber *)reactTagAtPoint:(CGPoint)point -{ - UIView *view = [self hitTest:point withEvent:nil]; - while (view && !view.reactTag) { - view = view.superview; - } - return view.reactTag; -} - -- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex -{ - [self insertSubview:subview atIndex:atIndex]; -} - -- (void)removeReactSubview:(UIView *)subview -{ - RCTAssert(subview.superview == self, @"%@ is a not a subview of %@", subview, self); - [subview removeFromSuperview]; -} - -- (NSArray *)reactSubviews -{ - return self.subviews; -} - -- (UIView *)reactSuperview -{ - return self.superview; -} - -- (UIViewController *)backingViewController -{ - id responder = [self nextResponder]; - if ([responder isKindOfClass:[RCTWrapperViewController class]]) { - return responder; - } - return nil; -} - -- (void)addControllerToClosestParent:(UIViewController *)controller -{ - if (!controller.parentViewController) { - UIView *parentView = (UIView *)self.reactSuperview; - while (parentView) { - if (parentView.backingViewController) { - [parentView.backingViewController addChildViewController:controller]; - [controller didMoveToParentViewController:parentView.backingViewController]; - break; - } - parentView = (UIView *)parentView.reactSuperview; - } - return; - } -} - -@end diff --git a/_index.html b/_index.html new file mode 100644 index 00000000000..58eaa647bb2 --- /dev/null +++ b/_index.html @@ -0,0 +1,12 @@ +React Native | Build Native Apps Using React
React Native
Build native apps using React

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/website/src/react-native/css/react-native.css b/css/react-native.css similarity index 100% rename from website/src/react-native/css/react-native.css rename to css/react-native.css diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md deleted file mode 100644 index eda46461b56..00000000000 --- a/docs/GettingStarted.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: getting-started -title: Getting Started -layout: docs -category: Quick Start -permalink: docs/getting-started.html -next: navigatorios ---- - - -Our first React Native implementation is `ReactKit`, targeting iOS. We are also -working on an Android implementation which we will release later. `ReactKit` -apps are built using the [React JS](https://github.com/facebook/react) framework, and render directly to -native UIKit elements using a fully asynchronous architecture. There is no -browser and no HTML. We have picked what we think is the best set of features -from these and other technologies to build what we hope to become the best -product development framework available, with an emphasis on iteration speed, -developer delight, continuity of technology, and absolutely beautiful and fast -products with no compromises in quality or capability. - -## Requirements - -1. OS X - This repo only contains the iOS implementation right now, and Xcode only runs on Mac. -2. New to Xcode? [Download it](https://developer.apple.com/xcode/downloads/) from the Mac App Store. -3. [Homebrew](http://brew.sh/) is the recommended way to install node, watchman, and flow. -4. New to node or npm? `brew install node` -5. We recommend installing [watchman](https://facebook.github.io/watchman/docs/install.html), otherwise you might hit a node file watching bug. `brew install watchman` -6. If you want to use [flow](http://www.flowtype.org), `brew install flow` - -## Quick start - -Get up and running with our Movies sample app: - -1. Once you have the repo cloned and met all the requirements above, start the -packager that will transform your JS code on-the-fly: - - ``` - npm install - npm start - ``` -2. Open the `Examples/Movies/Movies.xcodeproj` project in Xcode. -3. Make sure the target is set to `Movies` and that you have an iOS simulator -selected to run the app. -4. Build and run the project with the Xcode run button. - -You should now see the Movies app running on your iOS simulator. -Congratulations! You've just successfully run your first React Native app. - -Now try editing a JavaScript file and viewing your changes. Let's change the -movie search placeholder text: - -1. Open the `Examples/Movies/SearchScreen.js` file in your favorite JavaScript -editor. -2. Look for the current search placeholder text and change it to "Search for an -awesome movie...". -3. Hit cmd+R ([twice](http://openradar.appspot.com/19613391)) in your iOS simulator to reload the app and see your change. -If you don't immediately see your changes, try restarting your app within Xcode. - -Feel free to browse the Movies sample files and customize various properties to -get familiar with the codebase and React Native. - -Also check out the UI Component Explorer for more sample code: -`Examples/UIExplorer/UIExplorer.xcodeproj`. **Make sure to close the Movies -project first - Xcode will break if you have two projects open that reference -the same library.** - -## Troubleshooting - -+ Xcode will break if you have two examples open at the same time. -+ If `npm start` fails with log spew like: - ``` - 2015-02-02 10:56 node[24294] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21) - ``` -then you've hit the node file watching bug - `brew install watchman` should fix the issue. -+ Jest testing does not yet work on node versions after 0.10.x. -+ You can verify the packager is working by loading the [bundle](http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle) in your browser and -inspecting the contents. - -Please report any other issues you encounter so we can fix them ASAP. diff --git a/docs/Image.md b/docs/Image.md deleted file mode 100644 index 55b10bb402c..00000000000 --- a/docs/Image.md +++ /dev/null @@ -1,60 +0,0 @@ -Displaying images is a fascinating subject, React Native uses some cool tricks to make it a better experience. - -## No Automatic Sizing - -If you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience. - -In React Native, this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or just aspect ratio) of the image in advance, but we believe that it leads to a better user experience. - -## Background Image via Nesting - -A common feature request from developers familiar with the web is `background-image`. It turns out that iOS has a very elegant solution to this: you can add elements as a children to an `` component. This simplifies the API and solves the use case. - -```javascript -return ( - - Inside - -); -``` - -## Off-thread Decoding - -Image decoding can take more than a frame-worth of time. This is one of the major source of frame drops on the web because decoding is done in the main thread. In React Native, image decoding is done in a different thread. In practice, you already need to handle the case when the image is not downloaded yet, so displaying the placeholder for a few more frames while it is decoding does not require any code change. - -## Static Assets - -In the course of a project you add and remove images and in many instances, you end up shipping images you are not using anymore in the app. In order to fight this, we need to find a way to know statically which images are being used in the app. To do that, we introduced a marker called `ix`. The only allowed way to refer to an image in the bundle is to literally write `ix('name-of-the-asset')` in the source. - -```javascript -var { ix } = React; - -// GOOD - - -// BAD -var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive'; - - -// GOOD -var icon = this.props.active ? ix('my-icon-active') : ix('my-icon-inactive'); - -``` - -When your entire codebase respects this convention, you're able to do interesting things like automatically packaging the assets that are being used in your app. Note that in the current form, nothing is enforced, but it will be in the future. - -## Best Camera Roll Image - -iOS saves multiple sizes for the same image in your Camera Roll, it is very important to pick the one that's as close as possible for performance reasons. You wouldn't want to use the full quality 3264x2448 image as source when displaying a 200x200 thumbnail. If there's an exact match, React Native will pick it, otherwise it's going to use the first one that's at least 50% bigger in order to avoid blur when resizing from a close size. All of this is done by default so you don't have to worry about writing the tedious (and error prone) code to do it yourself. - -## Source being an object - -In React Native, one interesting decision is that the `src` attribute is named `source` and doesn't take a string but an object with an `uri` attribute. - -```javascript - -``` - -On the infrastructure side, the reason is that it allows to attach metadata to this object. For example if you are using `ix`, then we add a `isStored` attribute to flag it as a local file (don't rely on this fact, it's likely to change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting `{uri: ...}`, we can output `{uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}}` and transparently support spriting on all the existing call sites. - -On the user side, this lets you annotate the object with useful attributes such as the dimension of the image in order to compute the size it's going to be displayed in. Feel free to use it as your data structure to store more information about your image. diff --git a/docs/Network.md b/docs/Network.md deleted file mode 100644 index 831adccd2e5..00000000000 --- a/docs/Network.md +++ /dev/null @@ -1,42 +0,0 @@ -One of React Native goal is to be a playground where we can experiment with different architectures and crazy ideas. Since browsers are not flexible enough, we had no choice but to reimplement the entire stack. In the places that we did not intend to change, we tried to be as faithful as possible to the browser APIs, the networking stack is a great example. - -## XMLHttpRequest - -XMLHttpRequest API is implemented on-top of [iOS networking apis](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html). The notable difference from web is the security model: you can read from arbitrary websites on the internet, there isn't no concept of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). - -```javascript -var request = new XMLHttpRequest(); -request.onreadystatechange = (e) => { - if (request.readyState !== 4) { - return; - } - - if (request.status === 200) { - console.log('success', request.responseText); - } else { - console.warn('error'); - } -}; - -request.open('GET', 'https://mywebsite.com/endpoint.php'); -request.send(); -``` - -Please follow the [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) for a description of the API. - -As a developer, you're probably not going to use XMLHttpRequest directly as its API is very tedious to work with. But the fact that it is implemented and compatible with the browser one gives you the ability to use third-party libraries such as [Parse JS SDK](https://parse.com/docs/js_guide) or [super-agent](https://github.com/visionmedia/superagent) directly from npm. - -## Fetch - -[fetch](https://fetch.spec.whatwg.org/) is a better API being worked on by the standard committee and already available in Chrome. It is available in React Native by default. - -```javascript -fetch('https://mywebsite.com/endpoint.php') - .then((response) => response.text()) - .then((responseText) => { - console.log(responseText); - }) - .catch((error) => { - console.warn(error); - }); -``` diff --git a/docs/Physical vs Logical Pixels.md b/docs/Physical vs Logical Pixels.md deleted file mode 100644 index 25ba6e8841f..00000000000 --- a/docs/Physical vs Logical Pixels.md +++ /dev/null @@ -1,31 +0,0 @@ - - -## Pixel Grid Snapping - -In iOS, you can specify positions and dimensions for elements with arbitrary precision, for example 29.674825. But, ultimately the physical display only have a fixed number of pixels, for example 640×960 for iphone 4 or 750×1334 for iphone 6. iOS tries to be as faithful as possible to the user value by spreading one original pixel into multiple ones to be trick the eye. The downside of this technique is that it makes the resulting element look blurry. - -In practice, we found out that developers do not want this feature and they have to work around it by doing manual rounding in order to avoid having blurry elements. In React Native, we are rounding all the pixels automatically. - -We have to be careful when to do this rounding. You never want to work with rounded and unrounded values at the same time as you're going to accumulate rounding errors. Having even one rounding error is deadly because a one pixel border may vanish or be twice as big. - -In React Native, everything in JS and within the layout engine work with arbitrary precision numbers. It's only when we set the position and dimensions of the native element on the main thread that we round. Also, rounding is done relative to the root rather than the parent, again to avoid accumulating rounding errors. - -## Displaying a line that's as thin as the device permits - -A width of 1 is actually 2 physical pixels thick on an iPhone 4 and ~3 physical pixels thick on an iphone 6+. If you want to display a line that's as thin as possible, you can use a width of `1 / PixelRatio.get()`. It's a technique that works on all the devices independent of their pixel density. - -```javascript -style={{ borderWidth: 1 / PixelRatio.get() }} -``` - -## Fetching a correctly sized image - -You should get a higher resolution image if you are on a high pixel density device. A good rule of thumb is to multiply the size of the image you display by the pixel ratio. - -```javascript -var image = getImage({ - width: 200 * PixelRatio.get(), - height: 100 * PixelRatio.get(), -}); - -``` diff --git a/docs/Style.md b/docs/Style.md deleted file mode 100644 index b5738944b08..00000000000 --- a/docs/Style.md +++ /dev/null @@ -1,79 +0,0 @@ - -## Declaring Styles - -The way to declare styles in React Native is the following: - -```javascript -var styles = StyleSheet.create({ - base: { - width: 38, - height: 38, - }, - background: { - backgroundColor: '#222222', - }, - active: { - borderWidth: 2, - borderColor: '#00ff00', - }, -}); -``` - -`StyleSheet.create` construct is optional but provides some key advantages. It ensures that the values are **immutable** and **opaque** by transforming them into plain numbers that reference an internal table. By putting it at the end of the file, you also ensure that they are only created once for the application and not on every render. - -## Using Styles - -All the core components accept a style attribute - -```javascript - - -``` - -and also accepts an array of styles - -```javascript - -``` - -The behavior is the same as `Object.assign`: in case of conflicting values, the one from the right-most element will have precedence and falsy values like `false`, `undefined` and `null` will be ignored. A common pattern is to conditionally add a style based on some condition. - -```javascript - -``` - -Finally, if you really have to, you can also create style objects in render, but they are highly discouraged. Put them last in the array definition. - -```javascript - -``` - -## Pass Styles Around - -In order to let a call site customize the style of your component children, you can pass styles around. Use `View.stylePropType` and `Text.stylePropType` in order to make sure only styles are being passed. - -```javascript -var List = React.createClass({ - propTypes: { - style: View.stylePropType, - elementStyle: View.stylePropType, - }, - render: function() { - return ( - - {elements.map((element) => - - )} - - ); - } -}); - -// ... in another file ... - -``` diff --git a/docs/Text.md b/docs/Text.md deleted file mode 100644 index f830582c9c1..00000000000 --- a/docs/Text.md +++ /dev/null @@ -1,103 +0,0 @@ - - -## Nested Text - -In iOS, the way to display formatted text is by using `NSAttributedString`: you give the text that you want to display and annotate ranges with some specific formatting. In practice, this is very tedious. For React Native, we decided to use web paradigm for this where you can nest text to achieve the same effect. - -```javascript - - I am bold - - and red - - -``` - -Behind the scenes, this is going to be converted to a flat NSAttributedString that contains the following information - -```javascript -"I am bold and red" -0-9: bold -9-17: bold, red -``` - -## Containers - -The `` element is special relative to layout, everything inside is no longer using the flexbox layout but using text layout. This means that elements inside of a `` are no longer rectangles but wrap when they see the end of the line. - -```javascript - - First part and - second part - -// Text container: all the text flows as if it was one -// |First part | -// |and second | -// |part | - - - First part and - second part - -// View container: each text is its own block -// |First part | -// |and | -// |second part| -``` - -## Limited Style Inheritance - -On the web, the usual way to set a font family and size for the entire document is to write - -```css -/* CSS, *not* React Native */ -html { - font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; - font-size: 11px; - color: #141823; -} -``` - -When the browser is trying to render a text node, it's going to go all the way up to the root element of the tree and find an element with a `font-size` attribute. An unexpected property with this system is that **any** node can have `font-size` attribute, including a `
`. The reason why it was designed this way is that it is convenient, even though not really semantically correct. - -In React Native, we are more strict about it. The first place where it'll show up is that you have to wrap all the text nodes inside of a `` component. It is not allowed to have a text node directly under a ``. - -```javascript -// BAD: will fatal, can't have a text node as child of a - - Some text - - -// GOOD - - - Some text - - -``` - -You also lose the ability to setup a default font for an entire subtree. The recommended way to use consistent fonts and sizes across your application is to create a component `MyAppText` that's going to set them and use this component all across your app. You can also make other components such as `MyAppHeaderText` for other kind of texts. - -```javascript - - Text styled with the default font for the entire application - Text styled as a header - -``` - -React Native still has the concept of style inheritance, but limited to text subtrees. In this case, the second part will be both bold and red. - -```javascript - - I am bold - - and red - - -``` - -We believe that this more constrained way to style text will yield better apps. - -- (Developper) React components are designed with strong isolation properties in mind, you should be able to drop a component anywhere in your application and it will look and behave the same way, as long as the props are the same. Having text properties be inherited from outside of the props breaks isolation. - -- (Implementor) The implementation of React Native is also simplified. We do not need to have a `fontFamily` field on every single element and we do not need to potentially traverse the tree up to the root every time we display a text node. The style inheritance is only encoded inside of the native Text component and doesn't leak to other components or the system itself. diff --git a/docs/Timers.md b/docs/Timers.md deleted file mode 100644 index 5cec2df9a63..00000000000 --- a/docs/Timers.md +++ /dev/null @@ -1,66 +0,0 @@ -Timers are an important part of an application and React Native implements the [browser timers](https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Timers). - -## Timers - -- setTimeout, clearTimeout -- setInterval, clearInterval -- setImmediate, clearImmediate -- requestAnimationFrame, cancelAnimationFrame - -`requestAnimationFrame(fn)` is the exact equivalent of `setTimeout(fn, 0)`, they are triggered right after the screen has been flushed. - -`setImmediate` is executed at the end of the current JavaScript execution block, right before sending the batched response back to native. Note that if you call `setImmediate` within a `setImmediate` callback, it will be executed right away, it won't yield back to native in between. - -The `Promise` implementation uses `setImmediate` its asynchronicity primitive. - - -## InteractionManager - -One reason why native apps feel so good performance wise is that barely any work is being done during an interaction/animation. In React Native, you can use `InteractionManager` that allows long-running work to be scheduled after any interactions/animations have completed. - -Applications can schedule tasks to run after interactions with the following: - -```javascript -InteractionManager.runAfterInteractions(() => { - // ...long-running synchronous task... -}); -``` - -Compare this to other scheduling alternatives: - -- requestAnimationFrame(): for code that animates a view over time. -- setImmediate/setTimeout/setInterval(): run code later, note this may delay animations. -- runAfterInteractions(): run code later, without delaying active animations. - -The touch handling system considers one or more active touches to be an 'interaction' and will delay `runAfterInteractions()` callbacks until all touches have ended or been cancelled. - -InteractionManager also allows applications to register animations by creating an interaction 'handle' on animation start, and clearing it upon completion: - -```javascript -var handle = InteractionManager.createInteractionHandle(); -// run animation... (`runAfterInteractions` tasks are queued) -// later, on animation completion: -InteractionManager.clearInteractionHandle(handle); -// queued tasks run if all handles were cleared -``` - - -## TimerMixin - -We found out that the primary cause of fatals in apps created with React Native was due to timers firing after a component was unmounted. To solve this recurring issue, we introduced `TimerMixin`. If you include `TimerMixin`, then you can replace your calls to `setTimeout(fn, 500)` with `this.setTimeout(fn, 500)` (just prepend `this.`) and everything will be properly cleaned up for you when the component unmounts. - -```javascript -var { TimerMixin } = React; - -var Component = React.createClass({ - mixins: [TimerMixin], - componentDidMount: function() { - this.setTimeout( - () => { console.log('I do not leak!'); }, - 500 - ); - } -}); -``` - -We highly recommend never using bare timers and always using this mixin, it will save you from a lot of hard to track down bugs. diff --git a/docs/activityindicatorios.html b/docs/activityindicatorios.html new file mode 100644 index 00000000000..ea0fae33de9 --- /dev/null +++ b/docs/activityindicatorios.html @@ -0,0 +1,13 @@ +React Native | Build Native Apps Using React
\ No newline at end of file diff --git a/docs/animation.html b/docs/animation.html new file mode 100644 index 00000000000..b961930adb5 --- /dev/null +++ b/docs/animation.html @@ -0,0 +1,91 @@ +React Native | Build Native Apps Using React

Animation

@flow

static startAnimation(node: any, duration: number, delay: number, easing: (string | EasingFunction), properties: {[key: string]: any}) #

static stopAnimation(tag: number) #

{
+  "methods": [
+    {
+      "line": 17,
+      "source": "startAnimation: function(\n    node: any,\n    duration: number,\n    delay: number,\n    easing: (string | EasingFunction),\n    properties: {[key: string]: any}\n  ): number {\n    var nodeHandle = +node.getNodeHandle();\n    var easingSample = AnimationUtils.evaluateEasingFunction(duration, easing);\n    var tag: number = RCTAnimationManager.startAnimation(nodeHandle, AnimationUtils.allocateTag(), duration, delay, easingSample, properties);\n    return tag;\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "any",
+          "name": "node"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"number\",\"length\":1}",
+          "name": "duration"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"number\",\"length\":1}",
+          "name": "delay"
+        },
+        {
+          "typehint": "(string | EasingFunction)",
+          "name": "easing"
+        },
+        {
+          "typehint": "{[key: string]: any}",
+          "name": "properties"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "{\"type\":\"simple\",\"value\":\"number\",\"length\":1}",
+      "name": "startAnimation"
+    },
+    {
+      "line": 30,
+      "source": "stopAnimation: function(tag: number) {\n    RCTAnimationManager.stopAnimation(tag);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"number\",\"length\":1}",
+          "name": "tag"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "stopAnimation"
+    }
+  ],
+  "properties": [
+    [
+      [
+        "static"
+      ],
+      "",
+      "Mixin",
+      "require('AnimationMixin')",
+      "",
+      15
+    ]
+  ],
+  "superClass": null,
+  "type": "api",
+  "line": 14,
+  "name": "Animation",
+  "docblock": "/**\n *\n * @flow\n */\n",
+  "requires": [
+    {
+      "name": "NativeModules"
+    },
+    {
+      "name": "AnimationUtils"
+    },
+    {
+      "name": "AnimationMixin"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/appregistry.html b/docs/appregistry.html new file mode 100644 index 00000000000..2a876806bc4 --- /dev/null +++ b/docs/appregistry.html @@ -0,0 +1,111 @@ +React Native | Build Native Apps Using React

AppRegistry

AppRegistry is the JS entry point to running all React Native apps. App +root components should register themselves with +AppRegistry.registerComponent, then the native system can load the bundle +for the app and then actually run the app when it's ready by invoking +AppRegistry.runApplication.

AppRegistry should be required early in the require sequence to make +sure the JS execution environment is setup before other modules are +required.

static registerConfig(config) #

static registerComponent(appKey, getComponentFunc) #

static registerRunnable(appKey, func) #

static runApplication(appKey, appParameters) #

{
+  "methods": [
+    {
+      "line": 31,
+      "source": "registerConfig: function(config) {\n    for (var i = 0; i < config.length; ++i) {\n      if (config[i].run) {\n        AppRegistry.registerRunnable(config[i].appKey, config[i].run);\n      } else {\n        AppRegistry.registerComponent(config[i].appKey, config[i].component);\n      }\n    }\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "config"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "registerConfig"
+    },
+    {
+      "line": 41,
+      "source": "registerComponent: function(appKey, getComponentFunc) {\n    runnables[appKey] = {\n      run: (appParameters) =>\n        renderApplication(getComponentFunc(), appParameters.initialProps, appParameters.rootTag)\n    };\n    return appKey;\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "appKey"
+        },
+        {
+          "typehint": null,
+          "name": "getComponentFunc"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "registerComponent"
+    },
+    {
+      "line": 49,
+      "source": "registerRunnable: function(appKey, func) {\n    runnables[appKey] = {run: func};\n    return appKey;\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "appKey"
+        },
+        {
+          "typehint": null,
+          "name": "func"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "registerRunnable"
+    },
+    {
+      "line": 54,
+      "source": "runApplication: function(appKey, appParameters) {\n    console.log(\n      'Running application \"' + appKey + '\" with appParams: ' +\n      JSON.stringify(appParameters) + '. ' +\n      '__DEV__ === ' + __DEV__ +\n      ', development-level warning are ' + (__DEV__ ? 'ON' : 'OFF') +\n      ', performance optimizations are ' + (__DEV__ ? 'OFF' : 'ON')\n    );\n    invariant(\n      runnables[appKey] && runnables[appKey].run,\n      'Application ' + appKey + ' has not been registered.'\n    );\n    runnables[appKey].run(appParameters);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "appKey"
+        },
+        {
+          "typehint": null,
+          "name": "appParameters"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "runApplication"
+    }
+  ],
+  "properties": [],
+  "superClass": null,
+  "type": "api",
+  "line": 30,
+  "name": "AppRegistry",
+  "docblock": "/**\n * `AppRegistry` is the JS entry point to running all React Native apps.  App\n * root components should register themselves with\n * `AppRegistry.registerComponent`, then the native system can load the bundle\n * for the app and then actually run the app when it's ready by invoking\n * `AppRegistry.runApplication`.\n *\n * `AppRegistry` should be `require`d early in the `require` sequence to make\n * sure the JS execution environment is setup before other modules are\n * `require`d.\n */\n",
+  "requires": [
+    {
+      "name": "invariant"
+    },
+    {
+      "name": "renderApplication"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/appstate.html b/docs/appstate.html new file mode 100644 index 00000000000..4e96d5db960 --- /dev/null +++ b/docs/appstate.html @@ -0,0 +1,67 @@ +React Native | Build Native Apps Using React

AppState

static setApplicationIconBadgeNumber(number) #

static getApplicationIconBadgeNumber(callback) #

{
+  "methods": [
+    {
+      "line": 18,
+      "source": "setApplicationIconBadgeNumber: function(number) {\n    RKAppState.setApplicationIconBadgeNumber(number);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "number"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "setApplicationIconBadgeNumber"
+    },
+    {
+      "line": 22,
+      "source": "getApplicationIconBadgeNumber: function(callback) {\n    RKAppState.getApplicationIconBadgeNumber(callback);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "getApplicationIconBadgeNumber"
+    }
+  ],
+  "properties": [],
+  "superClass": null,
+  "type": "api",
+  "line": 16,
+  "name": "AppState",
+  "docblock": "/**\n *\n */\n",
+  "requires": [
+    {
+      "name": "NativeModulesDeprecated"
+    },
+    {
+      "name": "RCTDeviceEventEmitter"
+    },
+    {
+      "name": "Subscribable"
+    },
+    {
+      "name": "keyMirror"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/appstateios.html b/docs/appstateios.html new file mode 100644 index 00000000000..2f264400ff7 --- /dev/null +++ b/docs/appstateios.html @@ -0,0 +1,70 @@ +React Native | Build Native Apps Using React

AppStateIOS

static addEventListener(type, handler) #

static removeEventListener(type, handler) #

{
+  "methods": [
+    {
+      "line": 20,
+      "source": "static addEventListener(type, handler) {\n    _appStateHandlers[handler] = RCTDeviceEventEmitter.addListener(\n      DEVICE_APPSTATE_EVENT,\n      (appStateData) => {\n        handler(appStateData.app_state);\n      }\n    );\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "type"
+        },
+        {
+          "typehint": null,
+          "name": "handler"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "addEventListener"
+    },
+    {
+      "line": 29,
+      "source": "static removeEventListener(type, handler) {\n    if (!_appStateHandlers[handler]) {\n      return;\n    }\n    _appStateHandlers[handler].remove();\n    _appStateHandlers[handler] = null;\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "type"
+        },
+        {
+          "typehint": null,
+          "name": "handler"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "removeEventListener"
+    }
+  ],
+  "type": "api",
+  "line": 18,
+  "name": "AppStateIOS",
+  "docblock": "/**\n *\n */\n",
+  "requires": [
+    {
+      "name": "NativeModules"
+    },
+    {
+      "name": "RCTDeviceEventEmitter"
+    },
+    {
+      "name": "logError"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/asyncstorage.html b/docs/asyncstorage.html new file mode 100644 index 00000000000..dc93319c07a --- /dev/null +++ b/docs/asyncstorage.html @@ -0,0 +1,246 @@ +React Native | Build Native Apps Using React

AsyncStorage

AsyncStorage is a simple, asynchronous, persistent, global, key-value storage +system. It should be used instead of LocalStorage.

It is recommended that you use an abstraction on top of AsyncStorage instead +of AsyncStorage directly for anything more than light usage since it +operates globally.

This JS code is a simple facad over the native iOS implementation to provide +a clear JS API, real Error objects, and simple non-multi functions.

static getItem(key: string, callback: (error: ?Error, result: ?string) => void) #

Fetches key and passes the result to callback, along with an Error if +there is any.

static setItem(key: string, value: string, callback: ?(error: ?Error) => void) #

Sets value for key and calls callback on completion, along with an +Error if there is any.

static removeItem(key: string, callback: ?(error: ?Error) => void) #

static mergeItem(key: string, value: string, callback: ?(error: ?Error) => void) #

Merges existing value with input value, assuming they are stringified json.

Not supported by all native implementations.

static clear(callback: ?(error: ?Error) => void) #

Erases all AsyncStorage for all clients, libraries, etc. You probably +don't want to call this - use removeItem or multiRemove to clear only your +own keys instead.

static getAllKeys(callback: (error: ?Error) => void) #

Gets all keys known to the system, for all callers, libraries, etc.

static multiGet(keys: :({"type":"generic","value":[{"type":"simple","value":"Array","length":1},{"type":"simple","value":"string","length":1}],"length":4}, callback: (errors: ?Array<Error>, result: ?Array<Array<string>>) => void) #

multiGet invokes callback with an array of key-value pair arrays that +matches the input format of multiSet.

multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])

static multiSet(keyValuePairs: :({"type":"generic","value":[{"type":"simple","value":"Array","length":1},{"type":"generic","value":[{"type":"simple","value":"Array","length":1},{"type":"simple","value":"string","length":1}],"length":4}],"length":7}, callback: ?(errors: ?Array<Error>) => void) #

multiSet and multiMerge take arrays of key-value array pairs that match +the output of multiGet, e.g.

multiSet([['k1', 'val1'], ['k2', 'val2']], cb);

static multiRemove(keys: :({"type":"generic","value":[{"type":"simple","value":"Array","length":1},{"type":"simple","value":"string","length":1}],"length":4}, callback: ?(errors: ?Array<Error>) => void) #

Delete all the keys in the keys array.

static multiMerge(keyValuePairs: :({"type":"generic","value":[{"type":"simple","value":"Array","length":1},{"type":"generic","value":[{"type":"simple","value":"Array","length":1},{"type":"simple","value":"string","length":1}],"length":4}],"length":7}, callback: ?(errors: ?Array<Error>) => void) #

Merges existing values with input values, assuming they are stringified +json.

Not supported by all native implementations.

{
+  "methods": [
+    {
+      "line": 32,
+      "source": "getItem: function(\n    key: string,\n    callback: (error: ?Error, result: ?string) => void\n  ): void {\n    RKAsyncStorage.multiGet([key], function(errors, result) {\n      // Unpack result to get value from [[key,value]]\n      var value = (result && result[0] && result[0][1]) ? result[0][1] : null;\n      callback((errors && convertError(errors[0])) || null, value);\n    });\n  }",
+      "docblock": "/**\n   * Fetches `key` and passes the result to `callback`, along with an `Error` if\n   * there is any.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "key"
+        },
+        {
+          "typehint": "(error: ?Error, result: ?string) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "getItem"
+    },
+    {
+      "line": 47,
+      "source": "setItem: function(\n    key: string,\n    value: string,\n    callback: ?(error: ?Error) => void\n  ): void {\n    RKAsyncStorage.multiSet([[key,value]], function(errors) {\n      callback && callback((errors && convertError(errors[0])) || null);\n    });\n  }",
+      "docblock": "/**\n   * Sets `value` for `key` and calls `callback` on completion, along with an\n   * `Error` if there is any.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "key"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "value"
+        },
+        {
+          "typehint": "?(error: ?Error) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "setItem"
+    },
+    {
+      "line": 57,
+      "source": "removeItem: function(\n    key: string,\n    callback: ?(error: ?Error) => void\n  ): void {\n    RKAsyncStorage.multiRemove([key], function(errors) {\n      callback && callback((errors && convertError(errors[0])) || null);\n    });\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "key"
+        },
+        {
+          "typehint": "?(error: ?Error) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "removeItem"
+    },
+    {
+      "line": 71,
+      "source": "mergeItem: function(\n    key: string,\n    value: string,\n    callback: ?(error: ?Error) => void\n  ): void {\n    RKAsyncStorage.multiMerge([[key,value]], function(errors) {\n      callback && callback((errors && convertError(errors[0])) || null);\n    });\n  }",
+      "docblock": "/**\n   * Merges existing value with input value, assuming they are stringified json.\n   *\n   * Not supported by all native implementations.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "key"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "value"
+        },
+        {
+          "typehint": "?(error: ?Error) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "mergeItem"
+    },
+    {
+      "line": 86,
+      "source": "clear: function(callback: ?(error: ?Error) => void) {\n    RKAsyncStorage.clear(function(error) {\n      callback && callback(convertError(error));\n    });\n  }",
+      "docblock": "/**\n   * Erases *all* AsyncStorage for all clients, libraries, etc.  You probably\n   * don't want to call this - use removeItem or multiRemove to clear only your\n   * own keys instead.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "?(error: ?Error) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "clear"
+    },
+    {
+      "line": 95,
+      "source": "getAllKeys: function(callback: (error: ?Error) => void) {\n    RKAsyncStorage.getAllKeys(function(error, keys) {\n      callback(convertError(error), keys);\n    });\n  }",
+      "docblock": "/**\n   * Gets *all* keys known to the system, for all callers, libraries, etc.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "(error: ?Error) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "getAllKeys"
+    },
+    {
+      "line": 117,
+      "source": "multiGet: function(\n    keys: Array<string>,\n    callback: (errors: ?Array<Error>, result: ?Array<Array<string>>) => void\n  ): void {\n    RKAsyncStorage.multiGet(keys, function(errors, result) {\n      callback(\n        (errors && errors.map((error) => convertError(error))) || null,\n        result\n      );\n    });\n  }",
+      "docblock": "/**\n   * multiGet invokes callback with an array of key-value pair arrays that\n   * matches the input format of multiSet.\n   *\n   *   multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"generic\",\"value\":[{\"type\":\"simple\",\"value\":\"Array\",\"length\":1},{\"type\":\"simple\",\"value\":\"string\",\"length\":1}],\"length\":4}",
+          "name": "keys"
+        },
+        {
+          "typehint": "(errors: ?Array<Error>, result: ?Array<Array<string>>) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "multiGet"
+    },
+    {
+      "line": 135,
+      "source": "multiSet: function(\n    keyValuePairs: Array<Array<string>>,\n    callback: ?(errors: ?Array<Error>) => void\n  ): void {\n    RKAsyncStorage.multiSet(keyValuePairs, function(errors) {\n      callback && callback(\n        (errors && errors.map((error) => convertError(error))) || null\n      );\n    });\n  }",
+      "docblock": "/**\n   * multiSet and multiMerge take arrays of key-value array pairs that match\n   * the output of multiGet, e.g.\n   *\n   *   multiSet([['k1', 'val1'], ['k2', 'val2']], cb);\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"generic\",\"value\":[{\"type\":\"simple\",\"value\":\"Array\",\"length\":1},{\"type\":\"generic\",\"value\":[{\"type\":\"simple\",\"value\":\"Array\",\"length\":1},{\"type\":\"simple\",\"value\":\"string\",\"length\":1}],\"length\":4}],\"length\":7}",
+          "name": "keyValuePairs"
+        },
+        {
+          "typehint": "?(errors: ?Array<Error>) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "multiSet"
+    },
+    {
+      "line": 149,
+      "source": "multiRemove: function(\n    keys: Array<string>,\n    callback: ?(errors: ?Array<Error>) => void\n  ): void {\n    RKAsyncStorage.multiRemove(keys, function(errors) {\n      callback && callback(\n        (errors && errors.map((error) => convertError(error))) || null\n      );\n    });\n  }",
+      "docblock": "/**\n   * Delete all the keys in the `keys` array.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"generic\",\"value\":[{\"type\":\"simple\",\"value\":\"Array\",\"length\":1},{\"type\":\"simple\",\"value\":\"string\",\"length\":1}],\"length\":4}",
+          "name": "keys"
+        },
+        {
+          "typehint": "?(errors: ?Array<Error>) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "multiRemove"
+    },
+    {
+      "line": 166,
+      "source": "multiMerge: function(\n    keyValuePairs: Array<Array<string>>,\n    callback: ?(errors: ?Array<Error>) => void\n  ): void {\n    RKAsyncStorage.multiMerge(keyValuePairs, function(errors) {\n      callback && callback(\n        (errors && errors.map((error) => convertError(error))) || null\n      );\n    });\n  }",
+      "docblock": "/**\n   * Merges existing values with input values, assuming they are stringified\n   * json.\n   *\n   * Not supported by all native implementations.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"generic\",\"value\":[{\"type\":\"simple\",\"value\":\"Array\",\"length\":1},{\"type\":\"generic\",\"value\":[{\"type\":\"simple\",\"value\":\"Array\",\"length\":1},{\"type\":\"simple\",\"value\":\"string\",\"length\":1}],\"length\":4}],\"length\":7}",
+          "name": "keyValuePairs"
+        },
+        {
+          "typehint": "?(errors: ?Array<Error>) => void",
+          "name": "callback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": "void",
+      "name": "multiMerge"
+    }
+  ],
+  "properties": [],
+  "superClass": null,
+  "type": "api",
+  "line": 27,
+  "name": "AsyncStorage",
+  "docblock": "/**\n * AsyncStorage is a simple, asynchronous, persistent, global, key-value storage\n * system.  It should be used instead of LocalStorage.\n *\n * It is recommended that you use an abstraction on top of AsyncStorage instead\n * of AsyncStorage directly for anything more than light usage since it\n * operates globally.\n *\n * This JS code is a simple facad over the native iOS implementation to provide\n * a clear JS API, real Error objects, and simple non-multi functions.\n */\n",
+  "requires": [
+    {
+      "name": "NativeModulesDeprecated"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/cameraroll.html b/docs/cameraroll.html new file mode 100644 index 00000000000..bd46e2f5572 --- /dev/null +++ b/docs/cameraroll.html @@ -0,0 +1,93 @@ +React Native | Build Native Apps Using React

CameraRoll

static saveImageWithTag(tag: string, successCallback, errorCallback) #

Saves the image with tag tag to the camera roll.

@param {string} tag - Can be any of the three kinds of tags we accept: +1. URL +2. assets-library tag +3. tag returned from storing an image in memory

static getPhotos(params: object, callback: function, errorCallback: function) #

Invokes callback with photo identifier objects from the local camera +roll of the device matching shape defined by getPhotosReturnChecker.

@param {object} params - See getPhotosParamChecker. +@param {function} callback - Invoked with arg of shape defined by +getPhotosReturnChecker on success. +@param {function} errorCallback - Invoked with error message on error.

{
+  "methods": [
+    {
+      "line": 96,
+      "source": "static saveImageWithTag(tag, successCallback, errorCallback) {\n    invariant(\n      typeof tag === 'string',\n      'CameraRoll.saveImageWithTag tag must be a valid string.'\n    );\n    RKCameraRollManager.saveImageWithTag(\n      tag,\n      (imageTag) => {\n        successCallback && successCallback(imageTag);\n      },\n      (errorMessage) => {\n        errorCallback && errorCallback(errorMessage);\n      });\n  }",
+      "docblock": "/**\n   * Saves the image with tag `tag` to the camera roll.\n   *\n   * @param {string} tag - Can be any of the three kinds of tags we accept:\n   *                       1. URL\n   *                       2. assets-library tag\n   *                       3. tag returned from storing an image in memory\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"string\",\"length\":1}",
+          "name": "tag"
+        },
+        {
+          "typehint": null,
+          "name": "successCallback"
+        },
+        {
+          "typehint": null,
+          "name": "errorCallback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "saveImageWithTag"
+    },
+    {
+      "line": 120,
+      "source": "static getPhotos(params, callback, errorCallback) {\n    var metaCallback = callback;\n    if (__DEV__) {\n      getPhotosParamChecker({params}, 'params', 'CameraRoll.getPhotos');\n      invariant(\n        typeof callback === 'function',\n        'CameraRoll.getPhotos callback must be a valid function.'\n      );\n      invariant(\n        typeof errorCallback === 'function',\n        'CameraRoll.getPhotos errorCallback must be a valid function.'\n      );\n    }\n    if (__DEV__) {\n      metaCallback = (response) => {\n        getPhotosReturnChecker(\n          {response},\n          'response',\n          'CameraRoll.getPhotos callback'\n        );\n        callback(response);\n      };\n    }\n    RKCameraRollManager.getPhotos(params, metaCallback, errorCallback);\n  }",
+      "docblock": "/**\n   *  Invokes `callback` with photo identifier objects from the local camera\n   *  roll of the device matching shape defined by `getPhotosReturnChecker`.\n   *\n   *  @param {object} params - See `getPhotosParamChecker`.\n   *  @param {function} callback - Invoked with arg of shape defined by\n   *    `getPhotosReturnChecker` on success.\n   *  @param {function} errorCallback - Invoked with error message on error.\n   */\n",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"object\",\"length\":1}",
+          "name": "params"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"function\",\"length\":1}",
+          "name": "callback"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"function\",\"length\":1}",
+          "name": "errorCallback"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "getPhotos"
+    }
+  ],
+  "type": "api",
+  "line": 87,
+  "name": "CameraRoll",
+  "docblock": "/**\n *\n */\n",
+  "requires": [
+    {
+      "name": "ReactPropTypes"
+    },
+    {
+      "name": "NativeModules"
+    },
+    {
+      "name": "createStrictShapeTypeChecker"
+    },
+    {
+      "name": "deepFreezeAndThrowOnMutationInDev"
+    },
+    {
+      "name": "invariant"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/datepickerios.html b/docs/datepickerios.html new file mode 100644 index 00000000000..ed7a5b43ce1 --- /dev/null +++ b/docs/datepickerios.html @@ -0,0 +1,11 @@ +Error: TypeError: Object Object.keys(RKDatePickerIOSConsts.DatePickerModes) has no method 'map' + at /Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/guard.js:27:12 + at onOutputGenerated (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/index.js:96:9) + at Object.renderReactPage.done (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/DefaultRouter.js:352:7) + at renderReactPage (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/renderReactPage.js:130:17) + at renderComponentPackage (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/DefaultRouter.js:338:3) + at routePackageHandler (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/DefaultRouter.js:281:5) + at onComputePackage (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/index.js:100:9) + at /Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/guard.js:29:10 + at onWarmed (/Users/vjeux/random/react-native/website/node_modules/react-page-middleware/src/Packager.js:270:9) + at /Users/vjeux/random/react-native/website/node_modules/react-page-middleware/node_modules/async/lib/async.js:116:25 \ No newline at end of file diff --git a/docs/expandingtext.html b/docs/expandingtext.html new file mode 100644 index 00000000000..6f1274fde51 --- /dev/null +++ b/docs/expandingtext.html @@ -0,0 +1,25 @@ +React Native | Build Native Apps Using React

ExpandingText

A react component for displaying text which supports truncating +based on a set truncLength.

In the following example, the text will truncate +to show only the first 17 characters plus '...' with a See More button to +expand the text to its full length.

render: function() { + return <ExpandingText truncLength={20} text={EXAMPLE_TEXT} />; +},

seeMoreStyle Text.propTypes.style #

The styles that will be applied to the See More button. Default +is bold.

seeMoreText string #

The caption that will be appended at the end, by default it is +'See More'.

text string #

Text to be displayed. It will be truncated if the character length +is greater than the truncLength property.

textStyle Text.propTypes.style #

The styles that will be applied to the text (both truncated and +expanded).

truncLength number #

The maximum character length for the text that will +be displayed by default. Note that ... will be +appended to the truncated text which is counted towards +the total truncLength of the default displayed string. +The default is 130.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/getting-started.html b/docs/getting-started.html new file mode 100644 index 00000000000..d9c23752ad2 --- /dev/null +++ b/docs/getting-started.html @@ -0,0 +1,33 @@ +React Native | Build Native Apps Using React

Getting Started

Our first React Native implementation is ReactKit, targeting iOS. We are also +working on an Android implementation which we will release later. ReactKit +apps are built using the React JS framework, and render directly to +native UIKit elements using a fully asynchronous architecture. There is no +browser and no HTML. We have picked what we think is the best set of features +from these and other technologies to build what we hope to become the best +product development framework available, with an emphasis on iteration speed, +developer delight, continuity of technology, and absolutely beautiful and fast +products with no compromises in quality or capability.

Requirements #

  1. OS X - This repo only contains the iOS implementation right now, and Xcode only runs on Mac.
  2. New to Xcode? Download it from the Mac App Store.
  3. Homebrew is the recommended way to install node, watchman, and flow.
  4. New to node or npm? brew install node
  5. We recommend installing watchman, otherwise you might hit a node file watching bug. brew install watchman
  6. If you want to use flow, brew install flow

Quick start #

Get up and running with our Movies sample app:

  1. Once you have the repo cloned and met all the requirements above, start the +packager that will transform your JS code on-the-fly:

    npm install +npm start
  2. Open the Examples/Movies/Movies.xcodeproj project in Xcode.
  3. Make sure the target is set to Movies and that you have an iOS simulator +selected to run the app.
  4. Build and run the project with the Xcode run button.

You should now see the Movies app running on your iOS simulator. +Congratulations! You've just successfully run your first React Native app.

Now try editing a JavaScript file and viewing your changes. Let's change the +movie search placeholder text:

  1. Open the Examples/Movies/SearchScreen.js file in your favorite JavaScript +editor.
  2. Look for the current search placeholder text and change it to "Search for an +awesome movie...".
  3. Hit cmd+R (twice) in your iOS simulator to reload the app and see your change. +If you don't immediately see your changes, try restarting your app within Xcode.

Feel free to browse the Movies sample files and customize various properties to +get familiar with the codebase and React Native.

Also check out the UI Component Explorer for more sample code: +Examples/UIExplorer/UIExplorer.xcodeproj. Make sure to close the Movies +project first - Xcode will break if you have two projects open that reference +the same library.

Troubleshooting #

  • Xcode will break if you have two examples open at the same time.
  • If npm start fails with log spew like:
    2015-02-02 10:56 node[24294] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
    then you've hit the node file watching bug - brew install watchman should fix the issue.
  • Jest testing does not yet work on node versions after 0.10.x.
  • You can verify the packager is working by loading the bundle in your browser and +inspecting the contents.

Please report any other issues you encounter so we can fix them ASAP.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/image.html b/docs/image.html new file mode 100644 index 00000000000..d44fae15b96 --- /dev/null +++ b/docs/image.html @@ -0,0 +1,47 @@ +React Native | Build Native Apps Using React

Image

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.

Example usage:

renderImages: function() { + return ( + <View> + <Image + style={styles.icon} + source={ix('myIcon')} + /> + <Image + style={styles.logo} + source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}} + /> + </View> + ); +},

accessibilityLabel string #

accessibilityLabel - Custom string to display for accessibility.

accessible bool #

accessible - Whether this element should be revealed as an accessible +element.

capInsets EdgeInsetsPropType #

capInsets - 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:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/index.html#//apple_ref/occ/instm/UIImage/resizableImageWithCapInsets:

source {uri: string} #

style StyleSheetPropType(ImageStylePropTypes) #

testID string #

testID - A unique identifier for this element to be used in UI Automation +testing scripts.

Displaying images is a fascinating subject, React Native uses some cool tricks to make it a better experience.

No Automatic Sizing #

If you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience.

In React Native, this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or just aspect ratio) of the image in advance, but we believe that it leads to a better user experience.

Background Image via Nesting #

A common feature request from developers familiar with the web is background-image. It turns out that iOS has a very elegant solution to this: you can add elements as a children to an <Image> component. This simplifies the API and solves the use case.

return ( + <Image source={...}> + <Text>Inside</Text> + </Image> +);

Off-thread Decoding #

Image decoding can take more than a frame-worth of time. This is one of the major source of frame drops on the web because decoding is done in the main thread. In React Native, image decoding is done in a different thread. In practice, you already need to handle the case when the image is not downloaded yet, so displaying the placeholder for a few more frames while it is decoding does not require any code change.

Static Assets #

In the course of a project you add and remove images and in many instances, you end up shipping images you are not using anymore in the app. In order to fight this, we need to find a way to know statically which images are being used in the app. To do that, we introduced a marker called ix. The only allowed way to refer to an image in the bundle is to literally write ix('name-of-the-asset') in the source.

var { ix } = React; + +// GOOD +<Image source={ix('my-icon')} /> + +// BAD +var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive'; +<Image source={ix(icon)} /> + +// GOOD +var icon = this.props.active ? ix('my-icon-active') : ix('my-icon-inactive'); +<Image source={icon} />

When your entire codebase respects this convention, you're able to do interesting things like automatically packaging the assets that are being used in your app. Note that in the current form, nothing is enforced, but it will be in the future.

Best Camera Roll Image #

iOS saves multiple sizes for the same image in your Camera Roll, it is very important to pick the one that's as close as possible for performance reasons. You wouldn't want to use the full quality 3264x2448 image as source when displaying a 200x200 thumbnail. If there's an exact match, React Native will pick it, otherwise it's going to use the first one that's at least 50% bigger in order to avoid blur when resizing from a close size. All of this is done by default so you don't have to worry about writing the tedious (and error prone) code to do it yourself.

Source being an object #

In React Native, one interesting decision is that the src attribute is named source and doesn't take a string but an object with an uri attribute.

<Image source={{uri: 'something.jpg'}} />

On the infrastructure side, the reason is that it allows to attach metadata to this object. For example if you are using ix, then we add a isStored attribute to flag it as a local file (don't rely on this fact, it's likely to change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting {uri: ...}, we can output {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} and transparently support spriting on all the existing call sites.

On the user side, this lets you annotate the object with useful attributes such as the dimension of the image in order to compute the size it's going to be displayed in. Feel free to use it as your data structure to store more information about your image.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/layoutanimation.html b/docs/layoutanimation.html new file mode 100644 index 00000000000..883b34ba8bd --- /dev/null +++ b/docs/layoutanimation.html @@ -0,0 +1,114 @@ +React Native | Build Native Apps Using React

LayoutAnimation

static configureNext(config, onAnimationDidEnd, onError) #

static create(duration, type, creationProp) #

{
+  "methods": [
+    {
+      "line": 48,
+      "source": "configureNext(config, onAnimationDidEnd, onError) {\n    configChecker({config}, 'config', 'LayoutAnimation.configureNext');\n    RKUIManager.configureNextLayoutAnimation(config, onAnimationDidEnd, onError);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "config"
+        },
+        {
+          "typehint": null,
+          "name": "onAnimationDidEnd"
+        },
+        {
+          "typehint": null,
+          "name": "onError"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "configureNext"
+    },
+    {
+      "line": 52,
+      "source": "create(duration, type, creationProp) {\n    return {\n      duration,\n      create: {\n        type,\n        property: creationProp,\n      },\n      update: {\n        type,\n      },\n    };\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "duration"
+        },
+        {
+          "typehint": null,
+          "name": "type"
+        },
+        {
+          "typehint": null,
+          "name": "creationProp"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "create"
+    }
+  ],
+  "properties": [
+    [
+      [
+        "static"
+      ],
+      "",
+      "Types",
+      "keyMirror({\n  spring: true,\n  linear: true,\n  easeInEaseOut: true,\n  easeIn: true,\n  easeOut: true,\n})",
+      "",
+      64
+    ],
+    [
+      [
+        "static"
+      ],
+      "",
+      "Properties",
+      "keyMirror({\n  opacity: true,\n  scaleXY: true,\n})",
+      "",
+      65
+    ],
+    [
+      [
+        "static"
+      ],
+      "",
+      "configChecker",
+      "createStrictShapeTypeChecker({\n  duration: PropTypes.number.isRequired,\n  create: animChecker,\n  update: animChecker,\n  delete: animChecker,\n})",
+      "",
+      66
+    ]
+  ],
+  "superClass": null,
+  "type": "api",
+  "line": 47,
+  "name": "LayoutAnimation",
+  "docblock": "/**\n *\n */\n",
+  "requires": [
+    {
+      "name": "ReactPropTypes"
+    },
+    {
+      "name": "NativeModules"
+    },
+    {
+      "name": "createStrictShapeTypeChecker"
+    },
+    {
+      "name": "keyMirror"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/listview.html b/docs/listview.html new file mode 100644 index 00000000000..c36230fb7fb --- /dev/null +++ b/docs/listview.html @@ -0,0 +1,64 @@ +React Native | Build Native Apps Using React

ListView

ListView - A core component designed for efficient display of vertically +scrolling lists of changing data. The minimal API is to create a +ListView.DataSource, populate it with a simple array of data blobs, and +instantiate a ListView component with that data source and a renderRow +callback which takes a blob from the data array and returns a renderable +component.

Minimal example:

getInitialState: function() { + var ds = new ListViewDataSource({rowHasChanged: (r1, r2) => r1 !== r2}); + return { + dataSource: ds.cloneWithRows(['row 1', 'row 2']), + }; +}, + +render: function() { + return ( + <ListView + dataSource={this.state.dataSource} + renderRow={(rowData) => <Text>{rowData}</Text>} + /> + ); +},

ListView also supports more advanced features, including sections with sticky +section headers, header and footer support, callbacks on reaching the end of +the available data (onEndReached) and on the set of rows that are visible +in the device viewport change (onChangeVisibleRows), and several +performance optimizations.

There are a few performance operations designed to make ListView scroll +smoothly while dynamically loading potentially very large (or conceptually +infinite) data sets:

  • Only re-render changed rows - the hasRowChanged function provided to the +data source tells the ListView if it needs to re-render a row because the +source data has changed - see ListViewDataSource for more details.

  • Rate-limited row rendering - By default, only one row is rendered per +event-loop (customizable with the pageSize prop). This breaks up the +work into smaller chunks to reduce the chance of dropping frames while +rendering rows.

dataSource ListViewDataSource #

initialListSize number #

How many rows to render on initial component mount. Use this to make +it so that the first screen worth of data apears at one time instead of +over the course of multiple frames.

onChangeVisibleRows func #

(visibleRows, changedRows) => void

Called when the set of visible rows changes. visibleRows maps +{ sectionID: { rowID: true }} for all the visible rows, and +changedRows maps { sectionID: { rowID: true | false }} for the rows +that have changed their visibility, with true indicating visible, and +false indicating the view has moved out of view.

onEndReached func #

Called when all rows have been rendered and the list has been scrolled +to within onEndReachedThreshold of the bottom. The native scroll +event is provided.

onEndReachedThreshold number #

Threshold in pixels for onEndReached.

pageSize number #

Number of rows to render per event loop.

removeClippedSubviews bool #

An experimental performance optimization for improving scroll perf of +large lists, used in conjunction with overflow: 'hidden' on the row +containers. Use at your own risk.

renderFooter func #

() => renderable

The header and footer are always rendered (if these props are provided) +on every render pass. If they are expensive to re-render, wrap them +in StaticContainer or other mechanism as appropriate. Footer is always +at the bottom of the list, and header at the top, on every render pass.

renderHeader func #

renderRow func #

(rowData, sectionID, rowID) => renderable +Takes a data entry from the data source and its ids and should return +a renderable component to be rendered as the row. By default the data +is exactly what was put into the data source, but it's also possible to +provide custom extractors.

renderSectionHeader func #

(sectionData, sectionID) => renderable

If provided, a sticky header is rendered for this section. The sticky +behavior means that it will scroll with the content at the top of the +section until it reaches the top of the screen, at which point it will +stick to the top until it is pushed off the screen by the next section +header.

scrollRenderAheadDistance number #

How early to start rendering rows before they come on screen, in +pixels.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/mapview.html b/docs/mapview.html new file mode 100644 index 00000000000..a5595cabe70 --- /dev/null +++ b/docs/mapview.html @@ -0,0 +1,28 @@ +React Native | Build Native Apps Using React

MapView

legalLabelInsets EdgeInsetsPropType #

Insets for the map's legal label, originally at bottom left of the map. +See EdgeInsetsPropType.js for more information.

maxDelta number #

Maximum size of area that can be displayed.

minDelta number #

Minimum size of area that can be displayed.

onRegionChange func #

Callback that is called continuously when the user is dragging the map.

onRegionChangeComplete func #

Callback that is called once, when the user is done moving the map.

pitchEnabled bool #

When this property is set to true and a valid camera is associated +with the map, the camera’s pitch angle is used to tilt the plane +of the map. When this property is set to false, the camera’s pitch +angle is ignored and the map is always displayed as if the user +is looking straight down onto it.

region {latitude: number, longitude: number, latitudeDelta: number, longitudeDelta: number} #

The region to be displayed by the map.

The region is defined by the center coordinates and the span of +coordinates to display.

rotateEnabled bool #

When this property is set to true and a valid camera is associated with +the map, the camera’s heading angle is used to rotate the plane of the +map around its center point. When this property is set to false, the +camera’s heading angle is ignored and the map is always oriented so +that true north is situated at the top of the map view

scrollEnabled bool #

If false the user won't be able to change the map region being displayed. +Default value is true.

showsUserLocation bool #

If true the app will ask for the user's location and focus on it. +Default value is false.

NOTE: You need to add NSLocationWhenInUseUsageDescription key in +Info.plist to enable geolocation, otherwise it is going +to fail silently!

style View.propTypes.style #

Used to style and layout the MapView. See StyleSheet.js and +ViewStylePropTypes.js for more info.

zoomEnabled bool #

If false the user won't be able to pinch/zoom the map. +Default value is true.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/navigatorios.html b/docs/navigatorios.html new file mode 100644 index 00000000000..f1307319087 --- /dev/null +++ b/docs/navigatorios.html @@ -0,0 +1,50 @@ +React Native | Build Native Apps Using React

NavigatorIOS

NavigatorIOS wraps UIKit navigation and allows you to add back-swipe +functionality across your app.

Routes #

A route is an object used to describe each page in the navigator. The first +route is provided to NavigatorIOS as initialRoute:

render: function() { + return ( + <NavigatorIOS + initialRoute={{ + component: MyView, + title: 'My View Title', + passProps: { myProp: 'foo' }, + }} + /> + ); +},

Now MyView will be rendered by the navigator. It will recieve the route +object in the route prop, a navigator, and all of the props specified in +passProps.

See the initialRoute propType for a complete definition of a route.

Navigator #

A navigator is an object of navigation functions that a view can call. It +is passed as a prop to any component rendered by NavigatorIOS.

var MyView = React.createClass({ + _handleBackButtonPress: function() { + this.props.navigator.pop(); + }, + _handleNextButtonPress: function() { + this.props.navigator.push(nextRoute); + }, + ... +});

A navigation object contains the following functions:

  • push(route) - Navigate forward to a new route
  • pop() - Go back one page
  • popN(n) - Go back N pages at once. When N=1, behavior matches pop()
  • replace(route) - Replace the route for the current page and immediately +load the view for the new route
  • replacePrevious(route) - Replace the route/view for the previous page
  • replacePreviousAndPop(route) - Replaces the previous route/view and +transitions back to it
  • resetTo(route) - Replaces the top item and popToTop
  • popToRoute(route) - Go back to the item for a particular route object
  • popToTop() - Go back to the top item

Navigator functions are also available on the NavigatorIOS component:

var MyView = React.createClass({ + _handleNavigationRequest: function() { + this.refs.nav.push(otherRoute); + }, + render: () => ( + <NavigatorIOS + ref="nav" + initialRoute={...} + /> + ), +});

initialRoute {component: func, title: string, passProps: object, backButtonTitle: string, rightButtonTitle: string, onRightButtonPress: func, wrapperStyle: View.propTypes.style} #

NavigatorIOS uses "route" objects to identify child views, their props, +and navigation bar configuration. "push" and all the other navigation +operations expect routes to be like this:

itemWrapperStyle View.propTypes.style #

The default wrapper style for components in the navigator. +A common use case is to set the backgroundColor for every page

tintColor string #

The color used for buttons in the navigation bar

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/network.html b/docs/network.html new file mode 100644 index 00000000000..0759717e11e --- /dev/null +++ b/docs/network.html @@ -0,0 +1,33 @@ +React Native | Build Native Apps Using React

Network

One of React Native goal is to be a playground where we can experiment with different architectures and crazy ideas. Since browsers are not flexible enough, we had no choice but to reimplement the entire stack. In the places that we did not intend to change, we tried to be as faithful as possible to the browser APIs, the networking stack is a great example.

XMLHttpRequest #

XMLHttpRequest API is implemented on-top of iOS networking apis. The notable difference from web is the security model: you can read from arbitrary websites on the internet, there isn't no concept of CORS.

var request = new XMLHttpRequest(); +request.onreadystatechange = (e) => { + if (request.readyState !== 4) { + return; + } + + if (request.status === 200) { + console.log('success', request.responseText); + } else { + console.warn('error'); + } +}; + +request.open('GET', 'https://mywebsite.com/endpoint.php'); +request.send();

Please follow the MDN Documentation for a description of the API.

As a developer, you're probably not going to use XMLHttpRequest directly as its API is very tedious to work with. But the fact that it is implemented and compatible with the browser one gives you the ability to use third-party libraries such as Parse JS SDK or super-agent directly from npm.

Fetch #

fetch is a better API being worked on by the standard committee and already available in Chrome. It is available in React Native by default.

fetch('https://mywebsite.com/endpoint.php') + .then((response) => response.text()) + .then((responseText) => { + console.log(responseText); + }) + .catch((error) => { + console.warn(error); + });
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/pickerios.html b/docs/pickerios.html new file mode 100644 index 00000000000..ce4c2c5b338 --- /dev/null +++ b/docs/pickerios.html @@ -0,0 +1,12 @@ +React Native | Build Native Apps Using React
\ No newline at end of file diff --git a/docs/pixelratio.html b/docs/pixelratio.html new file mode 100644 index 00000000000..4cd9379c588 --- /dev/null +++ b/docs/pixelratio.html @@ -0,0 +1,58 @@ +React Native | Build Native Apps Using React

PixelRatio

PixelRatio class gives access to the device pixel density.

Some examples: +- PixelRatio.get() === 2 +- iPhone 4, 4S +- iPhone 5, 5c, 5s +- iPhone 6

  • PixelRatio.get() === 3
  • iPhone 6 plus

There are a few use cases for using PixelRatio:

== Displaying a line that's as thin as the device permits

A width of 1 is actually pretty thick on an iPhone 4+, we can do one that's +thinner using a width of 1 / PixelRatio.get(). It's a technique that works +on all the devices independent of their pixel density.

style={{ borderWidth: 1 / PixelRatio.get() }}

== Fetching a correctly sized image

You should get a higher resolution image if you are on a high pixel density +device. A good rule of thumb is to multiply the size of the image you display +by the pixel ratio.

var image = getImage({ +width: 200 PixelRatio.get(), +height: 100 PixelRatio.get() +});

<Image source={image} style={{width: 200, height: 100}} /> +

static get() #

static startDetecting() #

{
+  "methods": [
+    {
+      "line": 45,
+      "source": "static get() {\n    return Dimensions.get('window').scale;\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "get"
+    },
+    {
+      "line": 49,
+      "source": "static startDetecting() {\n    // no-op for iOS, but this is useful for other platforms\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "startDetecting"
+    }
+  ],
+  "type": "api",
+  "line": 44,
+  "name": "PixelRatio",
+  "docblock": "/**\n * PixelRatio class gives access to the device pixel density.\n *\n * Some examples:\n *   - PixelRatio.get() === 2\n *     - iPhone 4, 4S\n *     - iPhone 5, 5c, 5s\n *     - iPhone 6\n *\n *   - PixelRatio.get() === 3\n *     - iPhone 6 plus\n *\n * There are a few use cases for using PixelRatio:\n *\n * == Displaying a line that's as thin as the device permits\n *\n * A width of 1 is actually pretty thick on an iPhone 4+, we can do one that's\n * thinner using a width of 1 / PixelRatio.get(). It's a technique that works\n * on all the devices independent of their pixel density.\n *\n *   style={{ borderWidth: 1 / PixelRatio.get() }}\n *\n * == Fetching a correctly sized image\n *\n * You should get a higher resolution image if you are on a high pixel density\n * device. A good rule of thumb is to multiply the size of the image you display\n * by the pixel ratio.\n *\n *   var image = getImage({\n *     width: 200 * PixelRatio.get(),\n *     height: 100 * PixelRatio.get()\n *   });\n *   <Image source={image} style={{width: 200, height: 100}} />\n */\n",
+  "requires": [
+    {
+      "name": "Dimensions"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/pixels.html b/docs/pixels.html new file mode 100644 index 00000000000..2460f6c0b4d --- /dev/null +++ b/docs/pixels.html @@ -0,0 +1,16 @@ +React Native | Build Native Apps Using React

Physical vs Logical Pixels

Pixel Grid Snapping #

In iOS, you can specify positions and dimensions for elements with arbitrary precision, for example 29.674825. But, ultimately the physical display only have a fixed number of pixels, for example 640×960 for iphone 4 or 750×1334 for iphone 6. iOS tries to be as faithful as possible to the user value by spreading one original pixel into multiple ones to be trick the eye. The downside of this technique is that it makes the resulting element look blurry.

In practice, we found out that developers do not want this feature and they have to work around it by doing manual rounding in order to avoid having blurry elements. In React Native, we are rounding all the pixels automatically.

We have to be careful when to do this rounding. You never want to work with rounded and unrounded values at the same time as you're going to accumulate rounding errors. Having even one rounding error is deadly because a one pixel border may vanish or be twice as big.

In React Native, everything in JS and within the layout engine work with arbitrary precision numbers. It's only when we set the position and dimensions of the native element on the main thread that we round. Also, rounding is done relative to the root rather than the parent, again to avoid accumulating rounding errors.

Displaying a line that's as thin as the device permits #

A width of 1 is actually 2 physical pixels thick on an iPhone 4 and ~3 physical pixels thick on an iphone 6+. If you want to display a line that's as thin as possible, you can use a width of 1 / PixelRatio.get(). It's a technique that works on all the devices independent of their pixel density.

style={{ borderWidth: 1 / PixelRatio.get() }}

Fetching a correctly sized image #

You should get a higher resolution image if you are on a high pixel density device. A good rule of thumb is to multiply the size of the image you display by the pixel ratio.

var image = getImage({ + width: 200 * PixelRatio.get(), + height: 100 * PixelRatio.get(), +}); +<Image source={image} style={{width: 200, height: 100}} />
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/scrollview.html b/docs/scrollview.html new file mode 100644 index 00000000000..8d03d436edf --- /dev/null +++ b/docs/scrollview.html @@ -0,0 +1,54 @@ +React Native | Build Native Apps Using React

ScrollView

Component that wraps platform ScrollView while providing +integration with touch locking "responder" system.

Doesn't yet support other contained responders from blocking this scroll +view from becoming the responder.

alwaysBounceHorizontal bool #

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.

alwaysBounceVertical bool #

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.

automaticallyAdjustContentInsets bool #

centerContent bool #

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.

contentContainerStyle StyleSheetPropType(ViewStylePropTypes) #

These styles will be applied to the scroll view content container which +wraps all of the child views. Example:

return ( + <ScrollView contentContainerStyle={styles.contentContainer}> + </ScrollView> + ); + ... + var styles = StyleSheet.create({ + contentContainer: { + paddingVertical: 20 + } + });

contentInset EdgeInsetsPropType #

contentOffset PointPropType #

decelerationRate number #

A floating-point number that determines how quickly the scroll view +decelerates after the user lifts their finger. Reasonable choices include + - Normal: 0.998 (the default) + - Fast: 0.9

horizontal bool #

When true, the scroll view's children are arranged horizontally in a row +instead of vertically in a column. The default value is false.

keyboardDismissMode enum(// default +'none', 'interactive', 'onDrag') #

Determines whether the keyboard gets dismissed in response to a drag. + - 'none' (the default), drags do not dismiss the keyboard. + - 'onDrag', the keyboard is dismissed when a drag begins. + - 'interactive', the keyboard is dismissed interactively with the drag + and moves in synchrony with the touch; dragging upwards cancels the + dismissal.

keyboardShouldPersistTaps bool #

When false, tapping outside of the focused text input when the keyboard +is up dismisses the keyboard. When true, the scroll view will not catch +taps, and the keyboard will not dismiss automatically. The default value +is false.

maximumZoomScale number #

The maximum allowed zoom scale. The default value is 1.0.

minimumZoomScale number #

The minimum allowed zoom scale. The default value is 1.0.

onScroll func #

onScrollAnimationEnd func #

pagingEnabled bool #

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.

removeClippedSubviews bool #

Experimental: When true, offscreen child views (whose overflow value is +hidden) are removed from their native backing superview when offscreen. +This canimprove scrolling performance on long lists. The default value is +false.

scrollEnabled bool #

scrollIndicatorInsets EdgeInsetsPropType #

scrollsToTop bool #

When true, the scroll view scrolls to top when the status bar is tapped. +The default value is true.

showsHorizontalScrollIndicator bool #

showsVerticalScrollIndicator bool #

stickyHeaderIndices [number] #

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}.

style StyleSheetPropType(ViewStylePropTypes) #

throttleScrollCallbackMS number #

zoomScale number #

The current scale of the scroll view content. The default value is 1.0.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/slider.html b/docs/slider.html new file mode 100644 index 00000000000..518a4915a56 --- /dev/null +++ b/docs/slider.html @@ -0,0 +1,16 @@ +React Native | Build Native Apps Using React

Slider

onSlidingComplete func #

Callback called when the user finishes changing the value (e.g. when +the slider is released).

onValueChange func #

Callback continuously called while the user is dragging the slider.

style View.propTypes.style #

Used to style and layout the Slider. See StyleSheet.js and +ViewStylePropTypes.js for more info.

value number #

Initial value of the slider. The value should be between 0 and 1. +Default value is 0.

This is not a controlled component, e.g. if you don't update +the value, the component won't be reseted to it's inital value.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/statusbarios.html b/docs/statusbarios.html new file mode 100644 index 00000000000..441fd5f2518 --- /dev/null +++ b/docs/statusbarios.html @@ -0,0 +1,87 @@ +React Native | Build Native Apps Using React

StatusBarIOS

@flow

static setStyle(style: number, animated: boolean) #

static setHidden(hidden: boolean, animation: number) #

{
+  "methods": [
+    {
+      "line": 24,
+      "source": "setStyle(style: number, animated: boolean) {\n    animated = animated || false;\n    RKStatusBarManager.setStyle(style, animated);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"number\",\"length\":1}",
+          "name": "style"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"boolean\",\"length\":1}",
+          "name": "animated"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "setStyle"
+    },
+    {
+      "line": 29,
+      "source": "setHidden(hidden: boolean, animation: number) {\n    animation = animation || StatusBarIOS.Animation.none;\n    RKStatusBarManager.setHidden(hidden, animation);\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"boolean\",\"length\":1}",
+          "name": "hidden"
+        },
+        {
+          "typehint": "{\"type\":\"simple\",\"value\":\"number\",\"length\":1}",
+          "name": "animation"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "setHidden"
+    }
+  ],
+  "properties": [
+    [
+      [
+        "static"
+      ],
+      "",
+      "Style",
+      "{\n    default: RKStatusBarManager.Style.default,\n    lightContent: RKStatusBarManager.Style.lightContent\n  }",
+      "",
+      13
+    ],
+    [
+      [
+        "static"
+      ],
+      "",
+      "Animation",
+      "{\n    none: RKStatusBarManager.Animation.none,\n    fade: RKStatusBarManager.Animation.fade,\n    slide: RKStatusBarManager.Animation.slide,\n  }",
+      "",
+      18
+    ]
+  ],
+  "superClass": null,
+  "type": "api",
+  "line": 11,
+  "name": "StatusBarIOS",
+  "docblock": "/**\n *\n * @flow\n */\n",
+  "requires": [
+    {
+      "name": "NativeModules"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/style.html b/docs/style.html new file mode 100644 index 00000000000..81e39f68824 --- /dev/null +++ b/docs/style.html @@ -0,0 +1,47 @@ +React Native | Build Native Apps Using React

Style

Declaring Styles #

The way to declare styles in React Native is the following:

var styles = StyleSheet.create({ + base: { + width: 38, + height: 38, + }, + background: { + backgroundColor: '#222222', + }, + active: { + borderWidth: 2, + borderColor: '#00ff00', + }, +});

StyleSheet.create construct is optional but provides some key advantages. It ensures that the values are immutable and opaque by transforming them into plain numbers that reference an internal table. By putting it at the end of the file, you also ensure that they are only created once for the application and not on every render.

Using Styles #

All the core components accept a style attribute

<Text style={styles.base} /> +<View style={styles.background} />

and also accepts an array of styles

<View style={[style.base, style.background]} />

The behavior is the same as Object.assign: in case of conflicting values, the one from the right-most element will have precedence and falsy values like false, undefined and null will be ignored. A common pattern is to conditionally add a style based on some condition.

<View style={[style.base, this.state.active && style.active]} />

Finally, if you really have to, you can also create style objects in render, but they are highly discouraged. Put them last in the array definition.

<View + style={[style.base, { + width: this.state.width, + height: this.state.width * this.state.aspectRatio + }]} +/>

Pass Styles Around #

In order to let a call site customize the style of your component children, you can pass styles around. Use View.stylePropType and Text.stylePropType in order to make sure only styles are being passed.

var List = React.createClass({ + propTypes: { + style: View.stylePropType, + elementStyle: View.stylePropType, + }, + render: function() { + return ( + <View style={this.props.style}> + {elements.map((element) => + <View style={[styles.element, this.props.elementStyle]} /> + )} + </View> + ); + } +}); + +// ... in another file ... +<List style={styles.list} elementStyle={styles.listElement} />
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/stylesheet.html b/docs/stylesheet.html new file mode 100644 index 00000000000..2d98fa62a62 --- /dev/null +++ b/docs/stylesheet.html @@ -0,0 +1,140 @@ +React Native | Build Native Apps Using React

StyleSheet

A StyleSheet is an abstraction similar to CSS StyleSheets

Create a new StyleSheet:

var styles = StyleSheet.create({ +container: { +borderRadius: 4, +borderWidth: 0.5, +borderColor: '#d6d7da', +}, +title: { +fontSize: 19, +fontWeight: 'bold', +}, +activeTitle: { +color: 'red', +}, +})

Use a StyleSheet:

<View style={styles.container}> +<Text style={[styles.title, this.props.isActive && styles.activeTitle]} /> +</View> + +

Code quality: +- By moving styles away from the render function, you're making the code +code easier to understand. +- Naming the styles is a good way to add meaning to the low level components +in the render function.

Performance: +- Making a stylesheet from a style object makes it possible to refer to it +by ID instead of creating a new style object every time. +- It also allows to send the style only once through the bridge. All +subsequent uses are going to refer an id (not implemented yet).

static create(obj) #

static validateStyleProp(prop, style, caller) #

static validateStyle(name, styles) #

static addValidStylePropTypes(stylePropTypes) #

{
+  "methods": [
+    {
+      "line": 55,
+      "source": "static create(obj) {\n    var result = {};\n    for (var key in obj) {\n      StyleSheet.validateStyle(key, obj);\n      result[key] = StyleSheetRegistry.registerStyle(obj[key]);\n    }\n    return result;\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "obj"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "create"
+    },
+    {
+      "line": 64,
+      "source": "static validateStyleProp(prop, style, caller) {\n    if (!__DEV__) {\n      return;\n    }\n    if (allStylePropTypes[prop] === undefined) {\n      var message1 = '\"' + prop + '\" is not a valid style property.';\n      var message2 = '\\nValid style props: ' +\n        JSON.stringify(Object.keys(allStylePropTypes), null, '  ');\n      styleError(message1, style, caller, message2);\n    }\n    var error = allStylePropTypes[prop](\n      style,\n      prop,\n      caller,\n      ReactPropTypeLocations.prop\n    );\n    if (error) {\n      styleError(error.message, style, caller);\n    }\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "prop"
+        },
+        {
+          "typehint": null,
+          "name": "style"
+        },
+        {
+          "typehint": null,
+          "name": "caller"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "validateStyleProp"
+    },
+    {
+      "line": 85,
+      "source": "static validateStyle(name, styles) {\n    if (!__DEV__) {\n      return;\n    }\n    for (var prop in styles[name]) {\n      StyleSheet.validateStyleProp(prop, styles[name], 'StyleSheet ' + name);\n    }\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "name"
+        },
+        {
+          "typehint": null,
+          "name": "styles"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "validateStyle"
+    },
+    {
+      "line": 94,
+      "source": "static addValidStylePropTypes(stylePropTypes) {\n    for (var key in stylePropTypes) {\n      invariant(\n        allStylePropTypes[key] === undefined ||\n          allStylePropTypes[key] === stylePropTypes[key],\n        'Attemped to redefine existing style prop type \"' + key + '\".'\n      );\n      allStylePropTypes[key] = stylePropTypes[key];\n    }\n  }",
+      "modifiers": [
+        "static"
+      ],
+      "params": [
+        {
+          "typehint": null,
+          "name": "stylePropTypes"
+        }
+      ],
+      "tparams": null,
+      "returntypehint": null,
+      "name": "addValidStylePropTypes"
+    }
+  ],
+  "type": "api",
+  "line": 54,
+  "name": "StyleSheet",
+  "docblock": "/**\n * A StyleSheet is an abstraction similar to CSS StyleSheets\n *\n * Create a new StyleSheet:\n *\n * var styles = StyleSheet.create({\n *   container: {\n *     borderRadius: 4,\n *     borderWidth: 0.5,\n *     borderColor: '#d6d7da',\n *   },\n *   title: {\n *     fontSize: 19,\n *     fontWeight: 'bold',\n *   },\n *   activeTitle: {\n *     color: 'red',\n *   },\n * })\n *\n * Use a StyleSheet:\n *\n * <View style={styles.container}>\n *   <Text style={[styles.title, this.props.isActive && styles.activeTitle]} />\n * </View>\n *\n * Code quality:\n *  - By moving styles away from the render function, you're making the code\n *  code easier to understand.\n *  - Naming the styles is a good way to add meaning to the low level components\n *  in the render function.\n *\n * Performance:\n *  - Making a stylesheet from a style object makes it possible to refer to it\n * by ID instead of creating a new style object every time.\n *  - It also allows to send the style only once through the bridge. All\n * subsequent uses are going to refer an id (not implemented yet).\n */\n",
+  "requires": [
+    {
+      "name": "ImageStylePropTypes"
+    },
+    {
+      "name": "ReactPropTypeLocations"
+    },
+    {
+      "name": "StyleSheetRegistry"
+    },
+    {
+      "name": "TextStylePropTypes"
+    },
+    {
+      "name": "ViewStylePropTypes"
+    },
+    {
+      "name": "invariant"
+    }
+  ]
+}
© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/switchios.html b/docs/switchios.html new file mode 100644 index 00000000000..5ee96cf3a0a --- /dev/null +++ b/docs/switchios.html @@ -0,0 +1,18 @@ +React Native | Build Native Apps Using React

SwitchIOS

Use SwitchIOS to render a boolean input on iOS. This is +a controlled component, so you must hook in to the onValueChange callback +and update the value prop in order for the component to update, otherwise +the user's change will be reverted immediately to reflect props.value as the +source of truth.

disabled bool #

If true the user won't be able to toggle the switch. +Default value is false.

onTintColor string #

Background color when the switch is turned on.

onValueChange func #

Callback that is called when the user toggles the switch.

thumbTintColor string #

Background color for the switch round button.

tintColor string #

Background color when the switch is turned off.

value bool #

The value of the switch, if true the switch will be turned on. +Default value is false.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/tabbarios.html b/docs/tabbarios.html new file mode 100644 index 00000000000..7f2016a855b --- /dev/null +++ b/docs/tabbarios.html @@ -0,0 +1,12 @@ +React Native | Build Native Apps Using React
\ No newline at end of file diff --git a/docs/text.html b/docs/text.html new file mode 100644 index 00000000000..b12d8ea569b --- /dev/null +++ b/docs/text.html @@ -0,0 +1,88 @@ +React Native | Build Native Apps Using React

Text

A react component for displaying text which supports nesting, +styling, and touch handling. In the following example, the nested title and +body text will inherit the fontFamily from styles.baseText, but the title +provides its own additional styles. The title and body will stack on top of +each other on account of the literal newlines:

renderText: function() { + return ( + <Text style={styles.baseText}> + <Text style={styles.titleText} onPress={this.onPressTitle}> + {this.state.titleText + '\n\n'} + </Text> + <Text numberOfLines={5}> + {this.state.bodyText} + </Text> + </Text> + ); +}, +... +var styles = StyleSheet.create({ + baseText: { + fontFamily: 'Cochin', + }, + titleText: { + fontSize: 20, + fontWeight: 'bold', + }, +};

numberOfLines number #

Used to truncate the text with an elipsis after computing the text +layout, including line wrapping, such that the total number of lines does +not exceed this number.

onPress func #

This function is called on press. Text intrinsically supports press +handling with a default highlight state (which can be disabled with +suppressHighlighting).

style stylePropType #

suppressHighlighting bool #

When true, no visual change is made when text is pressed down. By +default, a gray oval highlights the text on press down.

testID string #

Used to locate this view in end-to-end tests.

Nested Text #

In iOS, the way to display formatted text is by using NSAttributedString: you give the text that you want to display and annotate ranges with some specific formatting. In practice, this is very tedious. For React Native, we decided to use web paradigm for this where you can nest text to achieve the same effect.

<Text style={{fontWeight: 'bold'}}> + I am bold + <Text style={{color: 'red'}}> + and red + </Text> +</Text>

Behind the scenes, this is going to be converted to a flat NSAttributedString that contains the following information

"I am bold and red" +0-9: bold +9-17: bold, red

Containers #

The <Text> element is special relative to layout, everything inside is no longer using the flexbox layout but using text layout. This means that elements inside of a <Text> are no longer rectangles but wrap when they see the end of the line.

<Text> + <Text>First part and </Text> + <Text>second part</Text> +</Text> +// Text container: all the text flows as if it was one +// |First part | +// |and second | +// |part | + +<View> + <Text>First part and </Text> + <Text>second part</Text> +</View> +// View container: each text is its own block +// |First part | +// |and | +// |second part|

Limited Style Inheritance #

On the web, the usual way to set a font family and size for the entire document is to write

/* CSS, *not* React Native */ +html { + font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; + font-size: 11px; + color: #141823; +}

When the browser is trying to render a text node, it's going to go all the way up to the root element of the tree and find an element with a font-size attribute. An unexpected property with this system is that any node can have font-size attribute, including a <div>. The reason why it was designed this way is that it is convenient, even though not really semantically correct.

In React Native, we are more strict about it. The first place where it'll show up is that you have to wrap all the text nodes inside of a <Text> component. It is not allowed to have a text node directly under a <View>.

// BAD: will fatal, can't have a text node as child of a <View> +<View> + Some text +</View> + +// GOOD +<View> + <Text> + Some text + </Text> +</View>

You also lose the ability to setup a default font for an entire subtree. The recommended way to use consistent fonts and sizes across your application is to create a component MyAppText that's going to set them and use this component all across your app. You can also make other components such as MyAppHeaderText for other kind of texts.

<View> + <MyAppText>Text styled with the default font for the entire application</MyAppText> + <MyAppHeaderText>Text styled as a header</MyAppHeaderText> +</View>

React Native still has the concept of style inheritance, but limited to text subtrees. In this case, the second part will be both bold and red.

<Text style={{fontWeight: 'bold'}}> + I am bold + <Text style={{color: 'red'}}> + and red + </Text> +</Text>

We believe that this more constrained way to style text will yield better apps.

  • (Developper) React components are designed with strong isolation properties in mind, you should be able to drop a component anywhere in your application and it will look and behave the same way, as long as the props are the same. Having text properties be inherited from outside of the props breaks isolation.

  • (Implementor) The implementation of React Native is also simplified. We do not need to have a fontFamily field on every single element and we do not need to potentially traverse the tree up to the root every time we display a text node. The style inheritance is only encoded inside of the native Text component and doesn't leak to other components or the system itself.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/textinput.html b/docs/textinput.html new file mode 100644 index 00000000000..35da9019776 --- /dev/null +++ b/docs/textinput.html @@ -0,0 +1,37 @@ +React Native | Build Native Apps Using React

TextInput

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:

<View> + <TextInput + style={{height: 40, borderColor: 'gray', borderWidth: 1}} + onChangeText={(text) => this.setState({input: text})} + /> + <Text>{'user input: ' + this.state.input}</Text> +</View>

The value prop can be used to set the value of the input in order to make +the state of the component clear, but <TextInput> does not behave as a true +controlled component by default because all operations are asynchronous. +Setting value once is like setting the default value, but you can change it +continuously based on onChangeText events as well. If you really want to +force the component to always revert to the value you are setting, you can +set controlled={true}.

The multiline prop is not supported in all releases, and some props are +multiline only.

autoCapitalize enum('none', 'sentences', 'words', 'characters') #

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

autoCorrect bool #

If false, disables auto-correct. Default value is true.

autoFocus bool #

If true, focuses the input on componentDidMount. Default value is false.

bufferDelay number #

This helps avoid drops characters due to race conditions between JS and +the native text input. The default should be fine, but if you're +potentially doing very slow operations on every keystroke then you may +want to try increasing this.

clearButtonMode enum('never', 'while-editing', 'unless-editing', 'always') #

When the clear button should appear on the right side of the text view

controlled bool #

If you really want this to behave as a controlled component, you can set +this true, but you will probably see flickering, dropped keystrokes, +and/or laggy typing, depending on how you process onChange events.

editable bool #

If false, text is not editable. Default value is true.

keyboardType enum('default', 'numeric') #

Determines which keyboard to open, e.g.numeric.

multiline bool #

If true, the text input can be multiple lines. Default value is false.

onBlur func #

Callback that is called when the text input is blurred

onChangeText func #

(text: string) => void

Callback that is called when the text input's text changes.

onEndEditing func #

onFocus func #

Callback that is called when the text input is focused

onSubmitEditing func #

placeholder string #

The string that will be rendered before text input has been entered

placeholderTextColor string #

The text color of the placeholder string

selectionState DocumentSelectionState #

See DocumentSelectionState.js, some state that is responsible for +maintaining selection information for a document

style Text.propTypes.style #

value string #

The default value for the text input

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/timers.html b/docs/timers.html new file mode 100644 index 00000000000..d457d11db9a --- /dev/null +++ b/docs/timers.html @@ -0,0 +1,28 @@ +React Native | Build Native Apps Using React

Timers

Timers are an important part of an application and React Native implements the browser timers.

Timers #

  • setTimeout, clearTimeout
  • setInterval, clearInterval
  • setImmediate, clearImmediate
  • requestAnimationFrame, cancelAnimationFrame

requestAnimationFrame(fn) is the exact equivalent of setTimeout(fn, 0), they are triggered right after the screen has been flushed.

setImmediate is executed at the end of the current JavaScript execution block, right before sending the batched response back to native. Note that if you call setImmediate within a setImmediate callback, it will be executed right away, it won't yield back to native in between.

The Promise implementation uses setImmediate its asynchronicity primitive.

InteractionManager #

One reason why native apps feel so good performance wise is that barely any work is being done during an interaction/animation. In React Native, you can use InteractionManager that allows long-running work to be scheduled after any interactions/animations have completed.

Applications can schedule tasks to run after interactions with the following:

InteractionManager.runAfterInteractions(() => { + // ...long-running synchronous task... +});

Compare this to other scheduling alternatives:

  • requestAnimationFrame(): for code that animates a view over time.
  • setImmediate/setTimeout/setInterval(): run code later, note this may delay animations.
  • runAfterInteractions(): run code later, without delaying active animations.

The touch handling system considers one or more active touches to be an 'interaction' and will delay runAfterInteractions() callbacks until all touches have ended or been cancelled.

InteractionManager also allows applications to register animations by creating an interaction 'handle' on animation start, and clearing it upon completion:

var handle = InteractionManager.createInteractionHandle(); +// run animation... (`runAfterInteractions` tasks are queued) +// later, on animation completion: +InteractionManager.clearInteractionHandle(handle); +// queued tasks run if all handles were cleared

TimerMixin #

We found out that the primary cause of fatals in apps created with React Native was due to timers firing after a component was unmounted. To solve this recurring issue, we introduced TimerMixin. If you include TimerMixin, then you can replace your calls to setTimeout(fn, 500) with this.setTimeout(fn, 500) (just prepend this.) and everything will be properly cleaned up for you when the component unmounts.

var { TimerMixin } = React; + +var Component = React.createClass({ + mixins: [TimerMixin], + componentDidMount: function() { + this.setTimeout( + () => { console.log('I do not leak!'); }, + 500 + ); + } +});

We highly recommend never using bare timers and always using this mixin, it will save you from a lot of hard to track down bugs.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/touchablehighlight.html b/docs/touchablehighlight.html new file mode 100644 index 00000000000..b9dc8a7f2bd --- /dev/null +++ b/docs/touchablehighlight.html @@ -0,0 +1,29 @@ +React Native | Build Native Apps Using React

TouchableHighlight

A wrapper for making views respond properly to touches. +On press down, the opacity of the wrapped view is decreased, which allows +the underlay color to show through, darkening or tinting the view. The +underlay comes from adding a view to the view hierarchy, which can sometimes +cause unwanted visual artifacts if not used correctly, for example if the +backgroundColor of the wrapped view isn't explicitly set to an opaque color.

Example:

renderButton: function() { + return ( + <TouchableHighlight onPress={this._onPressButton}> + <Image + style={styles.button} + source={ix('myButton')} + /> + </View> + ); +},

activeOpacity number #

Determines what the opacity of the wrapped view should be when touch is +active.

onPress func #

Called when the touch is released, but not if cancelled (e.g. by +a scroll that steals the responder lock).

style View.propTypes.style #

underlayColor string #

The color of the underlay that will show through when the touch is +active.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/touchableopacity.html b/docs/touchableopacity.html new file mode 100644 index 00000000000..879a05ef226 --- /dev/null +++ b/docs/touchableopacity.html @@ -0,0 +1,25 @@ +React Native | Build Native Apps Using React

TouchableOpacity

A wrapper for making views respond properly to touches. +On press down, the opacity of the wrapped view is decreased, dimming it. +This is done without actually changing the view hierarchy, and in general is +easy to add to an app without weird side-effects.

Example:

renderButton: function() { + return ( + <TouchableOpacity onPress={this._onPressButton}> + <Image + style={styles.button} + source={ix('myButton')} + /> + </View> + ); +},

activeOpacity number #

Determines what the opacity of the wrapped view should be when touch is +active.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/touchablewithoutfeedback.html b/docs/touchablewithoutfeedback.html new file mode 100644 index 00000000000..2d4e086ae6d --- /dev/null +++ b/docs/touchablewithoutfeedback.html @@ -0,0 +1,14 @@ +React Native | Build Native Apps Using React

TouchableWithoutFeedback

Do not use unless you have a very good reason. All the elements that +respond to press should have a visual feedback when touched. This is +one of the primary reason a "web" app doesn't feel "native".

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/docs/view.html b/docs/view.html new file mode 100644 index 00000000000..ea0eb43db77 --- /dev/null +++ b/docs/view.html @@ -0,0 +1,47 @@ +React Native | Build Native Apps Using React

View

The most fundamental component for building UI, View is a +container that supports layout with flexbox, style, some touch handling, and +accessibility controls, and is designed to be nested inside other views and +to have 0 to many children of any type. View maps directly to the native +view equivalent on whatever platform react is running on, whether that is a +UIView, <div>, android.view, etc. This example creates a View that +wraps two colored boxes and custom component in a row with padding.

<View style={{flexDirection: 'row', height: 100, padding: 20}}> + <View style={{backgroundColor: 'blue', flex: 0.3}} /> + <View style={{backgroundColor: 'red', flex: 0.5}} /> + <MyCustomComponent {...customProps} /> +</View>

By default, Views have a primary flex direction of 'column', so children +will stack up vertically by default. Views also expand to fill the parent +in the direction of the parent's flex direction by default, so in the case of +a default parent (flexDirection: 'column'), the children will fill the width, +but not the height.

Many library components can be treated like plain Views in many cases, for +example passing them children, setting style, etc.

Views are designed to be used with StyleSheets for clarity and +performance, although inline styles are also supported. It is common for +StyleSheets to be combined dynamically. See StyleSheet.js for more info.

accessible bool #

When true, indicates that the view is an accessibility element

onMoveShouldSetResponder func #

onResponderGrant func #

For most touch interactions, you'll simply want to wrap your component in +TouchableHighlight.js. Check out Touchable.js and +ScrollResponder.js for more discussion.

onResponderMove func #

onResponderReject func #

onResponderRelease func #

onResponderTerminate func #

onResponderTerminationRequest func #

onStartShouldSetResponder func #

onStartShouldSetResponderCapture func #

pointerEvents enum('box-none', 'none', 'box-only', 'auto') #

In the absence of auto property, none is much like CSS's none +value. box-none is as if you had applied the CSS class:

.cantTouchThis * { + pointer-events: auto; + } + .cantTouchThis { + pointer-events: none; + }

But since pointerEvents does not affect layout/appearance, and we are +already deviating from the spec by adding additional modes, we opt to not +include pointerEvents on style. On some platforms, we would need to +implement it as a className anyways. Using style or not is an +implementation detail of the platform.

removeClippedSubviews bool #

This is a special performance property exposed by RKView and is useful +for scrolling content when there are many subviews, most of which are +offscreen. For this property to be effective, it must be applied to a +view that contains many subviews that extend outside its bound. The +subviews must also have overflow: hidden, as should the containing view +(or one of its superviews).

style stylePropType #

Used to style and layout the View. See StyleSheet.js and +ViewStylePropTypes.js for more info.

testID string #

Used to locate this view in end-to-end tests.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/website/src/react-native/img/favicon.png b/img/favicon.png similarity index 100% rename from website/src/react-native/img/favicon.png rename to img/favicon.png diff --git a/website/src/react-native/img/logo.png b/img/logo.png similarity index 100% rename from website/src/react-native/img/logo.png rename to img/logo.png diff --git a/website/src/react-native/img/opengraph.png b/img/opengraph.png similarity index 100% rename from website/src/react-native/img/opengraph.png rename to img/opengraph.png diff --git a/website/src/react-native/img/react-native.png b/img/react-native.png similarity index 100% rename from website/src/react-native/img/react-native.png rename to img/react-native.png diff --git a/jestSupport/env.js b/jestSupport/env.js deleted file mode 100644 index 16f264febd8..00000000000 --- a/jestSupport/env.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -global.setImmediate = global.setImmediate || function(fn) { - return setTimeout(fn, 0); -}; diff --git a/jestSupport/scriptPreprocess.js b/jestSupport/scriptPreprocess.js deleted file mode 100644 index 2764b35bd68..00000000000 --- a/jestSupport/scriptPreprocess.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -var transformer = require('../packager/transformer.js'); - -function transformSource(src, filename) { - return transformer.transform(src, filename).code; -} - -module.exports = { - transformSource: transformSource, - - process: function(src, fileName) { - if (fileName.match(/node_modules/)) { - return src; - } - - try { - return transformSource(src, fileName); - } catch(e) { - throw new Error('\nError transforming file:\n js/' + - (fileName.split('/js/')[1] || fileName) + ':' + e.lineNumber + ': \'' + - e.message + '\'\n'); - } - } -}; diff --git a/lint/linterTransform.js b/lint/linterTransform.js deleted file mode 100644 index a61fa89a3b3..00000000000 --- a/lint/linterTransform.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -var eslint = require('eslint'); - -var ignoredStylisticRules = { - 'key-spacing': false, - 'comma-spacing': true, - 'no-multi-spaces': true, - 'brace-style': true, - 'camelcase': true, - 'consistent-this': true, - 'eol-last': true, - 'func-names': true, - 'func-style': true, - 'new-cap': true, - 'new-parens': true, - 'no-nested-ternary': true, - 'no-array-constructor': true, - 'no-lonely-if': true, - 'no-new-object': true, - 'no-spaced-func': true, - 'no-space-before-semi': true, - 'no-ternary': true, - 'no-trailing-spaces': true, - 'no-underscore-dangle': true, - 'no-wrap-func': true, - 'no-mixed-spaces-and-tabs': true, - 'quotes': true, - 'quote-props': true, - 'semi': true, - 'sort-vars': true, - 'space-after-keywords': true, - 'space-in-brackets': true, - 'space-in-parens': true, - 'space-infix-ops': true, - 'space-return-throw-case': true, - 'space-unary-word-ops': true, - 'max-nested-callbacks': true, - 'one-var': true, - 'wrap-regex': true, - 'curly': true, - 'no-mixed-requires': true, -}; - -function setLinterTransform(transformSource) { - var originalVerify = eslint.linter.verify; - eslint.linter.verify = function(text, config, filename, saveState) { - var transformedText; - try { - transformedText = transformSource(text); - } catch (e) { - return [{ - severity: 2, - line: e.lineNumber, - message: e.message, - source: text - }]; - } - var originalLines = text.split('\n'); - var transformedLines = transformedText.split('\n'); - var warnings = originalVerify.call(eslint.linter, transformedText, config, filename, saveState); - - // JSX and ES6 transforms usually generate pretty ugly code. Let's skip lint warnings - // about code style for lines that have been changed by transform step. - // Note that more important issues, like use of undefined vars, will still be reported. - return warnings.filter(function(error) { - var lineHasBeenTransformed = originalLines[error.line - 1] !== transformedLines[error.line - 1]; - var shouldIgnore = ignoredStylisticRules[error.ruleId] && lineHasBeenTransformed; - return !shouldIgnore; - }); - }; -} - -module.exports = { - setLinterTransform: setLinterTransform, -}; diff --git a/linter.js b/linter.js deleted file mode 100644 index 205e757c188..00000000000 --- a/linter.js +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2012-present Facebook. All Rights Reserved. -'use strict'; - -var transformSource = require('./jestSupport/scriptPreprocess.js').transformSource; -var linterTransform = require('./lint/linterTransform'); - -linterTransform.setLinterTransform(transformSource); - -// Run the original CLI -require('eslint/bin/eslint'); diff --git a/package.json b/package.json deleted file mode 100644 index f0af6823e75..00000000000 --- a/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "react-native", - "version": "0.1.0", - "description": "Build native apps with React!", - "repository": { - "type": "git", - "url": "git@github.com:facebook/react-native.git" - }, - "jest": { - "scriptPreprocessor": "jestSupport/scriptPreprocess.js", - "setupEnvScriptFile": "jestSupport/env.js", - "testPathIgnorePatterns": [ - "/node_modules/" - ], - "testFileExtensions": [ - "js" - ], - "unmockedModulePathPatterns": [ - "source-map" - ] - }, - "scripts": { - "test": "jest", - "lint": "node linter.js Examples/", - "start": "./packager/packager.sh" - }, - "dependencies": { - "absolute-path": "0.0.0", - "connect": "2.8.3", - "debug": "~2.1.0", - "joi": "~5.1.0", - "jstransform": "10.0.1", - "module-deps": "3.5.6", - "optimist": "0.6.1", - "q": "1.0.1", - "react-tools": "0.13.0-rc2", - "sane": "1.0.1", - "source-map": "0.1.31", - "stacktrace-parser": "0.1.1", - "uglify-js": "~2.4.16", - "underscore": "1.7.0", - "worker-farm": "1.1.0", - "yargs": "1.3.2" - }, - "devDependencies": { - "jest-cli": "0.2.1", - "eslint": "0.9.2" - } -} diff --git a/packager/blacklist.js b/packager/blacklist.js deleted file mode 100644 index eb81f452450..00000000000 --- a/packager/blacklist.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - */ -'use strict'; - -// Don't forget to everything listed here to `testConfig.json` -// modulePathIgnorePatterns. -var sharedBlacklist = [ - 'node_modules/JSAppServer', - 'packager/react-packager', - 'node_modules/parse/node_modules/xmlhttprequest/lib/XMLHttpRequest.js', - 'node_modules/react-tools/src/utils/ImmutableObject.js', - 'node_modules/react-tools/src/core/ReactInstanceHandles.js', - 'node_modules/react-tools/src/event/EventPropagators.js', - 'node_modules/jest-cli', -]; - -var webBlacklist = [ - '.ios.js' -]; - -var iosBlacklist = [ - 'node_modules/react-tools/src/browser/ui/React.js', - 'node_modules/react-tools/src/browser/eventPlugins/ResponderEventPlugin.js', - // 'node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js', - '.web.js', - '.android.js', -]; - -function escapeRegExp(str) { - return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); -} - -function blacklist(isWeb) { - return new RegExp('(' + - sharedBlacklist - .concat(isWeb ? webBlacklist : iosBlacklist) - .map(escapeRegExp) - .join('|') + - ')$' - ); -} - -module.exports = blacklist; diff --git a/packager/launchEditor.js b/packager/launchEditor.js deleted file mode 100644 index 93db9bfce45..00000000000 --- a/packager/launchEditor.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - */ -'use strict'; - -var fs = require('fs'); -var spawn = require('child_process').spawn; - -var firstLaunch = true; - -function guessEditor() { - if (firstLaunch) { - console.log('When you see Red Box with stack trace, you can click any ' + - 'stack frame to jump to the source file. The packager will launch your ' + - 'editor of choice. It will first look at REACT_EDITOR environment ' + - 'variable, then at EDITOR. To set it up, you can add something like ' + - 'REACT_EDITOR=atom to your .bashrc.'); - firstLaunch = false; - } - - var editor = process.env.REACT_EDITOR || process.env.EDITOR || 'subl'; - return editor; -} - -function launchEditor(fileName, lineNumber) { - if (!fs.existsSync(fileName)) { - return; - } - - var argument = fileName; - if (lineNumber) { - argument += ':' + lineNumber; - } - - var editor = guessEditor(); - console.log('Opening ' + fileName + ' with ' + editor); - spawn(editor, [argument], { stdio: ['pipe', 'pipe', process.stderr] }); -} - -module.exports = launchEditor; diff --git a/packager/launchPackager.command b/packager/launchPackager.command deleted file mode 100755 index dc56d7ff375..00000000000 --- a/packager/launchPackager.command +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Set terminal title -echo -en "\033]0;React Packager\a" -clear - -THIS_DIR=$(dirname "$0") -$THIS_DIR/packager.sh -echo "Process terminated. Press to close the window" -read diff --git a/packager/packager.js b/packager/packager.js deleted file mode 100644 index ca4e5c67590..00000000000 --- a/packager/packager.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - */ -'use strict'; - -var fs = require('fs'); -var path = require('path'); - -if (!fs.existsSync(path.resolve(__dirname, '..', 'node_modules'))) { - console.log( - '\n' + - 'Could not find dependencies.\n' + - 'Ensure dependencies are installed - ' + - 'run \'npm install\' from project root.\n' - ); - process.exit(); -} - -var ReactPackager = require('./react-packager'); -var blacklist = require('./blacklist.js'); -var connect = require('connect'); -var http = require('http'); -var launchEditor = require('./launchEditor.js'); -var parseCommandLine = require('./parseCommandLine.js'); - -var options = parseCommandLine([{ - command: 'port', - default: 8081, -}, { - command: 'root', - description: 'add another root(s) to be used by the packager in this project', -}]); - -if (!options.projectRoots) { - options.projectRoots = [path.resolve(__dirname, '..')]; -} - -if (options.root) { - if (typeof options.root === 'string') { - options.projectRoots.push(path.resolve(options.root)); - } else { - options.root.forEach(function(root) { - options.projectRoots.push(path.resolve(root)); - }); - } -} - -console.log('\n' + -' ===============================================================\n' + -' | Running packager on port ' + options.port + '. \n' + -' | Keep this packager running while developing on any JS \n' + -' | projects. Feel free to close this tab and run your own \n' + -' | packager instance if you prefer. \n' + -' | \n' + -' | https://github.com/facebook/react-native \n' + -' | \n' + -' ===============================================================\n' -); - -process.on('uncaughtException', function(e) { - console.error(e); - console.error(e.stack); - console.error('\n >>> ERROR: could not create packager - please shut down ' + - 'any existing instances that are already running.\n\n'); -}); - -runServer(options, function() { - console.log('\nReact packager ready.\n'); -}); - -function loadRawBody(req, res, next) { - req.rawBody = ''; - req.setEncoding('utf8'); - - req.on('data', function(chunk) { - req.rawBody += chunk; - }); - - req.on('end', function() { - next(); - }); -} - -function openStackFrameInEditor(req, res, next) { - if (req.url === '/open-stack-frame') { - var frame = JSON.parse(req.rawBody); - launchEditor(frame.file, frame.lineNumber); - res.end('OK'); - } else { - next(); - } -} - -function getAppMiddleware(options) { - return ReactPackager.middleware({ - projectRoots: options.projectRoots, - blacklistRE: blacklist(false), - cacheVersion: '2', - transformModulePath: require.resolve('./transformer.js'), - }); -} - -function runServer( - options, /* {[]string projectRoot, bool web} */ - readyCallback -) { - var app = connect() - .use(loadRawBody) - .use(openStackFrameInEditor) - .use(getAppMiddleware(options)); - - options.projectRoots.forEach(function(root) { - app.use(connect.static(root)); - }); - - app.use(connect.logger()) - .use(connect.compress()) - .use(connect.errorHandler()); - - return http.createServer(app).listen(options.port, readyCallback); -} diff --git a/packager/packager.sh b/packager/packager.sh deleted file mode 100755 index 98e4218423e..00000000000 --- a/packager/packager.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -ulimit -n 4096 - -THIS_DIR=$(dirname "$0") -node $THIS_DIR/packager.js "$@" diff --git a/packager/parseCommandLine.js b/packager/parseCommandLine.js deleted file mode 100644 index 5240d37d678..00000000000 --- a/packager/parseCommandLine.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * Wrapper on-top of `optimist` in order to properly support boolean flags - * and have a slightly less akward API. - * - * Usage example: - * var argv = parseCommandLine([{ - * command: 'web', - * description: 'Run in a web browser instead of iOS', - * default: true - * }]) - */ -'use strict'; - -var optimist = require('optimist'); - -function parseCommandLine(config) { - // optimist default API requires you to write the command name three time - // This is a small wrapper to accept an object instead - for (var i = 0; i < config.length; ++i) { - optimist - .boolean(config[i].command) - .default(config[i].command, config[i].default) - .describe(config[i].command, config[i].description); - } - var argv = optimist.argv; - - // optimist doesn't have support for --dev=false, instead it returns 'false' - for (var i = 0; i < config.length; ++i) { - var command = config[i].command; - if (argv[command] === undefined) { - argv[command] = config[i].default; - } - if (argv[command] === 'true') { - argv[command] = true; - } - if (argv[command] === 'false') { - argv[command] = false; - } - } - - // Show --help - if (argv.help || argv.h) { - optimist.showHelp(); - process.exit(); - } - - return argv; -} - -module.exports = parseCommandLine; diff --git a/packager/react-packager/.npmignore b/packager/react-packager/.npmignore deleted file mode 100644 index 2113f1066dc..00000000000 --- a/packager/react-packager/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -*~ -*.swm -*.swn -*.swp -*.DS_STORE -npm-debug.log -.cache -node_modules diff --git a/packager/react-packager/__mocks__/debug.js b/packager/react-packager/__mocks__/debug.js deleted file mode 100644 index d35fffd4aeb..00000000000 --- a/packager/react-packager/__mocks__/debug.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = function() { - return function() {}; -}; diff --git a/packager/react-packager/__mocks__/net.js b/packager/react-packager/__mocks__/net.js deleted file mode 100644 index 661fb196d9a..00000000000 --- a/packager/react-packager/__mocks__/net.js +++ /dev/null @@ -1,26 +0,0 @@ -var EventEmitter = require('events').EventEmitter; -var servers = {}; -exports.createServer = function(listener) { - var server = { - _listener: listener, - - socket: new EventEmitter(), - - listen: function(path) { - listener(this.socket); - servers[path] = this; - } - }; - - server.socket.setEncoding = function() {}; - server.socket.write = function(data) { - this.emit('data', data); - }; - - return server; -}; - -exports.connect = function(options) { - var server = servers[options.path || options.port]; - return server.socket; -}; diff --git a/packager/react-packager/example_project/bar.js b/packager/react-packager/example_project/bar.js deleted file mode 100644 index cc56ce6ec30..00000000000 --- a/packager/react-packager/example_project/bar.js +++ /dev/null @@ -1,5 +0,0 @@ -/** - * @providesModule bar - */ - - module.exports = setInterval; \ No newline at end of file diff --git a/packager/react-packager/example_project/config.json b/packager/react-packager/example_project/config.json deleted file mode 100644 index 0acdcb514db..00000000000 --- a/packager/react-packager/example_project/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "port": 3000, - "devPort": 3001, - "publicDir": "./public", - "rootPath": "../example_project", - "moduleOptions": { - "format": "haste", - "main": "index.js" - } -} diff --git a/packager/react-packager/example_project/foo/foo.js b/packager/react-packager/example_project/foo/foo.js deleted file mode 100644 index c45d9abaadc..00000000000 --- a/packager/react-packager/example_project/foo/foo.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @providesModule foo - */ - - -var bar = require('bar'); - -class Logger { - log() { - console.log('youll have to change me lol'); - } -} - -class SecretLogger extends Logger { - log(secret) { - console.log('logging ', secret); - } -} - -module.exports = (secret) => { - if (secret !== 'secret') throw new Error('wrong secret'); - bar(new SecretLogger().log.bind(SecretLogger, secret), 400); -}; diff --git a/packager/react-packager/example_project/index.js b/packager/react-packager/example_project/index.js deleted file mode 100644 index 2943d187513..00000000000 --- a/packager/react-packager/example_project/index.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @providesModule index - * @jsx React.DOM - */ - -require('main'); -require('code'); - -var foo = require('foo'); -foo('secret'); diff --git a/packager/react-packager/example_project/js/Channel.js b/packager/react-packager/example_project/js/Channel.js deleted file mode 100644 index d3cbae1c170..00000000000 --- a/packager/react-packager/example_project/js/Channel.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @providesModule Channel - */ - -var XHR = require('XHR'); - -/** - * Client implementation of a server-push channel. - * - * @see Channel.js for full documentation - */ -var channel = null, at = null, delay = 0; -var Channel = {}; - -Channel.connect = function() { - var url = '/pull'; - if (channel) { - url += '?channel=' + channel + '&at=' + at; - } - XHR.get(url, function(err, xhr) { - if (err) { - delay = Math.min(Math.max(1000, delay * 2), 30000); - } else { - var res = xhr.responseText; - res = JSON.parse(res); - - delay = 0; - - // Cache channel state - channel = res.channel; - at = res.at; - - var messages = res.messages; - messages.forEach(function(message) { - var ev = document.createEvent('CustomEvent'); - ev.initCustomEvent(message.event, true, true, message.detail); - window.dispatchEvent(ev); - }); - } - - // Reconnect - setTimeout(Channel.connect, delay); - }); -}; - -module.exports = Channel; diff --git a/packager/react-packager/example_project/js/XHR.js b/packager/react-packager/example_project/js/XHR.js deleted file mode 100644 index d9e0563f023..00000000000 --- a/packager/react-packager/example_project/js/XHR.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @providesModule XHR - */ - -function request(method, url, callback) { - var xhr = new XMLHttpRequest(); - xhr.open(method, url); - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - callback(null, xhr); - } else { - callback(new Error('status = ' + xhr.status, xhr)); - } - } - }; - xhr.send(); -} - -exports.get = function(url, callback) { - request('GET', url, callback); -}; diff --git a/packager/react-packager/example_project/js/code.js b/packager/react-packager/example_project/js/code.js deleted file mode 100644 index 70067859882..00000000000 --- a/packager/react-packager/example_project/js/code.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @providesModule code - */ -var XHR = require('XHR'); - -var $ = function(sel) {return document.querySelector(sel);}; - -function getListItems(files) { - var items = []; - files.forEach(function(file) { - var displayName = file.name + (file.type == 1 ? '/' : ''); - items.push( - React.DOM.li({ - className: 'type' + file.type, - key: file.ino - }, displayName) - ); - if (file.type === 1) { - items.push(getListItems(file.nodes)); - } - }); - - return React.DOM.ol(null, items); -} - -var FileList = React.createClass({ - getInitialState: function() { - return {files: []}; - }, - - componentDidMount: function() { - XHR.get( - this.props.source, - function(err, xhr) { - if (err) {throw err;} - - var files = JSON.parse(xhr.responseText); - this.setState({files: files}); - }.bind(this) - ); - }, - - render: function() { - return getListItems(this.state.files); - } -}); - -window.addEventListener('load', function() { - React.render(React.createElement(FileList, {source: '/files'}), - $('#code')); -}); diff --git a/packager/react-packager/example_project/js/main.js b/packager/react-packager/example_project/js/main.js deleted file mode 100644 index 58847092de0..00000000000 --- a/packager/react-packager/example_project/js/main.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @providesModule main - */ -var Channel = require('Channel'); - -function toArray(arr) {return Array.prototype.slice.apply(arr);} -function $(sel) {return document.querySelector(sel);} -function $$(sel) {return toArray(document.querySelectorAll(sel));} - -window.addEventListener('load', function() { - function channelLog() { - var args = Array.prototype.slice.apply(arguments); - var ts = new Date(); - var el = document.createElement('li'); - args.unshift(ts.getHours() + ':' + - ('0' + ts.getMinutes()).substr(0,2) + ':' + - ('0' + ts.getSeconds()).substr(0,2)); - el.className = 'console-entry'; - el.innerHTML = args.join(' '); - $('#console').appendChild(el); - el.scrollIntoView(); - } - - global.addEventListener('ChannelInit', function(event) { - $('#console').innerHTML = ''; - channelLog(event.type); - }); - - global.addEventListener('ChannelLog', function(event) { - channelLog.apply(null, event.detail); - }); - - // Tab pane support - function showTab(paneId) { - paneId = paneId.replace(/\W/g, ''); - if (paneId) { - $$('#nav-panes > div').forEach(function(pane) { - pane.classList.toggle('active', pane.id === paneId); - }); - $$('#nav-tabs li').forEach(function(tab) { - tab.classList.toggle('active', - tab.getAttribute('data-pane') === paneId); - }); - global.history.replaceState(null, null, '#' + paneId); - } - } - - $('#nav-tabs').onclick = function(e) { - showTab(e.target.getAttribute('data-pane')); - }; - - // Show current pane - showTab(location.hash); - - // Connect to server-push channel - Channel.connect(); -}); diff --git a/packager/react-packager/example_project/public/css/index.css b/packager/react-packager/example_project/public/css/index.css deleted file mode 100644 index 7d36bf2ce47..00000000000 --- a/packager/react-packager/example_project/public/css/index.css +++ /dev/null @@ -1,94 +0,0 @@ -html { - font-family: sans-serif; -} -body { - margin-right: 200px -} - -#nav-tabs { - margin: 0; - padding: 0; - position: absolute; - top: 0px; - left: 0px; - right: 0px; - background-color: #eee; - border-bottom: solid 1px black; - font-size: 10pt; - font-weight: bold; - vertical-align: bottom; - line-height: 20px; - height: 29px; -} -#nav-tabs li { - padding: 0 10px; - margin: 0; - border-bottom-width: 0; - display:inline-block; - cursor: pointer; - line-height: 29px; -} -#nav-tabs li:first-child { - color: #666; -} -#nav-tabs li.active { - background-color: #fff; -} - -#nav-panes { - position: absolute; - top: 30px; - left: 0px; - right: 0px; - bottom: 0px; - scroll: auto; - overflow: auto; - background-color: #fff; -} - -#nav-panes .pane { - display: none; -} -#nav-panes .active { - display: block; -} - -.pane { - padding: 10px; -} - -#console { - padding-left: 5px; -} -#console li { - font-size: 10pt; - font-family: monospace; - white-space: nowrap; - margin: 0; - list-style: none; -} - -#code > ol { - font-size: 10pt; - font-family: monospace; - margin: 0; - padding: 0; - cursor: pointer; -} -#code ol ol { - margin-left: 1em; - padding-left: 1em; - border-left: dashed 1px #ddd; -} -#code li { - color: #000; - font-weight: normal; - list-style: none; - line-height: 1.2em; -} -#code .type1 { - color: #009; -} -#code .type2 { - color: #909; -} diff --git a/packager/react-packager/example_project/public/index.html b/packager/react-packager/example_project/public/index.html deleted file mode 100644 index b19685d5709..00000000000 --- a/packager/react-packager/example_project/public/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/packager/react-packager/index.js b/packager/react-packager/index.js deleted file mode 100644 index 65ae88d8d5e..00000000000 --- a/packager/react-packager/index.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; - -var Activity = require('./src/Activity'); -var Server = require('./src/Server'); - -exports.middleware = function(options) { - var server = new Server(options); - return server.processRequest.bind(server); -}; - -exports.buildPackageFromUrl = function(options, reqUrl) { - Activity.disable(); - // Don't start the filewatcher or the cache. - if (options.nonPersistent == null) { - options.nonPersistent = true; - } - - var server = new Server(options); - return server.buildPackageFromUrl(reqUrl) - .then(function(p) { - server.end(); - return p; - }); -}; - -exports.getDependencies = function(options, main) { - Activity.disable(); - // Don't start the filewatcher or the cache. - if (options.nonPersistent == null) { - options.nonPersistent = true; - } - - var server = new Server(options); - return server.getDependencies(main) - .then(function(r) { - server.end(); - return r.dependencies; - }); -}; diff --git a/packager/react-packager/src/Activity/__tests__/Activity-test.js b/packager/react-packager/src/Activity/__tests__/Activity-test.js deleted file mode 100644 index 7fe31614820..00000000000 --- a/packager/react-packager/src/Activity/__tests__/Activity-test.js +++ /dev/null @@ -1,85 +0,0 @@ -'use strict'; - -jest.autoMockOff(); - -describe('Activity', function() { - var Activity; - - var origConsoleLog = console.log; - - beforeEach(function() { - console.log = jest.genMockFn(); - Activity = require('../'); - jest.runOnlyPendingTimers(); - }); - - afterEach(function() { - console.log = origConsoleLog; - }); - - describe('startEvent', function() { - it('writes a START event out to the console', function() { - var EVENT_NAME = 'EVENT_NAME'; - var DATA = {someData: 42}; - - Activity.startEvent(EVENT_NAME, DATA); - jest.runOnlyPendingTimers(); - - expect(console.log.mock.calls.length).toBe(1); - var consoleMsg = console.log.mock.calls[0][0]; - expect(consoleMsg).toContain('START'); - expect(consoleMsg).toContain(EVENT_NAME); - expect(consoleMsg).toContain(JSON.stringify(DATA)); - }); - }); - - describe('endEvent', function() { - it('writes an END event out to the console', function() { - var EVENT_NAME = 'EVENT_NAME'; - var DATA = {someData: 42}; - - var eventID = Activity.startEvent(EVENT_NAME, DATA); - Activity.endEvent(eventID); - jest.runOnlyPendingTimers(); - - expect(console.log.mock.calls.length).toBe(2); - var consoleMsg = console.log.mock.calls[1][0]; - expect(consoleMsg).toContain('END'); - expect(consoleMsg).toContain(EVENT_NAME); - expect(consoleMsg).toContain(JSON.stringify(DATA)); - }); - - it('throws when called with an invalid eventId', function() { - expect(function() { - Activity.endEvent(42); - }).toThrow('event(42) is not a valid event id!'); - }); - - it('throws when called with an expired eventId', function() { - var eid = Activity.startEvent('', ''); - Activity.endEvent(eid); - - expect(function() { - Activity.endEvent(eid); - }).toThrow('event(3) has already ended!'); - - jest.runOnlyPendingTimers(); - }); - }); - - describe('signal', function() { - it('writes a SIGNAL event out to the console', function() { - - var EVENT_NAME = 'EVENT_NAME'; - var DATA = {someData: 42}; - - Activity.signal(EVENT_NAME, DATA); - jest.runOnlyPendingTimers(); - - expect(console.log.mock.calls.length).toBe(1); - var consoleMsg = console.log.mock.calls[0][0]; - expect(consoleMsg).toContain(EVENT_NAME); - expect(consoleMsg).toContain(JSON.stringify(DATA)); - }); - }); -}); diff --git a/packager/react-packager/src/Activity/index.js b/packager/react-packager/src/Activity/index.js deleted file mode 100644 index 611ccb0b176..00000000000 --- a/packager/react-packager/src/Activity/index.js +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; - -var COLLECTION_PERIOD = 1000; - -var _endedEvents = Object.create(null); -var _eventStarts = Object.create(null); -var _queuedActions = []; -var _scheduledCollectionTimer = null; -var _uuid = 1; -var _enabled = true; - -function endEvent(eventId) { - var eventEndTime = Date.now(); - - if (!_eventStarts[eventId]) { - _throw('event(' + eventId + ') is not a valid event id!'); - } - - if (_endedEvents[eventId]) { - _throw('event(' + eventId + ') has already ended!'); - } - - _scheduleAction({ - action: 'endEvent', - eventId: eventId, - tstamp: eventEndTime - }); - _endedEvents[eventId] = true; -} - -function signal(eventName, data) { - var signalTime = Date.now(); - - if (eventName == null) { - _throw('No event name specified'); - } - - if (data == null) { - data = null; - } - - _scheduleAction({ - action: 'signal', - data: data, - eventName: eventName, - tstamp: signalTime - }); -} - -function startEvent(eventName, data) { - var eventStartTime = Date.now(); - - if (eventName == null) { - _throw('No event name specified'); - } - - if (data == null) { - data = null; - } - - var eventId = _uuid++; - var action = { - action: 'startEvent', - data: data, - eventId: eventId, - eventName: eventName, - tstamp: eventStartTime, - }; - _scheduleAction(action); - _eventStarts[eventId] = action; - - return eventId; -} - -function disable() { - _enabled = false; -} - -function _runCollection() { - /* jshint -W084 */ - var action; - while ((action = _queuedActions.shift())) { - _writeAction(action); - } - - _scheduledCollectionTimer = null; -} - -function _scheduleAction(action) { - _queuedActions.push(action); - - if (_scheduledCollectionTimer === null) { - _scheduledCollectionTimer = setTimeout(_runCollection, COLLECTION_PERIOD); - } -} - -/** - * This a utility function that throws an error message. - * - * The only purpose of this utility is to make APIs like - * startEvent/endEvent/signal inlineable in the JIT. - * - * (V8 can't inline functions that statically contain a `throw`, and probably - * won't be adding such a non-trivial optimization anytime soon) - */ -function _throw(msg) { - var err = new Error(msg); - - // Strip off the call to _throw() - var stack = err.stack.split('\n'); - stack.splice(1, 1); - err.stack = stack.join('\n'); - - throw err; -} - -function _writeAction(action) { - if (!_enabled) { - return; - } - - var data = action.data ? ': ' + JSON.stringify(action.data) : ''; - var fmtTime = new Date(action.tstamp).toLocaleTimeString(); - - switch (action.action) { - case 'startEvent': - console.log( - '[' + fmtTime + '] ' + - ' ' + action.eventName + - data - ); - break; - - case 'endEvent': - var startAction = _eventStarts[action.eventId]; - var startData = startAction.data ? ': ' + JSON.stringify(startAction.data) : ''; - console.log( - '[' + fmtTime + '] ' + - ' ' + startAction.eventName + - '(' + (action.tstamp - startAction.tstamp) + 'ms)' + - startData - ); - delete _eventStarts[action.eventId]; - break; - - case 'signal': - console.log( - '[' + fmtTime + '] ' + - ' ' + action.eventName + '' + - data - ); - break; - - default: - _throw('Unexpected scheduled action type: ' + action.action); - } -} - - -exports.endEvent = endEvent; -exports.signal = signal; -exports.startEvent = startEvent; -exports.disable = disable; diff --git a/packager/react-packager/src/DependencyResolver/ModuleDescriptor.js b/packager/react-packager/src/DependencyResolver/ModuleDescriptor.js deleted file mode 100644 index f1a30545c94..00000000000 --- a/packager/react-packager/src/DependencyResolver/ModuleDescriptor.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -function ModuleDescriptor(fields) { - if (!fields.id) { - throw new Error('Missing required fields id'); - } - this.id = fields.id; - - if (!fields.path) { - throw new Error('Missing required fields path'); - } - this.path = fields.path; - - if (!fields.dependencies) { - throw new Error('Missing required fields dependencies'); - } - this.dependencies = fields.dependencies; - - this.resolveDependency = fields.resolveDependency; - - this.entry = fields.entry || false; - - this.isPolyfill = fields.isPolyfill || false; - - this._fields = fields; -} - -ModuleDescriptor.prototype.toJSON = function() { - return { - id: this.id, - path: this.path, - dependencies: this.dependencies - }; -}; - -module.exports = ModuleDescriptor; diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__mocks__/fs.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__mocks__/fs.js deleted file mode 100644 index de3622d9315..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__mocks__/fs.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -var fs = jest.genMockFromModule('fs'); - -fs.realpath.mockImpl(function(filepath, callback) { - var node; - try { - node = getToNode(filepath); - } catch (e) { - return callback(e); - } - if (node && typeof node === 'object' && node.SYMLINK != null) { - return callback(null, node.SYMLINK); - } - callback(null, filepath); -}); - -fs.readdir.mockImpl(function(filepath, callback) { - var node; - try { - node = getToNode(filepath); - if (node && typeof node === 'object' && node.SYMLINK != null) { - node = getToNode(node.SYMLINK); - } - } catch (e) { - return callback(e); - } - - if (!(node && typeof node === 'object' && node.SYMLINK == null)) { - return callback(new Error(filepath + ' is not a directory.')); - } - - callback(null, Object.keys(node)); -}); - -fs.readFile.mockImpl(function(filepath, encoding, callback) { - try { - var node = getToNode(filepath); - // dir check - if (node && typeof node === 'object' && node.SYMLINK == null) { - callback(new Error('Trying to read a dir, ESIDR, or whatever')); - } - return callback(null, node); - } catch (e) { - return callback(e); - } -}); - -fs.lstat.mockImpl(function(filepath, callback) { - var node; - try { - node = getToNode(filepath); - } catch (e) { - return callback(e); - } - - if (node && typeof node === 'object' && node.SYMLINK == null) { - callback(null, { - isDirectory: function() { - return true; - }, - isSymbolicLink: function() { - return false; - } - }); - } else { - callback(null, { - isDirectory: function() { - return false; - }, - isSymbolicLink: function() { - if (typeof node === 'object' && node.SYMLINK) { - return true; - } - return false; - } - }); - } -}); - -var filesystem; - -fs.__setMockFilesystem = function(object) { - filesystem = object; - return filesystem; -}; - -function getToNode(filepath) { - var parts = filepath.split('/'); - if (parts[0] !== '') { - throw new Error('Make sure all paths are absolute.'); - } - var node = filesystem; - parts.slice(1).forEach(function(part) { - node = node[part]; - }); - - return node; -} - -module.exports = fs; diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js deleted file mode 100644 index eb839296c67..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js +++ /dev/null @@ -1,772 +0,0 @@ -'use strict'; - -jest - .dontMock('../index') - .dontMock('q') - .dontMock('path') - .dontMock('absolute-path') - .dontMock('../docblock') - .setMock('../../../ModuleDescriptor', function(data) {return data;}); - -describe('DependencyGraph', function() { - var DependencyGraph; - var fileWatcher; - var fs; - - beforeEach(function() { - fs = require('fs'); - DependencyGraph = require('../index'); - - fileWatcher = { - on: function() { - return this; - } - }; - }); - - describe('getOrderedDependencies', function() { - pit('should get dependencies', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("a")' - ].join('\n'), - 'a.js': [ - '/**', - ' * @providesModule a', - ' */', - ].join('\n'), - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - {id: 'index', path: '/root/index.js', dependencies: ['a']}, - {id: 'a', path: '/root/a.js', dependencies: []}, - ]); - }); - }); - - pit('should get recursive dependencies', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("a")', - ].join('\n'), - 'a.js': [ - '/**', - ' * @providesModule a', - ' */', - 'require("index")', - ].join('\n'), - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - {id: 'index', path: '/root/index.js', dependencies: ['a']}, - {id: 'a', path: '/root/a.js', dependencies: ['index']}, - ]); - }); - }); - - pit('should work with packages', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'lol' - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - {id: 'index', path: '/root/index.js', dependencies: ['aPackage']}, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: [] - }, - ]); - }); - }); - - pit('should ignore malformed packages', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - ].join('\n'), - 'aPackage': { - 'package.json': 'lol', - 'main.js': 'lol' - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - {id: 'index', path: '/root/index.js', dependencies: ['aPackage']}, - ]); - }); - }); - - pit('can have multiple modules with the same name', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("b")', - ].join('\n'), - 'b.js': [ - '/**', - ' * @providesModule b', - ' */', - ].join('\n'), - 'c.js': [ - '/**', - ' * @providesModule c', - ' */', - ].join('\n'), - 'somedir': { - 'somefile.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("c")', - ].join('\n') - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/somedir/somefile.js')) - .toEqual([ - { id: 'index', - path: '/root/somedir/somefile.js', - dependencies: ['c'] - }, - { id: 'c', - path: '/root/c.js', - dependencies: [] - }, - ]); - }); - }); - - pit('providesModule wins when conflict with package', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - ].join('\n'), - 'b.js': [ - '/**', - ' * @providesModule aPackage', - ' */', - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'lol' - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'] - }, - { id: 'aPackage', - path: '/root/b.js', - dependencies: [] - }, - ]); - }); - }); - - pit('should be forgiving with missing requires', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("lolomg")', - ].join('\n') - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['lolomg'] - } - ]); - }); - }); - - pit('should work with packages with subdirs', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage/subdir/lolynot")', - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'lol', - 'subdir': { - 'lolynot.js': 'lolynot' - } - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage/subdir/lolynot'] - }, - { id: 'aPackage/subdir/lolynot', - path: '/root/aPackage/subdir/lolynot.js', - dependencies: [] - }, - ]); - }); - }); - - pit('should work with packages with symlinked subdirs', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'symlinkedPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'lol', - 'subdir': { - 'lolynot.js': 'lolynot' - } - }, - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage/subdir/lolynot")', - ].join('\n'), - 'aPackage': { SYMLINK: '/symlinkedPackage' }, - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage/subdir/lolynot'] - }, - { id: 'aPackage/subdir/lolynot', - path: '/symlinkedPackage/subdir/lolynot.js', - dependencies: [] - }, - ]); - }); - }); - - pit('should work with relative modules in packages', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'require("./subdir/lolynot")', - 'subdir': { - 'lolynot.js': 'require("../other")' - }, - 'other.js': 'some code' - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: ['./subdir/lolynot'] - }, - { id: 'aPackage/subdir/lolynot', - path: '/root/aPackage/subdir/lolynot.js', - dependencies: ['../other'] - }, - { id: 'aPackage/other', - path: '/root/aPackage/other.js', - dependencies: [] - }, - ]); - }); - }); - }); - - describe('file watch updating', function() { - var triggerFileChange; - - beforeEach(function() { - fileWatcher = { - on: function(eventType, callback) { - if (eventType !== 'all') { - throw new Error('Can only handle "all" event in watcher.'); - } - triggerFileChange = callback; - return this; - } - }; - }); - - pit('updates module dependencies', function() { - var root = '/root'; - var filesystem = fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - 'require("foo")' - ].join('\n'), - 'foo': [ - '/**', - ' * @providesModule foo', - ' */', - 'require("aPackage")' - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'main', - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - filesystem.root['index.js'] = - filesystem.root['index.js'].replace('require("foo")', ''); - triggerFileChange('change', 'index.js', root); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: [] - }, - ]); - }); - }); - }); - - pit('updates module dependencies on file change', function() { - var root = '/root'; - var filesystem = fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - 'require("foo")' - ].join('\n'), - 'foo.js': [ - '/**', - ' * @providesModule foo', - ' */', - 'require("aPackage")' - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'main', - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - filesystem.root['index.js'] = - filesystem.root['index.js'].replace('require("foo")', ''); - triggerFileChange('change', 'index.js', root); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: [] - }, - ]); - }); - }); - }); - - pit('updates module dependencies on file delete', function() { - var root = '/root'; - var filesystem = fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - 'require("foo")' - ].join('\n'), - 'foo.js': [ - '/**', - ' * @providesModule foo', - ' */', - 'require("aPackage")' - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'main', - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - delete filesystem.root.foo; - triggerFileChange('delete', 'foo.js', root); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage', 'foo'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: [] - }, - ]); - }); - }); - }); - - pit('updates module dependencies on file add', function() { - var root = '/root'; - var filesystem = fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - 'require("foo")' - ].join('\n'), - 'foo.js': [ - '/**', - ' * @providesModule foo', - ' */', - 'require("aPackage")' - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'main', - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - filesystem.root['bar.js'] = [ - '/**', - ' * @providesModule bar', - ' */', - 'require("foo")' - ].join('\n'); - triggerFileChange('add', 'bar.js', root); - - filesystem.root.aPackage['main.js'] = 'require("bar")'; - triggerFileChange('change', 'aPackage/main.js', root); - - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage', 'foo'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: ['bar'] - }, - { id: 'bar', - path: '/root/bar.js', - dependencies: ['foo'] - }, - { id: 'foo', - path: '/root/foo.js', - dependencies: ['aPackage'] - }, - ]); - }); - }); - }); - - pit('runs changes through ignore filter', function() { - var root = '/root'; - var filesystem = fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - 'require("foo")' - ].join('\n'), - 'foo.js': [ - '/**', - ' * @providesModule foo', - ' */', - 'require("aPackage")' - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'main', - } - } - }); - - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher, - ignoreFilePath: function(filePath) { - if (filePath === '/root/bar.js') { - return true; - } - return false; - } - }); - return dgraph.load().then(function() { - filesystem.root['bar.js'] = [ - '/**', - ' * @providesModule bar', - ' */', - 'require("foo")' - ].join('\n'); - triggerFileChange('add', 'bar.js', root); - - filesystem.root.aPackage['main.js'] = 'require("bar")'; - triggerFileChange('change', 'aPackage/main.js', root); - - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage', 'foo'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: ['bar'] - }, - { id: 'foo', - path: '/root/foo.js', - dependencies: ['aPackage'] - }, - ]); - }); - }); - }); - - pit('should ignore directory updates', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'require("aPackage")', - 'require("foo")' - ].join('\n'), - 'foo.js': [ - '/**', - ' * @providesModule foo', - ' */', - 'require("aPackage")' - ].join('\n'), - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: 'main.js' - }), - 'main.js': 'main', - } - } - }); - var dgraph = new DependencyGraph({ - roots: [root], - fileWatcher: fileWatcher - }); - return dgraph.load().then(function() { - triggerFileChange('change', 'aPackage', '/root', { - isDirectory: function(){ return true; } - }); - return dgraph.load().then(function() { - expect(dgraph.getOrderedDependencies('/root/index.js')) - .toEqual([ - { id: 'index', - path: '/root/index.js', - dependencies: ['aPackage', 'foo'] - }, - { id: 'aPackage/main', - path: '/root/aPackage/main.js', - dependencies: [] - }, - { id: 'foo', - path: '/root/foo.js', - dependencies: ['aPackage'] - }, - ]); - }); - }); - }); - }); -}); diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/docblock.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/docblock.js deleted file mode 100644 index c2b6ac98464..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/docblock.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -var docblockRe = /^\s*(\/\*\*(.|\r?\n)*?\*\/)/; - -var ltrimRe = /^\s*/; -/** - * @param {String} contents - * @return {String} - */ -function extract(contents) { - var match = contents.match(docblockRe); - if (match) { - return match[0].replace(ltrimRe, '') || ''; - } - return ''; -} - - -var commentStartRe = /^\/\*\*?/; -var commentEndRe = /\*\/$/; -var wsRe = /[\t ]+/g; -var stringStartRe = /(\r?\n|^) *\*/g; -var multilineRe = - /(?:^|\r?\n) *(@[^\r\n]*?) *\r?\n *([^@\r\n\s][^@\r\n]+?) *\r?\n/g; -var propertyRe = /(?:^|\r?\n) *@(\S+) *([^\r\n]*)/g; - -/** - * @param {String} contents - * @return {Array} - */ -function parse(docblock) { - docblock = docblock - .replace(commentStartRe, '') - .replace(commentEndRe, '') - .replace(wsRe, ' ') - .replace(stringStartRe, '$1'); - - // Normalize multi-line directives - var prev = ''; - while (prev !== docblock) { - prev = docblock; - docblock = docblock.replace(multilineRe, '\n$1 $2\n'); - } - docblock = docblock.trim(); - - var result = []; - var match; - while ((match = propertyRe.exec(docblock))) { - result.push([match[1], match[2]]); - } - - return result; -} - -/** - * Same as parse but returns an object of prop: value instead of array of paris - * If a property appers more than once the last one will be returned - * - * @param {String} contents - * @return {Object} - */ -function parseAsObject(docblock) { - var pairs = parse(docblock); - var result = {}; - for (var i = 0; i < pairs.length; i++) { - result[pairs[i][0]] = pairs[i][1]; - } - return result; -} - - -exports.extract = extract; -exports.parse = parse; -exports.parseAsObject = parseAsObject; diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js deleted file mode 100644 index ce63185629c..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js +++ /dev/null @@ -1,514 +0,0 @@ -'use strict'; - -var ModuleDescriptor = require('../../ModuleDescriptor'); -var q = require('q'); -var fs = require('fs'); -var docblock = require('./docblock'); -var path = require('path'); -var isAbsolutePath = require('absolute-path'); -var debug = require('debug')('DependecyGraph'); -var util = require('util'); -var declareOpts = require('../../../lib/declareOpts'); - -var readFile = q.nfbind(fs.readFile); -var readDir = q.nfbind(fs.readdir); -var lstat = q.nfbind(fs.lstat); -var realpath = q.nfbind(fs.realpath); - -var validateOpts = declareOpts({ - roots: { - type: 'array', - required: true, - }, - ignoreFilePath: { - type: 'function', - default: function(){} - }, - fileWatcher: { - type: 'object', - required: true, - }, -}); - -function DependecyGraph(options) { - var opts = validateOpts(options); - - this._roots = opts.roots; - this._ignoreFilePath = opts.ignoreFilePath; - this._fileWatcher = options.fileWatcher; - - this._loaded = false; - this._queue = this._roots.slice(); - this._graph = Object.create(null); - this._packageByRoot = Object.create(null); - this._packagesById = Object.create(null); - this._moduleById = Object.create(null); - this._debugUpdateEvents = []; - - // Kick off the search process to precompute the dependency graph. - this._init(); -} - -DependecyGraph.prototype.load = function() { - return this._loading || (this._loading = this._search()); -}; - -/** - * Given an entry file return an array of all the dependent module descriptors. - */ -DependecyGraph.prototype.getOrderedDependencies = function(entryPath) { - var absolutePath = this._getAbsolutePath(entryPath); - if (absolutePath == null) { - throw new Error('Cannot find entry file in any of the roots: ' + entryPath); - } - - var module = this._graph[absolutePath]; - if (module == null) { - throw new Error('Module with path "' + entryPath + '" is not in graph'); - } - - var self = this; - var deps = []; - var visited = Object.create(null); - - // Node haste sucks. Id's aren't unique. So to make sure our entry point - // is the thing that ends up in our dependency list. - var graphMap = Object.create(this._moduleById); - graphMap[module.id] = module; - - // Recursively collect the dependency list. - function collect(module) { - deps.push(module); - - module.dependencies.forEach(function(name) { - var id = sansExtJs(name); - var dep = self.resolveDependency(module, id); - - if (dep == null) { - debug( - 'WARNING: Cannot find required module `%s` from module `%s`.', - name, - module.id - ); - return; - } - - if (!visited[dep.id]) { - visited[dep.id] = true; - collect(dep); - } - }); - } - - visited[module.id] = true; - collect(module); - - return deps; -}; - -/** - * Given a module descriptor `fromModule` return the module descriptor for - * the required module `depModuleId`. It could be top-level or relative, - * or both. - */ -DependecyGraph.prototype.resolveDependency = function( - fromModule, - depModuleId -) { - var packageJson, modulePath, dep; - - // Package relative modules starts with '.' or '..'. - if (depModuleId[0] !== '.') { - - // 1. `depModuleId` is simply a top-level `providesModule`. - // 2. `depModuleId` is a package module but given the full path from the - // package, i.e. package_name/module_name - if (this._moduleById[sansExtJs(depModuleId)]) { - return this._moduleById[sansExtJs(depModuleId)]; - } - - // 3. `depModuleId` is a package and it's depending on the "main" - // resolution. - packageJson = this._packagesById[depModuleId]; - - // We are being forgiving here and raising an error because we could be - // processing a file that uses it's own require system. - if (packageJson == null) { - debug( - 'WARNING: Cannot find required module `%s` from module `%s`.', - depModuleId, - fromModule.id - ); - return null; - } - - var main = packageJson.main || 'index'; - modulePath = withExtJs(path.join(packageJson._root, main)); - dep = this._graph[modulePath]; - if (dep == null) { - throw new Error( - 'Cannot find package main file for package: ' + packageJson._root - ); - } - return dep; - } else { - - // 4. `depModuleId` is a module defined in a package relative to - // `fromModule`. - packageJson = this._lookupPackage(fromModule.path); - - if (packageJson == null) { - throw new Error( - 'Expected relative module lookup from ' + fromModule.id + ' to ' + - depModuleId + ' to be within a package but no package.json found.' - ); - } - - // Example: depModuleId: ../a/b - // fromModule.path: /x/y/z - // modulePath: /x/y/a/b - var dir = path.dirname(fromModule.path); - modulePath = withExtJs(path.join(dir, depModuleId)); - - dep = this._graph[modulePath]; - if (dep == null) { - debug( - 'WARNING: Cannot find required module `%s` from module `%s`.' + - ' Inferred required module path is %s', - depModuleId, - fromModule.id, - modulePath - ); - return null; - } - - return dep; - } -}; - -/** - * Intiates the filewatcher and kicks off the search process. - */ -DependecyGraph.prototype._init = function() { - var processChange = this._processFileChange.bind(this); - var watcher = this._fileWatcher; - - this._loading = this.load().then(function() { - watcher.on('all', processChange); - }); -}; - -/** - * Implements a DFS over the file system looking for modules and packages. - */ -DependecyGraph.prototype._search = function() { - var self = this; - var dir = this._queue.shift(); - - if (dir == null) { - return q.Promise.resolve(this._graph); - } - - // Steps: - // 1. Read a dir and stat all the entries. - // 2. Filter the files and queue up the directories. - // 3. Process any package.json in the files - // 4. recur. - return readDir(dir) - .then(function(files){ - return q.all(files.map(function(filePath) { - return realpath(path.join(dir, filePath)).catch(handleBrokenLink); - })); - }) - .then(function(filePaths) { - filePaths = filePaths.filter(function(filePath) { - if (filePath == null) { - return false; - } - - return !self._ignoreFilePath(filePath); - }); - - var statsP = filePaths.map(function(filePath) { - return lstat(filePath).catch(handleBrokenLink); - }); - - return [ - filePaths, - q.all(statsP) - ]; - }) - .spread(function(files, stats) { - var modulePaths = files.filter(function(filePath, i) { - if (stats[i].isDirectory()) { - self._queue.push(filePath); - return false; - } - - if (stats[i].isSymbolicLink()) { - return false; - } - - return filePath.match(/\.js$/); - }); - - var processing = self._findAndProcessPackage(files, dir) - .then(function() { - return q.all(modulePaths.map(self._processModule.bind(self))); - }); - - return q.all([ - processing, - self._search() - ]); - }) - .then(function() { - return self; - }); -}; - -/** - * Given a list of files find a `package.json` file, and if found parse it - * and update indices. - */ -DependecyGraph.prototype._findAndProcessPackage = function(files, root) { - var self = this; - - var packagePath; - for (var i = 0; i < files.length ; i++) { - var file = files[i]; - if (path.basename(file) === 'package.json') { - packagePath = file; - break; - } - } - - if (packagePath != null) { - return readFile(packagePath, 'utf8') - .then(function(content) { - var packageJson; - try { - packageJson = JSON.parse(content); - } catch (e) { - debug('WARNING: malformed package.json: ', packagePath); - return q(); - } - - if (packageJson.name == null) { - debug( - 'WARNING: package.json `%s` is missing a name field', - packagePath - ); - return q(); - } - - packageJson._root = root; - self._packageByRoot[root] = packageJson; - self._packagesById[packageJson.name] = packageJson; - - return packageJson; - }); - } else { - return q(); - } -}; - -/** - * Parse a module and update indices. - */ -DependecyGraph.prototype._processModule = function(modulePath) { - var self = this; - return readFile(modulePath, 'utf8') - .then(function(content) { - var moduleDocBlock = docblock.parseAsObject(content); - var moduleData = { path: path.resolve(modulePath) }; - if (moduleDocBlock.providesModule || moduleDocBlock.provides) { - moduleData.id = - moduleDocBlock.providesModule || moduleDocBlock.provides; - } else { - moduleData.id = self._lookupName(modulePath); - } - moduleData.dependencies = extractRequires(content); - - var module = new ModuleDescriptor(moduleData); - self._updateGraphWithModule(module); - return module; - }); -}; - -/** - * Compute the name of module relative to a package it may belong to. - */ -DependecyGraph.prototype._lookupName = function(modulePath) { - var packageJson = this._lookupPackage(modulePath); - if (packageJson == null) { - return path.resolve(modulePath); - } else { - var relativePath = - sansExtJs(path.relative(packageJson._root, modulePath)); - return path.join(packageJson.name, relativePath); - } -}; - -DependecyGraph.prototype._deleteModule = function(module) { - delete this._graph[module.path]; - - // Others may keep a reference so we mark it as deleted. - module.deleted = true; - - // Haste allows different module to have the same id. - if (this._moduleById[module.id] === module) { - delete this._moduleById[module.id]; - } -}; - -/** - * Update the graph and indices with the module. - */ -DependecyGraph.prototype._updateGraphWithModule = function(module) { - if (this._graph[module.path]) { - this._deleteModule(this._graph[module.path]); - } - - this._graph[module.path] = module; - - if (this._moduleById[module.id]) { - debug( - 'WARNING: Top-level module name conflict `%s`.\n' + - 'module with path `%s` will replace `%s`', - module.id, - module.path, - this._moduleById[module.id].path - ); - } - - this._moduleById[module.id] = module; -}; - -/** - * Find the nearest package to a module. - */ -DependecyGraph.prototype._lookupPackage = function(modulePath) { - var packageByRoot = this._packageByRoot; - - /** - * Auxiliary function to recursively lookup a package. - */ - function lookupPackage(currDir) { - // ideally we stop once we're outside root and this can be a simple child - // dir check. However, we have to support modules that was symlinked inside - // our project root. - if (currDir === '/') { - return null; - } else { - var packageJson = packageByRoot[currDir]; - if (packageJson) { - return packageJson; - } else { - return lookupPackage(path.dirname(currDir)); - } - } - } - - return lookupPackage(path.dirname(modulePath)); -}; - -/** - * Process a filewatcher change event. - */ -DependecyGraph.prototype._processFileChange = function(eventType, filePath, root, stat) { - var absPath = path.join(root, filePath); - if (this._ignoreFilePath(absPath)) { - return; - } - - this._debugUpdateEvents.push({event: eventType, path: filePath}); - - if (eventType === 'delete') { - var module = this._graph[absPath]; - if (module == null) { - return; - } - - this._deleteModule(module); - } else if (!(stat && stat.isDirectory())) { - var self = this; - this._loading = this._loading.then(function() { - return self._processModule(absPath); - }); - } -}; - -DependecyGraph.prototype.getDebugInfo = function() { - return '

FileWatcher Update Events

' + - '
' + util.inspect(this._debugUpdateEvents) + '
' + - '

Graph dump

' + - '
' + util.inspect(this._graph) + '
'; -}; - -/** - * Searches all roots for the file and returns the first one that has file of the same path. - */ -DependecyGraph.prototype._getAbsolutePath = function(filePath) { - if (isAbsolutePath(filePath)) { - return filePath; - } - - for (var i = 0; i < this._roots.length; i++) { - var root = this._roots[i]; - var absPath = path.join(root, filePath); - if (this._graph[absPath]) { - return absPath; - } - } - - return null; -}; - -/** - * Extract all required modules from a `code` string. - */ -var requireRe = /\brequire\s*\(\s*[\'"]([^"\']+)["\']\s*\)/g; -var blockCommentRe = /\/\*(.|\n)*?\*\//g; -var lineCommentRe = /\/\/.+(\n|$)/g; -function extractRequires(code) { - var deps = []; - - code - .replace(blockCommentRe, '') - .replace(lineCommentRe, '') - .replace(requireRe, function(match, dep) { - deps.push(dep); - }); - - return deps; -} - -/** - * `file` without the .js extension. - */ -function sansExtJs(file) { - if (file.match(/\.js$/)) { - return file.slice(0, -3); - } else { - return file; - } -} - -/** - * `file` with the .js extension. - */ -function withExtJs(file) { - if (file.match(/\.js$/)) { - return file; - } else { - return file + '.js'; - } -} - -function handleBrokenLink(e) { - debug('WARNING: error stating, possibly broken symlink', e.message); - return q(); -} - -module.exports = DependecyGraph; diff --git a/packager/react-packager/src/DependencyResolver/haste/__tests__/HasteDependencyResolver-test.js b/packager/react-packager/src/DependencyResolver/haste/__tests__/HasteDependencyResolver-test.js deleted file mode 100644 index b25fd8211fa..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/__tests__/HasteDependencyResolver-test.js +++ /dev/null @@ -1,254 +0,0 @@ -'use strict'; - -jest.dontMock('../') - .dontMock('q') - .setMock('../../ModuleDescriptor', function(data) {return data;}); - -var q = require('q'); - -describe('HasteDependencyResolver', function() { - var HasteDependencyResolver; - - beforeEach(function() { - // For the polyfillDeps - require('path').join.mockImpl(function(a, b) { - return b; - }); - HasteDependencyResolver = require('../'); - }); - - describe('getDependencies', function() { - pit('should get dependencies with polyfills', function() { - var module = {id: 'index', path: '/root/index.js', dependencies: ['a']}; - var deps = [module]; - - var depResolver = new HasteDependencyResolver({ - projectRoot: '/root', - }); - - // Is there a better way? How can I mock the prototype instead? - var depGraph = depResolver._depGraph; - depGraph.getOrderedDependencies.mockImpl(function() { - return deps; - }); - depGraph.load.mockImpl(function() { - return q(); - }); - - return depResolver.getDependencies('/root/index.js', { dev: false }) - .then(function(result) { - expect(result.mainModuleId).toEqual('index'); - expect(result.dependencies).toEqual([ - { path: 'polyfills/prelude.js', - id: 'polyfills/prelude.js', - isPolyfill: true, - dependencies: [] - }, - { path: 'polyfills/require.js', - id: 'polyfills/require.js', - isPolyfill: true, - dependencies: ['polyfills/prelude.js'] - }, - { path: 'polyfills/polyfills.js', - id: 'polyfills/polyfills.js', - isPolyfill: true, - dependencies: ['polyfills/prelude.js', 'polyfills/require.js'] - }, - { id: 'polyfills/console.js', - isPolyfill: true, - path: 'polyfills/console.js', - dependencies: [ - 'polyfills/prelude.js', - 'polyfills/require.js', - 'polyfills/polyfills.js' - ], - }, - { id: 'polyfills/error-guard.js', - isPolyfill: true, - path: 'polyfills/error-guard.js', - dependencies: [ - 'polyfills/prelude.js', - 'polyfills/require.js', - 'polyfills/polyfills.js', - 'polyfills/console.js' - ], - }, - module - ]); - }); - }); - - pit('should get dependencies with polyfills', function() { - var module = {id: 'index', path: '/root/index.js', dependencies: ['a']}; - var deps = [module]; - - var depResolver = new HasteDependencyResolver({ - projectRoot: '/root', - }); - - // Is there a better way? How can I mock the prototype instead? - var depGraph = depResolver._depGraph; - depGraph.getOrderedDependencies.mockImpl(function() { - return deps; - }); - depGraph.load.mockImpl(function() { - return q(); - }); - - return depResolver.getDependencies('/root/index.js', { dev: true }) - .then(function(result) { - expect(result.mainModuleId).toEqual('index'); - expect(result.dependencies).toEqual([ - { path: 'polyfills/prelude_dev.js', - id: 'polyfills/prelude_dev.js', - isPolyfill: true, - dependencies: [] - }, - { path: 'polyfills/require.js', - id: 'polyfills/require.js', - isPolyfill: true, - dependencies: ['polyfills/prelude_dev.js'] - }, - { path: 'polyfills/polyfills.js', - id: 'polyfills/polyfills.js', - isPolyfill: true, - dependencies: ['polyfills/prelude_dev.js', 'polyfills/require.js'] - }, - { id: 'polyfills/console.js', - isPolyfill: true, - path: 'polyfills/console.js', - dependencies: [ - 'polyfills/prelude_dev.js', - 'polyfills/require.js', - 'polyfills/polyfills.js' - ], - }, - { id: 'polyfills/error-guard.js', - isPolyfill: true, - path: 'polyfills/error-guard.js', - dependencies: [ - 'polyfills/prelude_dev.js', - 'polyfills/require.js', - 'polyfills/polyfills.js', - 'polyfills/console.js' - ], - }, - module - ]); - }); - }); - - pit('should pass in more polyfills', function() { - var module = {id: 'index', path: '/root/index.js', dependencies: ['a']}; - var deps = [module]; - - var depResolver = new HasteDependencyResolver({ - projectRoot: '/root', - polyfillModuleNames: ['some module'], - }); - - // Is there a better way? How can I mock the prototype instead? - var depGraph = depResolver._depGraph; - depGraph.getOrderedDependencies.mockImpl(function() { - return deps; - }); - depGraph.load.mockImpl(function() { - return q(); - }); - - return depResolver.getDependencies('/root/index.js', { dev: false }) - .then(function(result) { - expect(result.mainModuleId).toEqual('index'); - expect(result.dependencies).toEqual([ - { path: 'polyfills/prelude.js', - id: 'polyfills/prelude.js', - isPolyfill: true, - dependencies: [] - }, - { path: 'polyfills/require.js', - id: 'polyfills/require.js', - isPolyfill: true, - dependencies: ['polyfills/prelude.js'] - }, - { path: 'polyfills/polyfills.js', - id: 'polyfills/polyfills.js', - isPolyfill: true, - dependencies: ['polyfills/prelude.js', 'polyfills/require.js'] - }, - { id: 'polyfills/console.js', - isPolyfill: true, - path: 'polyfills/console.js', - dependencies: [ - 'polyfills/prelude.js', - 'polyfills/require.js', - 'polyfills/polyfills.js' - ], - }, - { id: 'polyfills/error-guard.js', - isPolyfill: true, - path: 'polyfills/error-guard.js', - dependencies: [ - 'polyfills/prelude.js', - 'polyfills/require.js', - 'polyfills/polyfills.js', - 'polyfills/console.js' - ], - }, - { path: 'some module', - id: 'some module', - isPolyfill: true, - dependencies: [ - 'polyfills/prelude.js', - 'polyfills/require.js', - 'polyfills/polyfills.js', - 'polyfills/console.js', - 'polyfills/error-guard.js', - ] - }, - module - ]); - }); - }); - }); - - describe('wrapModule', function() { - it('should ', function() { - var depResolver = new HasteDependencyResolver({ - projectRoot: '/root', - }); - - var depGraph = depResolver._depGraph; - var dependencies = ['x', 'y', 'z']; - var code = [ - 'require("x")', - 'require("y")', - 'require("z")', - ].join('\n'); - - depGraph.resolveDependency.mockImpl(function(fromModule, toModuleName) { - if (toModuleName === 'x') { - return { - id: 'changed' - }; - } else if (toModuleName === 'y') { - return { id: 'y' }; - } - return null; - }); - - var processedCode = depResolver.wrapModule({ - id: 'test module', - path: '/root/test.js', - dependencies: dependencies - }, code); - - expect(processedCode).toEqual([ - '__d(\'test module\',["changed","y"],function(global,' + - ' require, requireDynamic, requireLazy, module, exports) {' + - ' require(\'changed\')', - 'require(\'y\')', - 'require("z")});', - ].join('\n')); - }); - }); -}); diff --git a/packager/react-packager/src/DependencyResolver/haste/index.js b/packager/react-packager/src/DependencyResolver/haste/index.js deleted file mode 100644 index 6aada00b98e..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/index.js +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; - -var path = require('path'); -var FileWatcher = require('../../FileWatcher'); -var DependencyGraph = require('./DependencyGraph'); -var ModuleDescriptor = require('../ModuleDescriptor'); -var declareOpts = require('../../lib/declareOpts'); - -var DEFINE_MODULE_CODE = [ - '__d(', - '\'_moduleName_\',', - '_deps_,', - 'function(global, require, requireDynamic, requireLazy, module, exports) {', - ' _code_', - '}', - ');', -].join(''); - -var DEFINE_MODULE_REPLACE_RE = /_moduleName_|_code_|_deps_/g; - -var REL_REQUIRE_STMT = /require\(['"]([\.\/0-9A-Z_$\-]*)['"]\)/gi; - -var validateOpts = declareOpts({ - projectRoots: { - type: 'array', - required: true, - }, - blacklistRE: { - type: 'object', // typeof regex is object - }, - polyfillModuleNames: { - type: 'array', - default: [], - }, - nonPersistent: { - type: 'boolean', - default: false, - }, - moduleFormat: { - type: 'string', - default: 'haste', - }, -}); - -function HasteDependencyResolver(options) { - var opts = validateOpts(options); - - this._fileWatcher = opts.nonPersistent - ? FileWatcher.createDummyWatcher() - : new FileWatcher(opts.projectRoots); - - this._depGraph = new DependencyGraph({ - roots: opts.projectRoots, - ignoreFilePath: function(filepath) { - return filepath.indexOf('__tests__') !== -1 || - (opts.blacklistRE && opts.blacklistRE.test(filepath)); - }, - fileWatcher: this._fileWatcher - }); - - - this._polyfillModuleNames = opts.polyfillModuleNames || []; -} - -var getDependenciesValidateOpts = declareOpts({ - dev: { - type: 'boolean', - default: true, - }, -}); - -HasteDependencyResolver.prototype.getDependencies = function(main, options) { - var opts = getDependenciesValidateOpts(options); - - var depGraph = this._depGraph; - var self = this; - - return depGraph.load() - .then(function() { - var dependencies = depGraph.getOrderedDependencies(main); - var mainModuleId = dependencies[0].id; - - self._prependPolyfillDependencies(dependencies, opts.dev); - - return { - mainModuleId: mainModuleId, - dependencies: dependencies - }; - }); -}; - -HasteDependencyResolver.prototype._prependPolyfillDependencies = function( - dependencies, - isDev -) { - var polyfillModuleNames = [ - isDev - ? path.join(__dirname, 'polyfills/prelude_dev.js') - : path.join(__dirname, 'polyfills/prelude.js'), - path.join(__dirname, 'polyfills/require.js'), - path.join(__dirname, 'polyfills/polyfills.js'), - path.join(__dirname, 'polyfills/console.js'), - path.join(__dirname, 'polyfills/error-guard.js'), - ].concat(this._polyfillModuleNames); - - var polyfillModules = polyfillModuleNames.map( - function(polyfillModuleName, idx) { - return new ModuleDescriptor({ - path: polyfillModuleName, - id: polyfillModuleName, - dependencies: polyfillModuleNames.slice(0, idx), - isPolyfill: true - }); - } - ); - dependencies.unshift.apply(dependencies, polyfillModules); -}; - -HasteDependencyResolver.prototype.wrapModule = function(module, code) { - if (module.isPolyfill) { - return code; - } - - var resolvedDeps = Object.create(null); - var resolvedDepsArr = []; - - for (var i = 0; i < module.dependencies.length; i++) { - var depName = module.dependencies[i]; - var dep = this._depGraph.resolveDependency(module, depName); - if (dep) { - resolvedDeps[depName] = dep.id; - resolvedDepsArr.push(dep.id); - } - } - - var relativizedCode = - code.replace(REL_REQUIRE_STMT, function(codeMatch, depName) { - var depId = resolvedDeps[depName]; - if (depId != null) { - return 'require(\'' + depId + '\')'; - } else { - return codeMatch; - } - }); - - return DEFINE_MODULE_CODE.replace(DEFINE_MODULE_REPLACE_RE, function(key) { - return { - '_moduleName_': module.id, - '_code_': relativizedCode, - '_deps_': JSON.stringify(resolvedDepsArr), - }[key]; - }); -}; - -HasteDependencyResolver.prototype.end = function() { - return this._fileWatcher.end(); -}; - -HasteDependencyResolver.prototype.getDebugInfo = function() { - return this._depGraph.getDebugInfo(); -}; - -module.exports = HasteDependencyResolver; diff --git a/packager/react-packager/src/DependencyResolver/haste/polyfills/console.js b/packager/react-packager/src/DependencyResolver/haste/polyfills/console.js deleted file mode 100644 index bb83822d578..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/polyfills/console.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This pipes all of our console logging functions to native logging so that - * JavaScript errors in required modules show up in Xcode via NSLog. - * - * @provides console - * @polyfill - */ - -/*eslint global-strict:0*/ -(function(global) { - 'use strict'; - - var OBJECT_COLUMN_NAME = '(index)'; - - function setupConsole(global) { - - if (!global.nativeLoggingHook) { - return; - } - - function doNativeLog() { - var str = Array.prototype.map.call(arguments, function(arg) { - if (arg == null) { - return arg === null ? 'null' : 'undefined'; - } else if (typeof arg === 'string') { - return '"' + arg + '"'; - } else { - // Perform a try catch, just in case the object has a circular - // reference or stringify throws for some other reason. - try { - return JSON.stringify(arg); - } catch (e) { - if (typeof arg.toString === 'function') { - try { - return arg.toString(); - } catch (E) { - return 'unknown'; - } - } - } - } - }).join(', '); - global.nativeLoggingHook(str); - } - - var repeat = function(element, n) { - return Array.apply(null, Array(n)).map(function() { return element; }); - }; - - function consoleTablePolyfill(rows) { - // convert object -> array - if (!Array.isArray(rows)) { - var data = rows; - rows = []; - for (var key in data) { - if (data.hasOwnProperty(key)) { - var row = data[key]; - row[OBJECT_COLUMN_NAME] = key; - rows.push(row); - } - } - } - if (rows.length === 0) { - global.nativeLoggingHook(''); - return; - } - - var columns = Object.keys(rows[0]).sort(); - var stringRows = []; - var columnWidths = []; - - // Convert each cell to a string. Also - // figure out max cell width for each column - columns.forEach(function(k, i) { - columnWidths[i] = k.length; - for (var j = 0; j < rows.length; j++) { - var cellStr = rows[j][k].toString(); - stringRows[j] = stringRows[j] || []; - stringRows[j][i] = cellStr; - columnWidths[i] = Math.max(columnWidths[i], cellStr.length); - } - }); - - // Join all elements in the row into a single string with | separators - // (appends extra spaces to each cell to make separators | alligned) - var joinRow = function(row, space) { - var cells = row.map(function(cell, i) { - var extraSpaces = repeat(' ', columnWidths[i] - cell.length).join(''); - return cell + extraSpaces; - }); - space = space || ' '; - return cells.join(space + '|' + space); - }; - - var separators = columnWidths.map(function(columnWidth) { - return repeat('-', columnWidth).join(''); - }); - var separatorRow = joinRow(separators, '-'); - var header = joinRow(columns); - var table = [header, separatorRow]; - - for (var i = 0; i < rows.length; i++) { - table.push(joinRow(stringRows[i])); - } - - // Notice extra empty line at the beginning. - // Native logging hook adds "RCTLog >" at the front of every - // logged string, which would shift the header and screw up - // the table - global.nativeLoggingHook('\n' + table.join('\n')); - } - - global.console = { - error: doNativeLog, - info: doNativeLog, - log: doNativeLog, - warn: doNativeLog, - table: consoleTablePolyfill - }; - - } - - if (typeof module !== 'undefined') { - module.exports = setupConsole; - } else { - setupConsole(global); - } - -})(this); diff --git a/packager/react-packager/src/DependencyResolver/haste/polyfills/error-guard.js b/packager/react-packager/src/DependencyResolver/haste/polyfills/error-guard.js deleted file mode 100644 index 745d650ea8a..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/polyfills/error-guard.js +++ /dev/null @@ -1,82 +0,0 @@ - -/** - * The particular require runtime that we are using looks for a global - * `ErrorUtils` object and if it exists, then it requires modules with the - * error handler specified via ErrorUtils.setGlobalHandler by calling the - * require function with applyWithGuard. Since the require module is loaded - * before any of the modules, this ErrorUtils must be defined (and the handler - * set) globally before requiring anything. - */ -/* eslint global-strict:0 */ -(function(global) { - var ErrorUtils = { - _inGuard: 0, - _globalHandler: null, - setGlobalHandler: function(fun) { - ErrorUtils._globalHandler = fun; - }, - reportError: function(error) { - Error._globalHandler && ErrorUtils._globalHandler(error); - }, - applyWithGuard: function(fun, context, args) { - try { - ErrorUtils._inGuard++; - return fun.apply(context, args); - } catch (e) { - ErrorUtils._globalHandler && ErrorUtils._globalHandler(e); - } finally { - ErrorUtils._inGuard--; - } - }, - applyWithGuardIfNeeded: function(fun, context, args) { - if (ErrorUtils.inGuard()) { - return fun.apply(context, args); - } else { - ErrorUtils.applyWithGuard(fun, context, args); - } - }, - inGuard: function() { - return ErrorUtils._inGuard; - }, - guard: function(fun, name, context) { - if (typeof fun !== 'function') { - console.warn('A function must be passed to ErrorUtils.guard, got ', fun); - return null; - } - name = name || fun.name || ''; - function guarded() { - return ( - ErrorUtils.applyWithGuard( - fun, - context || this, - arguments, - null, - name - ) - ); - } - - return guarded; - } - }; - global.ErrorUtils = ErrorUtils; - - /** - * This is the error handler that is called when we encounter an exception - * when loading a module. - */ - function setupErrorGuard() { - var onError = function(e) { - global.console.error( - 'Error: ' + - '\n stack: ' + e.stack + - '\n line: ' + e.line + - '\n message: ' + e.message, - e - ); - }; - global.ErrorUtils.setGlobalHandler(onError); - } - - setupErrorGuard(); -})(this); diff --git a/packager/react-packager/src/DependencyResolver/haste/polyfills/polyfills.js b/packager/react-packager/src/DependencyResolver/haste/polyfills/polyfills.js deleted file mode 100644 index 75f742790e1..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/polyfills/polyfills.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This pipes all of our console logging functions to native logging so that - * JavaScript errors in required modules show up in Xcode via NSLog. - * - * @provides Object.es6 - * @polyfill - */ - -// WARNING: This is an optimized version that fails on hasOwnProperty checks -// and non objects. It's not spec-compliant. It's a perf optimization. -/* eslint global-strict:0 */ -Object.assign = function(target, sources) { - if (__DEV__) { - if (target == null) { - throw new TypeError('Object.assign target cannot be null or undefined'); - } - if (typeof target !== 'object' && typeof target !== 'function') { - throw new TypeError( - 'In this environment the target of assign MUST be an object.' + - 'This error is a performance optimization and not spec compliant.' - ); - } - } - - for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) { - var nextSource = arguments[nextIndex]; - if (nextSource == null) { - continue; - } - - if (__DEV__) { - if (typeof nextSource !== 'object' && - typeof nextSource !== 'function') { - throw new TypeError( - 'In this environment the target of assign MUST be an object.' + - 'This error is a performance optimization and not spec compliant.' - ); - } - } - - // We don't currently support accessors nor proxies. Therefore this - // copy cannot throw. If we ever supported this then we must handle - // exceptions and side-effects. - - for (var key in nextSource) { - if (__DEV__) { - var hasOwnProperty = Object.prototype.hasOwnProperty; - if (!hasOwnProperty.call(nextSource, key)) { - throw new TypeError( - 'One of the sources to assign has an enumerable key on the ' + - 'prototype chain. This is an edge case that we do not support. ' + - 'This error is a performance optimization and not spec compliant.' - ); - } - } - target[key] = nextSource[key]; - } - } - - return target; -}; diff --git a/packager/react-packager/src/DependencyResolver/haste/polyfills/prelude.js b/packager/react-packager/src/DependencyResolver/haste/polyfills/prelude.js deleted file mode 100644 index 9f4db44e2bc..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/polyfills/prelude.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint global-strict:0 */ -__DEV__ = false; diff --git a/packager/react-packager/src/DependencyResolver/haste/polyfills/prelude_dev.js b/packager/react-packager/src/DependencyResolver/haste/polyfills/prelude_dev.js deleted file mode 100644 index 26b26a07632..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/polyfills/prelude_dev.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint global-strict:0 */ -__DEV__ = true; diff --git a/packager/react-packager/src/DependencyResolver/haste/polyfills/require.js b/packager/react-packager/src/DependencyResolver/haste/polyfills/require.js deleted file mode 100644 index e7fdde25023..00000000000 --- a/packager/react-packager/src/DependencyResolver/haste/polyfills/require.js +++ /dev/null @@ -1,627 +0,0 @@ -/* eslint global-strict:0,eqeqeq:0,no-bitwise:0,no-undef:0 */ -(function(global) { - - // avoid redefining require() - if (global.require) { - return; - } - - var __DEV__ = global.__DEV__; - - var toString = Object.prototype.toString; - - /** - * module index: { - * mod1: { - * exports: { ... }, - * id: 'mod1', - * dependencies: ['mod1', 'mod2'], - * factory: function() { ... }, - * waitingMap: { mod1: 1, mod3: 1, mod4: 1 }, - * waiting: 2 - * } - * } - */ - var modulesMap = {}, - /** - * inverse index: { - * mod1: [modules, waiting for mod1], - * mod2: [modules, waiting for mod2] - * } - */ - dependencyMap = {}, - /** - * modules whose reference counts are set out of order - */ - predefinedRefCounts = {}, - - _counter = 0, - - REQUIRE_WHEN_READY = 1, - USED_AS_TRANSPORT = 2, - - hop = Object.prototype.hasOwnProperty; - - function _debugUnresolvedDependencies(names) { - var unresolved = Array.prototype.slice.call(names); - var visited = {}; - var ii, name, module, dependency; - - while (unresolved.length) { - name = unresolved.shift(); - if (visited[name]) { - continue; - } - visited[name] = true; - - module = modulesMap[name]; - if (!module || !module.waiting) { - continue; - } - - for (ii = 0; ii < module.dependencies.length; ii++) { - dependency = module.dependencies[ii]; - if (!modulesMap[dependency] || modulesMap[dependency].waiting) { - unresolved.push(dependency); - } - } - } - - for (name in visited) if (hop.call(visited, name)) { - unresolved.push(name); - } - - var messages = []; - for (ii = 0; ii < unresolved.length; ii++) { - name = unresolved[ii]; - var message = name; - module = modulesMap[name]; - if (!module) { - message += ' is not defined'; - } else if (!module.waiting) { - message += ' is ready'; - } else { - var unresolvedDependencies = []; - for (var jj = 0; jj < module.dependencies.length; jj++) { - dependency = module.dependencies[jj]; - if (!modulesMap[dependency] || modulesMap[dependency].waiting) { - unresolvedDependencies.push(dependency); - } - } - message += ' is waiting for ' + unresolvedDependencies.join(', '); - } - messages.push(message); - } - return messages.join('\n'); - } - - /** - * This is mainly for logging in ModuleErrorLogger. - */ - function ModuleError(msg) { - this.name = 'ModuleError'; - this.message = msg; - this.stack = Error(msg).stack; - this.framesToPop = 2; - } - ModuleError.prototype = Object.create(Error.prototype); - ModuleError.prototype.constructor = ModuleError; - - var _performance = - global.performance || - global.msPerformance || - global.webkitPerformance || {}; - - if (!_performance.now) { - _performance = global.Date; - } - - var _now = _performance ? - _performance.now.bind(_performance) : function(){return 0;}; - - var _factoryStackCount = 0; - var _factoryTime = 0; - var _totalFactories = 0; - - /** - * The require function conforming to CommonJS spec: - * http://wiki.commonjs.org/wiki/Modules/1.1.1 - * - * To define a CommonJS-compliant module add the providesModule - * Haste header to your file instead of @provides. Your file is going - * to be executed in a separate context. Every variable/function you - * define will be local (private) to that module. To export local members - * use "exports" variable or return the exported value at the end of your - * file. Your code will have access to the "module" object. - * The "module" object will have an "id" property that is the id of your - * current module. "module" object will also have "exports" property that - * is the same as "exports" variable passed into your module context. - * You can require other modules using their ids. - * - * Haste will automatically pick dependencies from require() calls. So - * you don't have to manually specify @requires in your header. - * - * You cannot require() modules from non-CommonJS files. Write a legacy stub - * (@providesLegacy) and use @requires instead. - * - * @example - * - * / ** - * * @providesModule math - * * / - * exports.add = function() { - * var sum = 0, i = 0, args = arguments, l = args.length; - * while (i < l) { - * sum += args[i++]; - * } - * return sum; - * }; - * - * / ** - * * @providesModule increment - * * / - * var add = require('math').add; - * return function(val) { - * return add(val, 1); - * }; - * - * / ** - * * @providesModule program - * * / - * var inc = require('increment'); - * var a = 1; - * inc(a); // 2 - * - * module.id == "program"; - * - * - * @param {String} id - * @throws when module is not loaded or not ready to be required - */ - function require(id) { - var module = modulesMap[id], dep, i, msg; - if (module && module.exports) { - // If ref count is 1, this was the last call, so undefine the module. - // The ref count can be null or undefined, but those are never === 1. - if (module.refcount-- === 1) { - delete modulesMap[id]; - } - return module.exports; - } - - if (global.ErrorUtils && !global.ErrorUtils.inGuard()) { - return ErrorUtils.applyWithGuard(require, this, arguments); - } - - if (!module) { - msg = 'Requiring unknown module "' + id + '"'; - if (__DEV__) { - msg += '. It may not be loaded yet. Did you forget to run arc build?'; - } - throw new ModuleError(msg); - } - - if (module.hasError) { - throw new ModuleError( - 'Requiring module "' + id + '" which threw an exception' - ); - } - - if (module.waiting) { - throw new ModuleError( - 'Requiring module "' + id + '" with unresolved dependencies: ' + - _debugUnresolvedDependencies([id]) - ); - } - - var exports = module.exports = {}; - var factory = module.factory; - if (toString.call(factory) === '[object Function]') { - var args = [], - dependencies = module.dependencies, - length = dependencies.length, - ret; - if (module.special & USED_AS_TRANSPORT) { - length = Math.min(length, factory.length); - } - try { - for (i = 0; args.length < length; i++) { - dep = dependencies[i]; - if (!module.inlineRequires[dep]) { - args.push(dep === 'module' ? module : - (dep === 'exports' ? exports : - require.call(null, dep))); - } - } - - ++_totalFactories; - if (_factoryStackCount++ === 0) { - _factoryTime -= _now(); - } - try { - ret = factory.apply(module.context || global, args); - } catch (e) { - if (modulesMap.ex && modulesMap.erx) { - // when ErrorUtils is ready, ex and erx are ready. otherwise, we - // don't append module id to the error message but still throw it - var ex = require.call(null, 'ex'); - var erx = require.call(null, 'erx'); - var messageWithParams = erx(e.message); - if (messageWithParams[0].indexOf(' from module "%s"') < 0) { - messageWithParams[0] += ' from module "%s"'; - messageWithParams[messageWithParams.length] = id; - } - e.message = ex.apply(null, messageWithParams); - } - throw e; - } finally { - if (--_factoryStackCount === 0) { - _factoryTime += _now(); - } - } - } catch (e) { - module.hasError = true; - module.exports = null; - throw e; - } - if (ret) { - if (__DEV__) { - if (typeof ret != 'object' && typeof ret != 'function') { - throw new ModuleError( - 'Factory for module "' + id + '" returned ' + - 'an invalid value "' + ret + '". ' + - 'Returned value should be either a function or an object.' - ); - } - } - module.exports = ret; - } - } else { - module.exports = factory; - } - - // If ref count is 1, this was the last call, so undefine the module. - // The ref count can be null or undefined, but those are never === 1. - if (module.refcount-- === 1) { - delete modulesMap[id]; - } - return module.exports; - } - - require.__getFactoryTime = function() { - return (_factoryStackCount ? _now() : 0) + _factoryTime; - }; - - require.__getTotalFactories = function() { - return _totalFactories; - }; - - /** - * The define function conforming to CommonJS proposal: - * http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition - * - * define() allows you to explicitly state dependencies of your module - * in javascript. It's most useful in non-CommonJS files. - * - * define() is used internally by haste as a transport for CommonJS - * modules. So there's no need to use define() if you use providesModule - * - * @example - * / ** - * * @provides alpha - * * / - * - * // Sets up the module with ID of "alpha", that uses require, - * // exports and the module with ID of "beta": - * define("alpha", ["require", "exports", "beta"], - * function (require, exports, beta) { - * exports.verb = function() { - * return beta.verb(); - * //Or: - * return require("beta").verb(); - * } - * }); - * - * / ** - * * @provides alpha - * * / - * // An anonymous module could be defined (module id derived from filename) - * // that returns an object literal: - * - * define(["alpha"], function (alpha) { - * return { - * verb: function(){ - * return alpha.verb() + 2; - * } - * }; - * }); - * - * / ** - * * @provides alpha - * * / - * // A dependency-free module can define a direct object literal: - * - * define({ - * add: function(x, y){ - * return x + y; - * } - * }); - * - * @param {String} id optional - * @param {Array} dependencies optional - * @param {Object|Function} factory - */ - function define(id, dependencies, factory, - _special, _context, _refCount, _inlineRequires) { - if (dependencies === undefined) { - dependencies = []; - factory = id; - id = _uid(); - } else if (factory === undefined) { - factory = dependencies; - if (toString.call(id) === '[object Array]') { - dependencies = id; - id = _uid(); - } else { - dependencies = []; - } - } - - // Non-standard: we allow modules to be undefined. This is designed for - // temporary modules. - var canceler = { cancel: _undefine.bind(this, id) }; - - var record = modulesMap[id]; - - // Nonstandard hack: we call define with null deps and factory, but a - // non-null reference count (e.g. define('name', null, null, 0, null, 4)) - // when this module is defined elsewhere and we just need to update the - // reference count. We use this hack to avoid having to expose another - // global function to increment ref counts. - if (record) { - if (_refCount) { - record.refcount += _refCount; - } - // Calling define() on a pre-existing module does not redefine it - return canceler; - } else if (!dependencies && !factory && _refCount) { - // If this module hasn't been defined yet, store the ref count. We'll use - // it when the module is defined later. - predefinedRefCounts[id] = (predefinedRefCounts[id] || 0) + _refCount; - return canceler; - } else { - // Defining a new module - record = { id: id }; - record.refcount = (predefinedRefCounts[id] || 0) + (_refCount || 0); - delete predefinedRefCounts[id]; - } - - if (__DEV__) { - if ( - !factory || - (typeof factory != 'object' && typeof factory != 'function' && - typeof factory != 'string')) { - throw new ModuleError( - 'Invalid factory "' + factory + '" for module "' + id + '". ' + - 'Factory should be either a function or an object.' - ); - } - - if (toString.call(dependencies) !== '[object Array]') { - throw new ModuleError( - 'Invalid dependencies for module "' + id + '". ' + - 'Dependencies must be passed as an array.' - ); - } - } - - record.factory = factory; - record.dependencies = dependencies; - record.context = _context; - record.special = _special; - record.inlineRequires = _inlineRequires || {}; - record.waitingMap = {}; - record.waiting = 0; - record.hasError = false; - modulesMap[id] = record; - _initDependencies(id); - - return canceler; - } - - function _undefine(id) { - if (!modulesMap[id]) { - return; - } - - var module = modulesMap[id]; - delete modulesMap[id]; - - for (var dep in module.waitingMap) { - if (module.waitingMap[dep]) { - delete dependencyMap[dep][id]; - } - } - - for (var ii = 0; ii < module.dependencies.length; ii++) { - dep = module.dependencies[ii]; - if (modulesMap[dep]) { - if (modulesMap[dep].refcount-- === 1) { - _undefine(dep); - } - } else if (predefinedRefCounts[dep]) { - predefinedRefCounts[dep]--; - } - // Subtle: we won't account for this one fewer reference if we don't have - // the dependency's definition or reference count yet. - } - } - - /** - * Special version of define that executes the factory as soon as all - * dependencies are met. - * - * define() does just that, defines a module. Module's factory will not be - * called until required by other module. This makes sense for most of our - * library modules: we do not want to execute the factory unless it's being - * used by someone. - * - * On the other hand there are modules, that you can call "entrance points". - * You want to run the "factory" method for them as soon as all dependencies - * are met. - * - * @example - * - * define('BaseClass', [], function() { return ... }); - * // ^^ factory for BaseClass was just stored in modulesMap - * - * define('SubClass', ['BaseClass'], function() { ... }); - * // SubClass module is marked as ready (waiting == 0), factory is just - * // stored - * - * define('OtherClass, ['BaseClass'], function() { ... }); - * // OtherClass module is marked as ready (waiting == 0), factory is just - * // stored - * - * requireLazy(['SubClass', 'ChatConfig'], - * function() { ... }); - * // ChatRunner is waiting for ChatConfig to come - * - * define('ChatConfig', [], { foo: 'bar' }); - * // at this point ChatRunner is marked as ready, and its factory - * // executed + all dependent factories are executed too: BaseClass, - * // SubClass, ChatConfig notice that OtherClass's factory won't be - * // executed unless explicitly required by someone - * - * @param {Array} dependencies - * @param {Object|Function} factory - */ - function requireLazy(dependencies, factory, context) { - return define( - dependencies, - factory, - undefined, - REQUIRE_WHEN_READY, - context, - 1 - ); - } - - function _uid() { - return '__mod__' + _counter++; - } - - function _addDependency(module, dep) { - // do not add duplicate dependencies and circ deps - if (!module.waitingMap[dep] && module.id !== dep) { - module.waiting++; - module.waitingMap[dep] = 1; - dependencyMap[dep] || (dependencyMap[dep] = {}); - dependencyMap[dep][module.id] = 1; - } - } - - function _initDependencies(id) { - var modulesToRequire = []; - var module = modulesMap[id]; - var dep, i, subdep; - - // initialize id's waitingMap - for (i = 0; i < module.dependencies.length; i++) { - dep = module.dependencies[i]; - if (!modulesMap[dep]) { - _addDependency(module, dep); - } else if (modulesMap[dep].waiting) { - for (subdep in modulesMap[dep].waitingMap) { - if (modulesMap[dep].waitingMap[subdep]) { - _addDependency(module, subdep); - } - } - } - } - if (module.waiting === 0 && module.special & REQUIRE_WHEN_READY) { - modulesToRequire.push(id); - } - - // update modules depending on id - if (dependencyMap[id]) { - var deps = dependencyMap[id]; - var submodule; - dependencyMap[id] = undefined; - for (dep in deps) { - submodule = modulesMap[dep]; - - // add all deps of id - for (subdep in module.waitingMap) { - if (module.waitingMap[subdep]) { - _addDependency(submodule, subdep); - } - } - // remove id itself - if (submodule.waitingMap[id]) { - submodule.waitingMap[id] = undefined; - submodule.waiting--; - } - if (submodule.waiting === 0 && - submodule.special & REQUIRE_WHEN_READY) { - modulesToRequire.push(dep); - } - } - } - - // run everything that's ready - for (i = 0; i < modulesToRequire.length; i++) { - require.call(null, modulesToRequire[i]); - } - } - - function _register(id, exports) { - var module = modulesMap[id] = { id: id }; - module.exports = exports; - module.refcount = 0; - } - - // pseudo name used in common-require - // see require() function for more info - _register('module', 0); - _register('exports', 0); - - _register('define', define); - _register('global', global); - _register('require', require); - _register('requireDynamic', require); - _register('requireLazy', requireLazy); - - define.amd = {}; - - global.define = define; - global.require = require; - global.requireDynamic = require; - global.requireLazy = requireLazy; - - require.__debug = { - modules: modulesMap, - deps: dependencyMap, - printDependencyInfo: function() { - if (!global.console) { - return; - } - var names = Object.keys(require.__debug.deps); - global.console.log(_debugUnresolvedDependencies(names)); - } - }; - - /** - * All @providesModule files are wrapped by this function by makehaste. It - * is a convenience function around define() that prepends a bunch of required - * modules (global, require, module, etc) so that we don't have to spit that - * out for every module which would be a lot of extra bytes. - */ - global.__d = function(id, deps, factory, _special, _inlineRequires) { - var defaultDeps = ['global', 'require', 'requireDynamic', 'requireLazy', - 'module', 'exports']; - define(id, defaultDeps.concat(deps), factory, _special || USED_AS_TRANSPORT, - null, null, _inlineRequires); - }; - -})(this); diff --git a/packager/react-packager/src/DependencyResolver/index.js b/packager/react-packager/src/DependencyResolver/index.js deleted file mode 100644 index f42ecb8a727..00000000000 --- a/packager/react-packager/src/DependencyResolver/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -var HasteDependencyResolver = require('./haste'); -var NodeDependencyResolver = require('./node'); - -module.exports = function createDependencyResolver(options) { - if (options.moduleFormat === 'haste') { - return new HasteDependencyResolver(options); - } else if (options.moduleFormat === 'node') { - return new NodeDependencyResolver(options); - } else { - throw new Error('unsupported'); - } -}; diff --git a/packager/react-packager/src/DependencyResolver/node/index.js b/packager/react-packager/src/DependencyResolver/node/index.js deleted file mode 100644 index da03cc7ead9..00000000000 --- a/packager/react-packager/src/DependencyResolver/node/index.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -var Promise = require('q').Promise; -var ModuleDescriptor = require('../ModuleDescriptor'); - -var mdeps = require('module-deps'); -var path = require('path'); - -exports.getRuntimeCode = function() {}; - -exports.wrapModule = function(id, source) { - return Promise.resolve( - 'define(' + JSON.stringify(id) + ',' + ' function(exports, module) {\n' - + source + '\n});' - ); -}; - -exports.getDependencies = function(root, fileEntryPath) { - return new Promise(function(resolve) { - fileEntryPath = path.join(process.cwd(), root, fileEntryPath); - - var md = mdeps(); - - md.end({file: fileEntryPath}); - - var deps = []; - - md.on('data', function(data) { - deps.push( - new ModuleDescriptor({ - id: data.id, - deps: data.deps, - path: data.file, - entry: data.entry - }) - ); - }); - - md.on('end', function() { - resolve(deps); - }); - }); -}; diff --git a/packager/react-packager/src/FileWatcher/__mocks__/sane.js b/packager/react-packager/src/FileWatcher/__mocks__/sane.js deleted file mode 100644 index 20dda2a2bf8..00000000000 --- a/packager/react-packager/src/FileWatcher/__mocks__/sane.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = { - WatchmanWatcher: jest.genMockFromModule('sane/src/watchman_watcher') -}; diff --git a/packager/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js b/packager/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js deleted file mode 100644 index fc8a7a41caa..00000000000 --- a/packager/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -jest - .dontMock('../') - .dontMock('q') - .setMock( - 'child_process', - { exec: function(cmd, cb) { cb(null, '/usr/bin/watchman'); } } - ); - -describe('FileWatcher', function() { - var FileWatcher; - var Watcher; - - beforeEach(function() { - FileWatcher = require('../'); - Watcher = require('sane').WatchmanWatcher; - Watcher.prototype.once.mockImplementation(function(type, callback) { - callback(); - }); - }); - - it('it should get the watcher instance when ready', function() { - var fileWatcher = new FileWatcher(['rootDir']); - return fileWatcher._loading.then(function(watchers) { - watchers.forEach(function(watcher) { - expect(watcher instanceof Watcher).toBe(true); - }); - }); - }); - - pit('it should end the watcher', function() { - var fileWatcher = new FileWatcher(['rootDir']); - Watcher.prototype.close.mockImplementation(function(callback) { - callback(); - }); - - return fileWatcher.end().then(function() { - expect(Watcher.prototype.close).toBeCalled(); - }); - }); - -}); diff --git a/packager/react-packager/src/FileWatcher/index.js b/packager/react-packager/src/FileWatcher/index.js deleted file mode 100644 index f2721d8cfb9..00000000000 --- a/packager/react-packager/src/FileWatcher/index.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -var EventEmitter = require('events').EventEmitter; -var sane = require('sane'); -var q = require('q'); -var util = require('util'); -var exec = require('child_process').exec; - -var Promise = q.Promise; - -var detectingWatcherClass = new Promise(function(resolve, reject) { - exec('which watchman', function(err, out) { - if (err || out.length === 0) { - resolve(sane.NodeWatcher); - } else { - resolve(sane.WatchmanWatcher); - } - }); -}); - -module.exports = FileWatcher; - -var MAX_WAIT_TIME = 3000; - -function FileWatcher(projectRoots) { - var self = this; - this._loading = q.all( - projectRoots.map(createWatcher) - ).then(function(watchers) { - watchers.forEach(function(watcher) { - watcher.on('all', function(type, filepath, root) { - self.emit('all', type, filepath, root); - }); - }); - return watchers; - }); - this._loading.done(); -} - -util.inherits(FileWatcher, EventEmitter); - -FileWatcher.prototype.end = function() { - return this._loading.then(function(watchers) { - watchers.forEach(function(watcher) { - delete watchersByRoot[watcher._root]; - return q.ninvoke(watcher, 'close'); - }); - }); -}; - -var watchersByRoot = Object.create(null); - -function createWatcher(root) { - if (watchersByRoot[root] != null) { - return Promise.resolve(watchersByRoot[root]); - } - - return detectingWatcherClass.then(function(Watcher) { - var watcher = new Watcher(root, {glob: '**/*.js'}); - - return new Promise(function(resolve, reject) { - var rejectTimeout = setTimeout(function() { - reject(new Error([ - 'Watcher took too long to load', - 'Try running `watchman` from your terminal', - 'https://facebook.github.io/watchman/docs/troubleshooting.html', - ].join('\n'))); - }, MAX_WAIT_TIME); - - watcher.once('ready', function() { - clearTimeout(rejectTimeout); - watchersByRoot[root] = watcher; - watcher._root = root; - resolve(watcher); - }); - }); - }); -} - -FileWatcher.createDummyWatcher = function() { - var ev = new EventEmitter(); - ev.end = function() { - return q(); - }; - return ev; -}; diff --git a/packager/react-packager/src/JSTransformer/Cache.js b/packager/react-packager/src/JSTransformer/Cache.js deleted file mode 100644 index b9c5b8c14de..00000000000 --- a/packager/react-packager/src/JSTransformer/Cache.js +++ /dev/null @@ -1,160 +0,0 @@ -'use strict'; - -var path = require('path'); -var version = require('../../../../package.json').version; -var tmpdir = require('os').tmpDir(); -var isAbsolutePath = require('absolute-path'); -var declareOpts = require('../lib/declareOpts'); -var fs = require('fs'); -var _ = require('underscore'); -var q = require('q'); - -var Promise = q.Promise; - -var validateOpts = declareOpts({ - resetCache: { - type: 'boolean', - default: false, - }, - cacheVersion: { - type: 'string', - default: '1.0', - }, - projectRoots: { - type: 'array', - required: true, - }, -}); -module.exports = Cache; - -function Cache(options) { - var opts = validateOpts(options); - - this._cacheFilePath = cacheFilePath(opts); - - var data; - if (!opts.resetCache) { - data = loadCacheSync(this._cacheFilePath); - } else { - data = Object.create(null); - } - this._data = data; - - this._has = Object.prototype.hasOwnProperty.bind(data); - this._persistEventually = _.debounce( - this._persistCache.bind(this), - 2000 - ); -} - -Cache.prototype.get = function(filepath, loaderCb) { - if (!isAbsolutePath(filepath)) { - throw new Error('Use absolute paths'); - } - - var recordP = this._has(filepath) - ? this._data[filepath] - : this._set(filepath, loaderCb(filepath)); - - return recordP.then(function(record) { - return record.data; - }); -}; - -Cache.prototype._set = function(filepath, loaderPromise) { - this._data[filepath] = loaderPromise.then(function(data) { - return [ - data, - q.nfbind(fs.stat)(filepath) - ]; - }).spread(function(data, stat) { - this._persistEventually(); - return { - data: data, - mtime: stat.mtime.getTime(), - }; - }.bind(this)); - - return this._data[filepath]; -}; - -Cache.prototype.invalidate = function(filepath){ - if (this._has(filepath)) { - delete this._data[filepath]; - } -}; - -Cache.prototype.end = function() { - return this._persistCache(); -}; - -Cache.prototype._persistCache = function() { - if (this._persisting != null) { - return this._persisting; - } - - var data = this._data; - var cacheFilepath = this._cacheFilePath; - - this._persisting = q.all(_.values(data)) - .then(function(values) { - var json = Object.create(null); - Object.keys(data).forEach(function(key, i) { - json[key] = values[i]; - }); - return q.nfbind(fs.writeFile)(cacheFilepath, JSON.stringify(json)); - }) - .then(function() { - this._persisting = null; - return true; - }.bind(this)); - - return this._persisting; -}; - -function loadCacheSync(cachePath) { - var ret = Object.create(null); - if (!fs.existsSync(cachePath)) { - return ret; - } - - var cacheOnDisk; - try { - cacheOnDisk = JSON.parse(fs.readFileSync(cachePath)); - } catch (e) { - if (e instanceof SyntaxError) { - console.warn('Unable to parse cache file. Will clear and continue.'); - fs.unlinkSync(cachePath); - return ret; - } - throw e; - } - - // Filter outdated cache and convert to promises. - Object.keys(cacheOnDisk).forEach(function(key) { - if (!fs.existsSync(key)) { - return; - } - var value = cacheOnDisk[key]; - var stat = fs.statSync(key); - if (stat.mtime.getTime() === value.mtime) { - ret[key] = Promise.resolve(value); - } - }); - - return ret; -} - -function cacheFilePath(options) { - var roots = options.projectRoots.join(',').split(path.sep).join('-'); - var cacheVersion = options.cacheVersion || '0'; - return path.join( - tmpdir, - [ - 'react-packager-cache', - version, - cacheVersion, - roots, - ].join('-') - ); -} diff --git a/packager/react-packager/src/JSTransformer/README.md b/packager/react-packager/src/JSTransformer/README.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packager/react-packager/src/JSTransformer/__mocks__/q.js b/packager/react-packager/src/JSTransformer/__mocks__/q.js deleted file mode 100644 index 3d4d21f15a5..00000000000 --- a/packager/react-packager/src/JSTransformer/__mocks__/q.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -// Bug with Jest because we're going to the node_modules that is a sibling -// of what jest thinks our root (the dir with the package.json) should be. - -module.exports = require.requireActual('q'); diff --git a/packager/react-packager/src/JSTransformer/__mocks__/underscore.js b/packager/react-packager/src/JSTransformer/__mocks__/underscore.js deleted file mode 100644 index a985ab2069a..00000000000 --- a/packager/react-packager/src/JSTransformer/__mocks__/underscore.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -// Bug with Jest because we're going to the node_modules that is a sibling -// of what jest thinks our root (the dir with the package.json) should be. -module.exports = require.requireActual('underscore'); diff --git a/packager/react-packager/src/JSTransformer/__mocks__/worker.js b/packager/react-packager/src/JSTransformer/__mocks__/worker.js deleted file mode 100644 index 04a24e8db48..00000000000 --- a/packager/react-packager/src/JSTransformer/__mocks__/worker.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = function (data, callback) { - callback(null, {}); -}; diff --git a/packager/react-packager/src/JSTransformer/__tests__/Cache-test.js b/packager/react-packager/src/JSTransformer/__tests__/Cache-test.js deleted file mode 100644 index 97a500973ad..00000000000 --- a/packager/react-packager/src/JSTransformer/__tests__/Cache-test.js +++ /dev/null @@ -1,200 +0,0 @@ -'use strict'; - -jest - .dontMock('underscore') - .dontMock('path') - .dontMock('absolute-path') - .dontMock('../Cache'); - -var q = require('q'); - -describe('JSTransformer Cache', function() { - var Cache; - - beforeEach(function() { - require('os').tmpDir.mockImpl(function() { - return 'tmpDir'; - }); - - Cache = require('../Cache'); - }); - - describe('getting/settig', function() { - it('calls loader callback for uncached file', function() { - var cache = new Cache({projectRoots: ['/rootDir']}); - var loaderCb = jest.genMockFn().mockImpl(function() { - return q(); - }); - cache.get('/rootDir/someFile', loaderCb); - expect(loaderCb).toBeCalledWith('/rootDir/someFile'); - }); - - pit('gets the value from the loader callback', function() { - require('fs').stat.mockImpl(function(file, callback) { - callback(null, { - mtime: { - getTime: function() {} - } - }); - }); - var cache = new Cache({projectRoots: ['/rootDir']}); - var loaderCb = jest.genMockFn().mockImpl(function() { - return q('lol'); - }); - return cache.get('/rootDir/someFile', loaderCb).then(function(value) { - expect(value).toBe('lol'); - }); - }); - - pit('caches the value after the first call', function() { - require('fs').stat.mockImpl(function(file, callback) { - callback(null, { - mtime: { - getTime: function() {} - } - }); - }); - var cache = new Cache({projectRoots: ['/rootDir']}); - var loaderCb = jest.genMockFn().mockImpl(function() { - return q('lol'); - }); - return cache.get('/rootDir/someFile', loaderCb).then(function() { - var shouldNotBeCalled = jest.genMockFn(); - return cache.get('/rootDir/someFile', shouldNotBeCalled) - .then(function(value) { - expect(shouldNotBeCalled).not.toBeCalled(); - expect(value).toBe('lol'); - }); - }); - }); - }); - - describe('loading cache from disk', function() { - var fileStats; - - beforeEach(function() { - fileStats = { - '/rootDir/someFile': { - mtime: { - getTime: function() { - return 22; - } - } - }, - '/rootDir/foo': { - mtime: { - getTime: function() { - return 11; - } - } - } - }; - - var fs = require('fs'); - - fs.existsSync.mockImpl(function() { - return true; - }); - - fs.statSync.mockImpl(function(filePath) { - return fileStats[filePath]; - }); - - fs.readFileSync.mockImpl(function() { - return JSON.stringify({ - '/rootDir/someFile': { - mtime: 22, - data: 'oh hai' - }, - '/rootDir/foo': { - mtime: 11, - data: 'lol wat' - } - }); - }); - }); - - pit('should load cache from disk', function() { - var cache = new Cache({projectRoots: ['/rootDir']}); - var loaderCb = jest.genMockFn(); - return cache.get('/rootDir/someFile', loaderCb).then(function(value) { - expect(loaderCb).not.toBeCalled(); - expect(value).toBe('oh hai'); - - return cache.get('/rootDir/foo', loaderCb).then(function(value) { - expect(loaderCb).not.toBeCalled(); - expect(value).toBe('lol wat'); - }); - }); - }); - - pit('should not load outdated cache', function() { - require('fs').stat.mockImpl(function(file, callback) { - callback(null, { - mtime: { - getTime: function() {} - } - }); - }); - - fileStats['/rootDir/foo'].mtime.getTime = function() { - return 123; - }; - - var cache = new Cache({projectRoots: ['/rootDir']}); - var loaderCb = jest.genMockFn().mockImpl(function() { - return q('new value'); - }); - - return cache.get('/rootDir/someFile', loaderCb).then(function(value) { - expect(loaderCb).not.toBeCalled(); - expect(value).toBe('oh hai'); - - return cache.get('/rootDir/foo', loaderCb).then(function(value) { - expect(loaderCb).toBeCalled(); - expect(value).toBe('new value'); - }); - }); - }); - }); - - describe('writing cache to disk', function() { - it('should write cache to disk', function() { - var index = 0; - var mtimes = [10, 20, 30]; - var debounceIndex = 0; - require('underscore').debounce = function(callback) { - return function () { - if (++debounceIndex === 3) { - callback(); - } - }; - }; - - var fs = require('fs'); - fs.stat.mockImpl(function(file, callback) { - callback(null, { - mtime: { - getTime: function() { - return mtimes[index++]; - } - } - }); - }); - - var cache = new Cache({projectRoots: ['/rootDir']}); - cache.get('/rootDir/bar', function() { - return q('bar value'); - }); - cache.get('/rootDir/foo', function() { - return q('foo value'); - }); - cache.get('/rootDir/baz', function() { - return q('baz value'); - }); - - jest.runAllTicks(); - expect(fs.writeFile).toBeCalled(); - }); - }); -}); diff --git a/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js b/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js deleted file mode 100644 index 36d81d8fa2d..00000000000 --- a/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js +++ /dev/null @@ -1,70 +0,0 @@ -'use strict'; - -jest - .dontMock('worker-farm') - .dontMock('os') - .dontMock('../index'); - -var OPTIONS = { - transformModulePath: '/foo/bar' -}; - -describe('Transformer', function() { - var Transformer; - var workers; - - beforeEach(function() { - workers = jest.genMockFn(); - jest.setMock('worker-farm', jest.genMockFn().mockImpl(function() { - return workers; - })); - require('../Cache').prototype.get.mockImpl(function(filePath, callback) { - return callback(); - }); - require('fs').readFile.mockImpl(function(file, callback) { - callback(null, 'content'); - }); - Transformer = require('../'); - }); - - pit('should loadFileAndTransform', function() { - workers.mockImpl(function(data, callback) { - callback(null, { code: 'transformed' }); - }); - require('fs').readFile.mockImpl(function(file, callback) { - callback(null, 'content'); - }); - - return new Transformer(OPTIONS).loadFileAndTransform('file') - .then(function(data) { - expect(data).toEqual({ - code: 'transformed', - sourcePath: 'file', - sourceCode: 'content' - }); - }); - }); - - pit('should add file info to parse errors', function() { - require('fs').readFile.mockImpl(function(file, callback) { - callback(null, 'var x;\nvar answer = 1 = x;'); - }); - - workers.mockImpl(function(data, callback) { - var esprimaError = new Error('Error: Line 2: Invalid left-hand side in assignment'); - esprimaError.description = 'Invalid left-hand side in assignment'; - esprimaError.lineNumber = 2; - esprimaError.column = 15; - callback(null, {error: esprimaError}); - }); - - return new Transformer(OPTIONS).loadFileAndTransform('foo-file.js') - .catch(function(error) { - expect(error.type).toEqual('TransformError'); - expect(error.snippet).toEqual([ - 'var answer = 1 = x;', - ' ^', - ].join('\n')); - }); - }); -}); diff --git a/packager/react-packager/src/JSTransformer/index.js b/packager/react-packager/src/JSTransformer/index.js deleted file mode 100644 index 35785e6ee96..00000000000 --- a/packager/react-packager/src/JSTransformer/index.js +++ /dev/null @@ -1,158 +0,0 @@ - -'use strict'; - -var fs = require('fs'); -var q = require('q'); -var Cache = require('./Cache'); -var _ = require('underscore'); -var workerFarm = require('worker-farm'); -var declareOpts = require('../lib/declareOpts'); -var util = require('util'); - -var readFile = q.nfbind(fs.readFile); - -module.exports = Transformer; -Transformer.TransformError = TransformError; - -var validateOpts = declareOpts({ - projectRoots: { - type: 'array', - required: true, - }, - blacklistRE: { - type: 'object', // typeof regex is object - }, - polyfillModuleNames: { - type: 'array', - default: [], - }, - cacheVersion: { - type: 'string', - default: '1.0', - }, - resetCache: { - type: 'boolean', - default: false, - }, - transformModulePath: { - type:'string', - required: false, - }, - nonPersistent: { - type: 'boolean', - default: false, - }, -}); - -function Transformer(options) { - var opts = validateOpts(options); - - this._cache = opts.nonPersistent - ? new DummyCache() - : new Cache({ - resetCache: options.resetCache, - cacheVersion: options.cacheVersion, - projectRoots: options.projectRoots, - }); - - if (options.transformModulePath == null) { - this._failedToStart = q.Promise.reject(new Error('No transfrom module')); - } else { - this._workers = workerFarm( - {autoStart: true}, - options.transformModulePath - ); - } -} - -Transformer.prototype.kill = function() { - this._workers && workerFarm.end(this._workers); - return this._cache.end(); -}; - -Transformer.prototype.invalidateFile = function(filePath) { - this._cache.invalidate(filePath); -}; - -Transformer.prototype.loadFileAndTransform = function(filePath) { - if (this._failedToStart) { - return this._failedToStart; - } - - var workers = this._workers; - return this._cache.get(filePath, function() { - return readFile(filePath) - .then(function(buffer) { - var sourceCode = buffer.toString(); - - return q.nfbind(workers)({ - sourceCode: sourceCode, - filename: filePath, - }).then( - function(res) { - if (res.error) { - throw formatError(res.error, filePath, sourceCode); - } - - return { - code: res.code, - sourcePath: filePath, - sourceCode: sourceCode - }; - } - ); - }); - }); -}; - -function TransformError() {} -util.inherits(TransformError, SyntaxError); - -function formatError(err, filename, source) { - if (err.lineNumber && err.column) { - return formatEsprimaError(err, filename, source); - } else { - return formatGenericError(err, filename, source); - } -} - -function formatGenericError(err, filename) { - var msg = 'TransformError: ' + filename + ': ' + err.message; - var error = new TransformError(); - var stack = err.stack.split('\n').slice(0, -1); - stack.push(msg); - error.stack = stack.join('\n'); - error.message = msg; - error.type = 'TransformError'; - return error; -} - -function formatEsprimaError(err, filename, source) { - var stack = err.stack.split('\n'); - stack.shift(); - - var msg = 'TransformError: ' + err.description + ' ' + filename + ':' + - err.lineNumber + ':' + err.column; - var sourceLine = source.split('\n')[err.lineNumber - 1]; - var snippet = sourceLine + '\n' + new Array(err.column - 1).join(' ') + '^'; - - stack.unshift(msg); - - var error = new TransformError(); - error.message = msg; - error.type = 'TransformError'; - error.stack = stack.join('\n'); - error.snippet = snippet; - error.filename = filename; - error.lineNumber = err.lineNumber; - error.column = err.column; - error.description = err.description; - return error; -} - -function DummyCache() {} -DummyCache.prototype.get = function(filePath, loaderCb) { - return loaderCb(); -}; -DummyCache.prototype.end = -DummyCache.prototype.invalidate = function(){}; diff --git a/packager/react-packager/src/JSTransformer/worker.js b/packager/react-packager/src/JSTransformer/worker.js deleted file mode 100644 index 26f789e4049..00000000000 --- a/packager/react-packager/src/JSTransformer/worker.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -var transformer = require('./transformer'); - -module.exports = function (data, callback) { - var result; - try { - result = transformer.transform( - data.transformSets, - data.sourceCode, - data.options - ); - } catch (e) { - return callback(null, { - error: { - lineNumber: e.lineNumber, - column: e.column, - message: e.message, - stack: e.stack, - description: e.description - } - }); - } - - callback(null, result); -}; diff --git a/packager/react-packager/src/Packager/Package.js b/packager/react-packager/src/Packager/Package.js deleted file mode 100644 index 5d9b201c75e..00000000000 --- a/packager/react-packager/src/Packager/Package.js +++ /dev/null @@ -1,205 +0,0 @@ -'use strict'; - -var _ = require('underscore'); -var base64VLQ = require('./base64-vlq'); -var UglifyJS = require('uglify-js'); - -module.exports = Package; - -function Package(sourceMapUrl) { - this._finalized = false; - this._modules = []; - this._sourceMapUrl = sourceMapUrl; -} - -Package.prototype.setMainModuleId = function(moduleId) { - this._mainModuleId = moduleId; -}; - -Package.prototype.addModule = function( - transformedCode, - sourceCode, - sourcePath -) { - this._modules.push({ - transformedCode: transformedCode, - sourceCode: sourceCode, - sourcePath: sourcePath - }); -}; - -Package.prototype.finalize = function(options) { - options = options || {}; - if (options.runMainModule) { - var runCode = ';require("' + this._mainModuleId + '");'; - this.addModule( - runCode, - runCode, - 'RunMainModule.js' - ); - } - - Object.freeze(this._modules); - Object.seal(this._modules); - this._finalized = true; -}; - -Package.prototype._assertFinalized = function() { - if (!this._finalized) { - throw new Error('Package need to be finalized before getting any source'); - } -}; - -Package.prototype._getSource = function() { - if (this._source == null) { - this._source = _.pluck(this._modules, 'transformedCode').join('\n'); - } - return this._source; -}; - -Package.prototype._getInlineSourceMap = function() { - if (this._inlineSourceMap == null) { - var sourceMap = this.getSourceMap({excludeSource: true}); - this._inlineSourceMap = '\nRAW_SOURCE_MAP = ' + - JSON.stringify(sourceMap) + ';'; - } - - return this._inlineSourceMap; -}; - -Package.prototype.getSource = function(options) { - this._assertFinalized(); - - options = options || {}; - - if (options.minify) { - return this.getMinifiedSourceAndMap().code; - } - - var source = this._getSource(); - - if (options.inlineSourceMap) { - source += this._getInlineSourceMap(); - } - - source += '\n\/\/@ sourceMappingURL=' + this._sourceMapUrl; - - return source; -}; - -Package.prototype.getMinifiedSourceAndMap = function() { - this._assertFinalized(); - - var source = this._getSource(); - try { - return UglifyJS.minify(source, { - fromString: true, - outSourceMap: 'bundle.js', - inSourceMap: this.getSourceMap(), - }); - } catch(e) { - // Sometimes, when somebody is using a new syntax feature that we - // don't yet have transform for, the untransformed line is sent to - // uglify, and it chokes on it. This code tries to print the line - // and the module for easier debugging - var errorMessage = 'Error while minifying JS\n'; - if (e.line) { - errorMessage += 'Transformed code line: "' + - source.split('\n')[e.line - 1] + '"\n'; - } - if (e.pos) { - var fromIndex = source.lastIndexOf('__d(\'', e.pos); - if (fromIndex > -1) { - fromIndex += '__d(\''.length; - var toIndex = source.indexOf('\'', fromIndex); - errorMessage += 'Module name (best guess): ' + - source.substring(fromIndex, toIndex) + '\n'; - } - } - errorMessage += e.toString(); - throw new Error(errorMessage); - } -}; - -Package.prototype.getSourceMap = function(options) { - this._assertFinalized(); - - options = options || {}; - var mappings = this._getMappings(); - var map = { - file: 'bundle.js', - sources: _.pluck(this._modules, 'sourcePath'), - version: 3, - names: [], - mappings: mappings, - sourcesContent: options.excludeSource - ? [] : _.pluck(this._modules, 'sourceCode') - }; - return map; -}; - -Package.prototype._getMappings = function() { - var modules = this._modules; - - // The first line mapping in our package is basically the base64vlq code for - // zeros (A). - var firstLine = 'AAAA'; - - // Most other lines in our mappings are all zeros (for module, column etc) - // except for the lineno mappinp: curLineno - prevLineno = 1; Which is C. - var line = 'AACA'; - - var mappings = ''; - for (var i = 0; i < modules.length; i++) { - var module = modules[i]; - var transformedCode = module.transformedCode; - var lastCharNewLine = false; - module.lines = 0; - for (var t = 0; t < transformedCode.length; t++) { - if (t === 0 && i === 0) { - mappings += firstLine; - } else if (t === 0) { - mappings += 'AC'; - - // This is the only place were we actually don't know the mapping ahead - // of time. When it's a new module (and not the first) the lineno - // mapping is 0 (current) - number of lines in prev module. - mappings += base64VLQ.encode(0 - modules[i - 1].lines); - mappings += 'A'; - } else if (lastCharNewLine) { - module.lines++; - mappings += line; - } - lastCharNewLine = transformedCode[t] === '\n'; - if (lastCharNewLine) { - mappings += ';'; - } - } - if (i !== modules.length - 1) { - mappings += ';'; - } - } - return mappings; -}; - -Package.prototype.getDebugInfo = function() { - return [ - '

Main Module:

' + this._mainModuleId + '
', - '', - '

Module paths and transformed code:

', - this._modules.map(function(m) { - return '

Path:

' + m.sourcePath + '

Source:

' + - '
'; - }).join('\n'), - ].join('\n'); -}; diff --git a/packager/react-packager/src/Packager/__tests__/Package-test.js b/packager/react-packager/src/Packager/__tests__/Package-test.js deleted file mode 100644 index 41630fc4732..00000000000 --- a/packager/react-packager/src/Packager/__tests__/Package-test.js +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -jest.autoMockOff(); - -var SourceMapGenerator = require('source-map').SourceMapGenerator; - -describe('Package', function() { - var Package; - var ppackage; - - beforeEach(function() { - Package = require('../Package'); - ppackage = new Package('test_url'); - ppackage.getSourceMap = jest.genMockFn().mockImpl(function() { - return 'test-source-map'; - }); - }); - - describe('source package', function() { - it('should create a package and get the source', function() { - ppackage.addModule('transformed foo;', 'source foo', 'foo path'); - ppackage.addModule('transformed bar;', 'source bar', 'bar path'); - ppackage.finalize({}); - expect(ppackage.getSource({inlineSourceMap: true})).toBe([ - 'transformed foo;', - 'transformed bar;', - 'RAW_SOURCE_MAP = "test-source-map";', - '\/\/@ sourceMappingURL=test_url', - ].join('\n')); - }); - - it('should create a package and add run module code', function() { - ppackage.addModule('transformed foo;', 'source foo', 'foo path'); - ppackage.addModule('transformed bar;', 'source bar', 'bar path'); - ppackage.setMainModuleId('foo'); - ppackage.finalize({runMainModule: true}); - expect(ppackage.getSource({inlineSourceMap: true})).toBe([ - 'transformed foo;', - 'transformed bar;', - ';require("foo");', - 'RAW_SOURCE_MAP = "test-source-map";', - '\/\/@ sourceMappingURL=test_url', - ].join('\n')); - }); - - it('should get minified source', function() { - var minified = { - code: 'minified', - map: 'map', - }; - - require('uglify-js').minify = function() { - return minified; - }; - - ppackage.addModule('transformed foo;', 'source foo', 'foo path'); - ppackage.finalize(); - expect(ppackage.getMinifiedSourceAndMap()).toBe(minified); - }); - }); - - describe('sourcemap package', function() { - it('should create sourcemap', function() { - var p = new Package('test_url'); - p.addModule('transformed foo;\n', 'source foo', 'foo path'); - p.addModule('transformed bar;\n', 'source bar', 'bar path'); - p.setMainModuleId('foo'); - p.finalize({runMainModule: true}); - var s = p.getSourceMap(); - expect(s).toEqual(genSourceMap(p._modules)); - }); - }); -}); - - function genSourceMap(modules) { - var sourceMapGen = new SourceMapGenerator({file: 'bundle.js', version: 3}); - var packageLineNo = 0; - for (var i = 0; i < modules.length; i++) { - var module = modules[i]; - var transformedCode = module.transformedCode; - var sourcePath = module.sourcePath; - var sourceCode = module.sourceCode; - var transformedLineCount = 0; - var lastCharNewLine = false; - for (var t = 0; t < transformedCode.length; t++) { - if (t === 0 || lastCharNewLine) { - sourceMapGen.addMapping({ - generated: {line: packageLineNo + 1, column: 0}, - original: {line: transformedLineCount + 1, column: 0}, - source: sourcePath - }); - } - lastCharNewLine = transformedCode[t] === '\n'; - if (lastCharNewLine) { - transformedLineCount++; - packageLineNo++; - } - } - packageLineNo++; - sourceMapGen.setSourceContent( - sourcePath, - sourceCode - ); - } - return sourceMapGen.toJSON(); - } diff --git a/packager/react-packager/src/Packager/__tests__/Packager-test.js b/packager/react-packager/src/Packager/__tests__/Packager-test.js deleted file mode 100644 index d8348be8fa3..00000000000 --- a/packager/react-packager/src/Packager/__tests__/Packager-test.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; - -jest - .setMock('worker-farm', function() { return function() {};}) - .dontMock('path') - .dontMock('q') - .dontMock('os') - .dontMock('underscore') - .setMock('uglify-js') - .dontMock('../'); - -var q = require('q'); - -describe('Packager', function() { - var getDependencies; - var wrapModule; - var Packager; - - beforeEach(function() { - getDependencies = jest.genMockFn(); - wrapModule = jest.genMockFn(); - require('../../DependencyResolver').mockImpl(function() { - return { - getDependencies: getDependencies, - wrapModule: wrapModule, - }; - }); - - Packager = require('../'); - }); - - pit('create a package', function() { - require('fs').statSync.mockImpl(function() { - return { - isDirectory: function() {return true;} - }; - }); - - var packager = new Packager({projectRoots: []}); - var modules = [ - {id: 'foo', path: '/root/foo.js', dependencies: []}, - {id: 'bar', path: '/root/bar.js', dependencies: []}, - ]; - - getDependencies.mockImpl(function() { - return q({ - mainModuleId: 'foo', - dependencies: modules - }); - }); - - require('../../JSTransformer').prototype.loadFileAndTransform - .mockImpl(function(path) { - return q({ - code: 'transformed ' + path, - sourceCode: 'source ' + path, - sourcePath: path - }); - }); - - wrapModule.mockImpl(function(module, code) { - return 'lol ' + code + ' lol'; - }); - - return packager.package('/root/foo.js', true, 'source_map_url') - .then(function(p) { - expect(p.addModule.mock.calls[0]).toEqual([ - 'lol transformed /root/foo.js lol', - 'source /root/foo.js', - '/root/foo.js' - ]); - expect(p.addModule.mock.calls[1]).toEqual([ - 'lol transformed /root/bar.js lol', - 'source /root/bar.js', - '/root/bar.js' - ]); - - expect(p.finalize.mock.calls[0]).toEqual([ - {runMainModule: true} - ]); - }); - }); - -}); diff --git a/packager/react-packager/src/Packager/base64-vlq.js b/packager/react-packager/src/Packager/base64-vlq.js deleted file mode 100644 index 4483a507a96..00000000000 --- a/packager/react-packager/src/Packager/base64-vlq.js +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - * - * Based on the Base 64 VLQ implementation in Closure Compiler: - * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java - * - * Copyright 2011 The Closure Compiler Authors. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/*eslint no-bitwise:0,quotes:0,global-strict:0*/ - -var charToIntMap = {}; -var intToCharMap = {}; - -'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - .split('') - .forEach(function (ch, index) { - charToIntMap[ch] = index; - intToCharMap[index] = ch; - }); - -var base64 = {}; -/** - * Encode an integer in the range of 0 to 63 to a single base 64 digit. - */ -base64.encode = function base64_encode(aNumber) { - if (aNumber in intToCharMap) { - return intToCharMap[aNumber]; - } - throw new TypeError("Must be between 0 and 63: " + aNumber); -}; - -/** - * Decode a single base 64 digit to an integer. - */ -base64.decode = function base64_decode(aChar) { - if (aChar in charToIntMap) { - return charToIntMap[aChar]; - } - throw new TypeError("Not a valid base 64 digit: " + aChar); -}; - - - -// A single base 64 digit can contain 6 bits of data. For the base 64 variable -// length quantities we use in the source map spec, the first bit is the sign, -// the next four bits are the actual value, and the 6th bit is the -// continuation bit. The continuation bit tells us whether there are more -// digits in this value following this digit. -// -// Continuation -// | Sign -// | | -// V V -// 101011 - -var VLQ_BASE_SHIFT = 5; - -// binary: 100000 -var VLQ_BASE = 1 << VLQ_BASE_SHIFT; - -// binary: 011111 -var VLQ_BASE_MASK = VLQ_BASE - 1; - -// binary: 100000 -var VLQ_CONTINUATION_BIT = VLQ_BASE; - -/** - * Converts from a two-complement value to a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - */ -function toVLQSigned(aValue) { - return aValue < 0 - ? ((-aValue) << 1) + 1 - : (aValue << 1) + 0; -} - -/** - * Converts to a two-complement value from a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - */ -function fromVLQSigned(aValue) { - var isNegative = (aValue & 1) === 1; - var shifted = aValue >> 1; - return isNegative - ? -shifted - : shifted; -} - -/** - * Returns the base 64 VLQ encoded value. - */ -exports.encode = function base64VLQ_encode(aValue) { - var encoded = ""; - var digit; - - var vlq = toVLQSigned(aValue); - - do { - digit = vlq & VLQ_BASE_MASK; - vlq >>>= VLQ_BASE_SHIFT; - if (vlq > 0) { - // There are still more digits in this value, so we must make sure the - // continuation bit is marked. - digit |= VLQ_CONTINUATION_BIT; - } - encoded += base64.encode(digit); - } while (vlq > 0); - - return encoded; -}; - -/** - * Decodes the next base 64 VLQ value from the given string and returns the - * value and the rest of the string via the out parameter. - */ -exports.decode = function base64VLQ_decode(aStr, aOutParam) { - var i = 0; - var strLen = aStr.length; - var result = 0; - var shift = 0; - var continuation, digit; - - do { - if (i >= strLen) { - throw new Error("Expected more digits in base 64 VLQ value."); - } - digit = base64.decode(aStr.charAt(i++)); - continuation = !!(digit & VLQ_CONTINUATION_BIT); - digit &= VLQ_BASE_MASK; - result = result + (digit << shift); - shift += VLQ_BASE_SHIFT; - } while (continuation); - - aOutParam.value = fromVLQSigned(result); - aOutParam.rest = aStr.slice(i); -}; diff --git a/packager/react-packager/src/Packager/index.js b/packager/react-packager/src/Packager/index.js deleted file mode 100644 index 75cccdb26d0..00000000000 --- a/packager/react-packager/src/Packager/index.js +++ /dev/null @@ -1,144 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var fs = require('fs'); -var path = require('path'); -var q = require('q'); -var Promise = require('q').Promise; -var Transformer = require('../JSTransformer'); -var DependencyResolver = require('../DependencyResolver'); -var _ = require('underscore'); -var Package = require('./Package'); -var Activity = require('../Activity'); -var declareOpts = require('../lib/declareOpts'); - -var validateOpts = declareOpts({ - projectRoots: { - type: 'array', - required: true, - }, - blacklistRE: { - type: 'object', // typeof regex is object - }, - moduleFormat: { - type: 'string', - default: 'haste', - }, - polyfillModuleNames: { - type: 'array', - default: [], - }, - cacheVersion: { - type: 'string', - default: '1.0', - }, - resetCache: { - type: 'boolean', - default: false, - }, - transformModulePath: { - type:'string', - required: false, - }, - nonPersistent: { - type: 'boolean', - default: false, - }, -}); - -function Packager(options) { - var opts = this._opts = validateOpts(options); - - opts.projectRoots.forEach(verifyRootExists); - - this._resolver = new DependencyResolver({ - projectRoots: opts.projectRoots, - blacklistRE: opts.blacklistRE, - polyfillModuleNames: opts.polyfillModuleNames, - nonPersistent: opts.nonPersistent, - moduleFormat: opts.moduleFormat - }); - - this._transformer = new Transformer({ - projectRoots: opts.projectRoots, - blacklistRE: opts.blacklistRE, - cacheVersion: opts.cacheVersion, - resetCache: opts.resetCache, - transformModulePath: opts.transformModulePath, - nonPersistent: opts.nonPersistent, - }); -} - -Packager.prototype.kill = function() { - return q.all([ - this._transformer.kill(), - this._resolver.end(), - ]); -}; - -Packager.prototype.package = function(main, runModule, sourceMapUrl, isDev) { - var transformModule = this._transformModule.bind(this); - var ppackage = new Package(sourceMapUrl); - - var findEventId = Activity.startEvent('find dependencies'); - var transformEventId; - - return this.getDependencies(main, isDev) - .then(function(result) { - Activity.endEvent(findEventId); - transformEventId = Activity.startEvent('transform'); - - ppackage.setMainModuleId(result.mainModuleId); - return Promise.all( - result.dependencies.map(transformModule) - ); - }) - .then(function(transformedModules) { - Activity.endEvent(transformEventId); - - transformedModules.forEach(function(transformed) { - ppackage.addModule( - transformed.code, - transformed.sourceCode, - transformed.sourcePath - ); - }); - - ppackage.finalize({ runMainModule: runModule }); - return ppackage; - }); -}; - -Packager.prototype.invalidateFile = function(filePath) { - this._transformer.invalidateFile(filePath); -}; - -Packager.prototype.getDependencies = function(main, isDev) { - return this._resolver.getDependencies(main, { dev: isDev }); -}; - -Packager.prototype._transformModule = function(module) { - var resolver = this._resolver; - return this._transformer.loadFileAndTransform( - path.resolve(module.path) - ).then(function(transformed) { - return _.extend( - {}, - transformed, - {code: resolver.wrapModule(module, transformed.code)} - ); - }); -}; - - -function verifyRootExists(root) { - // Verify that the root exists. - assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory'); -} - -Packager.prototype.getGraphDebugInfo = function() { - return this._resolver.getDebugInfo(); -}; - - -module.exports = Packager; diff --git a/packager/react-packager/src/Server/__tests__/Server-test.js b/packager/react-packager/src/Server/__tests__/Server-test.js deleted file mode 100644 index 71b7e400f03..00000000000 --- a/packager/react-packager/src/Server/__tests__/Server-test.js +++ /dev/null @@ -1,208 +0,0 @@ -'use strict'; - -jest.setMock('worker-farm', function() { return function() {}; }) - .dontMock('q') - .dontMock('os') - .dontMock('path') - .dontMock('url') - .setMock('timers', { - setImmediate: function(fn) { - return setTimeout(fn, 0); - } - }) - .setMock('uglify-js') - .dontMock('../'); - -var q = require('q'); - -describe('processRequest', function() { - var server; - var Packager; - var FileWatcher; - - var options = { - projectRoots: ['root'], - blacklistRE: null, - cacheVersion: null, - polyfillModuleNames: null - }; - - var makeRequest = function(requestHandler, requrl) { - var deferred = q.defer(); - requestHandler({ - url: requrl - },{ - end: function(res) { - deferred.resolve(res); - } - },{ - next: function() {} - } - ); - return deferred.promise; - }; - - var invalidatorFunc = jest.genMockFunction(); - var watcherFunc = jest.genMockFunction(); - var requestHandler; - var triggerFileChange; - - beforeEach(function() { - Packager = require('../../Packager'); - FileWatcher = require('../../FileWatcher'); - - Packager.prototype.package = function() { - return q({ - getSource: function() { - return 'this is the source'; - }, - getSourceMap: function() { - return 'this is the source map'; - }, - }); - }; - - - FileWatcher.prototype.on = function(eventType, callback) { - if (eventType !== 'all') { - throw new Error('Can only handle "all" event in watcher.'); - } - watcherFunc.apply(this, arguments); - triggerFileChange = callback; - return this; - }; - - Packager.prototype.invalidateFile = invalidatorFunc; - - var Server = require('../'); - server = new Server(options); - requestHandler = server.processRequest.bind(server); - }); - - pit('returns JS bundle source on request of *.bundle',function() { - return makeRequest( - requestHandler, - 'mybundle.bundle?runModule=true' - ).then(function(response) { - expect(response).toEqual('this is the source'); - }); - }); - - pit('returns JS bundle source on request of *.bundle (compat)',function() { - return makeRequest( - requestHandler, - 'mybundle.runModule.bundle' - ).then(function(response) { - expect(response).toEqual('this is the source'); - }); - }); - - pit('returns sourcemap on request of *.map', function() { - return makeRequest( - requestHandler, - 'mybundle.map?runModule=true' - ).then(function(response) { - expect(response).toEqual('"this is the source map"'); - }); - }); - - pit('watches all files in projectRoot', function() { - return makeRequest( - requestHandler, - 'mybundle.bundle?runModule=true' - ).then(function() { - expect(watcherFunc.mock.calls[0][0]).toEqual('all'); - expect(watcherFunc.mock.calls[0][1]).not.toBe(null); - }); - }); - - - describe('file changes', function() { - pit('invalides files in package when file is updated', function() { - return makeRequest( - requestHandler, - 'mybundle.bundle?runModule=true' - ).then(function() { - var onFileChange = watcherFunc.mock.calls[0][1]; - onFileChange('all','path/file.js', options.projectRoots[0]); - expect(invalidatorFunc.mock.calls[0][0]).toEqual('root/path/file.js'); - }); - }); - - pit('rebuilds the packages that contain a file when that file is changed', function() { - var packageFunc = jest.genMockFunction(); - packageFunc - .mockReturnValueOnce( - q({ - getSource: function() { - return 'this is the first source'; - }, - getSourceMap: function() {}, - }) - ) - .mockReturnValue( - q({ - getSource: function() { - return 'this is the rebuilt source'; - }, - getSourceMap: function() {}, - }) - ); - - Packager.prototype.package = packageFunc; - - var Server = require('../../Server'); - server = new Server(options); - - requestHandler = server.processRequest.bind(server); - - - return makeRequest(requestHandler, 'mybundle.bundle?runModule=true') - .then(function(response) { - expect(response).toEqual('this is the first source'); - expect(packageFunc.mock.calls.length).toBe(1); - triggerFileChange('all','path/file.js', options.projectRoots[0]); - jest.runAllTimers(); - }) - .then(function() { - expect(packageFunc.mock.calls.length).toBe(2); - return makeRequest(requestHandler, 'mybundle.bundle?runModule=true') - .then(function(response) { - expect(response).toEqual('this is the rebuilt source'); - }); - }); - }); - }); - - describe('/onchange endpoint', function() { - var EventEmitter; - var req; - var res; - - beforeEach(function() { - EventEmitter = require.requireActual('events').EventEmitter; - req = new EventEmitter(); - req.url = '/onchange'; - res = { - writeHead: jest.genMockFn(), - end: jest.genMockFn() - }; - }); - - it('should hold on to request and inform on change', function() { - server.processRequest(req, res); - triggerFileChange('all', 'path/file.js', options.projectRoots[0]); - jest.runAllTimers(); - expect(res.end).toBeCalledWith(JSON.stringify({changed: true})); - }); - - it('should not inform changes on disconnected clients', function() { - server.processRequest(req, res); - req.emit('close'); - jest.runAllTimers(); - triggerFileChange('all', 'path/file.js', options.projectRoots[0]); - jest.runAllTimers(); - expect(res.end).not.toBeCalled(); - }); - }); -}); diff --git a/packager/react-packager/src/Server/index.js b/packager/react-packager/src/Server/index.js deleted file mode 100644 index 8982bc9165f..00000000000 --- a/packager/react-packager/src/Server/index.js +++ /dev/null @@ -1,269 +0,0 @@ -'use strict'; - -var url = require('url'); -var path = require('path'); -var declareOpts = require('../lib/declareOpts'); -var FileWatcher = require('../FileWatcher'); -var Packager = require('../Packager'); -var Activity = require('../Activity'); -var setImmediate = require('timers').setImmediate; -var q = require('q'); - -module.exports = Server; - -var validateOpts = declareOpts({ - projectRoots: { - type: 'array', - required: true, - }, - blacklistRE: { - type: 'object', // typeof regex is object - }, - moduleFormat: { - type: 'string', - default: 'haste', - }, - polyfillModuleNames: { - type: 'array', - default: [], - }, - cacheVersion: { - type: 'string', - default: '1.0', - }, - resetCache: { - type: 'boolean', - default: false, - }, - transformModulePath: { - type:'string', - required: false, - }, - nonPersistent: { - type: 'boolean', - default: false, - }, -}); - -function Server(options) { - var opts = validateOpts(options); - this._projectRoots = opts.projectRoots; - this._packages = Object.create(null); - this._packager = new Packager(opts); - this._changeWatchers = []; - - this._fileWatcher = options.nonPersistent - ? FileWatcher.createDummyWatcher() - : new FileWatcher(options.projectRoots); - - var onFileChange = this._onFileChange.bind(this); - this._fileWatcher.on('all', onFileChange); -} - -Server.prototype._onFileChange = function(type, filepath, root) { - var absPath = path.join(root, filepath); - this._packager.invalidateFile(absPath); - // Make sure the file watcher event runs through the system before - // we rebuild the packages. - setImmediate(this._rebuildPackages.bind(this, absPath)); - setImmediate(this._informChangeWatchers.bind(this)); -}; - -Server.prototype._rebuildPackages = function() { - var buildPackage = this._buildPackage.bind(this); - var packages = this._packages; - Object.keys(packages).forEach(function(key) { - var options = getOptionsFromUrl(key); - packages[key] = buildPackage(options).then(function(p) { - // Make a throwaway call to getSource to cache the source string. - p.getSource({ - inlineSourceMap: options.dev, - minify: options.minify, - }); - return p; - }); - }); -}; - -Server.prototype._informChangeWatchers = function() { - var watchers = this._changeWatchers; - var headers = { - 'Content-Type': 'application/json; charset=UTF-8', - }; - - watchers.forEach(function(w) { - w.res.writeHead(205, headers); - w.res.end(JSON.stringify({ changed: true })); - }); - - this._changeWatchers = []; -}; - -Server.prototype.end = function() { - q.all([ - this._fileWatcher.end(), - this._packager.kill(), - ]); -}; - -Server.prototype._buildPackage = function(options) { - return this._packager.package( - options.main, - options.runModule, - options.sourceMapUrl, - options.dev - ); -}; - -Server.prototype.buildPackageFromUrl = function(reqUrl) { - var options = getOptionsFromUrl(reqUrl); - return this._buildPackage(options); -}; - -Server.prototype.getDependencies = function(main) { - return this._packager.getDependencies(main); -}; - -Server.prototype._processDebugRequest = function(reqUrl, res) { - var ret = ''; - var pathname = url.parse(reqUrl).pathname; - var parts = pathname.split('/').filter(Boolean); - if (parts.length === 1) { - ret += ''; - ret += ''; - res.end(ret); - } else if (parts[1] === 'packages') { - ret += '

Cached Packages

'; - q.all(Object.keys(this._packages).map(function(url) { - return this._packages[url].then(function(p) { - ret += '

' + url + '

'; - ret += p.getDebugInfo(); - }); - }, this)).then( - function() { res.end(ret); }, - function(e) { - res.wrteHead(500); - res.end('Internal Error'); - console.log(e.stack); - } - ); - } else if (parts[1] === 'graph'){ - ret += '

Dependency Graph

'; - ret += this._packager.getGraphDebugInfo(); - res.end(ret); - } else { - res.writeHead('404'); - res.end('Invalid debug request'); - return; - } -}; - -Server.prototype._processOnChangeRequest = function(req, res) { - var watchers = this._changeWatchers; - - watchers.push({ - req: req, - res: res, - }); - - req.on('close', function() { - for (var i = 0; i < watchers.length; i++) { - if (watchers[i] && watchers[i].req === req) { - watchers.splice(i, 1); - break; - } - } - }); -}; - -Server.prototype.processRequest = function(req, res, next) { - var urlObj = url.parse(req.url, true); - var pathname = urlObj.pathname; - - var requestType; - if (pathname.match(/\.bundle$/)) { - requestType = 'bundle'; - } else if (pathname.match(/\.map$/)) { - requestType = 'map'; - } else if (pathname.match(/^\/debug/)) { - this._processDebugRequest(req.url, res); - return; - } else if (pathname.match(/^\/onchange\/?$/)) { - this._processOnChangeRequest(req, res); - return; - } else { - next(); - return; - } - - var startReqEventId = Activity.startEvent('request:' + req.url); - var options = getOptionsFromUrl(req.url); - var building = this._packages[req.url] || this._buildPackage(options); - - this._packages[req.url] = building; - building.then( - function(p) { - if (requestType === 'bundle') { - res.end(p.getSource({ - inlineSourceMap: options.dev, - minify: options.minify, - })); - Activity.endEvent(startReqEventId); - } else if (requestType === 'map') { - res.end(JSON.stringify(p.getSourceMap())); - Activity.endEvent(startReqEventId); - } - }, - function(error) { - handleError(res, error); - } - ).done(); -}; - -function getOptionsFromUrl(reqUrl) { - // `true` to parse the query param as an object. - var urlObj = url.parse(reqUrl, true); - - var match = urlObj.pathname.match(/^\/?([^\.]+)\..*(bundle|map)$/); - if (!(match && match[1])) { - throw new Error('Invalid url format, expected "/path/to/file.bundle"'); - } - var main = match[1] + '.js'; - - return { - sourceMapUrl: urlObj.pathname.replace(/\.bundle$/, '.map'), - main: main, - dev: getBoolOptionFromQuery(urlObj.query, 'dev', true), - minify: getBoolOptionFromQuery(urlObj.query, 'minify'), - runModule: getBoolOptionFromQuery(urlObj.query, 'runModule') || - // Backwards compatibility. - urlObj.pathname.split('.').some(function(part) { - return part === 'runModule'; - }), - }; -} - -function getBoolOptionFromQuery(query, opt, defaultVal) { - if (query[opt] == null && defaultVal != null) { - return defaultVal; - } - - return query[opt] === 'true' || query[opt] === '1'; -} - -function handleError(res, error) { - res.writeHead(500, { - 'Content-Type': 'application/json; charset=UTF-8', - }); - - if (error.type === 'TransformError') { - res.end(JSON.stringify(error)); - } else { - console.error(error.stack || error); - res.end(JSON.stringify({ - type: 'InternalError', - message: 'react-packager has encountered an internal error, ' + - 'please check your terminal error output for more details', - })); - } -} diff --git a/packager/react-packager/src/lib/__mocks__/declareOpts.js b/packager/react-packager/src/lib/__mocks__/declareOpts.js deleted file mode 100644 index 1afe4e297e5..00000000000 --- a/packager/react-packager/src/lib/__mocks__/declareOpts.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -module.exports = function(declared) { - return function(opts) { - for (var p in declared) { - if (opts[p] == null && declared[p].default != null){ - opts[p] = declared[p].default; - } - } - return opts; - }; -}; diff --git a/packager/react-packager/src/lib/__tests__/declareOpts-test.js b/packager/react-packager/src/lib/__tests__/declareOpts-test.js deleted file mode 100644 index 66ae174fb9a..00000000000 --- a/packager/react-packager/src/lib/__tests__/declareOpts-test.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; - -jest.autoMockOff(); - -var declareOpts = require('../declareOpts'); - -describe('declareOpts', function() { - it('should declare and validate simple opts', function() { - var validate = declareOpts({ - name: { - required: true, - type: 'string', - }, - age: { - type: 'number', - default: 21, - } - }); - var opts = validate({ name: 'fooer' }); - - expect(opts).toEqual({ - name: 'fooer', - age: 21 - }); - }); - - it('should work with complex types', function() { - var validate = declareOpts({ - things: { - required: true, - type: 'array', - }, - stuff: { - type: 'object', - required: true, - } - }); - - var opts = validate({ things: [1, 2, 3], stuff: {hai: 1} }); - expect(opts).toEqual({ - things: [1,2,3], - stuff: {hai: 1}, - }); - }); - - it('should throw when a required option is not present', function() { - var validate = declareOpts({ - foo: { - required: true, - type: 'number', - } - }); - - expect(function() { - validate({}); - }).toThrow('Error validating module options: foo is required'); - }); - - it('should throw on invalid type', function() { - var validate = declareOpts({ - foo: { - required: true, - type: 'number' - } - }); - - expect(function() { - validate({foo: 'lol'}); - }).toThrow('Error validating module options: foo must be a number'); - }); - - it('should throw on extra options', function() { - var validate = declareOpts({ - foo: { - required: true, - type: 'number', - } - }); - - expect(function() { - validate({foo: 1, lol: 1}); - }).toThrow('Error validating module options: lol is not allowed'); - }); -}); diff --git a/packager/react-packager/src/lib/declareOpts.js b/packager/react-packager/src/lib/declareOpts.js deleted file mode 100644 index 3b80da51929..00000000000 --- a/packager/react-packager/src/lib/declareOpts.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Declares, validates and defaults options. - * var validate = declareOpts({ - * foo: { - * type: 'bool', - * required: true, - * } - * }); - * - * var myOptions = validate(someOptions); - */ - -'use strict'; - -var Joi = require('joi'); - -module.exports = function(descriptor) { - var joiKeys = {}; - Object.keys(descriptor).forEach(function(prop) { - var record = descriptor[prop]; - if (record.type == null) { - throw new Error('Type is required'); - } - - if (record.type === 'function') { - record.type = 'func'; - } - - var propValidator = Joi[record.type](); - - if (record.required) { - propValidator = propValidator.required(); - } - - if (record.default) { - propValidator = propValidator.default(record.default); - } - - joiKeys[prop] = propValidator; - }); - - var schema = Joi.object().keys(joiKeys); - - return function(opts) { - opts = opts || {}; - - var res = Joi.validate(opts, schema, { - abortEarly: true, - allowUnknown: false, - }); - - if (res.error) { - throw new Error('Error validating module options: ' + res.error.message); - } - return res.value; - }; -}; diff --git a/packager/transformer.js b/packager/transformer.js deleted file mode 100644 index acb586d7f0f..00000000000 --- a/packager/transformer.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright 2004-present Facebook. All Rights Reserved. - * - * Note: This is a fork of the fb-specific transform.js - */ -'use strict'; - -var jstransform = require('jstransform').transform; - -var reactVisitors = - require('react-tools/vendor/fbtransform/visitors').getAllVisitors(); -var staticTypeSyntax = - require('jstransform/visitors/type-syntax').visitorList; -// Note that reactVisitors now handles ES6 classes, rest parameters, arrow -// functions, template strings, and object short notation. -var visitorList = reactVisitors; - - -function transform(srcTxt, filename) { - var options = { - es3: true, - sourceType: 'nonStrictModule', - filename: filename, - }; - - // These tranforms mostly just erase type annotations and static typing - // related statements, but they were conflicting with other tranforms. - // Running them first solves that problem - var staticTypeSyntaxResult = jstransform( - staticTypeSyntax, - srcTxt, - options - ); - - return jstransform( - visitorList, - staticTypeSyntaxResult.code, - options - ); -} - -module.exports = function(data, callback) { - var result; - try { - result = transform( - data.sourceCode, - data.filename - ); - } catch (e) { - return callback(null, { - error: { - lineNumber: e.lineNumber, - column: e.column, - message: e.message, - stack: e.stack, - description: e.description - } - }); - } - - callback(null, result); -}; - -// export for use in jest -module.exports.transform = transform; diff --git a/support.html b/support.html new file mode 100644 index 00000000000..f986d185567 --- /dev/null +++ b/support.html @@ -0,0 +1,12 @@ +React Native | Build Native Apps Using React

Need help?

React Native is worked on full-time by Facebook's product infrastructure user interface engineering teams. They're often around and available for questions.

Stack Overflow #

Many members of the community use Stack Overflow to ask questions. Read through the existing questions tagged with reactnative or ask your own!

IRC #

Many developers and users idle on Freenode.net's IRC network in #reactnative on freenode.

Twitter #

#reactnative hash tag on Twitter is used to keep up with the latest React Native news.

© 2015 Facebook Inc.
\ No newline at end of file diff --git a/website/.gitignore b/website/.gitignore deleted file mode 100644 index 37a25d50ab1..00000000000 --- a/website/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -src/react-native/docs/** -core/metadata.js diff --git a/website/README.md b/website/README.md deleted file mode 100644 index 37a326df20e..00000000000 --- a/website/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Run the server - -The first time, get all the dependencies loaded via - -``` -npm install -``` - -You also have to run `npm install` inside the `react-docgen` folder. This is only temporary until `react-docgen` is available as npm module. - -``` -cd react-docgen -npm install -cd .. -``` - -Then, run the server via - -``` -npm start -Open http://localhost:8080/react-native/index.html -``` - -Anytime you change the contents, just refresh the page and it's going to be updated - -# Publish the website - -First setup your environment by having two folders, one `react-native` and one `react-native-gh-pages`. The publish script expects those exact names. - -``` -cd ../../ -git clone git@github.com:facebook/react-native.git react-native-gh-pages -cd react-native-gh-pages -git checkout origin/gh-pages -git checkout -b gh-pages -git push --set-upstream origin gh-pages -cd ../react-native/website -``` - -Then, after you've done changes, just run the command and it'll automatically build the static version of the site and publish it to gh-pages. - -``` -./publish.sh -``` diff --git a/website/core/DocsSidebar.js b/website/core/DocsSidebar.js deleted file mode 100644 index 7b8cbb98b48..00000000000 --- a/website/core/DocsSidebar.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @providesModule DocsSidebar - * @jsx React.DOM - */ - -var React = require('React'); -var Metadata = require('Metadata'); - -var DocsSidebar = React.createClass({ - getCategories: function() { - var metadatas = Metadata.files.filter(function(metadata) { - return metadata.layout === 'docs' || metadata.layout === 'autodocs'; - }); - - // Build a hashmap of article_id -> metadata - var articles = {}; - for (var i = 0; i < metadatas.length; ++i) { - var metadata = metadatas[i]; - articles[metadata.id] = metadata; - } - - // Build a hashmap of article_id -> previous_id - var previous = {}; - for (var i = 0; i < metadatas.length; ++i) { - var metadata = metadatas[i]; - if (metadata.next) { - if (!articles[metadata.next]) { - throw '`next: ' + metadata.next + '` in ' + metadata.id + ' doesn\'t exist'; - } - previous[articles[metadata.next].id] = metadata.id; - } - } - - // Find the first element which doesn't have any previous - var first = null; - for (var i = 0; i < metadatas.length; ++i) { - var metadata = metadatas[i]; - if (!previous[metadata.id]) { - first = metadata; - break; - } - } - - var categories = []; - var currentCategory = null; - - var metadata = first; - var i = 0; - while (metadata && i++ < 1000) { - if (!currentCategory || metadata.category !== currentCategory.name) { - currentCategory && categories.push(currentCategory); - currentCategory = { - name: metadata.category, - links: [] - }; - } - currentCategory.links.push(metadata); - metadata = articles[metadata.next]; - } - categories.push(currentCategory); - - return categories; - }, - - getLink: function(metadata) { - if (metadata.permalink.match(/^https?:/)) { - return metadata.permalink; - } - return '/react-native/' + metadata.permalink + '#content'; - }, - - render: function() { - return
- {this.getCategories().map((category) => -
-

{category.name}

- -
- )} -
; - } -}); - -module.exports = DocsSidebar; diff --git a/website/core/H2.js b/website/core/H2.js deleted file mode 100644 index 3b67f42ecbd..00000000000 --- a/website/core/H2.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @providesModule H2 - * @jsx React.DOM - */ - -var React = require('React'); -var Header = require('Header'); - -var H2 = React.createClass({ - render: function() { - return this.transferPropsTo( -
{this.props.children}
- ); - } -}); - -module.exports = H2; diff --git a/website/core/Header.js b/website/core/Header.js deleted file mode 100644 index f49cae3747b..00000000000 --- a/website/core/Header.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @providesModule Header - * @jsx React.DOM - */ - -var React = require('React'); -var slugify = require('slugify'); - -var Header = React.createClass({ - render: function() { - var slug = slugify(this.props.toSlug || this.props.children); - var H = React.DOM['h' + this.props.level]; - - return this.transferPropsTo( - - - {this.props.children} - {' '}# - - ); - } -}); - -module.exports = Header; diff --git a/website/core/HeaderLinks.js b/website/core/HeaderLinks.js deleted file mode 100644 index 86b74928561..00000000000 --- a/website/core/HeaderLinks.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @providesModule HeaderLinks - * @jsx React.DOM - */ - -var React = require('React'); - -var HeaderLinks = React.createClass({ - links: [ - {section: 'docs', href: '/react-native/docs/getting-started.html#content', text: 'docs'}, - {section: 'support', href: '/react-native/support.html', text: 'support'}, - {section: 'github', href: 'http://github.com/facebook/react-native', text: 'github'}, - ], - - render: function() { - return ( -
    - {this.links.map(function(link) { - return ( -
  • - - {link.text} - -
  • - ); - }, this)} -
- ); - } -}); - -module.exports = HeaderLinks; diff --git a/website/core/Marked.js b/website/core/Marked.js deleted file mode 100644 index f7f6c5007ca..00000000000 --- a/website/core/Marked.js +++ /dev/null @@ -1,1094 +0,0 @@ -/** - * marked - a markdown parser - * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - * - * @providesModule Marked - * @jsx React.DOM - */ - -var React = require('React'); -var Prism = require('Prism'); -var Header = require('Header'); - -/** - * Block-Level Grammar - */ - -var block = { - newline: /^\n+/, - code: /^( {4}[^\n]+\n*)+/, - fences: noop, - hr: /^( *[-*_]){3,} *(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, - nptable: noop, - lheading: /^([^\n]+)\n *(=|-){3,} *\n*/, - blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/, - list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, - html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/, - def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, - table: noop, - paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, - text: /^[^\n]+/ -}; - -block.bullet = /(?:[*+-]|\d+\.)/; -block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; -block.item = replace(block.item, 'gm') - (/bull/g, block.bullet) - (); - -block.list = replace(block.list) - (/bull/g, block.bullet) - ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/) - (); - -block._tag = '(?!(?:' - + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' - + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' - + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b'; - -block.html = replace(block.html) - ('comment', //) - ('closed', /<(tag)[\s\S]+?<\/\1>/) - ('closing', /])*?>/) - (/tag/g, block._tag) - (); - -block.paragraph = replace(block.paragraph) - ('hr', block.hr) - ('heading', block.heading) - ('lheading', block.lheading) - ('blockquote', block.blockquote) - ('tag', '<' + block._tag) - ('def', block.def) - (); - -/** - * Normal Block Grammar - */ - -block.normal = merge({}, block); - -/** - * GFM Block Grammar - */ - -block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, - paragraph: /^/ -}); - -block.gfm.paragraph = replace(block.paragraph) - ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|') - (); - -/** - * GFM + Tables Block Grammar - */ - -block.tables = merge({}, block.gfm, { - nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, - table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ -}); - -/** - * Block Lexer - */ - -function Lexer(options) { - this.tokens = []; - this.tokens.links = {}; - this.options = options || marked.defaults; - this.rules = block.normal; - - if (this.options.gfm) { - if (this.options.tables) { - this.rules = block.tables; - } else { - this.rules = block.gfm; - } - } -} - -/** - * Expose Block Rules - */ - -Lexer.rules = block; - -/** - * Static Lex Method - */ - -Lexer.lex = function(src, options) { - var lexer = new Lexer(options); - return lexer.lex(src); -}; - -/** - * Preprocessing - */ - -Lexer.prototype.lex = function(src) { - src = src - .replace(/\r\n|\r/g, '\n') - .replace(/\t/g, ' ') - .replace(/\u00a0/g, ' ') - .replace(/\u2424/g, '\n'); - - return this.token(src, true); -}; - -/** - * Lexing - */ - -Lexer.prototype.token = function(src, top) { - var src = src.replace(/^ +$/gm, '') - , next - , loose - , cap - , bull - , b - , item - , space - , i - , l; - - while (src) { - // newline - if (cap = this.rules.newline.exec(src)) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - this.tokens.push({ - type: 'space' - }); - } - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - this.tokens.push({ - type: 'code', - text: !this.options.pedantic - ? cap.replace(/\n+$/, '') - : cap - }); - continue; - } - - // fences (gfm) - if (cap = this.rules.fences.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'code', - lang: cap[2], - text: cap[3] - }); - continue; - } - - // heading - if (cap = this.rules.heading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } - - // table no leading pipe (gfm) - if (top && (cap = this.rules.nptable.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // lheading - if (cap = this.rules.lheading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } - - // hr - if (cap = this.rules.hr.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'hr' - }); - continue; - } - - // blockquote - if (cap = this.rules.blockquote.exec(src)) { - src = src.substring(cap[0].length); - - this.tokens.push({ - type: 'blockquote_start' - }); - - cap = cap[0].replace(/^ *> ?/gm, ''); - - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - this.token(cap, top); - - this.tokens.push({ - type: 'blockquote_end' - }); - - continue; - } - - // list - if (cap = this.rules.list.exec(src)) { - src = src.substring(cap[0].length); - bull = cap[2]; - - this.tokens.push({ - type: 'list_start', - ordered: bull.length > 1 - }); - - // Get each top-level item. - cap = cap[0].match(this.rules.item); - - next = false; - l = cap.length; - i = 0; - - for (; i < l; i++) { - item = cap[i]; - - // Remove the list item's bullet - // so it is seen as the next token. - space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); - - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = !this.options.pedantic - ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') - : item.replace(/^ {1,4}/gm, ''); - } - - // Determine whether the next list item belongs here. - // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { - b = block.bullet.exec(cap[i+1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { - src = cap.slice(i + 1).join('\n') + src; - i = l - 1; - } - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - loose = next || /\n\n(?!\s*$)/.test(item); - if (i !== l - 1) { - next = item[item.length-1] === '\n'; - if (!loose) loose = next; - } - - this.tokens.push({ - type: loose - ? 'loose_item_start' - : 'list_item_start' - }); - - // Recurse. - this.token(item, false); - - this.tokens.push({ - type: 'list_item_end' - }); - } - - this.tokens.push({ - type: 'list_end' - }); - - continue; - } - - // html - if (cap = this.rules.html.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: this.options.sanitize - ? 'paragraph' - : 'html', - pre: cap[1] === 'pre' || cap[1] === 'script', - text: cap[0] - }); - continue; - } - - // def - if (top && (cap = this.rules.def.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.links[cap[1].toLowerCase()] = { - href: cap[2], - title: cap[3] - }; - continue; - } - - // table (gfm) - if (top && (cap = this.rules.table.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i] - .replace(/^ *\| *| *\| *$/g, '') - .split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // top-level paragraph - if (top && (cap = this.rules.paragraph.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'paragraph', - text: cap[1][cap[1].length-1] === '\n' - ? cap[1].slice(0, -1) - : cap[1] - }); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return this.tokens; -}; - -/** - * Inline-Level Grammar - */ - -var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, - autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, - url: noop, - tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, - link: /^!?\[(inside)\]\(href\)/, - reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, - strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, - code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, - br: /^ {2,}\n(?!\s*$)/, - del: noop, - text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; - -inline.link = replace(inline.link) - ('inside', inline._inside) - ('href', inline._href) - (); - -inline.reflink = replace(inline.reflink) - ('inside', inline._inside) - (); - -/** - * Normal Inline Grammar - */ - -inline.normal = merge({}, inline); - -/** - * Pedantic Inline Grammar - */ - -inline.pedantic = merge({}, inline.normal, { - strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, - em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ -}); - -/** - * GFM Inline Grammar - */ - -inline.gfm = merge({}, inline.normal, { - escape: replace(inline.escape)('])', '~|])')(), - url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, - del: /^~~(?=\S)([\s\S]*?\S)~~/, - text: replace(inline.text) - (']|', '~]|') - ('|', '|https?://|') - () -}); - -/** - * GFM + Line Breaks Inline Grammar - */ - -inline.breaks = merge({}, inline.gfm, { - br: replace(inline.br)('{2,}', '*')(), - text: replace(inline.gfm.text)('{2,}', '*')() -}); - -/** - * Inline Lexer & Compiler - */ - -function InlineLexer(links, options) { - this.options = options || marked.defaults; - this.links = links; - this.rules = inline.normal; - - if (!this.links) { - throw new - Error('Tokens array requires a `links` property.'); - } - - if (this.options.gfm) { - if (this.options.breaks) { - this.rules = inline.breaks; - } else { - this.rules = inline.gfm; - } - } else if (this.options.pedantic) { - this.rules = inline.pedantic; - } -} - -/** - * Expose Inline Rules - */ - -InlineLexer.rules = inline; - -/** - * Static Lexing/Compiling Method - */ - -InlineLexer.output = function(src, links, options) { - var inline = new InlineLexer(links, options); - return inline.output(src); -}; - -/** - * Lexing/Compiling - */ - -InlineLexer.prototype.output = function(src) { - var out = [] - , link - , text - , href - , cap; - - while (src) { - // escape - if (cap = this.rules.escape.exec(src)) { - src = src.substring(cap[0].length); - out.push(cap[1]); - continue; - } - - // autolink - if (cap = this.rules.autolink.exec(src)) { - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = cap[1][6] === ':' - ? cap[1].substring(7) - : cap[1]; - href = 'mailto:' + text; - } else { - text = cap[1]; - href = text; - } - out.push(React.DOM.a({href: this.sanitizeUrl(href)}, text)); - continue; - } - - // url (gfm) - if (cap = this.rules.url.exec(src)) { - src = src.substring(cap[0].length); - text = cap[1]; - href = text; - out.push(React.DOM.a({href: this.sanitizeUrl(href)}, text)); - continue; - } - - // tag - if (cap = this.rules.tag.exec(src)) { - src = src.substring(cap[0].length); - // TODO(alpert): Don't escape if sanitize is false - out.push(cap[0]); - continue; - } - - // link - if (cap = this.rules.link.exec(src)) { - src = src.substring(cap[0].length); - out.push(this.outputLink(cap, { - href: cap[2], - title: cap[3] - })); - continue; - } - - // reflink, nolink - if ((cap = this.rules.reflink.exec(src)) - || (cap = this.rules.nolink.exec(src))) { - src = src.substring(cap[0].length); - link = (cap[2] || cap[1]).replace(/\s+/g, ' '); - link = this.links[link.toLowerCase()]; - if (!link || !link.href) { - out.push.apply(out, this.output(cap[0][0])); - src = cap[0].substring(1) + src; - continue; - } - out.push(this.outputLink(cap, link)); - continue; - } - - // strong - if (cap = this.rules.strong.exec(src)) { - src = src.substring(cap[0].length); - out.push(React.DOM.strong(null, this.output(cap[2] || cap[1]))); - continue; - } - - // em - if (cap = this.rules.em.exec(src)) { - src = src.substring(cap[0].length); - out.push(React.DOM.em(null, this.output(cap[2] || cap[1]))); - continue; - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - out.push(React.DOM.code(null, cap[2])); - continue; - } - - // br - if (cap = this.rules.br.exec(src)) { - src = src.substring(cap[0].length); - out.push(React.DOM.br(null, null)); - continue; - } - - // del (gfm) - if (cap = this.rules.del.exec(src)) { - src = src.substring(cap[0].length); - out.push(React.DOM.del(null, this.output(cap[1]))); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - src = src.substring(cap[0].length); - out.push(this.smartypants(cap[0])); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return out; -}; - -/** - * Sanitize a URL for a link or image - */ - -InlineLexer.prototype.sanitizeUrl = function(url) { - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(url) - .replace(/[^A-Za-z0-9:]/g, '') - .toLowerCase(); - if (prot.indexOf('javascript:') === 0) { - return '#'; - } - } catch (e) { - return '#'; - } - } - return url; -}; - -/** - * Compile Link - */ - -InlineLexer.prototype.outputLink = function(cap, link) { - if (cap[0][0] !== '!') { - var shouldOpenInNewWindow = - link.href.charAt(0) !== '/' - && link.href.charAt(0) !== '#'; - - return React.DOM.a({ - href: this.sanitizeUrl(link.href), - title: link.title, - target: shouldOpenInNewWindow ? '_blank' : '' - }, this.output(cap[1])); - } else { - return React.DOM.img({ - src: this.sanitizeUrl(link.href), - alt: cap[1], - title: link.title - }, null); - } -}; - -/** - * Smartypants Transformations - */ - -InlineLexer.prototype.smartypants = function(text) { - if (!this.options.smartypants) return text; - return text - .replace(/--/g, '\u2014') - .replace(/'([^']*)'/g, '\u2018$1\u2019') - .replace(/"([^"]*)"/g, '\u201C$1\u201D') - .replace(/\.{3}/g, '\u2026'); -}; - -/** - * Parsing & Compiling - */ - -function Parser(options) { - this.tokens = []; - this.token = null; - this.options = options || marked.defaults; -} - -/** - * Static Parse Method - */ - -Parser.parse = function(src, options) { - var parser = new Parser(options); - return parser.parse(src); -}; - -/** - * Parse Loop - */ - -Parser.prototype.parse = function(src) { - this.inline = new InlineLexer(src.links, this.options); - this.tokens = src.reverse(); - - var out = []; - while (this.next()) { - out.push(this.tok()); - } - - return out; -}; - -/** - * Next Token - */ - -Parser.prototype.next = function() { - return this.token = this.tokens.pop(); -}; - -/** - * Preview Next Token - */ - -Parser.prototype.peek = function() { - return this.tokens[this.tokens.length-1] || 0; -}; - -/** - * Parse Text Tokens - */ - -Parser.prototype.parseText = function() { - var body = this.token.text; - - while (this.peek().type === 'text') { - body += '\n' + this.next().text; - } - - return this.inline.output(body); -}; - -/** - * Parse Current Token - */ - -Parser.prototype.tok = function() { - switch (this.token.type) { - case 'space': { - return []; - } - case 'hr': { - return React.DOM.hr(null, null); - } - case 'heading': { - return Header( - {level: this.token.depth, toSlug: this.token.text}, - this.inline.output(this.token.text) - ); - } - case 'code': { - return Prism(null, this.token.text); - } - case 'table': { - var table = [] - , body = [] - , row = [] - , heading - , i - , cells - , j; - - // header - for (i = 0; i < this.token.header.length; i++) { - heading = this.inline.output(this.token.header[i]); - row.push(React.DOM.th( - this.token.align[i] - ? {style: {textAlign: this.token.align[i]}} - : null, - heading - )); - } - table.push(React.DOM.thead(null, React.DOM.tr(null, row))); - - // body - for (i = 0; i < this.token.cells.length; i++) { - row = []; - cells = this.token.cells[i]; - for (j = 0; j < cells.length; j++) { - row.push(React.DOM.td( - this.token.align[j] - ? {style: {textAlign: this.token.align[j]}} - : null, - this.inline.output(cells[j]) - )); - } - body.push(React.DOM.tr(null, row)); - } - table.push(React.DOM.thead(null, body)); - - return React.DOM.table(null, table); - } - case 'blockquote_start': { - var body = []; - - while (this.next().type !== 'blockquote_end') { - body.push(this.tok()); - } - - return React.DOM.blockquote(null, body); - } - case 'list_start': { - var type = this.token.ordered ? 'ol' : 'ul' - , body = []; - - while (this.next().type !== 'list_end') { - body.push(this.tok()); - } - - return React.DOM[type](null, body); - } - case 'list_item_start': { - var body = []; - - while (this.next().type !== 'list_item_end') { - body.push(this.token.type === 'text' - ? this.parseText() - : this.tok()); - } - - return React.DOM.li(null, body); - } - case 'loose_item_start': { - var body = []; - - while (this.next().type !== 'list_item_end') { - body.push(this.tok()); - } - - return React.DOM.li(null, body); - } - case 'html': { - return !this.token.pre && !this.options.pedantic - ? this.inline.output(this.token.text) - : this.token.text; - } - case 'paragraph': { - return this.options.paragraphFn - ? this.options.paragraphFn.call(null, this.inline.output(this.token.text)) - : React.DOM.p(null, this.inline.output(this.token.text)); - } - case 'text': { - return this.options.paragraphFn - ? this.options.paragraphFn.call(null, this.parseText()) - : React.DOM.p(null, this.parseText()); - } - } -}; - -/** - * Helpers - */ - -function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function replace(regex, opt) { - regex = regex.source; - opt = opt || ''; - return function self(name, val) { - if (!name) return new RegExp(regex, opt); - val = val.source || val; - val = val.replace(/(^|[^\[])\^/g, '$1'); - regex = regex.replace(name, val); - return self; - }; -} - -function noop() {} -noop.exec = noop; - -function merge(obj) { - var i = 1 - , target - , key; - - for (; i < arguments.length; i++) { - target = arguments[i]; - for (key in target) { - if (Object.prototype.hasOwnProperty.call(target, key)) { - obj[key] = target[key]; - } - } - } - - return obj; -} - -/** - * Marked - */ - -function marked(src, opt, callback) { - if (callback || typeof opt === 'function') { - if (!callback) { - callback = opt; - opt = null; - } - - if (opt) opt = merge({}, marked.defaults, opt); - - var highlight = opt.highlight - , tokens - , pending - , i = 0; - - try { - tokens = Lexer.lex(src, opt) - } catch (e) { - return callback(e); - } - - pending = tokens.length; - - var done = function(hi) { - var out, err; - - if (hi !== true) { - delete opt.highlight; - } - - try { - out = Parser.parse(tokens, opt); - } catch (e) { - err = e; - } - - opt.highlight = highlight; - - return err - ? callback(err) - : callback(null, out); - }; - - if (!highlight || highlight.length < 3) { - return done(true); - } - - if (!pending) return done(); - - for (; i < tokens.length; i++) { - (function(token) { - if (token.type !== 'code') { - return --pending || done(); - } - return highlight(token.text, token.lang, function(err, code) { - if (code == null || code === token.text) { - return --pending || done(); - } - token.text = code; - token.escaped = true; - --pending || done(); - }); - })(tokens[i]); - } - - return; - } - try { - if (opt) opt = merge({}, marked.defaults, opt); - return Parser.parse(Lexer.lex(src, opt), opt); - } catch (e) { - e.message += '\nPlease report this to https://github.com/chjj/marked.'; - if ((opt || marked.defaults).silent) { - return [React.DOM.p(null, "An error occurred:"), - React.DOM.pre(null, e.message)]; - } - throw e; - } -} - -/** - * Options - */ - -marked.options = -marked.setOptions = function(opt) { - merge(marked.defaults, opt); - return marked; -}; - -marked.defaults = { - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - smartLists: false, - silent: false, - highlight: null, - langPrefix: 'lang-', - smartypants: false, - paragraphFn: null -}; - -/** - * Expose - */ - -marked.Parser = Parser; -marked.parser = Parser.parse; - -marked.Lexer = Lexer; -marked.lexer = Lexer.lex; - -marked.InlineLexer = InlineLexer; -marked.inlineLexer = InlineLexer.output; - -marked.parse = marked; - -var Marked = React.createClass({ - render: function() { - return this.props.children ? - React.DOM.div(null, marked(this.props.children, this.props)) : - null; - } -}); - -module.exports = Marked; diff --git a/website/core/Prism.js b/website/core/Prism.js deleted file mode 100644 index ef5d54f64a2..00000000000 --- a/website/core/Prism.js +++ /dev/null @@ -1,357 +0,0 @@ -/** - * Prism: Lightweight, robust, elegant syntax highlighting - * MIT license http://www.opensource.org/licenses/mit-license.php/ - * @author Lea Verou http://lea.verou.me - * - * @providesModule Prism - * @jsx React.DOM - */ - -var React = require('React'); - -var _ = { - util: { - type: function (o) { - return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; - }, - - // Deep clone a language definition (e.g. to extend it) - clone: function (o) { - var type = _.util.type(o); - - switch (type) { - case 'Object': - var clone = {}; - - for (var key in o) { - if (o.hasOwnProperty(key)) { - clone[key] = _.util.clone(o[key]); - } - } - - return clone; - - case 'Array': - return o.slice(); - } - - return o; - } - }, - - languages: { - extend: function (id, redef) { - var lang = _.util.clone(_.languages[id]); - - for (var key in redef) { - lang[key] = redef[key]; - } - - return lang; - }, - - // Insert a token before another token in a language literal - insertBefore: function (inside, before, insert, root) { - root = root || _.languages; - var grammar = root[inside]; - var ret = {}; - - for (var token in grammar) { - - if (grammar.hasOwnProperty(token)) { - - if (token == before) { - - for (var newToken in insert) { - - if (insert.hasOwnProperty(newToken)) { - ret[newToken] = insert[newToken]; - } - } - } - - ret[token] = grammar[token]; - } - } - - return root[inside] = ret; - }, - - // Traverse a language definition with Depth First Search - DFS: function(o, callback) { - for (var i in o) { - callback.call(o, i, o[i]); - - if (_.util.type(o) === 'Object') { - _.languages.DFS(o[i], callback); - } - } - } - }, - - tokenize: function(text, grammar) { - var Token = _.Token; - - var strarr = [text]; - - var rest = grammar.rest; - - if (rest) { - for (var token in rest) { - grammar[token] = rest[token]; - } - - delete grammar.rest; - } - - tokenloop: for (var token in grammar) { - if(!grammar.hasOwnProperty(token) || !grammar[token]) { - continue; - } - - var pattern = grammar[token], - inside = pattern.inside, - lookbehind = !!pattern.lookbehind, - lookbehindLength = 0; - - pattern = pattern.pattern || pattern; - - for (var i=0; i text.length) { - // Something went terribly wrong, ABORT, ABORT! - break tokenloop; - } - - if (str instanceof Token) { - continue; - } - - pattern.lastIndex = 0; - - var match = pattern.exec(str); - - if (match) { - if(lookbehind) { - lookbehindLength = match[1].length; - } - - var from = match.index - 1 + lookbehindLength, - match = match[0].slice(lookbehindLength), - len = match.length, - to = from + len, - before = str.slice(0, from + 1), - after = str.slice(to + 1); - - var args = [i, 1]; - - if (before) { - args.push(before); - } - - var wrapped = new Token(token, inside? _.tokenize(match, inside) : match); - - args.push(wrapped); - - if (after) { - args.push(after); - } - - Array.prototype.splice.apply(strarr, args); - } - } - } - - return strarr; - }, - - hooks: { - all: {}, - - add: function (name, callback) { - var hooks = _.hooks.all; - - hooks[name] = hooks[name] || []; - - hooks[name].push(callback); - }, - - run: function (name, env) { - var callbacks = _.hooks.all[name]; - - if (!callbacks || !callbacks.length) { - return; - } - - for (var i=0, callback; callback = callbacks[i++];) { - callback(env); - } - } - } -}; - -var Token = _.Token = function(type, content) { - this.type = type; - this.content = content; -}; - -Token.reactify = function(o, key) { - if (typeof o == 'string') { - return o; - } - - if (Array.isArray(o)) { - return o.map(function(element, i) { - return Token.reactify(element, i); - }); - } - - var attributes = { - className: 'token ' + o.type, - key: key - }; - if (o.type == 'comment') { - attributes.spellCheck = true; - } - - return React.DOM.span(attributes, Token.reactify(o.content)); -}; - -_.languages.markup = { - 'comment': /<!--[\w\W]*?-->/g, - 'prolog': /<\?.+?\?>/, - 'doctype': /<!DOCTYPE.+?>/, - 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, - 'tag': { - pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi, - inside: { - 'tag': { - pattern: /^<\/?[\w:-]+/i, - inside: { - 'punctuation': /^<\/?/, - 'namespace': /^[\w-]+?:/ - } - }, - 'attr-value': { - pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi, - inside: { - 'punctuation': /=|>|"/g - } - }, - 'punctuation': /\/?>/g, - 'attr-name': { - pattern: /[\w:-]+/g, - inside: { - 'namespace': /^[\w-]+?:/ - } - } - - } - }, - 'entity': /&#?[\da-z]{1,8};/gi -}; - -_.languages.css = { - 'comment': /\/\*[\w\W]*?\*\//g, - 'atrule': { - pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi, - inside: { - 'punctuation': /[;:]/g - } - }, - 'url': /url\((["']?).*?\1\)/gi, - 'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g, - 'property': /(\b|\B)[\w-]+(?=\s*:)/ig, - 'string': /("|')(\\?.)*?\1/g, - 'important': /\B!important\b/gi, - 'ignore': /&(lt|gt|amp);/gi, - 'punctuation': /[\{\};:]/g -}; - -_.languages.insertBefore('markup', 'tag', { - 'style': { - pattern: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig, - inside: { - 'tag': { - pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig, - inside: _.languages.markup.tag.inside - }, - rest: _.languages.css - } - } -}); - -_.languages.clike = { - 'comment': { - pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g, - lookbehind: true - }, - 'string': /("|')(\\?.)*?\1/g, - 'class-name': { - pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig, - lookbehind: true, - inside: { - punctuation: /(\.|\\)/ - } - }, - 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g, - 'boolean': /\b(true|false)\b/g, - 'function': { - pattern: /[a-z0-9_]+\(/ig, - inside: { - punctuation: /\(/ - } - }, - 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, - 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g, - 'ignore': /&(lt|gt|amp);/gi, - 'punctuation': /[{}[\];(),.:]/g -}; - -_.languages.javascript = _.languages.extend('clike', { - 'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g, - 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g -}); - -_.languages.insertBefore('javascript', 'keyword', { - 'regex': { - pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g, - lookbehind: true - } -}); - -_.languages.insertBefore('markup', 'tag', { - 'script': { - pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig, - inside: { - 'tag': { - pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig, - inside: _.languages.markup.tag.inside - }, - rest: _.languages.javascript - } - } -}); - -var Prism = React.createClass({ - statics: { - _: _ - }, - getDefaultProps: function() { - return { - language: 'javascript' - }; - }, - render: function() { - var grammar = _.languages[this.props.language]; - return ( -
- {Token.reactify(_.tokenize(this.props.children, grammar))} -
- ); - } -}); - -module.exports = Prism; diff --git a/website/core/Site.js b/website/core/Site.js deleted file mode 100644 index b9a770ce1bb..00000000000 --- a/website/core/Site.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @providesModule Site - * @jsx React.DOM - */ - -var React = require('React'); -var HeaderLinks = require('HeaderLinks'); - -var Site = React.createClass({ - render: function() { - return ( - - - - - React Native | Build Native Apps Using React - - - - - - - - - - - - - - - -
- - - {this.props.children} - -
-
© 2015 Facebook Inc.
-
-
- -
-