Skip to content

Commit

Permalink
Merge pull request #1439 from Sage/CARBON-865
Browse files Browse the repository at this point in the history
[CARBON-865] CustomDragLayer component for enabling Drag & Drop ghost row
  • Loading branch information
SeanArmstrong committed Aug 29, 2017
2 parents 937b3a3 + f33a17f commit c1cd931
Show file tree
Hide file tree
Showing 21 changed files with 786 additions and 111 deletions.
46 changes: 46 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,49 @@
# 1.6.0

### Draggable ghost row

The `DraggableContext` component now includes a `CustomDragLayer` to enable a ghost row when dragging.

In order to enable this you need to define the `draggableNode` prop on the `<WithDrag>` component. For example:

```
class DraggableItems extends React.Component {
render() {
return (
<DraggableContext onDrag={ onItemMoved }>
<ol>
{
items.map((item, index) => {
return (
<WithDrop key={ index } index={ index }>
<DraggableItem />
</WithDrop>
);
});
}
</ol>
</DraggableContext>
);
}
}
...
class DraggableItem extends React.Component {
render() {
return (
<li ref={ (node) => { this._listItem = node; } } >
<WithDrag draggableNode={ () => { return this._listItem; } }>
<span>{ item.content }</span>
</WithDrag>
</li>
);
}
}
```

Note that the `draggableNode` is passed as a function because the ref `_listItem` is undefined until the component is mounted.

# 1.5.0

## Component Improvements
Expand Down
@@ -1,9 +1,10 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, mount } from 'enzyme';
import ConfigurableItemRow from './configurable-item-row';
import Checkbox from './../../checkbox';
import Icon from './../../icon';
import { WithDrag, WithDrop } from './../../drag-and-drop';
import DraggableContext from './../../drag-and-drop/draggable-context';
import { rootTagTest } from './../../../utils/helpers/tags/tags-specs';

describe('ConfigurableItemRow', () => {
Expand Down Expand Up @@ -140,13 +141,20 @@ describe('ConfigurableItemRow', () => {

describe('icon', () => {
beforeEach(() => {
wrapper = shallow(
<ConfigurableItemRow name='Foo' />
wrapper = mount(
<DraggableContext onDrag={() => {}}>
<ConfigurableItemRow name='Foo' />
</DraggableContext>
);
});

it('renders a drag vertical icon', () => {
expect(wrapper.find(Icon).props().type).toEqual('drag_vertical')
it('renders a drag vertical icon wrapped in WithDrag', () => {
wrapper.update(); // this is required because the _draggableNode ref is initially undefined.
const withDrag = wrapper.find(WithDrag);
const row = wrapper.find(ConfigurableItemRow);
expect(withDrag.length).toEqual(1);
expect(withDrag.find(Icon).props().type).toEqual('drag_vertical');
expect(withDrag.props().draggableNode()).toEqual(row.node._listItem)
});
});

Expand All @@ -157,8 +165,10 @@ describe('ConfigurableItemRow', () => {
);
});

it('renders an <li>', () => {
expect(wrapper.find('li').length).toEqual(1)
it('renders an <li> wrapped in WithDrop', () => {
const withDrop = wrapper.find(WithDrop);
expect(withDrop.length).toEqual(1);
expect(withDrop.find('li').length).toEqual(1);
});
})
});
});
Expand Up @@ -73,15 +73,21 @@ class ConfigurableItemRow extends React.Component {
);
}

iconHTML() {
return (
<div>
<Icon
className='configurable-item-row__icon'
type='drag_vertical'
/>
</div>
);
}

icon() {
return (
<WithDrag>
<div>
<Icon
className='configurable-item-row__icon'
type='drag_vertical'
/>
</div>
<WithDrag draggableNode={ () => { return this._listItem; } } >
{this.iconHTML()}
</WithDrag>
);
}
Expand Down Expand Up @@ -119,16 +125,25 @@ class ConfigurableItemRow extends React.Component {
return typeof (dragAndDropActiveIndex) === 'number';
}

render() {
listItemHTML = () => {
const { rowIndex, enabled, locked, name, onChange } = this.props;
return (
<WithDrop index={ rowIndex } { ...tagComponent('configurable-item-row', this.props) }>
<li className={ this.classes(this.context.dragAndDropActiveIndex, rowIndex) }>
<div className='configurable-item-row__content-wrapper'>
{ this.icon() }
{ this.checkbox(enabled, locked, name, onChange) }
</div>
</li>
<li
className={ this.classes(this.context.dragAndDropActiveIndex, rowIndex) }
ref={ (node) => { this._listItem = node; } }
>
<div className='configurable-item-row__content-wrapper'>
{ this.icon() }
{ this.checkbox(enabled, locked, name, onChange) }
</div>
</li>
);
}

render() {
return (
<WithDrop index={ this.props.rowIndex } { ...tagComponent('configurable-item-row', this.props) }>
{ this.listItemHTML() }
</WithDrop>
);
}
Expand Down
Expand Up @@ -13,6 +13,12 @@
cursor: -webkit-grabbing;
}

.configurable-item-row--dragged {
.configurable-item-row__content-wrapper {
visibility: hidden;
}
}

.configurable-item-row__content-wrapper {
align-items: center;
display: flex;
Expand All @@ -22,3 +28,23 @@
.configurable-item-row__icon {
cursor: move;
}

.custom-drag-layer {
.configurable-item-row {
background-color: $grey-light;
border: none;
cursor: grabbing;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;

.configurable-item-row__icon {
cursor: grabbing;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
}

.configurable-item-row__content-wrapper {
visibility: visible;
}
}
}
14 changes: 14 additions & 0 deletions src/components/drag-and-drop/custom-drag-layer/__definition__.js
@@ -0,0 +1,14 @@
import CustomDragLayer from './';
import Definition from './../../../../demo/utils/definition';

const definition = new Definition('custom-drag-layer', CustomDragLayer, {
props: ['className'],
propTypes: {
className: 'String'
},
propDescriptions: {
className: 'Custom classes to apply to the component'
}
});

export default definition;

0 comments on commit c1cd931

Please sign in to comment.