Skip to content

Commit

Permalink
Merge pull request #980 from daynin/droppable
Browse files Browse the repository at this point in the history
feat(grid): add an ability to drop elements from outside of a grid
  • Loading branch information
daynin committed Sep 9, 2019
2 parents 80873c8 + 1ff0ab0 commit 56eb5c8
Show file tree
Hide file tree
Showing 10 changed files with 364 additions and 25 deletions.
19 changes: 18 additions & 1 deletion README.md
Expand Up @@ -49,6 +49,7 @@ RGL is React-only and does not require jQuery.
1. [Prevent Collision](https://strml.github.io/react-grid-layout/examples/12-prevent-collision.html)
1. [Error Case](https://strml.github.io/react-grid-layout/examples/13-error-case.html)
1. [Toolbox](https://strml.github.io/react-grid-layout/examples/14-toolbox.html)
1. [Drag From Outside](https://strml.github.io/react-grid-layout/examples/16-drag-from-outside.html)

#### Projects Using React-Grid-Layout

Expand Down Expand Up @@ -284,6 +285,14 @@ containerPadding: ?[number, number] = margin,
// if you like.
rowHeight: ?number = 150,

// Configuration of a dropping element. Dropping element is a "virtual" element
// which appears when you drag over some element from outside.
// It can be changed by passing specific parameters:
// i - id of an element
// w - width of an element
// h - height of an element
droppingItem?: { i: string, w: number, h: number }

//
// Flags
//
Expand All @@ -297,6 +306,12 @@ useCSSTransforms: ?boolean = true,
// dragged over.
preventCollision: ?boolean = false;

// If true, droppable elements (with "droppable" attribute)
// can be dropped on the grid. It triggers "onDrop" callback
// with position and event object as parameters.
// It can be useful for dropping an element in a specific position
isDroppable: ?boolean = false

//
// Callbacks
//
Expand All @@ -323,7 +338,9 @@ onResizeStart: ItemCallback,
// Calls when resize movement happens.
onResize: ItemCallback,
// Calls when resize is complete.
onResizeStop: ItemCallback
onResizeStop: ItemCallback,
// Calls when some element has been dropped
onDrop: (elemParams: { x: number, y: number, e: Event }) => void
```

### Responsive Grid Layout Props
Expand Down
4 changes: 4 additions & 0 deletions css/styles.css
Expand Up @@ -20,6 +20,10 @@
will-change: transform;
}

.react-grid-item.dropping {
visibility: hidden;
}

.react-grid-item.react-grid-placeholder {
background: red;
opacity: 0.2;
Expand Down
24 changes: 24 additions & 0 deletions examples/16-drag-from-outside.html
@@ -0,0 +1,24 @@
<!--
Do not edit this file! It is generated by `generate.js` in this folder, from `template.ejs` and vars.js.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="http://localhost:4002/dist/commons.js"></script>
<script src="http://localhost:4002/dist/16-drag-from-outside.bundle.js"></script>
<title>RGL Example 16 - Drag From Outside</title>
</head>
<body>
<h3>React-Grid-Layout Demo 16 - Drag From Outside</h3>
<ul>
<li><a href="https://github.com/STRML/react-grid-layout">View project on GitHub</a></li>
<li><a href="https://github.com/STRML/react-grid-layout/blob/master/test/examples/16-drag-from-outside.jsx">View this example's source</a></li>

<li><a href="1-basic.html"><b></b>View the next example: "Basic"</a></li>
</ul>
<p>React-Grid-Layout is a grid layout system for React. It features auto-packing, draggable and resizable widgets, static widgets, a fluid layout, and separate layouts per responsive breakpoint.</p>
<p>Try it out! Drag some boxes around, resize them, and resize the window to see the responsive breakpoints.</p>
<div id="content"></div>
</body>
</html>
7 changes: 7 additions & 0 deletions examples/example-styles.css
Expand Up @@ -95,3 +95,10 @@ li b {
border: 1px solid black;
background-color: #ddd;
}
.droppable-element {
width: 150px;
background: #ddd;
border: 1px solid black;
margin-top: 10px;
padding: 10px;
}
48 changes: 47 additions & 1 deletion lib/GridItem.jsx
@@ -1,5 +1,6 @@
// @flow
import React from "react";
import ReactDOM from "react-dom";
import PropTypes from "prop-types";
import { DraggableCore } from "react-draggable";
import { Resizable } from "react-resizable";
Expand All @@ -11,6 +12,7 @@ import type {
ReactDraggableCallbackData,
GridDragEvent,
GridResizeEvent,
DroppingPosition,
Position
} from "./utils";

Expand Down Expand Up @@ -41,6 +43,7 @@ type Props = {
static?: boolean,
useCSSTransforms?: boolean,
usePercentages?: boolean,
droppingPosition?: DroppingPosition,

className: string,
style?: Object,
Expand Down Expand Up @@ -142,7 +145,12 @@ export default class GridItem extends React.Component<Props, State> {
// Selector for draggable handle
handle: PropTypes.string,
// Selector for draggable cancel (see react-draggable)
cancel: PropTypes.string
cancel: PropTypes.string,
// Current position of a dropping element
droppingPosition: PropTypes.shape({
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired
})
};

static defaultProps = {
Expand All @@ -161,6 +169,42 @@ export default class GridItem extends React.Component<Props, State> {
className: ""
};

currentNode: HTMLElement;

componentWillReceiveProps(nextProps: Props) {
const { droppingPosition } = nextProps;
const { dragging } = this.state;

if (!droppingPosition || !this.props.droppingPosition) {
return;
}

if (!this.currentNode) {
// eslint-disable-next-line react/no-find-dom-node
this.currentNode = ((ReactDOM.findDOMNode(this): any): HTMLElement);
}

if (!dragging) {
this.onDragHandler("onDragStart")(droppingPosition.e, {
node: this.currentNode,
deltaX: droppingPosition.x,
deltaY: droppingPosition.y
});
} else if (
(dragging && droppingPosition.x !== this.props.droppingPosition.x) ||
droppingPosition.y !== this.props.droppingPosition.y
) {
const deltaX = droppingPosition.x - dragging.left;
const deltaY = droppingPosition.y - dragging.top;

this.onDragHandler("onDrag")(droppingPosition.e, {
node: this.currentNode,
deltaX,
deltaY
});
}
}

// Helper for generating column width
calcColWidth(): number {
const { margin, containerPadding, containerWidth, cols } = this.props;
Expand Down Expand Up @@ -462,6 +506,7 @@ export default class GridItem extends React.Component<Props, State> {
h,
isDraggable,
isResizable,
droppingPosition,
useCSSTransforms
} = this.props;

Expand All @@ -479,6 +524,7 @@ export default class GridItem extends React.Component<Props, State> {
resizing: Boolean(this.state.resizing),
"react-draggable": isDraggable,
"react-draggable-dragging": Boolean(this.state.dragging),
dropping: Boolean(droppingPosition),
cssTransforms: useCSSTransforms
}
),
Expand Down

0 comments on commit 56eb5c8

Please sign in to comment.