diff --git a/lerna.json b/lerna.json index ad9caf389..0db0b74b9 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "1.16.1", + "version": "1.17.2", "npmClient": "yarn", "command": { "publish": { diff --git a/packages/dockview-angular/package.json b/packages/dockview-angular/package.json index 87c50287f..71411409b 100644 --- a/packages/dockview-angular/package.json +++ b/packages/dockview-angular/package.json @@ -1,6 +1,6 @@ { "name": "dockview-angular", - "version": "1.16.1", + "version": "1.17.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": "^1.16.1" + "dockview-core": "^1.17.2" } } diff --git a/packages/dockview-core/package.json b/packages/dockview-core/package.json index 4c32611b7..b63be23e7 100644 --- a/packages/dockview-core/package.json +++ b/packages/dockview-core/package.json @@ -1,6 +1,6 @@ { "name": "dockview-core", - "version": "1.16.1", + "version": "1.17.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", diff --git a/packages/dockview-core/src/__tests__/dockview/components/tab/defaultTab.spec.ts b/packages/dockview-core/src/__tests__/dockview/components/tab/defaultTab.spec.ts index 291cf4712..2189282dd 100644 --- a/packages/dockview-core/src/__tests__/dockview/components/tab/defaultTab.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/components/tab/defaultTab.spec.ts @@ -54,7 +54,7 @@ describe('defaultTab', () => { let el = cut.element.querySelector('.dv-default-tab-action'); - fireEvent.mouseDown(el!); + fireEvent.pointerDown(el!); expect(api.close).toHaveBeenCalledTimes(0); fireEvent.click(el!); diff --git a/packages/dockview-core/src/__tests__/dockview/components/titlebar/tabsContainer.spec.ts b/packages/dockview-core/src/__tests__/dockview/components/titlebar/tabsContainer.spec.ts index b96b8f95f..b6e4fa861 100644 --- a/packages/dockview-core/src/__tests__/dockview/components/titlebar/tabsContainer.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/components/titlebar/tabsContainer.spec.ts @@ -459,6 +459,7 @@ describe('tabsContainer', () => { onDidRemovePanel: jest.fn(), element: document.createElement('div'), addFloatingGroup: jest.fn(), + doSetGroupActive: jest.fn(), }); const groupPanelMock = jest.fn(() => { @@ -486,10 +487,11 @@ describe('tabsContainer', () => { return { top: 10, left: 20, width: 0, height: 0 } as any; }); - const event = new KeyboardEvent('mousedown', { shiftKey: true }); + const event = new KeyboardEvent('pointerdown', { shiftKey: true }); const eventPreventDefaultSpy = jest.spyOn(event, 'preventDefault'); fireEvent(container, event); + expect(accessor.doSetGroupActive).toHaveBeenCalledWith(groupPanel); expect(accessor.addFloatingGroup).toHaveBeenCalledWith(groupPanel, { x: 100, y: 60, @@ -498,7 +500,7 @@ describe('tabsContainer', () => { expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1); expect(eventPreventDefaultSpy).toHaveBeenCalledTimes(1); - const event2 = new KeyboardEvent('mousedown', { shiftKey: false }); + const event2 = new KeyboardEvent('pointerdown', { shiftKey: false }); const eventPreventDefaultSpy2 = jest.spyOn(event2, 'preventDefault'); fireEvent(container, event2); @@ -513,6 +515,7 @@ describe('tabsContainer', () => { onDidRemovePanel: jest.fn(), element: document.createElement('div'), addFloatingGroup: jest.fn(), + doSetGroupActive: jest.fn(), }); const groupPanelMock = jest.fn(() => { @@ -540,14 +543,15 @@ describe('tabsContainer', () => { return { top: 10, left: 20, width: 0, height: 0 } as any; }); - const event = new KeyboardEvent('mousedown', { shiftKey: true }); + const event = new KeyboardEvent('pointerdown', { shiftKey: true }); const eventPreventDefaultSpy = jest.spyOn(event, 'preventDefault'); fireEvent(container, event); + expect(accessor.doSetGroupActive).toHaveBeenCalledWith(groupPanel); expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(0); expect(eventPreventDefaultSpy).toHaveBeenCalledTimes(0); - const event2 = new KeyboardEvent('mousedown', { shiftKey: false }); + const event2 = new KeyboardEvent('pointerdown', { shiftKey: false }); const eventPreventDefaultSpy2 = jest.spyOn(event2, 'preventDefault'); fireEvent(container, event2); @@ -595,7 +599,7 @@ describe('tabsContainer', () => { const el = cut.element.querySelector('.dv-tab')!; expect(el).toBeTruthy(); - const event = new KeyboardEvent('mousedown', { shiftKey: true }); + const event = new KeyboardEvent('pointerdown', { shiftKey: true }); const preventDefaultSpy = jest.spyOn(event, 'preventDefault'); fireEvent(el, event); diff --git a/packages/dockview-core/src/__tests__/dockview/components/watermark/watermark.spec.ts b/packages/dockview-core/src/__tests__/dockview/components/watermark/watermark.spec.ts index 2817bca57..92797f0e9 100644 --- a/packages/dockview-core/src/__tests__/dockview/components/watermark/watermark.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/components/watermark/watermark.spec.ts @@ -1,20 +1,16 @@ import { DockviewApi } from '../../../../api/component.api'; import { Watermark } from '../../../../dockview/components/watermark/watermark'; +import { fromPartial } from '@total-typescript/shoehorn'; describe('watermark', () => { test('that the group is closed when the close button is clicked', () => { const cut = new Watermark(); - - const mockApi = jest.fn, any[]>(() => { - return { - removeGroup: jest.fn(), - }; + const api = fromPartial({ + removeGroup: jest.fn(), }); - const api = new mockApi(); const group = jest.fn() as any; - cut.init({ containerApi: api }); - cut.updateParentGroup(group, true); + cut.init({ containerApi: api, group }); const closeEl = cut.element.querySelector('.dv-close-action')!; diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index b62cbd602..f6511e5d6 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -8,9 +8,9 @@ import { PanelUpdateEvent } from '../../panel/types'; import { Orientation } from '../../splitview/splitview'; import { CompositeDisposable } from '../../lifecycle'; import { Emitter } from '../../events'; -import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel'; +import { IDockviewPanel } from '../../dockview/dockviewPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; -import { fireEvent, getByTestId, queryByTestId } from '@testing-library/dom'; +import { fireEvent, queryByTestId } from '@testing-library/dom'; import { getPanelData } from '../../dnd/dataTransfer'; import { GroupDragEvent, @@ -262,6 +262,112 @@ describe('dockviewComponent', () => { dockview.dispose(); }); + describe('move group', () => { + test('horizontal', () => { + 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(600, 1000); + + const panel1 = dockview.addPanel({ + id: 'panel1', + component: 'default', + }); + const panel2 = dockview.addPanel({ + id: 'panel2', + component: 'default', + position: { direction: 'right' }, + }); + const panel3 = dockview.addPanel({ + id: 'panel3', + component: 'default', + position: { direction: 'right' }, + }); + + expect(panel1.api.width).toBe(200); + expect(panel2.api.width).toBe(200); + expect(panel3.api.width).toBe(200); + + panel3.api.setSize({ width: 300 }); + + expect(panel1.api.width).toBe(200); + expect(panel2.api.width).toBe(100); + expect(panel3.api.width).toBe(300); + + dockview.moveGroup({ + from: { group: panel3.api.group }, + to: { group: panel1.api.group, position: 'right' }, + }); + + expect(panel1.api.width).toBe(200); + expect(panel2.api.width).toBe(100); + expect(panel3.api.width).toBe(300); + }); + + test('vertical', () => { + 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, 600); + + const panel1 = dockview.addPanel({ + id: 'panel1', + component: 'default', + }); + const panel2 = dockview.addPanel({ + id: 'panel2', + component: 'default', + position: { direction: 'below' }, + }); + const panel3 = dockview.addPanel({ + id: 'panel3', + component: 'default', + position: { direction: 'below' }, + }); + + expect(panel1.api.height).toBe(200); + expect(panel2.api.height).toBe(200); + expect(panel3.api.height).toBe(200); + + panel3.api.setSize({ height: 300 }); + + expect(panel1.api.height).toBe(200); + expect(panel2.api.height).toBe(100); + expect(panel3.api.height).toBe(300); + + dockview.moveGroup({ + from: { group: panel3.api.group }, + to: { group: panel1.api.group, position: 'bottom' }, + }); + + expect(panel1.api.height).toBe(200); + expect(panel2.api.height).toBe(100); + expect(panel3.api.height).toBe(300); + }); + }); + test('set active panel', () => { dockview.layout(500, 1000); @@ -626,6 +732,7 @@ describe('dockviewComponent', () => { panel1: { id: 'panel1', contentComponent: 'default', + tabComponent: 'tab-default', title: 'panel1', }, panel2: { @@ -637,22 +744,26 @@ describe('dockviewComponent', () => { id: 'panel3', contentComponent: 'default', title: 'panel3', + renderer: 'onlyWhenVisible', }, panel4: { id: 'panel4', contentComponent: 'default', title: 'panel4', + renderer: 'always', }, panel5: { id: 'panel5', contentComponent: 'default', title: 'panel5', + minimumHeight: 100, + maximumHeight: 1000, + minimumWidth: 200, + maximumWidth: 2000, }, }, }); - // dockview.layout(1000, 1000, true); - expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({ activeGroup: 'group-1', grid: { @@ -712,6 +823,7 @@ describe('dockviewComponent', () => { panel1: { id: 'panel1', contentComponent: 'default', + tabComponent: 'tab-default', title: 'panel1', }, panel2: { @@ -723,16 +835,22 @@ describe('dockviewComponent', () => { id: 'panel3', contentComponent: 'default', title: 'panel3', + renderer: 'onlyWhenVisible', }, panel4: { id: 'panel4', contentComponent: 'default', title: 'panel4', + renderer: 'always', }, panel5: { id: 'panel5', contentComponent: 'default', title: 'panel5', + minimumHeight: 100, + maximumHeight: 1000, + minimumWidth: 200, + maximumWidth: 2000, }, }, }); diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts index 197e23e1c..d9b6d4bfb 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewGroupPanelModel.spec.ts @@ -116,10 +116,6 @@ class Watermark implements IWatermarkRenderer { return {}; } - updateParentGroup() { - // - } - dispose() { // } diff --git a/packages/dockview-core/src/__tests__/events.spec.ts b/packages/dockview-core/src/__tests__/events.spec.ts index af05c3f28..461b1518e 100644 --- a/packages/dockview-core/src/__tests__/events.spec.ts +++ b/packages/dockview-core/src/__tests__/events.spec.ts @@ -153,14 +153,14 @@ describe('events', () => { const disposable = addDisposableWindowListener( element as any, - 'mousedown', + 'pointerdown', handler, true ); expect(element.addEventListener).toBeCalledTimes(1); expect(element.addEventListener).toHaveBeenCalledWith( - 'mousedown', + 'pointerdown', handler, true ); @@ -171,7 +171,7 @@ describe('events', () => { expect(element.addEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledWith( - 'mousedown', + 'pointerdown', handler, true ); @@ -187,13 +187,13 @@ describe('events', () => { const disposable = addDisposableWindowListener( element as any, - 'mousedown', + 'pointerdown', handler ); expect(element.addEventListener).toBeCalledTimes(1); expect(element.addEventListener).toHaveBeenCalledWith( - 'mousedown', + 'pointerdown', handler, undefined ); @@ -204,7 +204,7 @@ describe('events', () => { expect(element.addEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledWith( - 'mousedown', + 'pointerdown', handler, undefined ); @@ -220,14 +220,14 @@ describe('events', () => { const disposable = addDisposableListener( element as any, - 'mousedown', + 'pointerdown', handler, true ); expect(element.addEventListener).toBeCalledTimes(1); expect(element.addEventListener).toHaveBeenCalledWith( - 'mousedown', + 'pointerdown', handler, true ); @@ -238,7 +238,7 @@ describe('events', () => { expect(element.addEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledWith( - 'mousedown', + 'pointerdown', handler, true ); @@ -254,13 +254,13 @@ describe('events', () => { const disposable = addDisposableListener( element as any, - 'mousedown', + 'pointerdown', handler ); expect(element.addEventListener).toBeCalledTimes(1); expect(element.addEventListener).toHaveBeenCalledWith( - 'mousedown', + 'pointerdown', handler, undefined ); @@ -271,7 +271,7 @@ describe('events', () => { expect(element.addEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledTimes(1); expect(element.removeEventListener).toBeCalledWith( - 'mousedown', + 'pointerdown', handler, undefined ); diff --git a/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts b/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts index 6371488ee..d8ed45209 100644 --- a/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts +++ b/packages/dockview-core/src/__tests__/gridview/baseComponentGridview.spec.ts @@ -68,8 +68,8 @@ class TestPanel implements IGridPanelView { class ClassUnderTest extends BaseGrid { readonly gridview = this.gridview; - constructor(options: BaseGridOptions) { - super(options); + constructor(parentElement: HTMLElement, options: BaseGridOptions) { + super(parentElement, options); } doRemoveGroup( @@ -106,8 +106,7 @@ class ClassUnderTest extends BaseGrid { describe('baseComponentGridview', () => { test('that .layout(...) force flag works', () => { - const cut = new ClassUnderTest({ - parentElement: document.createElement('div'), + const cut = new ClassUnderTest(document.createElement('div'), { orientation: Orientation.HORIZONTAL, proportionalLayout: true, }); @@ -131,8 +130,7 @@ describe('baseComponentGridview', () => { }); test('can add group', () => { - const cut = new ClassUnderTest({ - parentElement: document.createElement('div'), + const cut = new ClassUnderTest(document.createElement('div'), { orientation: Orientation.HORIZONTAL, proportionalLayout: true, }); diff --git a/packages/dockview-core/src/__tests__/overlay/overlay.spec.ts b/packages/dockview-core/src/__tests__/overlay/overlay.spec.ts index 90bdbec99..5611bc4c7 100644 --- a/packages/dockview-core/src/__tests__/overlay/overlay.spec.ts +++ b/packages/dockview-core/src/__tests__/overlay/overlay.spec.ts @@ -369,8 +369,11 @@ describe('overlay', () => { const overlay1 = createOverlay(); + const zIndexValue = (delta: number) => + `calc(var(--dv-overlay-z-index, 999) + ${delta})`; + expect(overlay1.element.getAttribute('aria-level')).toBe('0'); - expect(overlay1.element.style.zIndex).toBe('999'); + expect(overlay1.element.style.zIndex).toBe(zIndexValue(0)); const overlay2 = createOverlay(); const overlay3 = createOverlay(); @@ -378,38 +381,38 @@ describe('overlay', () => { expect(overlay1.element.getAttribute('aria-level')).toBe('0'); expect(overlay2.element.getAttribute('aria-level')).toBe('1'); expect(overlay3.element.getAttribute('aria-level')).toBe('2'); - expect(overlay1.element.style.zIndex).toBe('999'); - expect(overlay2.element.style.zIndex).toBe('1001'); - expect(overlay3.element.style.zIndex).toBe('1003'); + expect(overlay1.element.style.zIndex).toBe(zIndexValue(0)); + expect(overlay2.element.style.zIndex).toBe(zIndexValue(2)); + expect(overlay3.element.style.zIndex).toBe(zIndexValue(4)); overlay2.bringToFront(); expect(overlay1.element.getAttribute('aria-level')).toBe('0'); expect(overlay2.element.getAttribute('aria-level')).toBe('2'); expect(overlay3.element.getAttribute('aria-level')).toBe('1'); - expect(overlay1.element.style.zIndex).toBe('999'); - expect(overlay2.element.style.zIndex).toBe('1003'); - expect(overlay3.element.style.zIndex).toBe('1001'); + expect(overlay1.element.style.zIndex).toBe(zIndexValue(0)); + expect(overlay2.element.style.zIndex).toBe(zIndexValue(4)); + expect(overlay3.element.style.zIndex).toBe(zIndexValue(2)); overlay1.bringToFront(); expect(overlay1.element.getAttribute('aria-level')).toBe('2'); expect(overlay2.element.getAttribute('aria-level')).toBe('1'); expect(overlay3.element.getAttribute('aria-level')).toBe('0'); - expect(overlay1.element.style.zIndex).toBe('1003'); - expect(overlay2.element.style.zIndex).toBe('1001'); - expect(overlay3.element.style.zIndex).toBe('999'); + expect(overlay1.element.style.zIndex).toBe(zIndexValue(4)); + expect(overlay2.element.style.zIndex).toBe(zIndexValue(2)); + expect(overlay3.element.style.zIndex).toBe(zIndexValue(0)); overlay2.dispose(); expect(overlay1.element.getAttribute('aria-level')).toBe('1'); expect(overlay3.element.getAttribute('aria-level')).toBe('0'); - expect(overlay1.element.style.zIndex).toBe('1001'); - expect(overlay3.element.style.zIndex).toBe('999'); + expect(overlay1.element.style.zIndex).toBe(zIndexValue(2)); + expect(overlay3.element.style.zIndex).toBe(zIndexValue(0)); overlay1.dispose(); expect(overlay3.element.getAttribute('aria-level')).toBe('0'); - expect(overlay3.element.style.zIndex).toBe('999'); + expect(overlay3.element.style.zIndex).toBe(zIndexValue(0)); }); }); diff --git a/packages/dockview-core/src/__tests__/overlay/overlayRenderContainer.spec.ts b/packages/dockview-core/src/__tests__/overlay/overlayRenderContainer.spec.ts index 0e7ddfbce..250a81b46 100644 --- a/packages/dockview-core/src/__tests__/overlay/overlayRenderContainer.spec.ts +++ b/packages/dockview-core/src/__tests__/overlay/overlayRenderContainer.spec.ts @@ -258,6 +258,8 @@ describe('overlayRenderContainer', () => { await exhaustMicrotaskQueue(); expect(spy).toHaveBeenCalledWith('aria-level'); - expect(panelContentEl.parentElement!.style.zIndex).toBe('1004'); + expect(panelContentEl.parentElement!.style.zIndex).toBe( + 'calc(var(--dv-overlay-z-index, 999) + 5)' + ); }); }); diff --git a/packages/dockview-core/src/dnd/groupDragHandler.ts b/packages/dockview-core/src/dnd/groupDragHandler.ts index 7138437bf..bdda2be3b 100644 --- a/packages/dockview-core/src/dnd/groupDragHandler.ts +++ b/packages/dockview-core/src/dnd/groupDragHandler.ts @@ -21,7 +21,7 @@ export class GroupDragHandler extends DragHandler { this.addDisposables( addDisposableListener( element, - 'mousedown', + 'pointerdown', (e) => { if (e.shiftKey) { /** diff --git a/packages/dockview-core/src/dockview/components/tab/defaultTab.ts b/packages/dockview-core/src/dockview/components/tab/defaultTab.ts index 8b927a105..af86ee35b 100644 --- a/packages/dockview-core/src/dockview/components/tab/defaultTab.ts +++ b/packages/dockview-core/src/dockview/components/tab/defaultTab.ts @@ -30,7 +30,7 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer { this._element.appendChild(this.action); this.addDisposables( - addDisposableListener(this.action, 'mousedown', (ev) => { + addDisposableListener(this.action, 'pointerdown', (ev) => { ev.preventDefault(); }) ); @@ -46,7 +46,7 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer { this._title = event.title; this.render(); }), - addDisposableListener(this.action, 'mousedown', (ev) => { + addDisposableListener(this.action, 'pointerdown', (ev) => { ev.preventDefault(); }), addDisposableListener(this.action, 'click', (ev) => { diff --git a/packages/dockview-core/src/dockview/components/tab/tab.ts b/packages/dockview-core/src/dockview/components/tab/tab.ts index cf14b6df0..1eb1174d8 100644 --- a/packages/dockview-core/src/dockview/components/tab/tab.ts +++ b/packages/dockview-core/src/dockview/components/tab/tab.ts @@ -124,7 +124,7 @@ export class Tab extends CompositeDisposable { this._onDragStart.fire(event); }), dragHandler, - addDisposableListener(this._element, 'mousedown', (event) => { + addDisposableListener(this._element, 'pointerdown', (event) => { if (event.defaultPrevented) { return; } diff --git a/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts b/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts index 749e75763..9972bab90 100644 --- a/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts +++ b/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts @@ -253,7 +253,7 @@ export class TabsContainer }), addDisposableListener( this.voidContainer.element, - 'mousedown', + 'pointerdown', (event) => { const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups; @@ -278,7 +278,7 @@ export class TabsContainer } } ), - addDisposableListener(this.tabContainer, 'mousedown', (event) => { + addDisposableListener(this.tabContainer, 'pointerdown', (event) => { if (event.defaultPrevented) { return; } diff --git a/packages/dockview-core/src/dockview/components/watermark/watermark.ts b/packages/dockview-core/src/dockview/components/watermark/watermark.ts index 9b4f7a741..bee5c4b5a 100644 --- a/packages/dockview-core/src/dockview/components/watermark/watermark.ts +++ b/packages/dockview-core/src/dockview/components/watermark/watermark.ts @@ -5,8 +5,7 @@ import { import { addDisposableListener } from '../../../events'; import { toggleClass } from '../../../dom'; import { CompositeDisposable } from '../../../lifecycle'; -import { DockviewGroupPanel } from '../../dockviewGroupPanel'; -import { PanelUpdateEvent } from '../../../panel/types'; +import { IDockviewGroupPanel } from '../../dockviewGroupPanel'; import { createCloseButton } from '../../../svg'; import { DockviewApi } from '../../../api/component.api'; @@ -15,7 +14,7 @@ export class Watermark implements IWatermarkRenderer { private _element: HTMLElement; - private _group: DockviewGroupPanel | undefined; + private _group: IDockviewGroupPanel | undefined; private _api: DockviewApi | undefined; get element(): HTMLElement { @@ -52,8 +51,9 @@ export class Watermark title.appendChild(actionsContainer); this.addDisposables( - addDisposableListener(closeAnchor, 'click', (ev) => { - ev.preventDefault(); + addDisposableListener(closeAnchor, 'click', (event: MouseEvent) => { + event.preventDefault(); + if (this._group) { this._api?.removeGroup(this._group); } @@ -61,32 +61,12 @@ export class Watermark ); } - update(_event: PanelUpdateEvent): void { - // noop - } - - focus(): void { - // noop - } - - layout(_width: number, _height: number): void { - // noop - } - init(_params: WatermarkRendererInitParameters): void { this._api = _params.containerApi; + this._group = _params.group; this.render(); } - updateParentGroup(group: DockviewGroupPanel, _visible: boolean): void { - this._group = group; - this.render(); - } - - dispose(): void { - super.dispose(); - } - private render(): void { const isOneGroup = !!(this._api && this._api.size <= 1); toggleClass(this.element, 'dv-has-actions', isOneGroup); diff --git a/packages/dockview-core/src/dockview/deserializer.ts b/packages/dockview-core/src/dockview/deserializer.ts index 41a4a0102..1aa49b018 100644 --- a/packages/dockview-core/src/dockview/deserializer.ts +++ b/packages/dockview-core/src/dockview/deserializer.ts @@ -57,6 +57,10 @@ export class DefaultDockviewDeserialzier implements IPanelDeserializer { view, { renderer: panelData.renderer, + minimumWidth: panelData.minimumWidth, + minimumHeight: panelData.minimumHeight, + maximumWidth: panelData.maximumWidth, + maximumHeight: panelData.maximumHeight, } ); diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 592c39186..af3f887d1 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -3,6 +3,7 @@ import { SerializedGridObject, getGridLocation, ISerializedLeafNode, + orthogonal, } from '../gridview/gridview'; import { directionToPosition, @@ -51,7 +52,12 @@ import { DockviewPanelModel } from './dockviewPanelModel'; import { getPanelData } from '../dnd/dataTransfer'; import { Parameters } from '../panel/types'; import { Overlay } from '../overlay/overlay'; -import { addTestId, toggleClass, watchElementResize } from '../dom'; +import { + addTestId, + getDockviewTheme, + toggleClass, + watchElementResize, +} from '../dom'; import { DockviewFloatingGroupPanel } from './dockviewFloatingGroupPanel'; import { GroupDragEvent, @@ -92,33 +98,6 @@ function moveGroupWithoutDestroying(options: { }); } -function getDockviewTheme(element: HTMLElement): string | undefined { - function toClassList(element: HTMLElement) { - const list: string[] = []; - - for (let i = 0; i < element.classList.length; i++) { - list.push(element.classList.item(i)!); - } - - return list; - } - - let theme: string | undefined = undefined; - let parent: HTMLElement | null = element; - - while (parent !== null) { - theme = toClassList(parent).find((cls) => - cls.startsWith('dockview-theme-') - ); - if (typeof theme === 'string') { - break; - } - parent = parent.parentElement; - } - - return theme; -} - export interface PanelReference { update: (event: { params: { [key: string]: any } }) => void; remove: () => void; @@ -362,23 +341,18 @@ export class DockviewComponent } constructor(parentElement: HTMLElement, options: DockviewComponentOptions) { - super({ + super(parentElement, { proportionalLayout: true, orientation: Orientation.HORIZONTAL, styles: options.hideBorders ? { separatorBorder: 'transparent' } : undefined, - parentElement: parentElement, disableAutoResizing: options.disableAutoResizing, locked: options.locked, margin: options.gap, className: options.className, }); - // const gready = document.createElement('div'); - // gready.className = 'dv-overlay-render-container'; - // this.gridview.element.appendChild(gready); - this.overlayRenderContainer = new OverlayRenderContainer( this.gridview.element, this @@ -1022,19 +996,9 @@ export class DockviewComponent override updateOptions(options: Partial): void { super.updateOptions(options); - const changed_floatingGroupBounds = - 'floatingGroupBounds' in options && - options.floatingGroupBounds !== this.options.floatingGroupBounds; - - const changed_rootOverlayOptions = - 'rootOverlayModel' in options && - options.rootOverlayModel !== this.options.rootOverlayModel; - - this._options = { ...this.options, ...options }; - - if (changed_floatingGroupBounds) { + if ('floatingGroupBounds' in options) { for (const group of this._floatingGroups) { - switch (this.options.floatingGroupBounds) { + switch (options.floatingGroupBounds) { case 'boundedWithinViewport': group.overlay.minimumInViewportHeight = undefined; group.overlay.minimumInViewportWidth = undefined; @@ -1047,30 +1011,26 @@ export class DockviewComponent break; default: group.overlay.minimumInViewportHeight = - this.options.floatingGroupBounds?.minimumHeightWithinViewport; + options.floatingGroupBounds?.minimumHeightWithinViewport; group.overlay.minimumInViewportWidth = - this.options.floatingGroupBounds?.minimumWidthWithinViewport; + options.floatingGroupBounds?.minimumWidthWithinViewport; } group.overlay.setBounds(); } } - if (changed_rootOverlayOptions) { - this._rootDropTarget.setOverlayModel(options.rootOverlayModel!); + if ('rootOverlayModel' in options) { + this._rootDropTarget.setOverlayModel( + options.rootOverlayModel ?? DEFAULT_ROOT_OVERLAY_MODEL + ); } - if ( - // if explicitly set as `undefined` - 'gap' in options && - options.gap === undefined - ) { - this.gridview.margin = 0; + if ('gap' in options) { + this.gridview.margin = options.gap ?? 0; } - if (typeof options.gap === 'number') { - this.gridview.margin = options.gap; - } + this._options = { ...this.options, ...options }; this.layout(this.gridview.width, this.gridview.height, true); } @@ -1412,6 +1372,11 @@ export class DockviewComponent ); } + const initial = { + width: options.initialWidth, + height: options.initialHeight, + }; + if (options.position) { if (isPanelOptionsWithPanel(options.position)) { const referencePanel = @@ -1453,6 +1418,11 @@ export class DockviewComponent this.doSetGroupAndPanelActive(group); } + group.api.setSize({ + height: initial?.height, + width: initial?.width, + }); + return panel; } } else { @@ -1499,6 +1469,11 @@ export class DockviewComponent skipSetGroupActive: options.inactive, }); + referenceGroup.api.setSize({ + width: initial?.width, + height: initial?.height, + }); + if (!options.inactive) { this.doSetGroupAndPanelActive(referenceGroup); } @@ -1509,7 +1484,13 @@ export class DockviewComponent location, target ); - const group = this.createGroupAtLocation(relativeLocation); + const group = this.createGroupAtLocation( + relativeLocation, + this.orientationAtLocation(relativeLocation) === + Orientation.VERTICAL + ? initial?.height + : initial?.width + ); panel = this.createPanel(options, group); group.model.openPanel(panel, { skipSetActive: options.inactive, @@ -1543,7 +1524,12 @@ export class DockviewComponent skipSetGroupActive: options.inactive, }); } else { - const group = this.createGroupAtLocation(); + const group = this.createGroupAtLocation( + [0], + this.gridview.orientation === Orientation.VERTICAL + ? initial?.height + : initial?.width + ); panel = this.createPanel(options, group); group.model.openPanel(panel, { skipSetActive: options.inactive, @@ -1681,7 +1667,12 @@ export class DockviewComponent ); const group = this.createGroup(options); - this.doAddGroup(group, relativeLocation); + const size = + this.getLocationOrientation(relativeLocation) === + Orientation.VERTICAL + ? options.initialHeight + : options.initialWidth; + this.doAddGroup(group, relativeLocation, size); if (!options.skipSetActive) { this.doSetGroupAndPanelActive(group); } @@ -1695,6 +1686,13 @@ export class DockviewComponent } } + private getLocationOrientation(location: number[]) { + return location.length % 2 == 0 && + this.gridview.orientation === Orientation.HORIZONTAL + ? Orientation.HORIZONTAL + : Orientation.VERTICAL; + } + removeGroup( group: DockviewGroupPanel, options?: @@ -2109,7 +2107,24 @@ export class DockviewComponent target ); - this.gridview.addView(from, Sizing.Distribute, dropLocation); + let size: number; + + switch (this.gridview.orientation) { + case Orientation.VERTICAL: + size = + referenceLocation.length % 2 == 0 + ? from.api.width + : from.api.height; + break; + case Orientation.HORIZONTAL: + size = + referenceLocation.length % 2 == 0 + ? from.api.height + : from.api.width; + break; + } + + this.gridview.addView(from, size, dropLocation); } from.panels.forEach((panel) => { @@ -2283,7 +2298,13 @@ export class DockviewComponent this._api, group, view, - { renderer: options.renderer } + { + renderer: options.renderer, + minimumWidth: options.minimumWidth, + minimumHeight: options.minimumHeight, + maximumWidth: options.maximumWidth, + maximumHeight: options.maximumHeight, + } ); panel.init({ @@ -2295,10 +2316,11 @@ export class DockviewComponent } private createGroupAtLocation( - location: number[] = [0] + location: number[], + size?: number ): DockviewGroupPanel { const group = this.createGroup(); - this.doAddGroup(group, location); + this.doAddGroup(group, location, size); return group; } @@ -2307,4 +2329,11 @@ export class DockviewComponent group.value.model.containsPanel(panel) )?.value; } + + private orientationAtLocation(location: number[]) { + const rootOrientation = this.gridview.orientation; + return location.length % 2 == 1 + ? rootOrientation + : orthogonal(rootOrientation); + } } diff --git a/packages/dockview-core/src/dockview/dockviewGroupPanel.ts b/packages/dockview-core/src/dockview/dockviewGroupPanel.ts index 6f01fae5f..4efee9cd6 100644 --- a/packages/dockview-core/src/dockview/dockviewGroupPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewGroupPanel.ts @@ -34,6 +34,34 @@ export class DockviewGroupPanel { private readonly _model: DockviewGroupPanelModel; + get minimumWidth(): number { + const activePanelMinimumWidth = this.activePanel?.minimumWidth; + return typeof activePanelMinimumWidth === 'number' + ? activePanelMinimumWidth + : MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH; + } + + get minimumHeight(): number { + const activePanelMinimumHeight = this.activePanel?.minimumHeight; + return typeof activePanelMinimumHeight === 'number' + ? activePanelMinimumHeight + : MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT; + } + + get maximumWidth(): number { + const activePanelMaximumWidth = this.activePanel?.maximumWidth; + return typeof activePanelMaximumWidth === 'number' + ? activePanelMaximumWidth + : Number.MAX_SAFE_INTEGER; + } + + get maximumHeight(): number { + const activePanelMaximumHeight = this.activePanel?.maximumHeight; + return typeof activePanelMaximumHeight === 'number' + ? activePanelMaximumHeight + : Number.MAX_SAFE_INTEGER; + } + get panels(): IDockviewPanel[] { return this._model.panels; } @@ -71,8 +99,14 @@ export class DockviewGroupPanel id, 'groupview_default', { - minimumHeight: MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT, - minimumWidth: MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH, + minimumHeight: + options.constraints?.minimumHeight ?? + MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT, + minimumWidth: + options.constraints?.maximumHeight ?? + MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH, + maximumHeight: options.constraints?.maximumHeight, + maximumWidth: options.constraints?.maximumWidth, }, new DockviewGroupPanelApiImpl(id, accessor) ); diff --git a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts index 1c292a6c3..21e9cbe2d 100644 --- a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts +++ b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts @@ -38,6 +38,7 @@ import { } from './options'; import { OverlayRenderContainer } from '../overlay/overlayRenderContainer'; import { TitleEvent } from '../api/dockviewPanelApi'; +import { Contraints } from '../gridview/gridviewPanel'; interface GroupMoveEvent { groupId: string; @@ -50,6 +51,9 @@ interface CoreGroupOptions { locked?: DockviewGroupPanelLocked; hideHeader?: boolean; skipSetActive?: boolean; + constraints?: Partial; + initialWidth?: number; + initialHeight?: number; } export interface GroupOptions extends CoreGroupOptions { @@ -972,8 +976,6 @@ export class DockviewGroupPanelModel this.tabsContainer.hide(); this.contentContainer.element.appendChild(this.watermark.element); - - this.watermark.updateParentGroup(this.groupPanel, true); } if (!this.isEmpty && this.watermark) { this.watermark.element.remove(); diff --git a/packages/dockview-core/src/dockview/dockviewPanel.ts b/packages/dockview-core/src/dockview/dockviewPanel.ts index 984c3fcdb..8eb2cfb7f 100644 --- a/packages/dockview-core/src/dockview/dockviewPanel.ts +++ b/packages/dockview-core/src/dockview/dockviewPanel.ts @@ -11,6 +11,7 @@ import { IDockviewPanelModel } from './dockviewPanelModel'; import { DockviewComponent } from './dockviewComponent'; import { DockviewPanelRenderer } from '../overlay/overlayRenderContainer'; import { WillFocusEvent } from '../api/panelApi'; +import { Contraints } from '../gridview/gridviewPanel'; export interface IDockviewPanel extends IDisposable, IPanel { readonly view: IDockviewPanelModel; @@ -18,6 +19,10 @@ export interface IDockviewPanel extends IDisposable, IPanel { readonly api: DockviewPanelApi; readonly title: string | undefined; readonly params: Parameters | undefined; + readonly minimumWidth?: number; + readonly minimumHeight?: number; + readonly maximumWidth?: number; + readonly maximumHeight?: number; updateParentGroup( group: DockviewGroupPanel, options?: { skipSetActive?: boolean } @@ -40,6 +45,11 @@ export class DockviewPanel private _title: string | undefined; private _renderer: DockviewPanelRenderer | undefined; + private _minimumWidth: number | undefined; + private _minimumHeight: number | undefined; + private _maximumWidth: number | undefined; + private _maximumHeight: number | undefined; + get params(): Parameters | undefined { return this._params; } @@ -56,6 +66,22 @@ export class DockviewPanel return this._renderer ?? this.accessor.renderer; } + get minimumWidth(): number | undefined { + return this._minimumWidth; + } + + get minimumHeight(): number | undefined { + return this._minimumHeight; + } + + get maximumWidth(): number | undefined { + return this._maximumWidth; + } + + get maximumHeight(): number | undefined { + return this._maximumHeight; + } + constructor( public readonly id: string, component: string, @@ -64,11 +90,15 @@ export class DockviewPanel private readonly containerApi: DockviewApi, group: DockviewGroupPanel, readonly view: IDockviewPanelModel, - options: { renderer?: DockviewPanelRenderer } + options: { renderer?: DockviewPanelRenderer } & Partial ) { super(); this._renderer = options.renderer; this._group = group; + this._minimumWidth = options.minimumWidth; + this._minimumHeight = options.minimumHeight; + this._maximumWidth = options.maximumWidth; + this._maximumHeight = options.maximumHeight; this.api = new DockviewPanelApiImpl( this, @@ -129,6 +159,10 @@ export class DockviewPanel : undefined, title: this.title, renderer: this._renderer, + minimumHeight: this._minimumHeight, + maximumHeight: this._maximumHeight, + minimumWidth: this._minimumWidth, + maximumWidth: this._maximumWidth, }; } diff --git a/packages/dockview-core/src/dockview/options.ts b/packages/dockview-core/src/dockview/options.ts index 5fce93ebf..561a732f4 100644 --- a/packages/dockview-core/src/dockview/options.ts +++ b/packages/dockview-core/src/dockview/options.ts @@ -16,6 +16,7 @@ import { DockviewPanelRenderer } from '../overlay/overlayRenderContainer'; import { IGroupHeaderProps } from './framework'; import { AnchoredBox } from '../types'; import { FloatingGroupOptions } from './dockviewComponent'; +import { Contraints } from '../gridview/gridviewPanel'; export interface IHeaderActionsRenderer extends IDisposable { readonly element: HTMLElement; @@ -116,6 +117,17 @@ export const PROPERTY_KEYS: (keyof DockviewOptions)[] = (() => { return Object.keys(properties) as (keyof DockviewOptions)[]; })(); +export interface CreateComponentOptions { + /** + * The unqiue identifer of the component + */ + id: string; + /** + * The component name, this should determine what is rendered. + */ + name: string; +} + export interface DockviewFrameworkOptions { defaultTabComponent?: string; createRightHeaderActionComponent?: ( @@ -127,14 +139,10 @@ export interface DockviewFrameworkOptions { createPrefixHeaderActionComponent?: ( group: DockviewGroupPanel ) => IHeaderActionsRenderer; - createTabComponent?: (options: { - id: string; - name: string; - }) => ITabRenderer | undefined; - createComponent: (options: { - id: string; - name: string; - }) => IContentRenderer; + createTabComponent?: ( + options: CreateComponentOptions + ) => ITabRenderer | undefined; + createComponent: (options: CreateComponentOptions) => IContentRenderer; createWatermarkComponent?: () => IWatermarkRenderer; } @@ -230,7 +238,10 @@ export type AddPanelOptions

= { * Defaults to `false` which forces newly added panels to become active. */ inactive?: boolean; -} & Partial; + initialWidth?: number; + initialHeight?: number; +} & Partial & + Partial; type AddGroupOptionsWithPanel = { referencePanel: string | IDockviewPanel; diff --git a/packages/dockview-core/src/dockview/types.ts b/packages/dockview-core/src/dockview/types.ts index 99c7c38d9..aa5cae998 100644 --- a/packages/dockview-core/src/dockview/types.ts +++ b/packages/dockview-core/src/dockview/types.ts @@ -32,7 +32,6 @@ export interface IWatermarkRenderer extends Optional, RendererMethodOptionalList> { readonly element: HTMLElement; init: (params: WatermarkRendererInitParameters) => void; - updateParentGroup(group: DockviewGroupPanel, visible: boolean): void; } export interface ITabRenderer @@ -64,4 +63,8 @@ export interface GroupviewPanelState { title?: string; renderer?: DockviewPanelRenderer; params?: { [key: string]: any }; + minimumWidth?: number; + minimumHeight?: number; + maximumWidth?: number; + maximumHeight?: number; } diff --git a/packages/dockview-core/src/dom.ts b/packages/dockview-core/src/dom.ts index 249b84181..bcc82a496 100644 --- a/packages/dockview-core/src/dom.ts +++ b/packages/dockview-core/src/dom.ts @@ -280,3 +280,50 @@ export function disableIframePointEvents() { }, }; } + +export function getDockviewTheme(element: HTMLElement): string | undefined { + function toClassList(element: HTMLElement) { + const list: string[] = []; + + for (let i = 0; i < element.classList.length; i++) { + list.push(element.classList.item(i)!); + } + + return list; + } + + let theme: string | undefined = undefined; + let parent: HTMLElement | null = element; + + while (parent !== null) { + theme = toClassList(parent).find((cls) => + cls.startsWith('dockview-theme-') + ); + if (typeof theme === 'string') { + break; + } + parent = parent.parentElement; + } + + return theme; +} + +export class Classnames { + private _classNames: string[] = []; + + constructor(private readonly element: HTMLElement) {} + + setClassNames(classNames: string) { + for (const className of this._classNames) { + toggleClass(this.element, className, false); + } + + this._classNames = classNames + .split(' ') + .filter((v) => v.trim().length > 0); + + for (const className of this._classNames) { + toggleClass(this.element, className, true); + } + } +} diff --git a/packages/dockview-core/src/gridview/baseComponentGridview.ts b/packages/dockview-core/src/gridview/baseComponentGridview.ts index 6bed2c62c..332cef90c 100644 --- a/packages/dockview-core/src/gridview/baseComponentGridview.ts +++ b/packages/dockview-core/src/gridview/baseComponentGridview.ts @@ -7,7 +7,7 @@ import { ISplitviewStyles, Orientation, Sizing } from '../splitview/splitview'; import { IPanel } from '../panel/types'; import { MovementOptions2 } from '../dockview/options'; import { Resizable } from '../resizable'; -import { toggleClass } from '../dom'; +import { Classnames, toggleClass } from '../dom'; const nextLayoutId = sequentialNumberGenerator(); @@ -33,7 +33,6 @@ export interface BaseGridOptions { readonly proportionalLayout: boolean; readonly orientation: Orientation; readonly styles?: ISplitviewStyles; - readonly parentElement: HTMLElement; readonly disableAutoResizing?: boolean; readonly locked?: boolean; readonly margin?: number; @@ -100,7 +99,7 @@ export abstract class BaseGrid readonly onDidViewVisibilityChangeMicroTaskQueue = this._onDidViewVisibilityChangeMicroTaskQueue.onEvent; - private classNames: string[] = []; + private readonly _classNames: Classnames; get id(): string { return this._id; @@ -147,18 +146,15 @@ export abstract class BaseGrid this.gridview.locked = value; } - constructor(options: BaseGridOptions) { + constructor(parentElement: HTMLElement, options: BaseGridOptions) { super(document.createElement('div'), options.disableAutoResizing); this.element.style.height = '100%'; this.element.style.width = '100%'; - this.classNames = options.className?.split(' ') ?? []; + this._classNames = new Classnames(this.element); + this._classNames.setClassNames(options.className ?? ''); - for (const className of this.classNames) { - toggleClass(this.element, className, true); - } - - options.parentElement.appendChild(this.element); + parentElement.appendChild(this.element); this.gridview = new Gridview( !!options.proportionalLayout, @@ -214,14 +210,26 @@ export abstract class BaseGrid } updateOptions(options: Partial) { + if (typeof options.proportionalLayout === 'boolean') { + // this.gridview.proportionalLayout = options.proportionalLayout; // not supported + } + if (options.orientation) { + this.gridview.orientation = options.orientation; + } + if ('styles' in options) { + // this.gridview.styles = options.styles; // not supported + } + if ('disableResizing' in options) { + this.disableResizing = options.disableAutoResizing ?? false; + } + if ('locked' in options) { + this.locked = options.locked ?? false; + } + if ('margin' in options) { + this.gridview.margin = options.margin ?? 0; + } if ('className' in options) { - for (const className of this.classNames) { - toggleClass(this.element, className, false); - } - this.classNames = options.className?.split(' ') ?? []; - for (const className of this.classNames) { - toggleClass(this.element, className, true); - } + this._classNames.setClassNames(options.className ?? ''); } } diff --git a/packages/dockview-core/src/gridview/gridviewComponent.ts b/packages/dockview-core/src/gridview/gridviewComponent.ts index c342d3a50..a0ea22288 100644 --- a/packages/dockview-core/src/gridview/gridviewComponent.ts +++ b/packages/dockview-core/src/gridview/gridviewComponent.ts @@ -115,8 +115,7 @@ export class GridviewComponent } constructor(parentElement: HTMLElement, options: GridviewComponentOptions) { - super({ - parentElement: parentElement, + super(parentElement, { proportionalLayout: options.proportionalLayout, orientation: options.orientation, styles: options.styles, diff --git a/packages/dockview-core/src/gridview/gridviewPanel.ts b/packages/dockview-core/src/gridview/gridviewPanel.ts index 916c4f1e1..956d9baf8 100644 --- a/packages/dockview-core/src/gridview/gridviewPanel.ts +++ b/packages/dockview-core/src/gridview/gridviewPanel.ts @@ -15,6 +15,13 @@ import { Emitter, Event } from '../events'; import { IViewSize } from './gridview'; import { BaseGrid, IGridPanelView } from './baseComponentGridview'; +export interface Contraints { + minimumWidth?: number; + maximumWidth?: number; + minimumHeight?: number; + maximumHeight?: number; +} + export interface GridviewInitParameters extends PanelInitParameters { minimumWidth?: number; maximumWidth?: number; diff --git a/packages/dockview-core/src/overlay/overlay.scss b/packages/dockview-core/src/overlay/overlay.scss index 971d8629c..89788e032 100644 --- a/packages/dockview-core/src/overlay/overlay.scss +++ b/packages/dockview-core/src/overlay/overlay.scss @@ -26,8 +26,10 @@ } .dv-resize-container { + --dv-overlay-z-index: var(--dv-overlay-z-index, 999); + position: absolute; - z-index: 997; + z-index: calc(var(--dv-overlay-z-index) - 2); border: 1px solid var(--dv-tab-divider-color); box-shadow: var(--dv-floating-box-shadow); @@ -41,7 +43,7 @@ width: calc(100% - 8px); left: 4px; top: -2px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: ns-resize; } @@ -51,7 +53,7 @@ width: calc(100% - 8px); left: 4px; bottom: -2px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: ns-resize; } @@ -61,7 +63,7 @@ width: 4px; left: -2px; top: 4px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: ew-resize; } @@ -71,7 +73,7 @@ width: 4px; right: -2px; top: 4px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: ew-resize; } @@ -81,7 +83,7 @@ width: 4px; top: -2px; left: -2px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: nw-resize; } @@ -91,7 +93,7 @@ width: 4px; right: -2px; top: -2px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: ne-resize; } @@ -101,7 +103,7 @@ width: 4px; left: -2px; bottom: -2px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: sw-resize; } @@ -111,7 +113,7 @@ width: 4px; right: -2px; bottom: -2px; - z-index: 999; + z-index: var(--dv-overlay-z-index); position: absolute; cursor: se-resize; } diff --git a/packages/dockview-core/src/overlay/overlay.ts b/packages/dockview-core/src/overlay/overlay.ts index 0f39961ce..c0a2fd598 100644 --- a/packages/dockview-core/src/overlay/overlay.ts +++ b/packages/dockview-core/src/overlay/overlay.ts @@ -13,8 +13,6 @@ import { CompositeDisposable, MutableDisposable } from '../lifecycle'; import { clamp } from '../math'; import { AnchoredBox } from '../types'; -export const DEFAULT_OVERLAY_Z_INDEX = 999; - class AriaLevelTracker { private _orderedList: HTMLElement[] = []; @@ -37,7 +35,9 @@ class AriaLevelTracker { private update(): void { for (let i = 0; i < this._orderedList.length; i++) { this._orderedList[i].setAttribute('aria-level', `${i}`); - this._orderedList[i].style.zIndex = `${DEFAULT_OVERLAY_Z_INDEX + i * 2}`; + this._orderedList[ + i + ].style.zIndex = `calc(var(--dv-overlay-z-index, 999) + ${i * 2})`; } } } @@ -241,7 +241,7 @@ export class Overlay extends CompositeDisposable { iframes.release(); }, }, - addDisposableWindowListener(window, 'mousemove', (e) => { + addDisposableWindowListener(window, 'pointermove', (e) => { const containerRect = this.options.container.getBoundingClientRect(); const x = e.clientX - containerRect.left; @@ -327,7 +327,7 @@ export class Overlay extends CompositeDisposable { this.setBounds(bounds); }), - addDisposableWindowListener(window, 'mouseup', () => { + addDisposableWindowListener(window, 'pointerup', () => { toggleClass( this._element, 'dv-resize-container-dragging', @@ -342,7 +342,7 @@ export class Overlay extends CompositeDisposable { this.addDisposables( move, - addDisposableListener(dragTarget, 'mousedown', (event) => { + addDisposableListener(dragTarget, 'pointerdown', (event) => { if (event.defaultPrevented) { event.preventDefault(); return; @@ -358,7 +358,7 @@ export class Overlay extends CompositeDisposable { }), addDisposableListener( this.options.content, - 'mousedown', + 'pointerdown', (event) => { if (event.defaultPrevented) { return; @@ -377,7 +377,7 @@ export class Overlay extends CompositeDisposable { ), addDisposableListener( this.options.content, - 'mousedown', + 'pointerdown', () => { arialLevelTracker.push(this._element); }, @@ -409,7 +409,7 @@ export class Overlay extends CompositeDisposable { this.addDisposables( move, - addDisposableListener(resizeHandleElement, 'mousedown', (e) => { + addDisposableListener(resizeHandleElement, 'pointerdown', (e) => { e.preventDefault(); let startPosition: { @@ -422,7 +422,7 @@ export class Overlay extends CompositeDisposable { const iframes = disableIframePointEvents(); move.value = new CompositeDisposable( - addDisposableWindowListener(window, 'mousemove', (e) => { + addDisposableWindowListener(window, 'pointermove', (e) => { const containerRect = this.options.container.getBoundingClientRect(); const overlayRect = @@ -593,7 +593,7 @@ export class Overlay extends CompositeDisposable { iframes.release(); }, }, - addDisposableWindowListener(window, 'mouseup', () => { + addDisposableWindowListener(window, 'pointerup', () => { move.dispose(); this._onDidChangeEnd.fire(); }) diff --git a/packages/dockview-core/src/overlay/overlayReadyContainer.scss b/packages/dockview-core/src/overlay/overlayReadyContainer.scss index fbd978841..18cc80781 100644 --- a/packages/dockview-core/src/overlay/overlayReadyContainer.scss +++ b/packages/dockview-core/src/overlay/overlayReadyContainer.scss @@ -1,14 +1,12 @@ .dv-render-overlay { + --dv-overlay-z-index: var(--dv-overlay-z-index, 999); + position: absolute; z-index: 1; height: 100%; &.dv-render-overlay-float { - z-index: 998; - - &.dv-render-overlay-active { - // z-index: 1000; - } + z-index: calc(var(--dv-overlay-z-index) - 1); } } diff --git a/packages/dockview-core/src/overlay/overlayRenderContainer.ts b/packages/dockview-core/src/overlay/overlayRenderContainer.ts index 1d68042e9..f83f50e5e 100644 --- a/packages/dockview-core/src/overlay/overlayRenderContainer.ts +++ b/packages/dockview-core/src/overlay/overlayRenderContainer.ts @@ -9,7 +9,6 @@ import { } from '../lifecycle'; import { IDockviewPanel } from '../dockview/dockviewPanel'; import { DockviewComponent } from '../dockview/dockviewComponent'; -import { DEFAULT_OVERLAY_Z_INDEX } from './overlay'; export type DockviewPanelRenderer = 'onlyWhenVisible' | 'always'; @@ -137,9 +136,9 @@ export class OverlayRenderContainer extends CompositeDisposable { const level = Number( element.getAttribute('aria-level') ); - focusContainer.style.zIndex = `${ - DEFAULT_OVERLAY_Z_INDEX + level * 2 + 1 - }`; + focusContainer.style.zIndex = `calc(var(--dv-overlay-z-index, 999) + ${ + level * 2 + 1 + })`; }; const observer = new MutationObserver(() => { diff --git a/packages/dockview-core/src/paneview/paneviewComponent.ts b/packages/dockview-core/src/paneview/paneviewComponent.ts index 944378c31..2920cb802 100644 --- a/packages/dockview-core/src/paneview/paneviewComponent.ts +++ b/packages/dockview-core/src/paneview/paneviewComponent.ts @@ -24,7 +24,7 @@ import { sequentialNumberGenerator } from '../math'; import { PaneTransfer } from '../dnd/dataTransfer'; import { Resizable } from '../resizable'; import { Parameters } from '../panel/types'; -import { toggleClass } from '../dom'; +import { Classnames, toggleClass } from '../dom'; const nextLayoutId = sequentialNumberGenerator(); @@ -152,7 +152,7 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent { private readonly _onDidRemoveView = new Emitter(); readonly onDidRemoveView = this._onDidRemoveView.event; - private classNames: string[] = []; + private readonly _classNames: Classnames; get id(): string { return this._id; @@ -213,11 +213,8 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent { this._onDidRemoveView ); - this.classNames = options.className?.split(' ') ?? []; - - for (const className of this.classNames) { - toggleClass(this.element, className, true); - } + this._classNames = new Classnames(this.element); + this._classNames.setClassNames(options.className ?? ''); this._options = options; @@ -247,13 +244,11 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent { updateOptions(options: Partial): void { if ('className' in options) { - for (const className of this.classNames) { - toggleClass(this.element, className, false); - } - this.classNames = options.className?.split(' ') ?? []; - for (const className of this.classNames) { - toggleClass(this.element, className, true); - } + this._classNames.setClassNames(options.className ?? ''); + } + + if ('disableResizing' in options) { + this.disableResizing = options.disableAutoResizing ?? false; } this._options = { ...this.options, ...options }; diff --git a/packages/dockview-core/src/popoutWindow.ts b/packages/dockview-core/src/popoutWindow.ts index b289ba645..14564cdef 100644 --- a/packages/dockview-core/src/popoutWindow.ts +++ b/packages/dockview-core/src/popoutWindow.ts @@ -1,6 +1,6 @@ import { addStyles } from './dom'; import { Emitter, addDisposableWindowListener } from './events'; -import { CompositeDisposable, IDisposable } from './lifecycle'; +import { CompositeDisposable, Disposable, IDisposable } from './lifecycle'; import { Box } from './types'; export type PopoutWindowOptions = { @@ -99,6 +99,9 @@ export class PopoutWindow extends CompositeDisposable { this._window = { value: externalWindow, disposable }; disposable.addDisposables( + Disposable.from(() => { + externalWindow.close(); + }), addDisposableWindowListener(window, 'beforeunload', () => { /** * before the main window closes we should close this popup too diff --git a/packages/dockview-core/src/splitview/splitviewComponent.ts b/packages/dockview-core/src/splitview/splitviewComponent.ts index dc770d9a9..aa666fbfe 100644 --- a/packages/dockview-core/src/splitview/splitviewComponent.ts +++ b/packages/dockview-core/src/splitview/splitviewComponent.ts @@ -17,7 +17,7 @@ import { Emitter, Event } from '../events'; import { SplitviewPanel, ISplitviewPanel } from './splitviewPanel'; import { createComponent } from '../panel/componentFactory'; import { Resizable } from '../resizable'; -import { toggleClass } from '../dom'; +import { Classnames, toggleClass } from '../dom'; export interface SerializedSplitviewPanelData { id: string; @@ -100,7 +100,7 @@ export class SplitviewComponent private readonly _onDidLayoutChange = new Emitter(); readonly onDidLayoutChange: Event = this._onDidLayoutChange.event; - private classNames: string[] = []; + private readonly _classNames: Classnames; get panels(): SplitviewPanel[] { return this.splitview.getViews(); @@ -162,11 +162,8 @@ export class SplitviewComponent ) { super(parentElement, options.disableAutoResizing); - this.classNames = options.className?.split(' ') ?? []; - - for (const className of this.classNames) { - toggleClass(this.element, className, true); - } + this._classNames = new Classnames(this.element); + this._classNames.setClassNames(options.className ?? ''); this._options = options; @@ -189,25 +186,19 @@ export class SplitviewComponent updateOptions(options: Partial): void { if ('className' in options) { - for (const className of this.classNames) { - toggleClass(this.element, className, false); - } - this.classNames = options.className?.split(' ') ?? []; - for (const className of this.classNames) { - toggleClass(this.element, className, true); - } + this._classNames.setClassNames(options.className ?? ''); } - const hasOrientationChanged = - typeof options.orientation === 'string' && - this.options.orientation !== options.orientation; + if ('disableResizing' in options) { + this.disableResizing = options.disableAutoResizing ?? false; + } - this._options = { ...this.options, ...options }; - - if (hasOrientationChanged) { + if (typeof options.orientation === 'string') { this.splitview.orientation = options.orientation!; } + this._options = { ...this.options, ...options }; + this.splitview.layout( this.splitview.size, this.splitview.orthogonalSize diff --git a/packages/dockview-core/src/theme.scss b/packages/dockview-core/src/theme.scss index 6cd64d6b0..e121f583a 100644 --- a/packages/dockview-core/src/theme.scss +++ b/packages/dockview-core/src/theme.scss @@ -8,6 +8,7 @@ --dv-tabs-container-scrollbar-color: #888; --dv-icon-hover-background-color: rgba(90, 93, 94, 0.31); --dv-floating-box-shadow: 8px 8px 8px 0px rgba(83, 89, 93, 0.5); + --dv-overlay-z-index: 999; } @mixin dockview-theme-dark-mixin { @@ -267,29 +268,28 @@ } } - .dv-vertical > .dv-sash-container > .dv-sash { - - &:not(.disabled) { - &::after { - content: ''; - height: 4px; - width: 40px; - border-radius: 2px; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background-color: var(--dv-separator-handle-background-color); - position: absolute; - } - - &:hover { + .vertical > .sash-container > .sash { + &:not(.disabled) { &::after { - background-color: var( - --dv-separator-handle-hover-background-color - ); + content: ''; + height: 4px; + width: 40px; + border-radius: 2px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: var(--dv-separator-handle-background-color); + position: absolute; + } + + &:hover { + &::after { + background-color: var( + --dv-separator-handle-hover-background-color + ); + } } } - } } .dv-horizontal > .dv-sash-container > .dv-sash { @@ -308,12 +308,25 @@ &:hover { &::after { - background-color: var( - --dv-separator-handle-hover-background-color - ); + content: ''; + height: 40px; + width: 4px; + border-radius: 2px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: var(--dv-separator-handle-background-color); + position: absolute; + } + + &:hover { + &::after { + background-color: var( + --dv-separator-handle-hover-background-color + ); + } } } - } } } @@ -326,7 +339,7 @@ --dv-tabs-and-actions-container-background-color: #fcfcfc; // --dv-activegroup-visiblepanel-tab-background-color: #f0f1f2; - --dv-activegroup-hiddenpanel-tab-background-color: ##fcfcfc; + --dv-activegroup-hiddenpanel-tab-background-color: #fcfcfc; --dv-inactivegroup-visiblepanel-tab-background-color: #f0f1f2; --dv-inactivegroup-hiddenpanel-tab-background-color: #fcfcfc; --dv-tab-divider-color: transparent; diff --git a/packages/dockview-react/package.json b/packages/dockview-react/package.json index d62990c82..5a8508a94 100644 --- a/packages/dockview-react/package.json +++ b/packages/dockview-react/package.json @@ -1,6 +1,6 @@ { "name": "dockview-react", - "version": "1.16.1", + "version": "1.17.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": "^1.16.1" + "dockview": "^1.17.2" } } diff --git a/packages/dockview-vue/package.json b/packages/dockview-vue/package.json index 7994f7081..6fbef7925 100644 --- a/packages/dockview-vue/package.json +++ b/packages/dockview-vue/package.json @@ -1,6 +1,6 @@ { "name": "dockview-vue", - "version": "1.16.1", + "version": "1.17.2", "description": "Zero dependency layout manager supporting tabs, grids and splitviews", "keywords": [ "splitview", @@ -52,6 +52,6 @@ "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue --coverage" }, "dependencies": { - "dockview-core": "^1.16.1" + "dockview-core": "^1.17.2" } } diff --git a/packages/dockview-vue/src/utils.ts b/packages/dockview-vue/src/utils.ts index a4e18a5fe..4b6252899 100644 --- a/packages/dockview-vue/src/utils.ts +++ b/packages/dockview-vue/src/utils.ts @@ -183,10 +183,6 @@ export class VueWatermarkRenderer ); } - updateParentGroup(group: DockviewGroupPanel, visible: boolean): void { - // TODO: make optional on interface - } - update(event: PanelUpdateEvent): void { // noop } diff --git a/packages/dockview/README.md b/packages/dockview/README.md index 7a0dc6c1e..7c8472630 100644 --- a/packages/dockview/README.md +++ b/packages/dockview/README.md @@ -16,6 +16,8 @@ ## +![](https://github.com/mathuo/dockview/blob/HEAD/packages/docs/static/img/splashscreen.gif?raw=true) + Please see the website: https://dockview.dev ## Features diff --git a/packages/dockview/package.json b/packages/dockview/package.json index 292463f40..89fd9e985 100644 --- a/packages/dockview/package.json +++ b/packages/dockview/package.json @@ -1,6 +1,6 @@ { "name": "dockview", - "version": "1.16.1", + "version": "1.17.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": "^1.16.1" + "dockview-core": "^1.17.2" } } diff --git a/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx b/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx index d5fb32c7d..427e9650e 100644 --- a/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx +++ b/packages/dockview/src/__tests__/dockview/defaultTab.spec.tsx @@ -176,7 +176,7 @@ describe('defaultTab', () => { expect(element.querySelector('.dv-default-tab-action')).toBeTruthy(); }); - test('that mouseDown on close button prevents panel becoming active', async () => { + test('that pointerDown on close button prevents panel becoming active', async () => { const api = fromPartial({ setActive: jest.fn(), onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE), @@ -197,7 +197,7 @@ describe('defaultTab', () => { '.dv-default-tab-action' ) as HTMLElement; - fireEvent.mouseDown(btn); + fireEvent.pointerDown(btn); expect(api.setActive).toHaveBeenCalledTimes(0); fireEvent.click(element); diff --git a/packages/dockview/src/dockview/defaultTab.tsx b/packages/dockview/src/dockview/defaultTab.tsx index 56c3a6793..f1586fa83 100644 --- a/packages/dockview/src/dockview/defaultTab.tsx +++ b/packages/dockview/src/dockview/defaultTab.tsx @@ -49,7 +49,7 @@ export const DockviewDefaultTab: React.FunctionComponent< [api, closeActionOverride] ); - const onMouseDown = React.useCallback((e: React.MouseEvent) => { + const onPointerDown = React.useCallback((e: React.MouseEvent) => { e.preventDefault(); }, []); @@ -79,7 +79,7 @@ export const DockviewDefaultTab: React.FunctionComponent< {!hideClose && (

diff --git a/packages/dockview/src/dockview/reactWatermarkPart.ts b/packages/dockview/src/dockview/reactWatermarkPart.ts index f9b18a1c7..731ecd646 100644 --- a/packages/dockview/src/dockview/reactWatermarkPart.ts +++ b/packages/dockview/src/dockview/reactWatermarkPart.ts @@ -57,13 +57,6 @@ export class ReactWatermarkPart implements IWatermarkRenderer { // noop - retrieval from api } - updateParentGroup( - _group: DockviewGroupPanel, - _isPanelVisible: boolean - ): void { - // noop - } - dispose(): void { this.part?.dispose(); } diff --git a/packages/docs/blog/2024-09-05-dockview-1.17.0.md b/packages/docs/blog/2024-09-05-dockview-1.17.0.md new file mode 100644 index 000000000..9f8aa1902 --- /dev/null +++ b/packages/docs/blog/2024-09-05-dockview-1.17.0.md @@ -0,0 +1,23 @@ +--- +slug: dockview-1.17.0-release +title: Dockview 1.17.0 +tags: [release] +--- + +# Release Notes + +Please reference docs @ [dockview.dev](https://dockview.dev). + +## 🚀 Features + +- Touch Support [#698](https://github.com/mathuo/dockview/pull/698) +- Initial and bounding panel sizing [#690](https://github.com/mathuo/dockview/pull/690) +- Improve group resize logic [#693](https://github.com/mathuo/dockview/pull/693) + +## 🛠 Miscs + +- Bug: Theme Typo [#694](https://github.com/mathuo/dockview/pull/694) +- Docs [#703](https://github.com/mathuo/dockview/pull/703) + +## 🔥 Breaking changes + diff --git a/packages/docs/blog/2024-09-05-dockview-1.17.1.md b/packages/docs/blog/2024-09-05-dockview-1.17.1.md new file mode 100644 index 000000000..1472e5136 --- /dev/null +++ b/packages/docs/blog/2024-09-05-dockview-1.17.1.md @@ -0,0 +1,23 @@ +--- +slug: dockview-1.17.1-release +title: Dockview 1.17.1 +tags: [release] +--- + +# Release Notes + +Please reference docs @ [dockview.dev](https://dockview.dev). + +## 🚀 Features + +- Touch Support [#698](https://github.com/mathuo/dockview/pull/698) [#709](https://github.com/mathuo/dockview/pull/709) +- Initial and bounding panel sizing [#690](https://github.com/mathuo/dockview/pull/690) +- Improve group resize logic [#693](https://github.com/mathuo/dockview/pull/693) + +## 🛠 Miscs + +- Bug: Theme Typo [#694](https://github.com/mathuo/dockview/pull/694) +- Docs [#703](https://github.com/mathuo/dockview/pull/703) + +## 🔥 Breaking changes + diff --git a/packages/docs/blog/2024-10-12-dockview-1.17.2.md b/packages/docs/blog/2024-10-12-dockview-1.17.2.md new file mode 100644 index 000000000..e415da3c3 --- /dev/null +++ b/packages/docs/blog/2024-10-12-dockview-1.17.2.md @@ -0,0 +1,21 @@ +--- +slug: dockview-1.17.2-release +title: Dockview 1.17.2 +tags: [release] +--- + +# Release Notes + +Please reference docs @ [dockview.dev](https://dockview.dev). + +## 🚀 Features + +- Customization of z-index [#730](https://github.com/mathuo/dockview/pull/730) [#724](https://github.com/mathuo/dockview/pull/724) + +## 🛠 Miscs + +- Adjust README.md file [#715](https://github.com/mathuo/dockview/pull/715) +- Docs typo [#714](https://github.com/mathuo/dockview/pull/714) + +## 🔥 Breaking changes + diff --git a/packages/docs/docs/advanced/events.mdx b/packages/docs/docs/advanced/events.mdx deleted file mode 100644 index e4edada93..000000000 --- a/packages/docs/docs/advanced/events.mdx +++ /dev/null @@ -1,12 +0,0 @@ -import { MultiFrameworkContainer } from '@site/src/components/ui/container'; -import EventsDockview from '@site/sandboxes/events-dockview/src/app'; - -# Events - -A simple example showing events fired by `dockviewz that can be interacted with. - - diff --git a/packages/docs/docs/core/dnd/external.mdx b/packages/docs/docs/core/dnd/external.mdx index 7e80d2dc7..7264446a1 100644 --- a/packages/docs/docs/core/dnd/external.mdx +++ b/packages/docs/docs/core/dnd/external.mdx @@ -9,25 +9,9 @@ import { DocRef } from '@site/src/components/ui/reference/docRef'; import LiveExample from '@site/src/components/ui/exampleFrame'; - - - - - - - - - - - - - - ## Intercepting Drag Events You can intercept drag events to attach your own metadata using the `onWillDragPanel` and `onWillDragGroup` api methods. diff --git a/packages/docs/docs/core/overview.mdx b/packages/docs/docs/core/overview.mdx index abedc5738..f3cf26628 100644 --- a/packages/docs/docs/core/overview.mdx +++ b/packages/docs/docs/core/overview.mdx @@ -8,6 +8,15 @@ This section provided a core overview. The component takes a collection of [Options](/docs/api/dockview/options) as inputs and once you have created a dock you can store a reference to the [API](/docs/api/dockview/overview) that is created. + + +```tsx +const element: HTMLElement +const options: DockviewComponentOptions +const api: DockviewApi = createDockview(element, options); +``` + + ```tsx function onReady(event: DockviewReadyEvent) { diff --git a/packages/docs/docs/core/panels/add.mdx b/packages/docs/docs/core/panels/add.mdx index c1c330031..b964cdc05 100644 --- a/packages/docs/docs/core/panels/add.mdx +++ b/packages/docs/docs/core/panels/add.mdx @@ -176,3 +176,35 @@ api.addPanel({ } }); ``` + +### Minimum and Maximum + +You can define both minimum and maxmium widths and heights, these are persisted with layouts. + +:::info +Since panels exist within groups there are occasions where these boundaries will be ignored to prevent overflow and clipping issues within the dock. +::: + +```ts +api.addPanel({ + id: 'panel_1', + component: 'default', + minimumWidth: 100, + maximumWidth: 100, + minimumHeight: 200, + maximumHeight: 2000 +}); +``` + +### Initial Size + +You can define an `initialWidth` and `initialHeight`. The dock will may a best attempt to obey these inputs but it may not always be possible due to the constraints of the grid. + +```ts +api.addPanel({ + id: 'panel_1', + component: 'default', + initialWidth: 100, + initialHeight: 100 +}); +``` diff --git a/packages/docs/docs/core/panels/register.mdx b/packages/docs/docs/core/panels/register.mdx index 0b3b834be..5f90c7bb5 100644 --- a/packages/docs/docs/core/panels/register.mdx +++ b/packages/docs/docs/core/panels/register.mdx @@ -20,7 +20,7 @@ You can register panels through the dock [option](/docs/api/dockview/options) ` - + @@ -44,6 +44,37 @@ return + +```tsx +class Panel implements IContentRenderer { + private readonly _element: HTMLElement; + + get element(): HTMLElement { + return this._element; + } + + constructor() { + this._element = document.createElement('div'); + } + + init(parameters: GroupPanelPartInitParameters): void { + // + } +} + + +const api = createDockview(parentElement, { + createComponent: (options) => { + switch (options.name) { + case 'component_1': + return new Panel(); + } + }, +}); +``` + + + ```tsx const App = { diff --git a/packages/docs/docs/core/panels/tabs.mdx b/packages/docs/docs/core/panels/tabs.mdx index 37f5d4e76..4ea2b2ae6 100644 --- a/packages/docs/docs/core/panels/tabs.mdx +++ b/packages/docs/docs/core/panels/tabs.mdx @@ -109,7 +109,7 @@ not implemented ## Accessing Custom Panel Parameters -You can provide a generic type that matches the structure of the epxected custom panels parameters +You can provide a generic type that matches the structure of the expected custom panels parameters to provide type-hints for the panel parameters which can be accessed via the `params` option. diff --git a/packages/docs/docs/core/watermark.mdx b/packages/docs/docs/core/watermark.mdx index 7c8549ff3..e2416a6d8 100644 --- a/packages/docs/docs/core/watermark.mdx +++ b/packages/docs/docs/core/watermark.mdx @@ -25,7 +25,7 @@ The following properties can be set to configure the behaviours of floating grou diff --git a/packages/docs/docs/overview/getStarted/installation.mdx b/packages/docs/docs/overview/getStarted/installation.mdx index 4503011d6..2f0e97935 100644 --- a/packages/docs/docs/overview/getStarted/installation.mdx +++ b/packages/docs/docs/overview/getStarted/installation.mdx @@ -18,7 +18,7 @@ npm install dockview-core Firstly, install the `dockview` library: ```sh -npm install dockview +npm install dockview-react ``` diff --git a/packages/docs/docs/overview/getStarted/theme.mdx b/packages/docs/docs/overview/getStarted/theme.mdx index 06e9189c3..2e89eefe6 100644 --- a/packages/docs/docs/overview/getStarted/theme.mdx +++ b/packages/docs/docs/overview/getStarted/theme.mdx @@ -19,10 +19,15 @@ Firstly, you should import `dockview.css`: ```css -@import './node_modules/dockview/dist/styles/dockview.css'; +@import './node_modules/dockview-react/dist/styles/dockview.css'; ``` + +```css +@import './node_modules/dockview-vue/dist/styles/dockview.css'; +``` + ## Provided themes diff --git a/packages/docs/package.json b/packages/docs/package.json index 307716616..209c9c0a0 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -1,6 +1,6 @@ { "name": "dockview-docs", - "version": "1.16.1", + "version": "1.17.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": "^1.16.1", + "dockview": "^1.17.2", "prism-react-renderer": "^2.3.1", "react-dnd": "^16.0.1", "react-laag": "^2.0.5", diff --git a/packages/docs/sandboxes/iframe-dockview/src/app.tsx b/packages/docs/sandboxes/iframe-dockview/src/app.tsx index 5a6587484..5e2b1a882 100644 --- a/packages/docs/sandboxes/iframe-dockview/src/app.tsx +++ b/packages/docs/sandboxes/iframe-dockview/src/app.tsx @@ -1,13 +1,33 @@ -import { DockviewReact, DockviewReadyEvent } from 'dockview'; +import { + DockviewReact, + DockviewReadyEvent, + IDockviewPanelProps, +} from 'dockview'; import * as React from 'react'; const components = { - iframeComponent: () => { + iframeComponent: (props: IDockviewPanelProps) => { + const [enabled, setEnabled] = React.useState( + props.api.isActive + ); + + React.useEffect(() => { + const disposable = props.api.onDidActiveChange((event) => { + setEnabled(event.isActive); + console.log(event); + }); + + return () => { + disposable.dispose(); + }; + }, [props.api]); + return (