react-redux-infuser
Version:
A thin layer wrapping react-redux tools to simplify creating more powerful React containers
1,608 lines (1,373 loc) • 837 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
}
}return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
};
}(); /**
* import React from 'react';
* import { Component } from 'react';
* import infuse from 'react-redux-infuser';
*
* import * as appActions from './actions/appActions';
* import * as miscActions from './actions/miscActions';
* import * as appHandlers from './handlers/appHandlers';
* import * as helpers from './lib/helpers';
*
* class AppContainer extends Component {
* render() {
* const { foo, bar, appActions, miscActions, appHandlers, helpers } = this.props;
*
* // Where `foo, bar` are values bound to the state
* // Where `appActions, miscActions`, trigger redux actions
* // Where `appHandlers` is an object of handler functions bound to this container
* // Where `helpers` is an object of utility functions
*
* return (
* <div>Hello, world!</div>
* )
* }
* }
*
* export default infuse(AppContainer, {
*
* actions: {
* appActions: appActions,
* miscActions: miscActions
* },
*
* binders: {
* appHandlers: appHandlers
* },
*
* modules: {
* helpers: helpers
* },
*
* values: state => ({
* foo: state.app.foo,
* bar: state.app.bar
* })
*
* })
*/
/*
* Import peer dependencies.
*/
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _redux = require('redux');
var _reactRedux = require('react-redux');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}return call && ((typeof call === 'undefined' ? 'undefined' : _typeof(call)) === "object" || typeof call === "function") ? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass)));
}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
/**
* @class Binders
*
* Ok, this is the craziest part. Here's what's going on:
*
* PURPOSE: In order to bind functions to an instance, we need that instance to
* be available. Therefore, we can't just modify props before instantiation because
* they are generated before instantiation. Instead, we need a way to allow
* props to be immutable but still bind prop functions to the instance after
* instantiation.
*/
var Binders = function () {
/*
* The `binders` property of our `propsFor` object consists of many sub-objects.
* Each of these sub-objects is full of functions that should be bound to the
* container.
*
* This function will instead attach prop functions that stand in as proxies.
* Each proxy, when called, will check to see if the necessary bound function
* exists. If so, it'll call it. If not, it'll make it, then call it.
*/
function Binders(binders) {
var _this = this;
_classCallCheck(this, Binders);
/*
* This tracks the value the functions will bind to, I.E. the class instance.
* That instance doesn't exist at the moment the constructor runs so it has to be
* null for now and we'll attach a value to it after we have the instance.
*/
this.__bindTo__ = null;
/*
* Loop over each sub-object and create a corresponding sub-object for it
* on `this`.
*/
Object.keys(binders).forEach(function (binderPackName) {
var binderPack = binders[binderPackName];
var isFunction = typeof binderPack === 'function';
/*
* Loop over each function. We intend to turn it into a function bound
* to the container instance. To do that, we'll create a closure var
* that will hold a reference to the bound function once it exists.
* We then actually create a function that checks to see if this reference
* exists and creates it if not. Then it calls it.
*
* To create the bound function, we expect that we have already set a
* value for `this.__bindTo__` which we can only get once we the instance exists.
*/
if (!isFunction) {
var destBinderPack = _this[binderPackName] = {};
Object.keys(binderPack).forEach(function (fnName) {
var boundFn = null;
destBinderPack[fnName] = function () {
if (!boundFn) {
boundFn = binderPack[fnName].bind(_this.__bindTo__);
}
return boundFn.apply(undefined, arguments);
};
});
/*
* For a single function instead of an object of functions,
* just create a single binder.
*/
} else {
var boundFn = null;
_this[binderPackName] = function () {
if (!boundFn) {
boundFn = binderPack.bind(_this.__bindTo__);
}
return boundFn.apply(undefined, arguments);
};
}
});
}
/*
* This function attaches a value to `this.__bindTo__` so that when our
* prop functions attempt to create necessary bound functions, they'll
* have a value to bind to.
*/
_createClass(Binders, [{
key: 'use',
value: function use(bindTo) {
this.__bindTo__ = bindTo;
}
}]);
return Binders;
}();
/**
* Returns a new, connected component with actions, state values, and
* bound functions in place.
*
* @param {Class} Container A container class for a React app.
* @param {Object} propsFor Takes `actions`, `binders`, `values`, all optionally.
*
* @return {Class} A new, connected React class.
*/
function infuse(Container, propsFor) {
var binderCache = void 0;
/*
* Make sure we have all 3 values or fallbacks for each one.
* This makes each one optional.
*/
var actions = propsFor.actions || {};
var binders = propsFor.binders || {};
var modules = propsFor.modules || {};
var values = propsFor.values || function () {
return {};
};
/*
* There's a potential pitfall in that the `values` property is a function, not an object.
* It's an easy mistake to make so let's throw an error if the user provides an object
* instead of a function.
*/
if (typeof values !== 'function') {
throw new Error('The values property must be a function that selects values from the redux state.');
}
/**
* Runs on update and maps state values to class props.
*
* @param {Object} state Redux state
*
* @return {Object} Defines which state values should be mapped to properties.
*/
function mapStateToProps(state) {
return values(state);
}
/**
* The `actions` property of the `propsFor` config is an object full of sub-objects.
* Each of these sub-objects is full of functions. Here, we'll turn each sub-object
* into a class prop and we'll translate each function into an action creator.
*
* @param {Function} dispatch Reduxy dispatch stuff.
*
* @return {Object} Each value becomes a prop.
*/
function mapDispatchToProps(dispatch) {
var actionCreators = {};
/*
* For every collection of functions, create a destination in `actionCreators`
* where we'll store translated functions.
*/
Object.keys(actions).forEach(function (actionPackName) {
var actionPack = actions[actionPackName];
var isFunction = typeof actionPack === 'function';
if (!isFunction) {
var destActionPack = actionCreators[actionPackName] = {};
/*
* For each function, turn it into a function that triggers an action
* and store it in its destination location.
*/
Object.keys(actionPack).forEach(function (fnName) {
destActionPack[fnName] = (0, _redux.bindActionCreators)(actionPack[fnName], dispatch);
});
} else {
/*
* For functions, just bind the single function.
*/
actionCreators[actionPackName] = (0, _redux.bindActionCreators)(actionPack, dispatch);
}
});
/*
* Here, we'll take the opportunity to piggyback off of `connect`'s mapDispatchToProps
* to add any other modules to the props that the user might have given us
* but this time, we won't use bindActionCreators on them. We can just transfer
* them over.
*/
return Object.assign({}, actionCreators, modules);
}
/*
* In order for everything to work properly, we need a reference to a container instance.
* In order to get that reference, we need to return a proxy class. That proxy class gets
* run through `connect` so that it can have all the mapped state and action props ready to go.
* It's job is then simply to pass its props down the container instance when it's returned.
*/
return (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(function (_React$Component) {
_inherits(_class, _React$Component);
function _class() {
_classCallCheck(this, _class);
return _possibleConstructorReturn(this, (_class.__proto__ || Object.getPrototypeOf(_class)).apply(this, arguments));
}
_createClass(_class, [{
key: 'shouldComponentUpdate',
/*
* Only update the component if a prop has actually changed.
*/
value: function shouldComponentUpdate(nextProps) {
var curProps = this.props;
var shouldUpdate = false;
Object.keys(curProps).some(function (propName) {
if (curProps[propName] !== nextProps[propName]) {
return shouldUpdate = true;
}
});
return shouldUpdate;
}
}, {
key: 'render',
value: function render() {
/*
* Either generate our binder functions or pull them from the
* cache so we don't have to remake them on every render call.
*/
var newBinders = void 0;
if (binderCache) {
newBinders = binderCache;
} else {
newBinders = binderCache = new Binders(binders);
}
/*
* Create our collection of new props to add to the child
*/
var newProps = Object.assign({}, this.props);
Object.keys(newBinders).forEach(function (key) {
if (key !== '__bindTo__') {
newProps[key] = newBinders[key];
}
});
/*
* Instantiate the container and pass down our props to it, including our binder functions as
* well as children in case any exist.
*
* Now that the element exists, pass it into the `use` method on the `Binders` class so that
* when each binder proxy creates the actual bound function upon its first time being
* called, we'll have the value to bind to.
*/
var container = _react2.default.createElement(Container, newProps, this.props.children);
newBinders.use(container);
/*
* Return the cloned element.
*/
return container;
}
}]);
return _class;
}(_react2.default.Component));
}
infuse.Binders = Binders;
module.exports = exports = infuse;
},{"react":217,"react-redux":186,"redux":223}],2:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.updateFoo = updateFoo;
exports.updateBar = updateBar;
function updateFoo(payload) {
return {
type: 'UPDATE_FOO',
payload: payload
};
}
function updateBar(payload) {
return {
type: 'UPDATE_BAR',
payload: payload
};
}
},{}],3:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.clickMe = clickMe;
function clickMe(evt) {
var _props = this.props,
helpers = _props.helpers,
appActions = _props.appActions,
miscActions = _props.miscActions;
evt && evt.preventDefault();
helpers.logStuff();
appActions.updateFoo('foo was updated after click');
appActions.updateBar('bar was updated after click');
miscActions.updateName('name was updated after click');
}
},{}],4:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.logStuff = logStuff;
function logStuff() {
console.log('I am logging stuff because I am a helper');
}
},{}],5:[function(require,module,exports){
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
var _reactRedux = require('react-redux');
var _index = require('../../../bin/index');
var _index2 = _interopRequireDefault(_index);
var _store = require('./store');
var _store2 = _interopRequireDefault(_store);
var _appActions = require('./appActions');
var appActions = _interopRequireWildcard(_appActions);
var _miscActions = require('./miscActions');
var miscActions = _interopRequireWildcard(_miscActions);
var _appHandlers = require('./appHandlers');
var appHandlers = _interopRequireWildcard(_appHandlers);
var _helpers = require('./helpers');
var helpers = _interopRequireWildcard(_helpers);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var App = function (_Component) {
_inherits(App, _Component);
function App() {
_classCallCheck(this, App);
return _possibleConstructorReturn(this, (App.__proto__ || Object.getPrototypeOf(App)).apply(this, arguments));
}
_createClass(App, [{
key: 'render',
value: function render() {
return _react2.default.createElement('input', { type: 'text' });
}
}]);
return App;
}(_react.Component);
var AppContainer = function (_Component2) {
_inherits(AppContainer, _Component2);
_createClass(AppContainer, [{
key: 'componentDidUpdate',
value: function componentDidUpdate() {
console.log('updated');
}
}]);
function AppContainer() {
_classCallCheck(this, AppContainer);
var _this2 = _possibleConstructorReturn(this, (AppContainer.__proto__ || Object.getPrototypeOf(AppContainer)).call(this));
_this2.state = {
stateVal: 'this is the stateVal'
};
return _this2;
}
_createClass(AppContainer, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props,
appActions = _props.appActions,
miscActions = _props.miscActions,
updateBazzer = _props.updateBazzer,
appHandlers = _props.appHandlers,
helpers = _props.helpers;
setTimeout(function () {
helpers.logStuff();
appActions.updateFoo('foo was updated');
appActions.updateBar('bar was updated');
miscActions.updateName('name was updated');
updateBazzer();
}, 3000);
}
}, {
key: 'render',
value: function render() {
var _props2 = this.props,
appHandlers = _props2.appHandlers,
handleNothing = _props2.handleNothing;
return _react2.default.createElement(
'div',
null,
_react2.default.createElement(
'a',
{ onClick: appHandlers.clickMe },
'Click me'
),
_react2.default.createElement(
'div',
null,
'Misc name: ',
this.props.name
),
_react2.default.createElement(
'div',
null,
'App foo: ',
this.props.foo
),
_react2.default.createElement(
'div',
null,
'App bar: ',
this.props.bar
),
_react2.default.createElement(
'div',
null,
'App bazzer: ',
this.props.bazzer
),
_react2.default.createElement(
'a',
{ onClick: handleNothing },
'Click me too'
),
_react2.default.createElement('br', null),
_react2.default.createElement(App, {
appActions: this.props.appActions,
miscActions: this.props.miscActions,
appHandlers: this.props.appHandlers,
helpers: this.props.helpers
})
);
}
}]);
return AppContainer;
}(_react.Component);
var Infused = (0, _index2.default)(AppContainer, {
actions: {
appActions: appActions,
miscActions: miscActions,
updateBazzer: function updateBazzer() {
return { type: 'BAZZER' };
}
},
binders: {
appHandlers: appHandlers,
handleNothing: function handleNothing() {
console.log('my props are', this.props);
}
},
modules: {
helpers: helpers
},
values: function values(state) {
return {
name: state.misc.name,
foo: state.app.foo,
bar: state.app.bar,
bazzer: state.app.bazzer
};
}
});
_reactDom2.default.render(_react2.default.createElement(
_reactRedux.Provider,
{ store: _store2.default },
_react2.default.createElement(Infused, null)
), document.getElementById('app'));
},{"../../../bin/index":1,"./appActions":2,"./appHandlers":3,"./helpers":4,"./miscActions":6,"./store":7,"react":217,"react-dom":51,"react-redux":186}],6:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.updateName = updateName;
function updateName(payload) {
return {
type: 'UPDATE_NAME',
payload: payload
};
}
},{}],7:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _redux = require('redux');
var initialState = {
misc: {
name: 'Papa John'
},
app: {
foo: 'foofoofoo',
bar: 'barbarbar',
bazzer: 1
}
};
function miscReducer() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState.misc;
var action = arguments[1];
switch (action.type) {
case 'UPDATE_NAME':
return Object.assign({}, state, { name: action.payload });
default:
return state;
}
}
function appReducer() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState.app;
var action = arguments[1];
switch (action.type) {
case 'UPDATE_FOO':
return Object.assign({}, state, { foo: action.payload });
case 'UPDATE_BAR':
return Object.assign({}, state, { bar: action.payload });
case 'BAZZER':
return Object.assign({}, state, { bazzer: state.bazzer + 1 });
default:
return state;
}
}
var reducers = {
misc: miscReducer,
app: appReducer
};
function devToolsCompose() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (window.__REDUX_DEVTOOLS_EXTENSION__) {
args.push(window.__REDUX_DEVTOOLS_EXTENSION__());
}
return _redux.compose.apply(null, args);
}
var store = (0, _redux.createStore)((0, _redux.combineReducers)(reducers), initialState, devToolsCompose());
exports.default = store;
},{"redux":223}],8:[function(require,module,exports){
(function (process){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @typechecks
*/
var emptyFunction = require('./emptyFunction');
/**
* Upstream version of event listener. Does not take into account specific
* nature of platform.
*/
var EventListener = {
/**
* Listen to DOM events during the bubble phase.
*
* @param {DOMEventTarget} target DOM element to register listener on.
* @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
* @param {function} callback Callback function.
* @return {object} Object with a `remove` method.
*/
listen: function listen(target, eventType, callback) {
if (target.addEventListener) {
target.addEventListener(eventType, callback, false);
return {
remove: function remove() {
target.removeEventListener(eventType, callback, false);
}
};
} else if (target.attachEvent) {
target.attachEvent('on' + eventType, callback);
return {
remove: function remove() {
target.detachEvent('on' + eventType, callback);
}
};
}
},
/**
* Listen to DOM events during the capture phase.
*
* @param {DOMEventTarget} target DOM element to register listener on.
* @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
* @param {function} callback Callback function.
* @return {object} Object with a `remove` method.
*/
capture: function capture(target, eventType, callback) {
if (target.addEventListener) {
target.addEventListener(eventType, callback, true);
return {
remove: function remove() {
target.removeEventListener(eventType, callback, true);
}
};
} else {
if (process.env.NODE_ENV !== 'production') {
console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');
}
return {
remove: emptyFunction
};
}
},
registerDefault: function registerDefault() {}
};
module.exports = EventListener;
}).call(this,require('_process'))
},{"./emptyFunction":15,"_process":44}],9:[function(require,module,exports){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
'use strict';
var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
/**
* Simple, lightweight module assisting with the detection and context of
* Worker. Helps avoid circular dependencies and allows code to reason about
* whether or not they are in a Worker, even if they never include the main
* `ReactWorker` dependency.
*/
var ExecutionEnvironment = {
canUseDOM: canUseDOM,
canUseWorkers: typeof Worker !== 'undefined',
canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),
canUseViewport: canUseDOM && !!window.screen,
isInWorker: !canUseDOM // For now, this is true - might change in the future.
};
module.exports = ExecutionEnvironment;
},{}],10:[function(require,module,exports){
"use strict";
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
var _hyphenPattern = /-(.)/g;
/**
* Camelcases a hyphenated string, for example:
*
* > camelize('background-color')
* < "backgroundColor"
*
* @param {string} string
* @return {string}
*/
function camelize(string) {
return string.replace(_hyphenPattern, function (_, character) {
return character.toUpperCase();
});
}
module.exports = camelize;
},{}],11:[function(require,module,exports){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
'use strict';
var camelize = require('./camelize');
var msPattern = /^-ms-/;
/**
* Camelcases a hyphenated CSS property name, for example:
*
* > camelizeStyleName('background-color')
* < "backgroundColor"
* > camelizeStyleName('-moz-transition')
* < "MozTransition"
* > camelizeStyleName('-ms-transition')
* < "msTransition"
*
* As Andi Smith suggests
* (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
* is converted to lowercase `ms`.
*
* @param {string} string
* @return {string}
*/
function camelizeStyleName(string) {
return camelize(string.replace(msPattern, 'ms-'));
}
module.exports = camelizeStyleName;
},{"./camelize":10}],12:[function(require,module,exports){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/
var isTextNode = require('./isTextNode');
/*eslint-disable no-bitwise */
/**
* Checks if a given DOM node contains or is another DOM node.
*/
function containsNode(outerNode, innerNode) {
if (!outerNode || !innerNode) {
return false;
} else if (outerNode === innerNode) {
return true;
} else if (isTextNode(outerNode)) {
return false;
} else if (isTextNode(innerNode)) {
return containsNode(outerNode, innerNode.parentNode);
} else if ('contains' in outerNode) {
return outerNode.contains(innerNode);
} else if (outerNode.compareDocumentPosition) {
return !!(outerNode.compareDocumentPosition(innerNode) & 16);
} else {
return false;
}
}
module.exports = containsNode;
},{"./isTextNode":25}],13:[function(require,module,exports){
(function (process){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
var invariant = require('./invariant');
/**
* Convert array-like objects to arrays.
*
* This API assumes the caller knows the contents of the data type. For less
* well defined inputs use createArrayFromMixed.
*
* @param {object|function|filelist} obj
* @return {array}
*/
function toArray(obj) {
var length = obj.length;
// Some browsers builtin objects can report typeof 'function' (e.g. NodeList
// in old versions of Safari).
!(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;
!(typeof length === 'number') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;
!(length === 0 || length - 1 in obj) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;
!(typeof obj.callee !== 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object can\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;
// Old IE doesn't give collections access to hasOwnProperty. Assume inputs
// without method will throw during the slice call and skip straight to the
// fallback.
if (obj.hasOwnProperty) {
try {
return Array.prototype.slice.call(obj);
} catch (e) {
// IE < 9 does not support Array#slice on collections objects
}
}
// Fall back to copying key by key. This assumes all keys have a value,
// so will not preserve sparsely populated inputs.
var ret = Array(length);
for (var ii = 0; ii < length; ii++) {
ret[ii] = obj[ii];
}
return ret;
}
/**
* Perform a heuristic test to determine if an object is "array-like".
*
* A monk asked Joshu, a Zen master, "Has a dog Buddha nature?"
* Joshu replied: "Mu."
*
* This function determines if its argument has "array nature": it returns
* true if the argument is an actual array, an `arguments' object, or an
* HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).
*
* It will return false for other array-like objects like Filelist.
*
* @param {*} obj
* @return {boolean}
*/
function hasArrayNature(obj) {
return (
// not null/false
!!obj && (
// arrays are objects, NodeLists are functions in Safari
typeof obj == 'object' || typeof obj == 'function') &&
// quacks like an array
'length' in obj &&
// not window
!('setInterval' in obj) &&
// no DOM node should be considered an array-like
// a 'select' element has 'length' and 'item' properties on IE8
typeof obj.nodeType != 'number' && (
// a real array
Array.isArray(obj) ||
// arguments
'callee' in obj ||
// HTMLCollection/NodeList
'item' in obj)
);
}
/**
* Ensure that the argument is an array by wrapping it in an array if it is not.
* Creates a copy of the argument if it is already an array.
*
* This is mostly useful idiomatically:
*
* var createArrayFromMixed = require('createArrayFromMixed');
*
* function takesOneOrMoreThings(things) {
* things = createArrayFromMixed(things);
* ...
* }
*
* This allows you to treat `things' as an array, but accept scalars in the API.
*
* If you need to convert an array-like object, like `arguments`, into an array
* use toArray instead.
*
* @param {*} obj
* @return {array}
*/
function createArrayFromMixed(obj) {
if (!hasArrayNature(obj)) {
return [obj];
} else if (Array.isArray(obj)) {
return obj.slice();
} else {
return toArray(obj);
}
}
module.exports = createArrayFromMixed;
}).call(this,require('_process'))
},{"./invariant":23,"_process":44}],14:[function(require,module,exports){
(function (process){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
/*eslint-disable fb-www/unsafe-html*/
var ExecutionEnvironment = require('./ExecutionEnvironment');
var createArrayFromMixed = require('./createArrayFromMixed');
var getMarkupWrap = require('./getMarkupWrap');
var invariant = require('./invariant');
/**
* Dummy container used to render all markup.
*/
var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;
/**
* Pattern used by `getNodeName`.
*/
var nodeNamePattern = /^\s*<(\w+)/;
/**
* Extracts the `nodeName` of the first element in a string of markup.
*
* @param {string} markup String of markup.
* @return {?string} Node name of the supplied markup.
*/
function getNodeName(markup) {
var nodeNameMatch = markup.match(nodeNamePattern);
return nodeNameMatch && nodeNameMatch[1].toLowerCase();
}
/**
* Creates an array containing the nodes rendered from the supplied markup. The
* optionally supplied `handleScript` function will be invoked once for each
* <script> element that is rendered. If no `handleScript` function is supplied,
* an exception is thrown if any <script> elements are rendered.
*
* @param {string} markup A string of valid HTML markup.
* @param {?function} handleScript Invoked once for each rendered <script>.
* @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.
*/
function createNodesFromMarkup(markup, handleScript) {
var node = dummyNode;
!!!dummyNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;
var nodeName = getNodeName(markup);
var wrap = nodeName && getMarkupWrap(nodeName);
if (wrap) {
node.innerHTML = wrap[1] + markup + wrap[2];
var wrapDepth = wrap[0];
while (wrapDepth--) {
node = node.lastChild;
}
} else {
node.innerHTML = markup;
}
var scripts = node.getElementsByTagName('script');
if (scripts.length) {
!handleScript ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;
createArrayFromMixed(scripts).forEach(handleScript);
}
var nodes = Array.from(node.childNodes);
while (node.lastChild) {
node.removeChild(node.lastChild);
}
return nodes;
}
module.exports = createNodesFromMarkup;
}).call(this,require('_process'))
},{"./ExecutionEnvironment":9,"./createArrayFromMixed":13,"./getMarkupWrap":19,"./invariant":23,"_process":44}],15:[function(require,module,exports){
"use strict";
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/
function makeEmptyFunction(arg) {
return function () {
return arg;
};
}
/**
* This function accepts and discards inputs; it has no side effects. This is
* primarily useful idiomatically for overridable function endpoints which
* always need to be callable, since JS lacks a null-call idiom ala Cocoa.
*/
var emptyFunction = function emptyFunction() {};
emptyFunction.thatReturns = makeEmptyFunction;
emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
emptyFunction.thatReturnsNull = makeEmptyFunction(null);
emptyFunction.thatReturnsThis = function () {
return this;
};
emptyFunction.thatReturnsArgument = function (arg) {
return arg;
};
module.exports = emptyFunction;
},{}],16:[function(require,module,exports){
(function (process){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
'use strict';
var emptyObject = {};
if (process.env.NODE_ENV !== 'production') {
Object.freeze(emptyObject);
}
module.exports = emptyObject;
}).call(this,require('_process'))
},{"_process":44}],17:[function(require,module,exports){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
'use strict';
/**
* @param {DOMElement} node input/textarea to focus
*/
function focusNode(node) {
// IE8 can throw "Can't move focus to the control because it is invisible,
// not enabled, or of a type that does not accept the focus." for all kinds of
// reasons that are too expensive and fragile to test.
try {
node.focus();
} catch (e) {}
}
module.exports = focusNode;
},{}],18:[function(require,module,exports){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
/* eslint-disable fb-www/typeof-undefined */
/**
* Same as document.activeElement but wraps in a try-catch block. In IE it is
* not safe to call document.activeElement if there is nothing focused.
*
* The activeElement will be null only if the document or document body is not
* yet defined.
*
* @param {?DOMDocument} doc Defaults to current document.
* @return {?DOMElement}
*/
function getActiveElement(doc) /*?DOMElement*/{
doc = doc || (typeof document !== 'undefined' ? document : undefined);
if (typeof doc === 'undefined') {
return null;
}
try {
return doc.activeElement || doc.body;
} catch (e) {
return doc.body;
}
}
module.exports = getActiveElement;
},{}],19:[function(require,module,exports){
(function (process){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
/*eslint-disable fb-www/unsafe-html */
var ExecutionEnvironment = require('./ExecutionEnvironment');
var invariant = require('./invariant');
/**
* Dummy container used to detect which wraps are necessary.
*/
var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;
/**
* Some browsers cannot use `innerHTML` to render certain elements standalone,
* so we wrap them, render the wrapped nodes, then extract the desired node.
*
* In IE8, certain elements cannot render alone, so wrap all elements ('*').
*/
var shouldWrap = {};
var selectWrap = [1, '<select multiple="true">', '</select>'];
var tableWrap = [1, '<table>', '</table>'];
var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
var svgWrap = [1, '<svg xmlns="http://www.w3.org/2000/svg">', '</svg>'];
var markupWrap = {
'*': [1, '?<div>', '</div>'],
'area': [1, '<map>', '</map>'],
'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
'legend': [1, '<fieldset>', '</fieldset>'],
'param': [1, '<object>', '</object>'],
'tr': [2, '<table><tbody>', '</tbody></table>'],
'optgroup': selectWrap,
'option': selectWrap,
'caption': tableWrap,
'colgroup': tableWrap,
'tbody': tableWrap,
'tfoot': tableWrap,
'thead': tableWrap,
'td': trWrap,
'th': trWrap
};
// Initialize the SVG elements since we know they'll always need to be wrapped
// consistently. If they are created inside a <div> they will be initialized in
// the wrong namespace (and will not display).
var svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];
svgElements.forEach(function (nodeName) {
markupWrap[nodeName] = svgWrap;
shouldWrap[nodeName] = true;
});
/**
* Gets the markup wrap configuration for the supplied `nodeName`.
*
* NOTE: This lazily detects which wraps are necessary for the current browser.
*
* @param {string} nodeName Lowercase `nodeName`.
* @return {?array} Markup wrap configuration, if applicable.
*/
function getMarkupWrap(nodeName) {
!!!dummyNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;
if (!markupWrap.hasOwnProperty(nodeName)) {
nodeName = '*';
}
if (!shouldWrap.hasOwnProperty(nodeName)) {
if (nodeName === '*') {
dummyNode.innerHTML = '<link />';
} else {
dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';
}
shouldWrap[nodeName] = !dummyNode.firstChild;
}
return shouldWrap[nodeName] ? markupWrap[nodeName] : null;
}
module.exports = getMarkupWrap;
}).call(this,require('_process'))
},{"./ExecutionEnvironment":9,"./invariant":23,"_process":44}],20:[function(require,module,exports){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
'use strict';
/**
* Gets the scroll position of the supplied element or window.
*
* The return values are unbounded, unlike `getScrollPosition`. This means they
* may be negative or exceed the element boundaries (which is possible using
* inertial scrolling).
*
* @param {DOMWindow|DOMElement} scrollable
* @return {object} Map with `x` and `y` keys.
*/
function getUnboundedScrollPosition(scrollable) {
if (scrollable.Window && scrollable instanceof scrollable.Window) {
return {
x: scrollable.pageXOffset || scrollable.document.documentElement.scrollLeft,
y: scrollable.pageYOffset || scrollable.document.documentElement.scrollTop
};
}
return {
x: scrollable.scrollLeft,
y: scrollable.scrollTop
};
}
module.exports = getUnboundedScrollPosition;
},{}],21:[function(require,module,exports){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
var _uppercasePattern = /([A-Z])/g;
/**
* Hyphenates a camelcased string, for example:
*
* > hyphenate('backgroundColor')
* < "background-color"
*
* For CSS style names, use `hyphenateStyleName` instead which works properly
* with all vendor prefixes, including `ms`.
*
* @param {string} string
* @return {string}
*/
function hyphenate(string) {
return string.replace(_uppercasePattern, '-$1').toLowerCase();
}
module.exports = hyphenate;
},{}],22:[function(require,module,exports){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
'use strict';
var hyphenate = require('./hyphenate');
var msPattern = /^ms-/;
/**
* Hyphenates a camelcased CSS property name, for example:
*
* > hyphenateStyleName('backgroundColor')
* < "background-color"
* > hyphenateStyleName('MozTransition')
* < "-moz-transition"
* > hyphenateStyleName('msTransition')
* < "-ms-transition"
*
* As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
* is converted to `-ms-`.
*
* @param {string} string
* @return {string}
*/
function hyphenateStyleName(string) {
return hyphenate(string).replace(msPattern, '-ms-');
}
module.exports = hyphenateStyleName;
},{"./hyphenate":21}],23:[function(require,module,exports){
(function (process){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
'use strict';
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/
var validateFormat = function validateFormat(format) {};
if (process.env.NODE_ENV !== 'production') {
validateFormat = function validateFormat(format) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
};
}
function invariant(condition, format, a, b, c, d, e, f) {
validateFormat(format);
if (!condition) {
var error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(format.replace(/%s/g, function () {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
}
module.exports = invariant;
}).call(this,require('_process'))
},{"_process":44}],24:[function(require,module,exports){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
/**
* @param {*} object The object to check.
* @return {boolean} Whether or not the object is a DOM node.
*/
function isNode(object) {
var doc = object ? object.ownerDocument || object : document;
var defaultView = doc.defaultView || window;
return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
}
module.exports = isNode;
},{}],25:[function(require,module,exports){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
var isNode = require('./isNode');
/**
* @param {*} object The object to check.
* @return {boolean} Whether or not the object is a DOM text node.
*/
function isTextNode(object) {
return isNode(object) && object.nodeType == 3;
}
module.exports = isTextNode;
},{"./isNode":24}],26:[function(require,module,exports){
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the