UNPKG

react-pivot

Version:

React-Pivot is a data-grid component with pivot-table-like functionality for data display, filtering, and exploration.

353 lines (323 loc) 11.1 kB
/** * Copyright 2013-2014, 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 ReactPropTypes */ "use strict"; var ReactElement = require("./ReactElement"); var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames"); var deprecated = require("./deprecated"); var emptyFunction = require("./emptyFunction"); /** * Collection of methods that allow declaration and validation of props that are * supplied to React components. Example usage: * * var Props = require('ReactPropTypes'); * var MyArticle = React.createClass({ * propTypes: { * // An optional string prop named "description". * description: Props.string, * * // A required enum prop named "category". * category: Props.oneOf(['News','Photos']).isRequired, * * // A prop named "dialog" that requires an instance of Dialog. * dialog: Props.instanceOf(Dialog).isRequired * }, * render: function() { ... } * }); * * A more formal specification of how these methods are used: * * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) * decl := ReactPropTypes.{type}(.isRequired)? * * Each and every declaration produces a function with the same signature. This * allows the creation of custom validation functions. For example: * * var MyLink = React.createClass({ * propTypes: { * // An optional string or URI prop named "href". * href: function(props, propName, componentName) { * var propValue = props[propName]; * if (propValue != null && typeof propValue !== 'string' && * !(propValue instanceof URI)) { * return new Error( * 'Expected a string or an URI for ' + propName + ' in ' + * componentName * ); * } * } * }, * render: function() {...} * }); * * @internal */ var ANONYMOUS = '<<anonymous>>'; var elementTypeChecker = createElementTypeChecker(); var nodeTypeChecker = createNodeChecker(); var ReactPropTypes = { array: createPrimitiveTypeChecker('array'), bool: createPrimitiveTypeChecker('boolean'), func: createPrimitiveTypeChecker('function'), number: createPrimitiveTypeChecker('number'), object: createPrimitiveTypeChecker('object'), string: createPrimitiveTypeChecker('string'), any: createAnyTypeChecker(), arrayOf: createArrayOfTypeChecker, element: elementTypeChecker, instanceOf: createInstanceTypeChecker, node: nodeTypeChecker, objectOf: createObjectOfTypeChecker, oneOf: createEnumTypeChecker, oneOfType: createUnionTypeChecker, shape: createShapeTypeChecker, component: deprecated( 'React.PropTypes', 'component', 'element', this, elementTypeChecker ), renderable: deprecated( 'React.PropTypes', 'renderable', 'node', this, nodeTypeChecker ) }; function createChainableTypeChecker(validate) { function checkType(isRequired, props, propName, componentName, location) { componentName = componentName || ANONYMOUS; if (props[propName] == null) { var locationName = ReactPropTypeLocationNames[location]; if (isRequired) { return new Error( ("Required " + locationName + " `" + propName + "` was not specified in ")+ ("`" + componentName + "`.") ); } } else { return validate(props, propName, componentName, location); } } var chainedCheckType = checkType.bind(null, false); chainedCheckType.isRequired = checkType.bind(null, true); return chainedCheckType; } function createPrimitiveTypeChecker(expectedType) { function validate(props, propName, componentName, location) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== expectedType) { var locationName = ReactPropTypeLocationNames[location]; // `propValue` being instance of, say, date/regexp, pass the 'object' // check, but we can offer a more precise error message here rather than // 'of type `object`'. var preciseType = getPreciseType(propValue); return new Error( ("Invalid " + locationName + " `" + propName + "` of type `" + preciseType + "` ") + ("supplied to `" + componentName + "`, expected `" + expectedType + "`.") ); } } return createChainableTypeChecker(validate); } function createAnyTypeChecker() { return createChainableTypeChecker(emptyFunction.thatReturns()); } function createArrayOfTypeChecker(typeChecker) { function validate(props, propName, componentName, location) { var propValue = props[propName]; if (!Array.isArray(propValue)) { var locationName = ReactPropTypeLocationNames[location]; var propType = getPropType(propValue); return new Error( ("Invalid " + locationName + " `" + propName + "` of type ") + ("`" + propType + "` supplied to `" + componentName + "`, expected an array.") ); } for (var i = 0; i < propValue.length; i++) { var error = typeChecker(propValue, i, componentName, location); if (error instanceof Error) { return error; } } } return createChainableTypeChecker(validate); } function createElementTypeChecker() { function validate(props, propName, componentName, location) { if (!ReactElement.isValidElement(props[propName])) { var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` supplied to ") + ("`" + componentName + "`, expected a ReactElement.") ); } } return createChainableTypeChecker(validate); } function createInstanceTypeChecker(expectedClass) { function validate(props, propName, componentName, location) { if (!(props[propName] instanceof expectedClass)) { var locationName = ReactPropTypeLocationNames[location]; var expectedClassName = expectedClass.name || ANONYMOUS; return new Error( ("Invalid " + locationName + " `" + propName + "` supplied to ") + ("`" + componentName + "`, expected instance of `" + expectedClassName + "`.") ); } } return createChainableTypeChecker(validate); } function createEnumTypeChecker(expectedValues) { function validate(props, propName, componentName, location) { var propValue = props[propName]; for (var i = 0; i < expectedValues.length; i++) { if (propValue === expectedValues[i]) { return; } } var locationName = ReactPropTypeLocationNames[location]; var valuesString = JSON.stringify(expectedValues); return new Error( ("Invalid " + locationName + " `" + propName + "` of value `" + propValue + "` ") + ("supplied to `" + componentName + "`, expected one of " + valuesString + ".") ); } return createChainableTypeChecker(validate); } function createObjectOfTypeChecker(typeChecker) { function validate(props, propName, componentName, location) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== 'object') { var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` of type ") + ("`" + propType + "` supplied to `" + componentName + "`, expected an object.") ); } for (var key in propValue) { if (propValue.hasOwnProperty(key)) { var error = typeChecker(propValue, key, componentName, location); if (error instanceof Error) { return error; } } } } return createChainableTypeChecker(validate); } function createUnionTypeChecker(arrayOfTypeCheckers) { function validate(props, propName, componentName, location) { for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; if (checker(props, propName, componentName, location) == null) { return; } } var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` supplied to ") + ("`" + componentName + "`.") ); } return createChainableTypeChecker(validate); } function createNodeChecker() { function validate(props, propName, componentName, location) { if (!isNode(props[propName])) { var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` supplied to ") + ("`" + componentName + "`, expected a ReactNode.") ); } } return createChainableTypeChecker(validate); } function createShapeTypeChecker(shapeTypes) { function validate(props, propName, componentName, location) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== 'object') { var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` of type `" + propType + "` ") + ("supplied to `" + componentName + "`, expected `object`.") ); } for (var key in shapeTypes) { var checker = shapeTypes[key]; if (!checker) { continue; } var error = checker(propValue, key, componentName, location); if (error) { return error; } } } return createChainableTypeChecker(validate, 'expected `object`'); } function isNode(propValue) { switch(typeof propValue) { case 'number': case 'string': return true; case 'boolean': return !propValue; case 'object': if (Array.isArray(propValue)) { return propValue.every(isNode); } if (ReactElement.isValidElement(propValue)) { return true; } for (var k in propValue) { if (!isNode(propValue[k])) { return false; } } return true; default: return false; } } // Equivalent of `typeof` but with special handling for array and regexp. function getPropType(propValue) { var propType = typeof propValue; if (Array.isArray(propValue)) { return 'array'; } if (propValue instanceof RegExp) { // Old webkits (at least until Android 4.0) return 'function' rather than // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ // passes PropTypes.object. return 'object'; } return propType; } // This handles more types than `getPropType`. Only used for error messages. // See `createPrimitiveTypeChecker`. function getPreciseType(propValue) { var propType = getPropType(propValue); if (propType === 'object') { if (propValue instanceof Date) { return 'date'; } else if (propValue instanceof RegExp) { return 'regexp'; } } return propType; } module.exports = ReactPropTypes;