"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "DraggableCore", { enumerable: true, get: function () { return _DraggableCore.default; } }); exports.default = void 0; var React = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactDom = _interopRequireDefault(require("react-dom")); var _clsx = _interopRequireDefault(require("clsx")); var _domFns = require("./utils/domFns"); var _positionFns = require("./utils/positionFns"); var _shims = require("./utils/shims"); var _DraggableCore = _interopRequireDefault(require("./DraggableCore")); var _log = _interopRequireDefault(require("./utils/log")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } /*:: import type {ControlPosition, PositionOffsetControlPosition, DraggableCoreProps, DraggableCoreDefaultProps} from './DraggableCore';*/ /*:: import type {Bounds, 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, prevPropsPosition: ?ControlPosition, };*/ /*:: export type DraggableDefaultProps = { ...DraggableCoreDefaultProps, axis: 'both' | 'x' | 'y' | 'none', bounds: Bounds | string | false, defaultClassName: string, defaultClassNameDragging: string, defaultClassNameDragged: string, defaultPosition: ControlPosition, scale: number, };*/ /*:: export type DraggableProps = { ...DraggableCoreProps, ...DraggableDefaultProps, positionOffset: PositionOffsetControlPosition, position: ControlPosition, };*/ // // Define // class Draggable extends React.Component /*:: */{ // React 16.3+ // Arity (props, state) static getDerivedStateFromProps(_ref /*:: */, _ref2 /*:: */) /*: ?Partial*/{ let { position } /*: DraggableProps*/ = _ref /*: DraggableProps*/; let { prevPropsPosition } /*: DraggableState*/ = _ref2 /*: DraggableState*/; // Set x/y if a new position is provided in props that is different than the previous. if (position && (!prevPropsPosition || position.x !== prevPropsPosition.x || position.y !== prevPropsPosition.y)) { (0, _log.default)('Draggable: getDerivedStateFromProps %j', { position, prevPropsPosition }); return { x: position.x, y: position.y, prevPropsPosition: { ...position } }; } return null; } constructor(props /*: DraggableProps*/) { super(props); _defineProperty(this, "onDragStart", (e, coreData) => { (0, _log.default)('Draggable: onDragStart: %j', coreData); // Short-circuit if user's callback killed it. const shouldStart = this.props.onStart(e, (0, _positionFns.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 }); }); _defineProperty(this, "onDrag", (e, coreData) => { if (!this.state.dragging) return false; (0, _log.default)('Draggable: onDrag: %j', coreData); const uiData = (0, _positionFns.createDraggableData)(this, coreData); const newState = { x: uiData.x, y: uiData.y, slackX: 0, slackY: 0 }; // Keep within bounds. if (this.props.bounds) { // Save original x and y. const { x, y } = newState; // 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. const [newStateX, newStateY] = (0, _positionFns.getBoundPosition)(this, newState.x, newState.y); 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. const shouldUpdate = this.props.onDrag(e, uiData); if (shouldUpdate === false) return false; this.setState(newState); }); _defineProperty(this, "onDragStop", (e, coreData) => { if (!this.state.dragging) return false; // Short-circuit if user's callback killed it. const shouldContinue = this.props.onStop(e, (0, _positionFns.createDraggableData)(this, coreData)); if (shouldContinue === false) return false; (0, _log.default)('Draggable: onDragStop: %j', coreData); const newState /*: Partial*/ = { 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. const controlled = Boolean(this.props.position); if (controlled) { const { x, y } = this.props.position; newState.x = x; newState.y = y; } 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, prevPropsPosition: { ...props.position }, // 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.'); } } componentDidMount() { // Check to see if the element passed is an instanceof SVGElement if (typeof window.SVGElement !== 'undefined' && this.findDOMNode() instanceof window.SVGElement) { this.setState({ isElementSVG: true }); } } componentWillUnmount() { this.setState({ dragging: false }); // prevents invariant if unmounted while dragging } // React Strict Mode compatibility: if `nodeRef` is passed, we will use it instead of trying to find // the underlying DOM node ourselves. See the README for more information. findDOMNode() /*: ?HTMLElement*/{ var _this$props$nodeRef$c, _this$props; return (_this$props$nodeRef$c = (_this$props = this.props) === null || _this$props === void 0 || (_this$props = _this$props.nodeRef) === null || _this$props === void 0 ? void 0 : _this$props.current) !== null && _this$props$nodeRef$c !== void 0 ? _this$props$nodeRef$c : _reactDom.default.findDOMNode(this); } render() /*: ReactElement*/{ const { axis, bounds, children, defaultPosition, defaultClassName, defaultClassNameDragging, defaultClassNameDragged, position, positionOffset, scale, ...draggableCoreProps } = this.props; let style = {}; let svgTransform = null; // If this is controlled, we don't want to move it - unless it's dragging. const controlled = Boolean(position); const draggable = !controlled || this.state.dragging; const validPosition = position || defaultPosition; const transformOpts = { // Set left if horizontal drag is enabled x: (0, _positionFns.canDragX)(this) && draggable ? this.state.x : validPosition.x, // Set top if vertical drag is enabled y: (0, _positionFns.canDragY)(this) && draggable ? this.state.y : validPosition.y }; // If this element was SVG, we use the `transform` attribute. if (this.state.isElementSVG) { svgTransform = (0, _domFns.createSVGTransform)(transformOpts, 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 = (0, _domFns.createCSSTransform)(transformOpts, positionOffset); } // Mark with class while dragging const className = (0, _clsx.default)(children.props.className || '', defaultClassName, { [defaultClassNameDragging]: this.state.dragging, [defaultClassNameDragged]: this.state.dragged }); // Reuse the child provided // This makes it flexible to use whatever element is wanted (div, ul, etc) return /*#__PURE__*/React.createElement(_DraggableCore.default, _extends({}, draggableCoreProps, { onStart: this.onDragStart, onDrag: this.onDrag, onStop: this.onDragStop }), /*#__PURE__*/React.cloneElement(React.Children.only(children), { className: className, style: { ...children.props.style, ...style }, transform: svgTransform })); } } exports.default = Draggable; _defineProperty(Draggable, "displayName", 'Draggable'); _defineProperty(Draggable, "propTypes", { // Accepts all props accepts. ..._DraggableCore.default.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.default.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.default.oneOfType([_propTypes.default.shape({ left: _propTypes.default.number, right: _propTypes.default.number, top: _propTypes.default.number, bottom: _propTypes.default.number }), _propTypes.default.string, _propTypes.default.oneOf([false])]), defaultClassName: _propTypes.default.string, defaultClassNameDragging: _propTypes.default.string, defaultClassNameDragged: _propTypes.default.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.default.shape({ x: _propTypes.default.number, y: _propTypes.default.number }), positionOffset: _propTypes.default.shape({ x: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]), y: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.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.default.shape({ x: _propTypes.default.number, y: _propTypes.default.number }), /** * These properties should be defined on the child, not here. */ className: _shims.dontSetMe, style: _shims.dontSetMe, transform: _shims.dontSetMe }); _defineProperty(Draggable, "defaultProps", { ..._DraggableCore.default.defaultProps, axis: 'both', bounds: false, defaultClassName: 'react-draggable', defaultClassNameDragging: 'react-draggable-dragging', defaultClassNameDragged: 'react-draggable-dragged', defaultPosition: { x: 0, y: 0 }, scale: 1 });