From c48aee58e7aa859d0fc82ed5234ce39dbdd5f982 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Sat, 8 Feb 2025 11:30:19 +0000 Subject: [PATCH] conditional middle-btn tab close --- .../src/dockview/components/tab/tab.ts | 12 ++---- .../components/titlebar/tabsContainer.ts | 5 +-- packages/dockview/src/dockview/defaultTab.tsx | 43 +++++++++++++++++-- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/packages/dockview-core/src/dockview/components/tab/tab.ts b/packages/dockview-core/src/dockview/components/tab/tab.ts index 1eb1174d8..0b6ad55dc 100644 --- a/packages/dockview-core/src/dockview/components/tab/tab.ts +++ b/packages/dockview-core/src/dockview/components/tab/tab.ts @@ -49,8 +49,8 @@ export class Tab extends CompositeDisposable { private readonly dropTarget: Droptarget; private content: ITabRenderer | undefined = undefined; - private readonly _onChanged = new Emitter(); - readonly onChanged: Event = this._onChanged.event; + private readonly _onPointDown = new Emitter(); + readonly onPointerDown: Event = this._onPointDown.event; private readonly _onDropped = new Emitter(); readonly onDrop: Event = this._onDropped.event; @@ -117,7 +117,7 @@ export class Tab extends CompositeDisposable { this.onWillShowOverlay = this.dropTarget.onWillShowOverlay; this.addDisposables( - this._onChanged, + this._onPointDown, this._onDropped, this._onDragStart, dragHandler.onDragStart((event) => { @@ -125,11 +125,7 @@ export class Tab extends CompositeDisposable { }), dragHandler, addDisposableListener(this._element, 'pointerdown', (event) => { - if (event.defaultPrevented) { - return; - } - - this._onChanged.fire(event); + this._onPointDown.fire(event); }), this.dropTarget.onDrop((event) => { this._onDropped.fire(event); diff --git a/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts b/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts index e420f1183..30a18af2d 100644 --- a/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts +++ b/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts @@ -317,7 +317,7 @@ export class TabsContainer tab.onDragStart((event) => { this._onTabDragStart.fire({ nativeEvent: event, panel }); }), - tab.onChanged((event) => { + tab.onPointerDown((event) => { if (event.defaultPrevented) { return; } @@ -356,9 +356,6 @@ export class TabsContainer this.group.model.openPanel(panel); } break; - case 1: // middle click - panel.api.close(); - break; } }), tab.onDrop((event) => { diff --git a/packages/dockview/src/dockview/defaultTab.tsx b/packages/dockview/src/dockview/defaultTab.tsx index d2801f40e..676545540 100644 --- a/packages/dockview/src/dockview/defaultTab.tsx +++ b/packages/dockview/src/dockview/defaultTab.tsx @@ -21,6 +21,7 @@ function useTitle(api: DockviewPanelApi): string | undefined { export type IDockviewDefaultTabProps = IDockviewPanelHeaderProps & React.DOMAttributes & { hideClose?: boolean; + closeWithMiddleButton?: boolean; closeActionOverride?: () => void; }; @@ -32,10 +33,15 @@ export const DockviewDefaultTab: React.FunctionComponent< params: _params, hideClose, closeActionOverride, + onPointerDown, + onPointerUp, + onPointerLeave, ...rest }) => { const title = useTitle(api); + const isMiddleMouseButton = React.useRef(false); + const onClose = React.useCallback( (event: React.MouseEvent) => { event.preventDefault(); @@ -49,21 +55,52 @@ export const DockviewDefaultTab: React.FunctionComponent< [api, closeActionOverride] ); - const onPointerDown = React.useCallback((e: React.MouseEvent) => { - e.preventDefault(); + const onBtnPointerDown = React.useCallback((event: React.MouseEvent) => { + event.preventDefault(); }, []); + const _onPointerDown = React.useCallback( + (event: React.PointerEvent) => { + isMiddleMouseButton.current = event.button === 1; + onPointerDown?.(event); + }, + [onPointerDown] + ); + + const _onPointerUp = React.useCallback( + (event: React.PointerEvent) => { + if (isMiddleMouseButton && event.button === 1 && !hideClose) { + isMiddleMouseButton.current = false; + onClose(event); + } + + onPointerUp?.(event); + }, + [onPointerUp, onClose, hideClose] + ); + + const _onPointerLeave = React.useCallback( + (event: React.PointerEvent) => { + isMiddleMouseButton.current = false; + onPointerLeave?.(event); + }, + [onPointerLeave] + ); + return (
{title} {!hideClose && (