DroppableListBox
A droppable listbox allows to drag and drop items from one list to another.
| Install | yarn add @diallink-corp/convergo-react-dnd |
|---|---|
| Version | 4.1.2 |
| Usage | import {DroppableListBox} from '@diallink-corp/convergo-react-dnd' |
Example
function Example() {
const dragList = useListState({
initialItems: [
{ id: '1', type: 'folder', text: 'One' },
{ id: '2', type: 'item', text: 'Two' },
{ id: '3', type: 'folder', text: 'Three' }
]
});
const id = useRef(2);
const dropList = useListState({
initialItems: [
{ id: 'Four', type: 'folder', text: 'Four' },
{ id: 'Five', type: 'item', text: 'Five' }
]
});
const ref = useRef(null);
const onDragEnd = (e) => {
if (e.dropOperation === 'move') {
dragList.removeItem(...e.keys);
}
};
const onCut = (keys) => {
dragList.removeItem(...keys);
};
const onDrop = async (e) => {
if (e.target.type === 'root' || e.target.dropPosition !== 'on') {
const items = [];
for (const item of e.items) {
let type: string;
if (item.kind === 'text') {
if (item.types.has('folder')) {
type = 'folder';
} else if (item.types.has('item')) {
type = 'item';
}
if (!type) {
continue;
}
items.push({
id: String(++id.current),
type,
text: await item.getText(type)
});
}
}
if (e.target.type === 'root') {
dropList.prependItem(...items);
} else if (e.target.dropPosition === 'before') {
dropList.insertItemBefore(e.target.key, ...items);
} else {
dropList.insertItemAfter(e.target.key, ...items);
}
}
};
const handleRemoveItem = (key) => {
const item = dropList.getItem(key);
dragList.appendItem(item);
dropList.removeItem(key);
};
return (
<div style={{ display: 'flex', width: '100%' }}>
<DraggableCollection
items={dragList.items || []}
selectedKeys={dragList.selectedKeys}
onSelectionChange={dragList.setSelectedKeys}
onDragEnd={onDragEnd}
onCut={onCut}
aria-label="Draggable list of items"
>
{(item) => (
<Item key={item.id} textValue={item.text}>
{item.type === 'folder' && (
<Icon name="FolderIcon" variant="outline" />
)}
<span>{item.text}</span>
</Item>
)}
</DraggableCollection>
<DroppableListBox items={dropList.items || []} onDrop={onDrop} ref={ref}>
{(item) => (
<Item key={item.id} textValue={item.text}>
{item.type === 'folder' && (
<Icon name="FolderIcon" variant="outline" />
)}
<span>{item.text}</span>
<Button
size="small"
variant="text"
aria-label={`Remove item `}
onPress={() => handleRemoveItem(item.id)}
iconName="XMarkIcon"
iconVariant="outline"
/>
</Item>
)}
</DroppableListBox>
</div>
);
}
function Example() {
const dragList = useListState({
initialItems: [
{ id: '1', type: 'folder', text: 'One' },
{ id: '2', type: 'item', text: 'Two' },
{ id: '3', type: 'folder', text: 'Three' }
]
});
const id = useRef(2);
const dropList = useListState({
initialItems: [
{ id: 'Four', type: 'folder', text: 'Four' },
{ id: 'Five', type: 'item', text: 'Five' }
]
});
const ref = useRef(null);
const onDragEnd = (e) => {
if (e.dropOperation === 'move') {
dragList.removeItem(...e.keys);
}
};
const onCut = (keys) => {
dragList.removeItem(...keys);
};
const onDrop = async (e) => {
if (
e.target.type === 'root' ||
e.target.dropPosition !== 'on'
) {
const items = [];
for (const item of e.items) {
let type: string;
if (item.kind === 'text') {
if (item.types.has('folder')) {
type = 'folder';
} else if (item.types.has('item')) {
type = 'item';
}
if (!type) {
continue;
}
items.push({
id: String(++id.current),
type,
text: await item.getText(type)
});
}
}
if (e.target.type === 'root') {
dropList.prependItem(...items);
} else if (e.target.dropPosition === 'before') {
dropList.insertItemBefore(e.target.key, ...items);
} else {
dropList.insertItemAfter(e.target.key, ...items);
}
}
};
const handleRemoveItem = (key) => {
const item = dropList.getItem(key);
dragList.appendItem(item);
dropList.removeItem(key);
};
return (
<div style={{ display: 'flex', width: '100%' }}>
<DraggableCollection
items={dragList.items || []}
selectedKeys={dragList.selectedKeys}
onSelectionChange={dragList.setSelectedKeys}
onDragEnd={onDragEnd}
onCut={onCut}
aria-label="Draggable list of items"
>
{(item) => (
<Item key={item.id} textValue={item.text}>
{item.type === 'folder' && (
<Icon name="FolderIcon" variant="outline" />
)}
<span>{item.text}</span>
</Item>
)}
</DraggableCollection>
<DroppableListBox
items={dropList.items || []}
onDrop={onDrop}
ref={ref}
>
{(item) => (
<Item key={item.id} textValue={item.text}>
{item.type === 'folder' && (
<Icon name="FolderIcon" variant="outline" />
)}
<span>{item.text}</span>
<Button
size="small"
variant="text"
aria-label={`Remove item `}
onPress={() =>
handleRemoveItem(item.id)}
iconName="XMarkIcon"
iconVariant="outline"
/>
</Item>
)}
</DroppableListBox>
</div>
);
}
function Example() {
const dragList =
useListState({
initialItems: [
{
id: '1',
type: 'folder',
text: 'One'
},
{
id: '2',
type: 'item',
text: 'Two'
},
{
id: '3',
type: 'folder',
text: 'Three'
}
]
});
const id = useRef(2);
const dropList =
useListState({
initialItems: [
{
id: 'Four',
type: 'folder',
text: 'Four'
},
{
id: 'Five',
type: 'item',
text: 'Five'
}
]
});
const ref = useRef(
null
);
const onDragEnd = (
e
) => {
if (
e.dropOperation ===
'move'
) {
dragList
.removeItem(
...e.keys
);
}
};
const onCut =
(keys) => {
dragList
.removeItem(
...keys
);
};
const onDrop = async (
e
) => {
if (
e.target.type ===
'root' ||
e.target
.dropPosition !==
'on'
) {
const items = [];
for (
const item of e
.items
) {
let type: string;
if (
item.kind ===
'text'
) {
if (
item.types
.has(
'folder'
)
) {
type =
'folder';
} else if (
item.types
.has(
'item'
)
) {
type =
'item';
}
if (!type) {
continue;
}
items.push({
id: String(
++id
.current
),
type,
text:
await item
.getText(
type
)
});
}
}
if (
e.target.type ===
'root'
) {
dropList
.prependItem(
...items
);
} else if (
e.target
.dropPosition ===
'before'
) {
dropList
.insertItemBefore(
e.target.key,
...items
);
} else {
dropList
.insertItemAfter(
e.target.key,
...items
);
}
}
};
const handleRemoveItem =
(key) => {
const item =
dropList.getItem(
key
);
dragList
.appendItem(
item
);
dropList
.removeItem(key);
};
return (
<div
style={{
display: 'flex',
width: '100%'
}}
>
<DraggableCollection
items={dragList
.items || []}
selectedKeys={dragList
.selectedKeys}
onSelectionChange={dragList
.setSelectedKeys}
onDragEnd={onDragEnd}
onCut={onCut}
aria-label="Draggable list of items"
>
{(item) => (
<Item
key={item.id}
textValue={item
.text}
>
{item
.type ===
'folder' &&
(
<Icon
name="FolderIcon"
variant="outline"
/>
)}
<span>
{item.text}
</span>
</Item>
)}
</DraggableCollection>
<DroppableListBox
items={dropList
.items || []}
onDrop={onDrop}
ref={ref}
>
{(item) => (
<Item
key={item.id}
textValue={item
.text}
>
{item
.type ===
'folder' &&
(
<Icon
name="FolderIcon"
variant="outline"
/>
)}
<span>
{item.text}
</span>
<Button
size="small"
variant="text"
aria-label={`Remove item `}
onPress={() =>
handleRemoveItem(
item.id
)}
iconName="XMarkIcon"
iconVariant="outline"
/>
</Item>
)}
</DroppableListBox>
</div>
);
}