feat: add left header actions

This commit is contained in:
mathuo 2023-06-03 20:18:42 +01:00
parent 6434e68b5b
commit 13d3db605b
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
8 changed files with 102 additions and 69 deletions

View File

@ -46,30 +46,5 @@
padding: 0px 8px;
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);
}
}
}
}
}
}

View File

@ -28,7 +28,8 @@ export interface ITabsContainer extends IDisposable {
isActive: (tab: ITab) => boolean;
closePanel: (panel: IDockviewPanel) => void;
openPanel: (panel: IDockviewPanel, index?: number) => void;
setActionElement(element: HTMLElement | undefined): void;
setRightActionsElement(element: HTMLElement | undefined): void;
setLeftActionsElement(element: HTMLElement | undefined): void;
hidden: boolean;
show(): void;
hide(): void;
@ -40,12 +41,14 @@ export class TabsContainer
{
private readonly _element: HTMLElement;
private readonly tabContainer: HTMLElement;
private readonly actionContainer: HTMLElement;
private readonly rightActionsContainer: HTMLElement;
private readonly leftActionsContainer: HTMLElement;
private readonly voidContainer: VoidContainer;
private tabs: IValueDisposable<ITab>[] = [];
private selectedIndex = -1;
private actions: HTMLElement | undefined;
private rightActions: HTMLElement | undefined;
private leftActions: HTMLElement | undefined;
private _hidden = false;
@ -79,17 +82,31 @@ export class TabsContainer
this._element.style.display = 'none';
}
setActionElement(element: HTMLElement | undefined): void {
if (this.actions === element) {
setRightActionsElement(element: HTMLElement | undefined): void {
if (this.rightActions === element) {
return;
}
if (this.actions) {
this.actions.remove();
this.actions = undefined;
if (this.rightActions) {
this.rightActions.remove();
this.rightActions = undefined;
}
if (element) {
this.actionContainer.appendChild(element);
this.actions = element;
this.rightActionsContainer.appendChild(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.actionContainer.className = 'action-container';
this.rightActionsContainer = document.createElement('div');
this.rightActionsContainer.className = 'right-actions-container';
this.leftActionsContainer = document.createElement('div');
this.leftActionsContainer.className = 'left-actions-container';
this.tabContainer = document.createElement('div');
this.tabContainer.className = 'tabs-container';
@ -155,8 +175,9 @@ export class TabsContainer
this.voidContainer = new VoidContainer(this.accessor, this.group);
this._element.appendChild(this.tabContainer);
this._element.appendChild(this.leftActionsContainer);
this._element.appendChild(this.voidContainer.element);
this._element.appendChild(this.actionContainer);
this._element.appendChild(this.rightActionsContainer);
this.addDisposables(
this.voidContainer,

View File

@ -71,7 +71,8 @@ export type DockviewComponentUpdateOptions = Pick<
| 'showDndOverlay'
| 'watermarkFrameworkComponent'
| 'defaultTabComponent'
| 'createGroupControlElement'
| 'createLeftHeaderActionsElement'
| 'createRightHeaderActionsElement'
>;
export interface DockviewDropEvent extends GroupviewDropEvent {
@ -717,7 +718,7 @@ export class DockviewComponent
if (itemId === undefined) {
if (sourceGroup) {
this.moveGroup(sourceGroup, referenceGroup, target);
this.moveGroup(sourceGroup, referenceGroup, target);
}
return;
}

View File

@ -138,6 +138,7 @@ export class DockviewGroupPanelModel
private _isGroupActive = false;
private _locked = false;
private _control: IGroupControlRenderer | undefined;
private _lhs: IGroupControlRenderer | undefined;
private mostRecentlyUsed: IDockviewPanel[] = [];
@ -319,16 +320,29 @@ export class DockviewGroupPanelModel
this.setActive(this.isActive, true, true);
this.updateContainer();
if (this.accessor.options.createGroupControlElement) {
this._control = this.accessor.options.createGroupControlElement(
this.groupPanel
);
if (this.accessor.options.createRightHeaderActionsElement) {
this._control =
this.accessor.options.createRightHeaderActionsElement(
this.groupPanel
);
this.addDisposables(this._control);
this._control.init({
containerApi: new DockviewApi(this.accessor),
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 {
this.tabsContainer.setActionElement(element);
this.tabsContainer.setRightActionsElement(element);
}
public setActive(

View File

@ -79,7 +79,10 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
styles?: ISplitviewStyles;
defaultTabComponent?: string;
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
createGroupControlElement?: (
createRightHeaderActionsElement?: (
group: DockviewGroupPanel
) => IGroupControlRenderer;
createLeftHeaderActionsElement?: (
group: DockviewGroupPanel
) => IGroupControlRenderer;
singleTabMode?: 'fullwidth' | 'default';

View File

@ -65,7 +65,8 @@ export interface IDockviewReactProps {
className?: string;
disableAutoResizing?: boolean;
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
groupControlComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
rightHeaderActionsComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
leftHeaderActionsComponent?: React.FunctionComponent<IDockviewGroupControlProps>;
singleTabMode?: 'fullwidth' | 'default';
}
@ -150,10 +151,15 @@ export const DockviewReact = React.forwardRef(
? { separatorBorder: 'transparent' }
: undefined,
showDndOverlay: props.showDndOverlay,
createGroupControlElement: createGroupControlElement(
props.groupControlComponent,
createLeftHeaderActionsElement: createGroupControlElement(
props.leftHeaderActionsComponent,
{ addPortal }
),
createRightHeaderActionsElement: createGroupControlElement(
props.rightHeaderActionsComponent,
{ addPortal }
),
singleTabMode: props.singleTabMode,
});
@ -250,12 +256,24 @@ export const DockviewReact = React.forwardRef(
return;
}
dockviewRef.current.updateOptions({
createGroupControlElement: createGroupControlElement(
props.groupControlComponent,
createRightHeaderActionsElement: createGroupControlElement(
props.rightHeaderActionsComponent,
{ addPortal }
),
});
}, [props.groupControlComponent]);
}, [props.rightHeaderActionsComponent]);
React.useEffect(() => {
if (!dockviewRef.current) {
return;
}
dockviewRef.current.updateOptions({
createLeftHeaderActionsElement: createGroupControlElement(
props.leftHeaderActionsComponent,
{ addPortal }
),
});
}, [props.leftHeaderActionsComponent]);
return (
<div

View File

@ -58,20 +58,21 @@ You can create a Dockview through the use of the `DockviewReact` component.
import { DockviewReact } from 'dockview';
```
| Property | Type | Optional | Default | Description |
| --------------------- | ------------------------------------ | -------- | --------- | ------------------------------------------------------------ |
| onReady | (event: SplitviewReadyEvent) => void | No | | |
| components | object | No | | |
| tabComponents | object | Yes | | |
| watermarkComponent | object | Yes | | |
| hideBorders | boolean | Yes | false | |
| className | string | Yes | '' | |
| disableAutoResizing | boolean | Yes | false | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
| onDidDrop | Event | Yes | false | |
| showDndOverlay | Event | Yes | false | |
| defaultTabComponent | object | Yes | | |
| groupControlComponent | object | Yes | | |
| singleTabMode | 'fullwidth' \| 'default' | Yes | 'default' | |
| Property | Type | Optional | Default | Description |
| --------------------------- | ------------------------------------ | -------- | --------- | ------------------------------------------------------------ |
| onReady | (event: SplitviewReadyEvent) => void | No | | |
| components | object | No | | |
| tabComponents | object | Yes | | |
| watermarkComponent | object | Yes | | |
| hideBorders | boolean | Yes | false | |
| className | string | Yes | '' | |
| disableAutoResizing | boolean | Yes | false | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
| onDidDrop | Event | Yes | false | |
| showDndOverlay | Event | Yes | false | |
| defaultTabComponent | object | Yes | | |
| leftHeaderActionsComponent | object | Yes | | |
| rightHeaderActionsComponent | object | Yes | | |
| singleTabMode | 'fullwidth' \| 'default' | Yes | 'default' | |
## Dockview API

View File

@ -26,7 +26,7 @@ const components = {
},
};
const GroupControlComponent = (props: IDockviewGroupControlProps) => {
const RightHeaderActions = (props: IDockviewGroupControlProps) => {
const isGroupActive = props.isGroupActive;
const activePanel = props.activePanel;
@ -87,7 +87,7 @@ const DockviewGroupControl = () => {
<DockviewReact
onReady={onReady}
components={components}
groupControlComponent={GroupControlComponent}
rightHeaderActionsComponent={RightHeaderActions}
className="dockview-theme-abyss"
/>
);