Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-beautiful-dnd

Package Overview
Dependencies
Maintainers
1
Versions
94
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-beautiful-dnd - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

CONTRIBUTING.md

2

lib/view/draggable/draggable.js

@@ -216,2 +216,3 @@ 'use strict';

left: left,
margin: 0,
transform: movementStyle.transform ? '' + movementStyle.transform : null

@@ -244,2 +245,3 @@ };

return _this.getDraggingStyle(width, height, top, left, isDropAnimating, movementStyle);

@@ -246,0 +248,0 @@ }();

2

package.json
{
"name": "react-beautiful-dnd",
"version": "1.0.2",
"version": "1.0.3",
"description": "Beautiful, accessible drag and drop for lists with React.js",

@@ -5,0 +5,0 @@ "author": "Alex Reardon <areardon@atlassian.com>",

# react-beautiful-dnd
Beautiful, accessible drag and drop for lists with [React.js](https://facebook.github.io/react/)
Beautiful, accessible drag and drop for lists with [`React.js`](https://facebook.github.io/react/)

@@ -22,5 +22,5 @@ [![Build Status](https://travis-ci.org/atlassian/react-beautiful-dnd.svg?branch=master)](https://travis-ci.org/atlassian/react-beautiful-dnd) [![dependencies](https://david-dm.org/atlassian/react-beautiful-dnd.svg)](https://david-dm.org/atlassian/react-beautiful-dnd) [![SemVer](https://img.shields.io/badge/SemVer-2.0.0-brightgreen.svg)](http://semver.org/spec/v2.0.0.html)

## Why not [react-dnd](https://github.com/react-dnd/react-dnd)?
## Not for everyone
There are a lot of libraries out there that allow for drag and drop interactions within React. Most notable of these is the amazing **react-dnd**. It does an incredible job at providing a great set of drag and drop primitives which work especially well with the [wildly inconsistent](https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html) html5 drag and drop feature. **react-beautiful-dnd is a higher level abstraction specifically built for vertical and horizontal lists**. Within that subset of functionality react-beautiful-dnd offers a powerful, natural and beautiful drag and drop experience. However, it does not provide the breadth of functionality offered by **react-dnd**. So this library might not be for you depending on what your use case is.
There are a lot of libraries out there that allow for drag and drop interactions within React. Most notable of these is the amazing [`react-dnd`](https://github.com/react-dnd/react-dnd). It does an incredible job at providing a great set of drag and drop primitives which work especially well with the [wildly inconsistent](https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html) html5 drag and drop feature. **`react-beautiful-dnd` is a higher level abstraction specifically built for vertical and horizontal lists**. Within that subset of functionality `react-beautiful-dnd` offers a powerful, natural and beautiful drag and drop experience. However, it does not provide the breadth of functionality offered by react-dnd. So this library might not be for you depending on what your use case is.

@@ -70,9 +70,10 @@ ## Still young!

// fake data generator
const getItems = (count) => Array.from({length: count}, (v, k) => k).map(k => ({
id: `item-${k}`,
content: `item ${k}`
}));
const getItems = count =>
Array.from({ length: count }, (v, k) => k).map(k => ({
id: `item-${k}`,
content: `item ${k}`,
}));
// a little function to help us with reordering the result
const reorder = (list, startIndex, endIndex) => {
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);

@@ -97,8 +98,8 @@ const [removed] = result.splice(startIndex, 1);

// styles we need to apply on draggables
...draggableStyle
...draggableStyle,
});
const getListStyle = (isDraggingOver) => ({
const getListStyle = isDraggingOver => ({
background: isDraggingOver ? 'lightblue' : 'lightgrey',
padding: grid,
width: 250
width: 250,
});

@@ -110,10 +111,10 @@

this.state = {
items: getItems(10)
}
items: getItems(10),
};
this.onDragEnd = this.onDragEnd.bind(this);
}
onDragEnd (result) {
onDragEnd(result) {
// dropped outside the list
if(!result.destination) {
if (!result.destination) {
return;

@@ -129,3 +130,3 @@ }

this.setState({
items
items,
});

@@ -146,6 +147,3 @@ }

{this.state.items.map(item => (
<Draggable
key={item.id}
draggableId={item.id}
>
<Draggable key={item.id} draggableId={item.id}>
{(provided, snapshot) => (

@@ -180,56 +178,89 @@ <div>

### Core design principle 🎓
### Physicality
Drag and drop with react-beautiful-dnd is supposed to feel physical and natural - similar to that of moving physical objects around. Things should never 'snap' anywhere. Rather, everything should move naturally as much as possible.
The core design idea of `react-beautiful-dnd` is physicality: we want users to feel like they are moving physical objects around
#### Application 1: knowing when to move
#### Application 1: no instant movement
`Draggables` will move into their new position based on their center of gravity. Regardless of where a user grabs an item from - the movement of other things is **based on its center position**. This is similar to a set of scales ⚖️. Here are some rules that are followed to allow for a natural drag experience even with items of flexible height:
It is a fairly standard drag and drop pattern for things to disappear and reappear in response to the users drag. For a more natural drag we animate the movement of items as they need to move out of the way while dragging to more clearly show a drags effect. We also animate the drop of an item so that it animates into its new home position. At no point is an item instantly moved anywhere — regardless of whether it is dragging or not.
- A `Droppable` is dragged over when the center position of a dragging item goes over one of the boundaries of the `Droppable`
- A resting `Draggable` will move out of the way of a dragging `Draggable` when the center position of the dragging `Draggable` goes over the edge of the resting `Draggable`. Put another way: once the center position of a `Draggable` (A) goes over the edge of another `Draggable` (B), B moves out of the way.
#### Application 2: knowing when to move
#### Application 2: no drop shadows
It is quite common for drag and drop interactions to be based on the position that user started the drag from.
Drop shadows are useful in an environment where items and their destinations snap around. However, with react-beautiful-dnd it should be obvious where things will be dropping based on the movement of items. This might be changed in the future - but the experiment is to see how far we can get without any of these affordances.
In `react-beautiful-dnd` a dragging items impact is based on its centre of gravity — regardless of where a user grabs an item from. A dragging items impact follows similar rules to a set of scales ⚖️. Here are some rules that are followed to allow for a natural drag experience even with items of flexible height:
#### Application 3: no dead zones
- A list is *dragged over* when the centre position of a dragging item goes over one of the boundaries of the list
- A resting drag item will move out of the way of a dragging item when the centre position of the dragging item goes over the edge of the resting item. Put another way: once the centre position of an item (A) goes over the edge of another item (B), B moves out of the way.
react-beautiful-dnd works really hard to avoid any periods of time where the user cannot fully engage with the application (no 'dead zones'). However, there is a balance that needs to be done between correctness and power in order to make everybody's lives more sane. Here are the only situations where some things are not interactive:
#### Application 3: no drop shadows
Drop shadows are useful in an environment where items and their destinations snap around. However, with `react-beautiful-dnd` it should be obvious where things will be dropping based on the movement of items. This might be changed in the future - but the experiment is to see how far we can get without any of these affordances.
#### Application 4: maximise interactivity
`react-beautiful-dnd` works really hard to avoid as many periods of non-interactivity as possible. The user should feel like they are in control of the interface and not waiting for an animation to finish before they can continue to interact with the interface. However, there is a balance that needs to be made between correctness and power in order to make everybody's lives more sane. Here are the only situations where some things are not interactive:
1. From when a user cancels a drag to when the drop animation completes. On cancel there are lots of things moving back to where they should be. If you grab an item in a location that is not its true home then the following drag will be incorrect.
2. Starting a drag on an item that is animating its own drop. For simplicity this is the case - it is actually quite hard to grab something while it is animating home. It could be coded around - but it seems like an edge case that would add a lot of complexity.
Keep in mind that these dead zones may not always exist.
Keep in mind that these periods of inactivity may not always exist.
#### Application 5: no drag axis locking
For now, the library does not support drag axis locking (aka drag rails). This is where the user is restricted to only dragging along one axis. The current thinking is this breaks the physical metaphore we are going for and sends a message to the user that they are interacting with a piece of software rather than moving physical objects around. It is possible to ensure that a user can only drop in a single list by using props `type` and `isDropEnabled`. You can also do some visual treatment to the list `onDragStart` to show the user that this is the only place they can interact with.
### Sloppy clicks and click blocking 🐱🎁
A drag will not start until a user has dragged their mouse past a small threshold. If this threshold is not exceeded then the library will not impact the mouse click and will release the event to the browser.
When a user presses the mouse down on an element, we cannot determine if the user was clicking or dragging. Also, sometimes when a user clicks they can move the cursor slightly — a sloppy click. So we only start a drag once the user has moved beyond a certain distance with the mouse down (the drag threshold) — more than they would if they where just making a sloppy click. If the drag threshold is not exceeded then the user interaction behaves just like a regular click. If the drag threshold is exceeded then the interaction will be classified as a drag and the standard click action will not occur. 
When a user presses the mouse down on an element, we cannot determine if the user was clicking or dragging. If the sloppy click threshold was not exceeded then the event will be treated as if it where a click and the click event will bubble up unmodified. If the user has started dragging by moving the mouse beyond the sloppy click threshold then the click event will be prevented. This behavior allows you to wrap an element that has click behavior such as an anchor and have it work just like a standard anchor while also allowing it to be dragged.
This allows consumers to wrap interactive elements such as an anchor and have it be both a standard anchor as well as a draggable item in a natural way.
(🐱🎁 is a [schrodinger's cat](https://www.youtube.com/watch?v=IOYyCHGWJq4) joke)
### Focus management 📖
### Focus management
react-beautiful-dnd does not create any wrapper elements. This means that it will not impact the usage tab flow of a document. For example, if you are wrapping an *anchor* tag then the user will tab to the anchor directly and not an element surrounding the *anchor*. Whatever element you wrap will be given a `tab-index` to ensure that users can tab to the element to perform keyboard dragging.
`react-beautiful-dnd` does not create any wrapper elements. This means that it will not impact the usual tab flow of a document. For example, if you are wrapping an *anchor* tag then the user will tab to the anchor directly and not an element surrounding the *anchor*. Whatever element you wrap will be given a `tab-index` to ensure that users can tab to the element to perform keyboard dragging.
### Keyboard dragging 🎹
### Accessibility
Traditionally drag and drop interactions have been exclusively a mouse or touch interaction. This library supports drag and drop interactions using only a keyboard. This enables power users to drive more of our interfaces with a keyboard. It also opens drag and drop interactions to those who previously would be unable to use them due to an impediment.
Traditionally drag and drop interactions have been exclusively a mouse or touch interaction. This library ships with support for drag and drop interactions **using only a keyboard**. This enables power users to drive their experience entirely from the keyboard. As well as opening up these experiences to users who would have been excluded previously.
In addition to supporting keyboard, we have also audited how the keyboard shortcuts interact with standard browser keyboard interactions. When the user is not dragging they can use their keyboard as they normally would. While dragging we override and disable certain browser shortcuts (such as `tab`) to ensure a fluid experience for the user.
#### Shortcuts
Currently the keyboard handling is hard coded. This could be changed in the future to become customisable. Here is the existing keyboard mapping:
Currently the keyboard handling is hard coded. This might be changed in the future to become customisable. Here is the existing keyboard mapping:
- **tab `↹`** - standard browser tabbing will navigate through the `Droppable`'s. The library does not do anything fancy with `tab` while users are selecting. Once a drag has started, `tab` is blocked for the duration of the drag.
- **spacebar ` `** - lift a focused `Draggable`. Also, drop a dragging `Draggable` where the drag was started with a `spacebar`.
- **Up arrow `↑`** - move a `Draggable` that is dragging up on a vertical list
- **Down arrow `↓`** - move a `Draggable` that is dragging down on a vertical list
- **Escape `esc`** - cancel an existing drag - regardless of whether the user is dragging with the keyboard or mouse.
- **tab** <kbd>tab ↹</kbd> - standard browser tabbing will navigate through the `Droppable`'s. The library does not do anything fancy with `tab` while users are selecting. Once a drag has started, `tab` is blocked for the duration of the drag.
- **spacebar** <kbd>space</kbd> - lift a focused `Draggable`. Also, drop a dragging `Draggable` where the drag was started with a `spacebar`.
- **Up arrow** <kbd>↑</kbd> - move a `Draggable` that is dragging up on a vertical list
- **Down arrow** <kbd>↓</kbd> - move a `Draggable` that is dragging down on a vertical list
- **Escape** <kbd>esc</kbd> - cancel an existing drag - regardless of whether the user is dragging with the keyboard or mouse.
#### Limitations of keyboard dragging
There is a currently limitation of keyboard dragging: **the drag will cancel if the user scrolls the window**. This could be worked around but for now it is the simpliest initial approach.
There is current limitation of keyboard dragging: **the drag will cancel if the user scrolls the window**. This could be worked around but for now it is the simpliest initial approach.
## Carefully designed animations
With things moving a lot it would be easy for the user to become distracted by the animations or for them to get in the way. We have tweaked the various animations to ensure the right balance of guidance, performance and interactivity.
#### Dropping
When you drop a dragging item its movement is based on physics (thanks [`react-motion`](https://github.com/chenglou/react-motion)). This results in the drop feeling more weighted and physical.
#### Moving out of the way
Items that are moving out of the way of a dragging item do so with a CSS transition rather than physics. This is to maximise performance by allowing the GPU to handle the movement. The CSS animation curve has been designed to communicate getting out of the way.
How it is composed:
1. A warm up period to mimic a natural response time
2. A small phase to quickly move out of the way
3. A long tail so that people can read any text that is being animated in the second half of the animation
![animation curve](https://raw.githubusercontent.com/alexreardon/files/master/resources/dnd-ease-in-out-small.png?raw=true)
> animation curve used when moving out of the way
## Installation

@@ -251,3 +282,3 @@

In order to use drag and drop, you need to have the part of your react tree that you want to be able to use drag and drop in wrapped in a `DragDropContext`. It is advised to just wrap your entire application in a `DragDropContext`. Having nested `DragDropContext`'s is *not* supported. You will be able to achieve your desired conditional dragging and dropping using the props of `Droppable` and `Draggable`. You can think of `DragDropContext` as having a similar purpose to the [react-redux Provider component](https://github.com/reactjs/react-redux/blob/master/docs/api.md#provider-store)
In order to use drag and drop, you need to have the part of your `React` tree that you want to be able to use drag and drop in wrapped in a `DragDropContext`. It is advised to just wrap your entire application in a `DragDropContext`. Having nested `DragDropContext`'s is *not* supported. You will be able to achieve your desired conditional dragging and dropping using the props of `Droppable` and `Draggable`. You can think of `DragDropContext` as having a similar purpose to the [react-redux Provider component](https://github.com/reactjs/react-redux/blob/master/docs/api.md#provider-store)

@@ -273,4 +304,8 @@ ### Prop type information

class App extends React.Component {
onDragStart = () => {...}
onDragEnd = () => {...}
onDragStart = () => {
/*...*/
};
onDragEnd = () => {
/*...*/
};

@@ -285,3 +320,3 @@ render() {

</DragDropContext>
)
);
}

@@ -408,10 +443,7 @@ }

<Droppable
droppableId="droppable-1"
type="PERSON"
>
<Droppable droppableId="droppable-1" type="PERSON">
{(provided, snapshot) => (
<div
ref={provided.innerRef}
style={{backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey'}}
style={{ backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey' }}
>

@@ -421,3 +453,3 @@ I am a droppable!

)}
</Droppable>
</Droppable>;
```

@@ -433,10 +465,10 @@

The React children of a `Droppable` must be a function that returns a `ReactElement`.
The `React` children of a `Droppable` must be a function that returns a `ReactElement`.
```js
<Droppable droppableId="droppable-1">
{(provided, snapshot) => (
// ...
)}
</Droppable>
{(provided, snapshot) => ({
/*...*/
})}
</Droppable>;
```

@@ -458,8 +490,4 @@

<Droppable droppableId="droppable-1">
{(provided, snapshot) => (
<div ref={provided.innerRef}>
Good to go
</div>
)}
</Droppable>
{(provided, snapshot) => <div ref={provided.innerRef}>Good to go</div>}
</Droppable>;
```

@@ -472,6 +500,6 @@

isDraggingOver: boolean,
|}
|};
```
The `children` function is also provided with a small about of state relating to the current drag state. This can be optionally used to enhance your component. A common use case is changing the appearance of a `Droppable` while it is being dragged over.
The `children` function is also provided with a small amount of state relating to the current drag state. This can be optionally used to enhance your component. A common use case is changing the appearance of a `Droppable` while it is being dragged over.

@@ -483,3 +511,3 @@ ```js

ref={provided.innerRef}
style={{backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey'}}
style={{ backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey' }}
>

@@ -489,3 +517,3 @@ I am a droppable!

)}
</Droppable>
</Droppable>;
```

@@ -528,12 +556,9 @@

<Draggable
draggableId="draggable-1"
type="PERSON"
>
<Draggable draggableId="draggable-1" type="PERSON">
{(provided, snapshot) => (
<div>
<div
ref={draggableProvided.innerRef}
style={draggableProvided.draggableStyle}
{...draggableProvided.dragHandleProps}
ref={provided.innerRef}
style={provided.draggableStyle}
{...provided.dragHandleProps}
>

@@ -545,3 +570,3 @@ <h4>My draggable</h4>

)}
</Draggable>
</Draggable>;
```

@@ -555,7 +580,7 @@

- `type`: An *optional* type (`TypeId(string)`) of the `Draggable`. This is used to control what `Droppable`s the `Draggable` is permitted to drop on. `Draggable`s can only drop on `Droppable`s that share the same `type`. If no `type` is provided, it will be set to `'DEFAULT'`. Currently the `type` of a `Draggable` **must be** the same as its container `Droppable`. This restriction might be loosened in the future if there is a valid use case.
- `isDragDisabled`: An *optional* flag to control whether or not dropping is currently allowed on the `Droppable`. You can use this to implement your own conditional dropping logic. It will default to `false`.
- `isDragDisabled`: An *optional* flag to control whether or not the `Draggable` is permitted to drag. You can use this to implement your own conditional drag logic. It will default to `false`.
### Children function
The React children of a `Draggable` must be a function that returns a `ReactElement`.
The `React` children of a `Draggable` must be a function that returns a `ReactElement`.

@@ -576,3 +601,3 @@ ```js

)}
</Draggable>
</Draggable>;
```

@@ -599,8 +624,4 @@

<Draggable draggableId="draggable-1">
{(provided, snapshot) => (
<div ref={provided.innerRef}>
Drag me!
</div>
)}
</Draggable>
{(provided, snapshot) => <div ref={provided.innerRef}>Drag me!</div>}
</Draggable>;
```

@@ -614,7 +635,7 @@

- `provided.draggableStyle (?DraggableStyle)`: This is an `Object` or `null` that contains an a number of styles that needs to be applied to the `Draggable`. This needs to be applied to the same node that you apply `provided.innerRef` to. The controls the movement of the draggable when it is dragging and not dragging. You are welcome to add your own styles to this object - but please do not remove or replace any of the properties.
- `provided.draggableStyle (?DraggableStyle)`: This is an `Object` or `null` that contains an a number of styles that needs to be applied to the `Draggable`. This needs to be applied to the same node that you apply `provided.innerRef` to. This controls the movement of the draggable when it is dragging and not dragging. You are welcome to add your own styles to this object – but please do not remove or replace any of the properties.
**Ownership**
It is a contract of this library that it own the positioning logic of the dragging element. This includes properties such as `top`, `right`, `bottom`, `left` and `transform`. The library may change how it positions things and what properties it uses without performing a major version bump. It is also recommended that you do not apply your own `transition` property to the dragging element.
It is a contract of this library that it owns the positioning logic of the dragging element. This includes properties such as `top`, `right`, `bottom`, `left` and `transform`. The library may change how it positions things and what properties it uses without performing a major version bump. It is also recommended that you do not apply your own `transition` property to the dragging element.

@@ -625,6 +646,3 @@ ```js

<div>
<div
ref={provided.innerRef}
style={provided.draggableStyle}
>
<div ref={provided.innerRef} style={provided.draggableStyle}>
Drag me!

@@ -634,3 +652,3 @@ </div>

)}
</Draggable>
</Draggable>;
```

@@ -645,11 +663,8 @@

...provided.draggableStyle,
backgroundColor: snapshot.isDragging : 'blue' : 'white',
backgroundColor: snapshot.isDragging ? 'blue' : 'white',
fontSize: 18,
}
};
return (
<div>
<div
ref={provided.innerRef}
style={style}
>
<div ref={provided.innerRef} style={style}>
Drag me!

@@ -660,3 +675,3 @@ </div>

}}
</Draggable>
</Draggable>;
```

@@ -670,12 +685,12 @@

type DraggingStyle = {|
pointerEvents: 'none',
position: 'fixed',
boxSizing: 'border-box',
// allow scrolling of the element behind the dragging element
pointerEvents: 'none',
zIndex: ZIndex,
width: number,
height: number,
boxSizing: 'border-box',
top: number,
left: number,
margin: 0,
transform: ?string,
zIndex: ZIndex,
|}

@@ -687,6 +702,6 @@

pointerEvents: 'none' | 'auto',
|}
|};
```
- `provided.placeholder (?ReactElement)` The `Draggable` element has `position:fixed` applied to it while it is dragging. The role of the `placeholder` is to sit in the place that the `Draggable` was during a drag. It is needed to stop the `Droppable` list from collapsing when you drag. It is advised to render it as a sibling to the `Draggable` node. When the library moves to React 16 the `placeholder` will be removed from api.
- `provided.placeholder (?ReactElement)` The `Draggable` element has `position: fixed` applied to it while it is dragging. The role of the `placeholder` is to sit in the place that the `Draggable` was during a drag. It is needed to stop the `Droppable` list from collapsing when you drag. It is advised to render it as a sibling to the `Draggable` node. When the library moves to `React` 16 the `placeholder` will be removed from api.

@@ -697,6 +712,3 @@ ```js

<div>
<div
ref={provided.innerRef}
style={provided.draggableStyle}
>
<div ref={provided.innerRef} style={provided.draggableStyle}>
Drag me!

@@ -708,6 +720,6 @@ </div>

)}
</Draggable>
</Draggable>;
```
- `provided.dragHandleProps (?DragHandleProps)` every `Draggable` has a *drag handle*. This is what is used to drag the whole `Draggable`. Often this will be the same as the node as the `Draggable`, but sometimes it can be a child of the `Draggable`. `DragHandleProps` need to be applied to the node that you want to be the drag handle. This is a number of props that need to be applied to the `Draggable` node. The simpliest approach is to spread the props onto the draggable node (`{...provided.dragHandleProps}`). However, you are also welcome to [monkey patch](https://davidwalsh.name/monkey-patching) these props if you also need to respond to them. DragHandleProps will be `null` when `isDragDisabled` is set to `true`.
- `provided.dragHandleProps (?DragHandleProps)` every `Draggable` has a *drag handle*. This is what is used to drag the whole `Draggable`. Often this will be the same node as the `Draggable`, but sometimes it can be a child of the `Draggable`. `DragHandleProps` need to be applied to the node that you want to be the drag handle. This is a number of props that need to be applied to the `Draggable` node. The simpliest approach is to spread the props onto the draggable node (`{...provided.dragHandleProps}`). However, you are also welcome to [monkey patch](https://davidwalsh.name/monkey-patching) these props if you also need to respond to them. DragHandleProps will be `null` when `isDragDisabled` is set to `true`.

@@ -725,4 +737,4 @@ **Type information**

onDragStart: () => void,
onDrop: () => void
|}
onDrop: () => void,
|};
```

@@ -746,3 +758,3 @@

)}
</Draggable>
</Draggable>;
```

@@ -756,10 +768,5 @@

<div>
<div
ref={provided.innerRef}
style={provided.draggableStyle}
>
<div ref={provided.innerRef} style={provided.draggableStyle}>
<h2>Hello there</h2>
<div {...provided.dragHandleProps}>
Drag handle
</div>
<div {...provided.dragHandleProps}>Drag handle</div>
</div>

@@ -769,3 +776,3 @@ {provided.placeholder}

)}
</Draggable>
</Draggable>;
```

@@ -778,3 +785,3 @@

```js
const myOnClick = (event) => console.log('clicked on', event.target);
const myOnClick = event => console.log('clicked on', event.target);

@@ -785,3 +792,3 @@ <Draggable draggableId="draggable-1">

// dragHandleProps might be null
if(!provided.dragHandleProps) {
if (!provided.dragHandleProps) {
return myOnClick;

@@ -792,3 +799,3 @@ }

// event as well as the provided one.
return (event) => {
return event => {
provided.dragHandleProps.onClick(event);

@@ -798,3 +805,3 @@ // You may want to check if event.defaultPrevented

myOnClick(event);
}
};
})();

@@ -816,3 +823,3 @@

}}
</Draggable>
</Draggable>;
```

@@ -825,6 +832,6 @@

isDragging: boolean,
|}
|};
```
The `children` function is also provided with a small about of state relating to the current drag state. This can be optionally used to enhance your component. A common use case is changing the appearance of a `Draggable` while it is being dragged. Note: if you want to change the cursor to something like `grab` you will need to add the style to the body. (See `DragDropContext` > **style** above)
The `children` function is also provided with a small amount of state relating to the current drag state. This can be optionally used to enhance your component. A common use case is changing the appearance of a `Draggable` while it is being dragged. Note: if you want to change the cursor to something like `grab` you will need to add the style to the body. (See `DragDropContext` > **style** above)

@@ -852,3 +859,3 @@ ```js

}}
</Draggable>
</Draggable>;
```

@@ -870,10 +877,11 @@

This codebase is designed to be extremely performant - it is part of its DNA. It builds on prior investigations into React performance that you can read about [here](https://medium.com/@alexandereardon/performance-optimisations-for-react-applications-b453c597b191) and [here](https://medium.com/@alexandereardon/performance-optimisations-for-react-applications-round-2-2042e5c9af97). It is designed to perform the minimum number of renders required for each task.
This codebase is designed to be extremely performant - it is part of its DNA. It builds on prior investigations into `React` performance that you can read about [here](https://medium.com/@alexandereardon/performance-optimisations-for-react-applications-b453c597b191) and [here](https://medium.com/@alexandereardon/performance-optimisations-for-react-applications-round-2-2042e5c9af97). It is designed to perform the minimum number of renders required for each task.
**Highlights**
- using connected-components with memoization to ensure the only components that render are the ones that need to - thanks [react-redux](https://github.com/reactjs/react-redux), [reselect](https://github.com/reactjs/reselect) and [memoize-one](https://github.com/alexreardon/memoize-one)
- all movements are throttled with a [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) - thanks [raf-schd](https://github.com/alexreardon/raf-schd)
- memoization is used all over the place - thanks [memoize-one](https://github.com/alexreardon/memoize-one)
- conditionally disabling [`pointer-events`](https://developer.mozilla.org/en/docs/Web/CSS/pointer-events) on `Draggable`s while dragging to prevent the browser needing to do redundant work
- using connected-components with memoization to ensure the only components that render are the ones that need to - thanks [`react-redux`](https://github.com/reactjs/react-redux), [`reselect`](https://github.com/reactjs/reselect) and [`memoize-one`](https://github.com/alexreardon/memoize-one)
- all movements are throttled with a [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) - thanks [`raf-schd`](https://github.com/alexreardon/raf-schd)
- memoization is used all over the place - thanks [`memoize-one`](https://github.com/alexreardon/memoize-one)
- conditionally disabling [`pointer-events`](https://developer.mozilla.org/en/docs/Web/CSS/pointer-events) on `Draggable`s while dragging to prevent the browser needing to do redundant work - you can read more about the technique [here](https://www.thecssninja.com/css/pointer-events-60fps)
- Non primary animations are done on the GPU

@@ -900,2 +908,2 @@ | Minimal browser paints | Minimal React updates |

Alex Reardon - [@alexandereardon](https://twitter.com/alexandereardon) - areardon@atlassian.com
Alex Reardon - [@alexandereardon](https://twitter.com/alexandereardon) - areardon@atlassian.com

@@ -31,12 +31,36 @@ // @flow

export type DraggingStyle = {|
// Allow scrolling of the element behind the dragging element
pointerEvents: 'none',
// `position: fixed` is used to ensure that the element is always positioned
// in the correct position and ignores the surrounding position:relative parents
position: 'fixed',
boxSizing: 'border-box',
// allow scrolling of the element behind the dragging element
pointerEvents: 'none',
zIndex: ZIndex,
// When we do `position: fixed` the element looses its normal dimensions,
// especially if using flexbox. We set the width and height manually to
// ensure the element has the same dimensions as before it started dragging
width: number,
height: number,
// When we set the width and height they include the padding on the element.
// We use box-sizing: border-box to ensure that the width and height are inclusive of the padding
boxSizing: 'border-box',
// We initially position the element in the same visual spot as when it started.
// To do this we give the element the top / left position with the margins considered
top: number,
left: number,
// We clear any top or left margins on the element to ensure it does not push
// the element positioned with the top/left position.
// We also clear the margin right / bottom. This has no positioning impact,
// but it is cleanest to just remove all the margins rather than only the top and left.
margin: 0,
// Move the element in response to a user dragging
transform: ?string,
// When dragging or dropping we control the z-index to ensure that
// the layering is correct
zIndex: ZIndex,
|}

@@ -43,0 +67,0 @@

@@ -224,2 +224,3 @@ // @flow

movementStyle: MovementStyle): DraggingStyle => {
// For an explanation of properties see `draggable-types`.
const style: DraggingStyle = {

@@ -234,2 +235,3 @@ position: 'fixed',

left,
margin: 0,
transform: movementStyle.transform ? `${movementStyle.transform}` : null,

@@ -278,3 +280,5 @@ };

// Margins are accounted for. See `draggable-types` for explanation
const { width, height, top, left } = dimension.client.withoutMargin;
return this.getDraggingStyle(width, height, top, left, isDropAnimating, movementStyle);

@@ -281,0 +285,0 @@ })();

@@ -890,2 +890,3 @@ // @flow

left: dimension.page.withMargin.left,
margin: 0,
transform: null,

@@ -923,2 +924,3 @@ pointerEvents: 'none',

left: dimension.page.withMargin.left,
margin: 0,
transform: `translate(${offset.x}px, ${offset.y}px)`,

@@ -960,2 +962,3 @@ pointerEvents: 'none',

left: dimension.page.withMargin.left,
margin: 0,
};

@@ -1089,2 +1092,3 @@

left: dimension.page.withMargin.left,
margin: 0,
transform: `translate(${offset.x}px, ${offset.y}px)`,

@@ -1091,0 +1095,0 @@ pointerEvents: 'none',

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc