mirror of
https://github.com/mathuo/dockview
synced 2025-01-23 09:55:58 +00:00
bug: fix setTitle issues
This commit is contained in:
parent
ce381f8ce9
commit
cd6604d28c
@ -0,0 +1,63 @@
|
||||
import { DockviewApi } from '../../../../api/component.api';
|
||||
import { DockviewPanelApi, TitleEvent } from '../../../../api/dockviewPanelApi';
|
||||
import { DefaultTab } from '../../../../dockview/components/tab/defaultTab';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { Emitter } from '../../../../events';
|
||||
import { fireEvent } from '@testing-library/dom';
|
||||
|
||||
describe('defaultTab', () => {
|
||||
test('that title updates', () => {
|
||||
const cut = new DefaultTab();
|
||||
|
||||
let el = cut.element.querySelector('.dv-default-tab-content');
|
||||
expect(el).toBeTruthy();
|
||||
expect(el!.textContent).toBe('');
|
||||
|
||||
const onDidTitleChange = new Emitter<TitleEvent>();
|
||||
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: onDidTitleChange.event,
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
|
||||
cut.init({
|
||||
api,
|
||||
containerApi,
|
||||
params: {},
|
||||
title: 'title_abc',
|
||||
});
|
||||
|
||||
el = cut.element.querySelector('.dv-default-tab-content');
|
||||
expect(el).toBeTruthy();
|
||||
expect(el!.textContent).toBe('title_abc');
|
||||
|
||||
onDidTitleChange.fire({ title: 'title_def' });
|
||||
|
||||
expect(el!.textContent).toBe('title_def');
|
||||
});
|
||||
|
||||
test('that click closes tab', () => {
|
||||
const cut = new DefaultTab();
|
||||
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn(),
|
||||
close: jest.fn(),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
|
||||
cut.init({
|
||||
api,
|
||||
containerApi,
|
||||
params: {},
|
||||
title: 'title_abc',
|
||||
});
|
||||
|
||||
let el = cut.element.querySelector('.dv-default-tab-action');
|
||||
|
||||
fireEvent.mouseDown(el!);
|
||||
expect(api.close).toHaveBeenCalledTimes(0);
|
||||
|
||||
fireEvent.click(el!);
|
||||
expect(api.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
@ -1,16 +1,13 @@
|
||||
import { CompositeDisposable } from '../../../lifecycle';
|
||||
import { ITabRenderer, GroupPanelPartInitParameters } from '../../types';
|
||||
import { addDisposableListener } from '../../../events';
|
||||
import { PanelUpdateEvent } from '../../../panel/types';
|
||||
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
|
||||
import { createCloseButton } from '../../../svg';
|
||||
|
||||
export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
||||
private _element: HTMLElement;
|
||||
private _content: HTMLElement;
|
||||
private action: HTMLElement;
|
||||
//
|
||||
private params: GroupPanelPartInitParameters = {} as any;
|
||||
private _title: string | undefined;
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this._element;
|
||||
@ -21,7 +18,7 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
||||
|
||||
this._element = document.createElement('div');
|
||||
this._element.className = 'dv-default-tab';
|
||||
//
|
||||
|
||||
this._content = document.createElement('div');
|
||||
this._content.className = 'dv-default-tab-content';
|
||||
|
||||
@ -29,10 +26,9 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
||||
this.action.className = 'dv-default-tab-action';
|
||||
this.action.appendChild(createCloseButton());
|
||||
|
||||
//
|
||||
this._element.appendChild(this._content);
|
||||
this._element.appendChild(this.action);
|
||||
//
|
||||
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.action, 'mousedown', (ev) => {
|
||||
ev.preventDefault();
|
||||
@ -42,40 +38,33 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
||||
this.render();
|
||||
}
|
||||
|
||||
public update(event: PanelUpdateEvent): void {
|
||||
this.params = { ...this.params, ...event.params };
|
||||
init(params: GroupPanelPartInitParameters): void {
|
||||
this._title = params.title;
|
||||
|
||||
this.addDisposables(
|
||||
params.api.onDidTitleChange((event) => {
|
||||
this._title = event.title;
|
||||
this.render();
|
||||
}),
|
||||
addDisposableListener(this.action, 'mousedown', (ev) => {
|
||||
ev.preventDefault();
|
||||
}),
|
||||
addDisposableListener(this.action, 'click', (ev) => {
|
||||
if (ev.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
params.api.close();
|
||||
})
|
||||
);
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
//noop
|
||||
}
|
||||
|
||||
public init(params: GroupPanelPartInitParameters): void {
|
||||
this.params = params;
|
||||
this._content.textContent = params.title;
|
||||
|
||||
addDisposableListener(this.action, 'click', (ev) => {
|
||||
ev.preventDefault(); //
|
||||
this.params.api.close();
|
||||
});
|
||||
}
|
||||
|
||||
onGroupChange(_group: DockviewGroupPanel): void {
|
||||
this.render();
|
||||
}
|
||||
|
||||
onPanelVisibleChange(_isPanelVisible: boolean): void {
|
||||
this.render();
|
||||
}
|
||||
|
||||
public layout(_width: number, _height: number): void {
|
||||
// noop
|
||||
}
|
||||
|
||||
private render(): void {
|
||||
if (this._content.textContent !== this.params.title) {
|
||||
this._content.textContent = this.params.title;
|
||||
if (this._content.textContent !== this._title) {
|
||||
this._content.textContent = this._title ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,16 @@ import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { DockviewDefaultTab } from '../../dockview/defaultTab';
|
||||
import React from 'react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { DockviewApi, DockviewPanelApi } from 'dockview-core';
|
||||
import { DockviewApi, DockviewPanelApi, TitleEvent } from 'dockview-core';
|
||||
import { Emitter } from 'dockview-core/dist/cjs/events';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { Disposable } from 'dockview-core/dist/cjs/lifecycle';
|
||||
|
||||
describe('defaultTab', () => {
|
||||
test('has close button by default', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({});
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
|
||||
@ -25,6 +30,7 @@ describe('defaultTab', () => {
|
||||
test('that title is displayed', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
title: 'test_title',
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -43,8 +49,43 @@ describe('defaultTab', () => {
|
||||
).toBe('test_title');
|
||||
});
|
||||
|
||||
test('that title is updated', async () => {
|
||||
const onDidTitleChange = new Emitter<TitleEvent>();
|
||||
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
title: 'test_title',
|
||||
onDidTitleChange: onDidTitleChange.event,
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
|
||||
render(
|
||||
<DockviewDefaultTab
|
||||
api={api}
|
||||
containerApi={containerApi}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
|
||||
let element = await screen.getByTestId('dockview-dv-default-tab');
|
||||
expect(
|
||||
element.querySelector('.dv-default-tab-content')?.textContent
|
||||
).toBe('test_title');
|
||||
|
||||
act(() => {
|
||||
onDidTitleChange.fire({ title: 'test_title_2' });
|
||||
});
|
||||
|
||||
element = await screen.getByTestId('dockview-dv-default-tab');
|
||||
expect(
|
||||
element.querySelector('.dv-default-tab-content')?.textContent
|
||||
).toBe('test_title_2');
|
||||
});
|
||||
|
||||
test('has no close button when hideClose=true', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({});
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
|
||||
@ -64,6 +105,7 @@ describe('defaultTab', () => {
|
||||
test('that settings closeActionOverride skips api.close()', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
close: jest.fn(),
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -85,13 +127,14 @@ describe('defaultTab', () => {
|
||||
) as HTMLElement;
|
||||
fireEvent.click(btn);
|
||||
|
||||
expect(closeActionOverride).toBeCalledTimes(1);
|
||||
expect(api.close).toBeCalledTimes(0);
|
||||
expect(closeActionOverride).toHaveBeenCalledTimes(1);
|
||||
expect(api.close).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test('that clicking close calls api.close()', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
close: jest.fn(),
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -110,11 +153,13 @@ describe('defaultTab', () => {
|
||||
) as HTMLElement;
|
||||
fireEvent.click(btn);
|
||||
|
||||
expect(api.close).toBeCalledTimes(1);
|
||||
expect(api.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('has close button when hideClose=false', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({});
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
|
||||
@ -134,6 +179,7 @@ describe('defaultTab', () => {
|
||||
test('that mouseDown on close button prevents panel becoming active', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
setActive: jest.fn(),
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -152,9 +198,9 @@ describe('defaultTab', () => {
|
||||
) as HTMLElement;
|
||||
|
||||
fireEvent.mouseDown(btn);
|
||||
expect(api.setActive).toBeCalledTimes(0);
|
||||
expect(api.setActive).toHaveBeenCalledTimes(0);
|
||||
|
||||
fireEvent.click(element);
|
||||
expect(api.setActive).toBeCalledTimes(1);
|
||||
expect(api.setActive).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,22 @@
|
||||
import React from 'react';
|
||||
import { CloseButton } from '../svg';
|
||||
import { IDockviewPanelHeaderProps } from 'dockview-core';
|
||||
import { DockviewPanelApi, IDockviewPanelHeaderProps } from 'dockview-core';
|
||||
|
||||
function useTitle(api: DockviewPanelApi): string | undefined {
|
||||
const [title, setTitle] = React.useState<string | undefined>(api.title);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = api.onDidTitleChange((event) => {
|
||||
setTitle(event.title);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
export type IDockviewDefaultTabProps = IDockviewPanelHeaderProps &
|
||||
React.DOMAttributes<HTMLDivElement> & {
|
||||
@ -18,6 +34,8 @@ export const DockviewDefaultTab: React.FunctionComponent<
|
||||
closeActionOverride,
|
||||
...rest
|
||||
}) => {
|
||||
const title = useTitle(api);
|
||||
|
||||
const onClose = React.useCallback(
|
||||
(event: React.MouseEvent<HTMLSpanElement>) => {
|
||||
event.preventDefault();
|
||||
@ -57,7 +75,7 @@ export const DockviewDefaultTab: React.FunctionComponent<
|
||||
onClick={onClick}
|
||||
className="dv-default-tab"
|
||||
>
|
||||
<span className="dv-default-tab-content">{api.title}</span>
|
||||
<span className="dv-default-tab-content">{title}</span>
|
||||
{!hideClose && (
|
||||
<div
|
||||
className="dv-default-tab-action"
|
||||
|
Loading…
Reference in New Issue
Block a user