(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react-dom'), require('react')) : typeof define === 'function' && define.amd ? define(['react-dom', 'react'], factory) : (global.ReactDraggable = factory(global.ReactDOM,global.React)); }(this, (function (ReactDOM,React) { 'use strict'; ReactDOM = ReactDOM && ReactDOM.hasOwnProperty('default') ? ReactDOM['default'] : ReactDOM; React = React && React.hasOwnProperty('default') ? React['default'] : React; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * */ 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; }; var emptyFunction_1 = emptyFunction; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ /** * 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) {}; { 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; } } var invariant_1 = invariant; /** * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths. */ var warning = emptyFunction_1; { var printWarning = function printWarning(format) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } var argIndex = 0; var message = 'Warning: ' + format.replace(/%s/g, function () { return args[argIndex++]; }); if (typeof console !== 'undefined') { console.error(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) {} }; warning = function warning(condition, format) { if (format === undefined) { throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); } if (format.indexOf('Failed Composite propType: ') === 0) { return; // Ignore CompositeComponent proptype check. } if (!condition) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; } printWarning.apply(undefined, [format].concat(args)); } }; } var warning_1 = warning; /* object-assign (c) Sindre Sorhus @license MIT */ /* eslint-disable no-unused-vars */ var getOwnPropertySymbols = Object.getOwnPropertySymbols; var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject(val) { if (val === null || val === undefined) { throw new TypeError('Object.assign cannot be called with null or undefined'); } return Object(val); } function shouldUseNative() { try { if (!Object.assign) { return false; } // Detect buggy property enumeration order in older V8 versions. // https://bugs.chromium.org/p/v8/issues/detail?id=4118 var test1 = new String('abc'); // eslint-disable-line no-new-wrappers test1[5] = 'de'; if (Object.getOwnPropertyNames(test1)[0] === '5') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test2 = {}; for (var i = 0; i < 10; i++) { test2['_' + String.fromCharCode(i)] = i; } var order2 = Object.getOwnPropertyNames(test2).map(function (n) { return test2[n]; }); if (order2.join('') !== '0123456789') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test3 = {}; 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { test3[letter] = letter; }); if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { return false; } return true; } catch (err) { // We don't expect any of the above to throw, but better to be safe. return false; } } var objectAssign = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } if (getOwnPropertySymbols) { symbols = getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; var ReactPropTypesSecret_1 = ReactPropTypesSecret; { var invariant$1 = invariant_1; var warning$1 = warning_1; var ReactPropTypesSecret$1 = ReactPropTypesSecret_1; var loggedTypeFailures = {}; } /** * Assert that the values match with the type specs. * Error messages are memorized and will only be shown once. * * @param {object} typeSpecs Map of name to a ReactPropType * @param {object} values Runtime values that need to be type-checked * @param {string} location e.g. "prop", "context", "child context" * @param {string} componentName Name of the component for error messages. * @param {?Function} getStack Returns the component stack. * @private */ function checkPropTypes(typeSpecs, values, location, componentName, getStack) { { for (var typeSpecName in typeSpecs) { if (typeSpecs.hasOwnProperty(typeSpecName)) { var error; // Prop type validation may throw. In case they do, we don't want to // fail the render phase where it didn't fail before. So we log it. // After these have been cleaned up, we'll let them throw. try { // This is intentionally an invariant that gets caught. It's the same // behavior as without this statement except with a better message. invariant$1(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]); error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret$1); } catch (ex) { error = ex; } warning$1(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error); if (error instanceof Error && !(error.message in loggedTypeFailures)) { // Only monitor this failure once because there tends to be a lot of the // same error. loggedTypeFailures[error.message] = true; var stack = getStack ? getStack() : ''; warning$1(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); } } } } } var checkPropTypes_1 = checkPropTypes; var factoryWithTypeCheckers = function(isValidElement, throwOnDirectAccess) { /* global Symbol */ var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. /** * Returns the iterator method function contained on the iterable object. * * Be sure to invoke the function with the iterable as context: * * var iteratorFn = getIteratorFn(myIterable); * if (iteratorFn) { * var iterator = iteratorFn.call(myIterable); * ... * } * * @param {?object} maybeIterable * @return {?function} */ function getIteratorFn(maybeIterable) { var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); if (typeof iteratorFn === 'function') { return iteratorFn; } } /** * 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 = '<>'; // Important! // Keep this list in sync with production version in `./factoryWithThrowingShims.js`. var ReactPropTypes = { array: createPrimitiveTypeChecker('array'), bool: createPrimitiveTypeChecker('boolean'), func: createPrimitiveTypeChecker('function'), number: createPrimitiveTypeChecker('number'), object: createPrimitiveTypeChecker('object'), string: createPrimitiveTypeChecker('string'), symbol: createPrimitiveTypeChecker('symbol'), any: createAnyTypeChecker(), arrayOf: createArrayOfTypeChecker, element: createElementTypeChecker(), instanceOf: createInstanceTypeChecker, node: createNodeChecker(), objectOf: createObjectOfTypeChecker, oneOf: createEnumTypeChecker, oneOfType: createUnionTypeChecker, shape: createShapeTypeChecker, exact: createStrictShapeTypeChecker, }; /** * inlined Object.is polyfill to avoid requiring consumers ship their own * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is */ /*eslint-disable no-self-compare*/ function is(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } } /*eslint-enable no-self-compare*/ /** * We use an Error-like object for backward compatibility as people may call * PropTypes directly and inspect their output. However, we don't use real * Errors anymore. We don't inspect their stack anyway, and creating them * is prohibitively expensive if they are created too often, such as what * happens in oneOfType() for any type before the one that matched. */ function PropTypeError(message) { this.message = message; this.stack = ''; } // Make `instanceof Error` still work for returned errors. PropTypeError.prototype = Error.prototype; function createChainableTypeChecker(validate) { { var manualPropTypeCallCache = {}; var manualPropTypeWarningCount = 0; } function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { componentName = componentName || ANONYMOUS; propFullName = propFullName || propName; if (secret !== ReactPropTypesSecret_1) { if (throwOnDirectAccess) { // New behavior only for users of `prop-types` package invariant_1( false, 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use `PropTypes.checkPropTypes()` to call them. ' + 'Read more at http://fb.me/use-check-prop-types' ); } else if ("development" !== 'production' && typeof console !== 'undefined') { // Old behavior for people using React.PropTypes var cacheKey = componentName + ':' + propName; if ( !manualPropTypeCallCache[cacheKey] && // Avoid spamming the console because they are often not actionable except for lib authors manualPropTypeWarningCount < 3 ) { warning_1( false, 'You are manually calling a React.PropTypes validation ' + 'function for the `%s` prop on `%s`. This is deprecated ' + 'and will throw in the standalone `prop-types` package. ' + 'You may be seeing this warning due to a third-party PropTypes ' + 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.', propFullName, componentName ); manualPropTypeCallCache[cacheKey] = true; manualPropTypeWarningCount++; } } } if (props[propName] == null) { if (isRequired) { if (props[propName] === null) { return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.')); } return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.')); } return null; } else { return validate(props, propName, componentName, location, propFullName); } } var chainedCheckType = checkType.bind(null, false); chainedCheckType.isRequired = checkType.bind(null, true); return chainedCheckType; } function createPrimitiveTypeChecker(expectedType) { function validate(props, propName, componentName, location, propFullName, secret) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== expectedType) { // `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 PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.')); } return null; } return createChainableTypeChecker(validate); } function createAnyTypeChecker() { return createChainableTypeChecker(emptyFunction_1.thatReturnsNull); } function createArrayOfTypeChecker(typeChecker) { function validate(props, propName, componentName, location, propFullName) { if (typeof typeChecker !== 'function') { return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.'); } var propValue = props[propName]; if (!Array.isArray(propValue)) { var propType = getPropType(propValue); return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); } for (var i = 0; i < propValue.length; i++) { var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret_1); if (error instanceof Error) { return error; } } return null; } return createChainableTypeChecker(validate); } function createElementTypeChecker() { function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; if (!isValidElement(propValue)) { var propType = getPropType(propValue); return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.')); } return null; } return createChainableTypeChecker(validate); } function createInstanceTypeChecker(expectedClass) { function validate(props, propName, componentName, location, propFullName) { if (!(props[propName] instanceof expectedClass)) { var expectedClassName = expectedClass.name || ANONYMOUS; var actualClassName = getClassName(props[propName]); return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); } return null; } return createChainableTypeChecker(validate); } function createEnumTypeChecker(expectedValues) { if (!Array.isArray(expectedValues)) { warning_1(false, 'Invalid argument supplied to oneOf, expected an instance of array.'); return emptyFunction_1.thatReturnsNull; } function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; for (var i = 0; i < expectedValues.length; i++) { if (is(propValue, expectedValues[i])) { return null; } } var valuesString = JSON.stringify(expectedValues); return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); } return createChainableTypeChecker(validate); } function createObjectOfTypeChecker(typeChecker) { function validate(props, propName, componentName, location, propFullName) { if (typeof typeChecker !== 'function') { return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); } var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== 'object') { return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` 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, propFullName + '.' + key, ReactPropTypesSecret_1); if (error instanceof Error) { return error; } } } return null; } return createChainableTypeChecker(validate); } function createUnionTypeChecker(arrayOfTypeCheckers) { if (!Array.isArray(arrayOfTypeCheckers)) { warning_1(false, 'Invalid argument supplied to oneOfType, expected an instance of array.'); return emptyFunction_1.thatReturnsNull; } for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; if (typeof checker !== 'function') { warning_1( false, 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' + 'received %s at index %s.', getPostfixForTypeWarning(checker), i ); return emptyFunction_1.thatReturnsNull; } } function validate(props, propName, componentName, location, propFullName) { for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret_1) == null) { return null; } } return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.')); } return createChainableTypeChecker(validate); } function createNodeChecker() { function validate(props, propName, componentName, location, propFullName) { if (!isNode(props[propName])) { return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); } return null; } return createChainableTypeChecker(validate); } function createShapeTypeChecker(shapeTypes) { function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== 'object') { return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` 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, propFullName + '.' + key, ReactPropTypesSecret_1); if (error) { return error; } } return null; } return createChainableTypeChecker(validate); } function createStrictShapeTypeChecker(shapeTypes) { function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== 'object') { return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); } // We need to check all keys in case some are required but missing from // props. var allKeys = objectAssign({}, props[propName], shapeTypes); for (var key in allKeys) { var checker = shapeTypes[key]; if (!checker) { return new PropTypeError( 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' + '\nBad object: ' + JSON.stringify(props[propName], null, ' ') + '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ') ); } var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret_1); if (error) { return error; } } return null; } return createChainableTypeChecker(validate); } function isNode(propValue) { switch (typeof propValue) { case 'number': case 'string': case 'undefined': return true; case 'boolean': return !propValue; case 'object': if (Array.isArray(propValue)) { return propValue.every(isNode); } if (propValue === null || isValidElement(propValue)) { return true; } var iteratorFn = getIteratorFn(propValue); if (iteratorFn) { var iterator = iteratorFn.call(propValue); var step; if (iteratorFn !== propValue.entries) { while (!(step = iterator.next()).done) { if (!isNode(step.value)) { return false; } } } else { // Iterator will provide entry [k,v] tuples rather than values. while (!(step = iterator.next()).done) { var entry = step.value; if (entry) { if (!isNode(entry[1])) { return false; } } } } } else { return false; } return true; default: return false; } } function isSymbol(propType, propValue) { // Native Symbol. if (propType === 'symbol') { return true; } // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' if (propValue['@@toStringTag'] === 'Symbol') { return true; } // Fallback for non-spec compliant Symbols which are polyfilled. if (typeof Symbol === 'function' && propValue instanceof Symbol) { return true; } 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'; } if (isSymbol(propType, propValue)) { return 'symbol'; } return propType; } // This handles more types than `getPropType`. Only used for error messages. // See `createPrimitiveTypeChecker`. function getPreciseType(propValue) { if (typeof propValue === 'undefined' || propValue === null) { return '' + propValue; } var propType = getPropType(propValue); if (propType === 'object') { if (propValue instanceof Date) { return 'date'; } else if (propValue instanceof RegExp) { return 'regexp'; } } return propType; } // Returns a string that is postfixed to a warning about an invalid type. // For example, "undefined" or "of type array" function getPostfixForTypeWarning(value) { var type = getPreciseType(value); switch (type) { case 'array': case 'object': return 'an ' + type; case 'boolean': case 'date': case 'regexp': return 'a ' + type; default: return type; } } // Returns class name of the object, if any. function getClassName(propValue) { if (!propValue.constructor || !propValue.constructor.name) { return ANONYMOUS; } return propValue.constructor.name; } ReactPropTypes.checkPropTypes = checkPropTypes_1; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes; }; var propTypes = createCommonjsModule(function (module) { /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ { var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) || 0xeac7; var isValidElement = function(object) { return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; }; // By explicitly using `prop-types` you are opting into new development behavior. // http://fb.me/prop-types-in-prod var throwOnDirectAccess = true; module.exports = factoryWithTypeCheckers(isValidElement, throwOnDirectAccess); } }); var classnames = createCommonjsModule(function (module) { /*! Copyright (c) 2016 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames */ /* global define */ (function () { var hasOwn = {}.hasOwnProperty; function classNames () { var classes = []; for (var i = 0; i < arguments.length; i++) { var arg = arguments[i]; if (!arg) continue; var argType = typeof arg; if (argType === 'string' || argType === 'number') { classes.push(arg); } else if (Array.isArray(arg)) { classes.push(classNames.apply(null, arg)); } else if (argType === 'object') { for (var key in arg) { if (hasOwn.call(arg, key) && arg[key]) { classes.push(key); } } } } return classes.join(' '); } if ('object' !== 'undefined' && module.exports) { module.exports = classNames; } else if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) { // register as 'classnames', consistent with npm package name undefined('classnames', [], function () { return classNames; }); } else { window.classNames = classNames; } }()); }); // @credits https://gist.github.com/rogozhnikoff/a43cfed27c41e4e68cdc function findInArray(array /*: Array | TouchList*/, callback /*: Function*/) /*: any*/ { for (var i = 0, length = array.length; i < length; i++) { if (callback.apply(callback, [array[i], i, array])) return array[i]; } } function isFunction(func /*: any*/) /*: boolean*/ { return typeof func === 'function' || Object.prototype.toString.call(func) === '[object Function]'; } function isNum(num /*: any*/) /*: boolean*/ { return typeof num === 'number' && !isNaN(num); } function int(a /*: string*/) /*: number*/ { return parseInt(a, 10); } function dontSetMe(props /*: Object*/, propName /*: string*/, componentName /*: string*/) { if (props[propName]) { return new Error('Invalid prop ' + propName + ' passed to ' + componentName + ' - do not set this, set it on the child.'); } } var prefixes = ['Moz', 'Webkit', 'O', 'ms']; function getPrefix() /*: string*/ { var prop /*: string*/ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'transform'; // Checking specifically for 'window.document' is for pseudo-browser server-side // environments that define 'window' as the global context. // E.g. React-rails (see https://github.com/reactjs/react-rails/pull/84) if (typeof window === 'undefined' || typeof window.document === 'undefined') return ''; var style = window.document.documentElement.style; if (prop in style) return ''; for (var i = 0; i < prefixes.length; i++) { if (browserPrefixToKey(prop, prefixes[i]) in style) return prefixes[i]; } return ''; } function browserPrefixToKey(prop /*: string*/, prefix /*: string*/) /*: string*/ { return prefix ? '' + prefix + kebabToTitleCase(prop) : prop; } function kebabToTitleCase(str /*: string*/) /*: string*/ { var out = ''; var shouldCapitalize = true; for (var i = 0; i < str.length; i++) { if (shouldCapitalize) { out += str[i].toUpperCase(); shouldCapitalize = false; } else if (str[i] === '-') { shouldCapitalize = true; } else { out += str[i]; } } return out; } // Default export is the prefix itself, like 'Moz', 'Webkit', etc // Note that you may have to re-test for certain things; for instance, Chrome 50 // can handle unprefixed `transform`, but not unprefixed `user-select` var browserPrefix = getPrefix(); var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 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 defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var inherits = function (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 possibleConstructorReturn = function (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; }; var slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /*:: import type {ControlPosition, PositionOffsetControlPosition, MouseTouchEvent} from './types';*/ var matchesSelectorFunc = ''; function matchesSelector(el /*: Node*/, selector /*: string*/) /*: boolean*/ { if (!matchesSelectorFunc) { matchesSelectorFunc = findInArray(['matches', 'webkitMatchesSelector', 'mozMatchesSelector', 'msMatchesSelector', 'oMatchesSelector'], function (method) { // $FlowIgnore: Doesn't think elements are indexable return isFunction(el[method]); }); } // Might not be found entirely (not an Element?) - in that case, bail // $FlowIgnore: Doesn't think elements are indexable if (!isFunction(el[matchesSelectorFunc])) return false; // $FlowIgnore: Doesn't think elements are indexable return el[matchesSelectorFunc](selector); } // Works up the tree to the draggable itself attempting to match selector. function matchesSelectorAndParentsTo(el /*: Node*/, selector /*: string*/, baseNode /*: Node*/) /*: boolean*/ { var node = el; do { if (matchesSelector(node, selector)) return true; if (node === baseNode) return false; node = node.parentNode; } while (node); return false; } function addEvent(el /*: ?Node*/, event /*: string*/, handler /*: Function*/) /*: void*/ { if (!el) { return; } if (el.attachEvent) { el.attachEvent('on' + event, handler); } else if (el.addEventListener) { el.addEventListener(event, handler, true); } else { // $FlowIgnore: Doesn't think elements are indexable el['on' + event] = handler; } } function removeEvent(el /*: ?Node*/, event /*: string*/, handler /*: Function*/) /*: void*/ { if (!el) { return; } if (el.detachEvent) { el.detachEvent('on' + event, handler); } else if (el.removeEventListener) { el.removeEventListener(event, handler, true); } else { // $FlowIgnore: Doesn't think elements are indexable el['on' + event] = null; } } function outerHeight(node /*: HTMLElement*/) /*: number*/ { // This is deliberately excluding margin for our calculations, since we are using // offsetTop which is including margin. See getBoundPosition var height = node.clientHeight; var computedStyle = node.ownerDocument.defaultView.getComputedStyle(node); height += int(computedStyle.borderTopWidth); height += int(computedStyle.borderBottomWidth); return height; } function outerWidth(node /*: HTMLElement*/) /*: number*/ { // This is deliberately excluding margin for our calculations, since we are using // offsetLeft which is including margin. See getBoundPosition var width = node.clientWidth; var computedStyle = node.ownerDocument.defaultView.getComputedStyle(node); width += int(computedStyle.borderLeftWidth); width += int(computedStyle.borderRightWidth); return width; } function innerHeight(node /*: HTMLElement*/) /*: number*/ { var height = node.clientHeight; var computedStyle = node.ownerDocument.defaultView.getComputedStyle(node); height -= int(computedStyle.paddingTop); height -= int(computedStyle.paddingBottom); return height; } function innerWidth(node /*: HTMLElement*/) /*: number*/ { var width = node.clientWidth; var computedStyle = node.ownerDocument.defaultView.getComputedStyle(node); width -= int(computedStyle.paddingLeft); width -= int(computedStyle.paddingRight); return width; } // Get from offsetParent function offsetXYFromParent(evt /*: {clientX: number, clientY: number}*/, offsetParent /*: HTMLElement*/) /*: ControlPosition*/ { var isBody = offsetParent === offsetParent.ownerDocument.body; var offsetParentRect = isBody ? { left: 0, top: 0 } : offsetParent.getBoundingClientRect(); var x = evt.clientX + offsetParent.scrollLeft - offsetParentRect.left; var y = evt.clientY + offsetParent.scrollTop - offsetParentRect.top; return { x: x, y: y }; } function createCSSTransform(controlPos /*: ControlPosition*/, positionOffset /*: PositionOffsetControlPosition*/) /*: Object*/ { var translation = getTranslation(controlPos, positionOffset, 'px'); return defineProperty({}, browserPrefixToKey('transform', browserPrefix), translation); } function createSVGTransform(controlPos /*: ControlPosition*/, positionOffset /*: PositionOffsetControlPosition*/) /*: string*/ { var translation = getTranslation(controlPos, positionOffset, ''); return translation; } function getTranslation(_ref2, positionOffset /*: PositionOffsetControlPosition*/, unitSuffix /*: string*/) /*: string*/ { var x = _ref2.x, y = _ref2.y; var translation = 'translate(' + x + unitSuffix + ',' + y + unitSuffix + ')'; if (positionOffset) { var defaultX = '' + (typeof positionOffset.x === 'string' ? positionOffset.x : positionOffset.x + unitSuffix); var defaultY = '' + (typeof positionOffset.y === 'string' ? positionOffset.y : positionOffset.y + unitSuffix); translation = 'translate(' + defaultX + ', ' + defaultY + ')' + translation; } return translation; } function getTouch(e /*: MouseTouchEvent*/, identifier /*: number*/) /*: ?{clientX: number, clientY: number}*/ { return e.targetTouches && findInArray(e.targetTouches, function (t) { return identifier === t.identifier; }) || e.changedTouches && findInArray(e.changedTouches, function (t) { return identifier === t.identifier; }); } function getTouchIdentifier(e /*: MouseTouchEvent*/) /*: ?number*/ { if (e.targetTouches && e.targetTouches[0]) return e.targetTouches[0].identifier; if (e.changedTouches && e.changedTouches[0]) return e.changedTouches[0].identifier; } // User-select Hacks: // // Useful for preventing blue highlights all over everything when dragging. // Note we're passing `document` b/c we could be iframed function addUserSelectStyles(doc /*: ?Document*/) { if (!doc) return; var styleEl = doc.getElementById('react-draggable-style-el'); if (!styleEl) { styleEl = doc.createElement('style'); styleEl.type = 'text/css'; styleEl.id = 'react-draggable-style-el'; styleEl.innerHTML = '.react-draggable-transparent-selection *::-moz-selection {all: inherit;}\n'; styleEl.innerHTML += '.react-draggable-transparent-selection *::selection {all: inherit;}\n'; doc.getElementsByTagName('head')[0].appendChild(styleEl); } if (doc.body) addClassName(doc.body, 'react-draggable-transparent-selection'); } function removeUserSelectStyles(doc /*: ?Document*/) { try { if (doc && doc.body) removeClassName(doc.body, 'react-draggable-transparent-selection'); // $FlowIgnore: IE if (doc.selection) { // $FlowIgnore: IE doc.selection.empty(); } else { window.getSelection().removeAllRanges(); // remove selection caused by scroll } } catch (e) { // probably IE } } function styleHacks() /*: Object*/ { var childStyle /*: Object*/ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; // Workaround IE pointer events; see #51 // https://github.com/mzabriskie/react-draggable/issues/51#issuecomment-103488278 return _extends({ touchAction: 'none' }, childStyle); } function addClassName(el /*: HTMLElement*/, className /*: string*/) { if (el.classList) { el.classList.add(className); } else { if (!el.className.match(new RegExp('(?:^|\\s)' + className + '(?!\\S)'))) { el.className += ' ' + className; } } } function removeClassName(el /*: HTMLElement*/, className /*: string*/) { if (el.classList) { el.classList.remove(className); } else { el.className = el.className.replace(new RegExp('(?:^|\\s)' + className + '(?!\\S)', 'g'), ''); } } /*:: import type Draggable from '../Draggable';*/ /*:: import type {Bounds, ControlPosition, DraggableData, MouseTouchEvent} from './types';*/ /*:: import type DraggableCore from '../DraggableCore';*/ function getBoundPosition(draggable /*: Draggable*/, x /*: number*/, y /*: number*/) /*: [number, number]*/ { // If no bounds, short-circuit and move on if (!draggable.props.bounds) return [x, y]; // Clone new bounds var bounds = draggable.props.bounds; bounds = typeof bounds === 'string' ? bounds : cloneBounds(bounds); var node = findDOMNode(draggable); if (typeof bounds === 'string') { var ownerDocument = node.ownerDocument; var ownerWindow = ownerDocument.defaultView; var boundNode = void 0; if (bounds === 'parent') { boundNode = node.parentNode; } else { boundNode = ownerDocument.querySelector(bounds); } if (!(boundNode instanceof ownerWindow.HTMLElement)) { throw new Error('Bounds selector "' + bounds + '" could not find an element.'); } var nodeStyle = ownerWindow.getComputedStyle(node); var boundNodeStyle = ownerWindow.getComputedStyle(boundNode); // Compute bounds. This is a pain with padding and offsets but this gets it exactly right. bounds = { left: -node.offsetLeft + int(boundNodeStyle.paddingLeft) + int(nodeStyle.marginLeft), top: -node.offsetTop + int(boundNodeStyle.paddingTop) + int(nodeStyle.marginTop), right: innerWidth(boundNode) - outerWidth(node) - node.offsetLeft + int(boundNodeStyle.paddingRight) - int(nodeStyle.marginRight), bottom: innerHeight(boundNode) - outerHeight(node) - node.offsetTop + int(boundNodeStyle.paddingBottom) - int(nodeStyle.marginBottom) }; } // Keep x and y below right and bottom limits... if (isNum(bounds.right)) x = Math.min(x, bounds.right); if (isNum(bounds.bottom)) y = Math.min(y, bounds.bottom); // But above left and top limits. if (isNum(bounds.left)) x = Math.max(x, bounds.left); if (isNum(bounds.top)) y = Math.max(y, bounds.top); return [x, y]; } function snapToGrid(grid /*: [number, number]*/, pendingX /*: number*/, pendingY /*: number*/) /*: [number, number]*/ { var x = Math.round(pendingX / grid[0]) * grid[0]; var y = Math.round(pendingY / grid[1]) * grid[1]; return [x, y]; } function canDragX(draggable /*: Draggable*/) /*: boolean*/ { return draggable.props.axis === 'both' || draggable.props.axis === 'x'; } function canDragY(draggable /*: Draggable*/) /*: boolean*/ { return draggable.props.axis === 'both' || draggable.props.axis === 'y'; } // Get {x, y} positions from event. function getControlPosition(e /*: MouseTouchEvent*/, touchIdentifier /*: ?number*/, draggableCore /*: DraggableCore*/) /*: ?ControlPosition*/ { var touchObj = typeof touchIdentifier === 'number' ? getTouch(e, touchIdentifier) : null; if (typeof touchIdentifier === 'number' && !touchObj) return null; // not the right touch var node = findDOMNode(draggableCore); // User can provide an offsetParent if desired. var offsetParent = draggableCore.props.offsetParent || node.offsetParent || node.ownerDocument.body; return offsetXYFromParent(touchObj || e, offsetParent); } // Create an data object exposed by 's events function createCoreData(draggable /*: DraggableCore*/, x /*: number*/, y /*: number*/) /*: DraggableData*/ { var state = draggable.state; var isStart = !isNum(state.lastX); var node = findDOMNode(draggable); if (isStart) { // If this is our first move, use the x and y as last coords. return { node: node, deltaX: 0, deltaY: 0, lastX: x, lastY: y, x: x, y: y }; } else { // Otherwise calculate proper values. return { node: node, deltaX: x - state.lastX, deltaY: y - state.lastY, lastX: state.lastX, lastY: state.lastY, x: x, y: y }; } } // Create an data exposed by 's events function createDraggableData(draggable /*: Draggable*/, coreData /*: DraggableData*/) /*: DraggableData*/ { var scale = draggable.props.scale; return { node: coreData.node, x: draggable.state.x + coreData.deltaX / scale, y: draggable.state.y + coreData.deltaY / scale, deltaX: coreData.deltaX / scale, deltaY: coreData.deltaY / scale, lastX: draggable.state.x, lastY: draggable.state.y }; } // A lot faster than stringify/parse function cloneBounds(bounds /*: Bounds*/) /*: Bounds*/ { return { left: bounds.left, top: bounds.top, right: bounds.right, bottom: bounds.bottom }; } function findDOMNode(draggable /*: Draggable | DraggableCore*/) /*: HTMLElement*/ { var node = ReactDOM.findDOMNode(draggable); if (!node) { throw new Error(': Unmounted during event!'); } // $FlowIgnore we can't assert on HTMLElement due to tests... FIXME return node; } /*eslint no-console:0*/ function log() { } /*:: import type {EventHandler, MouseTouchEvent} from './utils/types';*/ // Simple abstraction for dragging events names. /*:: import type {Element as ReactElement} from 'react';*/ var eventsFor = { touch: { start: 'touchstart', move: 'touchmove', stop: 'touchend' }, mouse: { start: 'mousedown', move: 'mousemove', stop: 'mouseup' } }; // Default to mouse events. var dragEventFor = eventsFor.mouse; /*:: type DraggableCoreState = { dragging: boolean, lastX: number, lastY: number, touchIdentifier: ?number };*/ /*:: export type DraggableBounds = { left: number, right: number, top: number, bottom: number, };*/ /*:: export type DraggableData = { node: HTMLElement, x: number, y: number, deltaX: number, deltaY: number, lastX: number, lastY: number, };*/ /*:: export type DraggableEventHandler = (e: MouseEvent, data: DraggableData) => void;*/ /*:: export type ControlPosition = {x: number, y: number};*/ /*:: export type PositionOffsetControlPosition = {x: number|string, y: number|string};*/ // // Define . // // is for advanced usage of . It maintains minimal internal state so it can // work well with libraries that require more control over the element. // /*:: export type DraggableCoreProps = { allowAnyClick: boolean, cancel: string, children: ReactElement, disabled: boolean, enableUserSelectHack: boolean, offsetParent: HTMLElement, grid: [number, number], handle: string, onStart: DraggableEventHandler, onDrag: DraggableEventHandler, onStop: DraggableEventHandler, onMouseDown: (e: MouseEvent) => void, };*/ var DraggableCore = function (_React$Component) { inherits(DraggableCore, _React$Component); function DraggableCore() { var _ref; var _temp, _this, _ret; classCallCheck(this, DraggableCore); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = DraggableCore.__proto__ || Object.getPrototypeOf(DraggableCore)).call.apply(_ref, [this].concat(args))), _this), _this.state = { dragging: false, // Used while dragging to determine deltas. lastX: NaN, lastY: NaN, touchIdentifier: null }, _this.handleDragStart = function (e) { // Make it possible to attach event handlers on top of this one. _this.props.onMouseDown(e); // Only accept left-clicks. if (!_this.props.allowAnyClick && typeof e.button === 'number' && e.button !== 0) return false; // Get nodes. Be sure to grab relative document (could be iframed) var thisNode = ReactDOM.findDOMNode(_this); if (!thisNode || !thisNode.ownerDocument || !thisNode.ownerDocument.body) { throw new Error(' not mounted on DragStart!'); } var ownerDocument = thisNode.ownerDocument; // Short circuit if handle or cancel prop was provided and selector doesn't match. if (_this.props.disabled || !(e.target instanceof ownerDocument.defaultView.Node) || _this.props.handle && !matchesSelectorAndParentsTo(e.target, _this.props.handle, thisNode) || _this.props.cancel && matchesSelectorAndParentsTo(e.target, _this.props.cancel, thisNode)) { return; } // Set touch identifier in component state if this is a touch event. This allows us to // distinguish between individual touches on multitouch screens by identifying which // touchpoint was set to this element. var touchIdentifier = getTouchIdentifier(e); _this.setState({ touchIdentifier: touchIdentifier }); // Get the current drag point from the event. This is used as the offset. var position = getControlPosition(e, touchIdentifier, _this); if (position == null) return; // not possible but satisfies flow var x = position.x, y = position.y; // Create an event object with all the data parents need to make a decision here. var coreEvent = createCoreData(_this, x, y); // Call event handler. If it returns explicit false, cancel. log('calling', _this.props.onStart); var shouldUpdate = _this.props.onStart(e, coreEvent); if (shouldUpdate === false) return; // Add a style to the body to disable user-select. This prevents text from // being selected all over the page. if (_this.props.enableUserSelectHack) addUserSelectStyles(ownerDocument); // Initiate dragging. Set the current x and y as offsets // so we know how much we've moved during the drag. This allows us // to drag elements around even if they have been moved, without issue. _this.setState({ dragging: true, lastX: x, lastY: y }); // Add events to the document directly so we catch when the user's mouse/touch moves outside of // this element. We use different events depending on whether or not we have detected that this // is a touch-capable device. addEvent(ownerDocument, dragEventFor.move, _this.handleDrag); addEvent(ownerDocument, dragEventFor.stop, _this.handleDragStop); }, _this.handleDrag = function (e) { // Prevent scrolling on mobile devices, like ipad/iphone. if (e.type === 'touchmove') e.preventDefault(); // Get the current drag point from the event. This is used as the offset. var position = getControlPosition(e, _this.state.touchIdentifier, _this); if (position == null) return; var x = position.x, y = position.y; // Snap to grid if prop has been provided if (Array.isArray(_this.props.grid)) { var _deltaX = x - _this.state.lastX, _deltaY = y - _this.state.lastY; var _snapToGrid = snapToGrid(_this.props.grid, _deltaX, _deltaY); var _snapToGrid2 = slicedToArray(_snapToGrid, 2); _deltaX = _snapToGrid2[0]; _deltaY = _snapToGrid2[1]; if (!_deltaX && !_deltaY) return; // skip useless drag x = _this.state.lastX + _deltaX, y = _this.state.lastY + _deltaY; } var coreEvent = createCoreData(_this, x, y); // Call event handler. If it returns explicit false, trigger end. var shouldUpdate = _this.props.onDrag(e, coreEvent); if (shouldUpdate === false) { try { // $FlowIgnore _this.handleDragStop(new MouseEvent('mouseup')); } catch (err) { // Old browsers var event = ((document.createEvent('MouseEvents') /*: any*/) /*: MouseTouchEvent*/); // I see why this insanity was deprecated // $FlowIgnore event.initMouseEvent('mouseup', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); _this.handleDragStop(event); } return; } _this.setState({ lastX: x, lastY: y }); }, _this.handleDragStop = function (e) { if (!_this.state.dragging) return; var position = getControlPosition(e, _this.state.touchIdentifier, _this); if (position == null) return; var x = position.x, y = position.y; var coreEvent = createCoreData(_this, x, y); var thisNode = ReactDOM.findDOMNode(_this); if (thisNode) { // Remove user-select hack if (_this.props.enableUserSelectHack) removeUserSelectStyles(thisNode.ownerDocument); } // Reset the el. _this.setState({ dragging: false, lastX: NaN, lastY: NaN }); // Call event handler _this.props.onStop(e, coreEvent); if (thisNode) { removeEvent(thisNode.ownerDocument, dragEventFor.move, _this.handleDrag); removeEvent(thisNode.ownerDocument, dragEventFor.stop, _this.handleDragStop); } }, _this.onMouseDown = function (e) { dragEventFor = eventsFor.mouse; // on touchscreen laptops we could switch back to mouse return _this.handleDragStart(e); }, _this.onMouseUp = function (e) { dragEventFor = eventsFor.mouse; return _this.handleDragStop(e); }, _this.onTouchStart = function (e) { // We're on a touch device now, so change the event handlers dragEventFor = eventsFor.touch; return _this.handleDragStart(e); }, _this.onTouchEnd = function (e) { // We're on a touch device now, so change the event handlers dragEventFor = eventsFor.touch; return _this.handleDragStop(e); }, _temp), possibleConstructorReturn(_this, _ret); } createClass(DraggableCore, [{ key: 'componentWillUnmount', value: function componentWillUnmount() { // Remove any leftover event handlers. Remove both touch and mouse handlers in case // some browser quirk caused a touch event to fire during a mouse move, or vice versa. var thisNode = ReactDOM.findDOMNode(this); if (thisNode) { var ownerDocument = thisNode.ownerDocument; removeEvent(ownerDocument, eventsFor.mouse.move, this.handleDrag); removeEvent(ownerDocument, eventsFor.touch.move, this.handleDrag); removeEvent(ownerDocument, eventsFor.mouse.stop, this.handleDragStop); removeEvent(ownerDocument, eventsFor.touch.stop, this.handleDragStop); if (this.props.enableUserSelectHack) removeUserSelectStyles(ownerDocument); } } // Same as onMouseDown (start drag), but now consider this a touch device. }, { key: 'render', value: function render() { // Reuse the child provided // This makes it flexible to use whatever element is wanted (div, ul, etc) return React.cloneElement(React.Children.only(this.props.children), { style: styleHacks(this.props.children.props.style), // Note: mouseMove handler is attached to document so it will still function // when the user drags quickly and leaves the bounds of the element. onMouseDown: this.onMouseDown, onTouchStart: this.onTouchStart, onMouseUp: this.onMouseUp, onTouchEnd: this.onTouchEnd }); } }]); return DraggableCore; }(React.Component); DraggableCore.displayName = 'DraggableCore'; DraggableCore.propTypes = { /** * `allowAnyClick` allows dragging using any mouse button. * By default, we only accept the left button. * * Defaults to `false`. */ allowAnyClick: propTypes.bool, /** * `disabled`, if true, stops the from dragging. All handlers, * with the exception of `onMouseDown`, will not fire. */ disabled: propTypes.bool, /** * By default, we add 'user-select:none' attributes to the document body * to prevent ugly text selection during drag. If this is causing problems * for your app, set this to `false`. */ enableUserSelectHack: propTypes.bool, /** * `offsetParent`, if set, uses the passed DOM node to compute drag offsets * instead of using the parent node. */ offsetParent: function offsetParent(props /*: DraggableCoreProps*/, propName /*: $Keys*/) { if (props[propName] && props[propName].nodeType !== 1) { throw new Error('Draggable\'s offsetParent must be a DOM Node.'); } }, /** * `grid` specifies the x and y that dragging should snap to. */ grid: propTypes.arrayOf(propTypes.number), /** * `scale` specifies the scale of the area you are dragging inside of. It allows * the drag deltas to scale correctly with how far zoomed in/out you are. */ scale: propTypes.number, /** * `handle` specifies a selector to be used as the handle that initiates drag. * * Example: * * ```jsx * let App = React.createClass({ * render: function () { * return ( * *
*
Click me to drag
*
This is some other content
*
*
* ); * } * }); * ``` */ handle: propTypes.string, /** * `cancel` specifies a selector to be used to prevent drag initialization. * * Example: * * ```jsx * let App = React.createClass({ * render: function () { * return( * *
*
You can't drag from here
*
Dragging here works fine
*
*
* ); * } * }); * ``` */ cancel: propTypes.string, /** * Called when dragging starts. * If this function returns the boolean false, dragging will be canceled. */ onStart: propTypes.func, /** * Called while dragging. * If this function returns the boolean false, dragging will be canceled. */ onDrag: propTypes.func, /** * Called when dragging stops. * If this function returns the boolean false, the drag will remain active. */ onStop: propTypes.func, /** * A workaround option which can be passed if onMouseDown needs to be accessed, * since it'll always be blocked (as there is internal use of onMouseDown) */ onMouseDown: propTypes.func, /** * These properties should be defined on the child, not here. */ className: dontSetMe, style: dontSetMe, transform: dontSetMe }; DraggableCore.defaultProps = { allowAnyClick: false, // by default only accept left click cancel: null, disabled: false, enableUserSelectHack: true, offsetParent: null, handle: null, grid: null, transform: null, onStart: function onStart() {}, onDrag: function onDrag() {}, onStop: function onStop() {}, onMouseDown: function onMouseDown() {} }; /*:: import type {DraggableEventHandler} from './utils/types';*/ /*:: import type {Element as ReactElement} from 'react';*/ /*:: type DraggableState = { dragging: boolean, dragged: boolean, x: number, y: number, slackX: number, slackY: number, isElementSVG: boolean };*/ // // Define // /*:: export type DraggableProps = { ...$Exact, axis: 'both' | 'x' | 'y' | 'none', bounds: DraggableBounds | string | false, defaultClassName: string, defaultClassNameDragging: string, defaultClassNameDragged: string, defaultPosition: ControlPosition, positionOffset: PositionOffsetControlPosition, position: ControlPosition, scale: number };*/ var Draggable = function (_React$Component) { inherits(Draggable, _React$Component); function Draggable(props /*: DraggableProps*/) { classCallCheck(this, Draggable); var _this = possibleConstructorReturn(this, (Draggable.__proto__ || Object.getPrototypeOf(Draggable)).call(this, props)); _this.onDragStart = function (e, coreData) { // Short-circuit if user's callback killed it. var shouldStart = _this.props.onStart(e, createDraggableData(_this, coreData)); // Kills start event on core as well, so move handlers are never bound. if (shouldStart === false) return false; _this.setState({ dragging: true, dragged: true }); }; _this.onDrag = function (e, coreData) { if (!_this.state.dragging) return false; var uiData = createDraggableData(_this, coreData); var newState /*: $Shape*/ = { x: uiData.x, y: uiData.y }; // Keep within bounds. if (_this.props.bounds) { // Save original x and y. var _x = newState.x, _y = newState.y; // Add slack to the values used to calculate bound position. This will ensure that if // we start removing slack, the element won't react to it right away until it's been // completely removed. newState.x += _this.state.slackX; newState.y += _this.state.slackY; // Get bound position. This will ceil/floor the x and y within the boundaries. var _getBoundPosition = getBoundPosition(_this, newState.x, newState.y), _getBoundPosition2 = slicedToArray(_getBoundPosition, 2), newStateX = _getBoundPosition2[0], newStateY = _getBoundPosition2[1]; newState.x = newStateX; newState.y = newStateY; // Recalculate slack by noting how much was shaved by the boundPosition handler. newState.slackX = _this.state.slackX + (_x - newState.x); newState.slackY = _this.state.slackY + (_y - newState.y); // Update the event we fire to reflect what really happened after bounds took effect. uiData.x = newState.x; uiData.y = newState.y; uiData.deltaX = newState.x - _this.state.x; uiData.deltaY = newState.y - _this.state.y; } // Short-circuit if user's callback killed it. var shouldUpdate = _this.props.onDrag(e, uiData); if (shouldUpdate === false) return false; _this.setState(newState); }; _this.onDragStop = function (e, coreData) { if (!_this.state.dragging) return false; // Short-circuit if user's callback killed it. var shouldStop = _this.props.onStop(e, createDraggableData(_this, coreData)); if (shouldStop === false) return false; var newState /*: $Shape*/ = { dragging: false, slackX: 0, slackY: 0 }; // If this is a controlled component, the result of this operation will be to // revert back to the old position. We expect a handler on `onDragStop`, at the least. var controlled = Boolean(_this.props.position); if (controlled) { var _this$props$position = _this.props.position, _x2 = _this$props$position.x, _y2 = _this$props$position.y; newState.x = _x2; newState.y = _y2; } _this.setState(newState); }; _this.state = { // Whether or not we are currently dragging. dragging: false, // Whether or not we have been dragged before. dragged: false, // Current transform x and y. x: props.position ? props.position.x : props.defaultPosition.x, y: props.position ? props.position.y : props.defaultPosition.y, // Used for compensating for out-of-bounds drags slackX: 0, slackY: 0, // Can only determine if SVG after mounting isElementSVG: false }; if (props.position && !(props.onDrag || props.onStop)) { // eslint-disable-next-line no-console console.warn('A `position` was applied to this , without drag handlers. This will make this ' + 'component effectively undraggable. Please attach `onDrag` or `onStop` handlers so you can adjust the ' + '`position` of this element.'); } return _this; } createClass(Draggable, [{ key: 'componentDidMount', value: function componentDidMount() { // Check to see if the element passed is an instanceof SVGElement if (typeof window.SVGElement !== 'undefined' && ReactDOM.findDOMNode(this) instanceof window.SVGElement) { this.setState({ isElementSVG: true }); } } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps /*: Object*/) { // Set x/y if position has changed if (nextProps.position && (!this.props.position || nextProps.position.x !== this.props.position.x || nextProps.position.y !== this.props.position.y)) { this.setState({ x: nextProps.position.x, y: nextProps.position.y }); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this.setState({ dragging: false }); // prevents invariant if unmounted while dragging } }, { key: 'render', value: function render() /*: ReactElement*/ { var _classNames; var style = {}, svgTransform = null; // If this is controlled, we don't want to move it - unless it's dragging. var controlled = Boolean(this.props.position); var draggable = !controlled || this.state.dragging; var position = this.props.position || this.props.defaultPosition; var transformOpts = { // Set left if horizontal drag is enabled x: canDragX(this) && draggable ? this.state.x : position.x, // Set top if vertical drag is enabled y: canDragY(this) && draggable ? this.state.y : position.y }; // If this element was SVG, we use the `transform` attribute. if (this.state.isElementSVG) { svgTransform = createSVGTransform(transformOpts, this.props.positionOffset); } else { // Add a CSS transform to move the element around. This allows us to move the element around // without worrying about whether or not it is relatively or absolutely positioned. // If the item you are dragging already has a transform set, wrap it in a so // has a clean slate. style = createCSSTransform(transformOpts, this.props.positionOffset); } var _props = this.props, defaultClassName = _props.defaultClassName, defaultClassNameDragging = _props.defaultClassNameDragging, defaultClassNameDragged = _props.defaultClassNameDragged; var children = React.Children.only(this.props.children); // Mark with class while dragging var className = classnames(children.props.className || '', defaultClassName, (_classNames = {}, defineProperty(_classNames, defaultClassNameDragging, this.state.dragging), defineProperty(_classNames, defaultClassNameDragged, this.state.dragged), _classNames)); // Reuse the child provided // This makes it flexible to use whatever element is wanted (div, ul, etc) return React.createElement( DraggableCore, _extends({}, this.props, { onStart: this.onDragStart, onDrag: this.onDrag, onStop: this.onDragStop }), React.cloneElement(children, { className: className, style: _extends({}, children.props.style, style), transform: svgTransform }) ); } }]); return Draggable; }(React.Component); Draggable.displayName = 'Draggable'; Draggable.propTypes = _extends({}, DraggableCore.propTypes, { /** * `axis` determines which axis the draggable can move. * * Note that all callbacks will still return data as normal. This only * controls flushing to the DOM. * * 'both' allows movement horizontally and vertically. * 'x' limits movement to horizontal axis. * 'y' limits movement to vertical axis. * 'none' limits all movement. * * Defaults to 'both'. */ axis: propTypes.oneOf(['both', 'x', 'y', 'none']), /** * `bounds` determines the range of movement available to the element. * Available values are: * * 'parent' restricts movement within the Draggable's parent node. * * Alternatively, pass an object with the following properties, all of which are optional: * * {left: LEFT_BOUND, right: RIGHT_BOUND, bottom: BOTTOM_BOUND, top: TOP_BOUND} * * All values are in px. * * Example: * * ```jsx * let App = React.createClass({ * render: function () { * return ( * *
Content
*
* ); * } * }); * ``` */ bounds: propTypes.oneOfType([propTypes.shape({ left: propTypes.number, right: propTypes.number, top: propTypes.number, bottom: propTypes.number }), propTypes.string, propTypes.oneOf([false])]), defaultClassName: propTypes.string, defaultClassNameDragging: propTypes.string, defaultClassNameDragged: propTypes.string, /** * `defaultPosition` specifies the x and y that the dragged item should start at * * Example: * * ```jsx * let App = React.createClass({ * render: function () { * return ( * *
I start with transformX: 25px and transformY: 25px;
*
* ); * } * }); * ``` */ defaultPosition: propTypes.shape({ x: propTypes.number, y: propTypes.number }), positionOffset: propTypes.shape({ x: propTypes.oneOfType([propTypes.number, propTypes.string]), y: propTypes.oneOfType([propTypes.number, propTypes.string]) }), /** * `position`, if present, defines the current position of the element. * * This is similar to how form elements in React work - if no `position` is supplied, the component * is uncontrolled. * * Example: * * ```jsx * let App = React.createClass({ * render: function () { * return ( * *
I start with transformX: 25px and transformY: 25px;
*
* ); * } * }); * ``` */ position: propTypes.shape({ x: propTypes.number, y: propTypes.number }), /** * These properties should be defined on the child, not here. */ className: dontSetMe, style: dontSetMe, transform: dontSetMe }); Draggable.defaultProps = _extends({}, DraggableCore.defaultProps, { axis: 'both', bounds: false, defaultClassName: 'react-draggable', defaultClassNameDragging: 'react-draggable-dragging', defaultClassNameDragged: 'react-draggable-dragged', defaultPosition: { x: 0, y: 0 }, position: null, scale: 1 }); // Previous versions of this lib exported as the root export. As to not break // them, or TypeScript, we export *both* as the root and as 'default'. // See https://github.com/mzabriskie/react-draggable/pull/254 // and https://github.com/mzabriskie/react-draggable/issues/266 Draggable.default = Draggable; Draggable.DraggableCore = DraggableCore; return Draggable; }))); //# sourceMappingURL=react-draggable.js.map