mirror of
https://github.com/mathuo/dockview
synced 2025-03-10 07:52:07 +00:00
Merge branch 'master' of https://github.com/mathuo/dockview into 562-dockview-framework-wrappers-vuejs-angular-javascript-etc-1
This commit is contained in:
commit
56457fe269
@ -2,7 +2,7 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"command": {
|
"command": {
|
||||||
"publish": {
|
"publish": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-angular",
|
"name": "dockview-angular",
|
||||||
"version": "1.13.0",
|
"version": "1.13.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": "^1.13.0"
|
"dockview-core": "^1.13.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-core",
|
"name": "dockview-core",
|
||||||
"version": "1.13.0",
|
"version": "1.13.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",
|
||||||
|
@ -5331,4 +5331,102 @@ describe('dockviewComponent', () => {
|
|||||||
expect(addGroupCount).toBe(2);
|
expect(addGroupCount).toBe(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('that `onDidLayoutChange` only subscribes to events after initial subscription time', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
parentElement: container,
|
||||||
|
createComponent(options) {
|
||||||
|
switch (options.name) {
|
||||||
|
case 'default':
|
||||||
|
return new PanelContentPartTest(
|
||||||
|
options.id,
|
||||||
|
options.name
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new Error(`unsupported`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const api = new DockviewApi(dockview);
|
||||||
|
|
||||||
|
dockview.layout(1000, 1000);
|
||||||
|
|
||||||
|
let a = 0;
|
||||||
|
|
||||||
|
api.onDidLayoutChange((e) => {
|
||||||
|
a++;
|
||||||
|
});
|
||||||
|
|
||||||
|
api.addPanel({
|
||||||
|
id: 'panel_1',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
api.addPanel({
|
||||||
|
id: 'panel_2',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
api.addPanel({
|
||||||
|
id: 'panel_3',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
|
||||||
|
let b = 0;
|
||||||
|
|
||||||
|
api.onDidLayoutChange((e) => {
|
||||||
|
b++;
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.runAllTicks();
|
||||||
|
|
||||||
|
expect(a).toBe(1);
|
||||||
|
expect(b).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('addGroup with absolute position', () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
parentElement: container,
|
||||||
|
createComponent(options) {
|
||||||
|
switch (options.name) {
|
||||||
|
case 'default':
|
||||||
|
return new PanelContentPartTest(
|
||||||
|
options.id,
|
||||||
|
options.name
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new Error(`unsupported`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const api = new DockviewApi(dockview);
|
||||||
|
|
||||||
|
dockview.layout(1000, 1000);
|
||||||
|
|
||||||
|
api.addPanel({
|
||||||
|
id: 'panel_1',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
api.addPanel({
|
||||||
|
id: 'panel_2',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
const panel3 = api.addPanel({
|
||||||
|
id: 'panel_3',
|
||||||
|
component: 'default',
|
||||||
|
position: { direction: 'right' },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(api.panels.length).toBe(3);
|
||||||
|
expect(api.groups.length).toBe(2);
|
||||||
|
|
||||||
|
api.addGroup({ direction: 'left' });
|
||||||
|
|
||||||
|
expect(api.panels.length).toBe(3);
|
||||||
|
expect(api.groups.length).toBe(3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
AsapEvent,
|
||||||
Emitter,
|
Emitter,
|
||||||
Event,
|
Event,
|
||||||
addDisposableListener,
|
addDisposableListener,
|
||||||
@ -82,6 +83,41 @@ describe('events', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('asapEvent', () => {
|
||||||
|
test('that asapEvents fire once per event-loop-cycle', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const event = new AsapEvent();
|
||||||
|
|
||||||
|
let preFireCount = 0;
|
||||||
|
let postFireCount = 0;
|
||||||
|
|
||||||
|
event.onEvent(() => {
|
||||||
|
preFireCount++;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
event.fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check that subscribing after the events have fired but before the event-loop cycle completes
|
||||||
|
* results in no event fires.
|
||||||
|
*/
|
||||||
|
event.onEvent((e) => {
|
||||||
|
postFireCount++;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(preFireCount).toBe(0);
|
||||||
|
expect(postFireCount).toBe(0);
|
||||||
|
|
||||||
|
jest.runAllTimers();
|
||||||
|
|
||||||
|
expect(preFireCount).toBe(1);
|
||||||
|
expect(postFireCount).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should emit a value when any event fires', () => {
|
it('should emit a value when any event fires', () => {
|
||||||
const emitter1 = new Emitter<number>();
|
const emitter1 = new Emitter<number>();
|
||||||
const emitter2 = new Emitter<number>();
|
const emitter2 = new Emitter<number>();
|
||||||
|
@ -1620,8 +1620,6 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
addGroup(options?: AddGroupOptions): DockviewGroupPanel {
|
addGroup(options?: AddGroupOptions): DockviewGroupPanel {
|
||||||
const group = this.createGroup(options);
|
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
let referenceGroup: DockviewGroupPanel | undefined;
|
let referenceGroup: DockviewGroupPanel | undefined;
|
||||||
|
|
||||||
@ -1675,12 +1673,16 @@ export class DockviewComponent
|
|||||||
location,
|
location,
|
||||||
target
|
target
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const group = this.createGroup(options);
|
||||||
this.doAddGroup(group, relativeLocation);
|
this.doAddGroup(group, relativeLocation);
|
||||||
if (!options.skipSetActive) {
|
if (!options.skipSetActive) {
|
||||||
this.doSetGroupAndPanelActive(group);
|
this.doSetGroupAndPanelActive(group);
|
||||||
}
|
}
|
||||||
return group;
|
return group;
|
||||||
} else {
|
} else {
|
||||||
|
const group = this.createGroup(options);
|
||||||
|
|
||||||
this.doAddGroup(group);
|
this.doAddGroup(group);
|
||||||
this.doSetGroupAndPanelActive(group);
|
this.doSetGroupAndPanelActive(group);
|
||||||
return group;
|
return group;
|
||||||
|
@ -203,19 +203,53 @@ export function addDisposableListener<K extends keyof HTMLElementEventMap>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TickDelayedEvent implements IDisposable {
|
/**
|
||||||
private timer: any;
|
*
|
||||||
|
* Event Emitter that fires events from a Microtask callback, only one event will fire per event-loop cycle.
|
||||||
|
*
|
||||||
|
* It's kind of like using an `asapScheduler` in RxJs with additional logic to only fire once per event-loop cycle.
|
||||||
|
* This implementation exists to avoid external dependencies.
|
||||||
|
*
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask
|
||||||
|
* @see https://rxjs.dev/api/index/const/asapScheduler
|
||||||
|
*/
|
||||||
|
export class AsapEvent implements IDisposable {
|
||||||
private readonly _onFired = new Emitter<void>();
|
private readonly _onFired = new Emitter<void>();
|
||||||
readonly onEvent = this._onFired.event;
|
private _currentFireCount = 0;
|
||||||
|
private _queued = false;
|
||||||
|
|
||||||
|
readonly onEvent: Event<void> = (e) => {
|
||||||
|
/**
|
||||||
|
* when the event is first subscribed to take note of the current fire count
|
||||||
|
*/
|
||||||
|
const fireCountAtTimeOfEventSubscription = this._currentFireCount;
|
||||||
|
|
||||||
|
return this._onFired.event(() => {
|
||||||
|
/**
|
||||||
|
* if the current fire count is greater than the fire count at event subscription
|
||||||
|
* then the event has been fired since we subscribed and it's ok to "on_next" the event.
|
||||||
|
*
|
||||||
|
* if the count is not greater then what we are recieving is an event from the microtask
|
||||||
|
* queue that was triggered before we actually subscribed and therfore we should ignore it.
|
||||||
|
*/
|
||||||
|
if (this._currentFireCount > fireCountAtTimeOfEventSubscription) {
|
||||||
|
e();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
fire(): void {
|
fire(): void {
|
||||||
if (this.timer) {
|
this._currentFireCount++;
|
||||||
clearTimeout(this.timer);
|
|
||||||
|
if (this._queued) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.timer = setTimeout(() => {
|
|
||||||
|
this._queued = true;
|
||||||
|
|
||||||
|
queueMicrotask(() => {
|
||||||
|
this._queued = false;
|
||||||
this._onFired.fire();
|
this._onFired.fire();
|
||||||
clearTimeout(this.timer);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Emitter, Event, TickDelayedEvent } from '../events';
|
import { Emitter, Event, AsapEvent } from '../events';
|
||||||
import { getGridLocation, Gridview, IGridView } from './gridview';
|
import { getGridLocation, Gridview, IGridView } from './gridview';
|
||||||
import { Position } from '../dnd/droptarget';
|
import { Position } from '../dnd/droptarget';
|
||||||
import { Disposable, IValueDisposable } from '../lifecycle';
|
import { Disposable, IValueDisposable } from '../lifecycle';
|
||||||
@ -76,11 +76,8 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
private readonly _id = nextLayoutId.next();
|
private readonly _id = nextLayoutId.next();
|
||||||
protected readonly _groups = new Map<string, IValueDisposable<T>>();
|
protected readonly _groups = new Map<string, IValueDisposable<T>>();
|
||||||
protected readonly gridview: Gridview;
|
protected readonly gridview: Gridview;
|
||||||
//
|
|
||||||
protected _activeGroup: T | undefined;
|
|
||||||
|
|
||||||
private _onDidLayoutChange = new Emitter<void>();
|
protected _activeGroup: T | undefined;
|
||||||
readonly onDidLayoutChange = this._onDidLayoutChange.event;
|
|
||||||
|
|
||||||
private readonly _onDidRemove = new Emitter<T>();
|
private readonly _onDidRemove = new Emitter<T>();
|
||||||
readonly onDidRemove: Event<T> = this._onDidRemove.event;
|
readonly onDidRemove: Event<T> = this._onDidRemove.event;
|
||||||
@ -92,7 +89,9 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
readonly onDidActiveChange: Event<T | undefined> =
|
readonly onDidActiveChange: Event<T | undefined> =
|
||||||
this._onDidActiveChange.event;
|
this._onDidActiveChange.event;
|
||||||
|
|
||||||
protected readonly _bufferOnDidLayoutChange = new TickDelayedEvent();
|
protected readonly _bufferOnDidLayoutChange = new AsapEvent();
|
||||||
|
readonly onDidLayoutChange: Event<void> =
|
||||||
|
this._bufferOnDidLayoutChange.onEvent;
|
||||||
|
|
||||||
get id(): string {
|
get id(): string {
|
||||||
return this._id;
|
return this._id;
|
||||||
@ -172,9 +171,6 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
)(() => {
|
)(() => {
|
||||||
this._bufferOnDidLayoutChange.fire();
|
this._bufferOnDidLayoutChange.fire();
|
||||||
}),
|
}),
|
||||||
this._bufferOnDidLayoutChange.onEvent(() => {
|
|
||||||
this._onDidLayoutChange.fire();
|
|
||||||
}),
|
|
||||||
this._bufferOnDidLayoutChange
|
this._bufferOnDidLayoutChange
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -187,7 +183,7 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
|
|
||||||
public setVisible(panel: T, visible: boolean): void {
|
public setVisible(panel: T, visible: boolean): void {
|
||||||
this.gridview.setViewVisible(getGridLocation(panel.element), visible);
|
this.gridview.setViewVisible(getGridLocation(panel.element), visible);
|
||||||
this._onDidLayoutChange.fire();
|
this._bufferOnDidLayoutChange.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
public isVisible(panel: T): boolean {
|
public isVisible(panel: T): boolean {
|
||||||
@ -330,7 +326,6 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
this._onDidActiveChange.dispose();
|
this._onDidActiveChange.dispose();
|
||||||
this._onDidAdd.dispose();
|
this._onDidAdd.dispose();
|
||||||
this._onDidRemove.dispose();
|
this._onDidRemove.dispose();
|
||||||
this._onDidLayoutChange.dispose();
|
|
||||||
|
|
||||||
for (const group of this.groups) {
|
for (const group of this.groups) {
|
||||||
group.dispose();
|
group.dispose();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-react",
|
"name": "dockview-react",
|
||||||
"version": "1.13.0",
|
"version": "1.13.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": "^1.13.0"
|
"dockview": "^1.13.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-vue",
|
"name": "dockview-vue",
|
||||||
"version": "1.13.0",
|
"version": "1.13.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",
|
||||||
@ -56,6 +56,6 @@
|
|||||||
"build:types": "vue-tsc --project tsconfig.build-types.json --declaration --emitDeclarationOnly --outDir dist/types "
|
"build:types": "vue-tsc --project tsconfig.build-types.json --declaration --emitDeclarationOnly --outDir dist/types "
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dockview-core": "^1.13.0"
|
"dockview-core": "^1.13.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview",
|
"name": "dockview",
|
||||||
"version": "1.13.0",
|
"version": "1.13.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": "^1.13.0"
|
"dockview-core": "^1.13.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
packages/docs/blog/2024-05-05-dockview-1.13.1.md
Normal file
16
packages/docs/blog/2024-05-05-dockview-1.13.1.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
slug: dockview-1.13.1-release
|
||||||
|
title: Dockview 1.13.1
|
||||||
|
tags: [release]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Release Notes
|
||||||
|
|
||||||
|
Please reference docs @ [dockview.dev](https://dockview.dev).
|
||||||
|
|
||||||
|
## 🛠 Miscs
|
||||||
|
|
||||||
|
- Bug: fix duplicate group added when adding group with absolute position [#596](https://github.com/mathuo/dockview/issues/596)
|
||||||
|
|
||||||
|
- Bug: Adjust onDidLayoutChange behaviour [#597](https://github.com/mathuo/dockview/issues/597)
|
||||||
|
- `onDidLayoutChange` is an aggregation of events that constitute a layout change. Previously these events were aggregated and the events were then fired once through a `setTimeout(..., 0)` approach. This has been altered to fire on a `queueMicrotask` event and will only subscribe to events that happen after the event is subscribed to, previously you may have recieved events yet to fire on the `setTimeout` function but within the same event-loop cycle which was a bug.
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-docs",
|
"name": "dockview-docs",
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run build-templates && docusaurus build",
|
"build": "npm run build-templates && docusaurus build",
|
||||||
@ -37,7 +37,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": "^1.13.0",
|
"dockview": "^1.13.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",
|
||||||
|
Loading…
Reference in New Issue
Block a user