diff --git a/.gitignore b/.gitignore
index 701579a..0a191ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,4 @@ npm-debug.log
*.swp
.DS_Store
**/*-bundle.*.js
-demo/bundle.js
+demo/bundle.*
diff --git a/CHANGES.md b/CHANGES.md
index b272c65..6544f67 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,10 @@
+0.0.11 / 2016-04-30
+===================
+
+* Upgrade to React 0.15.2
+* Check if this.props.children is an array
+
+
0.0.10 / 2016-03-31
===================
diff --git a/dist-modules/Accordion/index.js b/dist-modules/Accordion/index.js
index 09d104d..c6dd389 100644
--- a/dist-modules/Accordion/index.js
+++ b/dist-modules/Accordion/index.js
@@ -88,6 +88,17 @@ var Accordion = function (_Component) {
return null;
}
+ if (!Array.isArray(this.props.children)) {
+ var expanded = !this.props.disabled && this.state.activeItems.indexOf(0) !== -1;
+
+ return _react2.default.cloneElement(this.props.children, {
+ expanded: expanded,
+ key: 0,
+ onClick: this.handleClick.bind(this, 0, this.props.children.props.onClick),
+ ref: 'item-' + 0
+ });
+ }
+
return this.props.children.map(function (item, index) {
var expanded = _this3.state.activeItems.indexOf(index) !== -1;
diff --git a/dist/react-sanfona.js b/dist/react-sanfona.js
index 287a143..26f8921 100644
--- a/dist/react-sanfona.js
+++ b/dist/react-sanfona.js
@@ -64,7 +64,7 @@ return /******/ (function(modules) { // webpackBootstrap
var _Accordion2 = _interopRequireDefault(_Accordion);
- var _AccordionItem = __webpack_require__(150);
+ var _AccordionItem = __webpack_require__(165);
var _AccordionItem2 = _interopRequireDefault(_AccordionItem);
@@ -166,6 +166,17 @@ return /******/ (function(modules) { // webpackBootstrap
return null;
}
+ if (!Array.isArray(this.props.children)) {
+ var expanded = !this.props.disabled && this.state.activeItems.indexOf(0) !== -1;
+
+ return _react2.default.cloneElement(this.props.children, {
+ expanded: expanded,
+ key: 0,
+ onClick: this.handleClick.bind(this, 0, this.props.children.props.onClick),
+ ref: 'item-' + 0
+ });
+ }
+
return this.props.children.map(function (item, index) {
var expanded = _this3.state.activeItems.indexOf(index) !== -1;
@@ -282,7 +293,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {/**
- * Copyright 2013-2015, Facebook, Inc.
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
@@ -296,19 +307,18 @@ return /******/ (function(modules) { // webpackBootstrap
'use strict';
- var ReactCurrentOwner = __webpack_require__(7);
- var ReactDOMTextComponent = __webpack_require__(8);
- var ReactDefaultInjection = __webpack_require__(73);
- var ReactInstanceHandles = __webpack_require__(47);
- var ReactMount = __webpack_require__(30);
- var ReactPerf = __webpack_require__(20);
- var ReactReconciler = __webpack_require__(52);
- var ReactUpdates = __webpack_require__(56);
- var ReactVersion = __webpack_require__(148);
+ var ReactDOMComponentTree = __webpack_require__(7);
+ var ReactDefaultInjection = __webpack_require__(11);
+ var ReactMount = __webpack_require__(154);
+ var ReactPerf = __webpack_require__(37);
+ var ReactReconciler = __webpack_require__(38);
+ var ReactUpdates = __webpack_require__(34);
+ var ReactVersion = __webpack_require__(161);
- var findDOMNode = __webpack_require__(93);
- var renderSubtreeIntoContainer = __webpack_require__(149);
- var warning = __webpack_require__(27);
+ var findDOMNode = __webpack_require__(162);
+ var getNativeComponentFromComposite = __webpack_require__(163);
+ var renderSubtreeIntoContainer = __webpack_require__(164);
+ var warning = __webpack_require__(20);
ReactDefaultInjection.inject();
@@ -330,42 +340,55 @@ return /******/ (function(modules) { // webpackBootstrap
/* eslint-enable camelcase */
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
- CurrentOwner: ReactCurrentOwner,
- InstanceHandles: ReactInstanceHandles,
+ ComponentTree: {
+ getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,
+ getNodeFromInstance: function (inst) {
+ // inst is an internal instance (but could be a composite)
+ if (inst._renderedComponent) {
+ inst = getNativeComponentFromComposite(inst);
+ }
+ if (inst) {
+ return ReactDOMComponentTree.getNodeFromInstance(inst);
+ } else {
+ return null;
+ }
+ }
+ },
Mount: ReactMount,
- Reconciler: ReactReconciler,
- TextComponent: ReactDOMTextComponent
+ Reconciler: ReactReconciler
});
}
if (process.env.NODE_ENV !== 'production') {
- var ExecutionEnvironment = __webpack_require__(11);
+ var ExecutionEnvironment = __webpack_require__(24);
if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
// First check if devtools is not installed
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
// If we're in Chrome or Firefox, provide a download link if not installed.
if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
- console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
+ // Firefox does not have the issue with devtools loaded over file://
+ var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;
+ console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');
}
}
+ var testFunc = function testFn() {};
+ process.env.NODE_ENV !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;
+
// If we're in IE8, check to see if we are in compatibility mode and provide
// information on preventing compatibility mode
var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
- process.env.NODE_ENV !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '') : undefined;
+ process.env.NODE_ENV !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '') : void 0;
var expectedFeatures = [
// shims
- Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim,
-
- // shams
- Object.create, Object.freeze];
+ Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];
for (var i = 0; i < expectedFeatures.length; i++) {
if (!expectedFeatures[i]) {
- console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
+ process.env.NODE_ENV !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;
break;
}
}
@@ -474,1823 +497,2089 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
/* 7 */
-/***/ function(module, exports) {
+/***/ function(module, exports, __webpack_require__) {
- /**
- * Copyright 2013-2015, Facebook, Inc.
+ /* WEBPACK VAR INJECTION */(function(process) {/**
+ * Copyright 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.
*
- * @providesModule ReactCurrentOwner
+ * @providesModule ReactDOMComponentTree
*/
'use strict';
- /**
- * Keeps track of the current owner.
- *
- * The current owner is the component who should own any components that are
- * currently being constructed.
- */
- var ReactCurrentOwner = {
-
- /**
- * @internal
- * @type {ReactComponent}
- */
- current: null
+ var DOMProperty = __webpack_require__(8);
+ var ReactDOMComponentFlags = __webpack_require__(10);
- };
+ var invariant = __webpack_require__(9);
- module.exports = ReactCurrentOwner;
+ var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
+ var Flags = ReactDOMComponentFlags;
-/***/ },
-/* 8 */
-/***/ function(module, exports, __webpack_require__) {
+ var internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);
- /* WEBPACK VAR INJECTION */(function(process) {/**
- * Copyright 2013-2015, 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.
+ /**
+ * Drill down (through composites and empty components) until we get a native or
+ * native text component.
*
- * @providesModule ReactDOMTextComponent
- * @typechecks static-only
+ * This is pretty polymorphic but unavoidable with the current structure we have
+ * for `_renderedChildren`.
*/
+ function getRenderedNativeOrTextFromComponent(component) {
+ var rendered;
+ while (rendered = component._renderedComponent) {
+ component = rendered;
+ }
+ return component;
+ }
- 'use strict';
-
- var DOMChildrenOperations = __webpack_require__(9);
- var DOMPropertyOperations = __webpack_require__(24);
- var ReactComponentBrowserEnvironment = __webpack_require__(28);
- var ReactMount = __webpack_require__(30);
+ /**
+ * Populate `_nativeNode` on the rendered native/text component with the given
+ * DOM node. The passed `inst` can be a composite.
+ */
+ function precacheNode(inst, node) {
+ var nativeInst = getRenderedNativeOrTextFromComponent(inst);
+ nativeInst._nativeNode = node;
+ node[internalInstanceKey] = nativeInst;
+ }
- var assign = __webpack_require__(41);
- var escapeTextContentForBrowser = __webpack_require__(23);
- var setTextContent = __webpack_require__(22);
- var validateDOMNesting = __webpack_require__(72);
+ function uncacheNode(inst) {
+ var node = inst._nativeNode;
+ if (node) {
+ delete node[internalInstanceKey];
+ inst._nativeNode = null;
+ }
+ }
/**
- * Text nodes violate a couple assumptions that React makes about components:
- *
- * - When mounting text into the DOM, adjacent text nodes are merged.
- * - Text nodes cannot be assigned a React root ID.
+ * Populate `_nativeNode` on each child of `inst`, assuming that the children
+ * match up with the DOM (element) children of `node`.
*
- * This component is used to wrap strings in elements so that they can undergo
- * the same reconciliation that is applied to elements.
+ * We cache entire levels at once to avoid an n^2 problem where we access the
+ * children of a node sequentially and have to walk from the start to our target
+ * node every time.
*
- * TODO: Investigate representing React components in the DOM with text nodes.
- *
- * @class ReactDOMTextComponent
- * @extends ReactComponent
- * @internal
+ * Since we update `_renderedChildren` and the actual DOM at (slightly)
+ * different times, we could race here and see a newer `_renderedChildren` than
+ * the DOM nodes we see. To avoid this, ReactMultiChild calls
+ * `prepareToManageChildren` before we change `_renderedChildren`, at which
+ * time the container's child nodes are always cached (until it unmounts).
*/
- var ReactDOMTextComponent = function (props) {
- // This constructor and its argument is currently used by mocks.
- };
-
- assign(ReactDOMTextComponent.prototype, {
-
- /**
- * @param {ReactText} text
- * @internal
- */
- construct: function (text) {
- // TODO: This is really a ReactText (ReactNode), not a ReactElement
- this._currentElement = text;
- this._stringText = '' + text;
-
- // Properties
- this._rootNodeID = null;
- this._mountIndex = 0;
- },
-
- /**
- * Creates the markup for this text node. This node is not intended to have
- * any features besides containing text content.
- *
- * @param {string} rootID DOM ID of the root node.
- * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
- * @return {string} Markup for this text node.
- * @internal
- */
- mountComponent: function (rootID, transaction, context) {
- if (process.env.NODE_ENV !== 'production') {
- if (context[validateDOMNesting.ancestorInfoContextKey]) {
- validateDOMNesting('span', null, context[validateDOMNesting.ancestorInfoContextKey]);
- }
+ function precacheChildNodes(inst, node) {
+ if (inst._flags & Flags.hasCachedChildNodes) {
+ return;
+ }
+ var children = inst._renderedChildren;
+ var childNode = node.firstChild;
+ outer: for (var name in children) {
+ if (!children.hasOwnProperty(name)) {
+ continue;
}
-
- this._rootNodeID = rootID;
- if (transaction.useCreateElement) {
- var ownerDocument = context[ReactMount.ownerDocumentContextKey];
- var el = ownerDocument.createElement('span');
- DOMPropertyOperations.setAttributeForID(el, rootID);
- // Populate node cache
- ReactMount.getID(el);
- setTextContent(el, this._stringText);
- return el;
- } else {
- var escapedText = escapeTextContentForBrowser(this._stringText);
-
- if (transaction.renderToStaticMarkup) {
- // Normally we'd wrap this in a `span` for the reasons stated above, but
- // since this is a situation where React won't take over (static pages),
- // we can simply return the text as it is.
- return escapedText;
- }
-
- return '' + escapedText + '';
+ var childInst = children[name];
+ var childID = getRenderedNativeOrTextFromComponent(childInst)._domID;
+ if (childID == null) {
+ // We're currently unmounting this child in ReactMultiChild; skip it.
+ continue;
}
- },
-
- /**
- * Updates this component by updating the text content.
- *
- * @param {ReactText} nextText The next text content
- * @param {ReactReconcileTransaction} transaction
- * @internal
- */
- receiveComponent: function (nextText, transaction) {
- if (nextText !== this._currentElement) {
- this._currentElement = nextText;
- var nextStringText = '' + nextText;
- if (nextStringText !== this._stringText) {
- // TODO: Save this as pending props and use performUpdateIfNecessary
- // and/or updateComponent to do the actual update for consistency with
- // other component types?
- this._stringText = nextStringText;
- var node = ReactMount.getNode(this._rootNodeID);
- DOMChildrenOperations.updateTextContent(node, nextStringText);
+ // We assume the child nodes are in the same order as the child instances.
+ for (; childNode !== null; childNode = childNode.nextSibling) {
+ if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {
+ precacheNode(childInst, childNode);
+ continue outer;
}
}
- },
-
- unmountComponent: function () {
- ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
+ // We reached the end of the DOM children without finding an ID match.
+ true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : invariant(false) : void 0;
}
+ inst._flags |= Flags.hasCachedChildNodes;
+ }
- });
-
- module.exports = ReactDOMTextComponent;
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)))
-
-/***/ },
-/* 9 */
-/***/ function(module, exports, __webpack_require__) {
-
- /* WEBPACK VAR INJECTION */(function(process) {/**
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule DOMChildrenOperations
- * @typechecks static-only
+ /**
+ * Given a DOM node, return the closest ReactDOMComponent or
+ * ReactDOMTextComponent instance ancestor.
*/
+ function getClosestInstanceFromNode(node) {
+ if (node[internalInstanceKey]) {
+ return node[internalInstanceKey];
+ }
- 'use strict';
+ // Walk up the tree until we find an ancestor whose instance we have cached.
+ var parents = [];
+ while (!node[internalInstanceKey]) {
+ parents.push(node);
+ if (node.parentNode) {
+ node = node.parentNode;
+ } else {
+ // Top of the tree. This node must not be part of a React tree (or is
+ // unmounted, potentially).
+ return null;
+ }
+ }
- var Danger = __webpack_require__(10);
- var ReactMultiChildUpdateTypes = __webpack_require__(18);
- var ReactPerf = __webpack_require__(20);
+ var closest;
+ var inst;
+ for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
+ closest = inst;
+ if (parents.length) {
+ precacheChildNodes(inst, node);
+ }
+ }
- var setInnerHTML = __webpack_require__(21);
- var setTextContent = __webpack_require__(22);
- var invariant = __webpack_require__(15);
+ return closest;
+ }
/**
- * Inserts `childNode` as a child of `parentNode` at the `index`.
- *
- * @param {DOMElement} parentNode Parent node in which to insert.
- * @param {DOMElement} childNode Child node to insert.
- * @param {number} index Index at which to insert the child.
- * @internal
+ * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
+ * instance, or null if the node was not rendered by this React.
*/
- function insertChildAt(parentNode, childNode, index) {
- // By exploiting arrays returning `undefined` for an undefined index, we can
- // rely exclusively on `insertBefore(node, null)` instead of also using
- // `appendChild(node)`. However, using `undefined` is not allowed by all
- // browsers so we must replace it with `null`.
-
- // fix render order error in safari
- // IE8 will throw error when index out of list size.
- var beforeChild = index >= parentNode.childNodes.length ? null : parentNode.childNodes.item(index);
-
- parentNode.insertBefore(childNode, beforeChild);
+ function getInstanceFromNode(node) {
+ var inst = getClosestInstanceFromNode(node);
+ if (inst != null && inst._nativeNode === node) {
+ return inst;
+ } else {
+ return null;
+ }
}
/**
- * Operations for updating with DOM children.
+ * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
+ * DOM node.
*/
- var DOMChildrenOperations = {
-
- dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
-
- updateTextContent: setTextContent,
-
- /**
- * Updates a component's children by processing a series of updates. The
- * update configurations are each expected to have a `parentNode` property.
- *
- * @param {array