From e6cae5f90d06b494d0ffb0a1d218a49a41870174 Mon Sep 17 00:00:00 2001 From: Matthew Pearson Date: Sat, 13 May 2023 14:23:29 -0700 Subject: [PATCH 01/14] added an optional type parameter for addPanel() so the `params` prop can be strictly typed --- .../src/__tests__/gridview/baseComponentGridview.spec.ts | 2 +- .../__tests__/groupview/dockviewGroupPanelModel.spec.ts | 6 +++--- packages/dockview-core/src/api/component.api.ts | 3 ++- packages/dockview-core/src/dockview/dockviewComponent.ts | 9 +++++---- packages/dockview-core/src/dockview/dockviewPanel.ts | 2 +- packages/dockview-core/src/dockview/options.ts | 9 +++++---- packages/dockview-core/src/gridview/basePanelView.ts | 7 ++++--- packages/dockview/src/react.ts | 4 ++-- packages/dockview/src/types.ts | 3 ++- 9 files changed, 25 insertions(+), 20 deletions(-) diff --git a/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts b/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts index 27e8925b1..c0d1a9754 100644 --- a/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts +++ b/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts @@ -21,7 +21,7 @@ class TestPanel implements IGridPanelView { return true; } - get params(): Record { + get params(): Parameters { return {}; } diff --git a/packages/dockview-core/src/__tests__/groupview/dockviewGroupPanelModel.spec.ts b/packages/dockview-core/src/__tests__/groupview/dockviewGroupPanelModel.spec.ts index b00522d05..3cd48758c 100644 --- a/packages/dockview-core/src/__tests__/groupview/dockviewGroupPanelModel.spec.ts +++ b/packages/dockview-core/src/__tests__/groupview/dockviewGroupPanelModel.spec.ts @@ -1,4 +1,4 @@ -import { DockviewComponent } from '../../dockview/dockviewComponent'; +import {DockviewComponent} from '../../dockview/dockviewComponent'; import { GroupPanelUpdateEvent, GroupviewPanelState, @@ -8,7 +8,7 @@ import { ITabRenderer, IWatermarkRenderer, } from '../../dockview/types'; -import { PanelUpdateEvent } from '../../panel/types'; +import { PanelUpdateEvent, Parameters } from '../../panel/types'; import { DockviewGroupPanelModel, GroupOptions, @@ -179,7 +179,7 @@ export class TestPanel implements IDockviewPanel { return this._group!; } - get params(): Record { + get params(): Parameters { return {}; } diff --git a/packages/dockview-core/src/api/component.api.ts b/packages/dockview-core/src/api/component.api.ts index d527ef6af..46d841f4a 100644 --- a/packages/dockview-core/src/api/component.api.ts +++ b/packages/dockview-core/src/api/component.api.ts @@ -8,6 +8,7 @@ import { AddPanelOptions, MovementOptions, } from '../dockview/options'; +import { Parameters } from '../panel/types'; import { Direction } from '../gridview/baseComponentGridview'; import { AddComponentOptions, @@ -431,7 +432,7 @@ 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/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 6d58c0b67..de75ca415 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -28,6 +28,7 @@ import { isPanelOptionsWithPanel, MovementOptions, } from './options'; +import { Parameters } from '../panel/types'; import { BaseGrid, Direction, @@ -96,7 +97,7 @@ export interface IDockviewComponent extends IBaseGrid { doSetGroupActive: (group: DockviewGroupPanel, skipFocus?: boolean) => void; removeGroup: (group: DockviewGroupPanel) => void; options: DockviewComponentOptions; - addPanel(options: AddPanelOptions): IDockviewPanel; + addPanel

(options: AddPanelOptions

): IDockviewPanel; removePanel(panel: IDockviewPanel): void; getGroupPanel: (id: string) => IDockviewPanel | undefined; createWatermarkComponent(): IWatermarkRenderer; @@ -495,7 +496,7 @@ export class DockviewComponent } } - addPanel(options: AddPanelOptions): IDockviewPanel { + addPanel

(options: AddPanelOptions

): IDockviewPanel { if (this.panels.find((_) => _.id === options.id)) { throw new Error(`panel with id ${options.id} already exists`); } @@ -907,8 +908,8 @@ export class DockviewComponent return view; } - private createPanel( - options: AddPanelOptions, + private createPanel

( + options: AddPanelOptions

, group: DockviewGroupPanel ): IDockviewPanel { const contentComponent = options.component; diff --git a/packages/dockview-core/src/dockview/dockviewPanel.ts b/packages/dockview-core/src/dockview/dockviewPanel.ts index 66ac5be5f..b13f8d5b6 100644 --- a/packages/dockview-core/src/dockview/dockviewPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewPanel.ts @@ -19,7 +19,7 @@ export interface IDockviewPanel extends IDisposable, IPanel { readonly group: DockviewGroupPanel; readonly api: DockviewPanelApi; readonly title: string; - readonly params: Record | undefined; + readonly params: Parameters | undefined; updateParentGroup(group: DockviewGroupPanel, isGroupActive: boolean): void; init(params: IGroupPanelInitParameters): void; toJSON(): GroupviewPanelState; diff --git a/packages/dockview-core/src/dockview/options.ts b/packages/dockview-core/src/dockview/options.ts index 1e9b66db1..091d26a3f 100644 --- a/packages/dockview-core/src/dockview/options.ts +++ b/packages/dockview-core/src/dockview/options.ts @@ -8,6 +8,7 @@ import { IWatermarkRenderer, DockviewDropTargets, } from './types'; +import { Parameters } from '../panel/types'; import { DockviewGroupPanel, DockviewGroupPanelApi, @@ -86,10 +87,10 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions { parentElement?: HTMLElement; } -export interface PanelOptions { +export interface PanelOptions

{ component: string; tabComponent?: string; - params?: { [key: string]: any }; + params?: P; id: string; title?: string; } @@ -131,8 +132,8 @@ export function isPanelOptionsWithGroup( return false; } -export interface AddPanelOptions - extends Omit { +export interface AddPanelOptions

+ extends Omit, 'component' | 'tabComponent'> { component: string; tabComponent?: string; position?: AddPanelPositionOptions; diff --git a/packages/dockview-core/src/gridview/basePanelView.ts b/packages/dockview-core/src/gridview/basePanelView.ts index 375b37a47..31c7b920c 100644 --- a/packages/dockview-core/src/gridview/basePanelView.ts +++ b/packages/dockview-core/src/gridview/basePanelView.ts @@ -5,13 +5,14 @@ import { PanelUpdateEvent, PanelInitParameters, IPanel, + Parameters, } from '../panel/types'; import { PanelApi, PanelApiImpl } from '../api/panelApi'; export interface BasePanelViewState { readonly id: string; readonly component: string; - readonly params?: Record; + readonly params?: Parameters; } export interface BasePanelViewExported { @@ -19,7 +20,7 @@ export interface BasePanelViewExported { readonly api: T; readonly width: number; readonly height: number; - readonly params: Record | undefined; + readonly params: Parameters | undefined; focus(): void; toJSON(): object; update(event: PanelUpdateEvent): void; @@ -50,7 +51,7 @@ export abstract class BasePanelView return this._height; } - get params(): Record | undefined { + get params(): Parameters | undefined { return this._params?.params; } diff --git a/packages/dockview/src/react.ts b/packages/dockview/src/react.ts index 9d78ba4c1..59299f22e 100644 --- a/packages/dockview/src/react.ts +++ b/packages/dockview/src/react.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import { IFrameworkPart, IDockviewDisposable } from 'dockview-core'; +import { IFrameworkPart, IDockviewDisposable, Parameters } from 'dockview-core'; export interface ReactPortalStore { addPortal: (portal: React.ReactPortal) => IDockviewDisposable; @@ -66,7 +66,7 @@ export const ReactPartContext = React.createContext<{}>({}); export class ReactPart

implements IFrameworkPart { - private _initialProps: Record = {}; + private _initialProps: Parameters = {}; private componentInstance?: IPanelWrapperRef; private ref?: { portal: React.ReactPortal; diff --git a/packages/dockview/src/types.ts b/packages/dockview/src/types.ts index d5b7b07a3..0028f3568 100644 --- a/packages/dockview/src/types.ts +++ b/packages/dockview/src/types.ts @@ -1,9 +1,10 @@ import * as React from 'react'; +import { Parameters } from 'dockview-core'; export interface PanelCollection { [name: string]: React.FunctionComponent; } -export interface PanelParameters> { +export interface PanelParameters { params: T; } From 6665c61a95b2bc10d3e1cc2a5566bdb81036486b Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Tue, 13 Jun 2023 20:08:03 +0100 Subject: [PATCH 02/14] feat: addPanel generics --- packages/dockview-core/src/api/component.api.ts | 8 ++++---- .../src/dockview/dockviewComponent.ts | 14 +++++++++----- .../dockview-core/src/dockview/dockviewPanel.ts | 2 +- .../src/gridview/gridviewComponent.ts | 13 +++++++++---- packages/dockview-core/src/panel/types.ts | 4 ++-- .../src/paneview/paneviewComponent.ts | 15 +++++++++------ .../src/splitview/splitviewComponent.ts | 13 +++++++++---- 7 files changed, 43 insertions(+), 26 deletions(-) diff --git a/packages/dockview-core/src/api/component.api.ts b/packages/dockview-core/src/api/component.api.ts index 46d841f4a..dc8b89f82 100644 --- a/packages/dockview-core/src/api/component.api.ts +++ b/packages/dockview-core/src/api/component.api.ts @@ -118,7 +118,7 @@ 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 +213,7 @@ 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 +297,7 @@ export class GridviewApi implements CommonApi { this.component.layout(width, height, force); } - addPanel(options: AddComponentOptions): IGridviewPanel { + addPanel(options: AddComponentOptions): IGridviewPanel { return this.component.addPanel(options); } @@ -432,7 +432,7 @@ 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/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 804abdac0..de0f1bd14 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -28,7 +28,6 @@ import { isPanelOptionsWithPanel, MovementOptions, } from './options'; -import { Parameters } from '../panel/types'; import { BaseGrid, Direction, @@ -45,6 +44,7 @@ import { import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel'; import { DockviewPanelModel } from './dockviewPanelModel'; import { getPanelData } from '../dnd/dataTransfer'; +import { Parameters } from '../panel/types'; export interface PanelReference { update: (event: { params: { [key: string]: any } }) => void; @@ -97,7 +97,9 @@ export interface IDockviewComponent extends IBaseGrid { doSetGroupActive: (group: DockviewGroupPanel, skipFocus?: boolean) => void; removeGroup: (group: DockviewGroupPanel) => void; options: DockviewComponentOptions; - addPanel

(options: AddPanelOptions

): IDockviewPanel; + addPanel( + options: AddPanelOptions + ): IDockviewPanel; removePanel(panel: IDockviewPanel): void; getGroupPanel: (id: string) => IDockviewPanel | undefined; createWatermarkComponent(): IWatermarkRenderer; @@ -496,7 +498,9 @@ export class DockviewComponent } } - addPanel

(options: AddPanelOptions

): IDockviewPanel { + addPanel( + options: AddPanelOptions + ): IDockviewPanel { if (this.panels.find((_) => _.id === options.id)) { throw new Error(`panel with id ${options.id} already exists`); } @@ -914,8 +918,8 @@ export class DockviewComponent return view; } - private createPanel

( - options: AddPanelOptions

, + private createPanel( + options: AddPanelOptions, group: DockviewGroupPanel ): IDockviewPanel { const contentComponent = options.component; diff --git a/packages/dockview-core/src/dockview/dockviewPanel.ts b/packages/dockview-core/src/dockview/dockviewPanel.ts index 01a8bd487..9245949fb 100644 --- a/packages/dockview-core/src/dockview/dockviewPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewPanel.ts @@ -14,7 +14,7 @@ export interface IDockviewPanel extends IDisposable, IPanel { readonly view: IDockviewPanelModel; readonly group: DockviewGroupPanel; readonly api: DockviewPanelApi; - readonly title: string; + readonly title: string | undefined; readonly params: Parameters | undefined; updateParentGroup(group: DockviewGroupPanel, isGroupActive: boolean): void; init(params: IGroupPanelInitParameters): void; diff --git a/packages/dockview-core/src/gridview/gridviewComponent.ts b/packages/dockview-core/src/gridview/gridviewComponent.ts index b216cd8a9..2b63e761c 100644 --- a/packages/dockview-core/src/gridview/gridviewComponent.ts +++ b/packages/dockview-core/src/gridview/gridviewComponent.ts @@ -21,7 +21,7 @@ import { GridPanelViewState, IGridviewPanel, } from './gridviewPanel'; -import { BaseComponentOptions } from '../panel/types'; +import { BaseComponentOptions, Parameters } from '../panel/types'; import { Orientation, Sizing } from '../splitview/splitview'; import { createComponent } from '../panel/componentFactory'; import { Emitter, Event } from '../events'; @@ -32,7 +32,8 @@ export interface SerializedGridviewComponent { activePanel?: string; } -export interface AddComponentOptions extends BaseComponentOptions { +export interface AddComponentOptions + extends BaseComponentOptions { minimumWidth?: number; maximumWidth?: number; minimumHeight?: number; @@ -57,7 +58,9 @@ export interface IGridviewComponent extends IBaseGrid { readonly orientation: Orientation; readonly onDidLayoutFromJSON: Event; updateOptions(options: Partial): void; - addPanel(options: AddComponentOptions): IGridviewPanel; + addPanel( + options: AddComponentOptions + ): IGridviewPanel; removePanel(panel: IGridviewPanel, sizing?: Sizing): void; focus(): void; fromJSON(serializedGridview: SerializedGridviewComponent): void; @@ -276,7 +279,9 @@ export class GridviewComponent this.doAddGroup(removedPanel, relativeLocation, options.size); } - public addPanel(options: AddComponentOptions): IGridviewPanel { + public addPanel( + options: AddComponentOptions + ): IGridviewPanel { let relativeLocation: number[] = options.location || [0]; if (options.position?.referencePanel) { diff --git a/packages/dockview-core/src/panel/types.ts b/packages/dockview-core/src/panel/types.ts index 98905e110..133e39a3b 100644 --- a/packages/dockview-core/src/panel/types.ts +++ b/packages/dockview-core/src/panel/types.ts @@ -29,10 +29,10 @@ export interface IFrameworkPart extends IDisposable { update(params: Parameters): void; } -export interface BaseComponentOptions { +export interface BaseComponentOptions { id: string; component: string; - params?: Parameters; + params?: T; snap?: boolean; priority?: LayoutPriority; size?: number; diff --git a/packages/dockview-core/src/paneview/paneviewComponent.ts b/packages/dockview-core/src/paneview/paneviewComponent.ts index 290316eb0..3aca60699 100644 --- a/packages/dockview-core/src/paneview/paneviewComponent.ts +++ b/packages/dockview-core/src/paneview/paneviewComponent.ts @@ -23,6 +23,7 @@ import { DefaultHeader } from './defaultPaneviewHeader'; import { sequentialNumberGenerator } from '../math'; import { PaneTransfer } from '../dnd/dataTransfer'; import { Resizable } from '../resizable'; +import { Parameters } from '../panel/types'; const nextLayoutId = sequentialNumberGenerator(); @@ -87,13 +88,11 @@ export class PaneFramework extends DraggablePaneviewPanel { } } -export interface AddPaneviewComponentOptions { +export interface AddPaneviewComponentOptions { id: string; component: string; headerComponent?: string; - params?: { - [key: string]: any; - }; + params?: T; minimumBodySize?: number; maximumBodySize?: number; isExpanded?: boolean; @@ -115,7 +114,9 @@ export interface IPaneviewComponent extends IDisposable { readonly onDidDrop: Event; readonly onDidLayoutChange: Event; readonly onDidLayoutFromJSON: Event; - addPanel(options: AddPaneviewComponentOptions): IPaneviewPanel; + addPanel( + options: AddPaneviewComponentOptions + ): IPaneviewPanel; layout(width: number, height: number): void; toJSON(): SerializedPaneview; fromJSON(serializedPaneview: SerializedPaneview): void; @@ -233,7 +234,9 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent { this._options = { ...this.options, ...options }; } - addPanel(options: AddPaneviewComponentOptions): IPaneviewPanel { + addPanel( + options: AddPaneviewComponentOptions + ): IPaneviewPanel { const body = createComponent( options.id, options.component, diff --git a/packages/dockview-core/src/splitview/splitviewComponent.ts b/packages/dockview-core/src/splitview/splitviewComponent.ts index 37573c40e..82d3b1862 100644 --- a/packages/dockview-core/src/splitview/splitviewComponent.ts +++ b/packages/dockview-core/src/splitview/splitviewComponent.ts @@ -11,7 +11,7 @@ import { Splitview, } from './splitview'; import { SplitviewComponentOptions } from './options'; -import { BaseComponentOptions } from '../panel/types'; +import { BaseComponentOptions, Parameters } from '../panel/types'; import { Emitter, Event } from '../events'; import { SplitviewPanel, ISplitviewPanel } from './splitviewPanel'; import { createComponent } from '../panel/componentFactory'; @@ -39,7 +39,8 @@ export interface SerializedSplitview { views: SerializedSplitviewPanel[]; } -export interface AddSplitviewComponentOptions extends BaseComponentOptions { +export interface AddSplitviewComponentOptions + extends BaseComponentOptions { index?: number; minimumSize?: number; maximumSize?: number; @@ -62,7 +63,9 @@ export interface ISplitviewComponent extends IDisposable { readonly onDidLayoutFromJSON: Event; readonly panels: SplitviewPanel[]; updateOptions(options: Partial): void; - addPanel(options: AddSplitviewComponentOptions): ISplitviewPanel; + addPanel( + options: AddSplitviewComponentOptions + ): ISplitviewPanel; layout(width: number, height: number): void; onDidLayoutChange: Event; toJSON(): SerializedSplitview; @@ -248,7 +251,9 @@ export class SplitviewComponent return this.panels.find((view) => view.id === id); } - addPanel(options: AddSplitviewComponentOptions): SplitviewPanel { + addPanel( + options: AddSplitviewComponentOptions + ): SplitviewPanel { if (this._panels.has(options.id)) { throw new Error(`panel ${options.id} already exists`); } From a8e243b3fdaf91120373cd2ce40baab0e1fb5e8d Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:13:56 +0100 Subject: [PATCH 03/14] bug: external-dnd event regression external-dnd events should not trigger the top-level center drop target --- .../dockview/dockviewComponent.spec.ts | 137 ++++++++++++++++++ .../src/dockview/dockviewComponent.ts | 9 ++ 2 files changed, 146 insertions(+) diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index 847372d8e..e6eb16d08 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -1,5 +1,6 @@ import { DockviewComponent } from '../../dockview/dockviewComponent'; import { + DockviewDropTargets, GroupPanelPartInitParameters, IContentRenderer, ITabRenderer, @@ -10,6 +11,8 @@ import { CompositeDisposable } from '../../lifecycle'; import { Emitter } from '../../events'; import { IDockviewPanel } from '../../dockview/dockviewPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; +import { fireEvent } from '@testing-library/dom'; +import { getPanelData } from '../../dnd/dataTransfer'; class PanelContentPartTest implements IContentRenderer { element: HTMLElement = document.createElement('div'); @@ -3820,4 +3823,138 @@ describe('dockviewComponent', () => { expect(el.style.height).toBe('123px'); expect(el.style.width).toBe('256px'); }); + + test('that external dnd events do not trigger the top-level center dnd target', () => { + const container = document.createElement('div'); + + const showDndOverlay = jest.fn().mockReturnValue(true); + + const dockview = new DockviewComponent({ + parentElement: container, + components: { + default: PanelContentPartTest, + }, + tabComponents: { + test_tab_id: PanelTabPartTest, + }, + orientation: Orientation.HORIZONTAL, + showDndOverlay: showDndOverlay, + }); + + dockview.layout(1000, 500); + + const panel1 = dockview.addPanel({ + id: 'panel_1', + component: 'default', + }); + dockview.addPanel({ + id: 'panel_2', + component: 'default', + position: { direction: 'right' }, + }); + + Object.defineProperty(dockview.element, 'clientWidth', { + get: () => 100, + }); + Object.defineProperty(dockview.element, 'clientHeight', { + get: () => 100, + }); + + jest.spyOn(dockview.element, 'getBoundingClientRect').mockReturnValue({ + left: 0, + top: 0, + width: 100, + height: 100, + } as any); + + // left + + const eventLeft = new KeyboardEvent('dragover'); + Object.defineProperty(eventLeft, 'clientX', { + get: () => 0, + }); + Object.defineProperty(eventLeft, 'clientY', { + get: () => 0, + }); + fireEvent(dockview.element, eventLeft); + + expect(showDndOverlay).toHaveBeenCalledWith({ + nativeEvent: eventLeft, + position: 'left', + target: DockviewDropTargets.Edge, + getData: getPanelData, + }); + expect(showDndOverlay).toBeCalledTimes(1); + + // right + + const eventRight = new KeyboardEvent('dragover'); + Object.defineProperty(eventRight, 'clientX', { + get: () => 100, + }); + Object.defineProperty(eventRight, 'clientY', { + get: () => 100, + }); + fireEvent(dockview.element, eventRight); + + expect(showDndOverlay).toHaveBeenCalledWith({ + nativeEvent: eventRight, + position: 'right', + target: DockviewDropTargets.Edge, + getData: getPanelData, + }); + expect(showDndOverlay).toBeCalledTimes(2); + + // top + + const eventTop = new KeyboardEvent('dragover'); + Object.defineProperty(eventTop, 'clientX', { + get: () => 50, + }); + Object.defineProperty(eventTop, 'clientY', { + get: () => 0, + }); + fireEvent(dockview.element, eventTop); + + expect(showDndOverlay).toHaveBeenCalledWith({ + nativeEvent: eventTop, + position: 'top', + target: DockviewDropTargets.Edge, + getData: getPanelData, + }); + expect(showDndOverlay).toBeCalledTimes(3); + + // top + + const eventBottom = new KeyboardEvent('dragover'); + Object.defineProperty(eventBottom, 'clientX', { + get: () => 50, + }); + Object.defineProperty(eventBottom, 'clientY', { + get: () => 100, + }); + fireEvent(dockview.element, eventBottom); + + expect(showDndOverlay).toHaveBeenCalledWith({ + nativeEvent: eventBottom, + position: 'bottom', + target: DockviewDropTargets.Edge, + getData: getPanelData, + }); + expect(showDndOverlay).toBeCalledTimes(4); + + // center + + const eventCenter = new KeyboardEvent('dragover'); + Object.defineProperty(eventCenter, 'clientX', { + get: () => 50, + }); + Object.defineProperty(eventCenter, 'clientY', { + get: () => 50, + }); + fireEvent(dockview.element, eventCenter); + + // expect not to be called for center + expect(showDndOverlay).toBeCalledTimes(4); + }); }); diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 21e579895..5fb066f7e 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -260,6 +260,15 @@ export class DockviewComponent } if (this.options.showDndOverlay) { + if (position === 'center') { + /** + * for external events only show the four-corner drag overlays, disable + * the center position so that external drag events can fall through to the group + * and panel drop target handlers + */ + return false; + } + return this.options.showDndOverlay({ nativeEvent: event, position: position, From b36fd3f312a0465570136bd99f7deeb5e8fa7d53 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:23:27 +0100 Subject: [PATCH 04/14] chore: v1.8.1 docs --- packages/docs/blog/2023-07-24-dockview-1.8.1.md | 17 +++++++++++++++++ .../components/_category_.json | 0 .../components/dockview.mdx | 0 .../components/gridview.mdx | 0 .../components/paneview.mdx | 0 .../components/splitview.mdx | 0 .../contributing.mdx | 0 .../{version-1.8.0 => version-1.8.1}/index.mdx | 0 .../{version-1.8.0 => version-1.8.1}/theme.mdx | 0 ...idebars.json => version-1.8.1-sidebars.json} | 0 packages/docs/versions.json | 4 ++-- 11 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 packages/docs/blog/2023-07-24-dockview-1.8.1.md rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/components/_category_.json (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/components/dockview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/components/gridview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/components/paneview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/components/splitview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/contributing.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/index.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.0 => version-1.8.1}/theme.mdx (100%) rename packages/docs/versioned_sidebars/{version-1.8.0-sidebars.json => version-1.8.1-sidebars.json} (100%) diff --git a/packages/docs/blog/2023-07-24-dockview-1.8.1.md b/packages/docs/blog/2023-07-24-dockview-1.8.1.md new file mode 100644 index 000000000..b6d7dafd1 --- /dev/null +++ b/packages/docs/blog/2023-07-24-dockview-1.8.1.md @@ -0,0 +1,17 @@ +--- +slug: dockview-1.8.1-release +title: Dockview 1.8.1 +tags: [release] +--- + +# Release Notes + +Please reference to docs @ [dockview.dev](https://dockview.dev). + +## 🚀 Features + +## 🛠 Miscs + +- Fix regression related to external dnd events [#311](https://github.com/mathuo/dockview/issues/311) + +## 🔥 Breaking changes diff --git a/packages/docs/versioned_docs/version-1.8.0/components/_category_.json b/packages/docs/versioned_docs/version-1.8.1/components/_category_.json similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/components/_category_.json rename to packages/docs/versioned_docs/version-1.8.1/components/_category_.json diff --git a/packages/docs/versioned_docs/version-1.8.0/components/dockview.mdx b/packages/docs/versioned_docs/version-1.8.1/components/dockview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/components/dockview.mdx rename to packages/docs/versioned_docs/version-1.8.1/components/dockview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.0/components/gridview.mdx b/packages/docs/versioned_docs/version-1.8.1/components/gridview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/components/gridview.mdx rename to packages/docs/versioned_docs/version-1.8.1/components/gridview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.0/components/paneview.mdx b/packages/docs/versioned_docs/version-1.8.1/components/paneview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/components/paneview.mdx rename to packages/docs/versioned_docs/version-1.8.1/components/paneview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.0/components/splitview.mdx b/packages/docs/versioned_docs/version-1.8.1/components/splitview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/components/splitview.mdx rename to packages/docs/versioned_docs/version-1.8.1/components/splitview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.0/contributing.mdx b/packages/docs/versioned_docs/version-1.8.1/contributing.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/contributing.mdx rename to packages/docs/versioned_docs/version-1.8.1/contributing.mdx diff --git a/packages/docs/versioned_docs/version-1.8.0/index.mdx b/packages/docs/versioned_docs/version-1.8.1/index.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/index.mdx rename to packages/docs/versioned_docs/version-1.8.1/index.mdx diff --git a/packages/docs/versioned_docs/version-1.8.0/theme.mdx b/packages/docs/versioned_docs/version-1.8.1/theme.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.0/theme.mdx rename to packages/docs/versioned_docs/version-1.8.1/theme.mdx diff --git a/packages/docs/versioned_sidebars/version-1.8.0-sidebars.json b/packages/docs/versioned_sidebars/version-1.8.1-sidebars.json similarity index 100% rename from packages/docs/versioned_sidebars/version-1.8.0-sidebars.json rename to packages/docs/versioned_sidebars/version-1.8.1-sidebars.json diff --git a/packages/docs/versions.json b/packages/docs/versions.json index 121848cb7..94df55eee 100644 --- a/packages/docs/versions.json +++ b/packages/docs/versions.json @@ -1,4 +1,4 @@ [ - "1.8.0", + "1.8.1", "1.7.6" -] +] \ No newline at end of file From 175e8caa67bb320adf739da0aa48f78a9dd3a9f8 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:30:50 +0100 Subject: [PATCH 05/14] chore(release): publish v1.8.1 --- lerna.json | 2 +- packages/dockview-core/package.json | 2 +- packages/dockview/package.json | 4 ++-- packages/docs/package.json | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lerna.json b/lerna.json index b885be29f..420562cf2 100644 --- a/lerna.json +++ b/lerna.json @@ -3,7 +3,7 @@ "packages/*" ], "useWorkspaces": true, - "version": "1.8.0", + "version": "1.8.1", "npmClient": "yarn", "command": { "publish": { diff --git a/packages/dockview-core/package.json b/packages/dockview-core/package.json index f36c90e51..041702e31 100644 --- a/packages/dockview-core/package.json +++ b/packages/dockview-core/package.json @@ -1,6 +1,6 @@ { "name": "dockview-core", - "version": "1.8.0", + "version": "1.8.1", "description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support", "main": "./dist/cjs/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/packages/dockview/package.json b/packages/dockview/package.json index a769f4503..7c41a3264 100644 --- a/packages/dockview/package.json +++ b/packages/dockview/package.json @@ -1,6 +1,6 @@ { "name": "dockview", - "version": "1.8.0", + "version": "1.8.1", "description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support", "main": "./dist/cjs/index.js", "types": "./dist/cjs/index.d.ts", @@ -56,7 +56,7 @@ "author": "https://github.com/mathuo", "license": "MIT", "dependencies": { - "dockview-core": "^1.8.0" + "dockview-core": "^1.8.1" }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.0.1", diff --git a/packages/docs/package.json b/packages/docs/package.json index dcde976d7..5d0e2cd2c 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "dockview-docs", - "version": "1.8.0", + "version": "1.8.1", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -22,7 +22,7 @@ "@minoru/react-dnd-treeview": "^3.4.3", "axios": "^1.3.3", "clsx": "^1.2.1", - "dockview": "^1.8.0", + "dockview": "^1.8.1", "prism-react-renderer": "^1.3.5", "react": "^18.2.0", "react-dnd": "^16.0.1", From 3ab3467547c3b7f73ac62c523d68c28585e5bbf4 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:49:56 +0100 Subject: [PATCH 06/14] feat: external-dnd center drop when dockview is empty --- .../dockview/dockviewComponent.spec.ts | 26 +++++++++++++++++-- .../src/dockview/dockviewComponent.ts | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index e6eb16d08..65ead5491 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -3824,7 +3824,7 @@ describe('dockviewComponent', () => { expect(el.style.width).toBe('256px'); }); - test('that external dnd events do not trigger the top-level center dnd target', () => { + test('that external dnd events do not trigger the top-level center dnd target unless empty', () => { const container = document.createElement('div'); const showDndOverlay = jest.fn().mockReturnValue(true); @@ -3847,7 +3847,7 @@ describe('dockviewComponent', () => { id: 'panel_1', component: 'default', }); - dockview.addPanel({ + const panel2 = dockview.addPanel({ id: 'panel_2', component: 'default', position: { direction: 'right' }, @@ -3956,5 +3956,27 @@ describe('dockviewComponent', () => { // expect not to be called for center expect(showDndOverlay).toBeCalledTimes(4); + + dockview.removePanel(panel1); + dockview.removePanel(panel2); + + // center, but empty + + const eventCenter2 = new KeyboardEvent('dragover'); + Object.defineProperty(eventCenter2, 'clientX', { + get: () => 50, + }); + Object.defineProperty(eventCenter2, 'clientY', { + get: () => 50, + }); + fireEvent(dockview.element, eventCenter2); + + expect(showDndOverlay).toHaveBeenCalledWith({ + nativeEvent: eventTop, + position: 'center', + target: DockviewDropTargets.Edge, + getData: getPanelData, + }); + expect(showDndOverlay).toBeCalledTimes(5); }); }); diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 5fb066f7e..166755ccb 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -260,7 +260,7 @@ export class DockviewComponent } if (this.options.showDndOverlay) { - if (position === 'center') { + if (position === 'center' && this.gridview.length !== 0) { /** * for external events only show the four-corner drag overlays, disable * the center position so that external drag events can fall through to the group From 8ae5a9fc9467fbe9ff25070f1b1d03f60203ea74 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Mon, 24 Jul 2023 21:01:55 +0100 Subject: [PATCH 07/14] chore: v1.8.2 docs --- ...3-07-24-dockview-1.8.1.md => 2023-07-24-dockview-1.8.2.md} | 4 ++-- .../components/_category_.json | 0 .../{version-1.8.1 => version-1.8.2}/components/dockview.mdx | 0 .../{version-1.8.1 => version-1.8.2}/components/gridview.mdx | 0 .../{version-1.8.1 => version-1.8.2}/components/paneview.mdx | 0 .../{version-1.8.1 => version-1.8.2}/components/splitview.mdx | 0 .../{version-1.8.1 => version-1.8.2}/contributing.mdx | 0 .../versioned_docs/{version-1.8.1 => version-1.8.2}/index.mdx | 0 .../versioned_docs/{version-1.8.1 => version-1.8.2}/theme.mdx | 0 ...ersion-1.8.1-sidebars.json => version-1.8.2-sidebars.json} | 0 packages/docs/versions.json | 2 +- 11 files changed, 3 insertions(+), 3 deletions(-) rename packages/docs/blog/{2023-07-24-dockview-1.8.1.md => 2023-07-24-dockview-1.8.2.md} (84%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/components/_category_.json (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/components/dockview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/components/gridview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/components/paneview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/components/splitview.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/contributing.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/index.mdx (100%) rename packages/docs/versioned_docs/{version-1.8.1 => version-1.8.2}/theme.mdx (100%) rename packages/docs/versioned_sidebars/{version-1.8.1-sidebars.json => version-1.8.2-sidebars.json} (100%) diff --git a/packages/docs/blog/2023-07-24-dockview-1.8.1.md b/packages/docs/blog/2023-07-24-dockview-1.8.2.md similarity index 84% rename from packages/docs/blog/2023-07-24-dockview-1.8.1.md rename to packages/docs/blog/2023-07-24-dockview-1.8.2.md index b6d7dafd1..321cecd3a 100644 --- a/packages/docs/blog/2023-07-24-dockview-1.8.1.md +++ b/packages/docs/blog/2023-07-24-dockview-1.8.2.md @@ -1,6 +1,6 @@ --- -slug: dockview-1.8.1-release -title: Dockview 1.8.1 +slug: dockview-1.8.2-release +title: Dockview 1.8.2 tags: [release] --- diff --git a/packages/docs/versioned_docs/version-1.8.1/components/_category_.json b/packages/docs/versioned_docs/version-1.8.2/components/_category_.json similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/components/_category_.json rename to packages/docs/versioned_docs/version-1.8.2/components/_category_.json diff --git a/packages/docs/versioned_docs/version-1.8.1/components/dockview.mdx b/packages/docs/versioned_docs/version-1.8.2/components/dockview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/components/dockview.mdx rename to packages/docs/versioned_docs/version-1.8.2/components/dockview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.1/components/gridview.mdx b/packages/docs/versioned_docs/version-1.8.2/components/gridview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/components/gridview.mdx rename to packages/docs/versioned_docs/version-1.8.2/components/gridview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.1/components/paneview.mdx b/packages/docs/versioned_docs/version-1.8.2/components/paneview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/components/paneview.mdx rename to packages/docs/versioned_docs/version-1.8.2/components/paneview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.1/components/splitview.mdx b/packages/docs/versioned_docs/version-1.8.2/components/splitview.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/components/splitview.mdx rename to packages/docs/versioned_docs/version-1.8.2/components/splitview.mdx diff --git a/packages/docs/versioned_docs/version-1.8.1/contributing.mdx b/packages/docs/versioned_docs/version-1.8.2/contributing.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/contributing.mdx rename to packages/docs/versioned_docs/version-1.8.2/contributing.mdx diff --git a/packages/docs/versioned_docs/version-1.8.1/index.mdx b/packages/docs/versioned_docs/version-1.8.2/index.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/index.mdx rename to packages/docs/versioned_docs/version-1.8.2/index.mdx diff --git a/packages/docs/versioned_docs/version-1.8.1/theme.mdx b/packages/docs/versioned_docs/version-1.8.2/theme.mdx similarity index 100% rename from packages/docs/versioned_docs/version-1.8.1/theme.mdx rename to packages/docs/versioned_docs/version-1.8.2/theme.mdx diff --git a/packages/docs/versioned_sidebars/version-1.8.1-sidebars.json b/packages/docs/versioned_sidebars/version-1.8.2-sidebars.json similarity index 100% rename from packages/docs/versioned_sidebars/version-1.8.1-sidebars.json rename to packages/docs/versioned_sidebars/version-1.8.2-sidebars.json diff --git a/packages/docs/versions.json b/packages/docs/versions.json index 94df55eee..cc0c8b8a8 100644 --- a/packages/docs/versions.json +++ b/packages/docs/versions.json @@ -1,4 +1,4 @@ [ - "1.8.1", + "1.8.2", "1.7.6" ] \ No newline at end of file From bae45867fa363ba583ea89afc3bd8bf7da78ae90 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Mon, 24 Jul 2023 21:04:39 +0100 Subject: [PATCH 08/14] chore(release): publish v1.8.2 --- lerna.json | 2 +- packages/dockview-core/package.json | 2 +- packages/dockview/package.json | 4 ++-- packages/docs/package.json | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lerna.json b/lerna.json index 420562cf2..870ae6ce2 100644 --- a/lerna.json +++ b/lerna.json @@ -3,7 +3,7 @@ "packages/*" ], "useWorkspaces": true, - "version": "1.8.1", + "version": "1.8.2", "npmClient": "yarn", "command": { "publish": { diff --git a/packages/dockview-core/package.json b/packages/dockview-core/package.json index 041702e31..244e5b904 100644 --- a/packages/dockview-core/package.json +++ b/packages/dockview-core/package.json @@ -1,6 +1,6 @@ { "name": "dockview-core", - "version": "1.8.1", + "version": "1.8.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support", "main": "./dist/cjs/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/packages/dockview/package.json b/packages/dockview/package.json index 7c41a3264..6951af3f7 100644 --- a/packages/dockview/package.json +++ b/packages/dockview/package.json @@ -1,6 +1,6 @@ { "name": "dockview", - "version": "1.8.1", + "version": "1.8.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support", "main": "./dist/cjs/index.js", "types": "./dist/cjs/index.d.ts", @@ -56,7 +56,7 @@ "author": "https://github.com/mathuo", "license": "MIT", "dependencies": { - "dockview-core": "^1.8.1" + "dockview-core": "^1.8.2" }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.0.1", diff --git a/packages/docs/package.json b/packages/docs/package.json index 5d0e2cd2c..e05be24b9 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "dockview-docs", - "version": "1.8.1", + "version": "1.8.2", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -22,7 +22,7 @@ "@minoru/react-dnd-treeview": "^3.4.3", "axios": "^1.3.3", "clsx": "^1.2.1", - "dockview": "^1.8.1", + "dockview": "^1.8.2", "prism-react-renderer": "^1.3.5", "react": "^18.2.0", "react-dnd": "^16.0.1", From 17c0f6e575eec301f607719a61c84f3fc1e7f694 Mon Sep 17 00:00:00 2001 From: Peter Bech Date: Wed, 26 Jul 2023 21:40:13 +0200 Subject: [PATCH 09/14] feat: added the option for 'no-drop-target' for locked on dockview groups --- .../src/dockview/dockviewGroupPanel.ts | 7 +- .../src/dockview/dockviewGroupPanelModel.ts | 33 ++++++--- packages/docs/docs/components/dockview.mdx | 13 ++++ .../lockedgroup-dockview/package.json | 32 +++++++++ .../lockedgroup-dockview/public/index.html | 44 ++++++++++++ .../lockedgroup-dockview/src/app.tsx | 71 +++++++++++++++++++ .../lockedgroup-dockview/src/index.tsx | 20 ++++++ .../lockedgroup-dockview/src/styles.css | 16 +++++ .../lockedgroup-dockview/tsconfig.json | 18 +++++ 9 files changed, 241 insertions(+), 13 deletions(-) create mode 100644 packages/docs/sandboxes/lockedgroup-dockview/package.json create mode 100644 packages/docs/sandboxes/lockedgroup-dockview/public/index.html create mode 100644 packages/docs/sandboxes/lockedgroup-dockview/src/app.tsx create mode 100644 packages/docs/sandboxes/lockedgroup-dockview/src/index.tsx create mode 100644 packages/docs/sandboxes/lockedgroup-dockview/src/styles.css create mode 100644 packages/docs/sandboxes/lockedgroup-dockview/tsconfig.json diff --git a/packages/dockview-core/src/dockview/dockviewGroupPanel.ts b/packages/dockview-core/src/dockview/dockviewGroupPanel.ts index 0a1ccd52f..6823cbd4d 100644 --- a/packages/dockview-core/src/dockview/dockviewGroupPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewGroupPanel.ts @@ -5,6 +5,7 @@ import { GroupOptions, IDockviewGroupPanelModel, IHeader, + DockviewGroupPanelLocked, } from './dockviewGroupPanelModel'; import { GridviewPanel, IGridviewPanel } from '../gridview/gridviewPanel'; import { IDockviewPanel } from '../dockview/dockviewPanel'; @@ -16,7 +17,7 @@ import { export interface IDockviewGroupPanel extends IGridviewPanel { model: IDockviewGroupPanelModel; - locked: boolean; + locked: DockviewGroupPanelLocked; readonly size: number; readonly panels: IDockviewPanel[]; readonly activePanel: IDockviewPanel | undefined; @@ -46,11 +47,11 @@ export class DockviewGroupPanel return this._model; } - get locked(): boolean { + get locked(): DockviewGroupPanelLocked { return this._model.locked; } - set locked(value: boolean) { + set locked(value: DockviewGroupPanelLocked) { this._model.locked = value; } diff --git a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts index fb15a8895..5bf54d466 100644 --- a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts +++ b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts @@ -48,7 +48,7 @@ interface GroupMoveEvent { } interface CoreGroupOptions { - locked?: boolean; + locked?: DockviewGroupPanelLocked; hideHeader?: boolean; } @@ -79,6 +79,8 @@ export interface IHeader { hidden: boolean; } +export type DockviewGroupPanelLocked = boolean | 'no-drop-target'; + export interface IDockviewGroupPanelModel extends IPanel { readonly isActive: boolean; readonly size: number; @@ -91,7 +93,7 @@ export interface IDockviewGroupPanelModel extends IPanel { readonly onDidRemovePanel: Event; readonly onDidActivePanelChange: Event; readonly onMove: Event; - locked: boolean; + locked: DockviewGroupPanelLocked; setActive(isActive: boolean): void; initialize(): void; // state @@ -136,7 +138,7 @@ export class DockviewGroupPanelModel private _activePanel: IDockviewPanel | undefined; private watermark?: IWatermarkRenderer; private _isGroupActive = false; - private _locked = false; + private _locked: DockviewGroupPanelLocked = false; private _isFloating = false; private _rightHeaderActions: IHeaderActionsRenderer | undefined; private _leftHeaderActions: IHeaderActionsRenderer | undefined; @@ -179,14 +181,18 @@ export class DockviewGroupPanelModel return this._activePanel; } - get locked(): boolean { + get locked(): DockviewGroupPanelLocked { return this._locked; } - set locked(value: boolean) { + set locked(value: DockviewGroupPanelLocked) { this._locked = value; - toggleClass(this.container, 'locked-groupview', value); + toggleClass( + this.container, + 'locked-groupview', + value === 'no-drop-target' || value + ); } get isActive(): boolean { @@ -261,7 +267,10 @@ export class DockviewGroupPanelModel this.dropTarget = new Droptarget(this.contentContainer.element, { acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'], canDisplayOverlay: (event, position) => { - if (this.locked && position === 'center') { + if ( + this.locked === 'no-drop-target' || + (this.locked && position === 'center') + ) { return false; } @@ -303,7 +312,7 @@ export class DockviewGroupPanelModel ); this.header.hidden = !!options.hideHeader; - this.locked = !!options.locked; + this.locked = options.locked || false; this.addDisposables( this.tabsContainer.onDrop((event) => { @@ -385,8 +394,8 @@ export class DockviewGroupPanelModel id: this.id, }; - if (this.locked) { - result.locked = true; + if (this.locked !== false) { + result.locked = this.locked; } if (this.header.hidden) { @@ -746,6 +755,10 @@ export class DockviewGroupPanelModel position: Position, index?: number ): void { + if (this.locked === 'no-drop-target') { + return; + } + const data = getPanelData(); if (data && data.viewId === this.accessor.id) { diff --git a/packages/docs/docs/components/dockview.mdx b/packages/docs/docs/components/dockview.mdx index b26720281..cf82ec4f5 100644 --- a/packages/docs/docs/components/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -26,6 +26,7 @@ import DockviewResizeContainer from '@site/sandboxes/resizecontainer-dockview/sr import DockviewTabheight from '@site/sandboxes/tabheight-dockview/src/app'; import DockviewWithIFrames from '@site/sandboxes/iframe-dockview/src/app'; import DockviewFloating from '@site/sandboxes/floatinggroup-dockview/src/app'; +import DockviewLockedGroup from '@site/sandboxes/lockedgroup-dockview/src/app'; import { attach as attachDockviewVanilla } from '@site/sandboxes/javascript/vanilla-dockview/src/app'; import { attach as attachSimpleDockview } from '@site/sandboxes/javascript/simple-dockview/src/app'; @@ -776,8 +777,20 @@ You can still add groups to a locked panel programatically using the API though. ```tsx panel.group.locked = true; + +// Or + +panel.group.locked = 'no-drop-target`; ``` +Use `true` to keep drop zones top, right, bottom, left for the group. Use `no-drop-target` to disable all drop zones. For you to get a +better understanding of what this means, try and drag the panels in the example below to the locked groups. + + + ### Group Controls Panel `DockviewReact` accepts `leftHeaderActionsComponent` and `rightHeaderActionsComponent` which expect a React component with props `IDockviewHeaderActionsProps`. diff --git a/packages/docs/sandboxes/lockedgroup-dockview/package.json b/packages/docs/sandboxes/lockedgroup-dockview/package.json new file mode 100644 index 000000000..ab2f1757f --- /dev/null +++ b/packages/docs/sandboxes/lockedgroup-dockview/package.json @@ -0,0 +1,32 @@ +{ + "name": "simple-dockview", + "description": "", + "keywords": [ + "dockview" + ], + "version": "1.0.0", + "main": "src/index.tsx", + "dependencies": { + "dockview": "*", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "typescript": "^4.9.5", + "react-scripts": "*" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} \ No newline at end of file diff --git a/packages/docs/sandboxes/lockedgroup-dockview/public/index.html b/packages/docs/sandboxes/lockedgroup-dockview/public/index.html new file mode 100644 index 000000000..1f8a52426 --- /dev/null +++ b/packages/docs/sandboxes/lockedgroup-dockview/public/index.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + React App + + + + +

+ + + + diff --git a/packages/docs/sandboxes/lockedgroup-dockview/src/app.tsx b/packages/docs/sandboxes/lockedgroup-dockview/src/app.tsx new file mode 100644 index 000000000..f63584d52 --- /dev/null +++ b/packages/docs/sandboxes/lockedgroup-dockview/src/app.tsx @@ -0,0 +1,71 @@ +import { + DockviewReact, + DockviewReadyEvent, + IDockviewPanelProps, +} from 'dockview'; +import * as React from 'react'; + +const components = { + default: (props: IDockviewPanelProps<{ title: string }>) => { + return ( +
+ {props.params.title} +
+ ); + }, +}; + +export const App: React.FC = (props: { theme?: string }) => { + const onReady = (event: DockviewReadyEvent) => { + const panel1 = event.api.addPanel({ + id: 'locked1', + component: 'default', + params: { + title: 'Locked', + }, + }); + + panel1.group.locked = true; + panel1.group.header.hidden = true; + + event.api.addPanel({ + id: 'Drag me', + component: 'default', + params: { + title: '', + }, + position: { referencePanel: 'locked1', direction: 'right' }, + }); + + event.api.addPanel({ + id: 'Drag me too', + component: 'default', + params: { + title: '', + }, + position: { referencePanel: 'Drag me', direction: 'right' }, + }); + + const panel3 = event.api.addPanel({ + id: 'locked2', + component: 'default', + params: { + title: 'Locked with no drop target', + }, + position: { referencePanel: 'Drag me too', direction: 'right' }, + }); + + panel3.group.locked = 'no-drop-target'; + panel3.group.header.hidden = true; + }; + + return ( + + ); +}; + +export default App; diff --git a/packages/docs/sandboxes/lockedgroup-dockview/src/index.tsx b/packages/docs/sandboxes/lockedgroup-dockview/src/index.tsx new file mode 100644 index 000000000..2fe1be232 --- /dev/null +++ b/packages/docs/sandboxes/lockedgroup-dockview/src/index.tsx @@ -0,0 +1,20 @@ +import { StrictMode } from 'react'; +import * as ReactDOMClient from 'react-dom/client'; +import './styles.css'; +import 'dockview/dist/styles/dockview.css'; + +import App from './app'; + +const rootElement = document.getElementById('root'); + +if (rootElement) { + const root = ReactDOMClient.createRoot(rootElement); + + root.render( + +
+ +
+
+ ); +} diff --git a/packages/docs/sandboxes/lockedgroup-dockview/src/styles.css b/packages/docs/sandboxes/lockedgroup-dockview/src/styles.css new file mode 100644 index 000000000..92b6a1b36 --- /dev/null +++ b/packages/docs/sandboxes/lockedgroup-dockview/src/styles.css @@ -0,0 +1,16 @@ +body { + margin: 0px; + color: white; + font-family: sans-serif; + text-align: center; +} + +#root { + height: 100vh; + width: 100vw; +} + +.app { + height: 100%; + +} diff --git a/packages/docs/sandboxes/lockedgroup-dockview/tsconfig.json b/packages/docs/sandboxes/lockedgroup-dockview/tsconfig.json new file mode 100644 index 000000000..cdc4fb5f5 --- /dev/null +++ b/packages/docs/sandboxes/lockedgroup-dockview/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "outDir": "build/dist", + "module": "esnext", + "target": "es5", + "lib": ["es6", "dom"], + "sourceMap": true, + "allowJs": true, + "jsx": "react-jsx", + "moduleResolution": "node", + "rootDir": "src", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "strictNullChecks": true + } +} From 55802a7a165f7c55bb9e62260ab56ce9425a2f63 Mon Sep 17 00:00:00 2001 From: Peter Bech Date: Wed, 26 Jul 2023 21:52:29 +0200 Subject: [PATCH 10/14] patch: renamed lockedgroup-dockview sandbox package name to match directory name --- packages/docs/sandboxes/lockedgroup-dockview/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/sandboxes/lockedgroup-dockview/package.json b/packages/docs/sandboxes/lockedgroup-dockview/package.json index ab2f1757f..3f7605d60 100644 --- a/packages/docs/sandboxes/lockedgroup-dockview/package.json +++ b/packages/docs/sandboxes/lockedgroup-dockview/package.json @@ -1,5 +1,5 @@ { - "name": "simple-dockview", + "name": "lockedgroup-dockview", "description": "", "keywords": [ "dockview" From b551d93dacf80d0bf81b8b5cc31b90d73d583362 Mon Sep 17 00:00:00 2001 From: Peter Bech Date: Wed, 26 Jul 2023 22:03:51 +0200 Subject: [PATCH 11/14] added lockedgroup-dockview to the codesandbox ci configuration --- .codesandbox/ci.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index f04bc5e88..52156e5a1 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -15,6 +15,7 @@ "/packages/docs/sandboxes/groupcontol-dockview", "/packages/docs/sandboxes/iframe-dockview", "/packages/docs/sandboxes/layout-dockview", + "/packages/docs/sandboxes/lockedgroup-dockview", "/packages/docs/sandboxes/nativeapp-dockview", "/packages/docs/sandboxes/nested-dockview", "/packages/docs/sandboxes/rendering-dockview", From d577f0238c514c9f8e5d83e2500fce6c988e7ddf Mon Sep 17 00:00:00 2001 From: Peter Bech <1520592+techbech@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:28:24 +0200 Subject: [PATCH 12/14] Fix wrong quotation sign in docs --- packages/docs/docs/components/dockview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/docs/components/dockview.mdx b/packages/docs/docs/components/dockview.mdx index cf82ec4f5..64092733d 100644 --- a/packages/docs/docs/components/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -780,7 +780,7 @@ panel.group.locked = true; // Or -panel.group.locked = 'no-drop-target`; +panel.group.locked = 'no-drop-target'; ``` Use `true` to keep drop zones top, right, bottom, left for the group. Use `no-drop-target` to disable all drop zones. For you to get a From 3ef9f4ed2d1fb07bfbee934675d5891a1f82593e Mon Sep 17 00:00:00 2001 From: Imbozter <49216935+Imbozter@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:53:50 +1000 Subject: [PATCH 13/14] Update dockview.mdx --- packages/docs/docs/components/dockview.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/docs/docs/components/dockview.mdx b/packages/docs/docs/components/dockview.mdx index 64092733d..01cbb2717 100644 --- a/packages/docs/docs/components/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -162,7 +162,6 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { | group | `GroupPanel | undefined` | | isGroupActive | `boolean` | | | title | `string` | | -| suppressClosable | `boolean` | | | close | `(): void` | | | setTitle | `(title: string): void` | | From 5ac2a9ffdb720056f465d5d9269d6466af0b487f Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Tue, 22 Aug 2023 20:31:47 +0100 Subject: [PATCH 14/14] feat: hideClose on DockviewDefaultTab --- package.json | 1 + .../__tests__/dockview/defaultTab.spec.tsx | 60 ++++++++++++++++ .../dockview/src/dockview/defaultTab.scss | 4 +- packages/dockview/src/dockview/defaultTab.tsx | 71 +++++++++++-------- yarn.lock | 5 ++ 5 files changed, 108 insertions(+), 33 deletions(-) create mode 100644 packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx diff --git a/package.json b/package.json index 114afaa58..c2fb363e7 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "devDependencies": { "@testing-library/dom": "^8.20.0", "@testing-library/jest-dom": "^5.16.5", + "@total-typescript/shoehorn": "^0.1.1", "@types/jest": "^29.4.0", "@typescript-eslint/eslint-plugin": "^5.52.0", "@typescript-eslint/parser": "^5.52.0", diff --git a/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx b/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx new file mode 100644 index 000000000..4d52dd18f --- /dev/null +++ b/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx @@ -0,0 +1,60 @@ +import { render, screen } from '@testing-library/react'; +import { DockviewDefaultTab } from '../../dockview/defaultTab'; +import * as React from 'react'; +import { fromPartial } from '@total-typescript/shoehorn'; +import { DockviewApi, DockviewPanelApi } from 'dockview-core'; + +describe('defaultTab', () => { + test('has close button by default', async () => { + const api = fromPartial({}); + const containerApi = fromPartial({}); + const params = {}; + + render( + + ); + + const element = await screen.getByTestId('dockview-default-tab'); + expect(element.querySelector('.dv-react-tab-close-btn')).toBeTruthy(); + }); + + test('has no close button when hideClose=true', async () => { + const api = fromPartial({}); + const containerApi = fromPartial({}); + const params = {}; + + render( + + ); + + const element = await screen.getByTestId('dockview-default-tab'); + expect(element.querySelector('.dv-react-tab-close-btn')).toBeNull(); + }); + + test('has close button when hideClose=false', async () => { + const api = fromPartial({}); + const containerApi = fromPartial({}); + const params = {}; + + render( + + ); + + const element = await screen.getByTestId('dockview-default-tab'); + expect(element.querySelector('.dv-react-tab-close-btn')).toBeTruthy(); + }); +}); diff --git a/packages/dockview/src/dockview/defaultTab.scss b/packages/dockview/src/dockview/defaultTab.scss index b40356490..3e3a89085 100644 --- a/packages/dockview/src/dockview/defaultTab.scss +++ b/packages/dockview/src/dockview/defaultTab.scss @@ -10,7 +10,7 @@ flex-grow: 1; } - .dockview-react-tab-action { + .dv-react-tab-close-btn { padding: 4px; display: flex; align-items: center; @@ -25,7 +25,7 @@ } &.inactive-tab:not(:hover) { - .dockview-react-tab-action { + .dv-react-tab-close-btn { visibility: hidden; } } diff --git a/packages/dockview/src/dockview/defaultTab.tsx b/packages/dockview/src/dockview/defaultTab.tsx index 9a35feea0..1faee461c 100644 --- a/packages/dockview/src/dockview/defaultTab.tsx +++ b/packages/dockview/src/dockview/defaultTab.tsx @@ -3,40 +3,49 @@ import * as React from 'react'; import { CloseButton } from '../svg'; export type IDockviewDefaultTabProps = IDockviewPanelHeaderProps & - React.DOMAttributes; + React.DOMAttributes & { hideClose?: boolean }; -export const DockviewDefaultTab: React.FunctionComponent = - ({ api, containerApi: _containerApi, params: _params, ...rest }) => { - const onClose = React.useCallback( - (event: React.MouseEvent) => { - event.stopPropagation(); - api.close(); - }, - [api] - ); +export const DockviewDefaultTab: React.FunctionComponent< + IDockviewDefaultTabProps +> = ({ + api, + containerApi: _containerApi, + params: _params, + hideClose, + ...rest +}) => { + const onClose = React.useCallback( + (event: React.MouseEvent) => { + event.stopPropagation(); + api.close(); + }, + [api] + ); - const onClick = React.useCallback( - (event: React.MouseEvent) => { - api.setActive(); + const onClick = React.useCallback( + (event: React.MouseEvent) => { + api.setActive(); - if (rest.onClick) { - rest.onClick(event); - } - }, - [api, rest.onClick] - ); + if (rest.onClick) { + rest.onClick(event); + } + }, + [api, rest.onClick] + ); - const iconClassname = React.useMemo(() => { - const cn = ['dockview-react-tab-action']; - return cn.join(','); - }, []); - - return ( -
- {api.title} -
+ return ( +
+ {api.title} + {!hideClose && ( +
-
- ); - }; + )} +
+ ); +}; diff --git a/yarn.lock b/yarn.lock index 9863d207e..70562dff6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2961,6 +2961,11 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@total-typescript/shoehorn@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@total-typescript/shoehorn/-/shoehorn-0.1.1.tgz#72d3ba9364faa4f6b8e66c57b7a9094457e3652b" + integrity sha512-XSPcazQsC2Cr7eCiAI+M2bTmMziBvFWYTYMgUDKLbU6i+7m3I2BF5gXF5vKDO8577fONs9CvmTvVa7+nMHMfxg== + "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"