react-addons
Advanced tools
Comparing version 0.8.0 to 0.9.0
41
index.js
@@ -1,40 +0,1 @@ | ||
/** | ||
* Copyright 2013 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. | ||
* | ||
* @providesModule ReactWithAddons | ||
*/ | ||
/** | ||
* This module exists purely in the open source project, and is meant as a way | ||
* to create a separate standalone build of React. This build has "addons", or | ||
* functionality we've built and think might be useful but doesn't have a good | ||
* place to live inside React core. | ||
*/ | ||
"use strict"; | ||
var LinkedStateMixin = require("./lib/LinkedStateMixin"); | ||
var ReactTransitionGroup = require("./lib/ReactTransitionGroup"); | ||
var cx = require("./lib/cx"); | ||
module.exports = { | ||
classSet: cx, | ||
LinkedStateMixin: LinkedStateMixin, | ||
TransitionGroup: ReactTransitionGroup, | ||
// Somebody will type this in as `ReactTransitionGroup` instead, | ||
// best to support it. | ||
ReactTransitionGroup: ReactTransitionGroup | ||
}; | ||
module.exports = require('./lib/ReactWithAddons'); |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -25,3 +25,3 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
* that should be used when dealing with the display of elements (via their | ||
* CSS classes and visibility on screeni. It is an API focused on mutating the | ||
* CSS classes and visibility on screen. It is an API focused on mutating the | ||
* display and not reading it as no logical state should be encoded in the | ||
@@ -31,20 +31,2 @@ * display of elements. | ||
/** | ||
* Tests whether the element has the class specified. | ||
* | ||
* Note: This function is not exported in CSSCore because CSS classNames should | ||
* not store any logical information about the element. Use DataStore to store | ||
* information on an element. | ||
* | ||
* @param {DOMElement} element the element to set the class on | ||
* @param {string} className the CSS className | ||
* @returns {boolean} true if the element has the class, false if not | ||
*/ | ||
function hasClass(element, className) { | ||
if (element.classList) { | ||
return !!className && element.classList.contains(className); | ||
} | ||
return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1; | ||
} | ||
var CSSCore = { | ||
@@ -69,3 +51,3 @@ | ||
element.classList.add(className); | ||
} else if (!hasClass(element, className)) { | ||
} else if (!CSSCore.hasClass(element, className)) { | ||
element.className = element.className + ' ' + className; | ||
@@ -94,3 +76,3 @@ } | ||
element.classList.remove(className); | ||
} else if (hasClass(element, className)) { | ||
} else if (CSSCore.hasClass(element, className)) { | ||
element.className = element.className | ||
@@ -115,5 +97,24 @@ .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1') | ||
return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className); | ||
}, | ||
/** | ||
* Tests whether the element has the class specified. | ||
* | ||
* @param {DOMNode|DOMWindow} element the element to set the class on | ||
* @param {string} className the CSS className | ||
* @returns {boolean} true if the element has the class, false if not | ||
*/ | ||
hasClass: function(element, className) { | ||
("production" !== process.env.NODE_ENV ? invariant( | ||
!/\s/.test(className), | ||
'CSS.hasClass takes only a single class name.' | ||
) : invariant(!/\s/.test(className))); | ||
if (element.classList) { | ||
return !!className && element.classList.contains(className); | ||
} | ||
return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1; | ||
} | ||
}; | ||
module.exports = CSSCore; |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -36,4 +36,4 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
if (typeof classNames == 'object') { | ||
return Object.keys(classNames).map(function(className) { | ||
return classNames[className] ? className : ''; | ||
return Object.keys(classNames).filter(function(className) { | ||
return classNames[className]; | ||
}).join(' '); | ||
@@ -40,0 +40,0 @@ } else { |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -37,2 +37,5 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
canUseEventListeners: | ||
canUseDOM && (window.addEventListener || window.attachEvent), | ||
isInWorker: !canUseDOM // For now, this is true - might change in the future. | ||
@@ -39,0 +42,0 @@ |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -19,7 +19,10 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
"use strict"; | ||
/** | ||
* Use invariant() to assert state which your program assumes to be true. | ||
* | ||
* Provide sprintf style format and arguments to provide information about | ||
* what broke and what you were expecting. | ||
* Provide sprintf-style format (only %s is supported) and arguments | ||
* to provide information about what broke and what you were | ||
* expecting. | ||
* | ||
@@ -30,12 +33,15 @@ * The invariant message will be stripped in production, but the invariant | ||
function invariant(condition) { | ||
var invariant = function(condition) { | ||
if (!condition) { | ||
throw new Error('Invariant Violation'); | ||
var error = new Error( | ||
'Minified exception occured; use the non-minified dev environment for ' + | ||
'the full error message and additional helpful warnings.' | ||
); | ||
error.framesToPop = 1; | ||
throw error; | ||
} | ||
} | ||
}; | ||
module.exports = invariant; | ||
if ("production" !== process.env.NODE_ENV) { | ||
var invariantDev = function(condition, format, a, b, c, d, e, f) { | ||
invariant = function(condition, format, a, b, c, d, e, f) { | ||
if (format === undefined) { | ||
@@ -48,10 +54,12 @@ throw new Error('invariant requires an error message argument'); | ||
var argIndex = 0; | ||
throw new Error( | ||
var error = new Error( | ||
'Invariant Violation: ' + | ||
format.replace(/%s/g, function() { return args[argIndex++]; }) | ||
); | ||
error.framesToPop = 1; // we don't care about invariant's own frame | ||
throw error; | ||
} | ||
}; | ||
} | ||
module.exports = invariantDev; | ||
} | ||
module.exports = invariant; |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -4,0 +4,0 @@ * Licensed under the Apache License, Version 2.0 (the "License"); |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -21,2 +21,4 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
var invariant = require("./invariant"); | ||
/** | ||
@@ -75,2 +77,6 @@ * Static poolers. Several custom versions for each potential number of | ||
var Klass = this; | ||
("production" !== process.env.NODE_ENV ? invariant( | ||
instance instanceof Klass, | ||
'Trying to release an instance into a pool of a different type.' | ||
) : invariant(instance instanceof Klass)); | ||
if (instance.destructor) { | ||
@@ -77,0 +83,0 @@ instance.destructor(); |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -55,3 +55,3 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
* | ||
* @param {array} children | ||
* @param {?*} children Children tree container. | ||
* @param {function(*, int)} forEachFunc. | ||
@@ -111,6 +111,6 @@ * @param {*} forEachContext Context for forEachContext. | ||
* | ||
* @param {array} children | ||
* @param {?*} children Children tree container. | ||
* @param {function(*, int)} mapFunction. | ||
* @param {*} mapContext Context for mapFunction. | ||
* @return {array} mirrored array with mapped children. | ||
* @return {object} Object containing the ordered map of results. | ||
*/ | ||
@@ -117,0 +117,0 @@ function mapChildren(children, func, context) { |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -42,3 +42,3 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
* We have provided some sugary mixins to make the creation and | ||
* consumption of ReactLink easier; see LinkedValueMixin and LinkedStateMixin. | ||
* consumption of ReactLink easier; see LinkedValueUtils and LinkedStateMixin. | ||
*/ | ||
@@ -45,0 +45,0 @@ |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -4,0 +4,0 @@ * Licensed under the Apache License, Version 2.0 (the "License"); |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -4,0 +4,0 @@ * Licensed under the Apache License, Version 2.0 (the "License"); |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -22,13 +22,13 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
var React = require("react"); | ||
var ReactTransitionableChild = require("./ReactTransitionableChild"); | ||
var ReactTransitionKeySet = require("./ReactTransitionKeySet"); | ||
var ReactTransitionChildMapping = require("./ReactTransitionChildMapping"); | ||
var cloneWithProps = require("./cloneWithProps"); | ||
var emptyFunction = require("./emptyFunction"); | ||
var merge = require("./merge"); | ||
var ReactTransitionGroup = React.createClass({ | ||
propTypes: { | ||
transitionName: React.PropTypes.string.isRequired, | ||
transitionEnter: React.PropTypes.bool, | ||
transitionLeave: React.PropTypes.bool, | ||
onTransition: React.PropTypes.func, | ||
component: React.PropTypes.func | ||
component: React.PropTypes.func, | ||
childFactory: React.PropTypes.func | ||
}, | ||
@@ -38,74 +38,149 @@ | ||
return { | ||
transitionEnter: true, | ||
transitionLeave: true, | ||
component: React.DOM.span | ||
component: React.DOM.span, | ||
childFactory: emptyFunction.thatReturnsArgument | ||
}; | ||
}, | ||
getInitialState: function() { | ||
return { | ||
children: ReactTransitionChildMapping.getChildMapping(this.props.children) | ||
}; | ||
}, | ||
componentWillReceiveProps: function(nextProps) { | ||
var nextChildMapping = ReactTransitionChildMapping.getChildMapping( | ||
nextProps.children | ||
); | ||
var prevChildMapping = this.state.children; | ||
this.setState({ | ||
children: ReactTransitionChildMapping.mergeChildMappings( | ||
prevChildMapping, | ||
nextChildMapping | ||
) | ||
}); | ||
var key; | ||
for (key in nextChildMapping) { | ||
if (!prevChildMapping.hasOwnProperty(key) && | ||
!this.currentlyTransitioningKeys[key]) { | ||
this.keysToEnter.push(key); | ||
} | ||
} | ||
for (key in prevChildMapping) { | ||
if (!nextChildMapping.hasOwnProperty(key) && | ||
!this.currentlyTransitioningKeys[key]) { | ||
this.keysToLeave.push(key); | ||
} | ||
} | ||
// If we want to someday check for reordering, we could do it here. | ||
}, | ||
componentWillMount: function() { | ||
// _transitionGroupCurrentKeys stores the union of previous *and* next keys. | ||
// If this were a component we'd store it as state, however, since this must | ||
// be a mixin, we need to keep the result of the union of keys in each | ||
// call to animateChildren() which happens in render(), so we can't | ||
// call setState() in there. | ||
this._transitionGroupCurrentKeys = {}; | ||
this.currentlyTransitioningKeys = {}; | ||
this.keysToEnter = []; | ||
this.keysToLeave = []; | ||
}, | ||
componentDidUpdate: function() { | ||
if (this.props.onTransition) { | ||
this.props.onTransition(); | ||
var keysToEnter = this.keysToEnter; | ||
this.keysToEnter = []; | ||
keysToEnter.forEach(this.performEnter); | ||
var keysToLeave = this.keysToLeave; | ||
this.keysToLeave = []; | ||
keysToLeave.forEach(this.performLeave); | ||
}, | ||
performEnter: function(key) { | ||
this.currentlyTransitioningKeys[key] = true; | ||
var component = this.refs[key]; | ||
if (component.componentWillEnter) { | ||
component.componentWillEnter( | ||
this._handleDoneEntering.bind(this, key) | ||
); | ||
} else { | ||
this._handleDoneEntering(key); | ||
} | ||
}, | ||
/** | ||
* Render some children in a transitionable way. | ||
*/ | ||
renderTransitionableChildren: function(sourceChildren) { | ||
var children = {}; | ||
var childMapping = ReactTransitionKeySet.getChildMapping(sourceChildren); | ||
_handleDoneEntering: function(key) { | ||
var component = this.refs[key]; | ||
if (component.componentDidEnter) { | ||
component.componentDidEnter(); | ||
} | ||
var currentKeys = ReactTransitionKeySet.mergeKeySets( | ||
this._transitionGroupCurrentKeys, | ||
ReactTransitionKeySet.getKeySet(sourceChildren) | ||
delete this.currentlyTransitioningKeys[key]; | ||
var currentChildMapping = ReactTransitionChildMapping.getChildMapping( | ||
this.props.children | ||
); | ||
for (var key in currentKeys) { | ||
// Here is how we keep the nodes in the DOM. ReactTransitionableChild | ||
// knows how to hold onto its child if it changes to undefined. Here, we | ||
// may look up an old key in the new children, and it may switch to | ||
// undefined. React's reconciler will keep the ReactTransitionableChild | ||
// instance alive such that we can animate it. | ||
if (childMapping[key] || this.props.transitionLeave) { | ||
children[key] = ReactTransitionableChild({ | ||
name: this.props.transitionName, | ||
enter: this.props.transitionEnter, | ||
onDoneLeaving: this._handleDoneLeaving.bind(this, key) | ||
}, childMapping[key]); | ||
} | ||
if (!currentChildMapping.hasOwnProperty(key)) { | ||
// This was removed before it had fully entered. Remove it. | ||
this.performLeave(key); | ||
} | ||
}, | ||
this._transitionGroupCurrentKeys = currentKeys; | ||
performLeave: function(key) { | ||
this.currentlyTransitioningKeys[key] = true; | ||
return children; | ||
var component = this.refs[key]; | ||
if (component.componentWillLeave) { | ||
component.componentWillLeave(this._handleDoneLeaving.bind(this, key)); | ||
} else { | ||
// Note that this is somewhat dangerous b/c it calls setState() | ||
// again, effectively mutating the component before all the work | ||
// is done. | ||
this._handleDoneLeaving(key); | ||
} | ||
}, | ||
_handleDoneLeaving: function(key) { | ||
// When the leave animation finishes, we should blow away the actual DOM | ||
// node. | ||
delete this._transitionGroupCurrentKeys[key]; | ||
this.forceUpdate(); | ||
var component = this.refs[key]; | ||
if (component.componentDidLeave) { | ||
component.componentDidLeave(); | ||
} | ||
delete this.currentlyTransitioningKeys[key]; | ||
var currentChildMapping = ReactTransitionChildMapping.getChildMapping( | ||
this.props.children | ||
); | ||
if (currentChildMapping.hasOwnProperty(key)) { | ||
// This entered again before it fully left. Add it again. | ||
this.performEnter(key); | ||
} else { | ||
var newChildren = merge(this.state.children); | ||
delete newChildren[key]; | ||
this.setState({children: newChildren}); | ||
} | ||
}, | ||
render: function() { | ||
return this.transferPropsTo( | ||
this.props.component( | ||
{ | ||
transitionName: null, | ||
transitionEnter: null, | ||
transitionLeave: null, | ||
component: null | ||
}, | ||
this.renderTransitionableChildren(this.props.children) | ||
) | ||
); | ||
// TODO: we could get rid of the need for the wrapper node | ||
// by cloning a single child | ||
var childrenToRender = {}; | ||
for (var key in this.state.children) { | ||
var child = this.state.children[key]; | ||
if (child) { | ||
// You may need to apply reactive updates to a child as it is leaving. | ||
// The normal React way to do it won't work since the child will have | ||
// already been removed. In case you need this behavior you can provide | ||
// a childFactory function to wrap every child, even the ones that are | ||
// leaving. | ||
childrenToRender[key] = cloneWithProps( | ||
this.props.childFactory(child), | ||
{ref: key} | ||
); | ||
} | ||
} | ||
return this.transferPropsTo(this.props.component(null, childrenToRender)); | ||
} | ||
@@ -112,0 +187,0 @@ }); |
/** | ||
* Copyright 2013 Facebook, Inc. | ||
* Copyright 2013-2014 Facebook, Inc. | ||
* | ||
@@ -21,7 +21,10 @@ * Licensed under the Apache License, Version 2.0 (the "License"); | ||
var ReactComponent = require("react").__internals.Component; | ||
var ReactTextComponent = require("react").__internals.TextComponent; | ||
var ReactInstanceHandles = require("./ReactInstanceHandles"); | ||
var ReactTextComponent = require("./ReactTextComponent"); | ||
var invariant = require("./invariant"); | ||
var SEPARATOR = ReactInstanceHandles.SEPARATOR; | ||
var SUBSEPARATOR = ':'; | ||
/** | ||
@@ -35,3 +38,55 @@ * TODO: Test that: | ||
var userProvidedKeyEscaperLookup = { | ||
'=': '=0', | ||
'.': '=1', | ||
':': '=2' | ||
}; | ||
var userProvidedKeyEscapeRegex = /[=.:]/g; | ||
function userProvidedKeyEscaper(match) { | ||
return userProvidedKeyEscaperLookup[match]; | ||
} | ||
/** | ||
* Generate a key string that identifies a component within a set. | ||
* | ||
* @param {*} component A component that could contain a manual key. | ||
* @param {number} index Index that is used if a manual key is not provided. | ||
* @return {string} | ||
*/ | ||
function getComponentKey(component, index) { | ||
if (component && component.props && component.props.key != null) { | ||
// Explicit key | ||
return wrapUserProvidedKey(component.props.key); | ||
} | ||
// Implicit key determined by the index in the set | ||
return index.toString(36); | ||
} | ||
/** | ||
* Escape a component key so that it is safe to use in a reactid. | ||
* | ||
* @param {*} key Component key to be escaped. | ||
* @return {string} An escaped string. | ||
*/ | ||
function escapeUserProvidedKey(text) { | ||
return ('' + text).replace( | ||
userProvidedKeyEscapeRegex, | ||
userProvidedKeyEscaper | ||
); | ||
} | ||
/** | ||
* Wrap a `key` value explicitly provided by the user to distinguish it from | ||
* implicitly-generated keys generated by a component's index in its parent. | ||
* | ||
* @param {string} key Value of a user-provided `key` attribute | ||
* @return {string} | ||
*/ | ||
function wrapUserProvidedKey(key) { | ||
return '$' + escapeUserProvidedKey(key); | ||
} | ||
/** | ||
* @param {?*} children Children tree container. | ||
@@ -51,3 +106,7 @@ * @param {!string} nameSoFar Name of the key path so far. | ||
var child = children[i]; | ||
var nextName = nameSoFar + ReactComponent.getKey(child, i); | ||
var nextName = ( | ||
nameSoFar + | ||
(nameSoFar ? SUBSEPARATOR : SEPARATOR) + | ||
getComponentKey(child, i) | ||
); | ||
var nextIndex = indexSoFar + subtreeCount; | ||
@@ -67,6 +126,5 @@ subtreeCount += traverseAllChildrenImpl( | ||
// so that it's consistent if the number of children grows | ||
var storageName = isOnlyChild ? | ||
ReactComponent.getKey(children, 0): | ||
nameSoFar; | ||
if (children === null || children === undefined || type === 'boolean') { | ||
var storageName = | ||
isOnlyChild ? SEPARATOR + getComponentKey(children, 0) : nameSoFar; | ||
if (children == null || type === 'boolean') { | ||
// All of the above are perceived as null. | ||
@@ -89,3 +147,7 @@ callback(traverseContext, null, storageName, indexSoFar); | ||
children[key], | ||
nameSoFar + '{' + key + '}', | ||
( | ||
nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) + | ||
wrapUserProvidedKey(key) + SUBSEPARATOR + | ||
getComponentKey(children[key], 0) | ||
), | ||
indexSoFar + subtreeCount, | ||
@@ -92,0 +154,0 @@ callback, |
{ | ||
"name": "react-addons", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"description": "Simple packaging of react addons to avoid fiddly 'react/addons' npm module.", | ||
@@ -28,4 +28,4 @@ "main": "index.js", | ||
"peerDependencies": { | ||
"react": ">= 0.8.0" | ||
"react": ">= 0.9.0" | ||
} | ||
} |
@@ -11,2 +11,5 @@ # react-addons | ||
`react` is a peerDependency of this module, so it won't add extra cruft to your project | ||
and will work nicely with browserify. | ||
## Example Usage | ||
@@ -16,13 +19,18 @@ | ||
// Previously, you might access React Addons with this path. | ||
// Previously, you might access React Addons with this path, which actually | ||
// returns the entire React library, with addons accessible via the `addons` property. | ||
// Unfortunately, this can confuse browserify and can add an extra 1MB (unminified) | ||
// to your build. | ||
var React = require('react/addons'); | ||
// Now, you can access it this way: | ||
// Now, you can access it this way, separately from React itself, | ||
// and enjoy the relatively small size (42kb unminified)! | ||
var React = require('react'); | ||
var addons = require('react-addons'); | ||
// And the addons are available directly on the module, like so: | ||
var classSet = require('react-addons').classSet; | ||
var classSet = addons.classSet; | ||
// Now, you don't have to worry about changing all your `require` statements | ||
// Now, you don't have to worry about changing your require statements | ||
// throughout your app to use `react/addons`! | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
560843
145
15986
35
166
1