diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..a9ce136 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["react-native"] +} diff --git a/README.md b/README.md index 0a8c541..bfc9ab9 100644 --- a/README.md +++ b/README.md @@ -7,84 +7,45 @@ Meteor-like methods for React Native. If you have questions, you can open a new issue in the repository or ask in the our Gitter chat: https://gitter.im/react-native-meteor/Lobby - - - -- [react-native-meteor](#react-native-meteor) - - [Compatibility notes](#compatibility-notes) - - [What is it for ?](#what-is-it-for-) - - [Install](#install) - - [Install from Git](#install-from-git) - - [Example usage](#example-usage) -- [Connect your components](#connect-your-components) - - [createContainer](#createcontainer) - - [Example](#example) - - [connectMeteor && getMeteorData](#connectmeteor-getmeteordata) - - [Example](#example) -- [Reactive variables](#reactive-variables) -- [Additionals collection methods](#additionals-collection-methods) -- [ListView Components](#listview-components) - - [MeteorListView Component](#meteorlistview-component) - - [Example usage](#example-usage) - - [MeteorComplexListView Component](#meteorcomplexlistview-component) - - [Example usage](#example-usage) -- [API](#api) - - [Meteor Collections](#meteor-collections) - - [Meteor.subscribe](#meteorsubscribe) - - [Meteor.collection(collectionName, options)](#meteorcollectioncollectionname-options) - - [Meteor DDP connection](#meteor-ddp-connection) - - [Meteor.connect(endpoint, options)](#meteorconnectendpoint-options) - - [Meteor.disconnect()](#meteordisconnect) - - [Meteor methods](#meteor-methods) - - [Availables packages](#availables-packages) - - [Convenience packages](#convenience-packages) - - [ReactiveDict](#reactivedict) - - [Meteor.Accounts](#meteoraccounts) - - [FSCollection](#fscollection) - - [Meteor.ddp](#meteorddp) -- [How To ?](#how-to-) - - [react-native-router-flux](#react-native-router-flux) -- [Author](#author) -- [Want to help ?](#want-to-help-) - - - - -## Compatibility notes - -* Since RN 0.26.0 you have to use ws or wss protocol to connect to your meteor server. http is not working on Android. -* It is recommended to always use the latest version of react-native-meteor compatible with your RN version. -* For RN < 0.45, you can use version 1.0.3 in case or problems. -* For RN 0.45, use version 1.0.6 of 'react-native-meteor' -* For RN > 0.45, use 1.1.x -* For RN > 0.49, use 1.2.x - ## What is it for ? The purpose of this library is : -* to set up and maintain a ddp connection with a ddp server, freeing the developer from having to do it on their own. -* be fully compatible with react-native and help react-native developers. -* **to match with [Meteor documentation](http://docs.meteor.com/) used with React.** +* To set up and maintain a ddp connection with a ddp server, freeing the developer from having to do it on their own. +* Be fully compatible with react-native and help react-native developers. +* **To match with [Meteor documentation](http://docs.meteor.com/) used with React.** ## Install - npm i --save react-native-meteor +``` +yarn add react-native-meteor +``` + +or + +``` +npm i --save react-native-meteor +``` [!! See detailed installation guide](https://github.com/inProgress-team/react-native-meteor/blob/master/docs/Install.md) -## Install from Git +## Compatibility notes -Sometimes we do not have time to update the version of the NPM package. In this case, you can use the latest version from the repository. +Since RN 0.26.0 you have to use ws or wss protocol to connect to your meteor server. http is not working on Android. - npm i --save https://github.com/inProgress-team/react-native-meteor +It is recommended to always use the latest version of react-native-meteor compatible with your RN version: + +* For RN > 0.49, use `react-native-meteor@latest` +* For RN > 0.45, use `react-native-meteor@1.1.x` +* For RN = 0.45, use `react-native-meteor@1.0.6` +* For RN < 0.45, you can use version `react-native-meteor@1.0.3` in case or problems. ## Example usage ```javascript import React, { Component } from 'react'; import { View, Text } from 'react-native'; -import Meteor, { createContainer, MeteorListView } from 'react-native-meteor'; +import Meteor, { withTracker, MeteorListView } from 'react-native-meteor'; Meteor.connect('ws://192.168.X.X:3000/websocket'); //do this only once @@ -111,7 +72,7 @@ class App extends Component { } } -export default createContainer(params => { +export default withTracker(params => { const handle = Meteor.subscribe('todos'); Meteor.subscribe('settings'); @@ -119,280 +80,26 @@ export default createContainer(params => { todosReady: handle.ready(), settings: Meteor.collection('settings').findOne(), }; -}, App); -``` - -# Connect your components - -[Since Meteor 1.3, createContainer is the recommended way to populate your React Components](http://guide.meteor.com/v1.3/react.html#using-createContainer). - -## createContainer - -Very similar to getMeteorData but your separate container components from presentational components. - -### Example - -```javascript -import Meteor, { createContainer } from 'react-native-meteor'; - - -class Orders extends Component { - render() { - const { pendingOrders } = this.props; - - //... - ); - } -} - -export default createContainer(params=>{ - return { - pendingOrders: Meteor.collection('orders').find({status: "pending"}), - }; -}, Orders) -``` - -## connectMeteor && getMeteorData - -connectMeteor is a React Mixin which enables getMeteorData (the old way of populating meteor data into your components). - -### Example - -```javascript -import Meteor, { connectMeteor } from 'react-native-meteor'; - -/* -* Uses decorators (see detailed installation to activate it) -* Or use : - - class Todos extends Component { - ... - } - connectMeteor(Todos); - export default Todos; - -*/ - -@connectMeteor -class Orders extends Component { - getMeteorData() { - return { - pendingOrders: Meteor.collection('orders').find({status: "pending"}), - }; - } - render() { - const { pendingOrders } = this.data; - - //... - ); - } -} -``` - -# Reactive variables - -These variables can be used inside getMeteorData or createContainer. They will be populated into your component if they change. - -* [Meteor.subscribe()](http://docs.meteor.com/#/full/meteor_subscribe) -* Meteor.collection(collectionName, options) - * [.find(selector, options)](http://docs.meteor.com/#/full/find) - * [.findOne(selector, options)](http://docs.meteor.com/#/full/findone) -* [Meteor.user()](http://docs.meteor.com/#/full/meteor_user) -* [Meteor.userId()](http://docs.meteor.com/#/full/meteor_userid) -* [Meteor.status()](http://docs.meteor.com/#/full/meteor_status) -* [Meteor.loggingIn()](http://docs.meteor.com/#/full/meteor_loggingin) -* [ReactiveDict()](https://atmospherejs.com/meteor/reactive-dict) - -# Additionals collection methods - -These methods (except update) work offline. That means that elements are correctly updated offline, and when you reconnect to ddp, Meteor calls are taken care of. - -* Meteor.collection(collectionName, options) - * [.insert(doc, callback)](http://docs.meteor.com/#/full/insert) - * [.update(id, modifier, [options], [callback])](http://docs.meteor.com/#/full/update) - * [.remove(id, callback(err, countRemoved))](http://docs.meteor.com/#/full/remove) - -# ListView Components - -## MeteorListView Component - -Same as [ListView](https://facebook.github.io/react-native/docs/listview.html) Component but does not need dataSource and accepts three arguments : - -* `collection` **string** _required_ -* `selector` [**string** / **object**] -* `options` **object** -* `listViewRef` [**string** / **function**] ref to ListView component. - -### Example usage - -```javascript - -``` - -## MeteorComplexListView Component - -Same as [ListView](https://facebook.github.io/react-native/docs/listview.html) Component but does not need dataSource and accepts one argument. You may need it if you make complex requests combining multiples collections. - -* `elements` **function** _required_ : a reactive function which returns an array of elements. -* `listViewRef` [**string** / **function**] ref to ListView component. - -### Example usage - -```javascript - { - return Meteor.collection('todos').find(); - }} - renderRow={this.renderItem} - //...other listview props -/> -``` - -# API - -## Meteor Collections - -### Meteor.subscribe - -[Meteor.subscribe()](http://docs.meteor.com/#/full/meteor_subscribe) returns an handle. If the component which called subscribe is unmounted, the subscription is automatically canceled. - -### Meteor.collection(collectionName, options) - -You need pass the `cursoredFind` option when you get your collection if you want to use cursor-like method: - -```‍‍‍javascript -Meteor.collection("collectionName", { cursoredFind: true }) -``` - -Or you can simply use `find()` to get an array of documents. The option default to false for backward compatibility. Cursor methods are available to share code more easily between a react-native app and a standard Meteor app. - -## Meteor DDP connection - -### Meteor.connect(endpoint, options) - -Connect to a DDP server. You only have to do this once in your app. - -_Arguments_ - -* `url` **string** _required_ -* `options` **object** Available options are : - * autoConnect **boolean** [true] whether to establish the connection to the server upon instantiation. When false, one can manually establish the connection with the Meteor.ddp.connect method. - * autoReconnect **boolean** [true] whether to try to reconnect to the server when the socket connection closes, unless the closing was initiated by a call to the disconnect method. - * reconnectInterval **number** [10000] the interval in ms between reconnection attempts. - -### Meteor.disconnect() - -Disconnect from the DDP server. - -## Meteor methods - -* [Meteor.call](http://docs.meteor.com/#/full/meteor_call) -* [Meteor.loginWithPassword](http://docs.meteor.com/#/full/meteor_loginwithpassword) (Please note that user is auto-resigned in - like in Meteor Web applications - thanks to React Native AsyncStorage.) -* [Meteor.logout](http://docs.meteor.com/#/full/meteor_logout) -* [Meteor.logoutOtherClients](http://docs.meteor.com/#/full/meteor_logoutotherclients) - -## Availables packages - -### Convenience packages - -Example `import { composeWithTracker } from 'react-native-meteor';`` - -* EJSON -* Tracker -* composeWithTracker: If you want to use [react-komposer](https://github.com/kadirahq/react-komposer), you can use react-native-meteor compatible composeWithTracker -* Accounts (see below) - -### ReactiveDict - -See [documentation](https://atmospherejs.com/meteor/reactive-dict). - -### Meteor.Accounts - -`import { Accounts } from 'react-native-meteor';`` - -* [Accounts.createUser](http://docs.meteor.com/#/full/accounts_createuser) -* [Accounts.changePassword](http://docs.meteor.com/#/full/accounts_forgotpassword) -* [Accounts.forgotPassword](http://docs.meteor.com/#/full/accounts_changepassword) -* [Accounts.resetPassword](http://docs.meteor.com/#/full/accounts_resetpassword) -* [Accounts.onLogin](http://docs.meteor.com/#/full/accounts_onlogin) -* [Accounts.onLoginFailure](http://docs.meteor.com/#/full/accounts_onloginfailure) - -### FSCollection - -* Meteor.FSCollection(collectionName) : Helper for [Meteor-CollectionFS](https://github.com/CollectionFS/Meteor-CollectionFS). Full documentation [here](https://github.com/inProgress-team/react-native-meteor/blob/master/docs/FSCollection.md) -* This plugin also exposes a FSCollectionImagesPreloader component which helps you preload every image you want in CollectionFS (only available on ios) - -```javascript -import { FSCollectionImagesPreloader } from 'react-native-meteor'; - - +})(App); ``` -### Meteor.ddp - -Once connected to the ddp server, you can access every method available in [ddp.js](https://github.com/mondora/ddp.js/). +## Documentation -* Meteor.ddp.on('connected') -* Meteor.ddp.on('added') -* Meteor.ddp.on('changed') -* ... +- Learn how to getting started from [connecting your components](docs/connect-your-components.md). +- The [API reference](docs/api.md) lists all public APIs. +- Visit the [How To ?](docs/how-to.md) section for further information. -# How To ? +## Author -## react-native-router-flux - -* You can use Switch with createContainer. Example : - -```javascript - componentWillMount() { - this.scenes = Actions.create( - - - - - - - - - //... - - - - ); - } - composer() { - return { - connected: Meteor.status().connected, - user: Meteor.user() - } - } - selector(data, props) { - if(!data.connected) { - return "loading"; - } else if (!data.user) { - return "login"; - } else { - return "loggedIn"; - } - } -``` +* Théo Mathieu ([@Mokto](https://github.com/Mokto)) from [inProgress](https://in-progress.io) +* Nicolas Charpentier ([@charpeni](https://github.com/charpeni)) -# Author +![image](https://user-images.githubusercontent.com/7189823/40546483-68c5e734-5ffd-11e8-8dd4-bdd11d9fbc93.png) -* Théo Mathieu ([@Mokto](https://github.com/Mokto)) -* From [inProgress](https://in-progress.io) +## Want to help ? -![inProgress](https://in-progress.io/wp-content/uploads/2016/04/LOGO-RESPONSIVE-IPG-01-copie-1.png?2a6543) +Pull Requests and issues reported are welcome! :) -# Want to help ? +## License -Pull Requests and issues reported are welcome! :) +react-native-meteor is [MIT Licensed](LICENSE). diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..7a38ee5 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,156 @@ +# API + +## Reactive variables + +These variables can be used inside getMeteorData or createContainer. They will be populated into your component if they change. + +* [Meteor.subscribe()](http://docs.meteor.com/#/full/meteor_subscribe) +* Meteor.collection(collectionName, options) + * [.find(selector, options)](http://docs.meteor.com/#/full/find) + * [.findOne(selector, options)](http://docs.meteor.com/#/full/findone) +* [Meteor.user()](http://docs.meteor.com/#/full/meteor_user) +* [Meteor.userId()](http://docs.meteor.com/#/full/meteor_userid) +* [Meteor.status()](http://docs.meteor.com/#/full/meteor_status) +* [Meteor.loggingIn()](http://docs.meteor.com/#/full/meteor_loggingin) +* [ReactiveDict()](https://atmospherejs.com/meteor/reactive-dict) + +## Additionals collection methods + +These methods (except update) work offline. That means that elements are correctly updated offline, and when you reconnect to ddp, Meteor calls are taken care of. + +* Meteor.collection(collectionName, options) + * [.insert(doc, callback)](http://docs.meteor.com/#/full/insert) + * [.update(id, modifier, [options], [callback])](http://docs.meteor.com/#/full/update) + * [.remove(id, callback(err, countRemoved))](http://docs.meteor.com/#/full/remove) + +## ListView Components + +### MeteorListView Component + +Same as [ListView](https://facebook.github.io/react-native/docs/listview.html) Component but does not need dataSource and accepts three arguments : + +* `collection` **string** _required_ +* `selector` [**string** / **object**] +* `options` **object** +* `listViewRef` [**string** / **function**] ref to ListView component. + +#### Example usage + +```javascript + +``` + +## MeteorComplexListView Component + +Same as [ListView](https://facebook.github.io/react-native/docs/listview.html) Component but does not need dataSource and accepts one argument. You may need it if you make complex requests combining multiples collections. + +* `elements` **function** _required_ : a reactive function which returns an array of elements. +* `listViewRef` [**string** / **function**] ref to ListView component. + +### Example usage + +```javascript + { + return Meteor.collection('todos').find(); + }} + renderRow={this.renderItem} + //...other listview props +/> +``` + +## Meteor Collections + +### Meteor.subscribe + +[Meteor.subscribe()](http://docs.meteor.com/#/full/meteor_subscribe) returns an handle. If the component which called subscribe is unmounted, the subscription is automatically canceled. + +### Meteor.collection(collectionName, options) + +You need pass the `cursoredFind` option when you get your collection if you want to use cursor-like method: + +```‍‍‍javascript +Meteor.collection("collectionName", { cursoredFind: true }) +``` + +Or you can simply use `find()` to get an array of documents. The option default to false for backward compatibility. Cursor methods are available to share code more easily between a react-native app and a standard Meteor app. + +## Meteor DDP connection + +### Meteor.connect(endpoint, options) + +Connect to a DDP server. You only have to do this once in your app. + +_Arguments_ + +* `url` **string** _required_ +* `options` **object** Available options are : + * autoConnect **boolean** [true] whether to establish the connection to the server upon instantiation. When false, one can manually establish the connection with the Meteor.ddp.connect method. + * autoReconnect **boolean** [true] whether to try to reconnect to the server when the socket connection closes, unless the closing was initiated by a call to the disconnect method. + * reconnectInterval **number** [10000] the interval in ms between reconnection attempts. + +### Meteor.disconnect() + +Disconnect from the DDP server. + +## Meteor methods + +* [Meteor.call](http://docs.meteor.com/#/full/meteor_call) +* [Meteor.loginWithPassword](http://docs.meteor.com/#/full/meteor_loginwithpassword) (Please note that user is auto-resigned in - like in Meteor Web applications - thanks to React Native AsyncStorage.) +* [Meteor.logout](http://docs.meteor.com/#/full/meteor_logout) +* [Meteor.logoutOtherClients](http://docs.meteor.com/#/full/meteor_logoutotherclients) + +## Availables packages + +### Convenience packages + +Example `import { composeWithTracker } from 'react-native-meteor';`` + +* EJSON +* Tracker +* composeWithTracker: If you want to use [react-komposer](https://github.com/kadirahq/react-komposer), you can use react-native-meteor compatible composeWithTracker +* Accounts (see below) + +### ReactiveDict + +See [documentation](https://atmospherejs.com/meteor/reactive-dict). + +### Meteor.Accounts + +`import { Accounts } from 'react-native-meteor';`` + +* [Accounts.createUser](http://docs.meteor.com/#/full/accounts_createuser) +* [Accounts.changePassword](http://docs.meteor.com/#/full/accounts_forgotpassword) +* [Accounts.forgotPassword](http://docs.meteor.com/#/full/accounts_changepassword) +* [Accounts.resetPassword](http://docs.meteor.com/#/full/accounts_resetpassword) +* [Accounts.onLogin](http://docs.meteor.com/#/full/accounts_onlogin) +* [Accounts.onLoginFailure](http://docs.meteor.com/#/full/accounts_onloginfailure) + +### FSCollection + +* Meteor.FSCollection(collectionName) : Helper for [Meteor-CollectionFS](https://github.com/CollectionFS/Meteor-CollectionFS). Full documentation [here](https://github.com/inProgress-team/react-native-meteor/blob/master/docs/FSCollection.md) +* This plugin also exposes a FSCollectionImagesPreloader component which helps you preload every image you want in CollectionFS (only available on ios) + +```javascript +import { FSCollectionImagesPreloader } from 'react-native-meteor'; + + +``` + +### Meteor.ddp + +Once connected to the ddp server, you can access every method available in [ddp.js](https://github.com/mondora/ddp.js/). + +* Meteor.ddp.on('connected') +* Meteor.ddp.on('added') +* Meteor.ddp.on('changed') +* ... diff --git a/docs/connect-your-components.md b/docs/connect-your-components.md new file mode 100644 index 0000000..f73eea2 --- /dev/null +++ b/docs/connect-your-components.md @@ -0,0 +1,92 @@ +# Connect your components + +The `withTracker` function now replaces the previous function `createContainer`, however it remains as part of the package for backwards compatibility. + +## withTracker + +A HOC function, which allows you to create a container component which provides data to your presentational components. + +### Example + +```javascript +import Meteor, { withTracker } from 'react-native-meteor'; + + +class Orders extends Component { + render() { + const { pendingOrders } = this.props; + + //... + ); + } +} + +export default withTracker(params => { + return { + pendingOrders: Meteor.collection('orders').find({ status: "pending" }), + }; +})(Orders); +``` + +## createContainer (Deprecated) + +Very similar to getMeteorData but your separate container components from presentational components. + +### Example + +```javascript +import Meteor, { createContainer } from 'react-native-meteor'; + + +class Orders extends Component { + render() { + const { pendingOrders } = this.props; + + //... + ); + } +} + +export default createContainer(params => { + return { + pendingOrders: Meteor.collection('orders').find({ status: "pending" }), + }; +}, Orders); +``` + +## connectMeteor && getMeteorData (Deprecated) + +connectMeteor is a React Mixin which enables getMeteorData (the old way of populating meteor data into your components). + +### Example + +```javascript +import Meteor, { connectMeteor } from 'react-native-meteor'; + +/* +* Uses decorators (see detailed installation to activate it) +* Or use : + + class Todos extends Component { + ... + } + connectMeteor(Todos); + export default Todos; + +*/ + +@connectMeteor +class Orders extends Component { + getMeteorData() { + return { + pendingOrders: Meteor.collection('orders').find({status: "pending"}), + }; + } + render() { + const { pendingOrders } = this.data; + + //... + ); + } +} +``` diff --git a/docs/how-to.md b/docs/how-to.md new file mode 100644 index 0000000..2e4dbba --- /dev/null +++ b/docs/how-to.md @@ -0,0 +1,39 @@ +# How To ? + +## react-native-router-flux + +* You can use Switch with createContainer. Example : + +```javascript + componentWillMount() { + this.scenes = Actions.create( + + + + + + + + + //... + + + + ); + } + composer() { + return { + connected: Meteor.status().connected, + user: Meteor.user() + } + } + selector(data, props) { + if(!data.connected) { + return "loading"; + } else if (!data.user) { + return "login"; + } else { + return "loggedIn"; + } + } +``` diff --git a/package.json b/package.json index b6c5c6e..bacaa3f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ "precommit": "lint-staged" }, "lint-staged": { - "*.{js,json,md}": ["prettier --write", "git add"] + "*.{js,json,md}": [ + "prettier --write", + "git add" + ] }, "repository": { "type": "git", @@ -43,9 +46,7 @@ }, "devDependencies": { "babel-core": "^6.7.2", - "babel-preset-es2015": "^6.6.0", - "babel-preset-react": "^6.5.0", - "babel-preset-stage-0": "^6.5.0", + "babel-preset-react-native": "^4.0.0", "chai": "^3.5.0", "husky": "^0.14.3", "lint-staged": "^7.1.2", diff --git a/src/Meteor.js b/src/Meteor.js index 66d4a0b..30972ed 100644 --- a/src/Meteor.js +++ b/src/Meteor.js @@ -14,6 +14,7 @@ import Mixin from './components/Mixin'; import MeteorListView from './components/ListView'; import MeteorComplexListView from './components/ComplexListView'; import createContainer from './components/createContainer'; +import withTracker from './components/ReactMeteorData'; import composeWithTracker from './components/composeWithTracker'; import FSCollection from './CollectionFS/FSCollection'; @@ -40,6 +41,7 @@ module.exports = { }, FSCollection, createContainer, + withTracker, getData() { return Data; }, diff --git a/src/components/Mixin.js b/src/components/Mixin.js index 8341b43..cce1888 100644 --- a/src/components/Mixin.js +++ b/src/components/Mixin.js @@ -1,173 +1,6 @@ import Trackr from 'trackr'; import EJSON from 'ejson'; import Data from '../Data'; +import { ReactMeteorData } from './ReactMeteorData'; -export default { - componentWillMount() { - Data.waitDdpReady(() => { - if (this.getMeteorData) { - this.data = {}; - this._meteorDataManager = new MeteorDataManager(this); - const newData = this._meteorDataManager.calculateData(); - this._meteorDataManager.updateData(newData); - } - }); - }, - componentWillUpdate(nextProps, nextState) { - if (this.startMeteorSubscriptions) { - if ( - !EJSON.equals(this.state, nextState) || - !EJSON.equals(this.props, nextProps) - ) { - this._meteorSubscriptionsManager._meteorDataChangedCallback(); - } - } - - if (this.getMeteorData) { - const saveProps = this.props; - const saveState = this.state; - let newData; - try { - // Temporarily assign this.state and this.props, - // so that they are seen by getMeteorData! - // This is a simulation of how the proposed Observe API - // for React will work, which calls observe() after - // componentWillUpdate and after props and state are - // updated, but before render() is called. - // See https://github.com/facebook/react/issues/3398. - this.props = nextProps; - this.state = nextState; - newData = this._meteorDataManager.calculateData(); - } finally { - this.props = saveProps; - this.state = saveState; - } - - this._meteorDataManager.updateData(newData); - } - }, - componentWillUnmount() { - if (this._meteorDataManager) { - this._meteorDataManager.dispose(); - } - - if (this._meteorSubscriptionsManager) { - this._meteorSubscriptionsManager.dispose(); - } - }, -}; - -// A class to keep the state and utility methods needed to manage -// the Meteor data for a component. -class MeteorDataManager { - constructor(component) { - this.component = component; - this.computation = null; - this.oldData = null; - this._meteorDataDep = new Trackr.Dependency(); - - this._meteorDataChangedCallback = () => { - this._meteorDataDep.changed(); - }; - - Data.onChange(this._meteorDataChangedCallback); - } - - dispose() { - if (this.computation) { - this.computation.stop(); - this.computation = null; - } - - Data.offChange(this._meteorDataChangedCallback); - } - - calculateData() { - const component = this.component; - - if (!component.getMeteorData) { - return null; - } - - if (this.computation) { - this.computation.stop(); - this.computation = null; - } - - let data; - // Use Tracker.nonreactive in case we are inside a Tracker Computation. - // This can happen if someone calls `ReactDOM.render` inside a Computation. - // In that case, we want to opt out of the normal behavior of nested - // Computations, where if the outer one is invalidated or stopped, - // it stops the inner one. - - this.computation = Trackr.nonreactive(() => { - return Trackr.autorun(c => { - this._meteorDataDep.depend(); - if (c.firstRun) { - const savedSetState = component.setState; - try { - component.setState = () => { - throw new Error( - "Can't call `setState` inside `getMeteorData` as this could cause an endless" + - ' loop. To respond to Meteor data changing, consider making this component' + - ' a "wrapper component" that only fetches data and passes it in as props to' + - ' a child component. Then you can use `componentWillReceiveProps` in that' + - ' child component.' - ); - }; - - data = component.getMeteorData(); - } finally { - component.setState = savedSetState; - } - } else { - // Stop this computation instead of using the re-run. - // We use a brand-new autorun for each call to getMeteorData - // to capture dependencies on any reactive data sources that - // are accessed. The reason we can't use a single autorun - // for the lifetime of the component is that Tracker only - // re-runs autoruns at flush time, while we need to be able to - // re-call getMeteorData synchronously whenever we want, e.g. - // from componentWillUpdate. - c.stop(); - // Calling forceUpdate() triggers componentWillUpdate which - // recalculates getMeteorData() and re-renders the component. - try { - component.forceUpdate(); - } catch (e) { - console.error(e); - } - } - }); - }); - - return data; - } - - updateData(newData) { - const component = this.component; - const oldData = this.oldData; - - if (!(newData && typeof newData === 'object')) { - throw new Error('Expected object returned from getMeteorData'); - } - // update componentData in place based on newData - for (let key in newData) { - component.data[key] = newData[key]; - } - // if there is oldData (which is every time this method is called - // except the first), delete keys in newData that aren't in - // oldData. don't interfere with other keys, in case we are - // co-existing with something else that writes to a component's - // this.data. - if (oldData) { - for (let key in oldData) { - if (!(key in newData)) { - delete component.data[key]; - } - } - } - this.oldData = newData; - } -} +export default ReactMeteorData; diff --git a/src/components/ReactMeteorData.js b/src/components/ReactMeteorData.js new file mode 100644 index 0000000..d352ead --- /dev/null +++ b/src/components/ReactMeteorData.js @@ -0,0 +1,91 @@ +import React from 'react'; +import EJSON from 'ejson'; + +import Data from '../Data'; +import MeteorDataManager from './MeteorDataManager'; + +const ReactMeteorData = { + componentWillMount() { + Data.waitDdpReady(() => { + if (this.getMeteorData) { + this.data = {}; + this._meteorDataManager = new MeteorDataManager(this); + const newData = this._meteorDataManager.calculateData(); + this._meteorDataManager.updateData(newData); + } + }); + }, + + componentWillUpdate(nextProps, nextState) { + if (this.startMeteorSubscriptions) { + if ( + !EJSON.equals(this.state, nextState) || + !EJSON.equals(this.props, nextProps) + ) { + this._meteorSubscriptionsManager._meteorDataChangedCallback(); + } + } + + if (this.getMeteorData) { + const saveProps = this.props; + const saveState = this.state; + let newData; + try { + // Temporarily assign this.state and this.props, + // so that they are seen by getMeteorData! + // This is a simulation of how the proposed Observe API + // for React will work, which calls observe() after + // componentWillUpdate and after props and state are + // updated, but before render() is called. + // See https://github.com/facebook/react/issues/3398. + this.props = nextProps; + this.state = nextState; + newData = this._meteorDataManager.calculateData(); + } finally { + this.props = saveProps; + this.state = saveState; + } + + this._meteorDataManager.updateData(newData); + } + }, + + componentWillUnmount() { + if (this._meteorDataManager) { + this._meteorDataManager.dispose(); + } + + if (this._meteorSubscriptionsManager) { + this._meteorSubscriptionsManager.dispose(); + } + }, +}; + +export { ReactMeteorData }; + +class ReactComponent extends React.Component {} +Object.assign(ReactComponent.prototype, ReactMeteorData); +class ReactPureComponent extends React.PureComponent {} +Object.assign(ReactPureComponent.prototype, ReactMeteorData); + +export default function connect(options) { + let expandedOptions = options; + if (typeof options === 'function') { + expandedOptions = { + getMeteorData: options, + }; + } + + const { getMeteorData, pure = true } = expandedOptions; + + const BaseComponent = pure ? ReactPureComponent : ReactComponent; + return WrappedComponent => + class ReactMeteorDataComponent extends BaseComponent { + getMeteorData() { + return getMeteorData(this.props); + } + render() { + return ; + } + }; +} diff --git a/src/components/createContainer.js b/src/components/createContainer.js index a21d2c4..3ba7bbe 100644 --- a/src/components/createContainer.js +++ b/src/components/createContainer.js @@ -1,87 +1,14 @@ -import React from 'react'; -import EJSON from 'ejson'; +import connect from './ReactMeteorData'; -import Data from '../Data'; -import MeteorDataManager from './MeteorDataManager'; +let hasDisplayedWarning = false; -export default function createContainer( - mapMeteorDataToProps, - WrappedComponent -) { - class componentWithMeteorContainer extends React.Component { - constructor(props) { - super(props); - - this.getMeteorData = this.getMeteorData.bind(this); - } - - getMeteorData() { - return mapMeteorDataToProps(this.props); - } - - componentWillMount() { - Data.waitDdpReady(() => { - if (this.getMeteorData) { - this.data = {}; - this._meteorDataManager = new MeteorDataManager(this); - const newData = this._meteorDataManager.calculateData(); - this._meteorDataManager.updateData(newData); - } - }); - } - - componentWillUpdate(nextProps, nextState) { - if (this.startMeteorSubscriptions) { - if ( - !EJSON.equals(this.state, nextState) || - !EJSON.equals(this.props, nextProps) - ) { - this._meteorSubscriptionsManager._meteorDataChangedCallback(); - } - } - - if (this.getMeteorData) { - const saveProps = this.props; - const saveState = this.state; - let newData; - try { - // Temporarily assign this.state and this.props, - // so that they are seen by getMeteorData! - // This is a simulation of how the proposed Observe API - // for React will work, which calls observe() after - // componentWillUpdate and after props and state are - // updated, but before render() is called. - // See https://github.com/facebook/react/issues/3398. - this.props = nextProps; - this.state = nextState; - newData = this._meteorDataManager.calculateData(); - } finally { - this.props = saveProps; - this.state = saveState; - } - - this._meteorDataManager.updateData(newData); - } - } - - componentWillUnmount() { - if (this._meteorDataManager) { - this._meteorDataManager.dispose(); - } - - if (this._meteorSubscriptionsManager) { - this._meteorSubscriptionsManager.dispose(); - } - } - - render() { - return ; - } +export default function createContainer(options, Component) { + if (__DEV__ && !hasDisplayedWarning) { + console.warn( + 'Warning: createContainer is deprecated, use withTracker instead.' + ); + hasDisplayedWarning = true; } - const newDisplayName = - WrappedComponent.displayName || WrappedComponent.name || 'Component'; - componentWithMeteorContainer.displayName = `WithMeteorContainer(${newDisplayName})`; - - return componentWithMeteorContainer; + return connect(options)(Component); } diff --git a/yarn.lock b/yarn.lock index 5e0de72..4ba03f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -196,22 +196,6 @@ babel-generator@^6.26.0: source-map "^0.5.7" trim-right "^1.0.1" -babel-helper-bindify-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - babel-helper-builder-react-jsx@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" @@ -238,23 +222,6 @@ babel-helper-define-map@^6.24.1: babel-types "^6.26.0" lodash "^4.17.4" -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-explode-class@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - dependencies: - babel-helper-bindify-decorators "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" @@ -286,24 +253,6 @@ babel-helper-optimise-call-expression@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" @@ -328,57 +277,35 @@ babel-messages@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-check-es2015-constants@^6.22.0: +babel-plugin-check-es2015-constants@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" dependencies: babel-runtime "^6.22.0" -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" +babel-plugin-react-transform@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz#402f25137b7bb66e9b54ead75557dfbc7ecaaa74" + dependencies: + lodash "^4.6.1" -babel-plugin-syntax-async-generators@^6.5.0: +babel-plugin-syntax-async-functions@^6.5.0: version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - -babel-plugin-syntax-class-constructor-call@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" -babel-plugin-syntax-class-properties@^6.8.0: +babel-plugin-syntax-class-properties@^6.5.0, babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" -babel-plugin-syntax-decorators@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - -babel-plugin-syntax-do-expressions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" - babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-export-extensions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" - -babel-plugin-syntax-flow@^6.18.0: +babel-plugin-syntax-flow@^6.18.0, babel-plugin-syntax-flow@^6.5.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" -babel-plugin-syntax-function-bind@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46" - -babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: +babel-plugin-syntax-jsx@^6.5.0, babel-plugin-syntax-jsx@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -386,35 +313,11 @@ babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" -babel-plugin-syntax-trailing-function-commas@^6.22.0: +babel-plugin-syntax-trailing-function-commas@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-transform-async-generator-functions@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-generators "^6.5.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-constructor-call@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9" - dependencies: - babel-plugin-syntax-class-constructor-call "^6.18.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-class-properties@^6.24.1: +babel-plugin-transform-class-properties@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" dependencies: @@ -423,36 +326,13 @@ babel-plugin-transform-class-properties@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - dependencies: - babel-helper-explode-class "^6.24.1" - babel-plugin-syntax-decorators "^6.13.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-do-expressions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb" - dependencies: - babel-plugin-syntax-do-expressions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: +babel-plugin-transform-es2015-arrow-functions@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.24.1: +babel-plugin-transform-es2015-block-scoping@^6.5.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" dependencies: @@ -462,7 +342,7 @@ babel-plugin-transform-es2015-block-scoping@^6.24.1: babel-types "^6.26.0" lodash "^4.17.4" -babel-plugin-transform-es2015-classes@^6.24.1: +babel-plugin-transform-es2015-classes@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" dependencies: @@ -476,33 +356,26 @@ babel-plugin-transform-es2015-classes@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-computed-properties@^6.24.1: +babel-plugin-transform-es2015-computed-properties@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-destructuring@^6.22.0: +babel-plugin-transform-es2015-destructuring@^6.5.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-duplicate-keys@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.22.0: +babel-plugin-transform-es2015-for-of@^6.5.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-function-name@^6.24.1: +babel-plugin-transform-es2015-function-name@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" dependencies: @@ -510,21 +383,13 @@ babel-plugin-transform-es2015-function-name@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-plugin-transform-es2015-literals@^6.22.0: +babel-plugin-transform-es2015-literals@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.24.1: +babel-plugin-transform-es2015-modules-commonjs@^6.5.0: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" dependencies: @@ -533,30 +398,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.24.1: babel-template "^6.26.0" babel-types "^6.26.0" -babel-plugin-transform-es2015-modules-systemjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.24.1: +babel-plugin-transform-es2015-parameters@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" dependencies: @@ -567,104 +409,59 @@ babel-plugin-transform-es2015-parameters@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-shorthand-properties@^6.24.1: +babel-plugin-transform-es2015-shorthand-properties@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-plugin-transform-es2015-spread@^6.22.0: +babel-plugin-transform-es2015-spread@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: +babel-plugin-transform-es2015-template-literals@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-export-extensions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" - dependencies: - babel-plugin-syntax-export-extensions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: +babel-plugin-transform-flow-strip-types@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" dependencies: babel-plugin-syntax-flow "^6.18.0" babel-runtime "^6.22.0" -babel-plugin-transform-function-bind@^6.22.0: +babel-plugin-transform-object-assign@^6.5.0: version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba" dependencies: - babel-plugin-syntax-function-bind "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-object-rest-spread@^6.22.0: +babel-plugin-transform-object-rest-spread@^6.5.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" -babel-plugin-transform-react-display-name@^6.23.0: +babel-plugin-transform-react-display-name@^6.5.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: +babel-plugin-transform-react-jsx-source@^6.5.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" dependencies: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-react-jsx@^6.24.1: +babel-plugin-transform-react-jsx@^6.5.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" dependencies: @@ -672,7 +469,7 @@ babel-plugin-transform-react-jsx@^6.24.1: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-regenerator@^6.24.1: +babel-plugin-transform-regenerator@^6.5.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" dependencies: @@ -685,86 +482,41 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-preset-es2015@^6.6.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - -babel-preset-react@^6.5.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.24.1" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-preset-stage-0@^6.5.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz#5642d15042f91384d7e5af8bc88b1db95b039e6a" - dependencies: - babel-plugin-transform-do-expressions "^6.22.0" - babel-plugin-transform-function-bind "^6.22.0" - babel-preset-stage-1 "^6.24.1" - -babel-preset-stage-1@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0" - dependencies: - babel-plugin-transform-class-constructor-call "^6.24.1" - babel-plugin-transform-export-extensions "^6.22.0" - babel-preset-stage-2 "^6.24.1" - -babel-preset-stage-2@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" +babel-preset-react-native@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-4.0.0.tgz#3df80dd33a453888cdd33bdb87224d17a5d73959" dependencies: + babel-plugin-check-es2015-constants "^6.5.0" + babel-plugin-react-transform "^3.0.0" + babel-plugin-syntax-async-functions "^6.5.0" + babel-plugin-syntax-class-properties "^6.5.0" babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.24.1" - babel-plugin-transform-decorators "^6.24.1" - babel-preset-stage-3 "^6.24.1" - -babel-preset-stage-3@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.24.1" - babel-plugin-transform-async-to-generator "^6.24.1" - babel-plugin-transform-exponentiation-operator "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.22.0" + babel-plugin-syntax-flow "^6.5.0" + babel-plugin-syntax-jsx "^6.5.0" + babel-plugin-syntax-trailing-function-commas "^6.5.0" + babel-plugin-transform-class-properties "^6.5.0" + babel-plugin-transform-es2015-arrow-functions "^6.5.0" + babel-plugin-transform-es2015-block-scoping "^6.5.0" + babel-plugin-transform-es2015-classes "^6.5.0" + babel-plugin-transform-es2015-computed-properties "^6.5.0" + babel-plugin-transform-es2015-destructuring "^6.5.0" + babel-plugin-transform-es2015-for-of "^6.5.0" + babel-plugin-transform-es2015-function-name "^6.5.0" + babel-plugin-transform-es2015-literals "^6.5.0" + babel-plugin-transform-es2015-modules-commonjs "^6.5.0" + babel-plugin-transform-es2015-parameters "^6.5.0" + babel-plugin-transform-es2015-shorthand-properties "^6.5.0" + babel-plugin-transform-es2015-spread "^6.5.0" + babel-plugin-transform-es2015-template-literals "^6.5.0" + babel-plugin-transform-flow-strip-types "^6.5.0" + babel-plugin-transform-object-assign "^6.5.0" + babel-plugin-transform-object-rest-spread "^6.5.0" + babel-plugin-transform-react-display-name "^6.5.0" + babel-plugin-transform-react-jsx "^6.5.0" + babel-plugin-transform-react-jsx-source "^6.5.0" + babel-plugin-transform-regenerator "^6.5.0" + babel-template "^6.24.1" + react-transform-hmr "^1.0.4" babel-register@^6.26.0: version "6.26.0" @@ -1162,6 +914,10 @@ diff@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + domexception@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -1475,6 +1231,13 @@ glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +global@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + dependencies: + min-document "^2.19.0" + process "~0.5.1" + globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -2001,10 +1764,6 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -2168,7 +1927,7 @@ lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" -lodash@^4.13.1, lodash@^4.17.4, lodash@^4.17.5: +lodash@^4.13.1, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.6.1: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" @@ -2276,6 +2035,12 @@ mime-types@^2.1.12, mime-types@~2.1.17: dependencies: mime-db "~1.33.0" +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + dependencies: + dom-walk "^0.1.0" + minimatch@0.3: version "0.3.0" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" @@ -2583,6 +2348,10 @@ private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -2627,6 +2396,10 @@ randomatic@^3.0.0: kind-of "^6.0.0" math-random "^1.0.1" +react-deep-force-update@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c" + react-komposer@^1.8.0: version "1.13.1" resolved "https://registry.yarnpkg.com/react-komposer/-/react-komposer-1.13.1.tgz#4b8ac4bcc71323bd7413dcab95c831197f50eed0" @@ -2644,9 +2417,19 @@ react-mixin@^3.0.3: object-assign "^4.0.1" smart-mixin "^2.0.0" -regenerate@^1.2.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" +react-proxy@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a" + dependencies: + lodash "^4.6.1" + react-deep-force-update "^1.0.0" + +react-transform-hmr@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz#e1a40bd0aaefc72e8dfd7a7cda09af85066397bb" + dependencies: + global "^4.3.0" + react-proxy "^1.1.7" regenerator-runtime@^0.11.0: version "0.11.1" @@ -2673,24 +2456,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"