mirror of
https://github.com/mathuo/dockview
synced 2025-02-02 06:25:44 +00:00
Merge pull request #825 from mathuo/818-container-with-theme-class-is-created-twice-1
bug: duplicate container HTML Element
This commit is contained in:
commit
6678ae24e0
@ -105,6 +105,21 @@ class ClassUnderTest extends BaseGrid<TestPanel> {
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
@ -368,8 +368,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
|
||||
|
@ -155,14 +155,17 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
||||
this.gridview.locked = value;
|
||||
}
|
||||
|
||||
constructor(parentElement: HTMLElement, options: BaseGridOptions) {
|
||||
super(parentElement, options.disableAutoResizing);
|
||||
constructor(container: HTMLElement, options: BaseGridOptions) {
|
||||
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.gridview = new Gridview(
|
||||
!!options.proportionalLayout,
|
||||
options.styles,
|
||||
|
@ -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
|
||||
|
@ -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, {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -318,11 +318,7 @@ export const DockviewReact = React.forwardRef(
|
||||
}, [props.prefixHeaderActionsComponent]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={props.className}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
ref={domRef}
|
||||
>
|
||||
<div style={{ height: '100%', width: '100%' }} ref={domRef}>
|
||||
{portals}
|
||||
</div>
|
||||
);
|
||||
|
@ -126,11 +126,7 @@ export const GridviewReact = React.forwardRef(
|
||||
}, [props.components]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={props.className}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
ref={domRef}
|
||||
>
|
||||
<div style={{ height: '100%', width: '100%' }} ref={domRef}>
|
||||
{portals}
|
||||
</div>
|
||||
);
|
||||
|
@ -176,11 +176,7 @@ export const PaneviewReact = React.forwardRef(
|
||||
}, [props.onDidDrop]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={props.className}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
ref={domRef}
|
||||
>
|
||||
<div style={{ height: '100%', width: '100%' }} ref={domRef}>
|
||||
{portals}
|
||||
</div>
|
||||
);
|
||||
|
@ -126,11 +126,7 @@ export const SplitviewReact = React.forwardRef(
|
||||
}, [props.components]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={props.className}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
ref={domRef}
|
||||
>
|
||||
<div style={{ height: '100%', width: '100%' }} ref={domRef}>
|
||||
{portals}
|
||||
</div>
|
||||
);
|
||||
|
@ -176,80 +176,92 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
setPending([]);
|
||||
}, [pending]);
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
setApi(event.api);
|
||||
setPanels([]);
|
||||
setGroups([]);
|
||||
setActivePanel(undefined);
|
||||
setActiveGroup(undefined);
|
||||
addLogLine(`Dockview Is Ready`);
|
||||
|
||||
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<boolean>(false);
|
||||
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
@ -3,5 +3,9 @@ import { RecoilRoot } from 'recoil';
|
||||
|
||||
// Default implementation, that you can customize
|
||||
export default function Root({ children }) {
|
||||
return <RecoilRoot>{children}</RecoilRoot>;
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user