kibana/x-pack/plugins/lens/public/drag_drop
Tim Roes ebbc062689
Move Lens frontend to Kibana Platform (#62965)
* Move Lens frontend to Kibana platform

* Fix line breaks

* Fix jest tests

* Fix remaining test

* Remove old Lens plugin entry

* Fix i18n prefix

* Add config schema

* Address review
2020-04-15 12:22:37 +02:00
..
__snapshots__ Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
_drag_drop.scss Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
_index.scss Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
drag_drop.test.tsx Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
drag_drop.tsx Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
index.ts Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
providers.test.tsx Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
providers.tsx Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00
readme.md Move Lens frontend to Kibana Platform (#62965) 2020-04-15 12:22:37 +02:00

Drag / Drop

This is a simple drag / drop mechanism that plays nice with React.

We aren't using EUI or another library, due to the fact that Lens visualizations and datasources may or may not be written in React. Even visualizations which are written in React will end up having their own ReactDOM.render call, and in that sense will be a standalone React application. We want to enable drag / drop across React and native DOM boundaries.

Getting started

First, place a RootDragDropProvider at the root of your application.

<RootDragDropProvider>
  ... your app here ...
</RootDragDropProvider>

If you have a child React application (e.g. a visualization), you will need to pass the drag / drop context down into it. This can be obtained like so:

const context = useContext(DragContext);

In your child application, place a ChildDragDropProvider at the root of that, and spread the context into it:

<ChildDragDropProvider {...context}>
  ... your child app here ...
</ChildDragDropProvider>

This enables your child application to share the same drag / drop context as the root application.

Dragging

An item can be both draggable and droppable at the same time, but for simplicity's sake, we'll treat these two cases separately.

To enable dragging an item, use DragDrop with both a draggable and a value attribute.

<div className="field-list">
  {fields.map(f => (
    <DragDrop key={f.id} className="field-list-item" value={f} draggable>
      {f.name}
    </DragDrop>
  ))}
</div>

Dropping

To enable dropping, use DragDrop with both a droppable attribute and an onDrop handler attribute. Droppable should only be set to true if there is an item being dragged, and if a drop of the dragged item is supported.

const { dragging } = useContext(DragContext);
  
return (
  <DragDrop
    className="axis"
    droppable={dragging && canHandleDrop(dragging)}
    onDrop={item => onChange([...items, item])}
  >
    {items.map(x => <div>{x.name}</div>)}
  </DragDrop>
);

Limitations

Currently this is a very simple drag / drop mechanism. We don't support reordering out of the box, though it could probably be built on top of this solution without modification of the core.