mirror of
https://github.com/mathuo/dockview
synced 2025-09-08 18:36:51 +00:00
feat: add left header actions
This commit is contained in:
parent
6434e68b5b
commit
13d3db605b
@ -46,30 +46,5 @@
|
|||||||
padding: 0px 8px;
|
padding: 0px 8px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-container {
|
|
||||||
text-align: right;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.tab-list {
|
|
||||||
display: flex;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.tab-action {
|
|
||||||
padding: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: var(--dv-icon-hover-background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,8 @@ export interface ITabsContainer extends IDisposable {
|
|||||||
isActive: (tab: ITab) => boolean;
|
isActive: (tab: ITab) => boolean;
|
||||||
closePanel: (panel: IDockviewPanel) => void;
|
closePanel: (panel: IDockviewPanel) => void;
|
||||||
openPanel: (panel: IDockviewPanel, index?: number) => void;
|
openPanel: (panel: IDockviewPanel, index?: number) => void;
|
||||||
setActionElement(element: HTMLElement | undefined): void;
|
setRightActionsElement(element: HTMLElement | undefined): void;
|
||||||
|
setLeftActionsElement(element: HTMLElement | undefined): void;
|
||||||
hidden: boolean;
|
hidden: boolean;
|
||||||
show(): void;
|
show(): void;
|
||||||
hide(): void;
|
hide(): void;
|
||||||
@ -40,12 +41,14 @@ export class TabsContainer
|
|||||||
{
|
{
|
||||||
private readonly _element: HTMLElement;
|
private readonly _element: HTMLElement;
|
||||||
private readonly tabContainer: HTMLElement;
|
private readonly tabContainer: HTMLElement;
|
||||||
private readonly actionContainer: HTMLElement;
|
private readonly rightActionsContainer: HTMLElement;
|
||||||
|
private readonly leftActionsContainer: HTMLElement;
|
||||||
private readonly voidContainer: VoidContainer;
|
private readonly voidContainer: VoidContainer;
|
||||||
|
|
||||||
private tabs: IValueDisposable<ITab>[] = [];
|
private tabs: IValueDisposable<ITab>[] = [];
|
||||||
private selectedIndex = -1;
|
private selectedIndex = -1;
|
||||||
private actions: HTMLElement | undefined;
|
private rightActions: HTMLElement | undefined;
|
||||||
|
private leftActions: HTMLElement | undefined;
|
||||||
|
|
||||||
private _hidden = false;
|
private _hidden = false;
|
||||||
|
|
||||||
@ -79,17 +82,31 @@ export class TabsContainer
|
|||||||
this._element.style.display = 'none';
|
this._element.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
setActionElement(element: HTMLElement | undefined): void {
|
setRightActionsElement(element: HTMLElement | undefined): void {
|
||||||
if (this.actions === element) {
|
if (this.rightActions === element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.actions) {
|
if (this.rightActions) {
|
||||||
this.actions.remove();
|
this.rightActions.remove();
|
||||||
this.actions = undefined;
|
this.rightActions = undefined;
|
||||||
}
|
}
|
||||||
if (element) {
|
if (element) {
|
||||||
this.actionContainer.appendChild(element);
|
this.rightActionsContainer.appendChild(element);
|
||||||
this.actions = element;
|
this.rightActions = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLeftActionsElement(element: HTMLElement | undefined): void {
|
||||||
|
if (this.leftActions === element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.leftActions) {
|
||||||
|
this.leftActions.remove();
|
||||||
|
this.leftActions = undefined;
|
||||||
|
}
|
||||||
|
if (element) {
|
||||||
|
this.leftActionsContainer.appendChild(element);
|
||||||
|
this.leftActions = element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,8 +163,11 @@ export class TabsContainer
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.actionContainer = document.createElement('div');
|
this.rightActionsContainer = document.createElement('div');
|
||||||
this.actionContainer.className = 'action-container';
|
this.rightActionsContainer.className = 'right-actions-container';
|
||||||
|
|
||||||
|
this.leftActionsContainer = document.createElement('div');
|
||||||
|
this.leftActionsContainer.className = 'left-actions-container';
|
||||||
|
|
||||||
this.tabContainer = document.createElement('div');
|
this.tabContainer = document.createElement('div');
|
||||||
this.tabContainer.className = 'tabs-container';
|
this.tabContainer.className = 'tabs-container';
|
||||||
@ -155,8 +175,9 @@ export class TabsContainer
|
|||||||
this.voidContainer = new VoidContainer(this.accessor, this.group);
|
this.voidContainer = new VoidContainer(this.accessor, this.group);
|
||||||
|
|
||||||
this._element.appendChild(this.tabContainer);
|
this._element.appendChild(this.tabContainer);
|
||||||
|
this._element.appendChild(this.leftActionsContainer);
|
||||||
this._element.appendChild(this.voidContainer.element);
|
this._element.appendChild(this.voidContainer.element);
|
||||||
this._element.appendChild(this.actionContainer);
|
this._element.appendChild(this.rightActionsContainer);
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
this.voidContainer,
|
this.voidContainer,
|
||||||
|
@ -71,7 +71,8 @@ export type DockviewComponentUpdateOptions = Pick<
|
|||||||
| 'showDndOverlay'
|
| 'showDndOverlay'
|
||||||
| 'watermarkFrameworkComponent'
|
| 'watermarkFrameworkComponent'
|
||||||
| 'defaultTabComponent'
|
| 'defaultTabComponent'
|
||||||
| 'createGroupControlElement'
|
| 'createLeftHeaderActionsElement'
|
||||||
|
| 'createRightHeaderActionsElement'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export interface DockviewDropEvent extends GroupviewDropEvent {
|
export interface DockviewDropEvent extends GroupviewDropEvent {
|
||||||
|
@ -138,6 +138,7 @@ export class DockviewGroupPanelModel
|
|||||||
private _isGroupActive = false;
|
private _isGroupActive = false;
|
||||||
private _locked = false;
|
private _locked = false;
|
||||||
private _control: IGroupControlRenderer | undefined;
|
private _control: IGroupControlRenderer | undefined;
|
||||||
|
private _lhs: IGroupControlRenderer | undefined;
|
||||||
|
|
||||||
private mostRecentlyUsed: IDockviewPanel[] = [];
|
private mostRecentlyUsed: IDockviewPanel[] = [];
|
||||||
|
|
||||||
@ -319,8 +320,9 @@ export class DockviewGroupPanelModel
|
|||||||
this.setActive(this.isActive, true, true);
|
this.setActive(this.isActive, true, true);
|
||||||
this.updateContainer();
|
this.updateContainer();
|
||||||
|
|
||||||
if (this.accessor.options.createGroupControlElement) {
|
if (this.accessor.options.createRightHeaderActionsElement) {
|
||||||
this._control = this.accessor.options.createGroupControlElement(
|
this._control =
|
||||||
|
this.accessor.options.createRightHeaderActionsElement(
|
||||||
this.groupPanel
|
this.groupPanel
|
||||||
);
|
);
|
||||||
this.addDisposables(this._control);
|
this.addDisposables(this._control);
|
||||||
@ -328,7 +330,19 @@ export class DockviewGroupPanelModel
|
|||||||
containerApi: new DockviewApi(this.accessor),
|
containerApi: new DockviewApi(this.accessor),
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setActionElement(this._control.element);
|
this.tabsContainer.setRightActionsElement(this._control.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.accessor.options.createLeftHeaderActionsElement) {
|
||||||
|
this._lhs = this.accessor.options.createLeftHeaderActionsElement(
|
||||||
|
this.groupPanel
|
||||||
|
);
|
||||||
|
this.addDisposables(this._lhs);
|
||||||
|
this._lhs.init({
|
||||||
|
containerApi: new DockviewApi(this.accessor),
|
||||||
|
api: this.groupPanel.api,
|
||||||
|
});
|
||||||
|
this.tabsContainer.setLeftActionsElement(this._lhs.element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,7 +525,7 @@ export class DockviewGroupPanelModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateActions(element: HTMLElement | undefined): void {
|
updateActions(element: HTMLElement | undefined): void {
|
||||||
this.tabsContainer.setActionElement(element);
|
this.tabsContainer.setRightActionsElement(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setActive(
|
public setActive(
|
||||||
|
@ -79,7 +79,10 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
|||||||
styles?: ISplitviewStyles;
|
styles?: ISplitviewStyles;
|
||||||
defaultTabComponent?: string;
|
defaultTabComponent?: string;
|
||||||
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
||||||
createGroupControlElement?: (
|
createRightHeaderActionsElement?: (
|
||||||
|
group: DockviewGroupPanel
|
||||||
|
) => IGroupControlRenderer;
|
||||||
|
createLeftHeaderActionsElement?: (
|
||||||
group: DockviewGroupPanel
|
group: DockviewGroupPanel
|
||||||
) => IGroupControlRenderer;
|
) => IGroupControlRenderer;
|
||||||
singleTabMode?: 'fullwidth' | 'default';
|
singleTabMode?: 'fullwidth' | 'default';
|
||||||
|
@ -65,7 +65,8 @@ export interface IDockviewReactProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
disableAutoResizing?: boolean;
|
disableAutoResizing?: boolean;
|
||||||
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
||||||
groupControlComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
|
rightHeaderActionsComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
|
||||||
|
leftHeaderActionsComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
|
||||||
singleTabMode?: 'fullwidth' | 'default';
|
singleTabMode?: 'fullwidth' | 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,10 +151,15 @@ export const DockviewReact = React.forwardRef(
|
|||||||
? { separatorBorder: 'transparent' }
|
? { separatorBorder: 'transparent' }
|
||||||
: undefined,
|
: undefined,
|
||||||
showDndOverlay: props.showDndOverlay,
|
showDndOverlay: props.showDndOverlay,
|
||||||
createGroupControlElement: createGroupControlElement(
|
createLeftHeaderActionsElement: createGroupControlElement(
|
||||||
props.groupControlComponent,
|
props.leftHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
|
createRightHeaderActionsElement: createGroupControlElement(
|
||||||
|
props.rightHeaderActionsComponent,
|
||||||
|
{ addPortal }
|
||||||
|
),
|
||||||
|
|
||||||
singleTabMode: props.singleTabMode,
|
singleTabMode: props.singleTabMode,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -250,12 +256,24 @@ export const DockviewReact = React.forwardRef(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dockviewRef.current.updateOptions({
|
dockviewRef.current.updateOptions({
|
||||||
createGroupControlElement: createGroupControlElement(
|
createRightHeaderActionsElement: createGroupControlElement(
|
||||||
props.groupControlComponent,
|
props.rightHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}, [props.groupControlComponent]);
|
}, [props.rightHeaderActionsComponent]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!dockviewRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dockviewRef.current.updateOptions({
|
||||||
|
createLeftHeaderActionsElement: createGroupControlElement(
|
||||||
|
props.leftHeaderActionsComponent,
|
||||||
|
{ addPortal }
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, [props.leftHeaderActionsComponent]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -59,7 +59,7 @@ import { DockviewReact } from 'dockview';
|
|||||||
```
|
```
|
||||||
|
|
||||||
| Property | Type | Optional | Default | Description |
|
| Property | Type | Optional | Default | Description |
|
||||||
| --------------------- | ------------------------------------ | -------- | --------- | ------------------------------------------------------------ |
|
| --------------------------- | ------------------------------------ | -------- | --------- | ------------------------------------------------------------ |
|
||||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||||
| components | object | No | | |
|
| components | object | No | | |
|
||||||
| tabComponents | object | Yes | | |
|
| tabComponents | object | Yes | | |
|
||||||
@ -70,7 +70,8 @@ import { DockviewReact } from 'dockview';
|
|||||||
| onDidDrop | Event | Yes | false | |
|
| onDidDrop | Event | Yes | false | |
|
||||||
| showDndOverlay | Event | Yes | false | |
|
| showDndOverlay | Event | Yes | false | |
|
||||||
| defaultTabComponent | object | Yes | | |
|
| defaultTabComponent | object | Yes | | |
|
||||||
| groupControlComponent | object | Yes | | |
|
| leftHeaderActionsComponent | object | Yes | | |
|
||||||
|
| rightHeaderActionsComponent | object | Yes | | |
|
||||||
| singleTabMode | 'fullwidth' \| 'default' | Yes | 'default' | |
|
| singleTabMode | 'fullwidth' \| 'default' | Yes | 'default' | |
|
||||||
|
|
||||||
## Dockview API
|
## Dockview API
|
||||||
|
@ -26,7 +26,7 @@ const components = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const GroupControlComponent = (props: IDockviewGroupControlProps) => {
|
const RightHeaderActions = (props: IDockviewGroupControlProps) => {
|
||||||
const isGroupActive = props.isGroupActive;
|
const isGroupActive = props.isGroupActive;
|
||||||
const activePanel = props.activePanel;
|
const activePanel = props.activePanel;
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ const DockviewGroupControl = () => {
|
|||||||
<DockviewReact
|
<DockviewReact
|
||||||
onReady={onReady}
|
onReady={onReady}
|
||||||
components={components}
|
components={components}
|
||||||
groupControlComponent={GroupControlComponent}
|
rightHeaderActionsComponent={RightHeaderActions}
|
||||||
className="dockview-theme-abyss"
|
className="dockview-theme-abyss"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user