diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..deec4eb5fa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,100 @@
+*AppPackages*
+*BundleArtifacts*
+*ReactAssets*
+
+#OS junk files
+[Tt]humbs.db
+*.DS_Store
+
+#Visual Studio files
+*.[Oo]bj
+*.user
+*.aps
+*.pch
+*.vspscc
+*.vssscc
+*_i.c
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.[Cc]ache
+*.ilk
+*.log
+*.lib
+*.sbr
+*.sdf
+*.opensdf
+*.opendb
+*.unsuccessfulbuild
+ipch/
+[Oo]bj/
+[Bb]in
+[Dd]ebug*/
+[Rr]elease*/
+Ankh.NoLoad
+
+#MonoDevelop
+*.pidb
+*.userprefs
+
+#Tooling
+_ReSharper*/
+*.resharper
+[Tt]est[Rr]esult*
+*.sass-cache
+
+#Project files
+[Bb]uild/
+
+#Subversion files
+.svn
+
+# Office Temp Files
+~$*
+
+# vim Temp Files
+*~
+
+#NuGet
+packages/
+*.nupkg
+
+#ncrunch
+*ncrunch*
+*crunch*.local.xml
+
+# visual studio database projects
+*.dbmdl
+
+#Test files
+*.testsettings
+
+#Other files
+*.DotSettings
+.vs/
+*project.lock.json
+
+#JavaScript files
+*.jsbundle
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Build results
+[Dd]ebugPublic/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Ll]og/
diff --git a/RNTester.sln b/RNTester.sln
new file mode 100644
index 0000000000..59411fd22a
--- /dev/null
+++ b/RNTester.sln
@@ -0,0 +1,121 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RNTesterApp", "windows\RNTester\RNTesterApp.csproj", "{283F872F-7145-45A4-8EE0-4A6DB9FB2628}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative", "..\ReactWindows\ReactNative\ReactNative.csproj", "{C7673AD5-E3AA-468C-A5FD-FA38154E205C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChakraBridge", "..\ReactWindows\ChakraBridge\ChakraBridge.vcxproj", "{4B72C796-16D5-4E3A-81C0-3E36F531E578}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ReactNative.Shared", "..\ReactWindows\ReactNative.Shared\ReactNative.Shared.shproj", "{EEA8B852-4D07-48E1-8294-A21AB5909FE5}"
+EndProject
+Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{c7673ad5-e3aa-468c-a5fd-fa38154e205c}*SharedItemsImports = 4
+ ..\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{eea8b852-4d07-48e1-8294-a21ab5909fe5}*SharedItemsImports = 13
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ DebugBundle|ARM = DebugBundle|ARM
+ DebugBundle|x64 = DebugBundle|x64
+ DebugBundle|x86 = DebugBundle|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ ReleaseBundle|ARM = ReleaseBundle|ARM
+ ReleaseBundle|x64 = ReleaseBundle|x64
+ ReleaseBundle|x86 = ReleaseBundle|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|ARM.ActiveCfg = Debug|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|ARM.Build.0 = Debug|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|ARM.Deploy.0 = Debug|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|x64.ActiveCfg = Debug|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|x64.Build.0 = Debug|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|x64.Deploy.0 = Debug|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|x86.ActiveCfg = Debug|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|x86.Build.0 = Debug|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Debug|x86.Deploy.0 = Debug|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|ARM.ActiveCfg = Debug|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|ARM.Build.0 = Debug|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|ARM.Deploy.0 = Debug|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|x64.ActiveCfg = Debug|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|x64.Build.0 = Debug|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|x64.Deploy.0 = Debug|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|x86.ActiveCfg = DebugBundle|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|x86.Build.0 = DebugBundle|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.DebugBundle|x86.Deploy.0 = DebugBundle|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|ARM.ActiveCfg = Release|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|ARM.Build.0 = Release|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|ARM.Deploy.0 = Release|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|x64.ActiveCfg = Release|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|x64.Build.0 = Release|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|x64.Deploy.0 = Release|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|x86.ActiveCfg = Release|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|x86.Build.0 = Release|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.Release|x86.Deploy.0 = Release|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|ARM.ActiveCfg = Release|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|ARM.Build.0 = Release|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|ARM.Deploy.0 = Release|ARM
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|x64.ActiveCfg = Release|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|x64.Build.0 = Release|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|x64.Deploy.0 = Release|x64
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|x86.ActiveCfg = ReleaseBundle|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|x86.Build.0 = ReleaseBundle|x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}.ReleaseBundle|x86.Deploy.0 = ReleaseBundle|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.ActiveCfg = Debug|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.Build.0 = Debug|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.ActiveCfg = Debug|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.Build.0 = Debug|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.ActiveCfg = Debug|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.Build.0 = Debug|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.DebugBundle|ARM.ActiveCfg = Debug|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.DebugBundle|ARM.Build.0 = Debug|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.DebugBundle|x64.ActiveCfg = Debug|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.DebugBundle|x64.Build.0 = Debug|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.DebugBundle|x86.ActiveCfg = Debug|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.DebugBundle|x86.Build.0 = Debug|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.ActiveCfg = Release|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.Build.0 = Release|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.ActiveCfg = Release|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.Build.0 = Release|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.ActiveCfg = Release|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.Build.0 = Release|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.ReleaseBundle|ARM.ActiveCfg = Release|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.ReleaseBundle|ARM.Build.0 = Release|ARM
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.ReleaseBundle|x64.ActiveCfg = Release|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.ReleaseBundle|x64.Build.0 = Release|x64
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.ReleaseBundle|x86.ActiveCfg = Release|x86
+ {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.ReleaseBundle|x86.Build.0 = Release|x86
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|ARM.ActiveCfg = Debug|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|ARM.Build.0 = Debug|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x64.ActiveCfg = Debug|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x64.Build.0 = Debug|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x86.ActiveCfg = Debug|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x86.Build.0 = Debug|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.DebugBundle|ARM.ActiveCfg = Debug|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.DebugBundle|ARM.Build.0 = Debug|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.DebugBundle|x64.ActiveCfg = Debug|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.DebugBundle|x64.Build.0 = Debug|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.DebugBundle|x86.ActiveCfg = Debug|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.DebugBundle|x86.Build.0 = Debug|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|ARM.ActiveCfg = Release|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|ARM.Build.0 = Release|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x64.ActiveCfg = Release|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x64.Build.0 = Release|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x86.ActiveCfg = Release|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x86.Build.0 = Release|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.ReleaseBundle|ARM.ActiveCfg = Release|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.ReleaseBundle|ARM.Build.0 = Release|ARM
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.ReleaseBundle|x64.ActiveCfg = Release|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.ReleaseBundle|x64.Build.0 = Release|x64
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.ReleaseBundle|x86.ActiveCfg = Release|Win32
+ {4B72C796-16D5-4E3A-81C0-3E36F531E578}.ReleaseBundle|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/js/BorderExample.js b/js/BorderExample.js
index 1dea4656dc..eed1be4000 100644
--- a/js/BorderExample.js
+++ b/js/BorderExample.js
@@ -146,6 +146,7 @@ exports.examples = [
{
title: 'Equal-Width Borders',
description: 'borderWidth & border*Color',
+ platforms: ['android', 'ios'],
render() {
return ;
}
@@ -160,6 +161,7 @@ exports.examples = [
{
title: 'Custom Borders',
description: 'border*Width & border*Color',
+ platforms: ['android', 'ios'],
render() {
return ;
}
@@ -209,6 +211,7 @@ exports.examples = [
{
title: 'Corner Radii',
description: 'borderTopLeftRadius & borderBottomRightRadius',
+ platforms: ['android', 'ios'],
render() {
return ;
}
@@ -224,6 +227,7 @@ exports.examples = [
{
title: 'CSS Trick - Triangle',
description: 'create a triangle by manipulating border colors and widths',
+ platforms: ['android', 'ios'],
render() {
return ;
}
diff --git a/js/FlipViewWindowsExample.windows.js b/js/FlipViewWindowsExample.windows.js
new file mode 100644
index 0000000000..c5f5113861
--- /dev/null
+++ b/js/FlipViewWindowsExample.windows.js
@@ -0,0 +1,252 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ */
+'use strict';
+
+var React = require('react');
+var ReactNative = require('react-native');
+var ReactWindows = require('react-native-windows');
+var {
+ Image,
+ StyleSheet,
+ Text,
+ TouchableWithoutFeedback,
+ TouchableOpacity,
+ View,
+} = ReactNative;
+var {FlipViewWindows} = ReactWindows;
+
+var PAGES = 5;
+var BGCOLOR = ['#fdc08e', '#fff6b9', '#99d1b7', '#dde5fe', '#f79273'];
+var IMAGE_URIS = [
+ 'http://apod.nasa.gov/apod/image/1410/20141008tleBaldridge001h990.jpg',
+ 'http://apod.nasa.gov/apod/image/1409/volcanicpillar_vetter_960.jpg',
+ 'http://apod.nasa.gov/apod/image/1409/m27_snyder_960.jpg',
+ 'http://apod.nasa.gov/apod/image/1409/PupAmulti_rot0.jpg',
+ 'http://apod.nasa.gov/apod/image/1510/lunareclipse_27Sep_beletskycrop4.jpg',
+];
+
+class LikeCount extends React.Component {
+ state = {
+ likes: 7,
+ };
+
+ onClick = () => {
+ this.setState({likes: this.state.likes + 1});
+ };
+
+ render() {
+ var thumbsUp = '\uD83D\uDC4D';
+ return (
+
+
+
+ {thumbsUp + ' Like'}
+
+
+
+ {this.state.likes + ' likes'}
+
+
+ );
+ }
+}
+
+class Button extends React.Component {
+ _handlePress = () => {
+ if (this.props.enabled && this.props.onPress) {
+ this.props.onPress();
+ }
+ };
+
+ render() {
+ return (
+
+
+ {this.props.text}
+
+
+ );
+ }
+}
+
+class ProgressBar extends React.Component {
+ render() {
+ var fractionalPosition = (this.props.progress.position + this.props.progress.offset);
+ var progressBarSize = (fractionalPosition / (PAGES - 1)) * this.props.size;
+ return (
+
+
+
+ );
+ }
+}
+
+class FlipViewWindowsExample extends React.Component {
+ static title = '';
+ static description = 'Container that allows to flip left and right between child views.';
+
+ state = {
+ page: 0,
+ animationsAreEnabled: true,
+ scrollEnabled: true,
+ progress: {
+ position: 0,
+ offset: 0,
+ },
+ };
+
+ onSelectionChange = (e) => {
+ this.setState({page: e.nativeEvent.position});
+ };
+
+ move = (delta) => {
+ var page = this.state.page + delta;
+ this.go(page);
+ };
+
+ go = (page) => {
+ this.flipView.setPage(page);
+ this.setState({page});
+ };
+
+ render() {
+ var pages = [];
+ for (var i = 0; i < PAGES; i++) {
+ var pageStyle = {
+ backgroundColor: BGCOLOR[i % BGCOLOR.length],
+ alignItems: 'center',
+ padding: 20,
+ };
+ pages.push(
+
+
+
+
+ );
+ }
+ var { page, animationsAreEnabled } = this.state;
+ return (
+
+ { this.flipView = flipView; }}>
+ {pages}
+
+
+ { animationsAreEnabled ?
+
+
+ 0} onPress={() => this.go(0)}/>
+ 0} onPress={() => this.move(-1)}/>
+ Page {page + 1} / {PAGES}
+
+ this.move(1)}/>
+ this.go(PAGES - 1)}/>
+
+
+ );
+ }
+}
+
+var styles = StyleSheet.create({
+ buttons: {
+ flexDirection: 'row',
+ height: 30,
+ backgroundColor: 'black',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ },
+ button: {
+ flex: 1,
+ width: 0,
+ margin: 5,
+ borderColor: 'gray',
+ borderWidth: 1,
+ backgroundColor: 'gray',
+ },
+ buttonDisabled: {
+ backgroundColor: 'black',
+ opacity: 0.5,
+ },
+ buttonText: {
+ color: 'white',
+ },
+ container: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ image: {
+ width: 300,
+ height: 200,
+ padding: 20,
+ },
+ likeButton: {
+ backgroundColor: 'rgba(0, 0, 0, 0.1)',
+ borderColor: '#333333',
+ borderWidth: 1,
+ borderRadius: 5,
+ flex: 1,
+ margin: 8,
+ padding: 8,
+ },
+ likeContainer: {
+ flexDirection: 'row',
+ },
+ likesText: {
+ flex: 1,
+ fontSize: 18,
+ alignSelf: 'center',
+ },
+ progressBarContainer: {
+ height: 10,
+ margin: 10,
+ borderColor: '#eeeeee',
+ borderWidth: 2,
+ },
+ progressBar: {
+ alignSelf: 'flex-start',
+ flex: 1,
+ backgroundColor: '#eeeeee',
+ },
+ flipView: {
+ flex: 1,
+ },
+});
+
+module.exports = FlipViewWindowsExample;
diff --git a/js/ImageExample.js b/js/ImageExample.js
index 580b988750..60a7ecfcad 100644
--- a/js/ImageExample.js
+++ b/js/ImageExample.js
@@ -1,4 +1,4 @@
-/**
+/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
@@ -593,7 +593,7 @@ exports.examples = [
/>
);
},
- platform: 'ios',
+ platforms: ['ios', 'windows'],
},
{
title: 'Cap Insets',
@@ -634,6 +634,7 @@ exports.examples = [
/>
);
},
+ platforms: ['android', 'ios'],
},
{
title: 'Bundled images',
diff --git a/js/ListViewWindowsExample.windows.js b/js/ListViewWindowsExample.windows.js
new file mode 100644
index 0000000000..6bb1532308
--- /dev/null
+++ b/js/ListViewWindowsExample.windows.js
@@ -0,0 +1,163 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+var React = require('react');
+var ReactNative = require('react-native');
+var {
+ Image,
+ ListView,
+ TouchableHighlight,
+ StyleSheet,
+ Text,
+ View,
+} = ReactNative;
+
+var RNTesterPage = require('./RNTesterPage');
+
+var ListViewSimpleExample = React.createClass({
+ statics: {
+ title: '',
+ description: 'Performant, scrollable list of data.'
+ },
+
+ getInitialState: function() {
+ var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
+ return {
+ dataSource: ds.cloneWithRows(this._genRows({})),
+ };
+ },
+
+ _pressData: ({}: {[key: number]: boolean}),
+
+ componentWillMount: function() {
+ this._pressData = {};
+ },
+
+ render: function() {
+ return (
+ '}
+ noSpacer={true}
+ noScroll={true}>
+
+
+ );
+ },
+
+ _renderRow: function(rowData: string, sectionID: number, rowID: number, highlightRow: (sectionID: number, rowID: number) => void) {
+ var rowHash = Math.abs(hashCode(rowData));
+ var imgSource = THUMB_URLS[rowHash % THUMB_URLS.length];
+ return (
+ {
+ this._pressRow(rowID);
+ highlightRow(sectionID, rowID);
+ }}>
+
+
+
+
+ {rowData + ' - ' + LOREM_IPSUM.substr(0, rowHash % 301 + 10)}
+
+
+
+
+ );
+ },
+
+ _genRows: function(pressData: {[key: number]: boolean}): Array {
+ var dataBlob = [];
+ for (var ii = 0; ii < 100; ii++) {
+ var pressedText = pressData[ii] ? ' (pressed)' : '';
+ dataBlob.push('Row ' + ii + pressedText);
+ }
+ return dataBlob;
+ },
+
+ _pressRow: function(rowID: number) {
+ this._pressData[rowID] = !this._pressData[rowID];
+ this.setState({dataSource: this.state.dataSource.cloneWithRows(
+ this._genRows(this._pressData)
+ )});
+ },
+
+ _renderSeperator: function(sectionID: number, rowID: number, adjacentRowHighlighted: bool) {
+ return (
+
+ );
+ }
+});
+
+var THUMB_URLS = [
+ require('./Thumbnails/like.png'),
+ require('./Thumbnails/dislike.png'),
+ require('./Thumbnails/call.png'),
+ require('./Thumbnails/fist.png'),
+ require('./Thumbnails/bandaged.png'),
+ require('./Thumbnails/flowers.png'),
+ require('./Thumbnails/heart.png'),
+ require('./Thumbnails/liking.png'),
+ require('./Thumbnails/party.png'),
+ require('./Thumbnails/poke.png'),
+ require('./Thumbnails/superlike.png'),
+ require('./Thumbnails/victory.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',
+ },
+ thumb: {
+ width: 64,
+ height: 64,
+ },
+ text: {
+ flex: 1,
+ },
+});
+
+module.exports = ListViewSimpleExample;
diff --git a/js/PickerWindowsExample.js b/js/PickerWindowsExample.js
new file mode 100644
index 0000000000..1883c0436e
--- /dev/null
+++ b/js/PickerWindowsExample.js
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+const React = require('react');
+const ReactNative = require('react-native');
+const StyleSheet = require('StyleSheet');
+const RNTesterBlock = require('RNTesterBlock');
+const RNTesterPage = require('RNTesterPage');
+
+const {
+ Picker,
+ Text,
+ TouchableWithoutFeedback,
+} = ReactNative;
+const Item = Picker.Item;
+
+const PickerExample = React.createClass({
+
+ statics: {
+ title: '',
+ description: 'Provides multiple options to choose from, using a dropdown menu.',
+ },
+
+ getInitialState: function() {
+ return {
+ selected1: 'key1',
+ selected2: 'key1',
+ selected3: 'key1',
+ color: 'red',
+ };
+ },
+
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Cannot change the value of this picker because it doesn't update selectedValue.
+
+
+
+
+
+
+
+
+
+
+ );
+ },
+
+ onValueChange: function(key: string, value: string) {
+ const newState = {};
+ newState[key] = value;
+ this.setState(newState);
+ },
+});
+
+var styles = StyleSheet.create({
+ picker: {
+ width: 100,
+ },
+});
+
+module.exports = PickerExample;
diff --git a/js/ProgressBarWindowsExample.windows.js b/js/ProgressBarWindowsExample.windows.js
new file mode 100644
index 0000000000..68adc1f17f
--- /dev/null
+++ b/js/ProgressBarWindowsExample.windows.js
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+var ProgressBar = require('ProgressBarWindows');
+var React = require('React');
+var RNTesterBlock = require('RNTesterBlock');
+var RNTesterPage = require('RNTesterPage');
+
+var TimerMixin = require('react-timer-mixin');
+
+var MovingBar = React.createClass({
+ mixins: [TimerMixin],
+
+ getInitialState: function() {
+ return {
+ progress: 0
+ };
+ },
+
+ componentDidMount: function() {
+ this.setInterval(
+ () => {
+ var progress = (this.state.progress + 0.1) % 100;
+ this.setState({progress: progress});
+ }, 10
+ );
+ },
+
+ render: function() {
+ return ;
+ },
+});
+
+var ProgressBarWindowsExample = React.createClass({
+
+ statics: {
+ title: '',
+ description: 'Visual indicator of progress of some operation. ' +
+ 'Shows a horizontal bar with either percent indeterminate progress.',
+ },
+
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ },
+});
+
+module.exports = ProgressBarWindowsExample;
diff --git a/js/RNTesterApp.windows.js b/js/RNTesterApp.windows.js
new file mode 100644
index 0000000000..892ceb32c3
--- /dev/null
+++ b/js/RNTesterApp.windows.js
@@ -0,0 +1,219 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @providesModule RNTesterApp
+ * @flow
+ */
+'use strict';
+
+const AppRegistry = require('AppRegistry');
+const AsyncStorage = require('AsyncStorage');
+const BackAndroid = require('BackAndroid');
+const Dimensions = require('Dimensions');
+const SplitViewWindows = require('SplitViewWindows');
+const Linking = require('Linking');
+const React = require('react');
+const StatusBar = require('StatusBar');
+const StyleSheet = require('StyleSheet');
+const ToolbarAndroid = require('ToolbarAndroid');
+const RNTesterActions = require('./RNTesterActions');
+const RNTesterExampleContainer = require('./RNTesterExampleContainer');
+const RNTesterExampleList = require('./RNTesterExampleList');
+const RNTesterList = require('./RNTesterList');
+const RNTesterNavigationReducer = require('./RNTesterNavigationReducer');
+const RNTesterHeaderWindows = require('./RNTesterHeaderWindows');
+const UIManager = require('UIManager');
+const URIActionMap = require('./URIActionMap');
+const View = require('View');
+
+import type { RNTesterNavigationState } from './RNTesterNavigationReducer';
+
+const DRAWER_WIDTH_LEFT = 56;
+
+type Props = {
+ exampleFromAppetizeParams: string,
+};
+
+const APP_STATE_KEY = 'RNTesterAppState.v2';
+
+class RNTesterApp extends React.Component {
+ props: Props;
+ state: RNTesterNavigationState;
+
+ componentWillMount() {
+ BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress.bind(this));
+ }
+
+ componentDidMount() {
+ Linking.getInitialURL().then((url) => {
+ AsyncStorage.getItem(APP_STATE_KEY, (err, storedString) => {
+ const exampleAction = URIActionMap(this.props.exampleFromAppetizeParams);
+ const urlAction = URIActionMap(url);
+ const launchAction = exampleAction || urlAction;
+ if (err || !storedString) {
+ const initialAction = launchAction || {type: 'InitialAction'};
+ this.setState(RNTesterNavigationReducer(null, initialAction));
+ return;
+ }
+ const storedState = JSON.parse(storedString);
+ if (launchAction) {
+ this.setState(RNTesterNavigationReducer(storedState, launchAction));
+ return;
+ }
+ this.setState(storedState);
+ });
+ });
+ }
+
+ render() {
+ if (!this.state) {
+ return null;
+ }
+ return (
+ {
+ this._overrideBackPressForPane = true;
+ }}
+ onPaneClose={() => {
+ this._overrideBackPressForPane = false;
+ }}
+ ref={(splitView) => { this.splitView = splitView; }}
+ renderPaneView={this._renderPaneContent}
+ statusBarBackgroundColor="#589c90">
+ {this._renderApp()}
+
+ );
+ }
+
+ _renderPaneContent = () => {
+ return (
+
+
+
+ );
+ };
+
+ _renderApp() {
+ const {
+ openExample,
+ } = this.state;
+
+ if (openExample) {
+ const ExampleModule = RNTesterList.Modules[openExample];
+ if (ExampleModule.external) {
+ return (
+ {
+ this._handleAction(RNTesterActions.Back());
+ }}
+ ref={(example) => { this._exampleRef = example; }}
+ />
+ );
+ } else if (ExampleModule) {
+ return (
+
+ this.splitView.openPane()}
+ title={ExampleModule.title}
+ style={styles.header}
+ />
+ { this._exampleRef = example; }}
+ />
+
+ );
+ }
+ }
+
+ return (
+
+ this.splitView.openPane()}
+ title="RNTester"
+ style={styles.header}
+ />
+
+
+ );
+ }
+
+ _handleAction = (action: Object): boolean => {
+ this.splitView && this.splitView.closePane();
+ const newState = RNTesterNavigationReducer(this.state, action);
+ if (this.state !== newState) {
+ this.setState(
+ newState,
+ () => AsyncStorage.setItem(APP_STATE_KEY, JSON.stringify(this.state))
+ );
+ return true;
+ }
+ return false;
+ };
+
+ _handleBackButtonPress() {
+ if (this._overrideBackPressForPane) {
+ // This hack is necessary because split view provides an imperative API
+ // with open and close methods. This code would be cleaner if the split
+ // view provided an `isOpen` prop and allowed us to pass a `onPaneClose` handler.
+ this.splitView && this.splitView.closePane();
+ return true;
+ }
+ if (
+ this._exampleRef &&
+ this._exampleRef.handleBackAction &&
+ this._exampleRef.handleBackAction()
+ ) {
+ return true;
+ }
+ return this._handleAction(RNTesterActions.Back());
+ };
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ toolbar: {
+ backgroundColor: '#E9EAED',
+ height: 56,
+ },
+ paneContentWrapper: {
+ flex: 1,
+ paddingTop: StatusBar.currentHeight,
+ backgroundColor: 'white',
+ },
+});
+
+AppRegistry.registerComponent('RNTesterApp', () => RNTesterApp);
+
+module.exports = RNTesterApp;
diff --git a/js/RNTesterExampleContainer.js b/js/RNTesterExampleContainer.js
index 635cd02147..c27bbfec35 100644
--- a/js/RNTesterExampleContainer.js
+++ b/js/RNTesterExampleContainer.js
@@ -20,13 +20,20 @@ const RNTesterPage = require('./RNTesterPage');
class RNTesterExampleContainer extends React.Component {
renderExample(example, i) {
// Filter platform-specific examples
- var {title, description, platform} = example;
+ var {title, description, platform, platforms} = example;
if (platform) {
if (Platform.OS !== platform) {
return null;
}
title += ' (' + platform + ' only)';
}
+ else if (platforms) {
+ if (platforms.indexOf(Platform.OS) < 0) {
+ return null;
+ }
+ title += ' (' + platforms.join(', ') + ' only)';
+ }
+
return (
+
+
+ Menu
+
+
+
+ {this.props.title}
+
+
+ );
+ }
+}
+
+var styles = StyleSheet.create({
+ header: {
+ flexDirection: 'row',
+ },
+ button: {
+ backgroundColor: 'blue',
+ height: 36,
+ padding: 8,
+ },
+ menu: {
+ color: 'white',
+ flex: 1,
+ fontSize: 15,
+ fontWeight: '500',
+ textAlign: 'center',
+ textAlignVertical: 'center',
+ },
+ titleContainer: {
+ alignItems: 'center',
+ flex: 1,
+ padding: 6,
+ },
+ title: {
+ fontSize: 17,
+ fontWeight: '500',
+ },
+});
+
+module.exports = RNTesterHeaderWindows;
diff --git a/js/RNTesterList.windows.js b/js/RNTesterList.windows.js
new file mode 100644
index 0000000000..d689ae8f15
--- /dev/null
+++ b/js/RNTesterList.windows.js
@@ -0,0 +1,205 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+export type RNTesterExample = {
+ key: string;
+ module: React.Component;
+};
+
+var ComponentExamples: Array = [
+ {
+ key: 'ActivityIndicatorExample',
+ module: require('./ActivityIndicatorExample'),
+ },
+ {
+ key: 'ButtonExample',
+ module: require('./ButtonExample'),
+ },
+ {
+ key: 'FlipViewWindowsExample',
+ module: require('./FlipViewWindowsExample'),
+ },
+ {
+ key: 'ImageExample',
+ module: require('./ImageExample'),
+ },
+ {
+ key: 'ListViewExample',
+ module: require('./ListViewWindowsExample'),
+ },
+ {
+ key: 'ListViewGridLayoutExample',
+ module: require('./ListViewGridLayoutExample'),
+ },
+ {
+ key: 'ListViewPagingExample',
+ module: require('./ListViewPagingExample'),
+ },
+ {
+ key: 'PickerWindowsExample',
+ module: require('./PickerWindowsExample'),
+ },
+ {
+ key: 'ProgressBarWindowsExample',
+ module: require('./ProgressBarWindowsExample'),
+ },
+ {
+ key: 'ScrollViewSimpleExample',
+ module: require('./ScrollViewSimpleExample'),
+ },
+ {
+ key: 'SliderExample',
+ module: require('./SliderExample'),
+ },
+ {
+ key: 'StatusBarExample',
+ module: require('./StatusBarExample'),
+ },
+ {
+ key: 'SwitchExample',
+ module: require('./SwitchExample'),
+ },
+ {
+ key: 'TextExample',
+ module: require('./TextExample'),
+ },
+ {
+ key: 'TextInputExample',
+ module: require('./TextInputExample'),
+ },
+ {
+ key: 'TouchableExample',
+ module: require('./TouchableExample'),
+ },
+ {
+ key: 'ViewExample',
+ module: require('./ViewExample'),
+ },
+ {
+ key: 'WebViewExample',
+ module: require('./WebViewExample'),
+ },
+];
+
+const APIExamples = [
+ {
+ key: 'AlertExample',
+ module: require('./AlertExample').AlertExample,
+ },
+ {
+ key: 'AnimatedExample',
+ module: require('./AnimatedExample'),
+ },
+ {
+ key: 'AppStateExample',
+ module: require('./AppStateExample'),
+ },
+ {
+ key: 'BorderExample',
+ module: require('./BorderExample'),
+ },
+ {
+ key: 'ClipboardExample',
+ module: require('./ClipboardExample'),
+ },
+ {
+ key: 'GeolocationExample',
+ module: require('./GeolocationExample'),
+ },
+ {
+ key: 'LayoutEventsExample',
+ module: require('./LayoutEventsExample'),
+ },
+ {
+ key: 'LinkingExample',
+ module: require('./LinkingExample'),
+ },
+ {
+ key: 'LayoutAnimationExample',
+ module: require('./LayoutAnimationExample'),
+ },
+ {
+ key: 'LayoutExample',
+ module: require('./LayoutExample'),
+ },
+ {
+ key: 'NativeAnimationsExample',
+ module: require('./NativeAnimationsExample'),
+ },
+ {
+ key: 'NetInfoExample',
+ module: require('./NetInfoExample'),
+ },
+ {
+ key: 'OrientationChangeExample',
+ module: require('./OrientationChangeExample'),
+ },
+ {
+ key: 'PanResponderExample',
+ module: require('./PanResponderExample'),
+ },
+ {
+ key: 'PointerEventsExample',
+ module: require('./PointerEventsExample'),
+ },
+ {
+ key: 'RTLExample',
+ module: require('./RTLExample'),
+ },
+ {
+ key: 'TimerExample',
+ module: require('./TimerExample'),
+ },
+ {
+ key: 'TransformExample',
+ module: require('./TransformExample'),
+ },
+ {
+ key: 'VibrationExample',
+ module: require('./VibrationExample'),
+ },
+ {
+ key: 'WebSocketExample',
+ module: require('./WebSocketExample'),
+ },
+ {
+ key: 'XHRExample',
+ module: require('./XHRExample'),
+ },
+];
+
+const Modules = {};
+
+APIExamples.concat(ComponentExamples).forEach(Example => {
+ Modules[Example.key] = Example.module;
+});
+
+const RNTesterList = {
+ APIExamples,
+ ComponentExamples,
+ Modules,
+};
+
+module.exports = RNTesterList;
diff --git a/js/TextExample.windows.js b/js/TextExample.windows.js
new file mode 100644
index 0000000000..43219ebcd4
--- /dev/null
+++ b/js/TextExample.windows.js
@@ -0,0 +1,467 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+var React = require('react');
+var ReactNative = require('react-native');
+var {
+ Image,
+ StyleSheet,
+ Text,
+ View,
+} = ReactNative;
+
+var Entity = React.createClass({
+ render: function() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
+});
+
+var AttributeToggler = React.createClass({
+ getInitialState: function() {
+ return {fontWeight: 'bold', fontSize: 15};
+ },
+ toggleWeight: function() {
+ this.setState({
+ fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold'
+ });
+ },
+ increaseSize: function() {
+ this.setState({
+ fontSize: this.state.fontSize + 1
+ });
+ },
+ render: function() {
+ var curStyle = {fontWeight: this.state.fontWeight, fontSize: this.state.fontSize};
+ return (
+
+
+ Tap the controls below to change attributes.
+
+
+ See how it will even work on this nested text
+
+
+ Toggle Weight
+
+
+ Increase Size
+
+
+ );
+ }
+});
+
+exports.title = '';
+exports.description = 'Base component for rendering styled text.';
+exports.displayName = 'TextExample';
+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: 'Padding',
+ render: function() {
+ return (
+
+ This text is indented by 10px padding on all sides.
+
+ );
+ },
+}, {
+ title: 'Font Family',
+ render: function() {
+ return (
+
+
+ Arial
+
+
+ Arial bold
+
+
+ Calibri
+
+
+ Calibri bold
+
+
+ Segoe UI
+
+
+ Segoe UI bold
+
+
+ Times New Roman
+
+
+ Times New Roman bold
+
+
+ Verdana
+
+
+ Verdana bold
+
+
+ );
+ },
+}, {
+ title: 'Font Size',
+ render: function() {
+ return (
+
+
+ Size 23
+
+
+ Size 8
+
+
+ );
+ },
+}, {
+ title: 'Color',
+ render: function() {
+ return (
+
+
+ Red color
+
+
+ Blue color
+
+
+ );
+ },
+}, {
+ title: 'Background color',
+ render: function() {
+ return (
+
+
+ Red background,
+
+ {' '}blue background,
+
+ {' '}inherited blue background,
+
+ {' '}nested green background.
+
+
+
+
+
+
+
+ Red background,
+
+
+
+ {' '}blue background,
+
+
+
+ {' '}inherited blue background,
+
+
+
+ {' '}nested green background.
+
+
+
+
+
+
+
+ );
+ },
+}, {
+ title: 'Font Weight',
+ render: function() {
+ return (
+
+
+ Move fast and be ultralight
+
+
+ Move fast and be light
+
+
+ Move fast and be normal
+
+
+ Move fast and be bold
+
+
+ Move fast and be ultrabold
+
+
+ );
+ },
+}, {
+ title: 'Font Style',
+ render: function() {
+ return (
+
+
+ Normal text
+
+
+ Italic text
+
+
+ );
+ },
+}, {
+ 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)
+
+ )
+
+ )
+
+
+ (opacity
+
+ (is inherited
+
+ (and accumulated
+
+ (and also applies to the background)
+
+ )
+
+ )
+
+ )
+
+
+ Entity Name
+
+
+ );
+ },
+}, {
+ title: 'Text Decoration',
+ render: function() {
+ return (
+
+
+ Solid underline
+
+
+ None textDecoration
+
+
+ Solid line-through
+
+
+ Both underline and line-through
+
+
+ Mixed text with underline and line-through text nodes
+
+
+ );
+ },
+}, {
+ title: 'Text Align',
+ render: function() {
+ return (
+
+
+ auto (default) - english LTR
+
+
+ أحب اللغة العربية auto (default) - arabic RTL
+
+
+ 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: 'Letter Spacing',
+ render: function() {
+ return (
+
+
+ letterSpacing = 0
+
+
+ letterSpacing = 2
+
+
+ letterSpacing = 9
+
+
+ letterSpacing = -1
+
+
+ );
+ },
+}, {
+ title: 'Unicode',
+ render: function() {
+ return (
+
+
+
+ 星际争霸是世界上最好的游戏。
+
+
+
+
+ 星际争霸是世界上最好的游戏。
+
+
+
+
+ 星际争霸是世界上最好的游戏。
+
+
+
+
+ 星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。
+
+
+
+ )
+ }
+}, {
+ title: 'Spaces',
+ render: function() {
+ return (
+
+ A {'generated'} {' '} {'string'} and some spaces
+
+ );
+ },
+}, {
+ title: 'Line Height',
+ render: function() {
+ return (
+
+
+ 35 - Holisticly formulate inexpensive ideas before best-of-breed benefits. Continually expedite magnetic potentialities rather than client-focused interfaces.
+
+
+ 35 - Holisticly formulate inexpensive ideas before best-of-breed benefits. Continually expedite magnetic potentialities rather than client-focused interfaces.
+
+
+ 100 - Holisticly formulate inexpensive ideas before best-of-breed benefits. Continually expedite magnetic potentialities rather than client-focused interfaces.
+
+
+ 100 - Holisticly formulate inexpensive ideas before best-of-breed benefits. Continually expedite magnetic potentialities rather than client-focused interfaces.
+
+
+ );
+ },
+}, {
+ title: 'Empty Text',
+ description: 'It\'s ok to have Text with zero or null children.',
+ render: function() {
+ return (
+
+ );
+ },
+}, {
+ title: 'numberOfLines attribute',
+ render: function() {
+ return (
+
+
+ Maximum of one line no matter now much I write here.
+ Maximum of one line no matter now much I write here.
+ 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.
+ Maximum of two lines no matter now much I write here.
+ Maximum of two lines no matter now much I write here.
+ 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.
+ No maximum lines specified no matter now much I write here.
+ No maximum lines specified no matter now much I write here.
+ No maximum lines specified no matter now much I write here.
+ No maximum lines specified no matter now much I write here.
+ No maximum lines specified no matter now much I write here.
+ No maximum lines specified no matter now much I write here.
+ If I keep writing it{"'"}ll just keep going and going
+
+
+ );
+ },
+}, {
+ title: 'Toggling Attributes',
+ render: function(): ReactElement {
+ return ;
+ },
+}];
+
+var styles = StyleSheet.create({
+ backgroundColorText: {
+ margin: 5,
+ marginBottom: 0,
+ backgroundColor: 'rgba(100, 100, 100, 0.3)'
+ },
+});
diff --git a/js/TextInputExample.windows.js b/js/TextInputExample.windows.js
new file mode 100644
index 0000000000..fec1d818e1
--- /dev/null
+++ b/js/TextInputExample.windows.js
@@ -0,0 +1,362 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+var React = require('react');
+var ReactNative = require('react-native');
+var {
+ Text,
+ TextInput,
+ View,
+ StyleSheet,
+} = ReactNative;
+
+var TextEventsExample = React.createClass({
+ getInitialState: function() {
+ return {
+ curText: '',
+ prevText: '',
+ prev2Text: '',
+ };
+ },
+
+ updateText: function(text) {
+ this.setState((state) => {
+ return {
+ curText: text,
+ prevText: state.curText,
+ prev2Text: state.prevText,
+ };
+ });
+ },
+
+ 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.singleLine}
+ />
+
+ {this.state.curText}{'\n'}
+ (prev: {this.state.prevText}){'\n'}
+ (prev2: {this.state.prev2Text})
+
+
+ );
+ }
+});
+
+class AutoExpandingTextInput extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {text: '', height: 0};
+ }
+ render() {
+ return (
+ {
+ this.setState({
+ text: event.nativeEvent.text,
+ height: event.nativeEvent.contentSize.height,
+ });
+ }}
+ style={[styles.default, {height: Math.max(35, this.state.height)}]}
+ value={this.state.text}
+ />
+ );
+ }
+}
+
+class RewriteExample extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {text: ''};
+ }
+ render() {
+ var limit = 20;
+ var remainder = limit - this.state.text.length;
+ var remainderColor = remainder > 5 ? 'blue' : 'red';
+ return (
+
+ {
+ text = text.replace(/ /g, '_');
+ this.setState({text});
+ }}
+ style={styles.default}
+ value={this.state.text}
+ />
+
+ {remainder}
+
+
+ );
+ }
+}
+
+class RewriteExampleInvalidCharacters extends React.Component {
+ state: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {text: ''};
+ }
+ render() {
+ return (
+
+ {
+ this.setState({text: text.replace(/\s/g, '')});
+ }}
+ style={styles.default}
+ value={this.state.text}
+ />
+
+ );
+ }
+}
+
+class ToggleDefaultPaddingExample extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {hasPadding: false};
+ }
+ render() {
+ return (
+
+
+ this.setState({hasPadding: !this.state.hasPadding})}>
+ Toggle padding
+
+
+ );
+ }
+}
+
+var styles = StyleSheet.create({
+ multiline: {
+ height: 60,
+ fontSize: 16,
+ marginBottom: 10,
+ },
+ eventLabel: {
+ margin: 3,
+ fontSize: 12,
+ },
+ singleLine: {
+ fontSize: 16,
+ },
+ singleLineWithHeightTextInput: {
+ height: 30,
+ },
+ hashtag: {
+ color: 'blue',
+ fontWeight: 'bold',
+ },
+});
+
+exports.title = '';
+exports.description = 'Single and multi-line text inputs.';
+exports.examples = [
+ {
+ title: 'Auto-focus',
+ render: function() {
+ return (
+
+ );
+ }
+ },
+ {
+ title: "Live Re-Write ( -> '_')",
+ render: function() {
+ return ;
+ }
+ },
+ {
+ title: 'Live Re-Write (no spaces allowed)',
+ render: function() {
+ return ;
+ }
+ },
+ {
+ title: 'Auto-correct',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Keyboard types',
+ render: function() {
+ var keyboardTypes = [
+ 'default',
+ 'url',
+ 'number-pad',
+ 'phone-pad',
+ 'name-phone-pad',
+ 'email-address',
+ 'decimal-pad',
+ 'web-search',
+ 'numeric',
+ ];
+ var examples = keyboardTypes.map((type) => {
+ return (
+
+ );
+ });
+ return {examples};
+ }
+ },
+ {
+ title: 'Event handling',
+ render: function(): ReactElement { return ; },
+ },
+ {
+ title: 'Colored input text',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Colored highlight/cursor for text input',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Clear and select',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Editable',
+ render: function() {
+ return (
+
+ );
+ }
+ },
+ {
+ title: 'Auto-expanding',
+ render: function() {
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Toggle Default Padding',
+ render: function(): ReactElement { return ; },
+ },
+];
diff --git a/js/TimerExample.js b/js/TimerExample.js
index 6f2705b70b..8e363f81e5 100644
--- a/js/TimerExample.js
+++ b/js/TimerExample.js
@@ -14,6 +14,7 @@
var React = require('react');
var ReactNative = require('react-native');
var {
+ Alert,
AlertIOS,
Platform,
ToastAndroid,
@@ -149,6 +150,8 @@ var TimerTester = React.createClass({
AlertIOS.alert(msg);
} else if (Platform.OS === 'android') {
ToastAndroid.show(msg, ToastAndroid.SHORT);
+ } else if (Platform.OS === 'windows') {
+ Alert.alert('Results', msg);
}
this._start = 0;
this.forceUpdate(() => { this._ii = 0; });
@@ -215,6 +218,7 @@ exports.examples = [
);
},
+ platforms: ['ios', 'android'],
},
{
title: 'this.setImmediate(fn)',
diff --git a/js/TouchableExample.js b/js/TouchableExample.js
index 838402dbf3..9322997057 100644
--- a/js/TouchableExample.js
+++ b/js/TouchableExample.js
@@ -121,6 +121,13 @@ exports.examples = [
},
platform: 'ios',
}, {
+ title: 'Pointer Type',
+ description: ' gesture events have pointer type information.',
+ render: function(): ReactElement {
+ return ;
+ },
+ platform: 'windows',
+ }, {
title: 'Touchable Hit Slop',
description: ' components accept hitSlop prop which extends the touch area ' +
'without changing the view bounds.',
@@ -250,6 +257,60 @@ class TouchableDelayEvents extends React.Component {
};
}
+class PointerType extends React.Component {
+ state = {
+ eventLog: [],
+ };
+
+ render() {
+ return (
+
+
+ this._appendEvent(e)}>
+
+ Press Me
+
+
+
+
+ {this.state.eventLog.map((e, ii) => {e})}
+
+
+ );
+ }
+
+ _appendEvent = (e) => {
+ var limit = 6;
+ var eventLog = this.state.eventLog.slice(0, limit - 1);
+ if (e.nativeEvent.pointerType === 'touch') {
+ eventLog.unshift('Touch');
+ } else if (e.nativeEvent.pointerType === 'mouse') {
+ var mouseClickType = e.nativeEvent.isLeftButton
+ ? 'left click'
+ : e.nativeEvent.isRightButton
+ ? 'right click'
+ : e.nativeEvent.isMiddleButton
+ ? 'middle button'
+ : e.nativeEvent.isHorizontalMouseWheel
+ ? 'scroll wheel'
+ : 'unknown';
+ eventLog.unshift('Mouse - ' + mouseClickType);
+ } else if (e.nativeEvent.pointerType === 'pen') {
+ var eraser = e.nativeEvent.isEraser ? ' eraser' : '';
+ var barrelButton = e.nativeEvent.isBarrelButtonPressed ? ' with barrel button pressed' : '';
+ eventLog.unshift('Pen' + eraser + barrelButton);
+ }
+
+ this.setState({eventLog});
+ };
+}
+
class ForceTouchExample extends React.Component {
state = {
force: 0,
diff --git a/js/XHRExample.windows.js b/js/XHRExample.windows.js
new file mode 100644
index 0000000000..ae6993ac43
--- /dev/null
+++ b/js/XHRExample.windows.js
@@ -0,0 +1,363 @@
+/**
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
+ *
+ * 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.
+ *
+ * @flow
+ */
+'use strict';
+
+var React = require('react');
+var ReactNative = require('react-native');
+var ReactWindows = require('react-native-windows');
+var {
+ StyleSheet,
+ Text,
+ TextInput,
+ TouchableHighlight,
+ View,
+} = ReactNative;
+var {ProgressBarWindows} = ReactWindows;
+
+var XHRExampleHeaders = require('./XHRExampleHeaders');
+var XHRExampleCookies = require('./XHRExampleCookies');
+var XHRExampleFetch = require('./XHRExampleFetch');
+var XHRExampleOnTimeOut = require('./XHRExampleOnTimeOut');
+
+// TODO t7093728 This is a simplified XHRExample.ios.js.
+// Once we have Camera roll, Toast, Intent (for opening URLs)
+// we should make this consistent with iOS.
+
+class Downloader extends React.Component {
+
+ xhr: XMLHttpRequest;
+ cancelled: boolean;
+
+ constructor(props) {
+ super(props);
+ this.cancelled = false;
+ this.state = {
+ status: '',
+ contentSize: 1,
+ downloaded: 0,
+ };
+ }
+
+ download() {
+ this.xhr && this.xhr.abort();
+
+ var xhr = this.xhr || new XMLHttpRequest();
+ xhr.onreadystatechange = () => {
+ if (xhr.readyState === xhr.HEADERS_RECEIVED) {
+ var contentSize = parseInt(xhr.getResponseHeader('Content-Length'), 10);
+ this.setState({
+ contentSize: contentSize,
+ downloaded: 0,
+ });
+ } else if (xhr.readyState === xhr.LOADING) {
+ this.setState({
+ downloaded: xhr.responseText.length,
+ });
+ } else if (xhr.readyState === xhr.DONE) {
+ if (this.cancelled) {
+ this.cancelled = false;
+ return;
+ }
+ if (xhr.status === 200) {
+ this.setState({
+ status: 'Download complete!',
+ });
+ } else if (xhr.status !== 0) {
+ this.setState({
+ status: 'Error: Server returned HTTP status of ' + xhr.status + ' ' + xhr.responseText,
+ });
+ } else {
+ this.setState({
+ status: 'Error: ' + xhr.responseText,
+ });
+ }
+ }
+ };
+ xhr.open('GET', 'http://www.gutenberg.org/cache/epub/100/pg100.txt');
+ // Avoid gzip so we can actually show progress
+ xhr.setRequestHeader('Accept-Encoding', '');
+ xhr.send();
+ this.xhr = xhr;
+
+ this.setState({status: 'Downloading...'});
+ }
+
+ componentWillUnmount() {
+ this.cancelled = true;
+ this.xhr && this.xhr.abort();
+ }
+
+ render() {
+ var button = this.state.status === 'Downloading...' ? (
+
+
+ ...
+
+
+ ) : (
+
+
+ Download 5MB Text File
+
+
+ );
+
+ return (
+
+ {button}
+
+ {this.state.status}
+
+ );
+ }
+}
+
+class FormUploader extends React.Component {
+
+ _isMounted: boolean;
+ _addTextParam: () => void;
+ _upload: () => void;
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isUploading: false,
+ uploadProgress: null,
+ textParams: [],
+ };
+ this._isMounted = true;
+ this._addTextParam = this._addTextParam.bind(this);
+ this._upload = this._upload.bind(this);
+ }
+
+ _addTextParam() {
+ var textParams = this.state.textParams;
+ textParams.push({name: '', value: ''});
+ this.setState({textParams});
+ }
+
+ componentWillUnmount() {
+ this._isMounted = false;
+ }
+
+ _onTextParamNameChange(index, text) {
+ var textParams = this.state.textParams;
+ textParams[index].name = text;
+ this.setState({textParams});
+ }
+
+ _onTextParamValueChange(index, text) {
+ var textParams = this.state.textParams;
+ textParams[index].value = text;
+ this.setState({textParams});
+ }
+
+ _upload() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', 'http://posttestserver.com/post.php');
+ xhr.onload = () => {
+ this.setState({isUploading: false});
+ if (xhr.status !== 200) {
+ console.log(
+ 'Upload failed',
+ 'Expected HTTP 200 OK response, got ' + xhr.status
+ );
+ return;
+ }
+ if (!xhr.responseText) {
+ console.log(
+ 'Upload failed',
+ 'No response payload.'
+ );
+ return;
+ }
+ var index = xhr.responseText.indexOf('http://www.posttestserver.com/');
+ if (index === -1) {
+ console.log(
+ 'Upload failed',
+ 'Invalid response payload.'
+ );
+ return;
+ }
+ var url = xhr.responseText.slice(index).split('\n')[0];
+ console.log('Upload successful: ' + url);
+ };
+ var formdata = new FormData();
+ this.state.textParams.forEach(
+ (param) => formdata.append(param.name, param.value)
+ );
+ if (xhr.upload) {
+ xhr.upload.onprogress = (event) => {
+ console.log('upload onprogress', event);
+ if (event.lengthComputable) {
+ this.setState({uploadProgress: event.loaded / event.total});
+ }
+ };
+ }
+ xhr.send(formdata);
+ this.setState({isUploading: true});
+ }
+
+ render() {
+ var textItems = this.state.textParams.map((item, index) => (
+
+
+ =
+
+
+ ));
+ var uploadButtonLabel = this.state.isUploading ? 'Uploading...' : 'Upload';
+ var uploadProgress = this.state.uploadProgress;
+ if (uploadProgress !== null) {
+ uploadButtonLabel += ' ' + Math.round(uploadProgress * 100) + '%';
+ }
+ var uploadButton = (
+
+ {uploadButtonLabel}
+
+ );
+ if (!this.state.isUploading) {
+ uploadButton = (
+
+ {uploadButton}
+
+ );
+ }
+ return (
+
+ {textItems}
+
+
+ Add a text param
+
+
+
+ {uploadButton}
+
+
+ );
+ }
+}
+
+exports.framework = 'React';
+exports.title = 'XMLHttpRequest';
+exports.description = 'Example that demonstrates upload and download requests ' +
+ 'using XMLHttpRequest.';
+exports.examples = [{
+ title: 'File Download',
+ render() {
+ return ;
+ }
+}, {
+ title: 'multipart/form-data Upload',
+ render() {
+ return ;
+ }
+}, {
+ title: 'Fetch Test',
+ render() {
+ return ;
+ }
+}, {
+ title: 'Headers',
+ render() {
+ return ;
+ }
+}, {
+ title: 'Cookies',
+ render() {
+ return ;
+ }
+}, {
+ title: 'Time Out Test',
+ render() {
+ return ;
+ }
+}];
+
+var styles = StyleSheet.create({
+ wrapper: {
+ borderRadius: 5,
+ marginBottom: 5,
+ },
+ button: {
+ backgroundColor: '#eeeeee',
+ padding: 8,
+ },
+ paramRow: {
+ flexDirection: 'row',
+ paddingVertical: 8,
+ alignItems: 'center',
+ borderBottomWidth: StyleSheet.hairlineWidth,
+ borderBottomColor: 'grey',
+ },
+ textButton: {
+ color: 'blue',
+ },
+ addTextParamButton: {
+ marginTop: 8,
+ },
+ textInput: {
+ flex: 1,
+ borderRadius: 3,
+ borderColor: 'grey',
+ borderWidth: 1,
+ paddingLeft: 8,
+ },
+ equalSign: {
+ paddingHorizontal: 4,
+ },
+ uploadButton: {
+ marginTop: 16,
+ },
+ uploadButtonBox: {
+ flex: 1,
+ paddingVertical: 12,
+ alignItems: 'center',
+ backgroundColor: 'blue',
+ borderRadius: 4,
+ },
+ uploadButtonLabel: {
+ color: 'white',
+ fontSize: 16,
+ fontWeight: '500',
+ },
+});
diff --git a/windows/RNTester/App.xaml b/windows/RNTester/App.xaml
new file mode 100644
index 0000000000..9031357659
--- /dev/null
+++ b/windows/RNTester/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/windows/RNTester/App.xaml.cs b/windows/RNTester/App.xaml.cs
new file mode 100644
index 0000000000..b7f8041ad3
--- /dev/null
+++ b/windows/RNTester/App.xaml.cs
@@ -0,0 +1,112 @@
+using ReactNative;
+using System;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace RNTesterApp
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ sealed partial class App : Application
+ {
+ private readonly ReactPage _reactPage;
+
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ this.Suspending += OnSuspending;
+ this.Resuming += OnResuming;
+
+ _reactPage = new MainPage();
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+ _reactPage.OnResume(Exit);
+
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ this.DebugSettings.EnableFrameRateCounter = true;
+ }
+
+ SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
+ AppViewBackButtonVisibility.Visible;
+#endif
+
+ Frame rootFrame = Window.Current.Content as Frame;
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ _reactPage.OnCreate(e.Arguments);
+
+ // Create a Frame to act as the navigation context and navigate to the first page
+ rootFrame = new Frame();
+
+ rootFrame.NavigationFailed += OnNavigationFailed;
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ }
+
+ if (rootFrame.Content == null)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ rootFrame.Content = _reactPage;
+ }
+
+ // Ensure the current window is active
+ Window.Current.Activate();
+ }
+
+ ///
+ /// Invoked when Navigation to a certain page fails
+ ///
+ /// The Frame which failed navigation
+ /// Details about the navigation failure
+ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+ }
+
+ ///
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ ///
+ /// The source of the suspend request.
+ /// Details about the suspend request.
+ private void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ _reactPage.OnSuspend();
+ }
+
+ ///
+ /// Invoked when application execution is being resumed.
+ ///
+ /// The source of the resume request.
+ /// Details about the resume request.
+ private void OnResuming(object sender, object e)
+ {
+ _reactPage.OnResume(Exit);
+ }
+ }
+}
diff --git a/windows/RNTester/Assets/LockScreenLogo.scale-200.png b/windows/RNTester/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 0000000000..735f57adb5
Binary files /dev/null and b/windows/RNTester/Assets/LockScreenLogo.scale-200.png differ
diff --git a/windows/RNTester/Assets/SplashScreen.scale-200.png b/windows/RNTester/Assets/SplashScreen.scale-200.png
new file mode 100644
index 0000000000..023e7f1fed
Binary files /dev/null and b/windows/RNTester/Assets/SplashScreen.scale-200.png differ
diff --git a/windows/RNTester/Assets/Square150x150Logo.scale-200.png b/windows/RNTester/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 0000000000..af49fec1a5
Binary files /dev/null and b/windows/RNTester/Assets/Square150x150Logo.scale-200.png differ
diff --git a/windows/RNTester/Assets/Square44x44Logo.scale-200.png b/windows/RNTester/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 0000000000..ce342a2ec8
Binary files /dev/null and b/windows/RNTester/Assets/Square44x44Logo.scale-200.png differ
diff --git a/windows/RNTester/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/windows/RNTester/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 0000000000..f6c02ce97e
Binary files /dev/null and b/windows/RNTester/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/windows/RNTester/Assets/StoreLogo.png b/windows/RNTester/Assets/StoreLogo.png
new file mode 100644
index 0000000000..7385b56c0e
Binary files /dev/null and b/windows/RNTester/Assets/StoreLogo.png differ
diff --git a/windows/RNTester/Assets/Wide310x150Logo.scale-200.png b/windows/RNTester/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 0000000000..288995b397
Binary files /dev/null and b/windows/RNTester/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/windows/RNTester/MainPage.cs b/windows/RNTester/MainPage.cs
new file mode 100644
index 0000000000..4cf829c2b0
--- /dev/null
+++ b/windows/RNTester/MainPage.cs
@@ -0,0 +1,59 @@
+using ReactNative;
+using ReactNative.Modules.Core;
+using ReactNative.Shell;
+using System.Collections.Generic;
+
+namespace RNTesterApp
+{
+ class MainPage : ReactPage
+ {
+ public override string MainComponentName
+ {
+ get
+ {
+ return "RNTesterApp";
+ }
+ }
+
+ public override string JavaScriptMainModuleName
+ {
+ get
+ {
+ return "RNTester/js/RNTesterApp.windows";
+ }
+ }
+
+#if BUNDLE
+ public override string JavaScriptBundleFile
+ {
+ get
+ {
+ return "ms-appx:///ReactAssets/index.windows.bundle";
+ }
+ }
+#endif
+
+ public override List Packages
+ {
+ get
+ {
+ return new List
+ {
+ new MainReactPackage(),
+ };
+ }
+ }
+
+ public override bool UseDeveloperSupport
+ {
+ get
+ {
+#if DEBUG
+ return true;
+#else
+ return false;
+#endif
+ }
+ }
+ }
+}
diff --git a/windows/RNTester/Package.appxmanifest b/windows/RNTester/Package.appxmanifest
new file mode 100644
index 0000000000..03377b09e1
--- /dev/null
+++ b/windows/RNTester/Package.appxmanifest
@@ -0,0 +1,29 @@
+
+
+
+
+
+ RNTesterApp
+ ericroz
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/windows/RNTester/Properties/AssemblyInfo.cs b/windows/RNTester/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..25ab411929
--- /dev/null
+++ b/windows/RNTester/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RNTesterApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RNTesterApp")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
\ No newline at end of file
diff --git a/windows/RNTester/Properties/Default.rd.xml b/windows/RNTester/Properties/Default.rd.xml
new file mode 100644
index 0000000000..80a960ce32
--- /dev/null
+++ b/windows/RNTester/Properties/Default.rd.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/windows/RNTester/RNTesterApp.csproj b/windows/RNTester/RNTesterApp.csproj
new file mode 100644
index 0000000000..97af936077
--- /dev/null
+++ b/windows/RNTester/RNTesterApp.csproj
@@ -0,0 +1,226 @@
+
+
+
+
+ Debug
+ x86
+ {283F872F-7145-45A4-8EE0-4A6DB9FB2628}
+ AppContainerExe
+ Properties
+ RNTesterApp
+ RNTesterApp
+ en-US
+ UAP
+ 10.0.10586.0
+ 10.0.10240.0
+ 14
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ RNTesterApp_TemporaryKey.pfx
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ bin\x86\ReleaseBundle\
+ TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;BUNDLE
+ true
+ ;2008
+ true
+ pdbonly
+ x86
+ false
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+ true
+
+
+ bin\ARM\ReleaseBundle\
+ TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;BUNDLE
+ true
+ ;2008
+ true
+ pdbonly
+ ARM
+ false
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+ true
+
+
+ bin\x64\ReleaseBundle\
+ TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;BUNDLE
+ true
+ ;2008
+ true
+ pdbonly
+ x64
+ false
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+ true
+
+
+ true
+ bin\x86\DebugBundle\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;BUNDLE
+ ;2008
+ true
+ full
+ x86
+ false
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+ true
+ bin\ARM\DebugBundle\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;BUNDLE
+ ;2008
+ true
+ full
+ ARM
+ false
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+ true
+ bin\x64\DebugBundle\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;BUNDLE
+ ;2008
+ true
+ full
+ x64
+ false
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+
+
+
+
+
+ App.xaml
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+ {c7673ad5-e3aa-468c-a5fd-fa38154e205c}
+ ReactNative
+
+
+
+
+ PreserveNewest
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/windows/RNTester/RNTester_TemporaryKey.pfx b/windows/RNTester/RNTester_TemporaryKey.pfx
new file mode 100644
index 0000000000..a9fac6cec4
Binary files /dev/null and b/windows/RNTester/RNTester_TemporaryKey.pfx differ
diff --git a/windows/RNTester/project.json b/windows/RNTester/project.json
new file mode 100644
index 0000000000..32d927479d
--- /dev/null
+++ b/windows/RNTester/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file