diff --git a/README.md b/README.md index 980350c04..a0a3a2b1f 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ --- -[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview) -[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview) +[![npm version](https://badge.fury.io/js/dockview-core.svg)](https://www.npmjs.com/package/dockview-core) +[![npm](https://img.shields.io/npm/dm/dockview-core)](https://www.npmjs.com/package/dockview-core) [![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview) -[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview) +[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview-core)](https://bundlephobia.com/result?p=dockview-core) ## diff --git a/lerna.json b/lerna.json index 8e89ed7f6..ea2983497 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "3.0.0", + "version": "3.0.2", "npmClient": "yarn", "command": { "publish": { diff --git a/packages/dockview-angular/package.json b/packages/dockview-angular/package.json index 410f007d1..90dec64e4 100644 --- a/packages/dockview-angular/package.json +++ b/packages/dockview-angular/package.json @@ -1,6 +1,6 @@ { "name": "dockview-angular", - "version": "3.0.0", + "version": "3.0.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", @@ -54,6 +54,6 @@ "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage" }, "dependencies": { - "dockview-core": "^3.0.0" + "dockview-core": "^3.0.2" } } diff --git a/packages/dockview-core/package.json b/packages/dockview-core/package.json index ac9d66d86..46d930d42 100644 --- a/packages/dockview-core/package.json +++ b/packages/dockview-core/package.json @@ -1,6 +1,6 @@ { "name": "dockview-core", - "version": "3.0.0", + "version": "3.0.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index 0be413221..0d00d1a31 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -5021,6 +5021,78 @@ describe('dockviewComponent', () => { expect(panel3.api.location.type).toBe('grid'); }); + test('grid -> floating -> popout -> floating', 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', + position: { direction: 'right' }, + }); + + expect(panel1.api.location.type).toBe('grid'); + expect(panel2.api.location.type).toBe('grid'); + expect(panel3.api.location.type).toBe('grid'); + + dockview.addFloatingGroup(panel2.group); + + expect(panel1.api.location.type).toBe('floating'); + expect(panel2.api.location.type).toBe('floating'); + expect(panel3.api.location.type).toBe('grid'); + + await dockview.addPopoutGroup(panel2.group); + + expect(panel1.api.location.type).toBe('popout'); + expect(panel2.api.location.type).toBe('popout'); + expect(panel3.api.location.type).toBe('grid'); + + dockview.addFloatingGroup(panel2.group); + + expect(panel1.api.location.type).toBe('floating'); + expect(panel2.api.location.type).toBe('floating'); + expect(panel3.api.location.type).toBe('grid'); + + await dockview.addPopoutGroup(panel2.group); + + expect(panel1.api.location.type).toBe('popout'); + expect(panel2.api.location.type).toBe('popout'); + expect(panel3.api.location.type).toBe('grid'); + + panel2.group.api.moveTo({ group: panel3.group }); + + expect(panel1.api.location.type).toBe('grid'); + expect(panel2.api.location.type).toBe('grid'); + expect(panel3.api.location.type).toBe('grid'); + }); + test('that panel is rendered when moving from popout to new group', async () => { const container = document.createElement('div'); diff --git a/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts b/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts index d8ed45209..3ab49faa7 100644 --- a/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts +++ b/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts @@ -105,6 +105,21 @@ class ClassUnderTest extends BaseGrid { } describe('baseComponentGridview', () => { + test('that the container is not removed when grid is disposed', () => { + const root = document.createElement('div'); + const container = document.createElement('div'); + root.appendChild(container); + + const cut = new ClassUnderTest(container, { + orientation: Orientation.HORIZONTAL, + proportionalLayout: true, + }); + + cut.dispose(); + + expect(container.parentElement).toBe(root); + }); + test('that .layout(...) force flag works', () => { const cut = new ClassUnderTest(document.createElement('div'), { orientation: Orientation.HORIZONTAL, diff --git a/packages/dockview-core/src/__tests__/paneview/paneviewComponent.spec.ts b/packages/dockview-core/src/__tests__/paneview/paneviewComponent.spec.ts index 77a58712b..8cfc7fc2e 100644 --- a/packages/dockview-core/src/__tests__/paneview/paneviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/paneview/paneviewComponent.spec.ts @@ -67,6 +67,27 @@ describe('componentPaneview', () => { container.className = 'container'; }); + test('that the container is not removed when grid is disposed', () => { + const root = document.createElement('div'); + const container = document.createElement('div'); + root.appendChild(container); + + const paneview = new PaneviewComponent(container, { + createComponent: (options) => { + switch (options.name) { + case 'default': + return new TestPanel(options.id, options.name); + default: + throw new Error('unsupported'); + } + }, + }); + + paneview.dispose(); + + expect(container.parentElement).toBe(root); + }); + test('vertical panels', () => { const disposables = new CompositeDisposable(); @@ -293,40 +314,6 @@ describe('componentPaneview', () => { disposable.dispose(); }); - test('dispose of paneviewComponent', () => { - expect(container.childNodes.length).toBe(0); - - const paneview = new PaneviewComponent(container, { - createComponent: (options) => { - switch (options.name) { - case 'default': - return new TestPanel(options.id, options.name); - default: - throw new Error('unsupported'); - } - }, - }); - - paneview.layout(1000, 1000); - - paneview.addPanel({ - id: 'panel1', - component: 'default', - title: 'Panel 1', - }); - paneview.addPanel({ - id: 'panel2', - component: 'default', - title: 'Panel 2', - }); - - expect(container.childNodes.length).toBeGreaterThan(0); - - paneview.dispose(); - - expect(container.childNodes.length).toBe(0); - }); - test('panel is disposed of when component is disposed', () => { const paneview = new PaneviewComponent(container, { createComponent: (options) => { @@ -606,10 +593,10 @@ describe('componentPaneview', () => { className: 'test-a test-b', }); - expect(paneview.element.className).toBe('container test-a test-b'); + expect(paneview.element.className).toBe('test-a test-b'); paneview.updateOptions({ className: 'test-b test-c' }); - expect(paneview.element.className).toBe('container test-b test-c'); + expect(paneview.element.className).toBe('test-b test-c'); }); }); diff --git a/packages/dockview-core/src/__tests__/splitview/splitviewComponent.spec.ts b/packages/dockview-core/src/__tests__/splitview/splitviewComponent.spec.ts index 6ab1415b2..90d0b3986 100644 --- a/packages/dockview-core/src/__tests__/splitview/splitviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/splitview/splitviewComponent.spec.ts @@ -26,6 +26,28 @@ describe('componentSplitview', () => { container.className = 'container'; }); + test('that the container is not removed when grid is disposed', () => { + const root = document.createElement('div'); + const container = document.createElement('div'); + root.appendChild(container); + + const splitview = new SplitviewComponent(container, { + orientation: Orientation.VERTICAL, + createComponent: (options) => { + switch (options.name) { + case 'default': + return new TestPanel(options.id, options.name); + default: + throw new Error('unsupported'); + } + }, + }); + + splitview.dispose(); + + expect(container.parentElement).toBe(root); + }); + test('event leakage', () => { Emitter.setLeakageMonitorEnabled(true); @@ -451,39 +473,6 @@ describe('componentSplitview', () => { disposable.dispose(); }); - test('dispose of splitviewComponent', () => { - expect(container.childNodes.length).toBe(0); - - const splitview = new SplitviewComponent(container, { - orientation: Orientation.HORIZONTAL, - createComponent: (options) => { - switch (options.name) { - case 'default': - return new TestPanel(options.id, options.name); - default: - throw new Error('unsupported'); - } - }, - }); - - splitview.layout(1000, 1000); - - splitview.addPanel({ - id: 'panel1', - component: 'default', - }); - splitview.addPanel({ - id: 'panel2', - component: 'default', - }); - - expect(container.childNodes.length).toBeGreaterThan(0); - - splitview.dispose(); - - expect(container.childNodes.length).toBe(0); - }); - test('panel is disposed of when component is disposed', () => { const splitview = new SplitviewComponent(container, { orientation: Orientation.HORIZONTAL, @@ -736,10 +725,10 @@ describe('componentSplitview', () => { className: 'test-a test-b', }); - expect(splitview.element.className).toBe('container test-a test-b'); + expect(splitview.element.className).toBe('test-a test-b'); splitview.updateOptions({ className: 'test-b test-c' }); - expect(splitview.element.className).toBe('container test-b test-c'); + expect(splitview.element.className).toBe('test-b test-c'); }); }); diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 58618a025..2aebef45d 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -370,8 +370,8 @@ export class DockviewComponent return this._floatingGroups; } - constructor(parentElement: HTMLElement, options: DockviewComponentOptions) { - super(parentElement, { + constructor(container: HTMLElement, options: DockviewComponentOptions) { + super(container, { proportionalLayout: true, orientation: Orientation.HORIZONTAL, styles: options.hideBorders @@ -850,6 +850,20 @@ export class DockviewComponent this.overlayRenderContainer; returnedGroup = group; + const alreadyRemoved = !this._popoutGroups.find( + (p) => p.popoutGroup === group + ); + + if (alreadyRemoved) { + /** + * If this popout group was explicitly removed then we shouldn't run the additional + * steps. To tell if the running of this disposable is the result of this popout group + * being explicitly removed we can check if this popout group is still referenced in + * the `this._popoutGroups` list. + */ + return; + } + if (floatingBox) { this.addFloatingGroup(group, { height: floatingBox.height, diff --git a/packages/dockview-core/src/gridview/baseComponentGridview.ts b/packages/dockview-core/src/gridview/baseComponentGridview.ts index 9d02993f3..93779f5a0 100644 --- a/packages/dockview-core/src/gridview/baseComponentGridview.ts +++ b/packages/dockview-core/src/gridview/baseComponentGridview.ts @@ -155,7 +155,7 @@ export abstract class BaseGrid this.gridview.locked = value; } - constructor(parentElement: HTMLElement, options: BaseGridOptions) { + constructor(container: HTMLElement, options: BaseGridOptions) { super(document.createElement('div'), options.disableAutoResizing); this.element.style.height = '100%'; this.element.style.width = '100%'; @@ -163,7 +163,8 @@ export abstract class BaseGrid this._classNames = new Classnames(this.element); this._classNames.setClassNames(options.className ?? ''); - parentElement.appendChild(this.element); + // the container is owned by the third-party, do not modify/delete it + container.appendChild(this.element); this.gridview = new Gridview( !!options.proportionalLayout, diff --git a/packages/dockview-core/src/gridview/gridviewComponent.ts b/packages/dockview-core/src/gridview/gridviewComponent.ts index 00084ce44..80df754bd 100644 --- a/packages/dockview-core/src/gridview/gridviewComponent.ts +++ b/packages/dockview-core/src/gridview/gridviewComponent.ts @@ -113,8 +113,8 @@ export class GridviewComponent this._deserializer = value; } - constructor(parentElement: HTMLElement, options: GridviewComponentOptions) { - super(parentElement, { + constructor(container: HTMLElement, options: GridviewComponentOptions) { + super(container, { proportionalLayout: options.proportionalLayout ?? true, orientation: options.orientation, styles: options.hideBorders diff --git a/packages/dockview-core/src/paneview/paneviewComponent.ts b/packages/dockview-core/src/paneview/paneviewComponent.ts index 86c87a690..b47ca0181 100644 --- a/packages/dockview-core/src/paneview/paneviewComponent.ts +++ b/packages/dockview-core/src/paneview/paneviewComponent.ts @@ -195,8 +195,10 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent { return this._options; } - constructor(parentElement: HTMLElement, options: PaneviewComponentOptions) { - super(parentElement, options.disableAutoResizing); + constructor(container: HTMLElement, options: PaneviewComponentOptions) { + super(document.createElement('div'), options.disableAutoResizing); + this.element.style.height = '100%'; + this.element.style.width = '100%'; this.addDisposables( this._onDidLayoutChange, @@ -210,6 +212,9 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent { this._classNames = new Classnames(this.element); this._classNames.setClassNames(options.className ?? ''); + // the container is owned by the third-party, do not modify/delete it + container.appendChild(this.element); + this._options = options; this.paneview = new Paneview(this.element, { diff --git a/packages/dockview-core/src/splitview/splitview.ts b/packages/dockview-core/src/splitview/splitview.ts index fc5857d08..77fbb9cf5 100644 --- a/packages/dockview-core/src/splitview/splitview.ts +++ b/packages/dockview-core/src/splitview/splitview.ts @@ -32,7 +32,7 @@ export interface ISplitviewStyles { } export interface SplitViewOptions { - orientation: Orientation; + orientation?: Orientation; descriptor?: ISplitViewDescriptor; proportionalLayout?: boolean; styles?: ISplitviewStyles; @@ -225,7 +225,7 @@ export class Splitview { private readonly container: HTMLElement, options: SplitViewOptions ) { - this._orientation = options.orientation; + this._orientation = options.orientation ?? Orientation.VERTICAL; this.element = this.createContainer(); this.margin = options.margin ?? 0; diff --git a/packages/dockview-core/src/splitview/splitviewComponent.ts b/packages/dockview-core/src/splitview/splitviewComponent.ts index 5e988c422..a165ba4b3 100644 --- a/packages/dockview-core/src/splitview/splitviewComponent.ts +++ b/packages/dockview-core/src/splitview/splitviewComponent.ts @@ -155,15 +155,17 @@ export class SplitviewComponent : this.splitview.orthogonalSize; } - constructor( - parentElement: HTMLElement, - options: SplitviewComponentOptions - ) { - super(parentElement, options.disableAutoResizing); + constructor(container: HTMLElement, options: SplitviewComponentOptions) { + super(document.createElement('div'), options.disableAutoResizing); + this.element.style.height = '100%'; + this.element.style.width = '100%'; this._classNames = new Classnames(this.element); this._classNames.setClassNames(options.className ?? ''); + // the container is owned by the third-party, do not modify/delete it + container.appendChild(this.element); + this._options = options; this.splitview = new Splitview(this.element, options); diff --git a/packages/dockview-react/package.json b/packages/dockview-react/package.json index 34ef63def..172398f3b 100644 --- a/packages/dockview-react/package.json +++ b/packages/dockview-react/package.json @@ -1,6 +1,6 @@ { "name": "dockview-react", - "version": "3.0.0", + "version": "3.0.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", @@ -54,6 +54,6 @@ "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-react --coverage" }, "dependencies": { - "dockview": "^3.0.0" + "dockview": "^3.0.2" } } diff --git a/packages/dockview-vue/package.json b/packages/dockview-vue/package.json index 97697e7b9..694edfad0 100644 --- a/packages/dockview-vue/package.json +++ b/packages/dockview-vue/package.json @@ -1,6 +1,6 @@ { "name": "dockview-vue", - "version": "3.0.0", + "version": "3.0.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", @@ -52,7 +52,7 @@ "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue --coverage" }, "dependencies": { - "dockview-core": "^3.0.0" + "dockview-core": "^3.0.2" }, "peerDependencies": { "vue": "^3.4.0" diff --git a/packages/dockview/package.json b/packages/dockview/package.json index aa5fb113b..e95bbedcf 100644 --- a/packages/dockview/package.json +++ b/packages/dockview/package.json @@ -1,6 +1,6 @@ { "name": "dockview", - "version": "3.0.0", + "version": "3.0.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", @@ -54,7 +54,7 @@ "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage" }, "dependencies": { - "dockview-core": "^3.0.0" + "dockview-core": "^3.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" diff --git a/packages/dockview/src/dockview/dockview.tsx b/packages/dockview/src/dockview/dockview.tsx index fefc605f1..2e4e2fc57 100644 --- a/packages/dockview/src/dockview/dockview.tsx +++ b/packages/dockview/src/dockview/dockview.tsx @@ -318,11 +318,7 @@ export const DockviewReact = React.forwardRef( }, [props.prefixHeaderActionsComponent]); return ( -
+
{portals}
); diff --git a/packages/dockview/src/gridview/gridview.tsx b/packages/dockview/src/gridview/gridview.tsx index 60b172651..9bc9dd60b 100644 --- a/packages/dockview/src/gridview/gridview.tsx +++ b/packages/dockview/src/gridview/gridview.tsx @@ -126,11 +126,7 @@ export const GridviewReact = React.forwardRef( }, [props.components]); return ( -
+
{portals}
); diff --git a/packages/dockview/src/paneview/paneview.tsx b/packages/dockview/src/paneview/paneview.tsx index 34ab300b9..e0d49d98d 100644 --- a/packages/dockview/src/paneview/paneview.tsx +++ b/packages/dockview/src/paneview/paneview.tsx @@ -176,11 +176,7 @@ export const PaneviewReact = React.forwardRef( }, [props.onDidDrop]); return ( -
+
{portals}
); diff --git a/packages/dockview/src/splitview/splitview.tsx b/packages/dockview/src/splitview/splitview.tsx index 63d2cf5d9..bb8593381 100644 --- a/packages/dockview/src/splitview/splitview.tsx +++ b/packages/dockview/src/splitview/splitview.tsx @@ -126,11 +126,7 @@ export const SplitviewReact = React.forwardRef( }, [props.components]); return ( -
+
{portals}
); diff --git a/packages/docs/blog/2025-01-09-dockview-3.0.1.md b/packages/docs/blog/2025-01-09-dockview-3.0.1.md new file mode 100644 index 000000000..cef014f95 --- /dev/null +++ b/packages/docs/blog/2025-01-09-dockview-3.0.1.md @@ -0,0 +1,17 @@ +--- +slug: dockview-3.0.1-release +title: Dockview 3.0.1 +tags: [release] +--- + +# Release Notes + +Please reference docs @ [dockview.dev](https://dockview.dev). + +## 🚀 Features + +## 🛠 Miscs + +## 🔥 Breaking changes + +- Fix duplicate HTML element [#810](https://github.com/mathuo/dockview/issues/818) diff --git a/packages/docs/blog/2025-01-11-dockview-3.0.2.md b/packages/docs/blog/2025-01-11-dockview-3.0.2.md new file mode 100644 index 000000000..f223b81bd --- /dev/null +++ b/packages/docs/blog/2025-01-11-dockview-3.0.2.md @@ -0,0 +1,18 @@ +--- +slug: dockview-3.0.2-release +title: Dockview 3.0.2 +tags: [release] +--- + +# Release Notes + +Please reference docs @ [dockview.dev](https://dockview.dev). + +## 🚀 Features + +## 🛠 Miscs + +## 🔥 Breaking changes + +- Fix issue when transitioning panel from floating to popout to floating [#810](https://github.com/mathuo/dockview/issues/824) +- Fix duplicate HTML containers [#825](https://github.com/mathuo/dockview/pull/825) diff --git a/packages/docs/package.json b/packages/docs/package.json index 700febd27..563eaddac 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "dockview-docs", - "version": "3.0.0", + "version": "3.0.2", "private": true, "scripts": { "build": "npm run build-templates && docusaurus build", @@ -38,7 +38,7 @@ "ag-grid-react": "^31.0.2", "axios": "^1.6.3", "clsx": "^2.1.0", - "dockview": "^3.0.0", + "dockview": "^3.0.2", "prism-react-renderer": "^2.3.1", "react-dnd": "^16.0.1", "react-laag": "^2.0.5", diff --git a/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx b/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx index a9f4ea97c..e1ccaef0f 100644 --- a/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx +++ b/packages/docs/sandboxes/react/dockview/demo-dockview/src/app.tsx @@ -176,75 +176,92 @@ const DockviewDemo = (props: { theme?: string }) => { setPending([]); }, [pending]); - const onReady = (event: DockviewReadyEvent) => { - setApi(event.api); - - event.api.onDidAddPanel((event) => { - setPanels((_) => [..._, event.id]); - addLogLine(`Panel Added ${event.id}`); - }); - event.api.onDidActivePanelChange((event) => { - setActivePanel(event?.id); - addLogLine(`Panel Activated ${event?.id}`); - }); - event.api.onDidRemovePanel((event) => { - setPanels((_) => { - const next = [..._]; - next.splice( - next.findIndex((x) => x === event.id), - 1 - ); - - return next; - }); - addLogLine(`Panel Removed ${event.id}`); - }); - - event.api.onDidAddGroup((event) => { - setGroups((_) => [..._, event.id]); - addLogLine(`Group Added ${event.id}`); - }); - - event.api.onDidMovePanel((event) => { - addLogLine(`Panel Moved ${event.panel.id}`); - }); - - event.api.onDidMaximizedGroupChange((event) => { - addLogLine( - `Group Maximized Changed ${event.group.api.id} [${event.isMaximized}]` - ); - }); - - event.api.onDidRemoveGroup((event) => { - setGroups((_) => { - const next = [..._]; - next.splice( - next.findIndex((x) => x === event.id), - 1 - ); - - return next; - }); - addLogLine(`Group Removed ${event.id}`); - }); - - event.api.onDidActiveGroupChange((event) => { - setActiveGroup(event?.id); - addLogLine(`Group Activated ${event?.id}`); - }); - - const state = localStorage.getItem('dv-demo-state'); - if (state) { - try { - event.api.fromJSON(JSON.parse(state)); - return; - } catch { - localStorage.removeItem('dv-demo-state'); - } + React.useEffect(() => { + if (!api) { return; } - defaultConfig(event.api); + const disposables = [ + api.onDidAddPanel((event) => { + setPanels((_) => [..._, event.id]); + addLogLine(`Panel Added ${event.id}`); + }), + api.onDidActivePanelChange((event) => { + setActivePanel(event?.id); + addLogLine(`Panel Activated ${event?.id}`); + }), + api.onDidRemovePanel((event) => { + setPanels((_) => { + const next = [..._]; + next.splice( + next.findIndex((x) => x === event.id), + 1 + ); + + return next; + }); + addLogLine(`Panel Removed ${event.id}`); + }), + + api.onDidAddGroup((event) => { + setGroups((_) => [..._, event.id]); + addLogLine(`Group Added ${event.id}`); + }), + + api.onDidMovePanel((event) => { + addLogLine(`Panel Moved ${event.panel.id}`); + }), + + api.onDidMaximizedGroupChange((event) => { + addLogLine( + `Group Maximized Changed ${event.group.api.id} [${event.isMaximized}]` + ); + }), + + api.onDidRemoveGroup((event) => { + setGroups((_) => { + const next = [..._]; + next.splice( + next.findIndex((x) => x === event.id), + 1 + ); + + return next; + }); + addLogLine(`Group Removed ${event.id}`); + }), + + api.onDidActiveGroupChange((event) => { + setActiveGroup(event?.id); + addLogLine(`Group Activated ${event?.id}`); + }), + ]; + + const loadLayout = () => { + const state = localStorage.getItem('dv-demo-state'); + + if (state) { + try { + api.fromJSON(JSON.parse(state)); + return; + } catch { + localStorage.removeItem('dv-demo-state'); + } + return; + } + + defaultConfig(api); + }; + + loadLayout(); + + return () => { + disposables.forEach((disposable) => disposable.dispose()); + }; + }, [api]); + + const onReady = (event: DockviewReadyEvent) => { + setApi(event.api); }; const [watermark, setWatermark] = React.useState(false); @@ -359,7 +376,6 @@ const DockviewDemo = (props: { theme?: string }) => { style={{ flexGrow: 1, overflow: 'hidden', - height: '100%', display: 'flex', }} > diff --git a/packages/docs/sandboxes/react/dockview/demo-dockview/src/groupActions.tsx b/packages/docs/sandboxes/react/dockview/demo-dockview/src/groupActions.tsx index 815621b72..0af2a66cc 100644 --- a/packages/docs/sandboxes/react/dockview/demo-dockview/src/groupActions.tsx +++ b/packages/docs/sandboxes/react/dockview/demo-dockview/src/groupActions.tsx @@ -88,7 +88,6 @@ const GroupAction = (props: { } onClick={() => { if (group) { - props.api.addFloatingGroup(group, { width: 400, height: 300, @@ -99,7 +98,6 @@ const GroupAction = (props: { right: 50, }, }); - } }} > diff --git a/packages/docs/src/pages/demo.tsx b/packages/docs/src/pages/demo.tsx index ad48bf86c..cab33d7ef 100644 --- a/packages/docs/src/pages/demo.tsx +++ b/packages/docs/src/pages/demo.tsx @@ -27,7 +27,7 @@ const ThemeToggle: React.FC = () => { value={theme} > {themeConfig.map((theme) => { - return ; + return ; })}
diff --git a/packages/docs/src/theme/Root.tsx b/packages/docs/src/theme/Root.tsx index 516775b04..eb8c4705e 100644 --- a/packages/docs/src/theme/Root.tsx +++ b/packages/docs/src/theme/Root.tsx @@ -3,5 +3,9 @@ import { RecoilRoot } from 'recoil'; // Default implementation, that you can customize export default function Root({ children }) { - return {children}; + return ( + + {children} + + ); } diff --git a/packages/docs/templates/dockview/demo-dockview/react/src/app.tsx b/packages/docs/templates/dockview/demo-dockview/react/src/app.tsx index 3ab3066da..befc23f44 100644 --- a/packages/docs/templates/dockview/demo-dockview/react/src/app.tsx +++ b/packages/docs/templates/dockview/demo-dockview/react/src/app.tsx @@ -124,6 +124,11 @@ const DockviewDemo = (props: { theme?: string }) => { const onReady = (event: DockviewReadyEvent) => { setApi(event.api); + setPanels([]); + setGroups([]); + setActivePanel(undefined); + setActiveGroup(undefined); + addLogLine(`Dockview Is Ready`); }; React.useEffect(() => {