react-beautiful-dnd
Advanced tools
Comparing version 2.6.4 to 3.0.0
@@ -50,2 +50,3 @@ 'use strict'; | ||
left: left - spacing.left, | ||
bottom: bottom + spacing.bottom, | ||
@@ -94,2 +95,9 @@ right: right + spacing.right | ||
droppableId: droppableId, | ||
placeholder: { | ||
margin: margin, | ||
withoutMargin: { | ||
width: clientRect.width, | ||
height: clientRect.height | ||
} | ||
}, | ||
@@ -96,0 +104,0 @@ client: { |
@@ -64,3 +64,3 @@ 'use strict'; | ||
var movement = { | ||
amount: (0, _position.patch)(axis.line, draggable.page.withMargin[axis.size]), | ||
amount: (0, _position.patch)(axis.line, draggable.client.withMargin[axis.size]), | ||
draggables: ordered, | ||
@@ -67,0 +67,0 @@ isBeyondStartPosition: isBeyondStartPosition |
@@ -60,3 +60,3 @@ 'use strict'; | ||
return function (draggable) { | ||
var fragment = draggable.page.withMargin; | ||
var fragment = draggable.page.withoutMargin; | ||
@@ -63,0 +63,0 @@ return isWithinHorizontal(fragment.left) && isWithinHorizontal(fragment.right) && isWithinVertical(fragment.top) && isWithinVertical(fragment.bottom); |
@@ -27,3 +27,3 @@ 'use strict'; | ||
var amount = (0, _position.patch)(destination.axis.line, draggable.page.withMargin[destination.axis.size]); | ||
var amount = (0, _position.patch)(destination.axis.line, draggable.client.withMargin[destination.axis.size]); | ||
@@ -30,0 +30,0 @@ if (destination.id === draggable.droppableId) { |
@@ -72,3 +72,3 @@ 'use strict'; | ||
}, _this.onMouseDown = function (event) { | ||
if (_this.keyboardSensor.isCapturing()) { | ||
if (_this.keyboardSensor.isCapturing() || _this.mouseSensor.isCapturing()) { | ||
return; | ||
@@ -75,0 +75,0 @@ } |
@@ -35,2 +35,6 @@ 'use strict'; | ||
var _shouldAllowDraggingFromTarget = require('../util/should-allow-dragging-from-target'); | ||
var _shouldAllowDraggingFromTarget2 = _interopRequireDefault(_shouldAllowDraggingFromTarget); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
@@ -90,2 +94,7 @@ | ||
} | ||
if (!(0, _shouldAllowDraggingFromTarget2.default)(event, props)) { | ||
return; | ||
} | ||
(0, _stopEvent2.default)(event); | ||
@@ -92,0 +101,0 @@ |
@@ -39,2 +39,6 @@ 'use strict'; | ||
var _shouldAllowDraggingFromTarget = require('../util/should-allow-dragging-from-target'); | ||
var _shouldAllowDraggingFromTarget2 = _interopRequireDefault(_shouldAllowDraggingFromTarget); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
@@ -221,2 +225,6 @@ | ||
if (!(0, _shouldAllowDraggingFromTarget2.default)(event, props)) { | ||
return; | ||
} | ||
var button = event.button, | ||
@@ -223,0 +231,0 @@ clientX = event.clientX, |
@@ -24,6 +24,2 @@ 'use strict'; | ||
var _isSloppyClickThresholdExceeded = require('../util/is-sloppy-click-threshold-exceeded'); | ||
var _isSloppyClickThresholdExceeded2 = _interopRequireDefault(_isSloppyClickThresholdExceeded); | ||
var _getWindowFromRef = require('../../get-window-from-ref'); | ||
@@ -33,5 +29,9 @@ | ||
var _shouldAllowDraggingFromTarget = require('../util/should-allow-dragging-from-target'); | ||
var _shouldAllowDraggingFromTarget2 = _interopRequireDefault(_shouldAllowDraggingFromTarget); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var timeForLongPress = exports.timeForLongPress = 200; | ||
var timeForLongPress = exports.timeForLongPress = 150; | ||
var forcePressThreshold = exports.forcePressThreshold = 0.15; | ||
@@ -64,9 +64,5 @@ | ||
var startDragging = function startDragging() { | ||
if (state.longPressTimerId) { | ||
clearTimeout(state.longPressTimerId); | ||
} | ||
var pending = state.pending; | ||
if (!state.pending) { | ||
if (!pending) { | ||
console.error('cannot start a touch drag without a pending position'); | ||
@@ -146,2 +142,15 @@ kill(); | ||
touchmove: function touchmove(event) { | ||
if (state.pending) { | ||
stopPendingDrag(); | ||
return; | ||
} | ||
if (!state.hasMoved) { | ||
setState({ | ||
hasMoved: true | ||
}); | ||
} | ||
(0, _stopEvent2.default)(event); | ||
var _event$touches$ = event.touches[0], | ||
@@ -157,19 +166,2 @@ clientX = _event$touches$.clientX, | ||
(0, _stopEvent2.default)(event); | ||
if (!state.hasMoved) { | ||
setState({ | ||
hasMoved: true | ||
}); | ||
} | ||
if (state.pending) { | ||
if (!(0, _isSloppyClickThresholdExceeded2.default)(state.pending, point)) { | ||
return; | ||
} | ||
startDragging(); | ||
return; | ||
} | ||
schedule.move(point); | ||
@@ -187,9 +179,3 @@ }, | ||
}, | ||
touchcancel: function touchcancel() { | ||
if (state.pending) { | ||
stopPendingDrag(); | ||
return; | ||
} | ||
cancel(); | ||
}, | ||
touchcancel: cancel, | ||
touchstart: function touchstart() { | ||
@@ -261,2 +247,6 @@ if (isDragging()) { | ||
if (!(0, _shouldAllowDraggingFromTarget2.default)(event, props)) { | ||
return; | ||
} | ||
event.stopPropagation(); | ||
@@ -267,6 +257,5 @@ | ||
var onTouchMove = function onTouchMove(event) { | ||
if (isCapturing()) { | ||
event.preventDefault(); | ||
var onTouchMove = function onTouchMove() { | ||
if (state.pending) { | ||
stopPendingDrag(); | ||
} | ||
@@ -273,0 +262,0 @@ }; |
@@ -198,3 +198,9 @@ 'use strict'; | ||
_this.getDraggingStyle = (0, _memoizeOne2.default)(function (width, height, top, left, isDropAnimating, movementStyle) { | ||
_this.getDraggingStyle = (0, _memoizeOne2.default)(function (dimension, isDropAnimating, movementStyle) { | ||
var _dimension$client$wit = dimension.client.withoutMargin, | ||
width = _dimension$client$wit.width, | ||
height = _dimension$client$wit.height, | ||
top = _dimension$client$wit.top, | ||
left = _dimension$client$wit.left; | ||
var style = { | ||
@@ -214,3 +220,3 @@ position: 'fixed', | ||
WebkitTapHighlightColor: 'rgba(0,0,0,0)', | ||
touchAction: 'none' | ||
touchAction: 'manipulation' | ||
}; | ||
@@ -227,3 +233,3 @@ return style; | ||
WebkitTapHighlightColor: 'rgba(0,0,0,0)', | ||
touchAction: 'none' | ||
touchAction: 'manipulation' | ||
}; | ||
@@ -239,12 +245,6 @@ return style; | ||
} | ||
(0, _invariant2.default)(dimension, 'draggable dimension required for dragging'); | ||
var _dimension$client$wit = dimension.client.withoutMargin, | ||
width = _dimension$client$wit.width, | ||
height = _dimension$client$wit.height, | ||
top = _dimension$client$wit.top, | ||
left = _dimension$client$wit.left; | ||
return _this.getDraggingStyle(width, height, top, left, isDropAnimating, movementStyle); | ||
return _this.getDraggingStyle(dimension, isDropAnimating, movementStyle); | ||
}(); | ||
@@ -310,6 +310,3 @@ | ||
return _react2.default.createElement(_placeholder2.default, { | ||
height: dimension.page.withMargin.height, | ||
width: dimension.page.withMargin.width | ||
}); | ||
return _react2.default.createElement(_placeholder2.default, { placeholder: dimension.placeholder }); | ||
} | ||
@@ -332,3 +329,4 @@ }, { | ||
children = _props.children, | ||
direction = _props.direction; | ||
direction = _props.direction, | ||
disableInteractiveElementBlocking = _props.disableInteractiveElementBlocking; | ||
@@ -362,3 +360,5 @@ | ||
callbacks: _this2.callbacks, | ||
getDraggableRef: _this2.getDraggableRef | ||
getDraggableRef: _this2.getDraggableRef, | ||
canDragInteractiveElements: disableInteractiveElementBlocking | ||
}, | ||
@@ -379,5 +379,7 @@ function (dragHandleProps) { | ||
isDragDisabled: false, | ||
type: 'DEFAULT' | ||
type: 'DEFAULT', | ||
disableInteractiveElementBlocking: false | ||
}; | ||
Draggable.contextTypes = (0, _defineProperty3.default)({}, _contextKeys.droppableIdKey, _propTypes2.default.string.isRequired); | ||
exports.default = Draggable; |
@@ -41,8 +41,2 @@ 'use strict'; | ||
var memoizedPlaceholder = (0, _memoizeOne2.default)(function (width, height) { | ||
return { | ||
width: width, height: height | ||
}; | ||
}); | ||
var getPlaceholder = (0, _memoizeOne2.default)(function (id, source, destination, draggable) { | ||
@@ -65,5 +59,3 @@ if (!destination) { | ||
var placeholder = memoizedPlaceholder(draggable.client.withoutMargin.width, draggable.client.withoutMargin.height); | ||
return placeholder; | ||
return draggable.placeholder; | ||
}); | ||
@@ -70,0 +62,0 @@ |
@@ -95,6 +95,3 @@ 'use strict'; | ||
return _react2.default.createElement(_placeholder2.default, { | ||
height: this.props.placeholder.height, | ||
width: this.props.placeholder.width | ||
}); | ||
return _react2.default.createElement(_placeholder2.default, { placeholder: this.props.placeholder }); | ||
} | ||
@@ -101,0 +98,0 @@ }, { |
@@ -44,6 +44,23 @@ 'use strict'; | ||
value: function render() { | ||
var placeholder = this.props.placeholder; | ||
var _placeholder$margin = placeholder.margin, | ||
top = _placeholder$margin.top, | ||
left = _placeholder$margin.left, | ||
bottom = _placeholder$margin.bottom, | ||
right = _placeholder$margin.right; | ||
var _placeholder$withoutM = placeholder.withoutMargin, | ||
width = _placeholder$withoutM.width, | ||
height = _placeholder$withoutM.height; | ||
var style = { | ||
width: this.props.width, | ||
height: this.props.height, | ||
pointerEvents: 'none' | ||
width: width, | ||
height: height, | ||
marginTop: top, | ||
marginLeft: left, | ||
marginBottom: bottom, | ||
marginRight: right, | ||
pointerEvents: 'none', | ||
boxSizing: 'border-box' | ||
}; | ||
@@ -50,0 +67,0 @@ return _react2.default.createElement('div', { style: style }); |
{ | ||
"name": "react-beautiful-dnd", | ||
"version": "2.6.4", | ||
"version": "3.0.0", | ||
"description": "Beautiful, accessible drag and drop for lists with React.js", | ||
@@ -19,3 +19,4 @@ "author": "Alex Reardon <areardon@atlassian.com>", | ||
"files": [ | ||
"/lib" | ||
"/lib", | ||
"/dist" | ||
], | ||
@@ -27,4 +28,5 @@ "scripts": { | ||
"typecheck": "flow check", | ||
"build": "yarn run build:clean && yarn run build:lib && yarn run build:flow", | ||
"build:clean": "rimraf lib", | ||
"build": "yarn run build:clean && yarn run build:lib && yarn run build:flow && yarn run build:dist", | ||
"build:clean": "rimraf lib && rimraf dist", | ||
"build:dist": "rollup -c && rollup -c --min", | ||
"build:lib": "babel src -d lib", | ||
@@ -64,2 +66,3 @@ "build:flow": "flow-copy-source --verbose src lib", | ||
"eslint-config-airbnb": "^16.1.0", | ||
"eslint-plugin-flowtype": "^2.39.1", | ||
"eslint-plugin-import": "^2.8.0", | ||
@@ -77,2 +80,8 @@ "eslint-plugin-jest": "^21.3.2", | ||
"rimraf": "^2.6.2", | ||
"rollup": "^0.51.8", | ||
"rollup-plugin-babel": "^3.0.2", | ||
"rollup-plugin-commonjs": "^8.2.6", | ||
"rollup-plugin-node-resolve": "^3.0.0", | ||
"rollup-plugin-replace": "^2.0.0", | ||
"rollup-plugin-uglify": "^2.0.1", | ||
"styled-components": "^2.2.3" | ||
@@ -79,0 +88,0 @@ }, |
285
README.md
@@ -45,2 +45,3 @@ # react-beautiful-dnd | ||
- Server side rendering compatible | ||
- Plays well with [nested interactive elements](https://github.com/atlassian/react-beautiful-dnd#interactive-child-elements-within-a-draggable) by default | ||
@@ -315,9 +316,2 @@ ### Lots more coming soon | ||
### Starting a drag | ||
A user can start a drag by: | ||
1. Holding their finger 👇 on an element for a small period of time 🕑 (long press); OR | ||
2. Moving an element beyond a small distance threshold | ||
### Understanding intention: tap, force press, scroll and drag | ||
@@ -327,24 +321,19 @@ | ||
#### Tap support | ||
### Starting a drag: long press | ||
If the user lifts their finger before the timer is finished then we release the event to the browser for it to determine whether to perform the standard tap / click action. This allows you to have a `Draggable` that is both clickable such as a anchor as well as draggable. | ||
A user can start a drag by holding their finger 👇 on an element for a small period of time 🕑 (long press) | ||
#### Opting out of native scrolling | ||
### Tap support | ||
When the user first puts their finger down we are not sure if they were attempting to scroll. However, when they first put their finger down we have a one time opportunity to opt out of native scrolling. You cannot opt back into native scrolling or out of native scrolling from this point. The primary reason we need to opt out of native scrolling is that the scroll of the page would cancel out the impact of a users reorder action. Scrolling while dragging will be supported when we add the [auto scrolling feature](https://github.com/atlassian/react-beautiful-dnd/issues/27) | ||
If the user lifts their finger before the timer is finished then we release the event to the browser for it to determine whether to perform the standard tap / click action. This allows you to have a `Draggable` that is both clickable such as a anchor as well as draggable. If the item was dragged then we block the tap action from occurring. | ||
| Native scrolling | Reordering | | ||
|---------------------------------|---------------------------------| | ||
| Moving up moves the **page** up | Moving up moves the **item** up | | ||
|![native scrolling](https://github.com/alexreardon/files/blob/master/resources/native-scroll.gif?raw=true)|![reordering](https://github.com/alexreardon/files/blob/master/resources/no-scroll-reorder.gif?raw=true)| | ||
### Native scrolling support | ||
When a user moves an item up we need the item to move up in the list and not for the viewport or container to scroll up also. If we did not disable native scrolling the user would not be able to reorder items. | ||
If we detect a `touchmove` before the long press timer expires we cancel the pending drag and allow the user to scroll normally. This means that the user needs to be fairly intentional and precise with their grabbing. Once the first `touchmove` occurs we have to either opt in our out of native scrolling. | ||
The library needs to opt out of native scrolling for reordering, however we recommend that you allow some ability for the user to scroll without reordering. This can be done through a variety of means including: | ||
- If the long press timer **has not** expired: *allow native scrolling and prevent dragging* | ||
- If the long press timer **has** expired: *a drag has started and we prevent native scrolling* | ||
- Not making `Draggable`s the full width of the viewport so they can scroll on the side of it | ||
- Use a *drag handle* so that only part of the `Draggable` is reserved for dragging | ||
### Force press support | ||
#### Force press support | ||
> Safari only | ||
@@ -358,8 +347,2 @@ | ||
Avoid the *pull to refresh action* and *anchor focus* on Android Chrome | ||
```css | ||
touch-action: none; | ||
``` | ||
A long press on anchors usually pops a content menu that has options for the link such as 'Open in new tab'. Because long press is used to start a drag we need to opt out of this behavior | ||
@@ -377,5 +360,11 @@ | ||
Avoid the *pull to refresh action* and *delayed anchor focus* on Android Chrome | ||
```css | ||
touch-action: manipulation; | ||
``` | ||
### Vibration | ||
> This is merely a suggestion - it is up to you to add this if you want this behavior. | ||
> This is merely an idea - it is up to you to add this if you want this behavior. | ||
@@ -398,2 +387,4 @@ If you like you could also trigger a [vibration event](https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API) when the user picks up a `Draggable`. This can provide tactile feedback that the user is doing something. It currently is only supported in Chrome on Android. | ||
### Package manager | ||
```bash | ||
@@ -407,2 +398,37 @@ # yarn | ||
### Distribution bundle | ||
A [universal module definition](https://github.com/umdjs/umd) bundle is published on `npm` under the `/dist` folder for consumption . We publish the following files: | ||
- `dist/react-beautiful-dnd.js` | ||
- `dist/react-beautiful-dnd.min.js` (minified bundle) | ||
These bundles list `react` as an external which needs to be provided. This is done to reduce the size of the bundle and prevent consumers from loading `react` multiple times. You can provide `react` through your module system or simply by having `react` on the `window`. | ||
You can use the UMD to run `react-beautiful-dnd` directly in the browser. | ||
```html | ||
<!-- peer dependency --> | ||
<script src="https://unpkg.com/react@15.6.0/dist/react.js"></script> | ||
<!-- lib (change x.x.x for the version you would like) --> | ||
<script src="https://unpkg.com/react-dom@x.x.x/dist/react-beautiful-dnd.js"></script> | ||
<!-- needed to mount your react app --> | ||
<script src="https://unpkg.com/react-dom@15.6.0/dist/react-dom.js"></script> | ||
<script> | ||
const React = window.React; | ||
const ReactDOM = window.ReactDOM; | ||
const { DragDropContext, Draggable, Droppable } = window.ReactBeautifulDnd; | ||
class App extends React.Component { | ||
//... | ||
} | ||
// You can use JSX if your environment supports it | ||
ReactDOM.render(React.createElement(App), document.getElementById('app')); | ||
</script> | ||
``` | ||
There is also an [example codepen](https://codepen.io/alexreardon/project/editor/ZyNMPo) you can use to play with this technique. | ||
## API | ||
@@ -424,3 +450,4 @@ | ||
type Props = Hooks & {| | ||
type Props = {| | ||
...Hooks, | ||
children?: ReactElement, | ||
@@ -736,2 +763,3 @@ |} | ||
- `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`. | ||
- `disableInteractiveElementBlocking`: An *optional* flag to opt out of blocking a drag from interactive elements. For more information refer to the section *Interactive child elements within a `Draggable`* | ||
@@ -834,2 +862,53 @@ ### Children function | ||
### Avoid margin collapsing between `Draggable`s | ||
[margin collapsing](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing) is one of those really hard parts of CSS. For our purposes, if you have one `Draggable` with a `margin-bottom: 10px` and the next `Draggable` has a `margin-top: 12px` these margins will *collapse* and the resulting margin will be the greater of the two: `12px`. When we do our calculations we are currently not accounting for margin collapsing. If you do want to have a margin on the siblings, wrap them both in a `div` and apply the margin to the inner `div` so they are not direct siblings. | ||
### `Draggable`s should be visible siblings | ||
It is an assumption that `Draggable`s and *visible siblings* of one another. There can be other elements in between, but these elements should not take up any additional space. You probably will not do this anyway, but just calling it out to be super clear | ||
```js | ||
// Direct siblings ✅ | ||
<Draggable draggableId="draggable-1" > | ||
{() => {}} | ||
</Draggable> | ||
<Draggable draggableId="draggable-2"> | ||
{() => {}} | ||
</Draggable> | ||
// Not direct siblings, but are visual siblings ✅ | ||
<div> | ||
<Draggable draggableId="draggable-1"> | ||
{() => {}} | ||
</Draggable> | ||
</div> | ||
<div> | ||
<Draggable draggableId="draggable-2"> | ||
{() => {}} | ||
</Draggable> | ||
</div> | ||
// Spacer elements ❌ | ||
<Draggable draggableId="draggable-1"> | ||
{() => {}} | ||
</Draggable> | ||
<p>I will break things!</p> | ||
<Draggable draggableId="draggable-2"> | ||
{() => {}} | ||
</Draggable> | ||
// Spacing on non sibling wrappers ❌ | ||
<div style={{padding: 10}}> | ||
<Draggable draggableId="draggable-1"> | ||
{() => {}} | ||
</Draggable> | ||
</div> | ||
<div style={{padding: 10}}> | ||
<Draggable draggableId="draggable-2"> | ||
{() => {}} | ||
</Draggable> | ||
</div> | ||
``` | ||
### Type information | ||
@@ -852,3 +931,3 @@ | ||
// Avoid pull to refresh action and anchor focus on Android Chrome | ||
touchAction: 'none', | ||
touchAction: 'manipulation', | ||
|} | ||
@@ -1026,130 +1105,16 @@ | ||
It is possible for your `Draggable` to be an interactive element such as a `<button>` or an `<a>`. However, there may be a situation where you want your `Draggable` element be the parent of an interactive element such as a `<button>` or an `<input>`. By default the child interactive element **will not be interactive**. Interacting with these nested interactive elements will be used as part of the calculation to start a drag. This is because we call `event.preventDefault()` on the `mousedown` event for the `Draggable`. Calling `preventDefault` will prevent the nested interactive element from performing its standard actions and interactions. What you will need to do is *opt out* of our standard calling of `event.preventDefault()`. By doing this the nested interactive element will not be able to be used to start a drag - but will allow the user to interact with it directly. Keep in mind - that by doing this the user will not be able to drag the `Draggable` by dragging on the interactive child element - which is probably what you want anyway. There are a few ways you can get around the standard `preventDefault` behavior. Here are some suggestions: | ||
It is possible for your `Draggable` to contain interactive elements. By default we block dragging on these elements. By doing this we allow those elements to function in the usual way. Here is the list of interactive elements that block dragging from by default: | ||
#### 1. Call `event.stopPropagation()` on the interactive element `mousedown` | ||
- `input` | ||
- `button` | ||
- `textarea` | ||
- `select` | ||
- `option` | ||
- `optgroup` | ||
- `video` | ||
- `audio` | ||
- [`contenteditable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable) (any elements that are `contenteditable` or are within a `contenteditable` container) | ||
*This is the simpler solution* | ||
You can opt out of this behavior by adding the `disableInteractiveElementBlocking` prop to a `Draggable`. However, it is questionable as to whether you should be doing so because it will render the interactive element unusable. If you need to *conditionally* block dragging from interactive elements you can add the `disableInteractiveElementBlocking` prop to opt out of the default blocking and monkey patch the `dragHandleProps (DragHandleProvided)` event handlers to disable dragging as required. | ||
On the child element, call `event.stopPropagation()` for the `onMouseDown` function. This will stop the event bubbling up to the `Draggable` and having `event.preventDefault()` called on it. The `Draggable` will not be aware that a `mousedown` has even occurred. | ||
```js | ||
<input | ||
// stop event from bubbling up to Draggable where it will be prevented | ||
onMouseDown={e => e.stopPropagation()} | ||
/> | ||
``` | ||
#### 2. Patch the `onMouseDown` event in `provided` | ||
*This is the more complex solution* | ||
If you cannot use the first solution, then you can consider patching the `provided` > `onMouseDown` function. The main idea of this approach is to add additional behavior to the existing `onMouseDown` function - only calling it when it should be called. | ||
```js | ||
class DraggableWithSelect extends Component { | ||
renderSelect = (provided) => { | ||
// Patched onMouseDown handler | ||
const onMouseDown = (event) => { | ||
// If mouse down is on a select, then do not | ||
// let react-beautiful-dnd do anything with it | ||
if(event.target.nodeName === 'SELECT') { | ||
return; | ||
} | ||
provided.dragHandleProps.onMouseDown(event); | ||
} | ||
// patching drag handle props | ||
const patched = { | ||
...provided.dragHandleProps, | ||
onMouseDown, | ||
} | ||
return ( | ||
<div> | ||
<div | ||
ref={provided.innerRef} | ||
style={getItemStyle( | ||
provided.draggableStyle, | ||
snapshot.isDragging | ||
)} | ||
{...patched} | ||
> | ||
<select> | ||
<option>One</option> | ||
<option>Two</option> | ||
<option>Three</option> | ||
</select> | ||
</div> | ||
{provided.placeholder} | ||
</div> | ||
); | ||
} | ||
render() { | ||
return ( | ||
<Draggable draggableId="draggable-1"> | ||
{this.renderSelect} | ||
</Draggable> | ||
); | ||
} | ||
} | ||
``` | ||
#### 3. Patch the `onKeyDown` event in `provided` | ||
Similar to #2, this patch should be used on inputs inside a `Draggable` | ||
```js | ||
class DraggableWithInput extends Component { | ||
renderInput = provided => { | ||
// Patched onMouseDown, make inputs selectable | ||
const onMouseDown = event => { | ||
if (event.target.nodeName === 'INPUT') { | ||
return; | ||
} | ||
provided.dragHandleProps.onMouseDown(event); | ||
}; | ||
// Patched onKeyDown handler, make typing in inputs | ||
// work as expected. For example, spacebar can be used | ||
// as normal characters instead of a shortcut. | ||
const onKeyDown = event => { | ||
if (event.target.nodeName === 'INPUT') { | ||
return; | ||
} | ||
provided.dragHandleProps.onKeyDown(event); | ||
}; | ||
// patching drag handle props | ||
const patched = { | ||
...provided.dragHandleProps, | ||
onMouseDown, | ||
onKeyDown, | ||
}; | ||
return ( | ||
<div> | ||
<div | ||
ref={provided.innerRef} | ||
style={getItemStyle( | ||
provided.draggableStyle, | ||
snapshot.isDragging | ||
)} | ||
{...patched} | ||
> | ||
<input type="text" /> | ||
</div> | ||
{provided.placeholder} | ||
</div> | ||
); | ||
} | ||
render() { | ||
return ( | ||
<Draggable draggableId="draggable-1"> | ||
{this.renderInput} | ||
</Draggable> | ||
); | ||
} | ||
} | ||
``` | ||
## Flow usage | ||
@@ -1210,3 +1175,3 @@ | ||
WebkitTapHighlightColor: 'rgba(0,0,0,0)', | ||
touchAction: 'none', | ||
touchAction: 'manipulation', | ||
|} | ||
@@ -1241,4 +1206,4 @@ type DraggingStyle = {| | ||
draggable: boolean, | ||
onDragStart: () => void, | ||
onDrop: () => void | ||
onDragStart: () => boolean, | ||
onDrop: () => boolean | ||
|} | ||
@@ -1291,2 +1256,6 @@ ``` | ||
## Size | ||
Great care has been taken to keep the library as light as possible. It is currently **~34kb (gzip)** in size. There could be a smaller net cost if you where already using one of the underlying dependencies. | ||
## Supported browsers | ||
@@ -1293,0 +1262,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
848334
159
13260
35
2
1279
5