Merge branch 'master' of https://github.com/mathuo/dockview into 936-handle-browser-blocked-popups

This commit is contained in:
mathuo 2025-06-15 21:59:18 +01:00
commit b28245b4af
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
16 changed files with 150 additions and 42 deletions

View File

@ -2,7 +2,7 @@
"packages": [ "packages": [
"packages/*" "packages/*"
], ],
"version": "4.2.5", "version": "4.3.1",
"npmClient": "yarn", "npmClient": "yarn",
"command": { "command": {
"publish": { "publish": {

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-angular", "name": "dockview-angular",
"version": "4.2.5", "version": "4.3.1",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews", "description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [ "keywords": [
"splitview", "splitview",
@ -54,6 +54,6 @@
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage" "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
}, },
"dependencies": { "dependencies": {
"dockview-core": "^4.2.5" "dockview-core": "^4.3.1"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-core", "name": "dockview-core",
"version": "4.2.5", "version": "4.3.1",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews", "description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [ "keywords": [
"splitview", "splitview",

View File

@ -5597,6 +5597,67 @@ describe('dockviewComponent', () => {
expect(dockview.groups.length).toBe(0); expect(dockview.groups.length).toBe(0);
}); });
test('popout single panel -> save layout -> load layout', async () => {
const container = document.createElement('div');
window.open = () => setupMockWindow();
const dockview = new DockviewComponent(container, {
createComponent(options) {
switch (options.name) {
case 'default':
return new PanelContentPartTest(
options.id,
options.name
);
default:
throw new Error(`unsupported`);
}
},
});
dockview.layout(1000, 500);
const panel1 = dockview.addPanel({
id: 'panel_1',
component: 'default',
});
const panel2 = dockview.addPanel({
id: 'panel_2',
component: 'default',
});
const panel3 = dockview.addPanel({
id: 'panel_3',
component: 'default',
});
const panel4 = dockview.addPanel({
id: 'panel_4',
component: 'default',
position: { direction: 'right' },
});
expect(dockview.panels.length).toBe(4);
expect(dockview.groups.length).toBe(2);
expect(await dockview.addPopoutGroup(panel1)).toBeTruthy();
expect(dockview.panels.length).toBe(4);
expect(dockview.groups.length).toBe(3);
expect(panel1.api.location.type).toBe('popout');
dockview.fromJSON(dockview.toJSON());
await new Promise((resolve) => setTimeout(resolve, 0)); // popout views are completed as a promise so must complete microtask-queue
expect(dockview.panels.length).toBe(4);
expect(dockview.groups.length).toBe(3);
expect(dockview.groups.every((g) => g.api.isVisible)).toBeTruthy();
});
test('move from fixed to popout group and back', async () => { test('move from fixed to popout group and back', async () => {
const container = document.createElement('div'); const container = document.createElement('div');

View File

@ -1,9 +1,4 @@
import { import { AsapEvent, Emitter, Event, addDisposableListener } from '../events';
AsapEvent,
Emitter,
Event,
addDisposableListener,
} from '../events';
describe('events', () => { describe('events', () => {
describe('emitter', () => { describe('emitter', () => {
@ -67,7 +62,7 @@ describe('events', () => {
expect(value).toBeUndefined(); expect(value).toBeUndefined();
}); });
it('should relay last value in replay mode', () => { it('should replay last value in replay mode', () => {
const emitter = new Emitter<number>({ replay: true }); const emitter = new Emitter<number>({ replay: true });
let value: number | undefined = undefined; let value: number | undefined = undefined;
@ -80,6 +75,20 @@ describe('events', () => {
stream.dispose(); stream.dispose();
}); });
it('should not replay last value in replay mode', () => {
const emitter = new Emitter<number>();
let value: number | undefined = undefined;
emitter.fire(1);
const stream = emitter.event((x) => {
value = x;
});
expect(value).toBeUndefined();
stream.dispose();
});
}); });
describe('asapEvent', () => { describe('asapEvent', () => {

View File

@ -168,10 +168,10 @@ export class Droptarget extends CompositeDisposable {
onDragOver: (e) => { onDragOver: (e) => {
Droptarget.ACTUAL_TARGET = this; Droptarget.ACTUAL_TARGET = this;
const overrideTraget = this.options.getOverrideTarget?.(); const overrideTarget = this.options.getOverrideTarget?.();
if (this._acceptedTargetZonesSet.size === 0) { if (this._acceptedTargetZonesSet.size === 0) {
if (overrideTraget) { if (overrideTarget) {
return; return;
} }
this.removeDropTarget(); this.removeDropTarget();
@ -214,7 +214,7 @@ export class Droptarget extends CompositeDisposable {
} }
if (!this.options.canDisplayOverlay(e, quadrant)) { if (!this.options.canDisplayOverlay(e, quadrant)) {
if (overrideTraget) { if (overrideTarget) {
return; return;
} }
this.removeDropTarget(); this.removeDropTarget();
@ -239,7 +239,7 @@ export class Droptarget extends CompositeDisposable {
this.markAsUsed(e); this.markAsUsed(e);
if (overrideTraget) { if (overrideTarget) {
// //
} else if (!this.targetElement) { } else if (!this.targetElement) {
this.targetElement = document.createElement('div'); this.targetElement = document.createElement('div');

View File

@ -13,7 +13,7 @@ import { DockviewGroupPanelModel } from '../../dockviewGroupPanelModel';
export class VoidContainer extends CompositeDisposable { export class VoidContainer extends CompositeDisposable {
private readonly _element: HTMLElement; private readonly _element: HTMLElement;
private readonly dropTraget: Droptarget; private readonly dropTarget: Droptarget;
private readonly _onDrop = new Emitter<DroptargetEvent>(); private readonly _onDrop = new Emitter<DroptargetEvent>();
readonly onDrop: Event<DroptargetEvent> = this._onDrop.event; readonly onDrop: Event<DroptargetEvent> = this._onDrop.event;
@ -48,7 +48,7 @@ export class VoidContainer extends CompositeDisposable {
const handler = new GroupDragHandler(this._element, accessor, group); const handler = new GroupDragHandler(this._element, accessor, group);
this.dropTraget = new Droptarget(this._element, { this.dropTarget = new Droptarget(this._element, {
acceptedTargetZones: ['center'], acceptedTargetZones: ['center'],
canDisplayOverlay: (event, position) => { canDisplayOverlay: (event, position) => {
const data = getPanelData(); const data = getPanelData();
@ -66,17 +66,17 @@ export class VoidContainer extends CompositeDisposable {
getOverrideTarget: () => group.model.dropTargetContainer?.model, getOverrideTarget: () => group.model.dropTargetContainer?.model,
}); });
this.onWillShowOverlay = this.dropTraget.onWillShowOverlay; this.onWillShowOverlay = this.dropTarget.onWillShowOverlay;
this.addDisposables( this.addDisposables(
handler, handler,
handler.onDragStart((event) => { handler.onDragStart((event) => {
this._onDragStart.fire(event); this._onDragStart.fire(event);
}), }),
this.dropTraget.onDrop((event) => { this.dropTarget.onDrop((event) => {
this._onDrop.fire(event); this._onDrop.fire(event);
}), }),
this.dropTraget this.dropTarget
); );
} }
} }

View File

@ -116,6 +116,7 @@ export interface DockviewPopoutGroupOptions {
* Defaults to `/popout.html` if not provided * Defaults to `/popout.html` if not provided
*/ */
popoutUrl?: string; popoutUrl?: string;
referenceGroup?: DockviewGroupPanel;
onDidOpen?: (event: { id: string; window: Window }) => void; onDidOpen?: (event: { id: string; window: Window }) => void;
onWillClose?: (event: { id: string; window: Window }) => void; onWillClose?: (event: { id: string; window: Window }) => void;
overridePopoutGroup?: DockviewGroupPanel; overridePopoutGroup?: DockviewGroupPanel;
@ -329,7 +330,7 @@ export class DockviewComponent
private readonly _onDidActivePanelChange = new Emitter< private readonly _onDidActivePanelChange = new Emitter<
IDockviewPanel | undefined IDockviewPanel | undefined
>(); >({ replay: true });
readonly onDidActivePanelChange: Event<IDockviewPanel | undefined> = readonly onDidActivePanelChange: Event<IDockviewPanel | undefined> =
this._onDidActivePanelChange.event; this._onDidActivePanelChange.event;
@ -1510,18 +1511,14 @@ export class DockviewComponent
const group = createGroupFromSerializedState(data); const group = createGroupFromSerializedState(data);
this.addPopoutGroup( this.addPopoutGroup(group, {
(gridReferenceGroup position: position ?? undefined,
overridePopoutGroup: gridReferenceGroup ? group : undefined,
referenceGroup: gridReferenceGroup
? this.getPanel(gridReferenceGroup) ? this.getPanel(gridReferenceGroup)
: undefined) ?? group, : undefined,
{ popoutUrl: url,
position: position ?? undefined, });
overridePopoutGroup: gridReferenceGroup
? group
: undefined,
popoutUrl: url,
}
);
} }
for (const floatingGroup of this._floatingGroups) { for (const floatingGroup of this._floatingGroups) {

View File

@ -160,7 +160,9 @@ export class Emitter<T> implements IDisposable {
} }
public fire(e: T): void { public fire(e: T): void {
this._last = e; if(this.options?.replay){
this._last = e;
}
for (const listener of this._listeners) { for (const listener of this._listeners) {
listener.callback(e); listener.callback(e);
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-react", "name": "dockview-react",
"version": "4.2.5", "version": "4.3.1",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews", "description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [ "keywords": [
"splitview", "splitview",
@ -54,6 +54,6 @@
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-react --coverage" "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-react --coverage"
}, },
"dependencies": { "dependencies": {
"dockview": "^4.2.5" "dockview": "^4.3.1"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-vue", "name": "dockview-vue",
"version": "4.2.5", "version": "4.3.1",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews", "description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [ "keywords": [
"splitview", "splitview",
@ -52,7 +52,7 @@
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue --coverage" "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue --coverage"
}, },
"dependencies": { "dependencies": {
"dockview-core": "^4.2.5" "dockview-core": "^4.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.4.0" "vue": "^3.4.0"

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview", "name": "dockview",
"version": "4.2.5", "version": "4.3.1",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews", "description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [ "keywords": [
"splitview", "splitview",
@ -54,7 +54,7 @@
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage" "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
}, },
"dependencies": { "dependencies": {
"dockview-core": "^4.2.5" "dockview-core": "^4.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"

View File

@ -0,0 +1,21 @@
---
slug: dockview-4.3.0-release
title: Dockview 4.3.0
tags: [release]
---
# Release Notes
Please reference docs @ [dockview.dev](https://dockview.dev).
## 🚀 Features
- Hide group private methods from public API [#925](https://github.com/mathuo/dockview/pull/925)
## 🛠 Miscs
- Bug: Fix the restoring of popout groups from layout [#933](https://github.com/mathuo/dockview/pull/933)
- Internals: Variable name typo [#940](https://github.com/mathuo/dockview/pull/940)
## 🔥 Breaking changes

View File

@ -0,0 +1,18 @@
---
slug: dockview-4.3.1-release
title: Dockview 4.3.1
tags: [release]
---
# Release Notes
Please reference docs @ [dockview.dev](https://dockview.dev).
## 🚀 Features
## 🛠 Miscs
- Internal: Improve GC cleanup by only retaining previously emitted event values when event is in replay mode [#947](https://github.com/mathuo/dockview/pull/947)
## 🔥 Breaking changes

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-docs", "name": "dockview-docs",
"version": "4.2.5", "version": "4.3.1",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "npm run build-templates && docusaurus build", "build": "npm run build-templates && docusaurus build",
@ -38,7 +38,7 @@
"ag-grid-react": "^31.0.2", "ag-grid-react": "^31.0.2",
"axios": "^1.6.3", "axios": "^1.6.3",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"dockview": "^4.2.5", "dockview": "^4.3.1",
"prism-react-renderer": "^2.3.1", "prism-react-renderer": "^2.3.1",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",
"react-laag": "^2.0.5", "react-laag": "^2.0.5",

View File

@ -19,7 +19,7 @@ export default function Home(): JSX.Element {
<div className="splashscreen-title"> <div className="splashscreen-title">
<h1>Fully Featured Docking Layout Manager</h1> <h1>Fully Featured Docking Layout Manager</h1>
<h2> <h2>
Zero dependency layout managment and docking Zero dependency layout management and docking
controls controls
</h2> </h2>
</div> </div>