Customize the shell layout with the settings (#6921)

* Add settings file

* Add support for layout customization

* Fix tests

* Add `type` option

* Fix opening document widgets

* Fix opening documents

* Add defaults for Markdown Preview

* Add docs

* Add screenshots

* Add `@jupyterlab/attachments`

* Fix integrity

* Add simple UI tests for layout customization

* Lint

* Update Playwright Snapshots

* Update Playwright Snapshots

* Update docs

* Add missing null

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jeremy Tuloup 2023-06-15 09:47:29 +02:00 committed by GitHub
parent 33a383d3f8
commit ab57fa1d20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 2621 additions and 2313 deletions

View File

@ -10,8 +10,8 @@
"watch": "webpack --config ./webpack.config.watch.js"
},
"resolutions": {
"@codemirror/state": "~6.2.0",
"@codemirror/view": "~6.11.0",
"@codemirror/state": "~6.2.1",
"@codemirror/view": "~6.13.2",
"@jupyter-notebook/application": "~7.0.0-beta.4",
"@jupyter-notebook/application-extension": "~7.0.0-beta.4",
"@jupyter-notebook/console-extension": "~7.0.0-beta.4",
@ -24,76 +24,79 @@
"@jupyter-notebook/tree-extension": "~7.0.0-beta.4",
"@jupyter-notebook/ui-components": "~7.0.0-beta.4",
"@jupyter/ydoc": "~1.0.2",
"@jupyterlab/application": "~4.0.1",
"@jupyterlab/application-extension": "~4.0.1",
"@jupyterlab/apputils": "~4.1.1",
"@jupyterlab/apputils-extension": "~4.0.1",
"@jupyterlab/cell-toolbar": "~4.0.1",
"@jupyterlab/cell-toolbar-extension": "~4.0.1",
"@jupyterlab/celltags-extension": "~4.0.1",
"@jupyterlab/codeeditor": "~4.0.1",
"@jupyterlab/codemirror": "~4.0.1",
"@jupyterlab/codemirror-extension": "~4.0.1",
"@jupyterlab/completer": "~4.0.1",
"@jupyterlab/completer-extension": "~4.0.1",
"@jupyterlab/console": "~4.0.1",
"@jupyterlab/console-extension": "~4.0.1",
"@jupyterlab/coreutils": "~6.0.1",
"@jupyterlab/csvviewer-extension": "~4.0.1",
"@jupyterlab/debugger": "~4.0.1",
"@jupyterlab/debugger-extension": "~4.0.1",
"@jupyterlab/docmanager": "~4.0.1",
"@jupyterlab/docmanager-extension": "~4.0.1",
"@jupyterlab/documentsearch": "~4.0.1",
"@jupyterlab/documentsearch-extension": "~4.0.1",
"@jupyterlab/extensionmanager": "~4.0.1",
"@jupyterlab/extensionmanager-extension": "~4.0.1",
"@jupyterlab/filebrowser": "~4.0.1",
"@jupyterlab/filebrowser-extension": "~4.0.1",
"@jupyterlab/fileeditor": "~4.0.1",
"@jupyterlab/fileeditor-extension": "~4.0.1",
"@jupyterlab/htmlviewer": "~4.0.1",
"@jupyterlab/htmlviewer-extension": "~4.0.1",
"@jupyterlab/hub-extension": "~4.0.1",
"@jupyterlab/javascript-extension": "~4.0.1",
"@jupyterlab/json-extension": "~4.0.1",
"@jupyterlab/lsp": "~4.0.1",
"@jupyterlab/lsp-extension": "~4.0.1",
"@jupyterlab/mainmenu": "~4.0.1",
"@jupyterlab/mainmenu-extension": "~4.0.1",
"@jupyterlab/markedparser-extension": "~4.0.1",
"@jupyterlab/mathjax-extension": "~4.0.1",
"@jupyterlab/metadataform": "~4.0.1",
"@jupyterlab/metadataform-extension": "~4.0.1",
"@jupyterlab/notebook": "~4.0.1",
"@jupyterlab/notebook-extension": "~4.0.1",
"@jupyterlab/observables": "~5.0.1",
"@jupyterlab/outputarea": "~4.0.1",
"@jupyterlab/pdf-extension": "~4.0.1",
"@jupyterlab/rendermime": "~4.0.1",
"@jupyterlab/rendermime-interfaces": "~3.8.1",
"@jupyterlab/running-extension": "~4.0.1",
"@jupyterlab/services": "~7.0.1",
"@jupyterlab/settingeditor": "~4.0.1",
"@jupyterlab/settingeditor-extension": "~4.0.1",
"@jupyterlab/settingregistry": "~4.0.1",
"@jupyterlab/shortcuts-extension": "~4.0.1",
"@jupyterlab/statedb": "~4.0.1",
"@jupyterlab/statusbar": "~4.0.1",
"@jupyterlab/terminal": "~4.0.1",
"@jupyterlab/terminal-extension": "~4.0.1",
"@jupyterlab/theme-dark-extension": "~4.0.1",
"@jupyterlab/theme-light-extension": "~4.0.1",
"@jupyterlab/toc-extension": "~6.0.1",
"@jupyterlab/tooltip": "~4.0.1",
"@jupyterlab/tooltip-extension": "~4.0.1",
"@jupyterlab/translation": "~4.0.1",
"@jupyterlab/translation-extension": "~4.0.1",
"@jupyterlab/ui-components": "~4.0.1",
"@jupyterlab/ui-components-extension": "~4.0.1",
"@jupyterlab/vega5-extension": "~4.0.1",
"@lezer/common": "~1.0.2",
"@lezer/highlight": "~1.1.4",
"@jupyterlab/application": "~4.0.2",
"@jupyterlab/application-extension": "~4.0.2",
"@jupyterlab/apputils": "~4.1.2",
"@jupyterlab/apputils-extension": "~4.0.2",
"@jupyterlab/attachments": "~4.0.2",
"@jupyterlab/cell-toolbar": "~4.0.2",
"@jupyterlab/cell-toolbar-extension": "~4.0.2",
"@jupyterlab/celltags-extension": "~4.0.2",
"@jupyterlab/codeeditor": "~4.0.2",
"@jupyterlab/codemirror": "~4.0.2",
"@jupyterlab/codemirror-extension": "~4.0.2",
"@jupyterlab/completer": "~4.0.2",
"@jupyterlab/completer-extension": "~4.0.2",
"@jupyterlab/console": "~4.0.2",
"@jupyterlab/console-extension": "~4.0.2",
"@jupyterlab/coreutils": "~6.0.2",
"@jupyterlab/csvviewer-extension": "~4.0.2",
"@jupyterlab/debugger": "~4.0.2",
"@jupyterlab/debugger-extension": "~4.0.2",
"@jupyterlab/docmanager": "~4.0.2",
"@jupyterlab/docmanager-extension": "~4.0.2",
"@jupyterlab/documentsearch": "~4.0.2",
"@jupyterlab/documentsearch-extension": "~4.0.2",
"@jupyterlab/extensionmanager": "~4.0.2",
"@jupyterlab/extensionmanager-extension": "~4.0.2",
"@jupyterlab/filebrowser": "~4.0.2",
"@jupyterlab/filebrowser-extension": "~4.0.2",
"@jupyterlab/fileeditor": "~4.0.2",
"@jupyterlab/fileeditor-extension": "~4.0.2",
"@jupyterlab/htmlviewer": "~4.0.2",
"@jupyterlab/htmlviewer-extension": "~4.0.2",
"@jupyterlab/hub-extension": "~4.0.2",
"@jupyterlab/javascript-extension": "~4.0.2",
"@jupyterlab/json-extension": "~4.0.2",
"@jupyterlab/lsp": "~4.0.2",
"@jupyterlab/lsp-extension": "~4.0.2",
"@jupyterlab/mainmenu": "~4.0.2",
"@jupyterlab/mainmenu-extension": "~4.0.2",
"@jupyterlab/markdownviewer": "~4.0.2",
"@jupyterlab/markdownviewer-extension": "~4.0.2",
"@jupyterlab/markedparser-extension": "~4.0.2",
"@jupyterlab/mathjax-extension": "~4.0.2",
"@jupyterlab/metadataform": "~4.0.2",
"@jupyterlab/metadataform-extension": "~4.0.2",
"@jupyterlab/notebook": "~4.0.2",
"@jupyterlab/notebook-extension": "~4.0.2",
"@jupyterlab/observables": "~5.0.2",
"@jupyterlab/outputarea": "~4.0.2",
"@jupyterlab/pdf-extension": "~4.0.2",
"@jupyterlab/rendermime": "~4.0.2",
"@jupyterlab/rendermime-interfaces": "~3.8.2",
"@jupyterlab/running-extension": "~4.0.2",
"@jupyterlab/services": "~7.0.2",
"@jupyterlab/settingeditor": "~4.0.2",
"@jupyterlab/settingeditor-extension": "~4.0.2",
"@jupyterlab/settingregistry": "~4.0.2",
"@jupyterlab/shortcuts-extension": "~4.0.2",
"@jupyterlab/statedb": "~4.0.2",
"@jupyterlab/statusbar": "~4.0.2",
"@jupyterlab/terminal": "~4.0.2",
"@jupyterlab/terminal-extension": "~4.0.2",
"@jupyterlab/theme-dark-extension": "~4.0.2",
"@jupyterlab/theme-light-extension": "~4.0.2",
"@jupyterlab/toc-extension": "~6.0.2",
"@jupyterlab/tooltip": "~4.0.2",
"@jupyterlab/tooltip-extension": "~4.0.2",
"@jupyterlab/translation": "~4.0.2",
"@jupyterlab/translation-extension": "~4.0.2",
"@jupyterlab/ui-components": "~4.0.2",
"@jupyterlab/ui-components-extension": "~4.0.2",
"@jupyterlab/vega5-extension": "~4.0.2",
"@lezer/common": "~1.0.3",
"@lezer/highlight": "~1.1.6",
"@lumino/algorithm": "~2.0.0",
"@lumino/application": "~2.1.1",
"@lumino/commands": "~2.1.1",
@ -108,7 +111,7 @@
"@lumino/widgets": "~2.1.1",
"react": "~18.2.0",
"react-dom": "~18.2.0",
"yjs": "~13.6.1"
"yjs": "~13.6.2"
},
"dependencies": {
"@jupyter-notebook/application": "^7.0.0-beta.4",
@ -124,6 +127,7 @@
"@jupyter-notebook/ui-components": "^7.0.0-beta.4",
"@jupyterlab/application-extension": "^4.0.1",
"@jupyterlab/apputils-extension": "^4.0.1",
"@jupyterlab/attachments": "^4.0.1",
"@jupyterlab/cell-toolbar-extension": "^4.0.1",
"@jupyterlab/celltags-extension": "^4.0.1",
"@jupyterlab/codemirror": "^4.0.1",
@ -145,6 +149,7 @@
"@jupyterlab/lsp": "^4.0.1",
"@jupyterlab/lsp-extension": "^4.0.1",
"@jupyterlab/mainmenu-extension": "^4.0.1",
"@jupyterlab/markdownviewer-extension": "^4.0.1",
"@jupyterlab/markedparser-extension": "^4.0.1",
"@jupyterlab/mathjax-extension": "^4.0.1",
"@jupyterlab/metadataform-extension": "^4.0.1",
@ -322,7 +327,8 @@
"@jupyterlab/fileeditor-extension": [
"@jupyterlab/fileeditor-extension:completer",
"@jupyterlab/fileeditor-extension:search"
]
],
"@jupyterlab/markdownviewer-extension": true
}
},
"singletonPackages": [
@ -347,6 +353,7 @@
"@jupyterlab/htmlviewer",
"@jupyterlab/lsp",
"@jupyterlab/mainmenu",
"@jupyterlab/markdownviewer",
"@jupyterlab/metadataform",
"@jupyterlab/notebook",
"@jupyterlab/observables",

View File

@ -5,7 +5,6 @@
:maxdepth: 1
configuring/config_overview
configuring/plugins
Security <https://jupyter-server.readthedocs.io/en/stable/operators/security.html>
extending/index.rst
```

View File

@ -0,0 +1,62 @@
# Interface Customization
Multiple elements in the Notebook interface can be customized via the Settings Editor.
## Layout
By default some widgets are displayed in pre-defined parts of the user interface, which are often called "areas" or "regions".
For example the table of contents will be displayed in the `left` area by default, while the debugger will be displayed in the `right` area.
However the positioning of some of these components can also be customized via the Settings Editor. Below are a few examples of how to do this.
### Open the Markdown Preview on the left
It is often useful to be able to see a rendered preview of a Markdown document while editing it.
By default the Markdown Preview opens on the right side of the application. However it is also possible to open it on the left side by changing the Notebook Shell settings in the Advanced Settings Editor:
```json
{
"layout": {
"Markdown Preview": {
"area": "left"
}
}
}
```
![a screenshot showing the markdown preview in Notebook 7](https://github.com/jupyter/notebook/assets/591645/3faf0823-ec6f-4d5f-a66f-d6f53dc383de)
### Configuring a third-party widget
Third-party extensions can also add widgets to the application shell. This is for example the case with the [Voila extension](https://github.com/voila-dashboards/voila), which adds a preview widget to visualize a notebook as a dashboard.
By default in JupyterLab the Voila Preview is added to the `main` area next to the corresponding notebook. With Notebook 7 it is possible to move the Voila Preview to the `right` area by changing the Notebook Shell setting in the Advanced Settings Editor as follows:
```json
{
"layout": {
"Voila Preview": {
"area": "right"
}
}
}
```
![a screenshot showing the voila preview in Notebook 7](https://github.com/jupyter/notebook/assets/591645/524ade3b-05de-4d3b-8ff9-089f2d38ac77)
```{note}
Refer to the [JupyterLab Layout Documentation](https://jupyterlab.readthedocs.io/en/latest/user/interface_customization.html#layout)
to learn more about the default positioning of other UI elements.
```
## Toolbars, Menu bar and Context Menu
It is also possible to customize toolbars, menus and context menu entries via the Settings Editor.
For example the items of the notebook toolbar can be reordered, or some menu entries can be hidden.
```{note}
Refer to the [JupyterLab Documentation](https://jupyterlab.readthedocs.io/en/latest/user/interface_customization.html)
to learn more about general interface customization via the settings editor.
```

View File

@ -10,6 +10,8 @@ ui_components
notebook_7_features
examples/Notebook/examples_index.rst
custom_css
configuring/plugins
configuring/interface_customization
troubleshooting
changelog
```

View File

@ -0,0 +1,34 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Notebook Shell",
"description": "Notebook Shell layout settings.",
"properties": {
"layout": {
"$ref": "#/definitions/layout",
"type": "object",
"title": "Customize shell widget positioning",
"description": "Overrides default widget position in the application layout",
"default": {
"Markdown Preview": { "area": "right" }
}
}
},
"additionalProperties": false,
"type": "object",
"definitions": {
"layout": {
"type": "object",
"properties": {
"[\\w-]+": {
"type": "object",
"properties": {
"area": {
"enum": ["left", "right"]
}
},
"additionalProperties": false
}
}
}
}
}

View File

@ -384,14 +384,36 @@ const rendermime: JupyterFrontEndPlugin<IRenderMimeRegistry> = {
*/
const shell: JupyterFrontEndPlugin<INotebookShell> = {
id: '@jupyter-notebook/application-extension:shell',
activate: (app: JupyterFrontEnd) => {
autoStart: true,
provides: INotebookShell,
optional: [ISettingRegistry],
activate: (
app: JupyterFrontEnd,
settingRegistry: ISettingRegistry | null
) => {
if (!(app.shell instanceof NotebookShell)) {
throw new Error(`${shell.id} did not find a NotebookShell instance.`);
}
return app.shell;
const notebookShell = app.shell;
if (settingRegistry) {
settingRegistry
.load(shell.id)
.then((settings) => {
// Add a layer of customization to support app shell mode
const customLayout = settings.composite['layout'] as any;
// Restore the layout.
void notebookShell.restoreLayout(customLayout);
})
.catch((reason) => {
console.error('Fail to load settings for the layout restorer.');
console.error(reason);
});
}
return notebookShell;
},
autoStart: true,
provides: INotebookShell,
};
/**

View File

@ -6,7 +6,7 @@ import { DocumentRegistry } from '@jupyterlab/docregistry';
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
import { find } from '@lumino/algorithm';
import { PromiseDelegate, Token } from '@lumino/coreutils';
import { JSONExt, PromiseDelegate, Token } from '@lumino/coreutils';
import { ISignal, Signal } from '@lumino/signaling';
import { BoxLayout, Panel, SplitPanel, Widget } from '@lumino/widgets';
@ -24,6 +24,40 @@ export const INotebookShell = new Token<INotebookShell>(
*/
export interface INotebookShell extends NotebookShell {}
/**
* The namespace for INotebookShell type information.
*/
export namespace INotebookShell {
/**
* The areas of the application shell where widgets can reside.
*/
export type Area = 'main' | 'top' | 'menu' | 'left' | 'right';
/**
* Widget position
*/
export interface IWidgetPosition {
/**
* Widget area
*/
area?: Area;
/**
* Widget opening options
*/
options?: DocumentRegistry.IOpenOptions;
}
/**
* Mapping of widget type identifier and their user customized position
*/
export interface IUserLayout {
/**
* Widget customized position
*/
[k: string]: IWidgetPosition;
}
}
/**
* The default rank for ranked panels.
*/
@ -36,6 +70,7 @@ export class NotebookShell extends Widget implements JupyterFrontEnd.IShell {
constructor() {
super();
this.id = 'main';
this._userLayout = {};
this._topHandler = new PanelHandler();
this._menuHandler = new PanelHandler();
@ -211,13 +246,23 @@ export class NotebookShell extends Widget implements JupyterFrontEnd.IShell {
}
}
/**
* User custom shell layout.
*/
get userLayout() {
return JSONExt.deepCopy(this._userLayout as any);
}
/**
* Activate a widget in its area.
*/
activateById(id: string): void {
// Search all areas that can have widgets for this widget, starting with main.
for (const area of ['main', 'top', 'left', 'right', 'menu']) {
const widget = find(this.widgets(area as Shell.Area), (w) => w.id === id);
const widget = find(
this.widgets(area as INotebookShell.Area),
(w) => w.id === id
);
if (widget) {
if (area === 'left') {
this.expandLeft(id);
@ -243,9 +288,25 @@ export class NotebookShell extends Widget implements JupyterFrontEnd.IShell {
*/
add(
widget: Widget,
area?: Shell.Area,
area?: INotebookShell.Area,
options?: DocumentRegistry.IOpenOptions
): void {
let userPosition: INotebookShell.IWidgetPosition | undefined;
if (options?.type && this._userLayout[options.type]) {
userPosition = this._userLayout[options.type];
} else {
userPosition = this._userLayout[widget.id];
}
area = userPosition?.area ?? area;
options =
options || userPosition?.options
? {
...options,
...userPosition?.options,
}
: undefined;
const rank = options?.rank ?? DEFAULT_RANK;
switch (area) {
case 'top':
@ -293,7 +354,7 @@ export class NotebookShell extends Widget implements JupyterFrontEnd.IShell {
*
* @param area The area
*/
*widgets(area: Shell.Area): IterableIterator<Widget> {
*widgets(area: INotebookShell.Area): IterableIterator<Widget> {
switch (area ?? 'main') {
case 'top':
yield* this._topHandler.panel.widgets;
@ -348,6 +409,15 @@ export class NotebookShell extends Widget implements JupyterFrontEnd.IShell {
this._rightHandler.panel.hide();
}
/**
* Restore the layout state and configuration for the application shell.
*/
async restoreLayout(
configuration: INotebookShell.IUserLayout
): Promise<void> {
this._userLayout = configuration;
}
private _topWrapper: Panel;
private _topHandler: PanelHandler;
private _menuWrapper: Panel;
@ -361,16 +431,7 @@ export class NotebookShell extends Widget implements JupyterFrontEnd.IShell {
private _translator: ITranslator = nullTranslator;
private _currentChanged = new Signal<this, void>(this);
private _mainWidgetLoaded = new PromiseDelegate<void>();
}
/**
* A namespace for Shell statics
*/
export namespace Shell {
/**
* The areas of the application shell where widgets can reside.
*/
export type Area = 'main' | 'top' | 'left' | 'right' | 'menu';
private _userLayout: INotebookShell.IUserLayout;
}
export namespace Private {

View File

@ -1,11 +1,7 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import {
INotebookShell,
NotebookShell,
Shell,
} from '@jupyter-notebook/application';
import { INotebookShell, NotebookShell } from '@jupyter-notebook/application';
import { JupyterFrontEnd } from '@jupyterlab/application';
@ -30,7 +26,7 @@ describe('Shell for notebooks', () => {
it('should make some areas empty initially', () => {
['main', 'left', 'right', 'menu'].forEach((area) => {
const widgets = Array.from(shell.widgets(area as Shell.Area));
const widgets = Array.from(shell.widgets(area as INotebookShell.Area));
expect(widgets.length).toEqual(0);
});
});
@ -139,7 +135,7 @@ describe('Shell for tree view', () => {
it('should make some areas empty initially', () => {
['main', 'left', 'right', 'menu'].forEach((area) => {
const widgets = Array.from(shell.widgets(area as Shell.Area));
const widgets = Array.from(shell.widgets(area as INotebookShell.Area));
expect(widgets.length).toEqual(0);
});
});

View File

@ -12,6 +12,8 @@ import { IDocumentWidgetOpener } from '@jupyterlab/docmanager';
import { IDocumentWidget, DocumentRegistry } from '@jupyterlab/docregistry';
import { INotebookShell } from '@jupyter-notebook/application';
import { Signal } from '@lumino/signaling';
/**
@ -21,17 +23,20 @@ import { Signal } from '@lumino/signaling';
const opener: JupyterFrontEndPlugin<IDocumentWidgetOpener> = {
id: '@jupyter-notebook/docmanager-extension:opener',
autoStart: true,
optional: [INotebookShell],
provides: IDocumentWidgetOpener,
activate: (app: JupyterFrontEnd) => {
activate: (app: JupyterFrontEnd, notebookShell: INotebookShell | null) => {
const baseUrl = PageConfig.getBaseUrl();
const docRegistry = app.docRegistry;
let id = 0;
return new (class {
open(widget: IDocumentWidget, options?: DocumentRegistry.IOpenOptions) {
const widgetName = options?.type;
const widgetName = options?.type ?? '';
const ref = options?.ref;
// check if there is an setting override and if it would add the widget in the main area
const userLayoutArea = notebookShell?.userLayout?.[widgetName]?.area;
if (ref !== '_noref') {
if (ref !== '_noref' && userLayoutArea === undefined) {
const path = widget.context.path;
const ext = PathExt.extname(path);
let route = 'edit';

View File

@ -359,7 +359,7 @@ const notebookToolsWidget: JupyterFrontEndPlugin<void> = {
// Add the notebook tools in right area.
if (notebookTools) {
shell.add(notebookTools, 'right');
shell.add(notebookTools, 'right', { type: 'Property Inspector' });
}
};
shell.currentChanged.connect(onChange);
@ -388,7 +388,9 @@ const trusted: JupyterFrontEndPlugin<void> = {
await current.context.ready;
const widget = TrustedComponent.create({ notebook, translator });
notebookShell.add(widget, 'menu', { rank: 11_000 });
notebookShell.add(widget, 'menu', {
rank: 11_000,
});
};
notebookShell.currentChanged.connect(onChange);

View File

@ -0,0 +1,44 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import path from 'path';
import { expect } from '@playwright/test';
import { galata } from '@jupyterlab/galata';
import { test } from './fixtures';
test.use({
mockSettings: {
...galata.DEFAULT_SETTINGS,
'@jupyter-notebook/application-extension:shell': {
layout: {
Debugger: { area: 'left' },
},
},
},
});
test.describe('Layout Customization', () => {
test('The Debugger panel should respect the settings and open in the left area', async ({
page,
tmpPath,
}) => {
const notebook = 'simple.ipynb';
await page.contents.uploadFile(
path.resolve(__dirname, `./notebooks/${notebook}`),
`${tmpPath}/${notebook}`
);
await page.goto(`notebooks/${tmpPath}/${notebook}`);
const menuPath = 'View>Left Sidebar>Show Debugger';
await page.menu.clickMenuItem(menuPath);
const panel = page.locator('#jp-left-stack');
expect(await panel.isVisible()).toBe(true);
expect(await panel.screenshot()).toMatchSnapshot('debugger.png');
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

4490
yarn.lock

File diff suppressed because it is too large Load Diff