diff --git a/.gitignore b/.gitignore index 339728658..8b844237a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ node_modules *.log EndToEnd/testapp/build package_builds +website/translated_docs +website/build +website/yarn.lock +website/node_modules diff --git a/docs/3DCoordinatesAndTransforms.md b/docs/3DCoordinatesAndTransforms.md deleted file mode 100644 index 5174e98f3..000000000 --- a/docs/3DCoordinatesAndTransforms.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -id: coordinates-and-transforms -title: 3D Coordinates and Transforms -layout: docs -category: The Basics -permalink: docs/coordinates-and-transforms.html -next: project-configuration -previous: reactnative ---- - -Most React UI components are positioned automatically by the layout algorithm. -Such layouts typically have X axis pointing to the right and Y axis pointing down. -In other words, top left is (0, 0) and the bottom right is (width, height). - -This orientation behavior changes when we start positioning objects in 3D, which has its own coordinate system. - -### React VR Uses the OpenGL® 3D Coordinate System - -With React VR, we introduce a 3D coordinate system with the following effects: - -* UI components can still be laid out in 2D in a traditional way, but the **``** plane they are located in can be transformed and positioned in 3D space. -* Individual components can be transformed, moved or rotated 3D relative to their layout in their parent. -* Each individual component can be positioned absolutely in 3D space. - -React VR transformations use the right-handed OpenGL coordinate system. Right-handed means that when you use the thumb of your right hand to point in a positive direction along an axis, the curl of your fingers represent the direction of positive rotation. - -![](img/coordinates.jpg) - -Unlike in React, **the Y axis points up, not down.** This enables stronger overlap with the common coordinate systems of world space in assets and 3D world modeling. - -Also, **the Z axis points forwards towards the user**. Because the default view of the user starts out at the origin, this means they start out looking in the –Z direction. Take care to place objects at a negative distance, such as -3 meters, if they are to be visible at the start. Here is an example of how such a transformation can be specified through a **`transform`** style property. We discuss chaining transforms later in this topic. -``` - -``` - -### Units - -Distance and dimensional units are in meters. - -Rotation units are in degrees. - -### Transforms - -Transforms place the various components in 3D space. React VR extends the transform style of React to be fully 3D. Here is a code example for a mesh transform from one of our samples. - -``` - -``` - -Transforms are represented as an array of objects within a style. Transforms within this array are applied last to first, for example: - -``` - style={{ - transform: [ - {rotateZ : this.state.rotation}, - {translate: [0, 2, 0]}, - {scale : 0.01 }, - ], - }} -``` -In the above example, scale is applied first, then translate, then the Z-axis rotation. The end result moves the component 2 meters in the Y-axis and then rotates around the Z-axis. - -The result of the transform example below is quite different: - -``` - style={{ - transform: [ - {translate: [0, 2, 0]}, - {rotateZ : this.state.rotation}, - {scale : 0.01 }, - ], - }} -``` - -In this example, the component rotates around its own origin before being moved 2 meters. - -### Transform Properties - -Transform properties are described by a sequence of commands paired with values in the form: - -``` -transform: [ - {TRANSFORM_COMMAND: TRANSFORM_VALUE}, - ... - ] -``` - -**`TRANSFORM_COMMAND`** can be one of the following. - -**`matrix`** : This accepts a value which is an array of 16 numbers where - -* translation is stored as `[1,0,0,0, 0,1,0,0, 0,0,1,0, Tx,Ty,Tz,1]` -* a scale is represented by `[Sx,0,0,0, 0,Sy,0,0, 0,0,Sz,0, 0,0,0,1]` -* rotation can be represented the R values in `[R00,R01,R02,0, R10,R11,R12,0, R20,R21,R22,0, 0,0,0,1]` - -**`matrix`** is the most flexible way of handling transforms and allows developers to use their own JavaScript modules and still be able to interface with React components. - -For example, a matrix which scales all axes by `0.01` and then translates by `[3,2,1]` can be represented by: - -``` - style={{ - transform: [ - {matrix : [0.01,0,0,0, 0,0.01,0,0, 0,0,0.01,0, 3,2,0,1]}, - ], - }} -``` - -**`rotateX`** : This command accepts a single value which rotates around the X-axis by a number of degrees. If you imagine rotating the head of an avatar about the X-axis, this results in the avatar appearing to look up or down. This rotation is commonly referred to as *pitch*. The default units for numbers or string representations of a number are degrees. To specify radians instead, append **`rad`** to the string, for example, **`-0.5rad`**. - -``` - style={{ - transform: [ - {rotateX : 10}, - ], - }} -``` - -**`rotateY`** : This command accepts a single value which rotates around the Y-axis by a number of degrees. If you imagine rotating the head of an avatar about the Y-axis, this results in the avatar appearing to look left or right. This rotation is commonly referred to as *yaw*. The default units for numbers or string representations of a number are degrees. To specify radians instead, append **`rad`** to the string, for example, **`-0.5rad`**. - -``` - style={{ - transform: [ - {rotateY : 10}, - ], - }} -``` - -**`rotateZ`** : This command accepts a single value which rotates around the Z-axis by a number of degrees. If you imagine rotating the head of an avatar about the Z-axis, this results in the avatar appearing to tilt their head. This rotation is commonly referred to as *roll*. The default units for numbers or string representations of a number are degrees. To specify radians instead, append **`rad`** to the string, for example, **`-0.5rad`**. - -``` - style={{ - transform: [ - {rotateZ : 10}, - ], - }} -``` - -**`scale`**: The scale command can take a number or an array. If the value is a number, the scale is uniform across all axis. For example: - -``` - style={{ - transform: [ - {scale : 10}, - ], - }} -``` -If using an array, the scale values can be stipulated per axis. For example: -``` - style={{ - transform: [ - {scale : [0.01, 0.02, 0.03]}, - ], - }} -``` - -**`translate`**: The translate command takes an array of numbers specifying the translation in meters along each of the principal axis in the order of **`[X,Y,Z]`**. - -``` - style={{ - transform: [ - {translate : [0.01, 0.02, 0.03]}, - ], - }} -``` - -**`translateX`**: Allows a translation along only the X axis in units of meters. - -``` - style={{ - transform: [ - {translateX : 1}, - ], - }} -``` - -**`translateY`**: Allows a translation along only the Y axis in units of meters. - -``` - style={{ - transform: [ - {translateY : 1}, - ], - }} -``` - -**`translateZ`**: Allows a translation along only the Z axis in units of meters. - -``` - style={{ - transform: [ - {translateZ : 1}, - ], - }} -``` diff --git a/docs/Animations.md b/docs/Animations.md deleted file mode 100755 index bc4a2900a..000000000 --- a/docs/Animations.md +++ /dev/null @@ -1,313 +0,0 @@ ---- -id: animations -title: Animations -layout: docs -category: Guides -permalink: docs/animations.html -next: timers -previous: images ---- - -Fluid, meaningful animations are essential to the VR Web user experience. - -### Animated ### - -The **`Animated`** library is designed to make it easy to concisely express a -wide variety of interesting animation and interaction patterns while providing -efficient performance. **`Animated`** focuses on declarative relationships between -inputs and outputs, with configurable transforms in between, and simple -**start** and **stop** methods to control time-based animation execution. - -For example, a complete component with a simple spring bounce on mount looks -like this: - -``` -class Playground extends React.Component { - constructor(props) { - super(props); - this.state = { - bounceValue: new Animated.Value(0), - }; - } - render() { - return ( - - ); - } - componentDidMount() { - this.state.bounceValue.setValue(1.5); // Start large - Animated.spring( // Base: spring, decay, timing - this.state.bounceValue, // Animate `bounceValue` - { - toValue: 0.8, // Animate to smaller size - friction: 1, // Bouncier spring - } - ).start(); // Start the animation - } -} -``` - -In the code example, **`bounceValue`** is initialized as part of **`state`** in -the constructor and mapped to the scale transform on the image. Behind the -scenes, the code extracts the numeric value and uses it to set the scale. After -the component mounts, the code sets the scale to 1.5 and then starts a spring -animation on **`bounceValue`**. All the dependent mappings get updated on each -frame as the spring animates (in this case, only the scale). This is done in an -optimized way that is faster than calling **`setState`** and re-rendering. - -Because the entire configuration is -declarative, we could implement further optimizations that serialize the -configuration and run the animation on a high-priority thread. - -#### Core API - -Most everything you need hangs directly off the **`Animated`** module. This -includes: - -* two value types: -**`Value`** for single values and **`ValueXY`** for vectors. - -* three animation types: -**`spring`**, **`decay`**, and **`timing`**. - -* three component types: -**`View`**, **`Text`**, and **`Image`**. - -You can make any other component animated with -`Animated.createAnimatedComponent`. - -The three animation types can be used to create almost any animation curve you -want because each can be customized: - -* **`spring`**: Simple single-spring physics model that matches [Origami](https://facebook.github.io/origami/). - * **`friction`**: Controls "bounciness"/overshoot. Default 7. - * **`tension`**: Controls speed. Default 40. -* **`decay`**: Starts with an initial velocity and gradually slows to a stop. - * **`velocity`**: Initial velocity. Required. - * **`deceleration`**: Rate of decay. Default 0.997. -* **`timing`**: Maps time range to easing value. - * **`duration`**: Length of animation (milliseconds). Default 500. - * **`easing`**: Easing function to define a curve. See the **`Easing`** module for several - predefined functions. The iOS default is **`Easing.inOut(Easing.ease)`**. - * **`delay`**: Starts the animation after a delay (milliseconds). Default 0. - -Start animations by calling **`start()`**. There is a completion callback for -**`start()`** called when the animation ends. If the animation ends -because it finished running normally, the completion callback is invoked -with **`{finished: true}`**. But, if the animation ends because **`stop`** was called -on it before it could finish (for example, if it was interrupted by a -gesture or another animation), then it receives **`{finished: false}`**. - -#### Composing Animations - -Animations can also be composed with **`parallel`**, **`sequence`**, **`stagger`**, and -**`delay`**. Each simply takes an array of animations to execute as input and -automatically calls **start** and **stop** as appropriate. For example: - -```javascript -Animated.sequence([ // spring to start and twirl after decay finishes - Animated.decay(position, { // coast to a stop - velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release - deceleration: 0.997, - }), - Animated.parallel([ // after decay, in parallel: - Animated.spring(position, { - toValue: {x: 0, y: 0} // return to start - }), - Animated.timing(twirl, { // and twirl - toValue: 360, - }), - ]), -]).start(); // start the sequence group -``` - -If one animation is stopped or interrupted, the default behavior is to stop all -other animations in the group. Parallel has a **`stopTogether`** option -that can be set to **`false`** to change this behavior. - -#### Interpolation - -Another powerful part of the **`Animated`** API is the **`interpolate`** function. It -allows input ranges to map to different output ranges. For example, here is a -simple mapping to convert a 0-1 range to a 0-100 range: - -```javascript -value.interpolate({ - inputRange: [0, 1], - outputRange: [0, 100], -}); -``` - -**`interpolate`** supports multiple range segments as well, which is handy for -defining dead zones and other handy tricks. The following example creates a negation -relationship at -300 that goes to 0 at -100, to 1 at 0, to 0 at 100, -and then creates a dead-zone that remains at 0 for all input beyond that: - -```javascript -value.interpolate({ - inputRange: [-300, -100, 0, 100, 101], - outputRange: [300, 0, 1, 0, 0], -}); -``` - -Which would map like so: - -Input | Output -------|------- - -400| 450 - -300| 300 - -200| 150 - -100| 0 - -50| 0.5 - 0| 1 - 50| 0.5 - 100| 0 - 101| 0 - 200| 0 - -**`interpolate`** also supports mapping to strings, allowing you to animate colors as well as values with units. This example animates a rotation: - -```javascript -value.interpolate({ - inputRange: [0, 360], - outputRange: ['0deg', '360deg'] -}) -``` - -**`interpolation`** also supports arbitrary easing functions, many of which are -already implemented in the -[`Easing`](https://github.com/facebook/react-vr/blob/master/Libraries/Animation/Animated/Easing.js) -class. This includes quadratic, exponential, and bezier curves as well as functions -such as **`step`** and **`bounce`**. **`interpolation`** also has configurable behavior for -extrapolating the **`outputRange`**. You can set the extrapolation by setting the **`extrapolate`**, -**`extrapolateLeft`**, or **`extrapolateRight`** options. The default value is -**`extend`** but you can use **`clamp`** to prevent the output value from exceeding -**`outputRange`**. - -#### Tracking Dynamic Values - -Animated values can also track other values. Instead of setting the **`toValue`** of an -animation to a static value, you can set it to an animated value. For example, to -spring physics for an interaction like "Chat Heads", or to **`timing`** with -**`duration: 0`** for rigid/instant tracking. You can also compose dynamic values through -interpolation: - -```javascript -Animated.spring(follower, {toValue: leader}).start(); -Animated.timing(opacity, { - toValue: pan.x.interpolate({ - inputRange: [0, 300], - outputRange: [1, 0], - }), -}).start(); -``` - -**`ValueXY`** is a handy way to deal with 2D interactions such as panning or dragging. -It is a simple wrapper that contains two **`Animated.Value`** -instances and some helper functions that call through to them. **`ValueXY`** -is a drop-in replacement for **`Value`** in many cases. For example, in the code -snippet above, **`leader`** and **`follower`** could both be of type **`ValueXY`** and the x -and y values would track as you expect. - -#### Responding to the Current Animation Value - -You might have noticed there is no obvious way to read the current value in mid-animation. -Due to the effects of optimizations, only the native runtime knows the current value. -If you need to run JavaScript in response to the current -value, there are two approaches: - -- **`spring.stopAnimation(callback)`** stops the animation and invokes **`callback`** -with the final value - this is useful when making gesture transitions. -- **`spring.addListener(callback)`** invokes **`callback`** asynchronously while the -animation is running, providing a recent value. This is useful for triggering -state changes such as snapping a bobble to a new option as the user drags -it closer. This is the preferred method for large state changes as they are less -sensitive to a few frames of lag compared to continuous gestures like panning -which need to run at 60fps. - -### requestAnimationFrame - -**`requestAnimationFrame`** is a polyfill from the browser you might be -familiar with. It accepts a function as its only argument and calls that -function before the next repaint. It is an essential building block for -animations and underlies all of the JavaScript-based animation APIs. In -general, you shouldn't need to call this yourself - the animation APIs will -manage frame updates for you. - -#### A sidenote about setNativeProps - -**`setNativeProps`** allows us to modify properties of native-backed -components (components that are actually backed by native views, unlike -composite components) directly, without having to **`setState`** and -re-render the component hierarchy. - -We could use this in the Rebound example to update the scale. This -might be helpful if the component that we are updating is deeply nested -and hasn't been optimized with **`shouldComponentUpdate`**. - -``` -// Back inside of the App component, replace the scrollSpring listener -// in componentWillMount with this: -this._scrollSpring.addListener({ - onSpringUpdate: () => { - if (!this._photo) { return } - var v = this._scrollSpring.getCurrentValue(); - var newProps = {style: {transform: [{scaleX: v}, {scaleY: v}]}}; - this._photo.setNativeProps(newProps); - }, -}); - -// Lastly, we update the render function to no longer pass in the -// transform via style (avoid clashes when re-rendering) and to set the -// photo ref -render() { - return ( - - - this._photo = component} - source={{uri: "img/ReboundExample.png"}} - style={{width: 250, height: 200}} /> - - - ); -} -``` - -It would not make sense to use **`setNativeProps`** with react-tween-state -because the updated tween values are set on the state automatically by -the library. Rebound, on the other hand, gives us an updated value for -each frame with the **`onSpringUpdate`** function. - -If your animations are dropping frames and performing below 60 -frames per second, look into using **`setNativeProps`** or -**`shouldComponentUpdate`** to optimize them. - -### LayoutAnimation - -**`LayoutAnimation`** lets you globally configure **`create`** and **`update`** -animations used for all views in the next render/layout cycle. This is useful -for performing flexbox layout updates without needing to measure or calculate -specific properties to animate them directly. It is especially useful when -layout changes might affect ancestors. - -A good example is a "see more" expansion that increases the size of the -parent and pushes down the row below. Without using **`LayoutAnimation`**, this -would require explicit coordination between the components to synchronize their -animations. - -While **`LayoutAnimation`** is very powerful and can be quite useful, -it provides much less control than **`Animated`** and other animation libraries. -If you can't get **`LayoutAnimation`** to do what you want, you may need to use -another approach. - -See LayoutAnimation.js for more information. diff --git a/docs/Colors.md b/docs/Colors.md deleted file mode 100755 index 6ee3b160c..000000000 --- a/docs/Colors.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -id: colors -title: Colors -layout: docs -category: Guides -permalink: docs/colors.html -next: images -previous: layoutandtransforms ---- - -The following formats are supported: - - - `'#f0f'` (#rgb) - - `'#f0fc'` (#rgba) - - `'#ff00ff'` (#rrggbb) - - `'#ff00ff00'` (#rrggbbaa) - - `'rgb(255, 255, 255)'` - - `'rgba(255, 255, 255, 1.0)'` - - `'hsl(360, 100%, 100%)'` - - `'hsla(360, 100%, 100%, 1.0)'` - - `'transparent'` - - `'red'` - - `0xff00ff00` (0xrrggbbaa) - - -For the named colors, React Native follows the [CSS3 specification](http://www.w3.org/TR/css3-color/#svg-color): - -- aliceblue (#f0f8ff) -- antiquewhite (#faebd7) -- aqua (#00ffff) -- aquamarine (#7fffd4) -- azure (#f0ffff) -- beige (#f5f5dc) -- bisque (#ffe4c4) -- black (#000000) -- blanchedalmond (#ffebcd) -- blue (#0000ff) -- blueviolet (#8a2be2) -- brown (#a52a2a) -- burlywood (#deb887) -- cadetblue (#5f9ea0) -- chartreuse (#7fff00) -- chocolate (#d2691e) -- coral (#ff7f50) -- cornflowerblue (#6495ed) -- cornsilk (#fff8dc) -- crimson (#dc143c) -- cyan (#00ffff) -- darkblue (#00008b) -- darkcyan (#008b8b) -- darkgoldenrod (#b8860b) -- darkgray (#a9a9a9) -- darkgreen (#006400) -- darkgrey (#a9a9a9) -- darkkhaki (#bdb76b) -- darkmagenta (#8b008b) -- darkolivegreen (#556b2f) -- darkorange (#ff8c00) -- darkorchid (#9932cc) -- darkred (#8b0000) -- darksalmon (#e9967a) -- darkseagreen (#8fbc8f) -- darkslateblue (#483d8b) -- darkslategray (#2f4f4f) -- darkslategrey (#2f4f4f) -- darkturquoise (#00ced1) -- darkviolet (#9400d3) -- deeppink (#ff1493) -- deepskyblue (#00bfff) -- dimgray (#696969) -- dimgrey (#696969) -- dodgerblue (#1e90ff) -- firebrick (#b22222) -- floralwhite (#fffaf0) -- forestgreen (#228b22) -- fuchsia (#ff00ff) -- gainsboro (#dcdcdc) -- ghostwhite (#f8f8ff) -- gold (#ffd700) -- goldenrod (#daa520) -- gray (#808080) -- green (#008000) -- greenyellow (#adff2f) -- grey (#808080) -- honeydew (#f0fff0) -- hotpink (#ff69b4) -- indianred (#cd5c5c) -- indigo (#4b0082) -- ivory (#fffff0) -- khaki (#f0e68c) -- lavender (#e6e6fa) -- lavenderblush (#fff0f5) -- lawngreen (#7cfc00) -- lemonchiffon (#fffacd) -- lightblue (#add8e6) -- lightcoral (#f08080) -- lightcyan (#e0ffff) -- lightgoldenrodyellow (#fafad2) -- lightgray (#d3d3d3) -- lightgreen (#90ee90) -- lightgrey (#d3d3d3) -- lightpink (#ffb6c1) -- lightsalmon (#ffa07a) -- lightseagreen (#20b2aa) -- lightskyblue (#87cefa) -- lightslategray (#778899) -- lightslategrey (#778899) -- lightsteelblue (#b0c4de) -- lightyellow (#ffffe0) -- lime (#00ff00) -- limegreen (#32cd32) -- linen (#faf0e6) -- magenta (#ff00ff) -- maroon (#800000) -- mediumaquamarine (#66cdaa) -- mediumblue (#0000cd) -- mediumorchid (#ba55d3) -- mediumpurple (#9370db) -- mediumseagreen (#3cb371) -- mediumslateblue (#7b68ee) -- mediumspringgreen (#00fa9a) -- mediumturquoise (#48d1cc) -- mediumvioletred (#c71585) -- midnightblue (#191970) -- mintcream (#f5fffa) -- mistyrose (#ffe4e1) -- moccasin (#ffe4b5) -- navajowhite (#ffdead) -- navy (#000080) -- oldlace (#fdf5e6) -- olive (#808000) -- olivedrab (#6b8e23) -- orange (#ffa500) -- orangered (#ff4500) -- orchid (#da70d6) -- palegoldenrod (#eee8aa) -- palegreen (#98fb98) -- paleturquoise (#afeeee) -- palevioletred (#db7093) -- papayawhip (#ffefd5) -- peachpuff (#ffdab9) -- peru (#cd853f) -- pink (#ffc0cb) -- plum (#dda0dd) -- powderblue (#b0e0e6) -- purple (#800080) -- rebeccapurple (#663399) -- red (#ff0000) -- rosybrown (#bc8f8f) -- royalblue (#4169e1) -- saddlebrown (#8b4513) -- salmon (#fa8072) -- sandybrown (#f4a460) -- seagreen (#2e8b57) -- seashell (#fff5ee) -- sienna (#a0522d) -- silver (#c0c0c0) -- skyblue (#87ceeb) -- slateblue (#6a5acd) -- slategray (#708090) -- slategrey (#708090) -- snow (#fffafa) -- springgreen (#00ff7f) -- steelblue (#4682b4) -- tan (#d2b48c) -- teal (#008080) -- thistle (#d8bfd8) -- tomato (#ff6347) -- turquoise (#40e0d0) -- violet (#ee82ee) -- wheat (#f5deb3) -- white (#ffffff) -- whitesmoke (#f5f5f5) -- yellow (#ffff00) -- yellowgreen (#9acd32) diff --git a/docs/ComponentsPropsAndState.md b/docs/ComponentsPropsAndState.md deleted file mode 100644 index ab6626d69..000000000 --- a/docs/ComponentsPropsAndState.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -id: components-props-and-state -title: Components, Props and State -layout: docs -category: The Basics -permalink: docs/components-props-and-state.html -next: layout-and-style -previous: reactvr-overview ---- - -Components, props, and state are key concepts of the React Native framework -that are also valid for React VR. - - -### Props & State - -There are two types of data that control a component: props and state. Props are set by the parent and they are fixed throughout the lifetime of a component. For data that is going to change, we have to use state. - -#### Props - -Most components can be customized with different parameters when they are created. These creation parameters are called `props`. - -Your own components can also use props. This lets you make a single component that is used in many different places in your app, with slightly different properties in each place. Refer to `this.props` in your render function: - -``` -import React, { Component } from 'react'; -import { AppRegistry, asset, Pano, Text, View } from 'react-vr'; - -class Greeting extends Component { - render() { - return ( - Hello {this.props.name}! - ); - } -} - -class LotsOfGreetings extends Component { - render() { - return ( - - - - - - - - - ); - } -} - -AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings); -``` - -Using name as a prop lets us customize the Greeting component, so we can reuse that component for each of our greetings. - -#### State - -In general, you should initialize state in the constructor, and then call setState when you want to change it. - -``` -import React, { Component } from 'react'; -import { AppRegistry, asset, Pano, Text, View } from 'react-vr'; - -class Blink extends Component { - constructor(props) { - super(props); - this.state = {showText: true}; - - // Toggle the state every second - setInterval(() => { - this.setState({ showText: !this.state.showText }); - }, 1000); - } - - render() { - let display = this.state.showText ? this.props.text : ' '; - return ( - {display} - ); - } -} - -class BlinkApp extends Component { - render() { - return ( - - - - - - - - - - ); - } -} - -AppRegistry.registerComponent('BlinkApp', () => BlinkApp); -``` - -State works the same way as it does in React, so for more details on handling state, you can look at the [React.Component API](https://facebook.github.io/react/docs/react-component.html). diff --git a/docs/Debugging.md b/docs/Debugging.md deleted file mode 100755 index 297d68c5d..000000000 --- a/docs/Debugging.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: debugging -title: Debugging -layout: docs -category: Guides -permalink: docs/debugging.html -next: platform-specific-code -previous: timers ---- - -## Reloading JavaScript - -Instead of recompiling your app every time you make a change, you can reload -your app's JavaScript code instantly. To do so, press **F5** in the browser on -Windows, or **Command ⌘** + **R** on MacOS. - -If you have loaded your application in Hot Reloading mode, you should also see changes dynamically update as you save source files on your host machine. - -``` -http://localhost:8081/vr/?hotreload -``` - -For more information, see the Dev Tools section. - -## In-app Errors and Warnings - -Errors and warnings are displayed in the console of your web browser. - -### Errors - -Console logs and output as console.error. - -### Warnings - -Console logs and output as console.warn. - -## Chrome Developer Tools - -The browser developer tools can be used for debugging, this includes adding -breakpoints and inspecting runtime values. You will notice that the source is -presented as a single bundle of JavaScript. However, as the React Native -packager also supports sourcemaps, the original source code can also be used. diff --git a/docs/DevTools.md b/docs/DevTools.md deleted file mode 100644 index b90527ad3..000000000 --- a/docs/DevTools.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: dev-tools -title: Dev Tools -layout: docs -category: The Basics -permalink: docs/dev-tools.html ---- - -## Hot Reloading - -Iteration is a key factor in any developer experience. VR is no exception and we would argue it is even more important here. While React VR facilitates reloading the whole page and scene, this has the side effect of resetting the state of the running application, which can cause issues as the size of the application increases. For this reason, React VR supports *hot reloading* of individual JavaScript modules. This goes a long way towards keeping the iteration experience incremental and rapid. - -Hot reloading is built into React VR, enabled by a startup flag (`enableHotReload`) when creating a VRInstance. For example: - -``` - const vr = new VRInstance(bundle, 'CubeSample', parent, { - scene: scene, - nativeModules: [ cubeModule ], - enableHotReload: true, - }); -``` - -You can also use `hotreload` as a query parameter to enable hot reloading should the application not set a preference. - -``` -http://localhost:8081/vr/?hotreload -``` - - -Hot reloading makes use of the React Native Packager to watch the local file system and notify the runtime regarding file changes. File changes trigger a reload of that module by the React VR runtime systems. For more information about using hot reloading and some nuances of the system, see [Introducing Hot Reloading](https://facebook.github.io/react-native/blog/2016/03/24/introducing-hot-reloading.html) in the React Native Blog. - -## React Dev Tools Inspector - -In the React Dev tools for Nuclide is the Element Inspector that allows developers to view and alter properties of components within a running application. To use the Inspector you must install [Nuclide](https://nuclide.io/) - -To make use of the Inspector, the bundle must be enabled with `dev=true`. This is the default setting for applications created by the react-vr CLI but you can confirm it by searching for the ReactVR.init function and looking for the `dev=true` query parameter. - -``` - ReactVR.init( - // When you're ready to deploy your app, update this line to point to - // your compiled index.bundle.js - '../index.vr.bundle?platform=vr&dev=true', - // Attach it to the body tag - document.body - ); -``` - -Once confirmed, you should follow the instructions for [loading a React Native Project](https://nuclide.io/docs/platforms/react-native/#loading-a-react-native-project). This will allow you to [start the React Native Packager](https://nuclide.io/docs/platforms/react-native/#running-applications__react-native-packager) from within Nuclide. - -Now the application, Nuclide and the React Native Packager are configured you should browse to the location of your React VR project index.html with the query param `devtools` for example: - -``` -http://localhost:8081/vr/?devtools -``` - -Now selecting the `React Inspector` tab should present a window similar to -![](img/inspector.jpg) - -Note: Because React VR makes extensive use of data types (such as Transforms) that are not in common use within React and React Native, certain properties are not displayed in their optimal form. diff --git a/docs/Fonts.md b/docs/Fonts.md deleted file mode 100644 index 1d5d5b0e6..000000000 --- a/docs/Fonts.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -id: fonts -title: Fonts and Text -layout: docs -category: The Basics -permalink: docs/fonts.html ---- - -The rendering of fonts and text in VR is tricky as text elements (glyphs) are rendered in 3D. - -#### Options - -One option is to use geometry fonts as used in three.js [TextGeometry](https://github.com/mrdoob/three.js/blob/master/src/geometries/TextGeometry.js) however this can be computationally expensive for large quantities of text. A second option is to use the browser to generate text blocks and then make these available through html5 canvas bitmaps to OpenGLES textures used by React VR. However, the difficulty with this approach is determining an ideal rendering size that strikes a proper balance between minimizing blur and managing the amount of texture memory required. - -#### React VR - -For these reasons, React VR takes a slightly different approach, one which attempts to maximize for the common usage, but in turn has its own constraints. React VR text rendering makes use of the same method as the Oculus Mobile SDK and uses [Signed Distance Field](http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf) fonts. - -Using distance field fonts allows the font to remain crisp and sharp even when dynamically rendered to the screen in 3D. Because the fonts are rendered using bitmap textures, a minimal amount of geometry is used. We get dynamic font content and placement with minimal geometry and texture usage. - -The constraint is that because glyphs are not generated dynamically, the full unicode character set often present in browsers is not available. - -#### Character sets - -The React VR default character set is based on 387 glyphs covering [EFIGS](https://en.wiktionary.org/wiki/EFIGS) languages. Also included are pregenerated textures for Japanese and Korean although these understandably are larger downloads. They are shipped within the `ovrui` npm package, in the `fonts/` directory. - -To use an alternative font texture, you need to load it before React VR is initialized. The loaded font can then be passed to React VR in your `client.js` code. - -``` -OVRUI.loadFont( - 'path/to/custom.fnt', - 'path/to/custom.png' -).then((font) => { - // 'font' contains everything React VR needs to render elements with - // your custom font. - - // Pass it to the boilerplate init code - const vr = new VRInstance(bundle, 'MyProject', parent, { - // Pass in the custom font as an initialization property - font: font, - ...options, - }); - - // ... -}); -``` - -You can install fallback fonts should the main font set not cover enough of the character set by loading fonts explicitly. Contained within the repository are fonts that cover the majority of Chinese, Japanese and Korean glyphs. Use the OVRUI function `addFontFallback` to add a fallback to an already loaded font set. - -``` -const fallbackFonts = { - '../static_assets/cjk_0.fnt': '../static_assets/cjk_0_sdf.png', - '../static_assets/cjk_1.fnt': '../static_assets/cjk_1_sdf.png', - '../static_assets/cjk_2.fnt': '../static_assets/cjk_2_sdf.png', - '../static_assets/korean_0.fnt': '../static_assets/korean_0_sdf.png', - '../static_assets/korean_1.fnt': '../static_assets/korean_1_sdf.png', - '../static_assets/efigs.fnt': '../static_assets/efigs.png', -}; - -function init(bundle, parent, options) { - // use the embedded defaultFont and and fallbacks - const font = OVRUI.loadFont(); - Promise.all( - Object.keys(fallbackFonts).map(key => OVRUI.loadFont(key, fallbackFonts[key])) - ).then(fonts => { - for (let i = 0; i < fonts.length; i++) { - OVRUI.addFontFallback(font, fonts[i]); - } - - const vr = new VRInstance(bundle, 'MyProject', parent, { - // Pass in the custom font as an initialization property - font: font, - ...options, - }); - - // ... - }); -} -``` - -It is also possible to generate your own font set textures using the fontue tool in the [Oculus Mobile SDK](https://developer.oculus.com/downloads/). The tool has a dependency on [FreeType](https://www.freetype.org), and can be found in the Oculus Mobile SDK `Tools/fontue` directory, along with a `readme.txt` describing its operation. - -The base command line for the EFIGS font is: - -``` -OculusSans-Medium.otf efigs\efigs -co -0.01 -ts 1.0 -hpad 128 -vpad 128 -sdf 256 1024 1024 -cf data\strings\values\strings.xml -cf data\strings\values-de\strings.xml -cf data\strings\values-en-rGB\strings.xml -cf data\strings\values-es\strings.xml -cf data\strings\values-es-rES\strings.xml -cf data\strings\values-fr\strings.xml -cf data\strings\values-it\strings.xml -cf data\EFIGS_extended.txt -``` - -Further characters can be added using additional `-cf` entries. diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md deleted file mode 100755 index 2080402de..000000000 --- a/docs/GettingStarted.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: quick-start-getting-started -title: Getting Started -layout: docs -category: The Basics -permalink: docs/getting-started.html -next: tutorial ---- - -Before starting your first React VR project, you have to install the dependencies used to build and manage React VR apps: **Node.js** and the **React VR CLI**. - -####Installing Node.js - -If you already have Node.js installed, make sure it is at least version 4.0. - -* **Mac**: On Mac, we recommend installing Node.js through [Homebrew](http://brew.sh/). - -* **Windows**: Get the Windows installer from the [nodejs.org download page](https://nodejs.org/en/download/). - -* **Linux**: Go to the [nodejs.org package manager page](https://nodejs.org/en/download/package-manager/) to find specific instructions for your Linux distribution. - -#### Creating your first project - -We can use the React VR command line interface tool to generate a new project called “WelcomeToVR.” The tool creates a new folder containing the skeleton for a React VR project and fetches all the necessary external dependencies. - -1. If you are still running **npm** in your terminal window, press `CTRL+C` to stop it. - -1. Navigate to a directory where you want to put your new project. - -1. Install the React VR CLI tool. Enter: - npm install -g react-vr-cli - -1. Use the React VR CLI tool to create a new application under a `WelcomeToVR` folder and install the required dependencies. Enter: - react-vr init WelcomeToVR - -1. Change directory to your new **WelcomeToVR** project directory. - cd WelcomeToVR - -1. Use the start command to initialize your local development server. Enter: - npm start - -1. Open your browser to http://localhost:8081/vr/index.html. You should see something similar to the following: ![](img/hellovr.jpg) - -#### Hello! -Click and drag around the world in your browser or open it up on your mobile device to see more. - -If you're using a web browser that supports WebVR such as [Oculus Browser](https://www.oculus.com/experiences/gear-vr/1257988667656584/), you should be able to put on your headset and explore the world in full VR. For more information on VR capable browsers, see the [VR Browsers](docs/vrbrowsers.html) topic. - -Our next topic explores the code that brings this scene to life. diff --git a/docs/Images.md b/docs/Images.md deleted file mode 100755 index e4106928d..000000000 --- a/docs/Images.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -id: images -title: Images -layout: docs -category: Guides -permalink: docs/images.html -next: animations -previous: colors ---- - -You must manually specify the dimensions of your image. Image dimensions are -specified in meters and it is not possible to predict the intended dimensions -merely from the pixel width and height of the image. - -```javascript -// GOOD - - -// BAD - -``` - -## Why Not Automatically Size Everything? - -The issue is that React VR is fully 3D. Pixels don't correspond directly to -world units because it is possible to place an image at various different -depths. If you don't specify the image dimensions *in the browser*, the browser -renders a 0x0 element, downloads the image, and then renders the image based -with the correct size. Therefore, we have chosen to make developers specify -explicit image dimensions. - -## Source as an object - -An interesting React Native decision is that the `src` attribute is named -`source` and doesn't take a string but an object with a `uri` attribute. - -```javascript - -``` - -This is desirable from an infrastructure viewpoint. It allows us to attach -metadata to this object. For example, if you are using -`require('./my-icon.png')`, then we add information about its actual location -and size. This is also future proofing, for example, we may want to support -sprites at some point, or texture sampling methods such as `nearest`, `mipmaps`, -and so on. - -## Background Image via Nesting - -A common feature request from developers familiar with the web is an equivalent -of `background-image`. To do this, create a normal `` component and then -add whatever children you would like to layer on top of it. - -```javascript -return ( - - Inside - -); -``` - -## Border Radius Styles - -Please note that the following corner specific, border radius style properties are currently ignored by the image component: - -* `borderTopLeftRadius` -* `borderTopRightRadius` -* `borderBottomLeftRadius` -* `borderBottomRightRadius` diff --git a/docs/Input.md b/docs/Input.md deleted file mode 100644 index 3bea9a4a5..000000000 --- a/docs/Input.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -id: input -title: Cursors and Input -layout: docs -category: The Basics -permalink: docs/input.html ---- - -## Cursors and Input - -Our goal is to make writing cross-platform interactions simple. The input schemes might vary with the device used to interact with your application, so we provide event handlers and API hooks to enable a diverse variety of input systems. - -Input events are collected from mouse, keyboard, touch, and gamepad interactions, and cursors are implemented as simple raycasters into your scene. The events are collected each frame by the runtime, and passed to your React application. - -Similarly, the runtime collects cursor position continuously and events such as entering or exiting a View are calculated and passed to the appropriate event handlers on the React side. - -**Note:** If you're looking for simple, button-style, `onClick` behavior, that is provided out of the box by [VrButton](docs/vrbutton.html). - -## Supported Input Events - -### `onEnter` - -This event fires whenever the platform cursor begins intersecting with a -component. If you have configured your application to use multiple cursors, -you can determine which cursor generated the event by examining the `source` -property of the event. This is useful for implementing different behaviors for -different cursor systems. - -### `onExit` - -This event fires whenever the platform cursor stops intersecting with a -component. It has the same properties as `onEnter` events. - -### `onMove` - -This event fires as the cursor moves across a View. The position of the -cursor is passed as the `offset` property of the event: a two-unit array -array representing the x and y coordinates of the cursor relative to the view. -These values are unitless numbers ranging from 0.0 to 1.0, where `[0, 0]` -represents the top-left corner of a View, `[0.5, 0.5]` represents the center of -the view, and `[1.0, 1.0]` represents the bottom-right corner. Using unitless -values allows the same product code to be used in both 3D-positioned Views -(which use meters), and Views in a CylindricalPanel (which use pixels). - -### `onInput` - -This event captures all interaction events: keyboard, mouse, touch, and gamepad. -Events coming into `onInput` can be further filtered by inspecting the `type` -field, which will be one of `'MouseInputEvent'`, `'KeyboardInputEvent'`, -`'TouchInputEvent'`, or `'GamepadInputEvent'`. Custom input systems can also -specify their own unique identifiers. For example, the `onClick` handler of -`VrButton` filters events to capture the primary buttons for each input channel. - -## Cursor Systems - -Cursors are implemented as raycasters. Originating from a point in space, an -invisible ray is sent into the scene until it intersects with a view or mesh -with an `onEnter`, `onExit`, or `onMove` event handler. If the interaction -state has changed, an appropriate event is sent to the view in the React -application. Your application can use any number of cursors at once; the first -implementation to return a value sets the cursor position on each frame. - -React VR ships with a cursor implementation that allows users to -use a mouse or touchscreen to interact with your application. We don't -initialize applications with any other cursors by default, because the set of -possible input devices for users with VR headsets can be wide-ranging. However, -we've made it extremely simple to implement your own raycasters, and we've -provided examples of raycasters that work with 3DOF or 6DOF controllers. - -Custom raycasters need to implement three methods: `getType`, `getRayOrigin`, and -`getRayDirection`. - -`getType` returns a unique string identifier for the -raycaster, so that React applications can provide special handling for specific -cursors. These two methods are called each frame to compose the ray -and calculate intersections. - -`getRayOrigin()` returns a 3-element array -representing the 3D position of the ray's origin, relative to the camera. - -`getRayDirection()` returns a 3-element array representing the vector direction -of the ray, relative to the camera's orientation. The current `camera` object -is passed to each of these methods when they are called. -As an example, the default mouse raycaster returns a fixed origin of -`[0, 0, 0]`, and calculates the direction of the ray by calculating the vector -from the origin to the mouse coordinates on your screen. A raycaster can also -return `null` from either of these methods and defer cursor calculation -to the next raycaster. - -Custom raycasters can also implement two optional methods: `frame` and -`drawsCursor`. If `frame()` is implemented, it is called on each frame of -the application; this is handy for updating virtual representations of -positional controllers in your 3D scene. `drawsCursor` returns a boolean value -determining whether this raycaster should ever draw a visible cursor. - -You can determine which raycasters your application uses by supplying a -`raycasters` option to `VRInstance` in your `client.js` file. The key should -point to an array of raycaster instances. - -## Cursor Visibility - -Raycaster implementations can determine whether a visible cursor -is drawn in your scene. A visible cursor helps users determine -where their interactions will land. To help you implement this, we provide a standard -application-level cursor that tracks where interactions occur. - -The `cursorVisibility` setting, passed at initialization time, controls the cursor -visibility and can have the following values: - - * `hidden` - No cursor is visible. This is the default. - * `visible` - Cursor is always displayed. - * `auto` - Visibility is computed each frame by React VR. Cursor is visible - when hovering over components that have input event handlers, for example - or a to which you've attached handlers. - -These settings are set at initialization time, which means they can be defined -in one of two different places. The first is in your `index.html` page: -`ReactVR.init()` takes a map of options as its third argument. - -``` - - -``` - -Alternatively, if you want these options to be compiled into your application, -you can also set them in the autogenerated `vr/client.js` file. These options -are passed as the last argument when the `VRInstance` is constructed. - -``` -// vr/client.js - -const vr = new VRInstance(bundle, 'YourProject', parent, { - // Custom initialization options go here - cursorVisibility: 'visible', - - ...options, -}); -``` - -## Example - -The following code builds a simple component that changes text color when the -cursor hovers over it: - -``` -class ColorChange extends React.Component { - constructor() { - super(); - - this.state = {textColor: 'white'}; - } - - render() { - return ( - this.setState({textColor: 'red'})} - onExit={() => this.setState({textColor: 'white'})}> - This text will turn red when you look at it. - - ); - } -} -``` diff --git a/docs/LayoutAndStyle.md b/docs/LayoutAndStyle.md deleted file mode 100644 index ec1bf41d5..000000000 --- a/docs/LayoutAndStyle.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -id: layout-and-style -title: Layout and Style -layout: docs -category: The Basics -permalink: docs/layout-and-style.html -next: events-and-links -previous: reactnative ---- - -React VR makes use of a Flexbox style layout algorithm to automatically position components and their children. - -The library we use, [Yoga](https://github.com/facebook/yoga), tries to follows the web implementation of flexbox as much as possible. Yoga does make changes to the default properties, and [these changes](http://jsfiddle.net/vjeux/y11txxv9/) can be forked to allow testing in a browser environment. - -#### Layout Sample - -In most cases, children are arranged vertically in a `'column'` or horizontally in a `'row'`. This arrangement behavior, as well as size and alignment, are controlled through style properties of the component. - -Here are some of the more common attributes: - -* `flexDirection` - Can be `column` or `row`. -* `justifyContent` - Can be `flex-start`, `space-around`, `center`, `space-between`, or `flex-end`. -* `alignItems` - Can be `stretch`, `flex-start`, `center`, or `flex-end`. -* `margin` - specifies space around the item. - -The behavior of these and other layout attributes is demonstrated by the *LayoutSample* included -with React VR. This sample displays the following scene, with buttons arranged vertically: - -![](img/layoutsample.jpg) - -Colored buttons with text can be generated by the following code within a component: - -``` -render() { - // below creates a view that is 2 meters wide and is positioned - // 5 meters in front of the user (z = -5). Its child items are laid out - // in a 'column' and marked to 'stretch' to the width of the view container. - // This causes call child view to have the same width. - return ( - - - - - - Red - - - Orange - - - Yellow - - - Green - - - Blue - - - - - ); -} -``` - - -For more information about layout, see [Layout with Flexbox](https://facebook.github.io/react-native/docs/flexbox.html) in the React Native docs. - - - -#### Style - -React VR doesn't use a special language or syntax for defining styles. All of the core and VR components accept a prop named `style`. You just style your application using JavaScript. Here is an example of a view with style applied to it: - -``` - -``` - -The style names and values usually match how CSS works on the web, except names are written like `backgroundColor` instead of `background-color`. - -The style prop can be a plain old JavaScript object. In the above example, we declared an inline object with attributes `flex`, `width`, and so on. This direct inline approach is simple and is what we usually do for sample code. - -As a component grows in complexity, it is often cleaner to use `StyleSheet.create` to define several styles in one place. - -``` -const styles = StyleSheet.create({ - bigblue: { - color: 'blue', - fontSize: 0.4 - }, - red: { - color: 'red', - }, -}); -``` - -Such styles can be used directly inside of the style property. The shorter syntax encourages style reuse. - -``` -bigblue colored text -``` - -You can also pass an array of styles: - -``` -red text -green text -``` - -In style arrays, the styles are merged and the members of the last array element take precedence. This means we can use this approach to help inherit styles or override their elements. - - -#### Width and Height - -A component's width and height style properties determine its size in the world and during layout. - -React VR uses meters as its units unlike React Native, which uses pixels. Using meters is important, as it gives meaningful physical size to the object in the VR world. Meter units are also used by the WebVR APIs. - -### Units - -The distance and dimensional units for the Web version of React VR are meters. diff --git a/docs/MoviesExample.json b/docs/MoviesExample.json deleted file mode 100755 index da7c33342..000000000 --- a/docs/MoviesExample.json +++ /dev/null @@ -1 +0,0 @@ -{"total":24,"movies":[{"id":"11494","title":"Chain Reaction","year":1996,"mpaa_rating":"PG-13","runtime":106,"release_dates":{"theater":"1996-08-02","dvd":"2001-05-22"},"ratings":{"critics_rating":"Rotten","critics_score":16,"audience_rating":"Spilled","audience_score":27},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg","profile":"http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg","detailed":"http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg","original":"http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg"},"abridged_cast":[{"name":"Keanu Reeves","id":"162654049","characters":["Eddie Kasalivich"]},{"name":"Morgan Freeman","id":"162652224","characters":["Paul Shannon"]},{"name":"Rachel Weisz","id":"162653682","characters":["Dr. Lily Sinclair"]},{"name":"Fred Ward","id":"162667867","characters":["Agt. Leon Ford"]},{"name":"Kevin Dunn","id":"162664658","characters":["Agt. Doyle"]}],"alternate_ids":{"imdb":"0115857"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/11494.json","alternate":"http://www.rottentomatoes.com/m/1072457-chain_reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/11494/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/11494/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/11494/similar.json"}},{"id":"770920361","title":"React! A Woman's Guide to Safety and Basic Self-Defense","year":1996,"mpaa_rating":"Unrated","runtime":"","release_dates":{"dvd":"1996-07-29"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/m7G-weBZPYfnoqSiF59LIPPYOuM=/44x81/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/47/10974721_ori.jpg","profile":"http://resizing.flixster.com/m7G-weBZPYfnoqSiF59LIPPYOuM=/44x81/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/47/10974721_ori.jpg","detailed":"http://resizing.flixster.com/m7G-weBZPYfnoqSiF59LIPPYOuM=/44x81/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/47/10974721_ori.jpg","original":"http://resizing.flixster.com/m7G-weBZPYfnoqSiF59LIPPYOuM=/44x81/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/47/10974721_ori.jpg"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770920361.json","alternate":"http://www.rottentomatoes.com/m/react_a_womans_guide_to_safety_and_basic_selfdefense/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770920361/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770920361/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770920361/similar.json"}},{"id":"770819043","title":"Reaction","year":"","mpaa_rating":"Unrated","runtime":13,"release_dates":{},"ratings":{"critics_score":-1,"audience_score":100},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770819043.json","alternate":"http://www.rottentomatoes.com/m/reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770819043/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770819043/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770819043/similar.json"}},{"id":"771364188","title":"Reactor","year":2013,"mpaa_rating":"Unrated","runtime":34,"release_dates":{},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[],"alternate_ids":{"imdb":"2828874"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/771364188.json","alternate":"http://www.rottentomatoes.com/m/reactor_2013/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/771364188/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/771364188/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/771364188/similar.json"}},{"id":"391535485","title":"Chain Reaction (House of Blood)","year":2006,"mpaa_rating":"NC-17","runtime":105,"release_dates":{"dvd":"2006-10-03"},"ratings":{"critics_score":-1,"audience_rating":"Spilled","audience_score":22},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/Q8IBqX3b-nhEAEYokJ_aH6jO6lE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941373_ori.jpg","profile":"http://resizing.flixster.com/Q8IBqX3b-nhEAEYokJ_aH6jO6lE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941373_ori.jpg","detailed":"http://resizing.flixster.com/Q8IBqX3b-nhEAEYokJ_aH6jO6lE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941373_ori.jpg","original":"http://resizing.flixster.com/Q8IBqX3b-nhEAEYokJ_aH6jO6lE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941373_ori.jpg"},"abridged_cast":[{"name":"Christopher Kriesa","id":"391535486"},{"name":"Jurgen Prochnow","id":"162693957"},{"name":"Dan van Husen","id":"391535498"},{"name":"Mehmet Yilmaz","id":"391535499"},{"name":"Lisa Sachsenweger","id":"770770690"}],"alternate_ids":{"imdb":"0460742"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/391535485.json","alternate":"http://www.rottentomatoes.com/m/house_of_blood/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/391535485/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/391535485/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/391535485/similar.json"}},{"id":"17962","title":"The Chain Reaction","year":1995,"mpaa_rating":"Unrated","runtime":72,"release_dates":{"dvd":"1999-12-14"},"ratings":{"critics_score":-1,"audience_rating":"Spilled","audience_score":33},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/e3AKmyWuh1Wr4qMAM_vQ0vtN9AA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941368_ori.jpg","profile":"http://resizing.flixster.com/e3AKmyWuh1Wr4qMAM_vQ0vtN9AA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941368_ori.jpg","detailed":"http://resizing.flixster.com/e3AKmyWuh1Wr4qMAM_vQ0vtN9AA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941368_ori.jpg","original":"http://resizing.flixster.com/e3AKmyWuh1Wr4qMAM_vQ0vtN9AA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/10/94/13/10941368_ori.jpg"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/17962.json","alternate":"http://www.rottentomatoes.com/m/the-chain-reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/17962/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/17962/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/17962/similar.json"}},{"id":"23108","title":"The Fifth Reaction","year":2003,"mpaa_rating":"Unrated","runtime":106,"release_dates":{"theater":"2003-01-01","dvd":"2005-11-22"},"ratings":{"critics_score":-1,"audience_rating":"Upright","audience_score":92},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/1FxtmlxCqRb0EPdHFrFDGpZ45CE=/54x75/dkpu1ddg7pbsk.cloudfront.net/movie/31/16/311623_ori.jpg","profile":"http://resizing.flixster.com/1FxtmlxCqRb0EPdHFrFDGpZ45CE=/54x75/dkpu1ddg7pbsk.cloudfront.net/movie/31/16/311623_ori.jpg","detailed":"http://resizing.flixster.com/1FxtmlxCqRb0EPdHFrFDGpZ45CE=/54x75/dkpu1ddg7pbsk.cloudfront.net/movie/31/16/311623_ori.jpg","original":"http://resizing.flixster.com/1FxtmlxCqRb0EPdHFrFDGpZ45CE=/54x75/dkpu1ddg7pbsk.cloudfront.net/movie/31/16/311623_ori.jpg"},"abridged_cast":[{"name":"Niki Karimi","id":"405588976"},{"name":"Jamshid Hashempour","id":"771029092"},{"name":"Merila Zareie","id":"770833361"},{"name":"Shahab Hosseini","id":"770830873"},{"name":"Soghra Abisi","id":"771029093"}],"alternate_ids":{"imdb":"0386843"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/23108.json","alternate":"http://www.rottentomatoes.com/m/the-fifth-reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/23108/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/23108/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/23108/similar.json"}},{"id":"770924192","title":"Chain Reaction","year":1995,"mpaa_rating":"Unrated","runtime":72,"release_dates":{},"ratings":{"critics_score":-1,"audience_score":100},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/yFgYWViboAAdHG99EoF3VULEblc=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/67/10976773_ori.jpg","profile":"http://resizing.flixster.com/yFgYWViboAAdHG99EoF3VULEblc=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/67/10976773_ori.jpg","detailed":"http://resizing.flixster.com/yFgYWViboAAdHG99EoF3VULEblc=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/67/10976773_ori.jpg","original":"http://resizing.flixster.com/yFgYWViboAAdHG99EoF3VULEblc=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/10/97/67/10976773_ori.jpg"},"abridged_cast":[{"name":"Johan Paulik","id":"364601611"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770924192.json","alternate":"http://www.rottentomatoes.com/m/chain_reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770924192/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770924192/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770924192/similar.json"}},{"id":"770795709","title":"The Chain Reaction (Nuclear Run)","year":1980,"mpaa_rating":"R","runtime":87,"release_dates":{"theater":"1980-09-25"},"ratings":{"critics_score":-1,"audience_rating":"Spilled","audience_score":29},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[{"name":"Ross Thompson","id":"770816985","characters":["Heinrich"]},{"name":"Steve Bisley","id":"391393048","characters":["Larry"]},{"name":"David Bracks","id":"770932042","characters":["Spray painter"]},{"name":"Tim Burns","id":"391393049","characters":["Survey driver"]},{"name":"Ralph Cotterill","id":"770686983","characters":["Gray"]}],"alternate_ids":{"imdb":"0080513"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770795709.json","alternate":"http://www.rottentomatoes.com/m/1003826-chain_reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770795709/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770795709/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770795709/similar.json"}},{"id":"770815970","title":"A Chemical Reaction","year":2009,"mpaa_rating":"Unrated","runtime":79,"release_dates":{"theater":"2009-01-01"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/d7ZWFBXpcaqXbOJ-W57_b8B2TR0=/54x80/dkpu1ddg7pbsk.cloudfront.net/movie/10/92/85/10928519_ori.jpg","profile":"http://resizing.flixster.com/d7ZWFBXpcaqXbOJ-W57_b8B2TR0=/54x80/dkpu1ddg7pbsk.cloudfront.net/movie/10/92/85/10928519_ori.jpg","detailed":"http://resizing.flixster.com/d7ZWFBXpcaqXbOJ-W57_b8B2TR0=/54x80/dkpu1ddg7pbsk.cloudfront.net/movie/10/92/85/10928519_ori.jpg","original":"http://resizing.flixster.com/d7ZWFBXpcaqXbOJ-W57_b8B2TR0=/54x80/dkpu1ddg7pbsk.cloudfront.net/movie/10/92/85/10928519_ori.jpg"},"abridged_cast":[{"name":"Paul Tukey","id":"770801638"}],"alternate_ids":{"imdb":"1469852"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770815970.json","alternate":"http://www.rottentomatoes.com/m/a-chemical-reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770815970/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770815970/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770815970/similar.json"}},{"id":"770827338","title":"Juno Reactor: Live in Tokyo","year":2002,"mpaa_rating":"Unrated","runtime":"","release_dates":{"theater":"2002-12-31","dvd":"2005-06-21"},"ratings":{"critics_score":-1,"audience_rating":"Spilled","audience_score":40},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[{"name":"Juno Reactor","id":"770751447"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770827338.json","alternate":"http://www.rottentomatoes.com/m/juno-reactor-live-in-tokyo/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770827338/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770827338/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770827338/similar.json"}},{"id":"771004226","title":"Historic WWII Shell Shock Film: Military Psychology & War Combat Stress Reaction for Soldiers","year":2007,"mpaa_rating":"Unrated","runtime":33,"release_dates":{"dvd":"2007-02-01"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/771004226.json","alternate":"http://www.rottentomatoes.com/m/historic_wwii_shell_shock_film_military_psychology_and_war_combat_stress_reaction_for_soldiers/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/771004226/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/771004226/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/771004226/similar.json"}},{"id":"770978318","title":"Fifth Reaction","year":2003,"mpaa_rating":"Unrated","runtime":107,"release_dates":{"dvd":"2005-11-22"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/kTMk0zw4RXlpYGytEtnYgNQv-Uc=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/02/55/11025581_ori.jpg","profile":"http://resizing.flixster.com/kTMk0zw4RXlpYGytEtnYgNQv-Uc=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/02/55/11025581_ori.jpg","detailed":"http://resizing.flixster.com/kTMk0zw4RXlpYGytEtnYgNQv-Uc=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/02/55/11025581_ori.jpg","original":"http://resizing.flixster.com/kTMk0zw4RXlpYGytEtnYgNQv-Uc=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/02/55/11025581_ori.jpg"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770978318.json","alternate":"http://www.rottentomatoes.com/m/fifth_reaction/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770978318/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770978318/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770978318/similar.json"}},{"id":"771006274","title":"Chain Reaction","year":2008,"mpaa_rating":"Unrated","runtime":90,"release_dates":{"dvd":"2008-01-22"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/2sFwWwxvTzwM5bT9qGm78oZjpBA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/05/21/11052126_ori.jpg","profile":"http://resizing.flixster.com/2sFwWwxvTzwM5bT9qGm78oZjpBA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/05/21/11052126_ori.jpg","detailed":"http://resizing.flixster.com/2sFwWwxvTzwM5bT9qGm78oZjpBA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/05/21/11052126_ori.jpg","original":"http://resizing.flixster.com/2sFwWwxvTzwM5bT9qGm78oZjpBA=/54x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/05/21/11052126_ori.jpg"},"abridged_cast":[{"name":"Rick Ross","id":"770761752","characters":["Pac Man"]},{"name":"Mr. Bones","id":"771060841","characters":["Chase"]},{"name":"Total Kaos","id":"771060844","characters":["Paul"]},{"name":"M Beezy","id":"771060843","characters":["Reno"]},{"name":"Sho nuff","id":"771060842","characters":["Tee"]}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/771006274.json","alternate":"http://www.rottentomatoes.com/m/chain_reaction-2008/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/771006274/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/771006274/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/771006274/similar.json"}},{"id":"770879444","title":"Deadly Reactor","year":1989,"mpaa_rating":"Unrated","runtime":88,"release_dates":{},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[{"name":"David Heavener","id":"162767691","characters":["Cody"]},{"name":"Stuart Whitman","id":"162656122","characters":["Duke"]},{"name":"Darwyn Swalve","id":"770883640","characters":["Hog"]},{"name":"Allyson Davis","id":"770880183"},{"name":"Barbara Kerek","id":"770935570"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770879444.json","alternate":"http://www.rottentomatoes.com/m/deadly_reactor/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770879444/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770879444/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770879444/similar.json"}},{"id":"770953999","title":"Juno Reactor - Live in Tokyo","year":2002,"mpaa_rating":"Unrated","runtime":"","release_dates":{"dvd":"2002-10-22"},"ratings":{"critics_score":-1,"audience_rating":"Upright","audience_score":100},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/Yttvb_8gXph4S7iJCiLQFbZ2s7Q=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/11/00/22/11002233_ori.jpg","profile":"http://resizing.flixster.com/Yttvb_8gXph4S7iJCiLQFbZ2s7Q=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/11/00/22/11002233_ori.jpg","detailed":"http://resizing.flixster.com/Yttvb_8gXph4S7iJCiLQFbZ2s7Q=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/11/00/22/11002233_ori.jpg","original":"http://resizing.flixster.com/Yttvb_8gXph4S7iJCiLQFbZ2s7Q=/54x74/dkpu1ddg7pbsk.cloudfront.net/movie/11/00/22/11002233_ori.jpg"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770953999.json","alternate":"http://www.rottentomatoes.com/m/juno_reactor_live_in_tokyo/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770953999/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770953999/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770953999/similar.json"}},{"id":"770959249","title":"Neil Young & Crazy Horse - Re-Ac-Tor","year":1981,"mpaa_rating":"Unrated","runtime":"","release_dates":{"dvd":"2003-09-23"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770959249.json","alternate":"http://www.rottentomatoes.com/m/neil_young_and_crazy_horse_reactor/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770959249/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770959249/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770959249/similar.json"}},{"id":"770988328","title":"Standard Deviants - Organic Chemistry Module 14: Electrophilic Reactions III","year":2004,"mpaa_rating":"Unrated","runtime":26,"release_dates":{"dvd":"2004-12-21"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/cQUqzav2aBRwjf6dSJTkUKGIEZ4=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034874_ori.jpg","profile":"http://resizing.flixster.com/cQUqzav2aBRwjf6dSJTkUKGIEZ4=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034874_ori.jpg","detailed":"http://resizing.flixster.com/cQUqzav2aBRwjf6dSJTkUKGIEZ4=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034874_ori.jpg","original":"http://resizing.flixster.com/cQUqzav2aBRwjf6dSJTkUKGIEZ4=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034874_ori.jpg"},"abridged_cast":[{"name":"Standard Deviants","id":"770893547"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988328.json","alternate":"http://www.rottentomatoes.com/m/standard_deviants_organic_chemistry_module_14_electrophilic_reactions_iii/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988328/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988328/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988328/similar.json"}},{"id":"770988330","title":"Standard Deviants - Organic Chemistry Module 13: Electrophilic Reactions II","year":2004,"mpaa_rating":"Unrated","runtime":26,"release_dates":{"dvd":"2004-12-21"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/6R33pXKxhjyiO-hjSHvYZ1r_EGk=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034876_ori.jpg","profile":"http://resizing.flixster.com/6R33pXKxhjyiO-hjSHvYZ1r_EGk=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034876_ori.jpg","detailed":"http://resizing.flixster.com/6R33pXKxhjyiO-hjSHvYZ1r_EGk=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034876_ori.jpg","original":"http://resizing.flixster.com/6R33pXKxhjyiO-hjSHvYZ1r_EGk=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034876_ori.jpg"},"abridged_cast":[{"name":"Standard Deviants","id":"770893547"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988330.json","alternate":"http://www.rottentomatoes.com/m/standard_deviants_organic_chemistry_module_13_electrophilic_reactions_ii/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988330/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988330/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988330/similar.json"}},{"id":"770988332","title":"Standard Deviants - Organic Chemistry Module 11: Electrophilic Reactions I","year":2004,"mpaa_rating":"Unrated","runtime":26,"release_dates":{"dvd":"2004-12-21"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/z770YngyfBvk2oid95j5ppFpaNE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034878_ori.jpg","profile":"http://resizing.flixster.com/z770YngyfBvk2oid95j5ppFpaNE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034878_ori.jpg","detailed":"http://resizing.flixster.com/z770YngyfBvk2oid95j5ppFpaNE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034878_ori.jpg","original":"http://resizing.flixster.com/z770YngyfBvk2oid95j5ppFpaNE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034878_ori.jpg"},"abridged_cast":[{"name":"Standard Deviants","id":"770893547"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988332.json","alternate":"http://www.rottentomatoes.com/m/standard_deviants_organic_chemistry_module_11_electrophilic_reactions_i/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988332/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988332/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988332/similar.json"}},{"id":"770988334","title":"Standard Deviants - Organic Chemistry Module 9: Reaction Energy Diagrams","year":2004,"mpaa_rating":"Unrated","runtime":26,"release_dates":{"dvd":"2004-12-21"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/FtChYDmsGfsjWUVm-ThAwPv10nE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034880_ori.jpg","profile":"http://resizing.flixster.com/FtChYDmsGfsjWUVm-ThAwPv10nE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034880_ori.jpg","detailed":"http://resizing.flixster.com/FtChYDmsGfsjWUVm-ThAwPv10nE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034880_ori.jpg","original":"http://resizing.flixster.com/FtChYDmsGfsjWUVm-ThAwPv10nE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034880_ori.jpg"},"abridged_cast":[{"name":"Standard Deviants","id":"770893547"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988334.json","alternate":"http://www.rottentomatoes.com/m/standard_deviants_organic_chemistry_module_9_reaction_energy_diagrams/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988334/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988334/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988334/similar.json"}},{"id":"770988338","title":"Standard Deviants - Organic Chemistry Module 7: Addition Reactions","year":2004,"mpaa_rating":"Unrated","runtime":26,"release_dates":{"dvd":"2004-12-21"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://resizing.flixster.com/noxh6ykIwPcnBfhtSZY3d3yADjE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034884_ori.jpg","profile":"http://resizing.flixster.com/noxh6ykIwPcnBfhtSZY3d3yADjE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034884_ori.jpg","detailed":"http://resizing.flixster.com/noxh6ykIwPcnBfhtSZY3d3yADjE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034884_ori.jpg","original":"http://resizing.flixster.com/noxh6ykIwPcnBfhtSZY3d3yADjE=/54x78/dkpu1ddg7pbsk.cloudfront.net/movie/11/03/48/11034884_ori.jpg"},"abridged_cast":[{"name":"Standard Deviants","id":"770893547"}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988338.json","alternate":"http://www.rottentomatoes.com/m/standard_deviants_organic_chemistry_module_7_addition_reactions/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988338/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988338/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/770988338/similar.json"}},{"id":"771013389","title":"Burn: Bosu Ultimate Reactive Neuromuscular Training","year":2008,"mpaa_rating":"Unrated","runtime":"","release_dates":{"dvd":"2008-07-22"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/771013389.json","alternate":"http://www.rottentomatoes.com/m/burn_bosu_ultimate_reactive_neuromuscular_training/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/771013389/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/771013389/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/771013389/similar.json"}},{"id":"771041962","title":"Bill Nye the Science Guy: Chemical Reactions","year":1994,"mpaa_rating":"Unrated","runtime":"","release_dates":{"dvd":"2009-07-07"},"ratings":{"critics_score":-1,"audience_score":0},"synopsis":"","posters":{"thumbnail":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","profile":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","detailed":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif","original":"http://d3biamo577v4eu.cloudfront.net/static/images/redesign/poster_default_thumb.gif"},"abridged_cast":[],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/771041962.json","alternate":"http://www.rottentomatoes.com/m/bill_nye_the_science_guy_chemical_reactions/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/771041962/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/771041962/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/771041962/similar.json"}}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=react&page_limit=30&page=1"},"link_template":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"} diff --git a/docs/NativeModules.md b/docs/NativeModules.md deleted file mode 100644 index 4678a94ab..000000000 --- a/docs/NativeModules.md +++ /dev/null @@ -1,181 +0,0 @@ ---- -id: native-modules -title: Native Modules and Views -layout: docs -category: Guides -permalink: docs/native-modules.html -next: TBD -previous: TBD ---- - -If React VR doesn't support a feature that you need, you can build it yourself. - -Perhaps an app needs access to a platform API that React VR doesn't have a corresponding module for yet. Maybe you want to reuse some existing JavaScript code without having to re-implement it in the React context. Or, you want to write some high performance, multi-threaded code for image processing, a database, or other advanced extensions. - -This is a more advanced feature and while we don't expect it to be part of the usual development process, it is essential you know that it exists. - -## Cube Example -One example of using Native Modules is to support interaction between a React VR UI element and a custom Three.js object that you've added to your scene. For example, a geometric cube similar to the one in the [Three.js README](https://github.com/mrdoob/three.js). - -### Setting up the Scene -The React VR framework can handle the camera and renderer setup for you, so you only need to focus on adding objects to your scene and animating them. First, we create the scene in the `init` function of `vr/client.js` (one of the files provided as part of the Starter Project) and provide it as an option to the `VRInstance` constructor. We also create `CubeModule`, a Native Module described later in this section. -``` - const scene = new THREE.Scene(); - const cubeModule = new CubeModule(); - - const vr = new VRInstance(bundle, 'CubeSample', parent, { - cursorVisibility: 'visible', - nativeModules: [ cubeModule ], - scene: scene, - }); -``` -Next, we create the cube mesh and add it to the scene. We use the same Three.js operations as we normally would, with a couple modifications which are often necessary to make Three.js objects appear correctly in React VR. - -* React VR uses units of 1 meter, so we use cube dimensions of 1 instead of 100. -* The VRInstance camera is at the origin, so we change the z position of the cube so it is visible. - -``` - const cube = new THREE.Mesh( - new THREE.BoxGeometry(1, 1, 1), - new THREE.MeshBasicMaterial() - ); - cube.position.z = -4; - scene.add(cube); - cubeModule.init(cube); -``` -Above, we also initialize the `cubeModule` with a handle to the cube. Finally, add the per-frame update logic into the `vr.render` method. -``` - vr.render = function(timestamp) { - const seconds = timestamp / 1000; - cube.position.x = 0 + (1 * (Math.cos(seconds))); - cube.position.y = 0.2 + (1 * Math.abs(Math.sin(seconds))); - }; -``` -### Using the Native Module -Let's say we want the cube to change color based on UI interaction such as a button click. Here is a Native Module that implements the `changeCubeColor` function, which is called asynchronously across the React Native bridge. The `constructor` and `init` methods are called directly in `client.js` to setup the module, as shown above. -``` -export default class CubeModule extends Module { - constructor() { - super('CubeModule'); - } - init(cube) { - this.cube = cube; - } - changeCubeColor(color) { - this.cube.material.color = new THREE.Color(color); - } -} -``` -Now we can call the `changeCubeColor` method from `index.vr.js`, for example in an `onClick` handler. -``` -import NativeModules from 'react-vr'; -... -const CubeModule = NativeModules.CubeModule; -... -render() { -... - CubeModule.changeCubeColor(hexColor)}> - ... - -.. - -``` - -See the `CubeSample` for the full code of this example. - -### Creating Native Views - -By implementing a native view, you can control how the properties specified in your React VR code interact with the runtime code. This can include visual representations and even sound. - -To create a native view, you need to import the main module `react-vr-web` - -``` -import * as ReactVR from 'react-vr-web'; -``` - -Then, create a class that extends the `RCTBaseView`. The constructor should create the `OVRUI.UIView` and register getters and setters on any properties. - -The class also implements a static `describe` function the runtime uses to determine which properties to send from the React VR code to the runtime. These are the runtime implementation of the PropTypes. - -``` -class RCTTestLight extends ReactVR.RCTBaseView { - constructor(guiSys: GuiSys) { - super(); - const light = new THREE.AmbientLight(); - this.view = new OVRUI.UIView(guiSys); - this.view.add(light); - - Object.defineProperty( - this.props, - 'intensity', - { - set: value => { - light.intensity = value; - }, - } - ); - - this.props.intensity = 1; - } - - static describe() { - return merge(super.describe(), { - // declare the native props sent from react to runtime - NativeProps: { - intensity: 'number', - }, - }); - } -} -``` - -Finally, the custom views must be registered to the React VR context. This is handled by providing a list of available `customViews` when creating `ReactVR.VRInstance` - -``` -const vr = new ReactVR.VRInstance(bundlePath, appName, document.body, { - customViews: [{name: 'TestLight', view: RCTTestLight}], - ...options, -}); -``` - - -To make this `TestLight` component available to React VR code, it is necessary to register a component that makes use of `NativeMethodsMixin`. Set the `propTypes` to enable the propTypes to be handled by the React VR core. `viewConfig` is used to support the `Animated` modules. The `render` function should return a component created using the `requireNativeComponent` utility function. - -``` -const TestLight = React.createClass({ - mixins: [NativeMethodsMixin], - - propTypes: { - ...View.propTypes, - style: StyleSheetPropType(LayoutAndTransformPropTypes), - intensity: PropTypes.number, - }, - - viewConfig: { - uiViewClassName: 'AmbientLight', - validAttributes: { - ...ReactNativeViewAttributes.RCTView, - intensity: true, - }, - }, - - getDefaultProps: function() { - return {}; - }, - - render: function() { - return ( - - - ); - }, -}); - -const RKTestLight = requireNativeComponent('TestLight', TestLight, { - nativeOnly: {}, -}); - -module.exports = TestLight; -``` diff --git a/docs/PlatformSpecificInformation.md b/docs/PlatformSpecificInformation.md deleted file mode 100755 index e3ef63ee7..000000000 --- a/docs/PlatformSpecificInformation.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -id: platform-specific-code -title: Platform Specific Code -layout: docs -category: Guides -permalink: docs/platform-specific-code.html -next: view -previous: debugging ---- - -When building a cross-platform app, you usually want to re-use as much code as possible. Scenarios may arise where it makes sense for the code to be different. For example you may want to implement separate visual components for iOS and Android. - -React Native provides two ways to easily organize your code and separate it by platform: - -* Using the [`Platform` module](docs/platform-specific-code.html#platform-module). -* Using [platform-specific file extensions](docs/platform-specific-code.html#platform-specific-extensions). - -Certain components may have properties that work on one platform only. All of these props are annotated with `@platform` and have a small badge next to them on the website. - - -## Platform module - -React Native provides a module that detects the platform in which the app is running. You can use the detection logic to implement platform-specific code. Use this option when only small parts of a component are platform-specific. - -```javascript -import { Platform, StyleSheet } from 'react-native'; - -const styles = StyleSheet.create({ - height: (Platform.OS === 'vr') ? 1 : 100, -}); -``` - -`Platform.OS` will be `vr` when running on WebVR. - -There is also a `Platform.select` method available, that given an object containing Platform.OS as keys, returns the value for the platform you are currently running on. - -```javascript -import { Platform, StyleSheet } from 'react-native'; - -const styles = StyleSheet.create({ - container: { - flex: 1, - ...Platform.select({ - ios: { - backgroundColor: 'red', - }, - android: { - backgroundColor: 'blue', - }, - vr: { - backgroundColor: 'orange', - }, - }), - }, -}); -``` - -This will result in a container having `flex: 1` on all platforms, a red background color on iOS, a blue background color on Android and an orange background color for VR. - -## Platform-specific extensions - -When your platform-specific code is more complex, consider splitting the code out into separate files. React Native detects when a file has a `.ios.`, `.android.` or `.vr.` extension and loads the relevant platform file from other components as required. - -For example, say you have the following files in your project: - -```sh -BigButton.ios.js -BigButton.android.js -BigButton.vr.js -``` - -You can then require the component as follows: - -```javascript -const BigButton = require('./BigButton'); -``` - -React Native automatically picks up the right file based on the running platform. diff --git a/docs/ProjectConfiguration.md b/docs/ProjectConfiguration.md deleted file mode 100644 index 359b3802d..000000000 --- a/docs/ProjectConfiguration.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: project-configuration -title: Project Configuration -layout: docs -category: The Basics -permalink: docs/project-configuration.html -next: vr-browsers ---- - -### Understanding the project structure - -When you initially ran the `react-vr` tool, it created a bunch of files in the project directory. What are they all for? - -* `index.vr.js` is the entry point for your React VR app. It contains your application code. -* `static_assets` contains all external resource files. Textures, models, and other objects you import should be placed here. They can be referenced with the `asset(path)` method, which will automatically resolve to the correct location. -* `vr` contains the support code necessary for running your app. Chances are, you don't need to change these files. This directory contains `index.html`, which is the web page that launches your application. -* `package.json` is a configuration file for your project. It tells `npm` how to install your project's external dependencies, such as the React VR and OVRUI libraries. diff --git a/docs/Publishing.md b/docs/Publishing.md deleted file mode 100644 index 5021b4889..000000000 --- a/docs/Publishing.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -id: publishing -title: Publishing Your Project -layout: docs -category: The Basics -permalink: docs/publishing.html ---- - -### Building a production release - -Once you've built a compelling VR experience, chances are you'll want to share -it on the web. React VR ships with a script to package everything up into a few -files that you can place on your web server. From the root directory of your -project, run the following: - -``` -npm run bundle -``` - -This creates a new directory in `vr` called `build`. Inside are the compiled -versions of your application files. These can be placed on a web server and -should work without any changes as long as they are placed in the -same directory. - -If you use any external assets (`asset()`), you'll also want to copy your -`static_assets` directory alongside your files so that they can be referenced -by your application. At this point, your directory structure should resemble -the following: - -``` -Web Server -├─ static_assets/ -│ -├─ index.html -├─ index.bundle.js -└─ client.bundle.js -``` - -If you want to host your JavaScript files from a separate location, you can do -so by modifying the contents of `index.html`. Make sure the `script` tag at the -top points to the correct location for `client.bundle.js`, and that the call to -`ReactVR.init()` contains the correct path to `index.bundle.js`. - -If you want to host your asset files from a separate location, such as a -dedicated CDN, you can pass the root directory as the `assetRoot` at the -`ReactVR.init()` call. For example, if your files were hosted at -`https://cdn.example.com/vr_assets/`, you would change the method call to -include the following third argument: - -``` -ReactVR.init( - 'path/to/index.bundle.js', - document.body, - { assetRoot: 'https://cdn.example.com/vr_assets/' } -); -``` - -### Integrating with an existing web page - -If you want to embed your VR experience within a web page, the recommended -method is to use an ` - ; - } - - return ( -
- {hero} -

- - {post.author} - - {' — '} - -

-

{title}

-
- ); - } -}); - -module.exports = BlogPostHeader; diff --git a/website/core/DocsSidebar.js b/website/core/DocsSidebar.js deleted file mode 100755 index 1ccd825ca..000000000 --- a/website/core/DocsSidebar.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule DocsSidebar - */ - -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]) { - console.log(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) { - return metadata.permalink; - }, - - render: function() { - return
-
- {this.getCategories().map((category) => -
-

{category.name}

- -
- )} -
-
; - } -}); - -module.exports = DocsSidebar; diff --git a/website/core/ExcerptLink.js b/website/core/ExcerptLink.js deleted file mode 100755 index 7a0ab14f7..000000000 --- a/website/core/ExcerptLink.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule ExcerptLink - */ - -'use strict'; - -var React = require('React'); - -var ExcerptLink = React.createClass({ - render: function() { - var cta = "Read more"; - - if (this.props.category === "videos") { - cta = "Watch video"; - } - - return ( - - ); - } -}); - -module.exports = ExcerptLink; diff --git a/website/core/Footer.js b/website/core/Footer.js index 8ae15cbba..202e0e55b 100755 --- a/website/core/Footer.js +++ b/website/core/Footer.js @@ -1,37 +1,80 @@ /** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. + * Copyright (c) 2017-present, Facebook, Inc. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Footer + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ -var React = require('React'); +const React = require('react'); -function getGitHubPath(path) { - return 'https://github.com/facebook/react-vr/blob/master/' + path; -} +class Footer extends React.Component { + docUrl(doc, language) { + const baseUrl = this.props.config.baseUrl; + return baseUrl + 'docs/' + (language ? language + '/' : '') + doc; + } -var Footer = React.createClass({ - render: function() { - // Link to Issues board instead of repo. Revert back to orignal footer - // (commented out below) when we go open-source. - return ( -

- You can file an issue on GitHub if you see a typo or error on this page! -

- ); - /* + pageUrl(doc, language) { + const baseUrl = this.props.config.baseUrl; + return baseUrl + (language ? language + '/' : '') + doc; + } + + render() { + const currentYear = new Date().getFullYear(); return ( -

- You can edit the content above on GitHub and send us a pull request! -

+ ); - */ } -}); +} module.exports = Footer; diff --git a/website/core/H2.js b/website/core/H2.js deleted file mode 100755 index 7bf4e9278..000000000 --- a/website/core/H2.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule H2 - */ - -var React = require('React'); -var Header = require('Header'); - -var H2 = React.createClass({ - render: function() { - return
{this.props.children}
; - } -}); - -module.exports = H2; diff --git a/website/core/Header.js b/website/core/Header.js deleted file mode 100755 index c83d7334b..000000000 --- a/website/core/Header.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Header - */ - -var React = require('React'); -var slugify = require('slugify'); - -var Header = React.createClass({ - contextTypes: { - permalink: React.PropTypes.string - }, - - render: function() { - var slug = slugify(this.props.toSlug || this.props.children); - var H = 'h' + this.props.level; - var base = this.context.permalink || ''; - return ( - - - {this.props.children} - {' '}# - - ); - } -}); - -module.exports = Header; diff --git a/website/core/HeaderLinks.js b/website/core/HeaderLinks.js deleted file mode 100755 index ddac55711..000000000 --- a/website/core/HeaderLinks.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule HeaderLinks - */ - -var React = require('React'); -var AlgoliaDocSearch = require('AlgoliaDocSearch'); - -var HeaderLinks = React.createClass({ - linksInternal: [ - {section: 'docs', href: 'docs/getting-started.html', text: 'Docs', target: '.nav-docs'}, - ], - linksExternal: [ - {section: 'github', href: 'https://github.com/facebook/react-vr', text: 'GitHub'}, - {section: 'react', href: 'http://facebook.github.io/react', text: 'React'}, - {section: 'react native', href: 'http://facebook.github.io/react-native', text: 'React Native'}, - ], - - makeLinks: function(links) { - return links.map(function(link) { - return ( -
  • - - {link.text} - -
  • - ); - }, this); - }, - - render: function() { - return ( -
    -
      - {this.makeLinks(this.linksInternal)} -
    - -
      - {this.makeLinks(this.linksExternal)} -
    -
    - ); - } -}); - -module.exports = HeaderLinks; diff --git a/website/core/HeaderWithGithub.js b/website/core/HeaderWithGithub.js deleted file mode 100755 index 5b239d888..000000000 --- a/website/core/HeaderWithGithub.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule HeaderWithGithub - */ - -var H = require('Header'); -var React = require('React'); - -function getGitHubPath(path) { - return 'https://github.com/facebook/react-vr/blob/master/' + path; -} - -var HeaderWithGithub = React.createClass({ - - contextTypes: { - version: React.PropTypes.string - }, - - render: function() { - return ( - - - - - - - -
    - - {this.props.title} - - - - Edit on GitHub - -
    - ); - } -}); - -module.exports = HeaderWithGithub; diff --git a/website/core/Hero.js b/website/core/Hero.js deleted file mode 100755 index 8a6674b63..000000000 --- a/website/core/Hero.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Hero - */ - -var React = require('React'); - -var Hero = React.createClass({ - render: function() { - return ( -
    -
    -
    {this.props.title}
    -
    - {this.props.subtitle} -
    -
    - {this.props.children} -
    - ); - } -}); - -module.exports = Hero; diff --git a/website/core/Marked.js b/website/core/Marked.js deleted file mode 100755 index d123b874b..000000000 --- a/website/core/Marked.js +++ /dev/null @@ -1,1113 +0,0 @@ -/** - * marked - a markdown parser - * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - * - * @providesModule Marked - */ - -var React = require('React'); -var Prism = require('Prism'); -var WebPlayer = require('WebPlayer'); -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', - 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); - - var color = cap[0].match(''); - if (color) { - out.push(React.DOM.span({className: 'color', style: {backgroundColor: color[1]}})); - continue; - } - - // 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 ( -
    - {this.inline.output(this.token.text)} -
    - ); - } - case 'code': { - var lang = this.token.lang - , text = this.token.text; - - if (lang && lang.indexOf('ReactNativeWebPlayer') === 0) { - return ( - {text} - ); - } - - return {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 - ? React.DOM.span({dangerouslySetInnerHTML: {__html: 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 100755 index 50b0b3c41..000000000 --- a/website/core/Prism.js +++ /dev/null @@ -1,356 +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 - */ - -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 100755 index 79d79e96c..000000000 --- a/website/core/Site.js +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Site - */ - -var React = require('React'); -var HeaderLinks = require('HeaderLinks'); -var Metadata = require('Metadata'); - -var Site = React.createClass({ - render: function() { - const path = Metadata.config.RN_DEPLOYMENT_PATH; - const version = Metadata.config.RN_VERSION; - const algoliaVersion = version === 'next' ? 'master' : version; - var relative = (this.props.section === 'docs' ? '../' : './'); - var basePath = relative; - var currentYear = (new Date()).getFullYear(); - - var title = this.props.title ? this.props.title : 'React VR | A framework for building VR apps using React'; - - console.log(this.props.section); - var metaTags = [ - { charSet: "utf-8" }, - { - httpEquiv: "X-UA-Compatible", - content: "IE=edge,chrome=1", - }, - { - name: "viewport", - content: "width=device-width", - }, - // Facebook - { property: "fb:app_id", content: "1677033832619985", }, - { property: "fb:admins", content: "121800083", }, - // Open Graph - { - property: "og:site_name", - content: "React Native", - }, - { - property: "og:title", - content: title, - }, - { - property: "og:url", - content: "https://facebook.github.io/react-vr/" + (this.props.path ? this.props.path : "index.html"), - }, - { - property: "og:image", - content: this.props.image ? this.props.image : "https://facebook.github.io/react-vr/img/opengraph.png", - }, - { - property: "og:description", - content: this.props.description ? this.props.description : "A framework for building native apps using React", - }, - // Twitter Cards - { - name: "twitter:site", - content: "@reactnative", - }, - { - name: "twitter:card", - content: "summary_large_image", - }, - ]; - - var typeTags = [{ - property: "og:type", - content: "website", - }]; - if (this.props.author) { - typeTags = [{ - property: "og:type", - content: "article", - }, { - property: "article:author", - content: this.props.author, - }]; - } - metaTags.push(...typeTags); - - if (this.props.authorTwitter) { - metaTags.push({ - name: "twitter:creator", - content: "@" + this.props.authorTwitter, - }); - } - - return ( - - - {title} - { - metaTags.map((tag, index) => - ) - } - - - - - - - - - - - - - - - - + + + + diff --git a/website/static/sample/static_assets/360_world.jpg b/website/static/sample/static_assets/360_world.jpg new file mode 100644 index 000000000..e93388336 Binary files /dev/null and b/website/static/sample/static_assets/360_world.jpg differ