React-Draggable

React draggable component

README

React-Draggable

TravisCI Build Status Appveyor Build Status npm downloads [gzip size]() [version]()


A simple component for making elements draggable.

  1. ``` js
  2. <Draggable>
  3.   <div>I can now be moved around!</div>
  4. </Draggable>
  5. ```



|VersionCompatibility|
|------------|--------------|
|4.xReact
|3.xReact
|2.xReact
|1.xReact
|0.xReact


Technical Documentation





Installing


  1. ``` sh
  2. $ npm install react-draggable
  3. ```

If you aren't using browserify/webpack, a
UMD version of react-draggable is available. It is updated per-release only.
This bundle is also what is loaded when installing from npm. It expects external React and ReactDOM.

If you want a UMD version of the latest master revision, you can generate it yourself from master by cloning this
repository and running $ make. This will create umd dist files in the dist/ folder.

Exports


The default export is ``. At the `.DraggableCore` property is [``](#draggablecore).
Here's how to use it:

  1. ``` js
  2. // ES6
  3. import Draggable from 'react-draggable'; // The default
  4. import {DraggableCore} from 'react-draggable'; //
  5. import Draggable, {DraggableCore} from 'react-draggable'; // Both at the same time

  6. // CommonJS
  7. let Draggable = require('react-draggable');
  8. let DraggableCore = Draggable.DraggableCore;
  9. ```

## ``

A `` element wraps an existing element and extends it with new event handlers and styles.
It does not create a wrapper element in the DOM.

Draggable items are moved using CSS Transforms. This allows items to be dragged regardless of their current
positioning (relative, absolute, or static). Elements can also be moved between drags without incident.

If the item you are dragging already has a CSS Transform applied, it will be overwritten by ``. Usean intermediate wrapper (`...`) in this case.

Draggable Usage


View the Demo and its
source for more.

  1. ``` js
  2. import React from 'react';
  3. import ReactDOM from 'react-dom';
  4. import Draggable from 'react-draggable';

  5. class App extends React.Component {

  6.   eventLogger = (e: MouseEvent, data: Object) => {
  7.     console.log('Event: ', e);
  8.     console.log('Data: ', data);
  9.   };

  10.   render() {
  11.     return (
  12.       <Draggable
  13.         axis="x"
  14.         handle=".handle"
  15.         defaultPosition={{x: 0, y: 0}}
  16.         position={null}
  17.         grid={[25, 25]}
  18.         scale={1}
  19.         onStart={this.handleStart}
  20.         onDrag={this.handleDrag}
  21.         onStop={this.handleStop}>
  22.         <div>
  23.           <div className="handle">Drag from here</div>
  24.           <div>This readme is really dragging on...</div>
  25.         </div>
  26.       </Draggable>
  27.     );
  28.   }
  29. }

  30. ReactDOM.render(<App/>, document.body);
  31. ```

Draggable API


The `` component transparently adds draggability to its children.

Note: Only a single child is allowed or an Error will be thrown.

For the `` component to correctly attach itself to its child, the child element must provide support
for the following props:
- style is used to give the transform css to the child.
- className is used to apply the proper classes to the object being dragged.
- onMouseDown, onMouseUp, onTouchStart, and onTouchEnd  are used to keep track of dragging state.

React.DOM elements support the above properties by default, so you may use those elements as children without
any changes. If you wish to use a React component you created, you'll need to be sure to

#### `` Props:

  1. ``` js
  2. //
  3. // Types:
  4. //
  5. type DraggableEventHandler = (e: Event, data: DraggableData) => void | false;
  6. type DraggableData = {
  7.   node: HTMLElement,
  8.   // lastX + deltaX === x
  9.   x: number, y: number,
  10.   deltaX: number, deltaY: number,
  11.   lastX: number, lastY: number
  12. };

  13. //
  14. // Props:
  15. //
  16. {
  17. // If set to `true`, will allow dragging on non left-button clicks.
  18. allowAnyClick: boolean,

  19. // Determines which axis the draggable can move. This only affects
  20. // flushing to the DOM. Callbacks will still include all values.
  21. // Accepted values:
  22. // - `both` allows movement horizontally and vertically (default).
  23. // - `x` limits movement to horizontal axis.
  24. // - `y` limits movement to vertical axis.
  25. // - 'none' stops all movement.
  26. axis: string,

  27. // Specifies movement boundaries. Accepted values:
  28. // - `parent` restricts movement within the node's offsetParent
  29. //    (nearest node with position relative or absolute), or
  30. // - a selector, restricts movement within the targeted node
  31. // - An object with `left, top, right, and bottom` properties.
  32. //   These indicate how far in each direction the draggable
  33. //   can be moved.
  34. bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,

  35. // Specifies a selector to be used to prevent drag initialization. The string is passed to
  36. // Element.matches, so it's possible to use multiple selectors like `.first, .second`.
  37. // Example: '.body'
  38. cancel: string,

  39. // Class names for draggable UI.
  40. // Default to 'react-draggable', 'react-draggable-dragging', and 'react-draggable-dragged'
  41. defaultClassName: string,
  42. defaultClassNameDragging: string,
  43. defaultClassNameDragged: string,

  44. // Specifies the `x` and `y` that the dragged item should start at.
  45. // This is generally not necessary to use (you can use absolute or relative
  46. // positioning of the child directly), but can be helpful for uniformity in
  47. // your callbacks and with css transforms.
  48. defaultPosition: {x: number, y: number},

  49. // If true, will not call any drag handlers.
  50. disabled: boolean,

  51. // Specifies the x and y that dragging should snap to.
  52. grid: [number, number],

  53. // Specifies a selector to be used as the handle that initiates drag.
  54. // Example: '.handle'
  55. handle: string,

  56. // If desired, you can provide your own offsetParent for drag calculations.
  57. // By default, we use the Draggable's offsetParent. This can be useful for elements
  58. // with odd display types or floats.
  59. offsetParent: HTMLElement,

  60. // Called whenever the user mouses down. Called regardless of handle or
  61. // disabled status.
  62. onMouseDown: (e: MouseEvent) => void,

  63. // Called when dragging starts. If `false` is returned any handler,
  64. // the action will cancel.
  65. onStart: DraggableEventHandler,

  66. // Called while dragging.
  67. onDrag: DraggableEventHandler,

  68. // Called when dragging stops.
  69. onStop: DraggableEventHandler,

  70. // If running in React Strict mode, ReactDOM.findDOMNode() is deprecated.
  71. // Unfortunately, in order for to work properly, we need raw access
  72. // to the underlying DOM node. If you want to avoid the warning, pass a `nodeRef`
  73. // as in this example:
  74. //
  75. // function MyComponent() {
  76. //   const nodeRef = React.useRef(null);
  77. //   return (
  78. //    
  79. //      
    Example Target
  80. //    
  81. //   );
  82. // }
  83. //
  84. // This can be used for arbitrarily nested components, so long as the ref ends up
  85. // pointing to the actual child DOM node and not a custom component.
  86. //
  87. // For rich components, you need to both forward the ref *and props* to the underlying DOM
  88. // element. Props must be forwarded so that DOM event handlers can be attached.
  89. // For example:
  90. //
  91. //   const Component1 = React.forwardRef(function (props, ref) {
  92. //     return
    Nested component
    ;
  93. //   });
  94. //
  95. //   const nodeRef = React.useRef(null);
  96. //  
  97. //    
  98. //  
  99. //
  100. // Thanks to react-transition-group for the inspiration.
  101. //
  102. // `nodeRef` is also available on .
  103. nodeRef: React.Ref<typeof React.Component>,

  104. // Much like React form elements, if this property is present, the item
  105. // becomes 'controlled' and is not responsive to user input. Use `position`
  106. // if you need to have direct control of the element.
  107. position: {x: number, y: number}

  108. // A position offset to start with. Useful for giving an initial position
  109. // to the element. Differs from `defaultPosition` in that it does not
  110. // affect the position returned in draggable callbacks, and in that it
  111. // accepts strings, like `{x: '10%', y: '10%'}`.
  112. positionOffset: {x: number | string, y: number | string},

  113. // Specifies the scale of the canvas your are dragging this element on. This allows
  114. // you to, for example, get the correct drag deltas while you are zoomed in or out via
  115. // a transform or matrix in the parent of this element.
  116. scale: number
  117. }
  118. ```


Note that sending className, style, or transform as properties will error - set them on the child element
directly.


Controlled vs. Uncontrolled


`` is a 'batteries-included' component that manages its own state. If you want to completelycontrol the lifecycle of the component, use ``.

For some users, they may want the nice state management that `` provides, but occasionally wantto programmatically reposition their components. `` allows this customization via a system that
is similar to how React handles form components.

If the prop `position: {x: number, y: number}` is defined, the `` will ignore its internal state and use
the provided position instead. Alternatively, you can seed the position using defaultPosition. Technically, since
`` works only on position deltas, you could also seed the initial position using CSS `top/left`.

We make one modification to the React philosophy here - we still allow dragging while a component is controlled.
We then expect you to use at least an onDrag or onStop handler to synchronize state.

To disable dragging while controlled, send the prop `disabled={true}` - at this point the `` will operate
like a completely static component.

## ``

For users that require absolute control, a `` element is available. This is useful as an abstractionover touch and mouse events, but with full control. `` has no internal state.

React-Grid-Layout for some usage examples.

`` is a useful building block for other libraries that simply want to abstract browser-specific
quirks and receive callbacks when a user attempts to move an element. It does not set styles or transforms
on itself and thus must have callbacks attached to be useful.

DraggableCore API


`` takes a limited subset of options:

  1. ``` js
  2. {
  3.   allowAnyClick: boolean,
  4.   cancel: string,
  5.   disabled: boolean,
  6.   enableUserSelectHack: boolean,
  7.   offsetParent: HTMLElement,
  8.   grid: [number, number],
  9.   handle: string,
  10.   onStart: DraggableEventHandler,
  11.   onDrag: DraggableEventHandler,
  12.   onStop: DraggableEventHandler,
  13.   onMouseDown: (e: MouseEvent) => void,
  14.   scale: number
  15. }
  16. ```

Note that there is no start position. `` simply calls `drag` handlers with the below parameters,
indicating its position (as inferred from the underlying MouseEvent) and deltas. It is up to the parent
to set actual positions on ``.

Drag callbacks (`onStart`, `onDrag`, `onStop`) are called with the [same arguments as ``](#draggable-api).


Contributing


- Fork the project
- Run the project in development mode: $ npm run dev
- Make changes.
- Add appropriate tests
- $ npm test
- If tests don't pass, make them pass.
- Update README with appropriate docs.
- Commit and PR

Release checklist


- Update CHANGELOG
- make release-patch, make release-minor, or make-release-major
- make publish

License


MIT