mirror of
https://github.com/mathuo/dockview
synced 2025-02-09 01:45:45 +00:00
Support bottom and right anchor for Overlay
This commit is contained in:
parent
ce381f8ce9
commit
bbdb99dbb5
@ -1,7 +1,14 @@
|
|||||||
import { Overlay } from '../../dnd/overlay';
|
import { Overlay } from '../../dnd/overlay';
|
||||||
|
|
||||||
|
const mockGetBoundingClientRect = ({ left, top, height, width }: { left: number, top: number, height: number, width: number }) => {
|
||||||
|
const result = { left, top, height, width, right: left + width, bottom: top + height, x: left, y: top };
|
||||||
|
return {
|
||||||
|
...result, toJSON: () => (result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('overlay', () => {
|
describe('overlay', () => {
|
||||||
test('toJSON', () => {
|
test('toJSON, top left', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
|
||||||
@ -23,11 +30,11 @@ describe('overlay', () => {
|
|||||||
container.childNodes.item(0) as HTMLElement,
|
container.childNodes.item(0) as HTMLElement,
|
||||||
'getBoundingClientRect'
|
'getBoundingClientRect'
|
||||||
).mockImplementation(() => {
|
).mockImplementation(() => {
|
||||||
return { left: 80, top: 100, width: 40, height: 50 } as any;
|
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 });
|
||||||
});
|
});
|
||||||
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
() => {
|
() => {
|
||||||
return { left: 20, top: 30, width: 100, height: 100 } as any;
|
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -39,7 +46,45 @@ describe('overlay', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('that out-of-bounds dimensions are fixed', () => {
|
test('toJSON, bottom right', () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const content = document.createElement('div');
|
||||||
|
|
||||||
|
document.body.appendChild(container);
|
||||||
|
container.appendChild(content);
|
||||||
|
|
||||||
|
const cut = new Overlay({
|
||||||
|
height: 200,
|
||||||
|
width: 100,
|
||||||
|
right: 10,
|
||||||
|
bottom: 20,
|
||||||
|
minimumInViewportWidth: 0,
|
||||||
|
minimumInViewportHeight: 0,
|
||||||
|
container,
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.spyOn(
|
||||||
|
container.childNodes.item(0) as HTMLElement,
|
||||||
|
'getBoundingClientRect'
|
||||||
|
).mockImplementation(() => {
|
||||||
|
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 });
|
||||||
|
});
|
||||||
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
|
() => {
|
||||||
|
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(cut.toJSON()).toEqual({
|
||||||
|
bottom: -20,
|
||||||
|
right: 0,
|
||||||
|
width: 40,
|
||||||
|
height: 50,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that out-of-bounds dimensions are fixed, top left', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
|
||||||
@ -61,11 +106,11 @@ describe('overlay', () => {
|
|||||||
container.childNodes.item(0) as HTMLElement,
|
container.childNodes.item(0) as HTMLElement,
|
||||||
'getBoundingClientRect'
|
'getBoundingClientRect'
|
||||||
).mockImplementation(() => {
|
).mockImplementation(() => {
|
||||||
return { left: 80, top: 100, width: 40, height: 50 } as any;
|
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 });
|
||||||
});
|
});
|
||||||
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
() => {
|
() => {
|
||||||
return { left: 20, top: 30, width: 100, height: 100 } as any;
|
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,7 +122,45 @@ describe('overlay', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('setBounds', () => {
|
test('that out-of-bounds dimensions are fixed, bottom right', () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const content = document.createElement('div');
|
||||||
|
|
||||||
|
document.body.appendChild(container);
|
||||||
|
container.appendChild(content);
|
||||||
|
|
||||||
|
const cut = new Overlay({
|
||||||
|
height: 200,
|
||||||
|
width: 100,
|
||||||
|
bottom: -1000,
|
||||||
|
right: -1000,
|
||||||
|
minimumInViewportWidth: 0,
|
||||||
|
minimumInViewportHeight: 0,
|
||||||
|
container,
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.spyOn(
|
||||||
|
container.childNodes.item(0) as HTMLElement,
|
||||||
|
'getBoundingClientRect'
|
||||||
|
).mockImplementation(() => {
|
||||||
|
return mockGetBoundingClientRect({ left: 80, top: 100, width: 40, height: 50 });
|
||||||
|
});
|
||||||
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
|
() => {
|
||||||
|
return mockGetBoundingClientRect({ left: 20, top: 30, width: 100, height: 100 });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(cut.toJSON()).toEqual({
|
||||||
|
bottom: -20,
|
||||||
|
right: 0,
|
||||||
|
width: 40,
|
||||||
|
height: 50,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setBounds, top left', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
|
||||||
@ -101,11 +184,11 @@ describe('overlay', () => {
|
|||||||
expect(element).toBeTruthy();
|
expect(element).toBeTruthy();
|
||||||
|
|
||||||
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
|
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
|
||||||
return { left: 300, top: 400, width: 1000, height: 1000 } as any;
|
return mockGetBoundingClientRect({ left: 300, top: 400, width: 200, height: 100 });
|
||||||
});
|
});
|
||||||
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
() => {
|
() => {
|
||||||
return { left: 0, top: 0, width: 1000, height: 1000 } as any;
|
return mockGetBoundingClientRect({ left: 0, top: 0, width: 1000, height: 1000 });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -117,6 +200,46 @@ describe('overlay', () => {
|
|||||||
expect(element.style.top).toBe('400px');
|
expect(element.style.top).toBe('400px');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('setBounds, bottom right', () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const content = document.createElement('div');
|
||||||
|
|
||||||
|
document.body.appendChild(container);
|
||||||
|
container.appendChild(content);
|
||||||
|
|
||||||
|
const cut = new Overlay({
|
||||||
|
height: 1000,
|
||||||
|
width: 1000,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
minimumInViewportWidth: 0,
|
||||||
|
minimumInViewportHeight: 0,
|
||||||
|
container,
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
|
||||||
|
const element: HTMLElement = container.querySelector(
|
||||||
|
'.dv-resize-container'
|
||||||
|
)!;
|
||||||
|
expect(element).toBeTruthy();
|
||||||
|
|
||||||
|
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
|
||||||
|
return mockGetBoundingClientRect({ left: 500, top: 500, width: 200, height: 100 });
|
||||||
|
});
|
||||||
|
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
|
||||||
|
() => {
|
||||||
|
return mockGetBoundingClientRect({ left: 0, top: 0, width: 1000, height: 1000 });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
cut.setBounds({ height: 100, width: 200, right: 300, bottom: 400 });
|
||||||
|
|
||||||
|
expect(element.style.height).toBe('100px');
|
||||||
|
expect(element.style.width).toBe('200px');
|
||||||
|
expect(element.style.right).toBe('300px');
|
||||||
|
expect(element.style.bottom).toBe('400px');
|
||||||
|
});
|
||||||
|
|
||||||
test('that the resize handles are added', () => {
|
test('that the resize handles are added', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const content = document.createElement('div');
|
const content = document.createElement('div');
|
||||||
|
@ -42,7 +42,7 @@ import {
|
|||||||
GroupDragEvent,
|
GroupDragEvent,
|
||||||
TabDragEvent,
|
TabDragEvent,
|
||||||
} from '../dockview/components/titlebar/tabsContainer';
|
} from '../dockview/components/titlebar/tabsContainer';
|
||||||
import { Box } from '../types';
|
import { AnchoredBox, Box } from '../types';
|
||||||
import {
|
import {
|
||||||
DockviewDidDropEvent,
|
DockviewDidDropEvent,
|
||||||
DockviewWillDropEvent,
|
DockviewWillDropEvent,
|
||||||
@ -139,7 +139,7 @@ export class SplitviewApi implements CommonApi<SerializedSplitview> {
|
|||||||
return this.component.onDidRemoveView;
|
return this.component.onDidRemoveView;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private readonly component: ISplitviewComponent) {}
|
constructor(private readonly component: ISplitviewComponent) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update configuratable options.
|
* Update configuratable options.
|
||||||
@ -295,7 +295,7 @@ export class PaneviewApi implements CommonApi<SerializedPaneview> {
|
|||||||
return emitter.event;
|
return emitter.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private readonly component: IPaneviewComponent) {}
|
constructor(private readonly component: IPaneviewComponent) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a panel given the panel object.
|
* Remove a panel given the panel object.
|
||||||
@ -459,7 +459,7 @@ export class GridviewApi implements CommonApi<SerializedGridviewComponent> {
|
|||||||
this.component.updateOptions({ orientation: value });
|
this.component.updateOptions({ orientation: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private readonly component: IGridviewComponent) {}
|
constructor(private readonly component: IGridviewComponent) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Focus the component. Will try to focus an active panel if one exists.
|
* Focus the component. Will try to focus an active panel if one exists.
|
||||||
@ -728,7 +728,7 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
return this.component.activeGroup;
|
return this.component.activeGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private readonly component: IDockviewComponent) {}
|
constructor(private readonly component: IDockviewComponent) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Focus the component. Will try to focus an active panel if one exists.
|
* Focus the component. Will try to focus an active panel if one exists.
|
||||||
@ -800,9 +800,15 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
*/
|
*/
|
||||||
addFloatingGroup(
|
addFloatingGroup(
|
||||||
item: IDockviewPanel | DockviewGroupPanel,
|
item: IDockviewPanel | DockviewGroupPanel,
|
||||||
coord?: { x: number; y: number }
|
coord?: { x: number; y: number },
|
||||||
|
options?: {
|
||||||
|
position?: AnchoredBox;
|
||||||
|
skipRemoveGroup?: boolean;
|
||||||
|
inDragMode?: boolean;
|
||||||
|
skipActiveGroup?: boolean;
|
||||||
|
}
|
||||||
): void {
|
): void {
|
||||||
return this.component.addFloatingGroup(item, coord);
|
return this.component.addFloatingGroup(item, coord, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
|
export const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
|
||||||
|
|
||||||
export const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100 };
|
export const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100, width: 300, height: 300 };
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
} from '../events';
|
} from '../events';
|
||||||
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
|
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
|
||||||
import { clamp } from '../math';
|
import { clamp } from '../math';
|
||||||
import { Box } from '../types';
|
import { AnchoredBox } from '../types';
|
||||||
|
|
||||||
const bringElementToFront = (() => {
|
const bringElementToFront = (() => {
|
||||||
let previous: HTMLElement | null = null;
|
let previous: HTMLElement | null = null;
|
||||||
@ -49,7 +49,7 @@ export class Overlay extends CompositeDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly options: Box & {
|
private readonly options: AnchoredBox & {
|
||||||
container: HTMLElement;
|
container: HTMLElement;
|
||||||
content: HTMLElement;
|
content: HTMLElement;
|
||||||
minimumInViewportWidth?: number;
|
minimumInViewportWidth?: number;
|
||||||
@ -78,23 +78,35 @@ export class Overlay extends CompositeDisposable {
|
|||||||
this.setBounds({
|
this.setBounds({
|
||||||
height: this.options.height,
|
height: this.options.height,
|
||||||
width: this.options.width,
|
width: this.options.width,
|
||||||
top: this.options.top,
|
...("top" in this.options && { top: this.options.top }),
|
||||||
left: this.options.left,
|
...("bottom" in this.options && { bottom: this.options.bottom }),
|
||||||
|
...("left" in this.options && { left: this.options.left }),
|
||||||
|
...("right" in this.options && { right: this.options.right })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setBounds(bounds: Partial<Box> = {}): void {
|
setBounds(bounds: Partial<AnchoredBox> = {}): void {
|
||||||
if (typeof bounds.height === 'number') {
|
if (typeof bounds.height === 'number') {
|
||||||
this._element.style.height = `${bounds.height}px`;
|
this._element.style.height = `${bounds.height}px`;
|
||||||
}
|
}
|
||||||
if (typeof bounds.width === 'number') {
|
if (typeof bounds.width === 'number') {
|
||||||
this._element.style.width = `${bounds.width}px`;
|
this._element.style.width = `${bounds.width}px`;
|
||||||
}
|
}
|
||||||
if (typeof bounds.top === 'number') {
|
if ("top" in bounds && typeof bounds.top === 'number') {
|
||||||
this._element.style.top = `${bounds.top}px`;
|
this._element.style.top = `${bounds.top}px`;
|
||||||
|
this._element.style.bottom = "auto";
|
||||||
}
|
}
|
||||||
if (typeof bounds.left === 'number') {
|
if ("bottom" in bounds && typeof bounds.bottom === 'number') {
|
||||||
|
this._element.style.bottom = `${bounds.bottom}px`;
|
||||||
|
this._element.style.top = "auto";
|
||||||
|
}
|
||||||
|
if ("left" in bounds && typeof bounds.left === 'number') {
|
||||||
this._element.style.left = `${bounds.left}px`;
|
this._element.style.left = `${bounds.left}px`;
|
||||||
|
this._element.style.right = "auto";
|
||||||
|
}
|
||||||
|
if ("right" in bounds && typeof bounds.right === 'number') {
|
||||||
|
this._element.style.right = `${bounds.right}px`;
|
||||||
|
this._element.style.left = "auto";
|
||||||
}
|
}
|
||||||
|
|
||||||
const containerRect = this.options.container.getBoundingClientRect();
|
const containerRect = this.options.container.getBoundingClientRect();
|
||||||
@ -106,39 +118,77 @@ export class Overlay extends CompositeDisposable {
|
|||||||
const xOffset = Math.max(0, this.getMinimumWidth(overlayRect.width));
|
const xOffset = Math.max(0, this.getMinimumWidth(overlayRect.width));
|
||||||
|
|
||||||
// a minimum height of minimumViewportHeight must be inside the viewport
|
// a minimum height of minimumViewportHeight must be inside the viewport
|
||||||
const yOffset =
|
const yOffset = Math.max(0, this.getMinimumHeight(overlayRect.height));
|
||||||
typeof this.options.minimumInViewportHeight === 'number'
|
|
||||||
? Math.max(0, this.getMinimumHeight(overlayRect.height))
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
const left = clamp(
|
if ("top" in bounds && typeof bounds.top === 'number') {
|
||||||
overlayRect.left - containerRect.left,
|
const top = clamp(
|
||||||
-xOffset,
|
overlayRect.top - containerRect.top,
|
||||||
Math.max(0, containerRect.width - overlayRect.width + xOffset)
|
-yOffset,
|
||||||
);
|
Math.max(0, containerRect.height - overlayRect.height + yOffset)
|
||||||
|
);
|
||||||
|
this._element.style.top = `${top}px`;
|
||||||
|
this._element.style.bottom = "auto";
|
||||||
|
}
|
||||||
|
|
||||||
const top = clamp(
|
if ("bottom" in bounds && typeof bounds.bottom === 'number') {
|
||||||
overlayRect.top - containerRect.top,
|
const bottom = clamp(
|
||||||
-yOffset,
|
containerRect.bottom - overlayRect.bottom,
|
||||||
Math.max(0, containerRect.height - overlayRect.height + yOffset)
|
-yOffset,
|
||||||
);
|
Math.max(0, containerRect.height - overlayRect.height + yOffset)
|
||||||
|
);
|
||||||
|
this._element.style.bottom = `${bottom}px`;
|
||||||
|
this._element.style.top = "auto";
|
||||||
|
}
|
||||||
|
|
||||||
this._element.style.left = `${left}px`;
|
if ("left" in bounds && typeof bounds.left === 'number') {
|
||||||
this._element.style.top = `${top}px`;
|
const left = clamp(
|
||||||
|
overlayRect.left - containerRect.left,
|
||||||
|
-xOffset,
|
||||||
|
Math.max(0, containerRect.width - overlayRect.width + xOffset)
|
||||||
|
);
|
||||||
|
this._element.style.left = `${left}px`;
|
||||||
|
this._element.style.right = "auto";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("right" in bounds && typeof bounds.right === 'number') {
|
||||||
|
const right = clamp(
|
||||||
|
containerRect.right - overlayRect.right,
|
||||||
|
-xOffset,
|
||||||
|
Math.max(0, containerRect.width - overlayRect.width + xOffset)
|
||||||
|
);
|
||||||
|
this._element.style.right = `${right}px`;
|
||||||
|
this._element.style.left = "auto";
|
||||||
|
}
|
||||||
|
|
||||||
this._onDidChange.fire();
|
this._onDidChange.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): Box {
|
toJSON(): AnchoredBox {
|
||||||
const container = this.options.container.getBoundingClientRect();
|
const container = this.options.container.getBoundingClientRect();
|
||||||
const element = this._element.getBoundingClientRect();
|
const element = this._element.getBoundingClientRect();
|
||||||
|
|
||||||
return {
|
const result: any = {};
|
||||||
top: element.top - container.top,
|
|
||||||
left: element.left - container.left,
|
if (this._element.style.top !== "auto") {
|
||||||
width: element.width,
|
result.top = parseFloat(this._element.style.top);
|
||||||
height: element.height,
|
} else if (this._element.style.bottom !== "auto") {
|
||||||
};
|
result.bottom = parseFloat(this._element.style.bottom);
|
||||||
|
} else {
|
||||||
|
result.top = element.top - container.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._element.style.left !== "auto") {
|
||||||
|
result.left = parseFloat(this._element.style.left);
|
||||||
|
} else if (this._element.style.right !== "auto") {
|
||||||
|
result.right = parseFloat(this._element.style.right);
|
||||||
|
} else {
|
||||||
|
result.left = element.left - container.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.width = element.width;
|
||||||
|
result.height = element.height;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupDrag(
|
setupDrag(
|
||||||
@ -193,18 +243,7 @@ export class Overlay extends CompositeDisposable {
|
|||||||
);
|
);
|
||||||
const yOffset = Math.max(
|
const yOffset = Math.max(
|
||||||
0,
|
0,
|
||||||
this.options.minimumInViewportHeight
|
this.getMinimumHeight(overlayRect.height)
|
||||||
? this.getMinimumHeight(overlayRect.height)
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
|
|
||||||
const left = clamp(
|
|
||||||
x - offset.x,
|
|
||||||
-xOffset,
|
|
||||||
Math.max(
|
|
||||||
0,
|
|
||||||
containerRect.width - overlayRect.width + xOffset
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const top = clamp(
|
const top = clamp(
|
||||||
@ -216,7 +255,50 @@ export class Overlay extends CompositeDisposable {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setBounds({ top, left });
|
const bottom = clamp(
|
||||||
|
offset.y - y + containerRect.height - overlayRect.height,
|
||||||
|
-yOffset,
|
||||||
|
Math.max(
|
||||||
|
0,
|
||||||
|
containerRect.height - overlayRect.height + yOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const left = clamp(
|
||||||
|
x - offset.x,
|
||||||
|
-xOffset,
|
||||||
|
Math.max(
|
||||||
|
0,
|
||||||
|
containerRect.width - overlayRect.width + xOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const right = clamp(
|
||||||
|
offset.x - x + containerRect.width - overlayRect.width,
|
||||||
|
-xOffset,
|
||||||
|
Math.max(
|
||||||
|
0,
|
||||||
|
containerRect.width - overlayRect.width + xOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const bounds: any = {};
|
||||||
|
|
||||||
|
// Anchor to top or to bottom depending on which one is closer
|
||||||
|
if (top <= bottom) {
|
||||||
|
bounds.top = top;
|
||||||
|
} else {
|
||||||
|
bounds.bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anchor to left or to right depending on which one is closer
|
||||||
|
if (left <= right) {
|
||||||
|
bounds.left = left;
|
||||||
|
} else {
|
||||||
|
bounds.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setBounds(bounds);
|
||||||
}),
|
}),
|
||||||
addDisposableWindowListener(window, 'mouseup', () => {
|
addDisposableWindowListener(window, 'mouseup', () => {
|
||||||
toggleClass(
|
toggleClass(
|
||||||
@ -342,8 +424,10 @@ export class Overlay extends CompositeDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let top: number | undefined = undefined;
|
let top: number | undefined = undefined;
|
||||||
|
let bottom: number | undefined = undefined;
|
||||||
let height: number | undefined = undefined;
|
let height: number | undefined = undefined;
|
||||||
let left: number | undefined = undefined;
|
let left: number | undefined = undefined;
|
||||||
|
let right: number | undefined = undefined;
|
||||||
let width: number | undefined = undefined;
|
let width: number | undefined = undefined;
|
||||||
|
|
||||||
const moveTop = () => {
|
const moveTop = () => {
|
||||||
@ -353,20 +437,21 @@ export class Overlay extends CompositeDisposable {
|
|||||||
startPosition!.originalY +
|
startPosition!.originalY +
|
||||||
startPosition!.originalHeight >
|
startPosition!.originalHeight >
|
||||||
containerRect.height
|
containerRect.height
|
||||||
? this.getMinimumHeight(
|
? this.getMinimumHeight(containerRect.height)
|
||||||
containerRect.height
|
|
||||||
)
|
|
||||||
: Math.max(
|
: Math.max(
|
||||||
0,
|
0,
|
||||||
startPosition!.originalY +
|
startPosition!.originalY +
|
||||||
startPosition!.originalHeight -
|
startPosition!.originalHeight -
|
||||||
Overlay.MINIMUM_HEIGHT
|
Overlay.MINIMUM_HEIGHT
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
height =
|
height =
|
||||||
startPosition!.originalY +
|
startPosition!.originalY +
|
||||||
startPosition!.originalHeight -
|
startPosition!.originalHeight -
|
||||||
top;
|
top;
|
||||||
|
|
||||||
|
bottom = containerRect.height - top - height;
|
||||||
};
|
};
|
||||||
|
|
||||||
const moveBottom = () => {
|
const moveBottom = () => {
|
||||||
@ -380,10 +465,12 @@ export class Overlay extends CompositeDisposable {
|
|||||||
typeof this.options
|
typeof this.options
|
||||||
.minimumInViewportHeight === 'number'
|
.minimumInViewportHeight === 'number'
|
||||||
? -top +
|
? -top +
|
||||||
this.options.minimumInViewportHeight
|
this.options.minimumInViewportHeight
|
||||||
: Overlay.MINIMUM_HEIGHT,
|
: Overlay.MINIMUM_HEIGHT,
|
||||||
Number.MAX_VALUE
|
Number.MAX_VALUE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bottom = containerRect.height - top - height;
|
||||||
};
|
};
|
||||||
|
|
||||||
const moveLeft = () => {
|
const moveLeft = () => {
|
||||||
@ -395,17 +482,19 @@ export class Overlay extends CompositeDisposable {
|
|||||||
containerRect.width
|
containerRect.width
|
||||||
? this.getMinimumWidth(containerRect.width)
|
? this.getMinimumWidth(containerRect.width)
|
||||||
: Math.max(
|
: Math.max(
|
||||||
0,
|
0,
|
||||||
startPosition!.originalX +
|
startPosition!.originalX +
|
||||||
startPosition!.originalWidth -
|
startPosition!.originalWidth -
|
||||||
Overlay.MINIMUM_WIDTH
|
Overlay.MINIMUM_WIDTH
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
width =
|
width =
|
||||||
startPosition!.originalX +
|
startPosition!.originalX +
|
||||||
startPosition!.originalWidth -
|
startPosition!.originalWidth -
|
||||||
left;
|
left;
|
||||||
|
|
||||||
|
right = containerRect.width - left - width;
|
||||||
};
|
};
|
||||||
|
|
||||||
const moveRight = () => {
|
const moveRight = () => {
|
||||||
@ -419,10 +508,12 @@ export class Overlay extends CompositeDisposable {
|
|||||||
typeof this.options
|
typeof this.options
|
||||||
.minimumInViewportWidth === 'number'
|
.minimumInViewportWidth === 'number'
|
||||||
? -left +
|
? -left +
|
||||||
this.options.minimumInViewportWidth
|
this.options.minimumInViewportWidth
|
||||||
: Overlay.MINIMUM_WIDTH,
|
: Overlay.MINIMUM_WIDTH,
|
||||||
Number.MAX_VALUE
|
Number.MAX_VALUE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
right = containerRect.width - left - width;
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
@ -456,7 +547,26 @@ export class Overlay extends CompositeDisposable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setBounds({ height, width, top, left });
|
const bounds: any = {};
|
||||||
|
|
||||||
|
// Anchor to top or to bottom depending on which one is closer
|
||||||
|
if (top! <= bottom!) {
|
||||||
|
bounds.top = top;
|
||||||
|
} else {
|
||||||
|
bounds.bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anchor to left or to right depending on which one is closer
|
||||||
|
if (left! <= right!) {
|
||||||
|
bounds.left = left;
|
||||||
|
} else {
|
||||||
|
bounds.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds.height = height;
|
||||||
|
bounds.width = width;
|
||||||
|
|
||||||
|
this.setBounds(bounds);
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
dispose: () => {
|
dispose: () => {
|
||||||
@ -485,7 +595,7 @@ export class Overlay extends CompositeDisposable {
|
|||||||
if (typeof this.options.minimumInViewportHeight === 'number') {
|
if (typeof this.options.minimumInViewportHeight === 'number') {
|
||||||
return height - this.options.minimumInViewportHeight;
|
return height - this.options.minimumInViewportHeight;
|
||||||
}
|
}
|
||||||
return height;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
override dispose(): void {
|
override dispose(): void {
|
||||||
|
@ -57,7 +57,7 @@ import {
|
|||||||
GroupDragEvent,
|
GroupDragEvent,
|
||||||
TabDragEvent,
|
TabDragEvent,
|
||||||
} from './components/titlebar/tabsContainer';
|
} from './components/titlebar/tabsContainer';
|
||||||
import { Box } from '../types';
|
import { AnchoredBox, Box } from '../types';
|
||||||
import {
|
import {
|
||||||
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
||||||
DEFAULT_FLOATING_GROUP_POSITION,
|
DEFAULT_FLOATING_GROUP_POSITION,
|
||||||
@ -126,7 +126,7 @@ export interface PanelReference {
|
|||||||
|
|
||||||
export interface SerializedFloatingGroup {
|
export interface SerializedFloatingGroup {
|
||||||
data: GroupPanelViewState;
|
data: GroupPanelViewState;
|
||||||
position: Box;
|
position: AnchoredBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SerializedPopoutGroup {
|
export interface SerializedPopoutGroup {
|
||||||
@ -208,7 +208,10 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|||||||
//
|
//
|
||||||
addFloatingGroup(
|
addFloatingGroup(
|
||||||
item: IDockviewPanel | DockviewGroupPanel,
|
item: IDockviewPanel | DockviewGroupPanel,
|
||||||
coord?: { x: number; y: number }
|
coord?: { x: number; y: number },
|
||||||
|
options?: {
|
||||||
|
position?: AnchoredBox
|
||||||
|
}
|
||||||
): void;
|
): void;
|
||||||
addPopoutGroup(
|
addPopoutGroup(
|
||||||
item: IDockviewPanel | DockviewGroupPanel,
|
item: IDockviewPanel | DockviewGroupPanel,
|
||||||
@ -223,8 +226,7 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|||||||
|
|
||||||
export class DockviewComponent
|
export class DockviewComponent
|
||||||
extends BaseGrid<DockviewGroupPanel>
|
extends BaseGrid<DockviewGroupPanel>
|
||||||
implements IDockviewComponent
|
implements IDockviewComponent {
|
||||||
{
|
|
||||||
private readonly nextGroupId = sequentialNumberGenerator();
|
private readonly nextGroupId = sequentialNumberGenerator();
|
||||||
private readonly _deserializer = new DefaultDockviewDeserialzier(this);
|
private readonly _deserializer = new DefaultDockviewDeserialzier(this);
|
||||||
private readonly _api: DockviewApi;
|
private readonly _api: DockviewApi;
|
||||||
@ -750,6 +752,7 @@ export class DockviewComponent
|
|||||||
item: DockviewPanel | DockviewGroupPanel,
|
item: DockviewPanel | DockviewGroupPanel,
|
||||||
coord?: { x?: number; y?: number; height?: number; width?: number },
|
coord?: { x?: number; y?: number; height?: number; width?: number },
|
||||||
options?: {
|
options?: {
|
||||||
|
position?: AnchoredBox;
|
||||||
skipRemoveGroup?: boolean;
|
skipRemoveGroup?: boolean;
|
||||||
inDragMode: boolean;
|
inDragMode: boolean;
|
||||||
skipActiveGroup?: boolean;
|
skipActiveGroup?: boolean;
|
||||||
@ -814,34 +817,70 @@ export class DockviewComponent
|
|||||||
|
|
||||||
group.model.location = { type: 'floating' };
|
group.model.location = { type: 'floating' };
|
||||||
|
|
||||||
const overlayLeft =
|
function getAnchoredBox(): AnchoredBox {
|
||||||
typeof coord?.x === 'number'
|
if (options?.position) {
|
||||||
? Math.max(coord.x, 0)
|
const result: any = {};
|
||||||
: DEFAULT_FLOATING_GROUP_POSITION.left;
|
if ("left" in options.position) {
|
||||||
const overlayTop =
|
result.left = Math.max(options.position.left, 0)
|
||||||
typeof coord?.y === 'number'
|
} else if ("right" in options.position) {
|
||||||
? Math.max(coord.y, 0)
|
result.right = Math.max(options.position.right, 0)
|
||||||
: DEFAULT_FLOATING_GROUP_POSITION.top;
|
} else {
|
||||||
|
result.left = DEFAULT_FLOATING_GROUP_POSITION.left;
|
||||||
|
}
|
||||||
|
if ("top" in options.position) {
|
||||||
|
result.top = Math.max(options.position.top, 0)
|
||||||
|
} else if ("bottom" in options.position) {
|
||||||
|
result.bottom = Math.max(options.position.bottom, 0)
|
||||||
|
} else {
|
||||||
|
result.top = DEFAULT_FLOATING_GROUP_POSITION.top;
|
||||||
|
}
|
||||||
|
if ("width" in options.position) {
|
||||||
|
result.width = Math.max(options.position.width, 0)
|
||||||
|
} else {
|
||||||
|
result.width = DEFAULT_FLOATING_GROUP_POSITION.width;
|
||||||
|
}
|
||||||
|
if ("height" in options.position) {
|
||||||
|
result.height = Math.max(options.position.height, 0)
|
||||||
|
} else {
|
||||||
|
result.height = DEFAULT_FLOATING_GROUP_POSITION.height;
|
||||||
|
}
|
||||||
|
return result as AnchoredBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: typeof coord?.x === 'number'
|
||||||
|
? Math.max(coord.x, 0)
|
||||||
|
: DEFAULT_FLOATING_GROUP_POSITION.left,
|
||||||
|
top: typeof coord?.y === 'number'
|
||||||
|
? Math.max(coord.y, 0)
|
||||||
|
: DEFAULT_FLOATING_GROUP_POSITION.top,
|
||||||
|
width: typeof coord?.width === 'number'
|
||||||
|
? Math.max(coord.width, 0)
|
||||||
|
: DEFAULT_FLOATING_GROUP_POSITION.width,
|
||||||
|
height: typeof coord?.height === 'number'
|
||||||
|
? Math.max(coord.height, 0)
|
||||||
|
: DEFAULT_FLOATING_GROUP_POSITION.height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const anchoredBox = getAnchoredBox();
|
||||||
|
|
||||||
const overlay = new Overlay({
|
const overlay = new Overlay({
|
||||||
container: this.gridview.element,
|
container: this.gridview.element,
|
||||||
content: group.element,
|
content: group.element,
|
||||||
height: coord?.height ?? 300,
|
...anchoredBox,
|
||||||
width: coord?.width ?? 300,
|
|
||||||
left: overlayLeft,
|
|
||||||
top: overlayTop,
|
|
||||||
minimumInViewportWidth:
|
minimumInViewportWidth:
|
||||||
this.options.floatingGroupBounds === 'boundedWithinViewport'
|
this.options.floatingGroupBounds === 'boundedWithinViewport'
|
||||||
? undefined
|
? undefined
|
||||||
: this.options.floatingGroupBounds
|
: this.options.floatingGroupBounds
|
||||||
?.minimumWidthWithinViewport ??
|
?.minimumWidthWithinViewport ??
|
||||||
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
||||||
minimumInViewportHeight:
|
minimumInViewportHeight:
|
||||||
this.options.floatingGroupBounds === 'boundedWithinViewport'
|
this.options.floatingGroupBounds === 'boundedWithinViewport'
|
||||||
? undefined
|
? undefined
|
||||||
: this.options.floatingGroupBounds
|
: this.options.floatingGroupBounds
|
||||||
?.minimumHeightWithinViewport ??
|
?.minimumHeightWithinViewport ??
|
||||||
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
|
||||||
});
|
});
|
||||||
|
|
||||||
const el = group.element.querySelector('.void-container');
|
const el = group.element.querySelector('.void-container');
|
||||||
@ -1194,13 +1233,8 @@ export class DockviewComponent
|
|||||||
|
|
||||||
this.addFloatingGroup(
|
this.addFloatingGroup(
|
||||||
group,
|
group,
|
||||||
{
|
undefined,
|
||||||
x: position.left,
|
{ position: position, skipRemoveGroup: true, inDragMode: false }
|
||||||
y: position.top,
|
|
||||||
height: position.height,
|
|
||||||
width: position.width,
|
|
||||||
},
|
|
||||||
{ skipRemoveGroup: true, inDragMode: false }
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1338,7 +1372,7 @@ export class DockviewComponent
|
|||||||
referenceGroup =
|
referenceGroup =
|
||||||
typeof options.position.referenceGroup === 'string'
|
typeof options.position.referenceGroup === 'string'
|
||||||
? this._groups.get(options.position.referenceGroup)
|
? this._groups.get(options.position.referenceGroup)
|
||||||
?.value
|
?.value
|
||||||
: options.position.referenceGroup;
|
: options.position.referenceGroup;
|
||||||
|
|
||||||
if (!referenceGroup) {
|
if (!referenceGroup) {
|
||||||
@ -1380,7 +1414,7 @@ export class DockviewComponent
|
|||||||
|
|
||||||
const o =
|
const o =
|
||||||
typeof options.floating === 'object' &&
|
typeof options.floating === 'object' &&
|
||||||
options.floating !== null
|
options.floating !== null
|
||||||
? options.floating
|
? options.floating
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
@ -1433,7 +1467,7 @@ export class DockviewComponent
|
|||||||
|
|
||||||
const coordinates =
|
const coordinates =
|
||||||
typeof options.floating === 'object' &&
|
typeof options.floating === 'object' &&
|
||||||
options.floating !== null
|
options.floating !== null
|
||||||
? options.floating
|
? options.floating
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
@ -1471,9 +1505,9 @@ export class DockviewComponent
|
|||||||
skipDispose: boolean;
|
skipDispose: boolean;
|
||||||
skipSetActiveGroup?: boolean;
|
skipSetActiveGroup?: boolean;
|
||||||
} = {
|
} = {
|
||||||
removeEmptyGroup: true,
|
removeEmptyGroup: true,
|
||||||
skipDispose: false,
|
skipDispose: false,
|
||||||
}
|
}
|
||||||
): void {
|
): void {
|
||||||
const group = panel.group;
|
const group = panel.group;
|
||||||
|
|
||||||
@ -1538,8 +1572,8 @@ export class DockviewComponent
|
|||||||
const referencePanel =
|
const referencePanel =
|
||||||
typeof options.referencePanel === 'string'
|
typeof options.referencePanel === 'string'
|
||||||
? this.panels.find(
|
? this.panels.find(
|
||||||
(panel) => panel.id === options.referencePanel
|
(panel) => panel.id === options.referencePanel
|
||||||
)
|
)
|
||||||
: options.referencePanel;
|
: options.referencePanel;
|
||||||
|
|
||||||
if (!referencePanel) {
|
if (!referencePanel) {
|
||||||
@ -1604,11 +1638,11 @@ export class DockviewComponent
|
|||||||
group: DockviewGroupPanel,
|
group: DockviewGroupPanel,
|
||||||
options?:
|
options?:
|
||||||
| {
|
| {
|
||||||
skipActive?: boolean;
|
skipActive?: boolean;
|
||||||
skipDispose?: boolean;
|
skipDispose?: boolean;
|
||||||
skipPopoutAssociated?: boolean;
|
skipPopoutAssociated?: boolean;
|
||||||
skipPopoutReturn?: boolean;
|
skipPopoutReturn?: boolean;
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
): void {
|
): void {
|
||||||
this.doRemoveGroup(group, options);
|
this.doRemoveGroup(group, options);
|
||||||
@ -1618,11 +1652,11 @@ export class DockviewComponent
|
|||||||
group: DockviewGroupPanel,
|
group: DockviewGroupPanel,
|
||||||
options?:
|
options?:
|
||||||
| {
|
| {
|
||||||
skipActive?: boolean;
|
skipActive?: boolean;
|
||||||
skipDispose?: boolean;
|
skipDispose?: boolean;
|
||||||
skipPopoutAssociated?: boolean;
|
skipPopoutAssociated?: boolean;
|
||||||
skipPopoutReturn?: boolean;
|
skipPopoutReturn?: boolean;
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
): DockviewGroupPanel {
|
): DockviewGroupPanel {
|
||||||
const panels = [...group.panels]; // reassign since group panels will mutate
|
const panels = [...group.panels]; // reassign since group panels will mutate
|
||||||
|
@ -1,37 +1,22 @@
|
|||||||
import { Overlay } from '../dnd/overlay';
|
import { Overlay } from '../dnd/overlay';
|
||||||
import { CompositeDisposable } from '../lifecycle';
|
import { CompositeDisposable } from '../lifecycle';
|
||||||
|
import { AnchoredBox } from '../types';
|
||||||
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
|
|
||||||
export interface IDockviewFloatingGroupPanel {
|
export interface IDockviewFloatingGroupPanel {
|
||||||
readonly group: IDockviewGroupPanel;
|
readonly group: IDockviewGroupPanel;
|
||||||
position(
|
position(bounds: Partial<AnchoredBox>): void;
|
||||||
bounds: Partial<{
|
|
||||||
top: number;
|
|
||||||
left: number;
|
|
||||||
height: number;
|
|
||||||
width: number;
|
|
||||||
}>
|
|
||||||
): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DockviewFloatingGroupPanel
|
export class DockviewFloatingGroupPanel
|
||||||
extends CompositeDisposable
|
extends CompositeDisposable
|
||||||
implements IDockviewFloatingGroupPanel
|
implements IDockviewFloatingGroupPanel {
|
||||||
{
|
|
||||||
constructor(readonly group: DockviewGroupPanel, readonly overlay: Overlay) {
|
constructor(readonly group: DockviewGroupPanel, readonly overlay: Overlay) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.addDisposables(overlay);
|
this.addDisposables(overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
position(
|
position(bounds: Partial<AnchoredBox>): void {
|
||||||
bounds: Partial<{
|
|
||||||
top: number;
|
|
||||||
left: number;
|
|
||||||
height: number;
|
|
||||||
width: number;
|
|
||||||
}>
|
|
||||||
): void {
|
|
||||||
this.overlay.setBounds(bounds);
|
this.overlay.setBounds(bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
import { IDockviewPanel } from './dockviewPanel';
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
||||||
import { IGroupHeaderProps } from './framework';
|
import { IGroupHeaderProps } from './framework';
|
||||||
|
import { AnchoredBox } from '../types';
|
||||||
|
|
||||||
export interface IHeaderActionsRenderer extends IDisposable {
|
export interface IHeaderActionsRenderer extends IDisposable {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
@ -37,11 +38,11 @@ export interface DockviewOptions {
|
|||||||
singleTabMode?: 'fullwidth' | 'default';
|
singleTabMode?: 'fullwidth' | 'default';
|
||||||
disableFloatingGroups?: boolean;
|
disableFloatingGroups?: boolean;
|
||||||
floatingGroupBounds?:
|
floatingGroupBounds?:
|
||||||
| 'boundedWithinViewport'
|
| 'boundedWithinViewport'
|
||||||
| {
|
| {
|
||||||
minimumHeightWithinViewport?: number;
|
minimumHeightWithinViewport?: number;
|
||||||
minimumWidthWithinViewport?: number;
|
minimumWidthWithinViewport?: number;
|
||||||
};
|
};
|
||||||
popoutUrl?: string;
|
popoutUrl?: string;
|
||||||
defaultRenderer?: DockviewPanelRenderer;
|
defaultRenderer?: DockviewPanelRenderer;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
@ -74,7 +75,7 @@ export class DockviewUnhandledDragOverEvent implements DockviewDndOverlayEvent {
|
|||||||
readonly position: Position,
|
readonly position: Position,
|
||||||
readonly getData: () => PanelTransfer | undefined,
|
readonly getData: () => PanelTransfer | undefined,
|
||||||
readonly group?: DockviewGroupPanel
|
readonly group?: DockviewGroupPanel
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
accept(): void {
|
accept(): void {
|
||||||
this._isAccepted = true;
|
this._isAccepted = true;
|
||||||
@ -176,13 +177,8 @@ export function isPanelOptionsWithGroup(
|
|||||||
|
|
||||||
type AddPanelFloatingGroupUnion = {
|
type AddPanelFloatingGroupUnion = {
|
||||||
floating:
|
floating:
|
||||||
| {
|
| Partial<AnchoredBox>
|
||||||
height?: number;
|
| true;
|
||||||
width?: number;
|
|
||||||
x?: number;
|
|
||||||
y?: number;
|
|
||||||
}
|
|
||||||
| true;
|
|
||||||
position: never;
|
position: never;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,3 +8,7 @@ export interface Box {
|
|||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AnchoredBox =
|
||||||
|
({ top: number, height: number } | { bottom: number, height: number }) &
|
||||||
|
({ left: number, width: number } | { right: number, width: number });
|
@ -29,7 +29,14 @@ const PanelAction = (props: {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const panel = props.api.getPanel(props.panelId);
|
const panel = props.api.getPanel(props.panelId);
|
||||||
if (panel) {
|
if (panel) {
|
||||||
props.api.addFloatingGroup(panel);
|
props.api.addFloatingGroup(panel, undefined, {
|
||||||
|
position: {
|
||||||
|
width: 400,
|
||||||
|
height: 300,
|
||||||
|
bottom: 20,
|
||||||
|
right: 20,
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -14,7 +14,7 @@ export function defaultConfig(api: DockviewApi) {
|
|||||||
id: 'panel_1',
|
id: 'panel_1',
|
||||||
component: 'default',
|
component: 'default',
|
||||||
renderer: 'always',
|
renderer: 'always',
|
||||||
title: 'Panel 1',
|
title: 'Panel 1'
|
||||||
});
|
});
|
||||||
|
|
||||||
api.addPanel({
|
api.addPanel({
|
||||||
|
Loading…
Reference in New Issue
Block a user