From 4801cb07a0d89d241240d9ba914b55f911fc0008 Mon Sep 17 00:00:00 2001 From: Christopher Davies Date: Wed, 8 May 2019 08:31:58 -0400 Subject: [PATCH 1/6] Add basic drag / drop component to Lens --- .../__snapshots__/drag_drop.test.tsx.snap | 26 ++++ .../lens/public/drag_drop/drag_drop.scss | 7 + .../lens/public/drag_drop/drag_drop.test.tsx | 102 +++++++++++++ .../lens/public/drag_drop/drag_drop.tsx | 136 ++++++++++++++++++ x-pack/plugins/lens/public/drag_drop/index.ts | 8 ++ .../lens/public/drag_drop/providers.tsx | 85 +++++++++++ .../plugins/lens/public/drag_drop/readme.md | 69 +++++++++ 7 files changed, 433 insertions(+) create mode 100644 x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap create mode 100644 x-pack/plugins/lens/public/drag_drop/drag_drop.scss create mode 100644 x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx create mode 100644 x-pack/plugins/lens/public/drag_drop/drag_drop.tsx create mode 100644 x-pack/plugins/lens/public/drag_drop/index.ts create mode 100644 x-pack/plugins/lens/public/drag_drop/providers.tsx create mode 100644 x-pack/plugins/lens/public/drag_drop/readme.md diff --git a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap new file mode 100644 index 0000000000000..54f81e3cac739 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DragDrop changes className if droppable 1`] = ` +
+ Hello! +
+`; + +exports[`DragDrop droppable is reflected in the className 1`] = ` +
+ Hello! +
+`; + +exports[`DragDrop renders if nothing is being dragged 1`] = ` +
+ Hello! +
+`; diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.scss b/x-pack/plugins/lens/public/drag_drop/drag_drop.scss new file mode 100644 index 0000000000000..25fd74fe482e8 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.scss @@ -0,0 +1,7 @@ +.drag-drop_is-drop-target { + background-color: transparentize($euiColorSecondary, .9); +} + +.drag-drop_is-active-drop-target { + background-color: transparentize($euiColorSecondary, .75); +} diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx new file mode 100644 index 0000000000000..f583e5d4a563e --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, shallow, mount } from 'enzyme'; +import { DragDrop } from './drag_drop'; +import { ChildDragDropProvider } from './providers'; + +jest.useFakeTimers(); + +describe('DragDrop', () => { + test('renders if nothing is being dragged', () => { + const component = render( + + Hello! + + ); + + expect(component).toMatchSnapshot(); + }); + + test('dragover calls preventDefault if droppable is true', () => { + const preventDefault = jest.fn(() => {}); + const component = shallow(Hello!); + + component.find('.drag-drop').simulate('dragover', { preventDefault }); + + expect(preventDefault).toBeCalled(); + }); + + test('dragover does not call preventDefault if droppable is false', () => { + const preventDefault = jest.fn(() => {}); + const component = shallow(Hello!); + + component.find('.drag-drop').simulate('dragover', { preventDefault }); + + expect(preventDefault).not.toBeCalled(); + }); + + test('dragstart sets dragging in the context', async () => { + const setDragging = jest.fn(() => {}); + const dataTransfer = { + setData: jest.fn(() => {}), + getData: jest.fn(() => {}), + }; + const value = {}; + + const component = mount( + + Hello! + + ); + + component.find('.drag-drop').simulate('dragstart', { dataTransfer }); + + jest.runAllTimers(); + + expect(dataTransfer.setData).toBeCalledWith('text', 'dragging'); + expect(setDragging).toBeCalledWith(value); + }); + + test('drop resets all the things', async () => { + const preventDefault = jest.fn(() => {}); + const stopPropagation = jest.fn(() => {}); + const setDragging = jest.fn(() => {}); + const onDrop = jest.fn(() => {}); + const value = {}; + + const component = mount( + + + Hello! + + + ); + + component.find('.drag-drop').simulate('drop', { preventDefault, stopPropagation }); + + expect(preventDefault).toBeCalled(); + expect(stopPropagation).toBeCalled(); + expect(setDragging).toBeCalledWith(undefined); + expect(onDrop).toBeCalledWith('hola'); + }); + + test('droppable is reflected in the className', () => { + const component = render( + { + throw x; + }} + droppable + > + Hello! + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx new file mode 100644 index 0000000000000..da01866058bd5 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useContext } from 'react'; +import { DragContext } from './providers'; + +type DroppableEvent = React.DragEvent; + +/** + * A function that handles a drop event. + */ +type DropHandler = (item: any) => void; + +/** + * The argument to the DragDrop component. + */ +interface Props { + /** + * The CSS class(es) for the root element. + */ + className?: string; + + /** + * The event handler that fires when an item + * is dropped onto this DragDrop component. + */ + onDrop?: DropHandler; + + /** + * The value associated with this item, if it is draggable. + * If this component is dragged, this will be the value of + * "dragging" in the root drag/drop context. + */ + value?: any; + + /** + * The React children. + */ + children?: React.ReactNodeArray; + + /** + * Indicates whether or not the currently dragged item + * can be dropped onto this component. + */ + droppable?: boolean; + + /** + * Indicates whether or not this component is draggable. + */ + draggable?: boolean; +} + +/** + * A draggable / droppable item. Items can be both draggable and droppable at + * the same time. + * + * @param props + */ +export function DragDrop(props: Props) { + const { dragging, setDragging } = useContext(DragContext); + const [state, setState] = useState({ isActive: false }); + const { className, onDrop, value, children, droppable, draggable } = props; + const isDragging = draggable && value === dragging; + + const classSuffix = + ' drag-drop' + + (droppable ? ' drag-drop_is-drop-target' : '') + + (droppable && state.isActive ? ' drag-drop_is-active-drop-target' : '') + + (isDragging ? ' drag-drop_is-dragging' : ''); + + const dragStart = (e: DroppableEvent) => { + // Setting stopPropgagation causes Chrome failures, so + // we are manually checking if we've already handled this + // in a nested child, and doing nothing if so... + if (e.dataTransfer.getData('text')) { + return; + } + + e.dataTransfer.setData('text', 'dragging'); + + // Chrome causes issues if you try to render from within a + // dragStart event, so we drop a setTimeout to avoid that. + setTimeout(() => setDragging(value)); + }; + + const dragEnd = (e: DroppableEvent) => { + e.stopPropagation(); + setDragging(undefined); + }; + + const dragOver = (e: DroppableEvent) => { + if (!droppable) { + return; + } + + e.preventDefault(); + + // An optimization to prevent a bunch of React churn. + if (!state.isActive) { + setState({ ...state, isActive: true }); + } + }; + + const dragLeave = () => { + setState({ ...state, isActive: false }); + }; + + const drop = (e: DroppableEvent) => { + e.preventDefault(); + e.stopPropagation(); + + setState({ ...state, isActive: false }); + setDragging(undefined); + + if (onDrop) { + onDrop(dragging); + } + }; + + return ( +
+ {children} +
+ ); +} diff --git a/x-pack/plugins/lens/public/drag_drop/index.ts b/x-pack/plugins/lens/public/drag_drop/index.ts new file mode 100644 index 0000000000000..e597bb8b6e893 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './providers'; +export * from './drag_drop'; diff --git a/x-pack/plugins/lens/public/drag_drop/providers.tsx b/x-pack/plugins/lens/public/drag_drop/providers.tsx new file mode 100644 index 0000000000000..5c6dc32a1f052 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/providers.tsx @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState } from 'react'; + +/** + * The shape of the drag / drop context. + */ +export interface DragContextState { + /** + * The item being dragged or undefined. + */ + dragging: any; + + /** + * Set the item being dragged. + */ + setDragging: (dragging: any) => void; +} + +/** + * The drag / drop context singleton, used like so: + * + * const { dragging, setDragging } = useContext(DragContext); + */ +export const DragContext = React.createContext({ + dragging: undefined, + setDragging: () => {}, +}); + +/** + * The argument to DragDropProvider. + */ +export interface ProviderProps { + /** + * The item being dragged. If unspecified, the provider will + * behave as if it is the root provider. + */ + dragging: any; + + /** + * Sets the item being dragged. If unspecified, the provider + * will behave as if it is the root provider. + */ + setDragging: (dragging: any) => void; + + /** + * The React children. + */ + children?: any; +} + +/** + * A React provider that tracks the dragging state. This should + * be placed at the root of any React application that supports + * drag / drop. + * + * @param props + */ +export function RootDragDropProvider({ children }: { children: React.ReactNodeArray }) { + const [state, setState] = useState<{ dragging: any }>({ + dragging: undefined, + }); + const setDragging = (dragging: any) => setState({ dragging }); + + return ( + + {children} + + ); +} + +/** + * A React drag / drop provider that derives its state from a RootDragDropProvider. If + * part of a React application is rendered separately from the root, this provider can + * be used to enable drag / drop functionality within the disconnected part. + * + * @param props + */ +export function ChildDragDropProvider({ dragging, setDragging, children }: ProviderProps) { + return {children}; +} diff --git a/x-pack/plugins/lens/public/drag_drop/readme.md b/x-pack/plugins/lens/public/drag_drop/readme.md new file mode 100644 index 0000000000000..8d11cb6226927 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/readme.md @@ -0,0 +1,69 @@ +# 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. + +```js + + ... your app here ... + +``` + +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: + +```js +const context = useContext(DragContext); +``` + +In your child application, place a `ChildDragDropProvider` at the root of that, and spread the context into it: + +```js + + ... your child app here ... + +``` + +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. + +```js +
+ {fields.map(f => ( + + {f.name} + + ))} +
+``` + +## 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. + +```js +const { dragging } = useContext(DragContext); + +return ( + onChange([...items, item])} + > + {items.map(x =>
{x.name}
)} +
+); +``` + +## 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. From 961eaeaed9ede08309f852200b7c6700c288ac23 Mon Sep 17 00:00:00 2001 From: Christopher Davies Date: Wed, 8 May 2019 08:39:52 -0400 Subject: [PATCH 2/6] Fix tests and type errors --- .../drag_drop/__snapshots__/drag_drop.test.tsx.snap | 10 ++-------- .../plugins/lens/public/drag_drop/drag_drop.test.tsx | 10 ++++++---- x-pack/plugins/lens/public/drag_drop/drag_drop.tsx | 3 ++- x-pack/plugins/lens/public/drag_drop/providers.tsx | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap index 54f81e3cac739..56a95a6624f47 100644 --- a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap +++ b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap @@ -1,16 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`DragDrop changes className if droppable 1`] = ` -
- Hello! -
-`; - exports[`DragDrop droppable is reflected in the className 1`] = `
Hello!
@@ -19,6 +12,7 @@ exports[`DragDrop droppable is reflected in the className 1`] = ` exports[`DragDrop renders if nothing is being dragged 1`] = `
Hello! diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx index f583e5d4a563e..01c310fba2c3c 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx @@ -26,7 +26,7 @@ describe('DragDrop', () => { const preventDefault = jest.fn(() => {}); const component = shallow(Hello!); - component.find('.drag-drop').simulate('dragover', { preventDefault }); + component.find('[data-test-subj="drag-drop"]').simulate('dragover', { preventDefault }); expect(preventDefault).toBeCalled(); }); @@ -35,7 +35,7 @@ describe('DragDrop', () => { const preventDefault = jest.fn(() => {}); const component = shallow(Hello!); - component.find('.drag-drop').simulate('dragover', { preventDefault }); + component.find('[data-test-subj="drag-drop"]').simulate('dragover', { preventDefault }); expect(preventDefault).not.toBeCalled(); }); @@ -54,7 +54,7 @@ describe('DragDrop', () => { ); - component.find('.drag-drop').simulate('dragstart', { dataTransfer }); + component.find('[data-test-subj="drag-drop"]').simulate('dragstart', { dataTransfer }); jest.runAllTimers(); @@ -77,7 +77,9 @@ describe('DragDrop', () => { ); - component.find('.drag-drop').simulate('drop', { preventDefault, stopPropagation }); + component + .find('[data-test-subj="drag-drop"]') + .simulate('drop', { preventDefault, stopPropagation }); expect(preventDefault).toBeCalled(); expect(stopPropagation).toBeCalled(); diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx index da01866058bd5..148aaad962e42 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -39,7 +39,7 @@ interface Props { /** * The React children. */ - children?: React.ReactNodeArray; + children?: any; /** * Indicates whether or not the currently dragged item @@ -122,6 +122,7 @@ export function DragDrop(props: Props) { return (
({ dragging: undefined, }); From 4ae26ab29739fb4fe11d40b00679354f09927a29 Mon Sep 17 00:00:00 2001 From: Christopher Davies Date: Wed, 8 May 2019 11:39:32 -0400 Subject: [PATCH 3/6] Modify CSS to match Kibana norms --- .../drag_drop/__snapshots__/drag_drop.test.tsx.snap | 8 ++++---- x-pack/plugins/lens/public/drag_drop/drag_drop.scss | 4 ++-- .../plugins/lens/public/drag_drop/drag_drop.test.tsx | 8 ++++---- x-pack/plugins/lens/public/drag_drop/drag_drop.tsx | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap index 56a95a6624f47..4aef482ebd216 100644 --- a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap +++ b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap @@ -2,8 +2,8 @@ exports[`DragDrop droppable is reflected in the className 1`] = `
Hello!
@@ -11,8 +11,8 @@ exports[`DragDrop droppable is reflected in the className 1`] = ` exports[`DragDrop renders if nothing is being dragged 1`] = `
Hello! diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.scss b/x-pack/plugins/lens/public/drag_drop/drag_drop.scss index 25fd74fe482e8..f0b3238f76f2e 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.scss +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.scss @@ -1,7 +1,7 @@ -.drag-drop_is-drop-target { +.lnsDragDrop-isDropTarget { background-color: transparentize($euiColorSecondary, .9); } -.drag-drop_is-active-drop-target { +.lnsDragDrop-isActiveDropTarget { background-color: transparentize($euiColorSecondary, .75); } diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx index 01c310fba2c3c..9d488051377b9 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx @@ -26,7 +26,7 @@ describe('DragDrop', () => { const preventDefault = jest.fn(() => {}); const component = shallow(Hello!); - component.find('[data-test-subj="drag-drop"]').simulate('dragover', { preventDefault }); + component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault }); expect(preventDefault).toBeCalled(); }); @@ -35,7 +35,7 @@ describe('DragDrop', () => { const preventDefault = jest.fn(() => {}); const component = shallow(Hello!); - component.find('[data-test-subj="drag-drop"]').simulate('dragover', { preventDefault }); + component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault }); expect(preventDefault).not.toBeCalled(); }); @@ -54,7 +54,7 @@ describe('DragDrop', () => { ); - component.find('[data-test-subj="drag-drop"]').simulate('dragstart', { dataTransfer }); + component.find('[data-test-subj="lnsDragDrop"]').simulate('dragstart', { dataTransfer }); jest.runAllTimers(); @@ -78,7 +78,7 @@ describe('DragDrop', () => { ); component - .find('[data-test-subj="drag-drop"]') + .find('[data-test-subj="lnsDragDrop"]') .simulate('drop', { preventDefault, stopPropagation }); expect(preventDefault).toBeCalled(); diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx index 148aaad962e42..47a0cc45c9b19 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -66,10 +66,10 @@ export function DragDrop(props: Props) { const isDragging = draggable && value === dragging; const classSuffix = - ' drag-drop' + - (droppable ? ' drag-drop_is-drop-target' : '') + - (droppable && state.isActive ? ' drag-drop_is-active-drop-target' : '') + - (isDragging ? ' drag-drop_is-dragging' : ''); + ' lnsDragDrop' + + (droppable ? ' lnsDragDrop-isDropTarget' : '') + + (droppable && state.isActive ? ' lnsDragDrop_isActiveDropTarget' : '') + + (isDragging ? ' lnsDragDrop_isDragging' : ''); const dragStart = (e: DroppableEvent) => { // Setting stopPropgagation causes Chrome failures, so @@ -122,7 +122,7 @@ export function DragDrop(props: Props) { return (
Date: Wed, 8 May 2019 11:56:07 -0400 Subject: [PATCH 4/6] A bit of tidying up of the types, etc --- .../lens/public/drag_drop/drag_drop.test.tsx | 18 +++++++++--------- .../lens/public/drag_drop/drag_drop.tsx | 6 +++--- .../lens/public/drag_drop/providers.tsx | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx index 9d488051377b9..9e78c9b48bf2b 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx @@ -23,7 +23,7 @@ describe('DragDrop', () => { }); test('dragover calls preventDefault if droppable is true', () => { - const preventDefault = jest.fn(() => {}); + const preventDefault = jest.fn(); const component = shallow(Hello!); component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault }); @@ -32,7 +32,7 @@ describe('DragDrop', () => { }); test('dragover does not call preventDefault if droppable is false', () => { - const preventDefault = jest.fn(() => {}); + const preventDefault = jest.fn(); const component = shallow(Hello!); component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault }); @@ -41,10 +41,10 @@ describe('DragDrop', () => { }); test('dragstart sets dragging in the context', async () => { - const setDragging = jest.fn(() => {}); + const setDragging = jest.fn(); const dataTransfer = { - setData: jest.fn(() => {}), - getData: jest.fn(() => {}), + setData: jest.fn(), + getData: jest.fn(), }; const value = {}; @@ -63,10 +63,10 @@ describe('DragDrop', () => { }); test('drop resets all the things', async () => { - const preventDefault = jest.fn(() => {}); - const stopPropagation = jest.fn(() => {}); - const setDragging = jest.fn(() => {}); - const onDrop = jest.fn(() => {}); + const preventDefault = jest.fn(); + const stopPropagation = jest.fn(); + const setDragging = jest.fn(); + const onDrop = jest.fn(); const value = {}; const component = mount( diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx index 47a0cc45c9b19..6894abac296da 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -12,7 +12,7 @@ type DroppableEvent = React.DragEvent; /** * A function that handles a drop event. */ -type DropHandler = (item: any) => void; +type DropHandler = (item: unknown) => void; /** * The argument to the DragDrop component. @@ -34,12 +34,12 @@ interface Props { * If this component is dragged, this will be the value of * "dragging" in the root drag/drop context. */ - value?: any; + value?: unknown; /** * The React children. */ - children?: any; + children: React.ReactNode; /** * Indicates whether or not the currently dragged item diff --git a/x-pack/plugins/lens/public/drag_drop/providers.tsx b/x-pack/plugins/lens/public/drag_drop/providers.tsx index 46b295520a1cc..c0b4eb563b32b 100644 --- a/x-pack/plugins/lens/public/drag_drop/providers.tsx +++ b/x-pack/plugins/lens/public/drag_drop/providers.tsx @@ -13,12 +13,12 @@ export interface DragContextState { /** * The item being dragged or undefined. */ - dragging: any; + dragging: unknown; /** * Set the item being dragged. */ - setDragging: (dragging: any) => void; + setDragging: (dragging: unknown) => void; } /** @@ -39,18 +39,18 @@ export interface ProviderProps { * The item being dragged. If unspecified, the provider will * behave as if it is the root provider. */ - dragging: any; + dragging: unknown; /** * Sets the item being dragged. If unspecified, the provider * will behave as if it is the root provider. */ - setDragging: (dragging: any) => void; + setDragging: (dragging: unknown) => void; /** * The React children. */ - children?: any; + children: React.ReactNode; } /** @@ -60,11 +60,11 @@ export interface ProviderProps { * * @param props */ -export function RootDragDropProvider({ children }: { children: any }) { - const [state, setState] = useState<{ dragging: any }>({ +export function RootDragDropProvider({ children }: { children: React.ReactNode }) { + const [state, setState] = useState<{ dragging: unknown }>({ dragging: undefined, }); - const setDragging = (dragging: any) => setState({ dragging }); + const setDragging = (dragging: unknown) => setState({ dragging }); return ( From 6d67617b76e90a07d6fba93987379d11c9fc51e6 Mon Sep 17 00:00:00 2001 From: Christopher Davies Date: Wed, 8 May 2019 14:25:50 -0400 Subject: [PATCH 5/6] Fix class names in the DragDrop component --- x-pack/plugins/lens/public/drag_drop/drag_drop.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx index 6894abac296da..06511b67900d9 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -68,8 +68,8 @@ export function DragDrop(props: Props) { const classSuffix = ' lnsDragDrop' + (droppable ? ' lnsDragDrop-isDropTarget' : '') + - (droppable && state.isActive ? ' lnsDragDrop_isActiveDropTarget' : '') + - (isDragging ? ' lnsDragDrop_isDragging' : ''); + (droppable && state.isActive ? ' lnsDragDrop-isActiveDropTarget' : '') + + (isDragging ? ' lnsDragDrop-isDragging' : ''); const dragStart = (e: DroppableEvent) => { // Setting stopPropgagation causes Chrome failures, so From 269b7db2490371936c96d00b3c4dcccac2d94ccf Mon Sep 17 00:00:00 2001 From: Christopher Davies Date: Thu, 9 May 2019 08:56:56 -0400 Subject: [PATCH 6/6] Use classNames --- .../drag_drop/__snapshots__/drag_drop.test.tsx.snap | 4 ++-- x-pack/plugins/lens/public/drag_drop/drag_drop.tsx | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap index 4aef482ebd216..d18a2db614f55 100644 --- a/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap +++ b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap @@ -2,7 +2,7 @@ exports[`DragDrop droppable is reflected in the className 1`] = `
Hello! @@ -11,7 +11,7 @@ exports[`DragDrop droppable is reflected in the className 1`] = ` exports[`DragDrop renders if nothing is being dragged 1`] = `
diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx index 06511b67900d9..35326a46a6820 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -5,6 +5,7 @@ */ import React, { useState, useContext } from 'react'; +import classNames from 'classnames'; import { DragContext } from './providers'; type DroppableEvent = React.DragEvent; @@ -65,11 +66,11 @@ export function DragDrop(props: Props) { const { className, onDrop, value, children, droppable, draggable } = props; const isDragging = draggable && value === dragging; - const classSuffix = - ' lnsDragDrop' + - (droppable ? ' lnsDragDrop-isDropTarget' : '') + - (droppable && state.isActive ? ' lnsDragDrop-isActiveDropTarget' : '') + - (isDragging ? ' lnsDragDrop-isDragging' : ''); + const classes = classNames('lnsDragDrop', className, { + 'lnsDragDrop-isDropTarget': droppable, + 'lnsDragDrop-isActiveDropTarget': droppable && state.isActive, + 'lnsDragDrop-isDragging': isDragging, + }); const dragStart = (e: DroppableEvent) => { // Setting stopPropgagation causes Chrome failures, so @@ -123,7 +124,7 @@ export function DragDrop(props: Props) { return (