Skip to content

Commit

Permalink
drag lists
Browse files Browse the repository at this point in the history
  • Loading branch information
exced committed Dec 20, 2017
1 parent f100312 commit 2952bb8
Show file tree
Hide file tree
Showing 13 changed files with 484 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cache:
directories:
- node_modules
notifications:
email: false
email: false
script:
- yarn coverage
- yarn lib
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const App = (props) => (
)
```

## TODO
- Allow custom styling
- ...

## API

| Name | Type | Default | Required | Description |
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"file-loader": "1.1.5",
"fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0",
"immutable": "4.0.0-rc.9",
"jest": "20.0.4",
"less": "^2.7.3",
"less-loader": "^4.0.5",
Expand All @@ -40,9 +41,9 @@
"promise": "8.0.1",
"raf": "3.4.0",
"react": "^16.1.1",
"react-beautiful-dnd": "^3.0.0",
"react-dev-utils": "^4.2.1",
"react-dom": "^16.1.1",
"react-sortable-hoc": "^0.6.8",
"style-loader": "0.19.0",
"styled-components": "^2.2.4",
"sw-precache-webpack-plugin": "0.11.4",
Expand Down
Binary file added public/images/file.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/folder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 51 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,58 @@
import React from 'react'
import FileManager from './lib'
import { Icon } from 'antd'

const map = {
"1": {
id: "1",
title: "title1",
children: ["1", "2", "3"],
},
"2": {
id: "2",
title: "title2",
children: [],
},
"3": {
id: "3",
title: "title3",
children: ["4", "5"],
},
"4": {
id: "4",
title: "title4",
children: [],
},
"5": {
id: "5",
title: "title5",
children: [],
},
}

const renderItem = (item) => (
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ flex: 1 }}>
<div style={{ float: 'left' }}>
<img src={item.children.length > 0 ? '/images/folder.png' : '/images/file.png'} alt={item.title} style={{ width: 22, height: 22 }} />
</div>
</div>
<div style={{ flex: 5 }}>
<div style={{ width: 150, textAlign: 'left', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
<span>{item.title}</span>
</div>
</div>
<div style={{ flex: 1 }}>
{item.children.length > 0 &&
<div style={{ float: 'right' }}>
<Icon type="right" />
</div>}
</div>
</div>
)

const App = () => (
<FileManager />
<FileManager map={map} rootId={"1"} renderItem={renderItem} />
)

export default App
115 changes: 115 additions & 0 deletions src/lib/Column.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// License: https://github.com/atlassian/react-beautiful-dnd
// See https://github.com/atlassian/react-beautiful-dnd
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Droppable, Draggable } from 'react-beautiful-dnd'
import Item from './Item'

const Wrapper = styled.div`
background-color: ${({ isDraggingOver }) => (isDraggingOver ? '#c5d0e0' : '#b5bfce')};
display: flex;
flex-direction: column;
opacity: ${({ isDropDisabled }) => (isDropDisabled ? 0.5 : 'inherit')};
padding: 8px;
padding-bottom: 0;
transition: background-color 0.1s ease, opacity 0.1s ease;
user-select: none;
width: 250px;
`

const DropZone = styled.div`
min-height: 250px;
margin-bottom: 8px;
`

const ScrollContainer = styled.div`
overflow-x: hidden;
overflow-y: auto;
max-height: 300px;
`

const Container = styled.div`
`

export default class Column extends Component {

renderList = (dropProvided) => {
const {
listType,
data,
selectedId,
onChangeSelectedId,
renderItem,
} = this.props;

return (
<Container>
<DropZone innerRef={dropProvided.innerRef}>
{data.map(item => (
<Draggable key={item.id} draggableId={item.id} type={listType}>
{(dragProvided, dragSnapshot) => (
<div>
<Item
key={item.id}
item={item}
isDragging={dragSnapshot.isDragging}
provided={dragProvided}
autoFocus={this.props.autoFocusId === item.id}
selected={selectedId === item.id}
onClick={() => onChangeSelectedId(item.id)}
renderItem={renderItem}
/>
{dragProvided.placeholder}
</div>
)}
</Draggable>
))}
{dropProvided.placeholder}
</DropZone>
</Container>
);
}

render() {
const {
ignoreContainerClipping,
internalScroll,
isDropDisabled,
listId,
listType,
style,
} = this.props;

return (
<Droppable
droppableId={listId}
ignoreContainerClipping={ignoreContainerClipping}
isDropDisabled={isDropDisabled}
type={listType}
>
{(dropProvided, dropSnapshot) => (
<Wrapper
style={style}
isDraggingOver={dropSnapshot.isDraggingOver}
isDropDisabled={isDropDisabled}
>
{internalScroll ? (
<ScrollContainer>
{this.renderList(dropProvided)}
</ScrollContainer>
) : (
this.renderList(dropProvided)
)}
</Wrapper>
)}
</Droppable>
);
}
}

Column.propTypes = {
selectedId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
onChangeSelectedId: PropTypes.func.isRequired,
renderItem: PropTypes.func.isRequired,
}
9 changes: 0 additions & 9 deletions src/lib/Components/Root.js

This file was deleted.

56 changes: 56 additions & 0 deletions src/lib/Item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import styled from 'styled-components'

const Container = styled.div`
border-radius: 3px;
border: 1px solid grey;
background-color: ${({ selected, isDragging }) => (isDragging ? 'green' : (selected ? 'blue' : 'white'))};
/* cursor: grabbing is handled by app */
cursor: grab;
box-shadow: ${({ isDragging }) => (isDragging ? `2px 2px 1px grey` : 'none')};
padding: 6px;
min-height: 40px;
margin-bottom: 6px;
user-select: none;
transition: background-color 0.1s ease;
/* anchor overrides */
color: black;
&:hover {
color: black;
text-decoration: none;
}
&:focus {
outline: 2px solid purple;
box-shadow: none;
}
`;

export default class Item extends Component {
componentDidMount() {
if (!this.props.autoFocus) {
return;
}

// eslint-disable-next-line react/no-find-dom-node
const node = ReactDOM.findDOMNode(this);
node.focus();
}

render() {
const { item, renderItem, isDragging, provided, selected, onClick } = this.props;

return (
<Container
isDragging={isDragging}
innerRef={provided.innerRef}
style={provided.draggableStyle}
selected={selected}
onClick={onClick}
{...provided.dragHandleProps}
>
{renderItem(item)}
</Container>
);
}
}
Loading

0 comments on commit 2952bb8

Please sign in to comment.