From bfa4f6028865cdf0f433423981028a1479b07aef Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Tue, 29 Aug 2023 20:22:23 +0100 Subject: [PATCH] feat : drag intercept examples --- .../dockview-core/src/api/component.api.ts | 28 ++++++-- .../src/dnd/abstractDragHandler.ts | 30 ++++---- .../docs/sandboxes/dnd-dockview/src/app.tsx | 71 +++++++++++++++++-- 3 files changed, 107 insertions(+), 22 deletions(-) diff --git a/packages/dockview-core/src/api/component.api.ts b/packages/dockview-core/src/api/component.api.ts index 168ad0b9a..6229625ad 100644 --- a/packages/dockview-core/src/api/component.api.ts +++ b/packages/dockview-core/src/api/component.api.ts @@ -38,6 +38,10 @@ import { import { Emitter, Event } from '../events'; import { IDockviewPanel } from '../dockview/dockviewPanel'; import { PaneviewDropEvent } from '../paneview/draggablePaneviewPanel'; +import { + GroupDragEvent, + TabDragEvent, +} from '../dockview/components/titlebar/tabsContainer'; export interface CommonApi { readonly height: number; @@ -118,7 +122,9 @@ export class SplitviewApi implements CommonApi { return this.component.layout(width, height); } - addPanel(options: AddSplitviewComponentOptions): ISplitviewPanel { + addPanel( + options: AddSplitviewComponentOptions + ): ISplitviewPanel { return this.component.addPanel(options); } @@ -213,7 +219,9 @@ export class PaneviewApi implements CommonApi { this.component.layout(width, height); } - addPanel(options: AddPaneviewComponentOptions): IPaneviewPanel { + addPanel( + options: AddPaneviewComponentOptions + ): IPaneviewPanel { return this.component.addPanel(options); } @@ -297,7 +305,9 @@ export class GridviewApi implements CommonApi { this.component.layout(width, height, force); } - addPanel(options: AddComponentOptions): IGridviewPanel { + addPanel( + options: AddComponentOptions + ): IGridviewPanel { return this.component.addPanel(options); } @@ -402,6 +412,14 @@ export class DockviewApi implements CommonApi { return this.component.onDidDrop; } + get onWillDragGroup(): Event { + return this.component.onWillDragGroup; + } + + get onWillDragPanel(): Event { + return this.component.onWillDragPanel; + } + get panels(): IDockviewPanel[] { return this.component.panels; } @@ -432,7 +450,9 @@ export class DockviewApi implements CommonApi { this.component.layout(width, height, force); } - addPanel(options: AddPanelOptions): IDockviewPanel { + addPanel( + options: AddPanelOptions + ): IDockviewPanel { return this.component.addPanel(options); } diff --git a/packages/dockview-core/src/dnd/abstractDragHandler.ts b/packages/dockview-core/src/dnd/abstractDragHandler.ts index 22426e2a6..306ab236e 100644 --- a/packages/dockview-core/src/dnd/abstractDragHandler.ts +++ b/packages/dockview-core/src/dnd/abstractDragHandler.ts @@ -66,19 +66,23 @@ export abstract class DragHandler extends CompositeDisposable { if (event.dataTransfer) { event.dataTransfer.effectAllowed = 'move'; - /** - * Although this is not used by dockview many third party dnd libraries will check - * dataTransfer.types to determine valid drag events. - * - * For example: in react-dnd if dataTransfer.types is not set then the dragStart event will be cancelled - * through .preventDefault(). Since this is applied globally to all drag events this would break dockviews - * dnd logic. You can see the code at - * https://github.com/react-dnd/react-dnd/blob/main/packages/backend-html5/src/HTML5BackendImpl.ts#L542 - */ - event.dataTransfer.setData( - 'text/plain', - '__dockview_internal_drag_event__' - ); + const hasData = event.dataTransfer.items.length > 0; + + if (!hasData) { + /** + * Although this is not used by dockview many third party dnd libraries will check + * dataTransfer.types to determine valid drag events. + * + * For example: in react-dnd if dataTransfer.types is not set then the dragStart event will be cancelled + * through .preventDefault(). Since this is applied globally to all drag events this would break dockviews + * dnd logic. You can see the code at + * https://github.com/react-dnd/react-dnd/blob/main/packages/backend-html5/src/HTML5BackendImpl.ts#L542 + */ + event.dataTransfer.setData( + 'text/plain', + '__dockview_internal_drag_event__' + ); + } } }), addDisposableListener(this.el, 'dragend', () => { diff --git a/packages/docs/sandboxes/dnd-dockview/src/app.tsx b/packages/docs/sandboxes/dnd-dockview/src/app.tsx index 7a4f97f1a..655fa176f 100644 --- a/packages/docs/sandboxes/dnd-dockview/src/app.tsx +++ b/packages/docs/sandboxes/dnd-dockview/src/app.tsx @@ -1,4 +1,5 @@ import { + DockviewApi, DockviewDndOverlayEvent, DockviewDropEvent, DockviewReact, @@ -42,8 +43,14 @@ const DraggableElement = () => ( ); const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => { - const onReady = (event: DockviewReadyEvent) => { - event.api.addPanel({ + const [api, setApi] = React.useState(); + + React.useEffect(() => { + if (!api) { + return; + } + + api.addPanel({ id: 'panel_1', component: 'default', params: { @@ -51,7 +58,7 @@ const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => { }, }); - event.api.addPanel({ + api.addPanel({ id: 'panel_2', component: 'default', params: { @@ -59,7 +66,7 @@ const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => { }, }); - event.api.addPanel({ + api.addPanel({ id: 'panel_3', component: 'default', params: { @@ -67,7 +74,7 @@ const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => { }, }); - event.api.addPanel({ + api.addPanel({ id: 'panel_4', component: 'default', params: { @@ -75,6 +82,45 @@ const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => { }, position: { referencePanel: 'panel_1', direction: 'right' }, }); + + const panelDragDisposable = api.onWillDragPanel((event) => { + const dataTransfer = event.nativeEvent.dataTransfer; + + if (dataTransfer) { + dataTransfer.setData( + 'text/plain', + 'Some custom panel data transfer data' + ); + dataTransfer.setData( + 'text/json', + '{text: "Some custom panel data transfer data"}' + ); + } + }); + + const groupDragDisposable = api.onWillDragGroup((event) => { + const dataTransfer = event.nativeEvent.dataTransfer; + + if (dataTransfer) { + dataTransfer.setData( + 'text/plain', + 'Some custom group data transfer data' + ); + dataTransfer.setData( + 'text/json', + '{text: "Some custom group data transfer data"}' + ); + } + }); + + return () => { + panelDragDisposable.dispose(); + groupDragDisposable.dispose(); + }; + }, [api]); + + const onReady = (event: DockviewReadyEvent) => { + setApi(event.api); }; const onDidDrop = (event: DockviewDropEvent) => { @@ -92,6 +138,20 @@ const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => { return true; }; + const onDrop = (event: React.DragEvent) => { + const dataTransfer = event.dataTransfer; + + let text = 'The following dataTransfer data was found:\n'; + + for (let i = 0; i < dataTransfer.items.length; i++) { + const item = dataTransfer.items[i]; + const value = dataTransfer.getData(item.type); + text += `type=${item.type},data=${value}\n`; + } + + alert(text); + }; + return (
{ >
+
Inspect Data Transfer