diff --git a/src/Container.tsx b/src/Container.tsx index 69c9e03..6cccc39 100644 --- a/src/Container.tsx +++ b/src/Container.tsx @@ -176,7 +176,7 @@ export function Container(props: { tabHeight={ tabHeight } onClickPanel={ () => handleClickedPanel(props.state, panelRect.panel, null) } onClickTab={ (tabNumber) => handleClickedPanel(props.state, panelRect.panel, tabNumber) } - onCloseTab={ (ev, tabNumber) => handleClosedTab(ev, props.state, panelRect.panel, tabNumber) } + onCloseTab={ (ev, tabNumber) => handleClosedTab(props.state, panelRect.panel, tabNumber, ev) } onDragHeader={ (ev, tabNumber) => handleDraggedHeader(ev, props.state, layoutRef, rectRef, panelRect.panel, tabNumber) } /> )} @@ -195,9 +195,16 @@ export function Container(props: { }}> setTitle(layoutContent, title), setPreferredSize: (w, h) => setPreferredSize(layoutContent, w, h), + close: () => + handleClosedTab( + props.state, + layoutContent.panel, + layoutContent.tabIndex, + undefined + ), }}> { layoutContent.content.element } @@ -495,15 +502,24 @@ function handleClickedPanel( function handleClosedTab( - ev: React.MouseEvent, state: Dockable.RefState, panel: Dockable.Panel, - tabNumber: number) + tabNumber: number, + ev?: React.MouseEvent +) { - ev.preventDefault() + if (ev) { + ev.preventDefault(); + } - const content = panel.contentList[tabNumber] - Dockable.removeContent(state.ref.current, panel, content.contentId) - Dockable.coallesceEmptyPanels(state.ref.current) - state.commit() + const content = panel.contentList[tabNumber]; + + if (content && content.isClosable && !content.isClosable()) { + // Don't close the tab + return; + } + + Dockable.removeContent(state.ref.current, panel, content.contentId); + Dockable.coallesceEmptyPanels(state.ref.current); + state.commit(); } \ No newline at end of file diff --git a/src/Panel.tsx b/src/Panel.tsx index 6b542e2..8c05277 100644 --- a/src/Panel.tsx +++ b/src/Panel.tsx @@ -1,4 +1,4 @@ -import * as React from "react" +import React, { useRef } from "react"; import * as Dockable from "./index.js" import styled from "styled-components" @@ -52,6 +52,7 @@ const StyledTabRowInner = styled.div<{ { width: 4px; height: 4px; + display: none; } &::-webkit-scrollbar-track @@ -141,6 +142,7 @@ export function ContainerPanel(props: { }) { const panelRect: Dockable.LayoutPanel = props.panelRect + const refTabRowInner = useRef(null); const isActivePanel = props.state.ref.current.activePanel === panelRect.panel @@ -159,6 +161,11 @@ export function ContainerPanel(props: { draggable tabHeight={ props.tabHeight } tabCount={ panelRect.panel.contentList.length } + onWheel={(ev) => { + if (refTabRowInner && refTabRowInner.current) + refTabRowInner.current.scrollLeft += ev.deltaY; + ev.preventDefault(); + }} onMouseDown={ ev => { props.onClickPanel() props.onDragHeader(ev, null) diff --git a/src/global.ts b/src/global.ts index 269cc9b..6651772 100644 --- a/src/global.ts +++ b/src/global.ts @@ -69,10 +69,12 @@ export function spawnFloatingEphemeral( export interface ContentContextProps { - layoutContent: Dockable.LayoutContent + layoutContent: Dockable.LayoutContent; + content: Dockable.Content; - setTitle: (title: string) => void - setPreferredSize: (w: number, h: number) => void + setTitle: (title: string) => void; + setPreferredSize: (w: number, h: number) => void; + close: () => void; } diff --git a/src/state.ts b/src/state.ts index 8da5936..12a8daa 100644 --- a/src/state.ts +++ b/src/state.ts @@ -60,6 +60,7 @@ export interface Content { contentId: ContentId title: string + isClosable?: () => boolean; element: JSX.Element }