Merge branch 'master' of https://github.com/mathuo/dockview into 263-left-header-actions

This commit is contained in:
mathuo 2023-06-11 11:34:16 +01:00
commit 2ca4c6fd65
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
42 changed files with 726 additions and 455 deletions

View File

@ -3,7 +3,7 @@
"packages/*" "packages/*"
], ],
"useWorkspaces": true, "useWorkspaces": true,
"version": "1.7.3", "version": "1.7.4",
"npmClient": "yarn", "npmClient": "yarn",
"command": { "command": {
"publish": { "publish": {

View File

@ -35,6 +35,7 @@
"homepage": "https://github.com/mathuo/dockview#readme", "homepage": "https://github.com/mathuo/dockview#readme",
"devDependencies": { "devDependencies": {
"@testing-library/dom": "^8.20.0", "@testing-library/dom": "^8.20.0",
"@testing-library/jest-dom": "^5.16.5",
"@types/jest": "^29.4.0", "@types/jest": "^29.4.0",
"@typescript-eslint/eslint-plugin": "^5.52.0", "@typescript-eslint/eslint-plugin": "^5.52.0",
"@typescript-eslint/parser": "^5.52.0", "@typescript-eslint/parser": "^5.52.0",
@ -58,8 +59,8 @@
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"ts-jest": "^29.0.5", "ts-jest": "^29.0.5",
"ts-loader": "^9.4.2", "ts-loader": "^9.4.2",
"tslib": "^2.5.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.5.0",
"typedoc": "^0.24.7", "typedoc": "^0.24.7",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"webpack": "^5.75.0", "webpack": "^5.75.0",
@ -67,4 +68,4 @@
"webpack-dev-server": "^4.11.1" "webpack-dev-server": "^4.11.1"
}, },
"dependencies": {} "dependencies": {}
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-core", "name": "dockview-core",
"version": "1.7.3", "version": "1.7.4",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support", "description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support",
"main": "./dist/cjs/index.js", "main": "./dist/cjs/index.js",
"types": "./dist/cjs/index.d.ts", "types": "./dist/cjs/index.d.ts",

View File

@ -2,10 +2,10 @@ import { IDockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import { import {
GroupPanelPartInitParameters, GroupPanelPartInitParameters,
GroupPanelUpdateEvent,
IContentRenderer, IContentRenderer,
ITabRenderer, ITabRenderer,
} from '../../dockview/types'; } from '../../dockview/types';
import { PanelUpdateEvent } from '../../panel/types';
export class DockviewPanelModelMock implements IDockviewPanelModel { export class DockviewPanelModelMock implements IDockviewPanelModel {
constructor( constructor(
@ -21,7 +21,14 @@ export class DockviewPanelModelMock implements IDockviewPanelModel {
// //
} }
update(event: GroupPanelUpdateEvent): void { updateParentGroup(
group: DockviewGroupPanel,
isPanelVisible: boolean
): void {
//
}
update(event: PanelUpdateEvent): void {
// //
} }

View File

@ -1,4 +1,5 @@
import { PanelApiImpl } from '../../api/panelApi'; import { PanelApiImpl } from '../../api/panelApi';
import { IPanel } from '../../panel/types';
describe('api', () => { describe('api', () => {
let api: PanelApiImpl; let api: PanelApiImpl;
@ -7,7 +8,23 @@ describe('api', () => {
api = new PanelApiImpl('dummy_id'); api = new PanelApiImpl('dummy_id');
}); });
it('should update isFcoused getter', () => { test('updateParameters', () => {
const panel = {
update: jest.fn(),
} as Partial<IPanel>;
api.initialize(panel as IPanel);
expect(panel.update).toHaveBeenCalledTimes(0);
api.updateParameters({ keyA: 'valueA' });
expect(panel.update).toHaveBeenCalledTimes(1);
expect(panel.update).toHaveBeenCalledWith({
params: { keyA: 'valueA' },
});
});
test('should update isFcoused getter', () => {
expect(api.isFocused).toBeFalsy(); expect(api.isFocused).toBeFalsy();
api._onDidChangeFocus.fire({ isFocused: true }); api._onDidChangeFocus.fire({ isFocused: true });
@ -17,7 +34,7 @@ describe('api', () => {
expect(api.isFocused).toBeFalsy(); expect(api.isFocused).toBeFalsy();
}); });
it('should update isActive getter', () => { test('should update isActive getter', () => {
expect(api.isFocused).toBeFalsy(); expect(api.isFocused).toBeFalsy();
api._onDidActiveChange.fire({ isActive: true }); api._onDidActiveChange.fire({ isActive: true });
@ -27,7 +44,7 @@ describe('api', () => {
expect(api.isActive).toBeFalsy(); expect(api.isActive).toBeFalsy();
}); });
it('should update isActive getter', () => { test('should update isActive getter', () => {
expect(api.isVisible).toBeTruthy(); expect(api.isVisible).toBeTruthy();
api._onDidVisibilityChange.fire({ isVisible: false }); api._onDidVisibilityChange.fire({ isVisible: false });
@ -37,7 +54,7 @@ describe('api', () => {
expect(api.isVisible).toBeTruthy(); expect(api.isVisible).toBeTruthy();
}); });
it('should update width and height getter', () => { test('should update width and height getter', () => {
expect(api.height).toBe(0); expect(api.height).toBe(0);
expect(api.width).toBe(0); expect(api.width).toBe(0);

View File

@ -1,4 +1,4 @@
import { DockviewPanelApiImpl, TitleEvent } from '../../api/dockviewPanelApi'; import { DockviewPanelApiImpl } from '../../api/dockviewPanelApi';
import { DockviewComponent } from '../../dockview/dockviewComponent'; import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel'; import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
@ -8,6 +8,7 @@ describe('groupPanelApi', () => {
const panelMock = jest.fn<DockviewPanel, []>(() => { const panelMock = jest.fn<DockviewPanel, []>(() => {
return { return {
update: jest.fn(), update: jest.fn(),
setTitle: jest.fn(),
} as any; } as any;
}); });
const groupMock = jest.fn<DockviewGroupPanel, []>(() => { const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -20,11 +21,38 @@ describe('groupPanelApi', () => {
const cut = new DockviewPanelApiImpl(panel, group); const cut = new DockviewPanelApiImpl(panel, group);
cut.setTitle('test_title'); cut.setTitle('test_title');
expect(panel.setTitle).toBeCalledTimes(1);
expect(panel.setTitle).toBeCalledWith('test_title');
});
expect(panel.update).toBeCalledTimes(1); test('updateParameters', () => {
expect(panel.update).toBeCalledWith({ const groupPanel: Partial<IDockviewPanel> = {
params: { title: 'test_title' }, id: 'test_id',
update: jest.fn(),
};
const accessor: Partial<DockviewComponent> = {
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
};
const groupViewPanel = new DockviewGroupPanel(
<DockviewComponent>accessor,
'',
{}
);
const cut = new DockviewPanelApiImpl(
<IDockviewPanel>groupPanel,
<DockviewGroupPanel>groupViewPanel
);
cut.updateParameters({ keyA: 'valueA' });
expect(groupPanel.update).toHaveBeenCalledWith({
params: { keyA: 'valueA' },
}); });
expect(groupPanel.update).toHaveBeenCalledTimes(1);
}); });
test('onDidGroupChange', () => { test('onDidGroupChange', () => {

View File

@ -1,6 +1,5 @@
import { DockviewComponent } from '../../dockview/dockviewComponent'; import { DockviewComponent } from '../../dockview/dockviewComponent';
import { import {
GroupPanelUpdateEvent,
GroupviewPanelState, GroupviewPanelState,
IGroupPanelInitParameters, IGroupPanelInitParameters,
GroupPanelPartInitParameters, GroupPanelPartInitParameters,
@ -39,7 +38,7 @@ class TestModel implements IDockviewPanelModel {
this.tab = new TestContentPart(id); this.tab = new TestContentPart(id);
} }
update(event: GroupPanelUpdateEvent): void { update(event: PanelUpdateEvent): void {
// //
} }
@ -203,6 +202,10 @@ export class TestPanel implements IDockviewPanel {
//noop //noop
} }
setTitle(title: string): void {
//
}
update(event: PanelUpdateEvent) { update(event: PanelUpdateEvent) {
//noop //noop
} }

View File

@ -43,7 +43,7 @@ describe('dockviewPanel', () => {
expect(latestTitle).toBe('new title'); expect(latestTitle).toBe('new title');
expect(cut.title).toBe('new title'); expect(cut.title).toBe('new title');
cut.update({ params: { title: 'another title' } }); cut.setTitle('another title');
expect(latestTitle).toBe('another title'); expect(latestTitle).toBe('another title');
expect(cut.title).toBe('another title'); expect(cut.title).toBe('another title');
@ -81,6 +81,9 @@ describe('dockviewPanel', () => {
cut.setTitle('newTitle'); cut.setTitle('newTitle');
expect(cut.title).toBe('newTitle'); expect(cut.title).toBe('newTitle');
cut.api.setTitle('new title 2');
expect(cut.title).toBe('new title 2');
}); });
test('dispose cleanup', () => { test('dispose cleanup', () => {
@ -142,7 +145,7 @@ describe('dockviewPanel', () => {
expect(cut.params).toEqual(undefined); expect(cut.params).toEqual(undefined);
cut.update({ params: { params: { variableA: 'A', variableB: 'B' } } }); cut.update({ params: { variableA: 'A', variableB: 'B' } });
expect(cut.params).toEqual({ variableA: 'A', variableB: 'B' }); expect(cut.params).toEqual({ variableA: 'A', variableB: 'B' });
}); });
@ -181,4 +184,67 @@ describe('dockviewPanel', () => {
expect(group.api.setSize).toBeCalledWith({ height: 123, width: 456 }); expect(group.api.setSize).toBeCalledWith({ height: 123, width: 456 });
expect(group.api.setSize).toBeCalledTimes(1); expect(group.api.setSize).toBeCalledTimes(1);
}); });
test('updateParameter', () => {
const dockviewApiMock = jest.fn<DockviewApi, []>(() => {
return {} as any;
});
const accessorMock = jest.fn<DockviewComponent, []>(() => {
return {} as any;
});
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
return {} as any;
});
const panelModelMock = jest.fn<Partial<IDockviewPanelModel>, []>(() => {
return {
update: jest.fn(),
init: jest.fn(),
dispose: jest.fn(),
};
});
const api = new dockviewApiMock();
const accessor = new accessorMock();
const group = new groupMock();
const model = <IDockviewPanelModel>new panelModelMock();
const cut = new DockviewPanel('fake-id', accessor, api, group, model);
cut.init({ params: { a: '1', b: '2' }, title: 'A title' });
expect(cut.params).toEqual({ a: '1', b: '2' });
// update 'a' and add 'c'
cut.update({ params: { a: '-1', c: '3' } });
expect(cut.params).toEqual({ a: '-1', b: '2', c: '3' });
cut.update({ params: { d: '4', e: '5', f: '6' } });
expect(cut.params).toEqual({
a: '-1',
b: '2',
c: '3',
d: '4',
e: '5',
f: '6',
});
cut.update({
params: {
d: '',
e: null,
f: undefined,
g: '',
h: null,
i: undefined,
},
});
expect(cut.params).toEqual({
a: '-1',
b: '2',
c: '3',
d: '',
e: null,
g: '',
h: null,
});
});
}); });

View File

@ -2,6 +2,10 @@ import { Emitter, Event } from '../events';
describe('events', () => { describe('events', () => {
describe('emitter', () => { describe('emitter', () => {
it('debug mode is off', () => {
expect(Emitter.ENABLE_TRACKING).toBeFalsy();
});
it('should emit values', () => { it('should emit values', () => {
const emitter = new Emitter<number>(); const emitter = new Emitter<number>();
let value: number | undefined = undefined; let value: number | undefined = undefined;

View File

@ -89,7 +89,7 @@ export class DockviewPanelApiImpl
} }
public setTitle(title: string): void { public setTitle(title: string): void {
this.panel.update({ params: { title } }); this.panel.setTitle(title);
} }
public close(): void { public close(): void {

View File

@ -155,9 +155,7 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
this.panelUpdatesDisposable.value = this._onUpdateParameters.event( this.panelUpdatesDisposable.value = this._onUpdateParameters.event(
(parameters) => { (parameters) => {
panel.update({ panel.update({
params: { params: parameters,
params: parameters,
},
}); });
} }
); );

View File

@ -3,14 +3,10 @@ import {
DockviewPanelApi, DockviewPanelApi,
DockviewPanelApiImpl, DockviewPanelApiImpl,
} from '../api/dockviewPanelApi'; } from '../api/dockviewPanelApi';
import { import { GroupviewPanelState, IGroupPanelInitParameters } from './types';
GroupPanelUpdateEvent,
GroupviewPanelState,
IGroupPanelInitParameters,
} from './types';
import { DockviewGroupPanel } from './dockviewGroupPanel'; import { DockviewGroupPanel } from './dockviewGroupPanel';
import { CompositeDisposable, IDisposable } from '../lifecycle'; import { CompositeDisposable, IDisposable } from '../lifecycle';
import { IPanel, Parameters } from '../panel/types'; import { IPanel, PanelUpdateEvent, Parameters } from '../panel/types';
import { IDockviewPanelModel } from './dockviewPanelModel'; import { IDockviewPanelModel } from './dockviewPanelModel';
import { IDockviewComponent } from './dockviewComponent'; import { IDockviewComponent } from './dockviewComponent';
@ -23,7 +19,8 @@ export interface IDockviewPanel extends IDisposable, IPanel {
updateParentGroup(group: DockviewGroupPanel, isGroupActive: boolean): void; updateParentGroup(group: DockviewGroupPanel, isGroupActive: boolean): void;
init(params: IGroupPanelInitParameters): void; init(params: IGroupPanelInitParameters): void;
toJSON(): GroupviewPanelState; toJSON(): GroupviewPanelState;
update(event: GroupPanelUpdateEvent): void; setTitle(title: string): void;
update(event: PanelUpdateEvent): void;
} }
export class DockviewPanel export class DockviewPanel
@ -117,19 +114,24 @@ export class DockviewPanel
} }
} }
public update(event: GroupPanelUpdateEvent): void { public update(event: PanelUpdateEvent): void {
const params = event.params as IGroupPanelInitParameters; // merge the new parameters with the existing parameters
this._params = { this._params = {
...(this._params || {}), ...(this._params || {}),
...event.params.params, ...event.params,
}; };
if (params.title !== this.title) { /**
this._title = params.title; * delete new keys that have a value of undefined,
this.api._onDidTitleChange.fire({ title: params.title }); * allow values of null
*/
for (const key of Object.keys(event.params)) {
if (event.params[key] === undefined) {
delete this._params[key];
}
} }
// update the view with the updated props
this.view.update({ this.view.update({
params: { params: {
params: this._params, params: this._params,

View File

@ -3,19 +3,19 @@ import {
GroupPanelPartInitParameters, GroupPanelPartInitParameters,
IContentRenderer, IContentRenderer,
ITabRenderer, ITabRenderer,
GroupPanelUpdateEvent,
} from './types'; } from './types';
import { DockviewGroupPanel } from './dockviewGroupPanel'; import { DockviewGroupPanel } from './dockviewGroupPanel';
import { IDisposable } from '../lifecycle'; import { IDisposable } from '../lifecycle';
import { createComponent } from '../panel/componentFactory'; import { createComponent } from '../panel/componentFactory';
import { IDockviewComponent } from './dockviewComponent'; import { IDockviewComponent } from './dockviewComponent';
import { PanelUpdateEvent } from '../panel/types';
export interface IDockviewPanelModel extends IDisposable { export interface IDockviewPanelModel extends IDisposable {
readonly contentComponent: string; readonly contentComponent: string;
readonly tabComponent?: string; readonly tabComponent?: string;
readonly content: IContentRenderer; readonly content: IContentRenderer;
readonly tab?: ITabRenderer; readonly tab?: ITabRenderer;
update(event: GroupPanelUpdateEvent): void; update(event: PanelUpdateEvent): void;
layout(width: number, height: number): void; layout(width: number, height: number): void;
init(params: GroupPanelPartInitParameters): void; init(params: GroupPanelPartInitParameters): void;
updateParentGroup(group: DockviewGroupPanel, isPanelVisible: boolean): void; updateParentGroup(group: DockviewGroupPanel, isPanelVisible: boolean): void;
@ -80,7 +80,7 @@ export class DockviewPanelModel implements IDockviewPanelModel {
this.content.layout?.(width, height); this.content.layout?.(width, height);
} }
update(event: GroupPanelUpdateEvent): void { update(event: PanelUpdateEvent): void {
this.content.update?.(event); this.content.update?.(event);
this.tab.update?.(event); this.tab.update?.(event);
} }

View File

@ -1,11 +1,6 @@
import { IDockviewComponent } from './dockviewComponent'; import { IDockviewComponent } from './dockviewComponent';
import { DockviewPanelApi } from '../api/dockviewPanelApi'; import { DockviewPanelApi } from '../api/dockviewPanelApi';
import { import { PanelInitParameters, IPanel } from '../panel/types';
PanelInitParameters,
IPanel,
PanelUpdateEvent,
Parameters,
} from '../panel/types';
import { DockviewApi } from '../api/component.api'; import { DockviewApi } from '../api/component.api';
import { Event } from '../events'; import { Event } from '../events';
import { Optional } from '../types'; import { Optional } from '../types';
@ -91,11 +86,6 @@ export interface IGroupPanelInitParameters
// //
} }
export type GroupPanelUpdateEvent = PanelUpdateEvent<{
params?: Parameters;
title?: string;
}>;
export interface GroupviewPanelState { export interface GroupviewPanelState {
id: string; id: string;
contentComponent?: string; contentComponent?: string;

View File

@ -102,10 +102,10 @@ export class Emitter<T> implements IDisposable {
if (index > -1) { if (index > -1) {
this._listeners.splice(index, 1); this._listeners.splice(index, 1);
} else if (Emitter.ENABLE_TRACKING) { } else if (Emitter.ENABLE_TRACKING) {
console.warn( // console.warn(
`Listener already disposed`, // `Listener already disposed`,
Stacktrace.create().print() // Stacktrace.create().print()
); // );
} }
}, },
}; };

View File

@ -104,6 +104,7 @@ export abstract class BasePanelView<T extends PanelApiImpl>
} }
update(event: PanelUpdateEvent): void { update(event: PanelUpdateEvent): void {
// merge the new parameters with the existing parameters
this._params = { this._params = {
...this._params, ...this._params,
params: { params: {
@ -111,6 +112,18 @@ export abstract class BasePanelView<T extends PanelApiImpl>
...event.params, ...event.params,
}, },
}; };
/**
* delete new keys that have a value of undefined,
* allow values of null
*/
for (const key of Object.keys(event.params)) {
if (event.params[key] === undefined) {
delete this._params.params[key];
}
}
// update the view with the updated props
this.part?.update({ params: this._params.params }); this.part?.update({ params: this._params.params });
} }

View File

@ -15,6 +15,7 @@ const config: JestConfigWithTsJest = {
setupFiles: [ setupFiles: [
'<rootDir>/packages/dockview/src/__tests__/__mocks__/resizeObserver.js', '<rootDir>/packages/dockview/src/__tests__/__mocks__/resizeObserver.js',
], ],
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
coveragePathIgnorePatterns: ['/node_modules/'], coveragePathIgnorePatterns: ['/node_modules/'],
modulePathIgnorePatterns: [ modulePathIgnorePatterns: [
'<rootDir>/packages/dockview/src/__tests__/__mocks__', '<rootDir>/packages/dockview/src/__tests__/__mocks__',

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview", "name": "dockview",
"version": "1.7.3", "version": "1.7.4",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support", "description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support",
"main": "./dist/cjs/index.js", "main": "./dist/cjs/index.js",
"types": "./dist/cjs/index.d.ts", "types": "./dist/cjs/index.d.ts",
@ -56,7 +56,7 @@
"author": "https://github.com/mathuo", "author": "https://github.com/mathuo",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"dockview-core": "^1.7.3" "dockview-core": "^1.7.4"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-node-resolve": "^15.0.1",

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render } from '@testing-library/react'; import { act, render, waitFor } from '@testing-library/react';
import { DockviewApi } from 'dockview-core'; import { DockviewApi, IDockviewPanel } from 'dockview-core';
import { import {
IDockviewPanelProps, IDockviewPanelProps,
DockviewReact, DockviewReact,
@ -15,7 +15,17 @@ describe('gridview react', () => {
beforeEach(() => { beforeEach(() => {
components = { components = {
default: (props: IDockviewPanelProps) => { default: (props: IDockviewPanelProps) => {
return <div>hello world</div>; return (
<div>
{Object.keys(props.params).map((key) => {
return (
<div
key={key}
>{`key=${key},value=${props.params[key]}`}</div>
);
})}
</div>
);
}, },
}; };
}); });
@ -51,4 +61,84 @@ describe('gridview react', () => {
expect(api!.width).toBe(650); expect(api!.width).toBe(650);
expect(api!.height).toBe(450); expect(api!.height).toBe(450);
}); });
test('that the component can update parameters', async () => {
let api: DockviewApi;
const onReady = (event: DockviewReadyEvent) => {
api = event.api;
};
const wrapper = render(
<DockviewReact components={components} onReady={onReady} />
);
let panel: IDockviewPanel;
act(() => {
panel = api!.addPanel({
id: 'panel_1',
component: 'default',
params: {
keyA: 'valueA',
keyB: 'valueB',
},
});
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: 'valueAA', keyC: 'valueC' });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=valueC/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyC: null });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: undefined });
});
await waitFor(() => {
expect(wrapper.queryByText(/key=keyA/i)).not.toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
});
}); });

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render } from '@testing-library/react'; import { act, render, waitFor } from '@testing-library/react';
import { GridviewApi, Orientation } from 'dockview-core'; import { GridviewApi, IGridviewPanel, Orientation } from 'dockview-core';
import { import {
IGridviewPanelProps, IGridviewPanelProps,
GridviewReact, GridviewReact,
@ -15,7 +15,17 @@ describe('gridview react', () => {
beforeEach(() => { beforeEach(() => {
components = { components = {
default: (props: IGridviewPanelProps) => { default: (props: IGridviewPanelProps) => {
return <div>hello world</div>; return (
<div>
{Object.keys(props.params).map((key) => {
return (
<div
key={key}
>{`key=${key},value=${props.params[key]}`}</div>
);
})}
</div>
);
}, },
}; };
}); });
@ -62,4 +72,88 @@ describe('gridview react', () => {
expect(api!.width).toBe(650); expect(api!.width).toBe(650);
expect(api!.height).toBe(450); expect(api!.height).toBe(450);
}); });
test('that the component can update parameters', async () => {
let api: GridviewApi;
const onReady = (event: GridviewReadyEvent) => {
api = event.api;
};
const wrapper = render(
<GridviewReact
orientation={Orientation.VERTICAL}
components={components}
onReady={onReady}
/>
);
let panel: IGridviewPanel;
act(() => {
panel = api!.addPanel({
id: 'panel_1',
component: 'default',
params: {
keyA: 'valueA',
keyB: 'valueB',
},
});
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: 'valueAA', keyC: 'valueC' });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=valueC/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyC: null });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: undefined });
});
await waitFor(() => {
expect(wrapper.queryByText(/key=keyA/i)).not.toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
});
}); });

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render } from '@testing-library/react'; import { act, render, waitFor } from '@testing-library/react';
import { PaneviewApi } from 'dockview-core'; import { IPaneviewPanel, PaneviewApi } from 'dockview-core';
import { import {
IPaneviewPanelProps, IPaneviewPanelProps,
PaneviewReact, PaneviewReact,
@ -15,7 +15,17 @@ describe('gridview react', () => {
beforeEach(() => { beforeEach(() => {
components = { components = {
default: (props: IPaneviewPanelProps) => { default: (props: IPaneviewPanelProps) => {
return <div>hello world</div>; return (
<div>
{Object.keys(props.params).map((key) => {
return (
<div
key={key}
>{`key=${key},value=${props.params[key]}`}</div>
);
})}
</div>
);
}, },
}; };
}); });
@ -49,4 +59,85 @@ describe('gridview react', () => {
expect(api!.width).toBe(650); expect(api!.width).toBe(650);
expect(api!.height).toBe(450); expect(api!.height).toBe(450);
}); });
test('that the component can update parameters', async () => {
let api: PaneviewApi;
const onReady = (event: PaneviewReadyEvent) => {
api = event.api;
};
const wrapper = render(
<PaneviewReact components={components} onReady={onReady} />
);
let panel: IPaneviewPanel;
act(() => {
panel = api!.addPanel({
id: 'panel_1',
component: 'default',
title: 'Panel 1',
params: {
keyA: 'valueA',
keyB: 'valueB',
},
});
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: 'valueAA', keyC: 'valueC' });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=valueC/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyC: null });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: undefined });
});
await waitFor(() => {
expect(wrapper.queryByText(/key=keyA/i)).not.toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
});
}); });

View File

@ -1,53 +0,0 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { DockviewApi } from 'dockview-core';
import {
IDockviewPanelProps,
DockviewReact,
DockviewReadyEvent,
} from '../../../dockview/dockview';
import { PanelCollection } from '../../../types';
import { setMockRefElement } from '../../__test_utils__/utils';
describe('dockview', () => {
let components: PanelCollection<IDockviewPanelProps>;
beforeEach(() => {
components = {
default: (props: IDockviewPanelProps) => {
return <div>hello world</div>;
},
};
});
test('default', () => {
let api: DockviewApi | undefined;
const onReady = (event: DockviewReadyEvent) => {
api = event.api;
};
render(<DockviewReact components={components} onReady={onReady} />);
expect(api).toBeTruthy();
});
test('is sized to container', () => {
const el = document.createElement('div') as any;
jest.spyOn(el, 'clientHeight', 'get').mockReturnValue(450);
jest.spyOn(el, 'clientWidth', 'get').mockReturnValue(650);
setMockRefElement(el);
let api: DockviewApi | undefined;
const onReady = (event: DockviewReadyEvent) => {
api = event.api;
};
render(<DockviewReact components={components} onReady={onReady} />);
expect(api!.width).toBe(650);
expect(api!.height).toBe(450);
});
});

View File

@ -1,58 +0,0 @@
import {
DockviewGroupPanel,
DockviewGroupPanelApi,
DockviewGroupPanelModel,
} from 'dockview-core';
import { ReactHeaderActionsRendererPart } from '../../../dockview/headerActionsRenderer';
describe('headerActionsRenderer', () => {
test('#1', () => {
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
onDidActivePanelChange: jest.fn(),
};
}
);
const groupview = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
api: {} as DockviewGroupPanelApi as any,
model: groupview,
};
});
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new ReactHeaderActionsRendererPart(
jest.fn(),
{
addPortal: jest.fn(),
},
groupPanel
);
expect(cut.element.childNodes.length).toBe(0);
expect(cut.element.className).toBe('dockview-react-part');
expect(cut.part).toBeUndefined();
cut.init({
containerApi: <any>jest.fn(),
api: <any>{
onDidActiveChange: jest.fn(),
},
});
const update = jest.fn();
jest.spyOn(cut.part!, 'update').mockImplementation(update);
cut.update({ params: { valueA: 'A' } });
expect(update).toBeCalledWith({ valueA: 'A' });
});
});

View File

@ -1,64 +0,0 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { GridviewApi, Orientation } from 'dockview-core';
import {
IGridviewPanelProps,
GridviewReact,
GridviewReadyEvent,
} from '../../../gridview/gridview';
import { PanelCollection } from '../../../types';
import { setMockRefElement } from '../../__test_utils__/utils';
describe('gridview react', () => {
let components: PanelCollection<IGridviewPanelProps>;
beforeEach(() => {
components = {
default: (props: IGridviewPanelProps) => {
return <div>hello world</div>;
},
};
});
test('default', () => {
let api: GridviewApi | undefined;
const onReady = (event: GridviewReadyEvent) => {
api = event.api;
};
render(
<GridviewReact
orientation={Orientation.VERTICAL}
components={components}
onReady={onReady}
/>
);
expect(api).toBeTruthy();
});
test('is sized to container', () => {
setMockRefElement({
clientHeight: 450,
clientWidth: 650,
appendChild: jest.fn(),
});
let api: GridviewApi | undefined;
const onReady = (event: GridviewReadyEvent) => {
api = event.api;
};
render(
<GridviewReact
orientation={Orientation.VERTICAL}
components={components}
onReady={onReady}
/>
);
expect(api!.width).toBe(650);
expect(api!.height).toBe(450);
});
});

View File

@ -1,52 +0,0 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { PaneviewApi } from 'dockview-core';
import {
IPaneviewPanelProps,
PaneviewReact,
PaneviewReadyEvent,
} from '../../../paneview/paneview';
import { PanelCollection } from '../../../types';
import { setMockRefElement } from '../../__test_utils__/utils';
describe('gridview react', () => {
let components: PanelCollection<IPaneviewPanelProps>;
beforeEach(() => {
components = {
default: (props: IPaneviewPanelProps) => {
return <div>hello world</div>;
},
};
});
test('default', () => {
let api: PaneviewApi | undefined;
const onReady = (event: PaneviewReadyEvent) => {
api = event.api;
};
render(<PaneviewReact components={components} onReady={onReady} />);
expect(api).toBeTruthy();
});
test('is sized to container', () => {
setMockRefElement({
clientHeight: 450,
clientWidth: 650,
appendChild: jest.fn(),
});
let api: PaneviewApi | undefined;
const onReady = (event: PaneviewReadyEvent) => {
api = event.api;
};
render(<PaneviewReact components={components} onReady={onReady} />);
expect(api!.width).toBe(650);
expect(api!.height).toBe(450);
});
});

View File

@ -1,90 +0,0 @@
import { ReactPart } from '../../react';
import * as React from 'react';
import { render, screen, act } from '@testing-library/react';
interface TestInterface {
valueA: string;
valueB: number;
}
describe('react', () => {
describe('ReactPart', () => {
test('update underlying component via ReactPart class', () => {
let api: ReactPart<TestInterface>;
const onReady = (_api: ReactPart<TestInterface>) => {
api = _api;
};
render(<TestWrapper onReady={onReady} component={Component} />);
expect(api!).toBeTruthy();
expect(screen.getByTestId('valueA').textContent).toBe('stringA');
expect(screen.getByTestId('valueB').textContent).toBe('42');
act(() => {
api.update({ valueB: '32' });
});
expect(screen.getByTestId('valueA').textContent).toBe('stringA');
expect(screen.getByTestId('valueB').textContent).toBe('32');
act(() => {
api.update({ valueA: 'anotherStringA', valueB: '22' });
});
expect(screen.getByTestId('valueA').textContent).toBe(
'anotherStringA'
);
expect(screen.getByTestId('valueB').textContent).toBe('22');
});
});
});
const Component = (props: TestInterface) => {
return (
<div>
<div data-testid="valueA">{props.valueA}</div>
<div data-testid="valueB">{props.valueB}</div>
</div>
);
};
const TestWrapper = (props: {
component: React.FunctionComponent<TestInterface>;
onReady: (api: ReactPart<TestInterface>) => void;
}) => {
const [portal, setPortal] = React.useState<React.ReactPortal[]>([]);
const ref = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
const cut = new ReactPart<TestInterface>(
ref.current!,
{
addPortal: (portal: React.ReactPortal) => {
setPortal((_) => [..._, portal]);
return {
dispose: () => {
setPortal((_) => _.filter((_) => _ !== portal));
},
};
},
},
props.component,
{
valueA: 'stringA',
valueB: 42,
}
);
props.onReady(cut);
return () => {
cut.dispose();
};
}, []);
return <div ref={ref}>{portal}</div>;
};

View File

@ -1,64 +0,0 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { SplitviewApi, Orientation } from 'dockview-core';
import {
ISplitviewPanelProps,
SplitviewReact,
SplitviewReadyEvent,
} from '../../../splitview/splitview';
import { PanelCollection } from '../../../types';
import { setMockRefElement } from '../../__test_utils__/utils';
describe('splitview react', () => {
let components: PanelCollection<ISplitviewPanelProps>;
beforeEach(() => {
components = {
default: (props: ISplitviewPanelProps) => {
return <div>hello world</div>;
},
};
});
test('default', () => {
let api: SplitviewApi | undefined;
const onReady = (event: SplitviewReadyEvent) => {
api = event.api;
};
render(
<SplitviewReact
orientation={Orientation.VERTICAL}
components={components}
onReady={onReady}
/>
);
expect(api).toBeTruthy();
});
test('is sized to container', () => {
setMockRefElement({
clientHeight: 450,
clientWidth: 650,
appendChild: jest.fn(),
});
let api: SplitviewApi | undefined;
const onReady = (event: SplitviewReadyEvent) => {
api = event.api;
};
render(
<SplitviewReact
orientation={Orientation.VERTICAL}
components={components}
onReady={onReady}
/>
);
expect(api!.width).toBe(650);
expect(api!.height).toBe(450);
});
});

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render } from '@testing-library/react'; import { act, render, waitFor } from '@testing-library/react';
import { SplitviewApi, Orientation } from 'dockview-core'; import { SplitviewApi, Orientation, ISplitviewPanel } from 'dockview-core';
import { import {
ISplitviewPanelProps, ISplitviewPanelProps,
SplitviewReact, SplitviewReact,
@ -15,7 +15,17 @@ describe('splitview react', () => {
beforeEach(() => { beforeEach(() => {
components = { components = {
default: (props: ISplitviewPanelProps) => { default: (props: ISplitviewPanelProps) => {
return <div>hello world</div>; return (
<div>
{Object.keys(props.params).map((key) => {
return (
<div
key={key}
>{`key=${key},value=${props.params[key]}`}</div>
);
})}
</div>
);
}, },
}; };
}); });
@ -61,4 +71,88 @@ describe('splitview react', () => {
expect(api!.width).toBe(650); expect(api!.width).toBe(650);
expect(api!.height).toBe(450); expect(api!.height).toBe(450);
}); });
test('that the component can update parameters', async () => {
let api: SplitviewApi;
const onReady = (event: SplitviewReadyEvent) => {
api = event.api;
};
const wrapper = render(
<SplitviewReact
orientation={Orientation.VERTICAL}
components={components}
onReady={onReady}
/>
);
let panel: ISplitviewPanel;
act(() => {
panel = api!.addPanel({
id: 'panel_1',
component: 'default',
params: {
keyA: 'valueA',
keyB: 'valueB',
},
});
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: 'valueAA', keyC: 'valueC' });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=valueC/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyC: null });
});
await waitFor(() => {
expect(
wrapper.queryByText(/key=keyA,value=valueAA/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
act(() => {
panel.api.updateParameters({ keyA: undefined });
});
await waitFor(() => {
expect(wrapper.queryByText(/key=keyA/i)).not.toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyB,value=valueB/i)
).toBeInTheDocument();
expect(
wrapper.queryByText(/key=keyC,value=null/i)
).toBeInTheDocument();
});
});
}); });

View File

@ -0,0 +1,20 @@
---
slug: dockview-1.7.4-release
title: Dockview 1.7.4
tags: [release]
---
# Release Notes
Please reference to docs @ [dockview.dev](https://dockview.dev).
## 🚀 Features
- Improvements and tests added to the panel `api.updateParameters(...)` method [#265](https://github.com/mathuo/dockview/pull/265)
## 🛠 Miscs
- Fix bug associated with overidding panel titles when using `api.updateParameters(...)` [#265](https://github.com/mathuo/dockview/pull/265)
- Cleanup listeners and disposables after use [#257](https://github.com/mathuo/dockview/pull/257)
## 🔥 Breaking changes

View File

@ -436,6 +436,40 @@ const panel2 = api.addPanel({
}); });
``` ```
### Update Panel
You can programatically update the `params` passed through to the panel through the panal api using `api.updateParameters`.
```ts
const panel = api.addPanel({
id: 'panel_1',
component: 'default',
params: {
keyA: 'valueA',
},
});
// ...
panel.api.updateParameters({
keyB: 'valueB',
});
// ...
panel.api.updateParameters({
keyA: 'anotherValueA',
});
```
To delete a parameter you should pass a value of `undefined` for the key.
```ts
panel.api.updateParameters({
keyA: undefined, // this will delete 'keyA'.
});
```
### Panel Rendering ### Panel Rendering
By default `DockviewReact` only adds to the DOM those panels that are visible, By default `DockviewReact` only adds to the DOM those panels that are visible,

View File

@ -1,6 +1,6 @@
{ {
"name": "dockview-docs", "name": "dockview-docs",
"version": "1.7.3", "version": "1.7.4",
"private": true, "private": true,
"scripts": { "scripts": {
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@ -22,7 +22,7 @@
"@minoru/react-dnd-treeview": "^3.4.3", "@minoru/react-dnd-treeview": "^3.4.3",
"axios": "^1.3.3", "axios": "^1.3.3",
"clsx": "^1.2.1", "clsx": "^1.2.1",
"dockview": "^1.7.3", "dockview": "^1.7.4",
"prism-react-renderer": "^1.3.5", "prism-react-renderer": "^1.3.5",
"react": "^18.2.0", "react": "^18.2.0",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",

View File

@ -435,6 +435,40 @@ const panel2 = api.addPanel({
}); });
``` ```
### Update Panel
You can programatically update the `params` passed through to the panel through the panal api using `api.updateParameters`.
```ts
const panel = api.addPanel({
id: 'panel_1',
component: 'default',
params: {
keyA: 'valueA',
},
});
// ...
panel.api.updateParameters({
keyB: 'valueB',
});
// ...
panel.api.updateParameters({
keyA: 'anotherValueA',
});
```
To delete a parameter you should pass a value of `undefined` for the key.
```ts
panel.api.updateParameters({
keyA: undefined, // this will delete 'keyA'.
});
```
### Panel Rendering ### Panel Rendering
By default `DockviewReact` only adds to the DOM those panels that are visible, By default `DockviewReact` only adds to the DOM those panels that are visible,

View File

@ -1,3 +1,3 @@
[ [
"1.7.3" "1.7.4"
] ]

View File

@ -2,6 +2,11 @@
# yarn lockfile v1 # yarn lockfile v1
"@adobe/css-tools@^4.0.1":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.2.0.tgz#e1a84fca468f4b337816fcb7f0964beb620ba855"
integrity sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==
"@algolia/autocomplete-core@1.7.4": "@algolia/autocomplete-core@1.7.4":
version "1.7.4" version "1.7.4"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz#85ff36b2673654a393c8c505345eaedd6eaa4f70" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz#85ff36b2673654a393c8c505345eaedd6eaa4f70"
@ -2888,6 +2893,21 @@
lz-string "^1.4.4" lz-string "^1.4.4"
pretty-format "^27.0.2" pretty-format "^27.0.2"
"@testing-library/jest-dom@^5.16.5":
version "5.16.5"
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e"
integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==
dependencies:
"@adobe/css-tools" "^4.0.1"
"@babel/runtime" "^7.9.2"
"@types/testing-library__jest-dom" "^5.9.1"
aria-query "^5.0.0"
chalk "^3.0.0"
css.escape "^1.5.1"
dom-accessibility-api "^0.5.6"
lodash "^4.17.15"
redent "^3.0.0"
"@testing-library/react@^13.4.0": "@testing-library/react@^13.4.0":
version "13.4.0" version "13.4.0"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.4.0.tgz#6a31e3bf5951615593ad984e96b9e5e2d9380966" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.4.0.tgz#6a31e3bf5951615593ad984e96b9e5e2d9380966"
@ -3107,6 +3127,14 @@
dependencies: dependencies:
"@types/istanbul-lib-report" "*" "@types/istanbul-lib-report" "*"
"@types/jest@*":
version "29.5.2"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.2.tgz#86b4afc86e3a8f3005b297ed8a72494f89e6395b"
integrity sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==
dependencies:
expect "^29.0.0"
pretty-format "^29.0.0"
"@types/jest@^29.4.0": "@types/jest@^29.4.0":
version "29.5.0" version "29.5.0"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.0.tgz#337b90bbcfe42158f39c2fb5619ad044bbb518ac" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.0.tgz#337b90bbcfe42158f39c2fb5619ad044bbb518ac"
@ -3292,6 +3320,13 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
"@types/testing-library__jest-dom@^5.9.1":
version "5.14.6"
resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.6.tgz#4887f6e1af11215428ab02777873bcede98a53b0"
integrity sha512-FkHXCb+ikSoUP4Y4rOslzTdX5sqYwMxfefKh1GmZ8ce1GOkEHntSp6b5cGadmNfp5e4BMEWOMx+WSKd5/MqlDA==
dependencies:
"@types/jest" "*"
"@types/tough-cookie@*": "@types/tough-cookie@*":
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397"
@ -4659,6 +4694,14 @@ chalk@^2.0.0, chalk@^2.3.0:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
supports-color "^5.3.0" supports-color "^5.3.0"
chalk@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@ -5488,6 +5531,11 @@ css-what@^6.0.1, css-what@^6.1.0:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
css.escape@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
cssesc@^3.0.0: cssesc@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@ -5928,7 +5976,7 @@ docusaurus-plugin-sass@^0.2.3:
dependencies: dependencies:
sass-loader "^10.1.1" sass-loader "^10.1.1"
dom-accessibility-api@^0.5.9: dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9:
version "0.5.16" version "0.5.16"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453"
integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
@ -9918,7 +9966,7 @@ markdown-escapes@^1.0.0:
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
marked@^4.3.0: marked@^4.2.12, marked@^4.3.0:
version "4.3.0" version "4.3.0"
resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3"
integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==
@ -10136,6 +10184,13 @@ minimatch@^6.1.6:
dependencies: dependencies:
brace-expansion "^2.0.1" brace-expansion "^2.0.1"
minimatch@^7.1.3:
version "7.4.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb"
integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==
dependencies:
brace-expansion "^2.0.1"
minimatch@^7.4.1, minimatch@^7.4.2: minimatch@^7.4.1, minimatch@^7.4.2:
version "7.4.3" version "7.4.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.3.tgz#012cbf110a65134bb354ae9773b55256cdb045a2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.3.tgz#012cbf110a65134bb354ae9773b55256cdb045a2"
@ -14256,6 +14311,16 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
typedoc@^0.23.25:
version "0.23.28"
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.23.28.tgz#3ce9c36ef1c273fa849d2dea18651855100d3ccd"
integrity sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==
dependencies:
lunr "^2.3.9"
marked "^4.2.12"
minimatch "^7.1.3"
shiki "^0.14.1"
typedoc@^0.24.7: typedoc@^0.24.7:
version "0.24.7" version "0.24.7"
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.7.tgz#7eeb272a1894b3789acc1a94b3f2ae8e7330ee39" resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.7.tgz#7eeb272a1894b3789acc1a94b3f2ae8e7330ee39"