Repository: deathbeds/jupyterlab-deck (language: python)

Issue:
Add foreground, background layers
## Elevator Pitch

Enable placing whole cells, or just outputs, in the background or foreground of the whole deck, or just a slide.

## Motivation

Being able to use (potentially dynamic) content would be a powerful technique for both theming as well as combining out-of-band content.

## Design Ideas

- offer these as `jss`-compatible recipes which can be added to cells
  - might "just work" with https://github.com/deathbeds/jupyterlab-fonts/issues/47
- use custom metadata
  - probably better fine-grained control
Offer per-slide layout and deck-level defaults
## Elevator Pitch

A notebook-based deck should be able to be customized and then overridden on a per-cell basis.

## Motivation

- CSS [grid](https://css-tricks.com/snippets/css/complete-guide-grid/) offers a lot of options for in-plane layout
- even wilder things are possible without actually changing the ordering/nesting of the DOM elements
- CSS variables can be overridden in `style`, including jupyterlab defaults like fine-grained font size choices, and would have very high specificity

## Design Ideas

- Allow a notebook to have `juptyerlab-deck.slideStyle`.
- Allow `slide` and `subslide` cells to set `jupyterlab-deck.slideStyle`, overriding the style.
  - These would be applied to the `.jp-Notebook`'s style, rather than the cell's. 
  - These would be "sticky" until the next (sub)slide changes them, such as signaling a reversion to the default flexbox model.
- Offer a number of pre-built patterns with wee icons, which can then be updated by e.g. settings, other (theme) extensions, or copy/pasted from metadata.
  - Specifically for grid, individual cells could override the template behavior with additional metadata in `jupyterlab-deck.style`, though this might create illogical navigation patterns and exciting failure modes when adding too many cells for a layout, but _caveat emptor_ once you start messing with `style` directly.
- Presumably #15's `position: fixed` elements would not affect custom layouts.


Discussion / hints:

Fix patch:
diff --git a/.binder/environment.yml b/.binder/environment.yml
index 27da85e..c5b7bff 100644
--- a/.binder/environment.yml
+++ b/.binder/environment.yml
@@ -7,11 +7,12 @@ channels:
 dependencies:
   - python >=3.10,<3.11
   ### environment-base.yml ###
-  - python >=3.7,<3.11
-  - pip
   - doit-with-toml
-  - jupyterlab >=3.4.8,<4
   - ipywidgets >=8
+  - jupyterlab >=3.4.8,<4
+  - jupyterlab-fonts >=2.1.1
+  - pip
+  - python >=3.7,<3.11
   ### environment-base.yml ###
   ### environment-build.yml ###
   # runtimes
@@ -35,9 +36,10 @@ dependencies:
   ### environment-lint.yml ###
   ### environment-docs.yml ###
   # demo
+  - ipydrawio
+  - jupyter-videochat
   - jupyterlab-myst
   - jupyterlab-webrtc-docprovider
-  - jupyter-videochat
   # docs
   - docutils >=0.18
   - pydata-sphinx-theme
@@ -48,7 +50,7 @@ dependencies:
   # lite cruft
   - pkginfo
   - pip:
-      - jupyterlite ==0.1.0b13
+      - jupyterlite ==0.1.0b14
   ### environment-docs.yml ###
   ### environment-test.yml ###
   # test
diff --git a/.github/environment-base.yml b/.github/environment-base.yml
index 1d58b73..d9d64f7 100644
--- a/.github/environment-base.yml
+++ b/.github/environment-base.yml
@@ -1,8 +1,9 @@
 dependencies:
   ### environment-base.yml ###
-  - python >=3.7,<3.11
-  - pip
   - doit-with-toml
-  - jupyterlab >=3.4.8,<4
   - ipywidgets >=8
+  - jupyterlab >=3.4.8,<4
+  - jupyterlab-fonts >=2.1.1
+  - pip
+  - python >=3.7,<3.11
   ### environment-base.yml ###
diff --git a/.github/environment-build.yml b/.github/environment-build.yml
index df31c6c..ab4ba6b 100644
--- a/.github/environment-build.yml
+++ b/.github/environment-build.yml
@@ -7,11 +7,12 @@ channels:
 dependencies:
   - python >=3.10,<3.11
   ### environment-base.yml ###
-  - python >=3.7,<3.11
-  - pip
   - doit-with-toml
-  - jupyterlab >=3.4.8,<4
   - ipywidgets >=8
+  - jupyterlab >=3.4.8,<4
+  - jupyterlab-fonts >=2.1.1
+  - pip
+  - python >=3.7,<3.11
   ### environment-base.yml ###
   ### environment-build.yml ###
   # runtimes
diff --git a/.github/environment-docs.yml b/.github/environment-docs.yml
index 9e886b0..478c86b 100644
--- a/.github/environment-docs.yml
+++ b/.github/environment-docs.yml
@@ -7,11 +7,12 @@ channels:
 dependencies:
   - python >=3.10,<3.11
   ### environment-base.yml ###
-  - python >=3.7,<3.11
-  - pip
   - doit-with-toml
-  - jupyterlab >=3.4.8,<4
   - ipywidgets >=8
+  - jupyterlab >=3.4.8,<4
+  - jupyterlab-fonts >=2.1.1
+  - pip
+  - python >=3.7,<3.11
   ### environment-base.yml ###
   ### environment-build.yml ###
   # runtimes
@@ -24,9 +25,10 @@ dependencies:
   ### environment-build.yml ###
   ### environment-docs.yml ###
   # demo
+  - ipydrawio
+  - jupyter-videochat
   - jupyterlab-myst
   - jupyterlab-webrtc-docprovider
-  - jupyter-videochat
   # docs
   - docutils >=0.18
   - pydata-sphinx-theme
@@ -37,5 +39,5 @@ dependencies:
   # lite cruft
   - pkginfo
   - pip:
-      - jupyterlite ==0.1.0b13
+      - jupyterlite ==0.1.0b14
   ### environment-docs.yml ###
diff --git a/.github/environment-lint.yml b/.github/environment-lint.yml
index 86b06f1..2b948a1 100644
--- a/.github/environment-lint.yml
+++ b/.github/environment-lint.yml
@@ -7,11 +7,12 @@ channels:
 dependencies:
   - python >=3.10,<3.11
   ### environment-base.yml ###
-  - python >=3.7,<3.11
-  - pip
   - doit-with-toml
-  - jupyterlab >=3.4.8,<4
   - ipywidgets >=8
+  - jupyterlab >=3.4.8,<4
+  - jupyterlab-fonts >=2.1.1
+  - pip
+  - python >=3.7,<3.11
   ### environment-base.yml ###
   ### environment-build.yml ###
   # runtimes
@@ -33,11 +34,6 @@ dependencies:
   - robotframework-robocop >=2.6
   - pyflakes
   ### environment-lint.yml ###
-  ### environment-test.yml ###
-  # test
-  - pytest-cov
-  - pytest-html
-  ### environment-test.yml ###
   ### environment-robot.yml ###
   - robotframework >=6
   - robotframework-pabot
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e418b98..91783a2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,9 @@
 
 ### `0.1.2` (unreleased)
 
-- TBD
+- [#17] adds foreground and background layers with customized per-cell styling
+
+[#17]: https://github.com/deathbeds/jupyterlab-deck/issues/15
 
 ### `0.1.1`
 
diff --git a/dodo.py b/dodo.py
index 921265a..fffb2c8 100644
--- a/dodo.py
+++ b/dodo.py
@@ -2,6 +2,7 @@
 import json
 import os
 import platform
+import shutil
 import subprocess
 import sys
 import time
@@ -127,6 +128,7 @@ class B:
     PYTEST_COV_XML = REPORTS_COV_XML / "pytest.coverage.xml"
     HTMLCOV_HTML = REPORTS / "htmlcov/index.html"
     ROBOT = REPORTS / "robot"
+    ROBOT_SCREENSHOTS = ROBOT / "screenshots"
     ROBOT_LOG_HTML = ROBOT / "log.html"
     PAGES_LITE = BUILD / "pages-lite"
     PAGES_LITE_SHASUMS = PAGES_LITE / "SHA256SUMS"
@@ -189,8 +191,6 @@ def pip_list():
         )
 
     def copy_one(src, dest):
-        import shutil
-
         if not dest.parent.exists():
             dest.parent.mkdir(parents=True)
         if dest.exists():
@@ -202,7 +202,6 @@ def copy_some(dest, srcs):
             U.copy_one(src, dest / src.name)
 
     def clean_some(*paths):
-        import shutil
 
         for path in paths:
             if path.is_dir():
@@ -338,6 +337,14 @@ def run_robot_with_retries(extra_args=None):
             cwd=B.ROBOT,
         )
 
+        if B.ROBOT_SCREENSHOTS.exists():
+            shutil.rmtree(B.ROBOT_SCREENSHOTS)
+
+        B.ROBOT_SCREENSHOTS.mkdir()
+
+        for screen_root in B.ROBOT.glob("*/screenshots/*"):
+            shutil.copytree(screen_root, B.ROBOT_SCREENSHOTS / screen_root.name)
+
         return fail_count == 0
 
     def get_robot_stem(attempt=0, extra_args=None, browser="headlessfirefox"):
@@ -354,9 +361,6 @@ def get_robot_stem(attempt=0, extra_args=None, browser="headlessfirefox"):
         return stem
 
     def run_robot(attempt=0, extra_args=None):
-        import shutil
-        import subprocess
-
         import lxml.etree as ET
 
         extra_args = extra_args or []
@@ -378,25 +382,19 @@ def run_robot(attempt=0, extra_args=None):
 
         args = [
             *runner,
+            *(["--name", f"{C.PLATFORM[:3]}{C.PY_VERSION}"]),
+            *(["--randomize", "all"]),
+            # variables
+            *(["--variable", f"ATTEMPT:{attempt}"]),
+            *(["--variable", f"OS:{C.PLATFORM}"]),
+            *(["--variable", f"PY:{C.PY_VERSION}"]),
+            *(["--variable", f"ROBOCOV:{B.ROBOCOV}"]),
+            *(["--variable", f"ROOT:{P.ROOT}"]),
+            # files
+            *(["--xunit", out_dir / "xunit.xml"]),
+            *(["--outputdir", out_dir]),
+            # dynamic
             *extra_args,
-            "--name",
-            f"""{C.PLATFORM[:3]}{C.PY_VERSION}""",
-            "--outputdir",
-            out_dir,
-            "--variable",
-            f"OS:{C.PLATFORM}",
-            "--variable",
-            f"PY:{C.PY_VERSION}",
-            "--variable",
-            f"ROOT:{P.ROOT}",
-            "--variable",
-            f"ROBOCOV:{B.ROBOCOV}",
-            "--variable",
-            f"ATTEMPT:{attempt}",
-            "--randomize",
-            "all",
-            "--xunit",
-            out_dir / "xunit.xml",
         ]
 
         if out_dir.exists():
diff --git a/examples/Layers.ipynb b/examples/Layers.ipynb
index 5d42df9..cb3784a 100644
--- a/examples/Layers.ipynb
+++ b/examples/Layers.ipynb
@@ -42,20 +42,26 @@
    "cell_type": "markdown",
    "id": "43e53706-854f-466c-a233-050a430e7f84",
    "metadata": {
-    "jupyterlab-deck": {
-     "layer": "deck",
-     "style": {
-      "bottom": 0,
-      "left": 0,
-      "margin": "auto",
-      "opacity": "0.25",
-      "pointer-events": "none",
-      "right": 0,
-      "top": 0,
-      "width": "50%",
-      "z-index": -1
+    "@deathbeds/jupyterlab-fonts": {
+     "styles": {
+      "": {
+       "body[data-jp-deck-mode='presenting'] &": {
+        "bottom": 0,
+        "left": 0,
+        "margin": "auto",
+        "opacity": "0.25",
+        "pointer-events": "none",
+        "right": 0,
+        "top": 0,
+        "width": "50%",
+        "z-index": -1
+       }
+      }
      }
     },
+    "jupyterlab-deck": {
+     "layer": "deck"
+    },
     "tags": []
    },
    "source": [
@@ -109,15 +115,21 @@
    "cell_type": "markdown",
    "id": "c042f573-cbaf-45ce-a863-29fa3364e683",
    "metadata": {
-    "jupyterlab-deck": {
-     "layer": "fragment",
-     "style": {
-      "right": "0",
-      "top": "60%",
-      "width": "25%",
-      "z-index": 1
+    "@deathbeds/jupyterlab-fonts": {
+     "styles": {
+      "": {
+       "body[data-jp-deck-mode='presenting'] &": {
+        "right": "0",
+        "top": "60%",
+        "width": "25%",
+        "z-index": 1
+       }
+      }
      }
     },
+    "jupyterlab-deck": {
+     "layer": "fragment"
+    },
     "tags": []
    },
    "source": [
@@ -143,15 +155,21 @@
    "cell_type": "markdown",
    "id": "7f0da6ff-9da5-453c-8515-88fabeb03582",
    "metadata": {
-    "jupyterlab-deck": {
-     "layer": "slide",
-     "style": {
-      "right": "0",
-      "top": "30%",
-      "width": "25%",
-      "z-index": 1
+    "@deathbeds/jupyterlab-fonts": {
+     "styles": {
+      "": {
+       "body[data-jp-deck-mode='presenting'] &": {
+        "right": "0",
+        "top": "30%",
+        "width": "25%",
+        "z-index": 1
+       }
+      }
      }
     },
+    "jupyterlab-deck": {
+     "layer": "slide"
+    },
     "tags": []
    },
    "source": [
@@ -178,15 +196,21 @@
    "cell_type": "markdown",
    "id": "f70bb81f-10f8-4b85-b86c-44f58fba188d",
    "metadata": {
-    "jupyterlab-deck": {
-     "layer": "stack",
-     "style": {
-      "right": "0",
-      "top": "5%",
-      "width": "25%",
-      "z-index": 1
+    "@deathbeds/jupyterlab-fonts": {
+     "styles": {
+      "": {
+       "body[data-jp-deck-mode='presenting'] &": {
+        "right": "0",
+        "top": "5%",
+        "width": "25%",
+        "z-index": 1
+       }
+      }
      }
     },
+    "jupyterlab-deck": {
+     "layer": "stack"
+    },
     "tags": []
    },
    "source": [
@@ -222,7 +246,7 @@
    "source": [
     "# Layer Style\n",
     "\n",
-    "> Some key `jupyterlab-deck.style` properties control the **position** of layers:"
+    "> Some key `@deathbeds/jupyterlab-fonts.styles` properties control the **position** of layers:"
    ]
   },
   {
@@ -286,9 +310,13 @@
    "cell_type": "markdown",
    "id": "4770b931-336e-467b-8c74-7ad2169802ff",
    "metadata": {
-    "jupyterlab-deck": {
-     "style": {
-      "zoom": "200%"
+    "@deathbeds/jupyterlab-fonts": {
+     "styles": {
+      "": {
+       "body[data-jp-deck-mode='presenting'] &": {
+        "zoom": "200%"
+       }
+      }
      }
     },
     "slideshow": {
@@ -299,7 +327,7 @@
    "source": [
     "## More Style\n",
     "\n",
-    "> `jupyterlab-deck.style` metadata works with normal slides, too."
+    "> `@deathbeds/jupyterlab-deck.styles` metadata works with normal slides, too."
    ]
   },
   {
@@ -314,6 +342,10 @@
   }
  ],
  "metadata": {
+  "@deathbeds/jupyterlab-fonts": {
+   "styles": {}
+  },
+  "foo": "x",
   "kernelspec": {
    "display_name": "Python 3 (ipykernel)",
    "language": "python",
diff --git a/examples/README.ipynb b/examples/README.ipynb
index 213e690..290b07f 100644
--- a/examples/README.ipynb
+++ b/examples/README.ipynb
@@ -626,15 +626,7 @@
  ],
  "metadata": {
   "@deathbeds/jupyterlab-fonts": {
-   "styles": {
-    ":root": {
-     "--jp-code-font-family": "'Fira Code Bold'",
-     "--jp-code-font-size": "20px",
-     "--jp-content-font-family": "'Sedgwick Ave Display'",
-     "--jp-content-font-size1": "18px"
-    },
-    "@import": "https://tools-static.wmflabs.org/fontcdn/css?0family=Sedgwick+Ave+Display#"
-   }
+   "styles": {}
   },
   "kernelspec": {
    "display_name": "Python 3 (ipykernel)",
diff --git a/js/jupyterlab-deck/package.json b/js/jupyterlab-deck/package.json
index c2c0b1c..6f4f4b6 100644
--- a/js/jupyterlab-deck/package.json
+++ b/js/jupyterlab-deck/package.json
@@ -27,12 +27,19 @@
     "@jupyterlab/ui-components": "3"
   },
   "devDependencies": {
+    "@deathbeds/jupyterlab-fonts": "^2.1.1",
     "@jupyterlab/builder": "^3.4.8"
   },
   "jupyterlab": {
     "extension": "lib/plugin.js",
     "outputDir": "../../src/jupyterlab_deck/_d/share/jupyter/labextensions/@deathbeds/jupyterlab-deck",
     "schemaDir": "schema",
-    "webpackConfig": "./webpack.config.js"
+    "webpackConfig": "./webpack.config.js",
+    "sharedPackages": {
+      "@deathbeds/jupyterlab-fonts": {
+        "bundled": false,
+        "singleton": true
+      }
+    }
   }
 }
diff --git a/js/jupyterlab-deck/schema/plugin.json b/js/jupyterlab-deck/schema/plugin.json
index 97bf064..6dc8834 100644
--- a/js/jupyterlab-deck/schema/plugin.json
+++ b/js/jupyterlab-deck/schema/plugin.json
@@ -2,9 +2,100 @@
   "$schema": "http://json-schema.org/draft-07/schema",
   "properties": {
     "active": {
+      "title": "Activate Deck",
       "type": "boolean",
       "default": false,
       "description": "Whether presentation mode is currently active."
+    },
+    "stylePresets": {
+      "title": "Style Presets",
+      "$ref": "#/definitions/style-presets",
+      "default": {
+        "background": {
+          "scope": "layer",
+          "label": "Move to the background",
+          "styles": {
+            "z-index": "-1"
+          }
+        },
+        "top": {
+          "scope": "layer",
+          "label": "Move to the top",
+          "styles": {
+            "top": "0"
+          }
+        },
+        "right": {
+          "scope": "layer",
+          "label": "Move to the right",
+          "styles": {
+            "right": "0"
+          }
+        },
+        "bottom": {
+          "scope": "layer",
+          "label": "Move to the bottom",
+          "styles": {
+            "bottom": "0"
+          }
+        },
+        "left": {
+          "scope": "layer",
+          "label": "Move to the left",
+          "styles": {
+            "left": "0"
+          }
+        },
+        "fade-out": {
+          "scope": "layer",
+          "label": "Fade out",
+          "styles": {
+            "opacity": "0.125"
+          }
+        },
+        "unclickable": {
+          "scope": "layer",
+          "label": "Unclickable",
+          "styles": {
+            "pointer-events": "none"
+          }
+        }
+      }
+    }
+  },
+  "definitions": {
+    "style-presets": {
+      "type": "object",
+      "description": "Style presets to apply to @deathbeds/jupyterlab-fonts",
+      "additionalItems": {
+        "$ref": "#/definitions/style-preset"
+      }
+    },
+    "style-preset": {
+      "type": "object",
+      "required": [
+        "label",
+        "styles"
+      ],
+      "properties": {
+        "label": {
+          "label": "string",
+          "description": "the human-readable label"
+        },
+        "scope": {
+          "type": "string",
+          "enum": [
+            "layer",
+            "slide",
+            "deck",
+            "any"
+          ]
+        },
+        "styles": {
+          "type": "object",
+          "description": "a JSS-compatible description of a stylesheet: will be nested correctly"
+        }
+      }
     }
   },
   "description": "Configure Deck Settings",
diff --git a/js/jupyterlab-deck/src/manager.ts b/js/jupyterlab-deck/src/manager.ts
index 5912b52..8d7fcfb 100644
--- a/js/jupyterlab-deck/src/manager.ts
+++ b/js/jupyterlab-deck/src/manager.ts
@@ -1,3 +1,4 @@
+import { IFontManager } from '@deathbeds/jupyterlab-fonts';
 import { LabShell } from '@jupyterlab/application';
 import { ISettingRegistry } from '@jupyterlab/settingregistry';
 import { StatusBar } from '@jupyterlab/statusbar';
@@ -22,6 +23,8 @@ import {
   DIRECTION_KEYS,
   CSS,
   COMPOUND_KEYS,
+  IStylePreset,
+  IDeckSettings,
 } from './tokens';
 
 export class DeckManager implements IDeckManager {
@@ -32,6 +35,7 @@ export class DeckManager implements IDeckManager {
     this._statusbar = options.statusbar;
     this._trans = options.translator;
     this._settings = options.settings;
+    this._fonts = options.fonts;
 
     this._shell.activeChanged.connect(this._onActiveWidgetChanged, this);
     this._shell.layoutModified.connect(this._addDeckStylesLater, this);
@@ -45,10 +49,18 @@ export class DeckManager implements IDeckManager {
       .catch(console.warn);
   }
 
+  public get fonts() {
+    return this._fonts;
+  }
+
   public get activeChanged(): ISignal<IDeckManager, void> {
     return this._activeChanged;
   }
 
+  public get stylePresetsChanged(): ISignal<IDeckManager, void> {
+    return this._stylePresetsChanged;
+  }
+
   /**
    * translate a string by message id (usually the en-US string), potentially
    * with positional arguments, starting with %1.
@@ -64,6 +76,15 @@ export class DeckManager implements IDeckManager {
     presenter.activeChanged.connect(() => this._activeChanged.emit(void 0));
   }
 
+  public addStylePreset(preset: IStylePreset): void {
+    this._stylePresets.set(preset.key, preset);
+    this._stylePresetsChanged.emit(void 0);
+  }
+
+  public get stylePresets(): IStylePreset[] {
+    return [...this._stylePresets.values()];
+  }
+
   /** enable deck mode */
   public start = async (): Promise<void> => {
     await this._appStarted;
@@ -308,13 +329,32 @@ export class DeckManager implements IDeckManager {
 
   protected async _onSettingsChanged() {
     const settings = await this._settings;
-    const { composite } = settings;
-    const active = composite['active'] === true;
+    let composite: IDeckSettings;
+    composite = settings.composite as IDeckSettings;
+    const active = composite.active === true;
+
     if (active && !this._active) {
       void this.start();
     } else if (!active && this._active) {
       void this.stop();
     }
+
+    if (composite.stylePresets) {
+      for (let keyPreset of Object.entries(composite.stylePresets)) {
+        let [key, preset] = keyPreset;
+        let { scope, label, styles } = preset;
+        if (!styles || !label) {
+          continue;
+        }
+        this._stylePresets.set(key, {
+          key,
+          scope: scope || 'any',
+          styles,
+          label,
+        });
+        this._stylePresetsChanged.emit(void 0);
+      }
+    }
   }
 
   cacheStyle(node: HTMLElement) {
@@ -373,6 +413,9 @@ export class DeckManager implements IDeckManager {
   protected _statusBarWasEnabled = false;
   protected _styleCache = new Map<HTMLElement, string>();
   protected _trans: TranslationBundle;
+  protected _stylePresets = new Map<string, IStylePreset>();
+  protected _stylePresetsChanged = new Signal<IDeckManager, void>(this);
+  protected _fonts: IFontManager;
 }
 
 export namespace DeckManager {
@@ -383,6 +426,7 @@ export namespace DeckManager {
     statusbar: StatusBar | null;
     settings: Promise<ISettingRegistry.ISettings>;
     appStarted: Promise<void>;
+    fonts: IFontManager;
   }
   export interface IExtent {
     onScreen: number[];
diff --git a/js/jupyterlab-deck/src/notebook/decktools.tsx b/js/jupyterlab-deck/src/notebook/decktools.tsx
index f618340..5edacb3 100644
--- a/js/jupyterlab-deck/src/notebook/decktools.tsx
+++ b/js/jupyterlab-deck/src/notebook/decktools.tsx
@@ -1,3 +1,8 @@
+import {
+  ISettings,
+  PACKAGE_NAME as FONTS_PACKAGE_NAME,
+  Stylist,
+} from '@deathbeds/jupyterlab-fonts';
 import { VDomModel, VDomRenderer } from '@jupyterlab/apputils';
 import { Cell, ICellModel } from '@jupyterlab/cells';
 import { INotebookTools, NotebookTools } from '@jupyterlab/notebook';
@@ -7,16 +12,22 @@ import React from 'react';
 
 import { ICONS } from '../icons';
 import {
-  IDeckManager,
   CSS,
-  LAYER_TITLES,
   ICellDeckMetadata,
+  ID,
+  IDeckManager,
+  IStylePreset,
+  LAYER_SCOPES,
+  LAYER_TITLES,
   META,
   TLayerScope,
-  LAYER_SCOPES,
-  ID,
 } from '../tokens';
 
+const NULL_SELECTOR = '';
+const PRESENTING_CELL = `body[data-jp-deck-mode='presenting'] &`;
+
+type __ = IDeckManager['__'];
+
 export class NotebookDeckTools extends NotebookTools.Tool {
   constructor(options: NotebookDeckTools.IOptions) {
     super();
@@ -56,12 +67,53 @@ export class DeckCellEditor extends VDomRenderer<DeckCellEditor.Model> {
 
     return (
       <div>
+        {this.layerTool(layer, __)}
+        {this.presetTool(__)}
+      </div>
+    );
+  }
+
+  presetTool(__: __) {
+    return (
+      <div className={CSS.toolPreset}>
+        <label
+          title={__('Choose from pre-defined style templates.')}
+          htmlFor={ID.layerSelect}
+        >
+          {__('Slide Style')}
+          <ICONS.deckStart.react tag="span" width={16} />
+        </label>
+        <div className={CSS.selectSplit}>
+          <div className={CSS.selectWrapper}>
+            <select
+              className={CSS.styled}
+              value={this.model.selectedPreset}
+              onChange={this.model.onPresetSelect}
+              id={ID.presetSelect}
+            >
+              {this.presetOptions(__)}
+            </select>
+          </div>
+          <button
+            className={`${CSS.styled} ${CSS.apply}`}
+            onClick={this.model.applyPreset}
+          >
+            {__('Add Style')}
+          </button>
+        </div>
+      </div>
+    );
+  }
+
+  layerTool(layer: TLayerScope | '-', __: __) {
+    return (
+      <div className={CSS.toolLayer}>
         <label
           title={__('Display this cell as an out-of-order layer.')}
           htmlFor={ID.layerSelect}
         >
           {__('Layer')}
-          <ICONS.deckStart.react tag="span" height={16} />
+          <ICONS.deckStart.react tag="span" width={16} />
           <div className={CSS.selectWrapper}>
             <select
               className={CSS.styled}
@@ -77,7 +129,24 @@ export class DeckCellEditor extends VDomRenderer<DeckCellEditor.Model> {
     );
   }
 
-  layerOptions(__: any): JSX.Element[] {
+  presetOptions(__: __): JSX.Element[] {
+    // todo: get options from... elsewhere
+    const presetOptions: JSX.Element[] = [
+      <option key="-" value="">
+        -
+      </option>,
+    ];
+    for (const preset of this.model.stylePresets) {
+      presetOptions.push(
+        <option value={preset.key} key={preset.key}>
+          {__(preset.label)}
+        </option>
+      );
+    }
+    return presetOptions;
+  }
+
+  layerOptions(__: __): JSX.Element[] {
     const layerOptions: JSX.Element[] = [];
 
     for (const [layerValue, layerTitle] of Object.entries(LAYER_TITLES)) {
@@ -96,7 +165,9 @@ export namespace DeckCellEditor {
     constructor(options: NotebookDeckTools.IOptions) {
       super();
       this._manager = options.manager;
+      this._notebookTools = options.notebookTools;
     }
+
     update() {
       this._activeMeta =
         (this._activeCell?.model.metadata.get(META) as any as ICellDeckMetadata) ||
@@ -121,6 +192,68 @@ export namespace DeckCellEditor {
       }
     };
 
+    applyPreset = () => {
+      if (!this._activeCell || !this._selectedPreset) {
+        return;
+      }
+      let meta = {
+        ...((this._activeCell.model.metadata.get(FONTS_PACKAGE_NAME) ||
+          JSONExt.emptyObject) as ISettings),
+      };
+      for (const preset of this._manager.stylePresets) {
+        if (preset.key != this._selectedPreset) {
+          continue;
+        }
+        if (!meta['styles']) {
+          meta['styles'] = {};
+        }
+
+        let metaStyles = meta['styles'] as any;
+        if (!metaStyles[NULL_SELECTOR]) {
+          metaStyles[NULL_SELECTOR] = {};
+        }
+
+        let metaNull = metaStyles[NULL_SELECTOR] as any;
+
+        if (!metaNull[PRESENTING_CELL]) {
+          metaNull[PRESENTING_CELL] = {};
+        }
+
+        let presenting = metaNull[PRESENTING_CELL];
+        for (let [key, value] of Object.entries(preset.styles)) {
+          presenting[key] = value;
+        }
+        this._activeCell.model.metadata.delete(FONTS_PACKAGE_NAME);
+        this._activeCell.model.metadata.set(FONTS_PACKAGE_NAME, meta as any);
+        this.forceStyle();
+        this._notebookTools.update();
+        return;
+      }
+    };
+
+    forceStyle() {
+      let panel = this._notebookTools.activeNotebookPanel;
+      if (!panel) {
+        return;
+      }
+      let stylist = (this._manager.fonts as any)._stylist as Stylist;
+      let meta = panel.model?.metadata.get(FONTS_PACKAGE_NAME) || JSONExt.emptyObject;
+      stylist.stylesheet(meta as ISettings, panel);
+    }
+
+    get selectedPreset() {
+      return this._selectedPreset;
+    }
+
+    get stylePresets(): IStylePreset[] {
+      return this._manager.stylePresets;
+    }
+
+    onPresetSelect = (change: React.ChangeEvent<HTMLSelectElement>) => {
+      this._selectedPreset = change.target.value;
+      this.stateChanged.emit(void 0);
+    };
+
     protected _setDeckMetadata(newMeta: ICellDeckMetadata, cell: Cell<ICellModel>) {
       if (Object.keys(newMeta).length) {
         cell.model.metadata.set(META, newMeta as ReadonlyPartialJSONObject);
@@ -146,5 +279,7 @@ export namespace DeckCellEditor {
     private _manager: IDeckManager;
     private _activeCell: Cell<ICellModel> | null = null;
     private _activeMeta: ICellDeckMetadata | null = null;
+    private _selectedPreset: string = '';
+    private _notebookTools: INotebookTools;
   }
 }
diff --git a/js/jupyterlab-deck/src/notebook/presenter.ts b/js/jupyterlab-deck/src/notebook/presenter.ts
index 06e5cd6..8c277d5 100644
--- a/js/jupyterlab-deck/src/notebook/presenter.ts
+++ b/js/jupyterlab-deck/src/notebook/presenter.ts
@@ -31,7 +31,6 @@ import {
 import { NotebookDeckTools } from './decktools';
 
 const emptyMap = Object.freeze(new Map());
-const FIXED = { position: 'fixed' };
 
 /** An presenter for working with notebooks */
 export class NotebookPresenter implements IPresenter<NotebookPanel> {
@@ -148,21 +147,32 @@ export class NotebookPresenter implements IPresenter<NotebookPanel> {
   }
 
   public canGo(panel: NotebookPanel): Partial<TCanGoDirection> {
-    const { activeCellIndex } = panel.content;
+    let { activeCellIndex, activeCell } = panel.content;
     const notebookModel = panel.content.model;
+    let activeExtent: NotebookPresenter.IExtent | null = null;
     if (notebookModel) {
       const extents = this._getExtents(notebookModel);
-      const activeExtent = extents.get(activeCellIndex);
-      if (activeExtent) {
-        const { up, down, forward, back } = activeExtent;
-        return {
-          up: up != null,
-          down: down != null,
-          forward: forward != null,
-          back: back != null,
-        };
+      activeExtent = extents.get(activeCellIndex) || null;
+      if (!activeExtent && activeCell) {
+        let meta = this._getCellDeckMetadata(activeCell.model);
+        if (meta.layer) {
+          while (!activeExtent && activeCellIndex) {
+            activeCellIndex--;
+            activeExtent = extents.get(activeCellIndex) || null;
+          }
+        }
       }
     }
+
+    if (activeExtent) {
+      const { up, down, forward, back } = activeExtent;
+      return {
+        up: up != null,
+        down: down != null,
+        forward: forward != null,
+        back: back != null,
+      };
+    }
     return JSONExt.emptyObject;
   }
 
@@ -172,14 +182,26 @@ export class NotebookPresenter implements IPresenter<NotebookPanel> {
     direction: TDirection,
     alternate?: TDirection
   ): Promise<void> => {
-    const { activeCellIndex } = panel.content;
     const notebookModel = panel.content.model;
     /* istanbul ignore if */
     if (!notebookModel) {
       return;
     }
+    let { activeCellIndex, activeCell } = panel.content;
+
     const extents = this._getExtents(notebookModel);
-    const activeExtent = extents.get(activeCellIndex);
+    let activeExtent = extents.get(activeCellIndex);
+
+    if (!activeExtent && activeCell) {
+      let meta = this._getCellDeckMetadata(activeCell.model);
+      if (!meta.layer && direction === 'up') {
+        return;
+      }
+      while (!activeExtent && activeCellIndex) {
+        activeCellIndex--;
+        activeExtent = extents.get(activeCellIndex);
+      }
+    }
 
     const fromExtent = activeExtent && activeExtent[direction];
     const fromExtentAlternate = alternate && activeExtent && activeExtent[alternate];
@@ -191,7 +213,7 @@ export class NotebookPresenter implements IPresenter<NotebookPanel> {
     } else {
       console.warn(
         EMOJI,
-        this._manager.__(`Can go "%1" from cell %2`, direction, `${activeCellIndex}`)
+        this._manager.__(`Cannot go "%1" from cell %2`, direction, `${activeCellIndex}`)
       );
     }
   };
@@ -221,22 +243,38 @@ export class NotebookPresenter implements IPresenter<NotebookPanel> {
     const extents = this._getExtents(notebookModel);
     const layers = this._getLayers(notebookModel, extents);
 
-    const { activeCellIndex, activeCell } = notebook;
+    let { activeCellIndex } = notebook;
 
     let cell = notebookModel.cells.get(activeCellIndex);
 
+    let layerIndex: number | null = null;
+
     if (cell) {
       let meta = this._getCellDeckMetadata(cell);
       if (meta && meta.layer) {
-        return;
+        layerIndex = activeCellIndex;
       }
     }
 
     let activeExtent = extents.get(activeCellIndex);
 
     if (!activeExtent) {
-      let offset = this._previousActiveCellIndex > activeCellIndex ? -1 : 1;
-      notebook.activeCellIndex = activeCellIndex + offset;
+      if (layerIndex == null) {
+        let offset = this._previousActiveCellIndex > activeCellIndex ? -1 : 1;
+        notebook.activeCellIndex = activeCellIndex + offset;
+        return;
+      } else {
+        while (activeCellIndex) {
+          activeCellIndex--;
+          activeExtent = extents.get(activeCellIndex);
+          if (activeExtent) {
+            break;
+          }
+        }
+      }
+    }
+
+    if (!activeExtent) {
       return;
     }
 
@@ -248,8 +286,6 @@ export class NotebookPresenter implements IPresenter<NotebookPanel> {
 
     idx = -1;
 
-    let meta: ICellDeckMetadata;
-    let node: HTMLElement;
     for (const cell of notebook.widgets) {
       idx++;
 
@@ -271,30 +307,12 @@ export class NotebookPresenter implements IPresenter<NotebookPanel> {
           cell.removeClass(CSS.onScreen);
         }
       }
-
-      meta = (cell.model.metadata.get(META) || {}) as any;
-      node = cell.node;
-
-      let { layer, style } = meta;
-
-      if (layer) {
-        style = { ...style, ...FIXED };
-      }
-
-      if (style) {
-        for (let prop in style) {
-          if (style[prop] != null) {
-            node.style.setProperty(prop, `${style[prop]}`);
-          }
-        }
-      } else {
-        node.setAttribute('style', '');
-      }
     }
 
-    if (activeCell) {
-      ElementExt.scrollIntoViewIfNeeded(notebook.node, activeCell.node);
-    }
+    ElementExt.scrollIntoViewIfNeeded(
+      notebook.node,
+      notebook.widgets[activeCellIndex].node
+    );
     this._activeChanged.emit(void 0);
   }
 
diff --git a/js/jupyterlab-deck/src/plugin.ts b/js/jupyterlab-deck/src/plugin.ts
index 72382da..b834c2d 100644
--- a/js/jupyterlab-deck/src/plugin.ts
+++ b/js/jupyterlab-deck/src/plugin.ts
@@ -1,3 +1,4 @@
+import { IFontManager } from '@deathbeds/jupyterlab-fonts';
 import {
   JupyterFrontEnd,
   JupyterFrontEndPlugin,
@@ -19,7 +20,7 @@ import '../style/index.css';
 
 const plugin: JupyterFrontEndPlugin<IDeckManager> = {
   id: `${NS}:plugin`,
-  requires: [ITranslator, ILabShell, ISettingRegistry, ILayoutRestorer],
+  requires: [ITranslator, ILabShell, ISettingRegistry, ILayoutRestorer, IFontManager],
   optional: [ICommandPalette, IStatusBar],
   provides: IDeckManager,
   autoStart: true,
@@ -29,6 +30,7 @@ const plugin: JupyterFrontEndPlugin<IDeckManager> = {
     shell: ILabShell,
     settings: ISettingRegistry,
     restorer: ILayoutRestorer,
+    fonts: IFontManager,
     palette?: ICommandPalette,
     statusbar?: IStatusBar
   ) => {
@@ -42,6 +44,7 @@ const plugin: JupyterFrontEndPlugin<IDeckManager> = {
       shell,
       translator: (translator || /* istanbul ignore next */ nullTranslator).load(NS),
       statusbar: theStatusBar,
+      fonts,
       settings: settings.load(PLUGIN_ID),
       appStarted: Promise.all([app.started, restorer.restored]).then(() => void 0),
     });
diff --git a/js/jupyterlab-deck/src/remote.tsx b/js/jupyterlab-deck/src/remote.tsx
index 5bc87c7..fb9232f 100644
--- a/js/jupyterlab-deck/src/remote.tsx
+++ b/js/jupyterlab-deck/src/remote.tsx
@@ -18,6 +18,13 @@ export class DeckRemote extends VDomRenderer<DeckRemote.Model> {
     this.addClass(CSS.remote);
   }
 
+  dispose() {
+    super.dispose();
+    if (this.model) {
+      this.model.dispose();
+    }
+  }
+
   protected render(): JSX.Element {
     const { manager, canGo } = this.model;
 
diff --git a/js/jupyterlab-deck/src/tokens.ts b/js/jupyterlab-deck/src/tokens.ts
index ac35c65..99cb509 100644
--- a/js/jupyterlab-deck/src/tokens.ts
+++ b/js/jupyterlab-deck/src/tokens.ts
@@ -1,3 +1,4 @@
+import { IFontManager, IStyles } from '@deathbeds/jupyterlab-fonts';
 import { Token } from '@lumino/coreutils';
 import { ISignal } from '@lumino/signaling';
 import { Widget } from '@lumino/widgets';
@@ -22,8 +23,14 @@ export interface IDeckManager {
   cacheStyle(node: HTMLElement): void;
   uncacheStyle(node: HTMLElement): void;
   addPresenter(presenter: IPresenter<any>): void;
-  activeChanged: ISignal<IDeckManager, void>;
+  addStylePreset(preset: IStylePreset): void;
+  stylePresets: IStylePreset[];
   activeWidget: Widget | null;
+  // signals
+  activeChanged: ISignal<IDeckManager, void>;
+  stylePresetsChanged: ISignal<IDeckManager, void>;
+  // re-hosted
+  fonts: IFontManager;
 }
 
 export const IDeckManager = new Token<IDeckManager>(PLUGIN_ID);
@@ -57,6 +64,8 @@ export namespace CSS {
   export const presenting = `[data-jp-deck-mode='${DATA.presenting}']`;
   export const stop = 'jp-deck-mod-stop';
   export const metaTool = 'jp-Deck-Metadata';
+  export const selectSplit = 'jp-Deck-SelectSplit';
+  export const apply = 'jp-deck-mod-apply';
   // lab
   export const disabled = 'jp-mod-disabled';
   export const icon = 'jp-icon3';
@@ -65,10 +74,15 @@ export namespace CSS {
   export const iconWarn = 'jp-icon-warn0';
   export const selectWrapper = 'jp-select-wrapper';
   export const styled = 'jp-mod-styled';
+  export const accept = 'jp-mod-accept';
+  // tools
+  export const toolLayer = 'jp-Deck-Tool-layer';
+  export const toolPreset = 'jp-Deck-Tool-preset';
 }
 
 export namespace ID {
   export const layerSelect = 'id-jp-decktools-select-layer';
+  export const presetSelect = 'id-jp-decktools-select-preset';
 }
 
 export const EMOJI = '🃏';
@@ -146,5 +160,18 @@ export const LAYER_TITLES: TSelectLabels<TLayerScope | '-'> = {
 /** Expected cell metadata in the `jupyterlab-deck` namespace */
 export interface ICellDeckMetadata {
   layer?: TLayerScope;
-  style?: Record<string, string | number>;
+}
+
+export interface IStylePreset {
+  key: string;
+  scope: 'layer' | 'slide' | 'deck' | 'any';
+  label: string;
+  styles: IStyles;
+}
+
+export interface IDeckSettings {
+  active?: boolean;
+  stylePresets?: {
+    [key: string]: Partial<IStylePreset>;
+  };
 }
diff --git a/js/jupyterlab-deck/style/decktools.css b/js/jupyterlab-deck/style/decktools.css
new file mode 100644
index 0000000..0088052
--- /dev/null
+++ b/js/jupyterlab-deck/style/decktools.css
@@ -0,0 +1,14 @@
+.jp-Deck-SelectSplit {
+  display: flex;
+  flex-direction: row;
+}
+
+.jp-Deck-SelectSplit .jp-select-wrapper {
+  flex: 1;
+  margin: 0;
+  height: unset;
+}
+
+.jp-Deck-SelectSplit button {
+  flex-shrink: 1;
+}
diff --git a/js/jupyterlab-deck/style/index.css b/js/jupyterlab-deck/style/index.css
index 941efa6..19faca8 100644
--- a/js/jupyterlab-deck/style/index.css
+++ b/js/jupyterlab-deck/style/index.css
@@ -2,3 +2,4 @@
 @import './notebook.css';
 @import './shell.css';
 @import './remote.css';
+@import './decktools.css';
diff --git a/js/jupyterlab-deck/style/notebook.css b/js/jupyterlab-deck/style/notebook.css
index 72c2d7b..fc0ecf7 100644
--- a/js/jupyterlab-deck/style/notebook.css
+++ b/js/jupyterlab-deck/style/notebook.css
@@ -74,6 +74,10 @@
   transition: opacity 0.1s;
 }
 
+.jp-Deck .jp-deck-mod-layer {
+  position: fixed;
+}
+
 /** markdown tweaks **/
 .jp-Deck .jp-MarkdownOutput {
   border: 0;
diff --git a/package.json b/package.json
index b1969f1..6419b8a 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
     "eslint-plugin-import": "^2.26.0",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-react": "^7.31.8",
-    "lerna": "^5.5.2",
+    "lerna": "^6.0.1",
     "nyc": "^15.1.0",
     "prettier": "^2.7.1",
     "prettier-package-json": "^2.7.0",
diff --git a/pages-lite/README.ipynb b/pages-lite/README.ipynb
index a88aa01..4ea21d9 100644
--- a/pages-lite/README.ipynb
+++ b/pages-lite/README.ipynb
@@ -51,13 +51,96 @@
         "tags": [],
         "trusted": true
       },
-      "execution_count": 12,
+      "execution_count": 95,
       "outputs": [
         {
           "output_type": "display_data",
           "data": {
             "text/plain": "<IPython.core.display.HTML object>",
-            "text/html": "<iframe src=\"./nyc/robot/log.html\" style=\"width: 99%; height: 70vh; overflow-y: hidden;\">\n"
+            "text/html": "<iframe src=\"./robot/log.html\" style=\"width: 99%; height: 70vh; overflow-y: hidden;\">\n"
+          },
+          "metadata": {}
+        }
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "source": "## Robot Screenshots",
+      "metadata": {
+        "slideshow": {
+          "slide_type": "slide"
+        },
+        "tags": []
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": "%pip install ipywidgets\nimport ipywidgets, pathlib",
+      "metadata": {
+        "tags": [],
+        "jupyter": {
+          "source_hidden": true
+        },
+        "trusted": true
+      },
+      "execution_count": 96,
+      "outputs": []
+    },
+    {
+      "cell_type": "code",
+      "source": "screens = ipywidgets.SelectionRangeSlider(options=sorted(pathlib.Path(\"robot/screenshots\").rglob(\"*.png\")), layout=dict(width=\"80%\"))\nscreens.value = [screens.options[0], screens.options[0]]\nhtml = ipywidgets.HTML(layout=dict(height=\"60vh\", max_height=\"60vh\"))",
+      "metadata": {
+        "tags": [],
+        "jupyter": {
+          "source_hidden": true
+        },
+        "trusted": true
+      },
+      "execution_count": 97,
+      "outputs": []
+    },
+    {
+      "cell_type": "code",
+      "source": "def screens_changed(*a):\n    if not screens.value and len(screens.value) == 2: return\n    mm = list(map(screens.options.index, screens.value))\n    html.value = \" \".join([\n        f\"\"\"<a href=\"../files/{s}\"><img src=\"../files/{s}\" width=\"200\" /></a>\"\"\" for s in screens.options[mm[0]:mm[1]]\n    ])\nscreens_changed()\nscreens.observe(screens_changed)",
+      "metadata": {
+        "tags": [],
+        "jupyter": {
+          "source_hidden": true
+        },
+        "trusted": true
+      },
+      "execution_count": 98,
+      "outputs": []
+    },
+    {
+      "cell_type": "code",
+      "source": "display(screens,html)",
+      "metadata": {
+        "trusted": true
+      },
+      "execution_count": 99,
+      "outputs": [
+        {
+          "output_type": "display_data",
+          "data": {
+            "text/plain": "SelectionRangeSlider(index=(0, 0), layout=Layout(width='80%'), options=(PosixPath('robot/screenshots/li_1/lab/…",
+            "application/vnd.jupyter.widget-view+json": {
+              "version_major": 2,
+              "version_minor": 0,
+              "model_id": "a6afaa3ace6c44f0be12133c37476994"
+            }
+          },
+          "metadata": {}
+        },
+        {
+          "output_type": "display_data",
+          "data": {
+            "text/plain": "HTML(value='', layout=Layout(height='60vh', max_height='60vh'))",
+            "application/vnd.jupyter.widget-view+json": {
+              "version_major": 2,
+              "version_minor": 0,
+              "model_id": "c8c5e270bb99466e83d2d094d9d45c98"
+            }
           },
           "metadata": {}
         }
@@ -83,7 +166,7 @@
         "tags": [],
         "trusted": true
       },
-      "execution_count": 11,
+      "execution_count": 100,
       "outputs": [
         {
           "output_type": "display_data",
@@ -115,7 +198,7 @@
         "tags": [],
         "trusted": true
       },
-      "execution_count": 9,
+      "execution_count": 101,
       "outputs": [
         {
           "output_type": "display_data",
@@ -147,7 +230,7 @@
         "tags": [],
         "trusted": true
       },
-      "execution_count": 13,
+      "execution_count": 102,
       "outputs": [
         {
           "output_type": "display_data",
@@ -160,4 +243,4 @@
       ]
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 8eb02c7..eee3d64 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -22,8 +22,8 @@ classifiers = [
 requires-python = ">=3.7"
 dynamic = ["description"]
 dependencies = [
-    # likely need to pin less tightly
-    "jupyterlab >=3,<4",
+    "jupyterlab >=3.3,<4",
+    "jupyterlab-fonts >=2.1.1"
 ]
 
 [project.urls]
diff --git a/yarn.lock b/yarn.lock
index 9b4880b..50298bd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -155,7 +155,7 @@
   resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz#03c4339d2b8971eb3beca5252bafd9b9f79db3dc"
   integrity sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==
 
-"@babel/runtime@^7.1.2":
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.3":
   version "7.19.4"
   resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78"
   integrity sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==
@@ -257,6 +257,17 @@
     "@jupyterlab/statusbar" "3"
     "@jupyterlab/ui-components" "3"
 
+"@deathbeds/jupyterlab-fonts@^2.1.1":
+  version "2.1.1"
+  resolved "https://registry.npmjs.org/@deathbeds/jupyterlab-fonts/-/jupyterlab-fonts-2.1.1.tgz#651303e2ea8624e46daee351ce461f49ccb9a551"
+  integrity sha512-a45PK5mKycxiQY6Pl2uQ/Xhafup/6cj9+Bae9J/HJVZKs5j5JcuuBVlwZUo4BgHMFA2DTNvBHtDtbULUz4k+rA==
+  dependencies:
+    "@jupyterlab/application" "3"
+    "@jupyterlab/mainmenu" "3"
+    "@jupyterlab/notebook" "3"
+    jss "^10.9.2"
+    jss-preset-default "^10.9.2"
+
 "@discoveryjs/json-ext@^0.5.0":
   version "0.5.7"
   resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
@@ -718,6 +729,20 @@
     "@lumino/widgets" "^1.33.0"
     react "^17.0.1"
 
+"@jupyterlab/mainmenu@3":
+  version "3.4.8"
+  resolved "https://registry.npmjs.org/@jupyterlab/mainmenu/-/mainmenu-3.4.8.tgz#dfa3bcffacaaf54c8b982836a9b5647eeb33fb06"
+  integrity sha512-rz6nJnwXI2SktjuaJuoXfiBURSG77a/nrmpCDZ+bWunV7vyjb6jNsA7Xuq32aWc/tlWcGBYamtWbUlVHPPm4jQ==
+  dependencies:
+    "@jupyterlab/apputils" "^3.4.8"
+    "@jupyterlab/services" "^6.4.8"
+    "@jupyterlab/translation" "^3.4.8"
+    "@jupyterlab/ui-components" "^3.4.8"
+    "@lumino/algorithm" "^1.9.0"
+    "@lumino/commands" "^1.19.0"
+    "@lumino/coreutils" "^1.11.0"
+    "@lumino/widgets" "^1.33.0"
+
 "@jupyterlab/nbformat@^3.4.8":
   version "3.4.8"
   resolved "https://registry.npmjs.org/@jupyterlab/nbformat/-/nbformat-3.4.8.tgz#8552c9d32e8f04bd3e9be468be57662f0c5307c2"
@@ -921,39 +946,39 @@
     react-dom "^17.0.1"
     typestyle "^2.0.4"
 
-"@lerna/add@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/add/-/add-5.6.2.tgz#d0e25fd4900b6f8a9548f940cc016ce8a3e2d2ba"
-  integrity sha512-NHrm7kYiqP+EviguY7/NltJ3G9vGmJW6v2BASUOhP9FZDhYbq3O+rCDlFdoVRNtcyrSg90rZFMOWHph4KOoCQQ==
-  dependencies:
-    "@lerna/bootstrap" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/filter-options" "5.6.2"
-    "@lerna/npm-conf" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+"@lerna/add@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/add/-/add-6.0.1.tgz#6d71084fe7918c96c909bebdc5c27ed6006e09d6"
+  integrity sha512-cCQIlMODhi3KYyTDOp2WWL4Kj2dKK+MmCiaSf+USrbSWPVVXQGn5Eb11XOMUfYYq3Ula75sWL2urtYwuu8IbmA==
+  dependencies:
+    "@lerna/bootstrap" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/filter-options" "6.0.1"
+    "@lerna/npm-conf" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     dedent "^0.7.0"
     npm-package-arg "8.1.1"
     p-map "^4.0.0"
     pacote "^13.6.1"
     semver "^7.3.4"
 
-"@lerna/bootstrap@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-5.6.2.tgz#a0f015ae7c30189a3064c0d5940134010ece635e"
-  integrity sha512-S2fMOEXbef7nrybQhzBywIGSLhuiQ5huPp1sU+v9Y6XEBsy/2IA+lb0gsZosvPqlRfMtiaFstL+QunaBhlWECA==
-  dependencies:
-    "@lerna/command" "5.6.2"
-    "@lerna/filter-options" "5.6.2"
-    "@lerna/has-npm-version" "5.6.2"
-    "@lerna/npm-install" "5.6.2"
-    "@lerna/package-graph" "5.6.2"
-    "@lerna/pulse-till-done" "5.6.2"
-    "@lerna/rimraf-dir" "5.6.2"
-    "@lerna/run-lifecycle" "5.6.2"
-    "@lerna/run-topologically" "5.6.2"
-    "@lerna/symlink-binary" "5.6.2"
-    "@lerna/symlink-dependencies" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+"@lerna/bootstrap@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-6.0.1.tgz#2af0b790b9ce426b78f12543159c8506d77afc28"
+  integrity sha512-a3DWchHFOiRmDN24VTdmTxKvAqw6Msp8pDCWXq4rgOQSFxqyYECd8BYvmy8dTW6LcC4EG0HqTGRguuEaKCasOw==
+  dependencies:
+    "@lerna/command" "6.0.1"
+    "@lerna/filter-options" "6.0.1"
+    "@lerna/has-npm-version" "6.0.1"
+    "@lerna/npm-install" "6.0.1"
+    "@lerna/package-graph" "6.0.1"
+    "@lerna/pulse-till-done" "6.0.1"
+    "@lerna/rimraf-dir" "6.0.1"
+    "@lerna/run-lifecycle" "6.0.1"
+    "@lerna/run-topologically" "6.0.1"
+    "@lerna/symlink-binary" "6.0.1"
+    "@lerna/symlink-dependencies" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     "@npmcli/arborist" "5.3.0"
     dedent "^0.7.0"
     get-port "^5.1.1"
@@ -965,100 +990,100 @@
     p-waterfall "^2.1.1"
     semver "^7.3.4"
 
-"@lerna/changed@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/changed/-/changed-5.6.2.tgz#96a647ed202d8146b2077bf13a682466e8607f9a"
-  integrity sha512-uUgrkdj1eYJHQGsXXlpH5oEAfu3x0qzeTjgvpdNrxHEdQWi7zWiW59hRadmiImc14uJJYIwVK5q/QLugrsdGFQ==
+"@lerna/changed@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/changed/-/changed-6.0.1.tgz#58614a0c65bfab77fefd142d5edc8282e057ea83"
+  integrity sha512-b0KzqpNv25ZxH9M/7jtDQaXWUBhVzBVJ8DQ4PjjeoulOCQ+mA9tNQr8UVmeU1UZiaNtNz6Hcy55vyvVvNe07VA==
   dependencies:
-    "@lerna/collect-updates" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/listable" "5.6.2"
-    "@lerna/output" "5.6.2"
+    "@lerna/collect-updates" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/listable" "6.0.1"
+    "@lerna/output" "6.0.1"
 
-"@lerna/check-working-tree@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-5.6.2.tgz#dd03b0c3fe9f141c31c0c47a9a0162ee9c0f6c28"
-  integrity sha512-6Vf3IB6p+iNIubwVgr8A/KOmGh5xb4SyRmhFtAVqe33yWl2p3yc+mU5nGoz4ET3JLF1T9MhsePj0hNt6qyOTLQ==
+"@lerna/check-working-tree@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-6.0.1.tgz#ad71d53941b5c85523499b283e5f44b52eca6276"
+  integrity sha512-9Ti1EuE3IiJUvvAtFk+Xr9Uw6KehT78ghnI4f/hi4uew5q0Mf2+DMaBNexbhOTpRFBeIq4ucDFhiN091pNkUNw==
   dependencies:
-    "@lerna/collect-uncommitted" "5.6.2"
-    "@lerna/describe-ref" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/collect-uncommitted" "6.0.1"
+    "@lerna/describe-ref" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
 
-"@lerna/child-process@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/child-process/-/child-process-5.6.2.tgz#4adbd09ff5a8e43b9471f1a987ae65a7d669421b"
-  integrity sha512-QIOQ3jIbWdduHd5892fbo3u7/dQgbhzEBB7cvf+Ys/iCPP8UQrBECi1lfRgA4kcTKC2MyMz0SoyXZz/lFcXc3A==
+"@lerna/child-process@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/child-process/-/child-process-6.0.1.tgz#2141f643a4ed7d38fa9270a80403467a353a3b39"
+  integrity sha512-5smM8Or/RQkHysNFrUYdrCYlhpr3buNpCYU7T2DPYzOWRPm+X5rCvt/dDOcS3UgYT2jEyS86S5Y7pK2X7eXtmg==
   dependencies:
     chalk "^4.1.0"
     execa "^5.0.0"
     strong-log-transformer "^2.1.0"
 
-"@lerna/clean@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/clean/-/clean-5.6.2.tgz#9611adf3e3035731af2b71aabeb850f7d16fc27d"
-  integrity sha512-A7j8r0Hk2pGyLUyaCmx4keNHen1L/KdcOjb4nR6X8GtTJR5AeA47a8rRKOCz9wwdyMPlo2Dau7d3RV9viv7a5g==
-  dependencies:
-    "@lerna/command" "5.6.2"
-    "@lerna/filter-options" "5.6.2"
-    "@lerna/prompt" "5.6.2"
-    "@lerna/pulse-till-done" "5.6.2"
-    "@lerna/rimraf-dir" "5.6.2"
+"@lerna/clean@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/clean/-/clean-6.0.1.tgz#e59f94140e577cbb66f76f78794b97778f78a246"
+  integrity sha512-ZaWPzzYNkJM7Ib2GWPLSELVBf5nRCGOGBtR9DSLKAore0Me876JLgi4h2R+Y2PVyCvT1kmoQKAclnjxdZbCONA==
+  dependencies:
+    "@lerna/command" "6.0.1"
+    "@lerna/filter-options" "6.0.1"
+    "@lerna/prompt" "6.0.1"
+    "@lerna/pulse-till-done" "6.0.1"
+    "@lerna/rimraf-dir" "6.0.1"
     p-map "^4.0.0"
     p-map-series "^2.1.0"
     p-waterfall "^2.1.1"
 
-"@lerna/cli@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/cli/-/cli-5.6.2.tgz#87a3dea0f066fa4b01c38ab191f316885dfe9fcd"
-  integrity sha512-w0NRIEqDOmYKlA5t0iyqx0hbY7zcozvApmfvwF0lhkuhf3k6LRAFSamtimGQWicC779a7J2NXw4ASuBV47Fs1Q==
+"@lerna/cli@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/cli/-/cli-6.0.1.tgz#8a92386702cff815f36104792ad5dc14f11a61a8"
+  integrity sha512-AuAnUXkBGdts/rmHltrkZucYy11OwYPb/4HM3zxLeq4O30w2ocZIytkOtSkuVKOMPWBZR8b37fNuZBzvxe5OmA==
   dependencies:
-    "@lerna/global-options" "5.6.2"
+    "@lerna/global-options" "6.0.1"
     dedent "^0.7.0"
     npmlog "^6.0.2"
     yargs "^16.2.0"
 
-"@lerna/collect-uncommitted@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-5.6.2.tgz#8f62d5a57c7800e9f5278897c7b254c1e3d425fe"
-  integrity sha512-i0jhxpypyOsW2PpPwIw4xg6EPh7/N3YuiI6P2yL7PynZ8nOv8DkIdoyMkhUP4gALjBfckH8Bj94eIaKMviqW4w==
+"@lerna/collect-uncommitted@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-6.0.1.tgz#b93f5acfa9c63fffe41bfaaac02a0efad9180b00"
+  integrity sha512-qPqwmIlSlf8XBJnqMc+6pz6qXQ0Pfjil70FB2IPvoWbfrLvMI6K3I/AXeub9X5fj5HYqNs1XtwhWHJcMFpJddw==
   dependencies:
-    "@lerna/child-process" "5.6.2"
+    "@lerna/child-process" "6.0.1"
     chalk "^4.1.0"
     npmlog "^6.0.2"
 
-"@lerna/collect-updates@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-5.6.2.tgz#7dc9df48183ef35a975154182d338c64de76104f"
-  integrity sha512-DdTK13X6PIsh9HINiMniFeiivAizR/1FBB+hDVe6tOhsXFBfjHMw1xZhXlE+mYIoFmDm1UFK7zvQSexoaxRqFA==
+"@lerna/collect-updates@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-6.0.1.tgz#7b4be193ee51a72ccedc20acf845fe32fdee9ee2"
+  integrity sha512-OwRcLqD1N5znlZM/Ctf031RDkodHVO62byiD35AbHGoGM2EI2TSYyIbqnJ8QsQJMB05/KhIBndL8Mpcdle7/rg==
   dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/describe-ref" "5.6.2"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/describe-ref" "6.0.1"
     minimatch "^3.0.4"
     npmlog "^6.0.2"
     slash "^3.0.0"
 
-"@lerna/command@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/command/-/command-5.6.2.tgz#6cbb42b63c40a33565a7d39302d0e171e8e0f5b6"
-  integrity sha512-eLVGI9TmxcaGt1M7TXGhhBZoeWOtOedMiH7NuCGHtL6TMJ9k+SCExyx+KpNmE6ImyNOzws6EvYLPLjftiqmoaA==
-  dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/package-graph" "5.6.2"
-    "@lerna/project" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
-    "@lerna/write-log-file" "5.6.2"
+"@lerna/command@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/command/-/command-6.0.1.tgz#a429e724237bc3c4a735e8eaef9816f2203cb7dc"
+  integrity sha512-V9w8M7pMU7KztxaL0+fetTSQYTa12bhTl86ll9VjlgYZ5qUAXk9E42Y8hbVThyYtHEhkRnIMinkWsmH/9YKU/A==
+  dependencies:
+    "@lerna/child-process" "6.0.1"
+    "@lerna/package-graph" "6.0.1"
+    "@lerna/project" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
+    "@lerna/write-log-file" "6.0.1"
     clone-deep "^4.0.1"
     dedent "^0.7.0"
     execa "^5.0.0"
     is-ci "^2.0.0"
     npmlog "^6.0.2"
 
-"@lerna/conventional-commits@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-5.6.2.tgz#23f1a86ab79e48609c98a572eb59a705d7f0512f"
-  integrity sha512-fPrJpYJhxCgY2uyOCTcAAC6+T6lUAtpEGxLbjWHWTb13oKKEygp9THoFpe6SbAD0fYMb3jeZCZCqNofM62rmuA==
+"@lerna/conventional-commits@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-6.0.1.tgz#72dd55aadc7c20eca5af3d03cdcfb613964dafc4"
+  integrity sha512-6oIGEZKy1GpooW28C0aEDkZ/rVkqpX44knP8Jyb5//1054QogqPhGC5q6J0lZxyhun8dQkpF6XTHlIintI8xow==
   dependencies:
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/validation-error" "6.0.1"
     conventional-changelog-angular "^5.0.12"
     conventional-changelog-core "^4.2.4"
     conventional-recommended-bump "^6.1.0"
@@ -1069,24 +1094,24 @@
     pify "^5.0.0"
     semver "^7.3.4"
 
-"@lerna/create-symlink@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-5.6.2.tgz#9bd327128e30a144ef50a45242433a2325081391"
-  integrity sha512-0WIs3P6ohPVh2+t5axrLZDE5Dt7fe3Kv0Auj0sBiBd6MmKZ2oS76apIl0Bspdbv8jX8+TRKGv6ib0280D0dtEw==
+"@lerna/create-symlink@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-6.0.1.tgz#5a9f75f8e5c0d83c39d70240f51284cc5d6770ad"
+  integrity sha512-ZmLx9SP5De6u1xkD7Z6gMMFuyLKCb+2bodreFe7ryOVP3cOLbmNOmgMgj+gtUgIwIv7BDwX3qFWlPY6B3VW3hQ==
   dependencies:
     cmd-shim "^5.0.0"
     fs-extra "^9.1.0"
     npmlog "^6.0.2"
 
-"@lerna/create@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/create/-/create-5.6.2.tgz#2c2e4b089cd8426cd256c6b0a0df5e676aa3503a"
-  integrity sha512-+Y5cMUxMNXjTTU9IHpgRYIwKo39w+blui1P+s+qYlZUSCUAew0xNpOBG8iN0Nc5X9op4U094oIdHxv7Dyz6tWQ==
+"@lerna/create@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/create/-/create-6.0.1.tgz#7905cef9196cb6a1caff5d7cd78a46fc7ea635a9"
+  integrity sha512-VuTdvBJDzvAaMBYoKTRMBQC+nfwnihxdA/ekUqBD+W8MMsqPLCGCneyl7JK9RaSSib/10LyRDEmfo79UAndcgQ==
   dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/npm-conf" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/npm-conf" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     dedent "^0.7.0"
     fs-extra "^9.1.0"
     init-package-json "^3.0.2"
@@ -1100,218 +1125,218 @@
     validate-npm-package-name "^4.0.0"
     yargs-parser "20.2.4"
 
-"@lerna/describe-ref@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-5.6.2.tgz#8beb9884b59c419c67cec935cd90c08704e4c9b0"
-  integrity sha512-UqU0N77aT1W8duYGir7R+Sk3jsY/c4lhcCEcnayMpFScMbAp0ETGsW04cYsHK29sgg+ZCc5zEwebBqabWhMhnA==
+"@lerna/describe-ref@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-6.0.1.tgz#e9277bcc3c1c839fc7305b808f9dd02a5404aaf8"
+  integrity sha512-PcTVt4qgAXUPBtWHyqixtwE/eXe56+DFRnfTcJlb4x5F7LJ+7VNpdR/81qfP89Xj10U5IjELXbXmriz1KMwhfw==
   dependencies:
-    "@lerna/child-process" "5.6.2"
+    "@lerna/child-process" "6.0.1"
     npmlog "^6.0.2"
 
-"@lerna/diff@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/diff/-/diff-5.6.2.tgz#059f62c95e08a506574e0e66044934a395e15b11"
-  integrity sha512-aHKzKvUvUI8vOcshC2Za/bdz+plM3r/ycqUrPqaERzp+kc1pYHyPeXezydVdEmgmmwmyKI5hx4+2QNnzOnun2A==
+"@lerna/diff@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/diff/-/diff-6.0.1.tgz#e8c5d541d74a9aa13a4ac6745f2f0d9531207fd1"
+  integrity sha512-/pGXH9txA8wX1YJ/KOBXzx0Z2opADBW4HKPCxxHAu+6dTGMbKABDljVT5Np3UpfIrAGDE5fTuf0aGL4vkKUWrg==
   dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     npmlog "^6.0.2"
 
-"@lerna/exec@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/exec/-/exec-5.6.2.tgz#b4edee66e26760de28bbf8472993ae8ad7508073"
-  integrity sha512-meZozok5stK7S0oAVn+kdbTmU+kHj9GTXjW7V8kgwG9ld+JJMTH3nKK1L3mEKyk9TFu9vFWyEOF7HNK6yEOoVg==
-  dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/filter-options" "5.6.2"
-    "@lerna/profiler" "5.6.2"
-    "@lerna/run-topologically" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+"@lerna/exec@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/exec/-/exec-6.0.1.tgz#d2d0785c46b7ceb3758fe75bb6d95d177a0a0ec3"
+  integrity sha512-x9puoI3091Alp45w7XOGRxThOw45p+tWGPR5TBCEQiiH7f8eF9Dc4WX5HXf31ooK6NmD40eKPYhBgy8oQnJY9w==
+  dependencies:
+    "@lerna/child-process" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/filter-options" "6.0.1"
+    "@lerna/profiler" "6.0.1"
+    "@lerna/run-topologically" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     p-map "^4.0.0"
 
-"@lerna/filter-options@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-5.6.2.tgz#0201d3aaf71eb7d7f8b1d28193218710c3220aa0"
-  integrity sha512-4Z0HIhPak2TabTsUqEBQaQeOqgqEt0qyskvsY0oviYvqP/nrJfJBZh4H93jIiNQF59LJCn5Ce3KJJrLExxjlzw==
+"@lerna/filter-options@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-6.0.1.tgz#4dbd29a31fb2ac228f72c51b223f17623d1f2c71"
+  integrity sha512-6KxbBI/2skRl/yQdjugQ1PWrSLq19650z8mltF0HT7B686fj7LlDNtESFOtY6iZ8IPqKBkIavOP0DPmJZd7Szw==
   dependencies:
-    "@lerna/collect-updates" "5.6.2"
-    "@lerna/filter-packages" "5.6.2"
+    "@lerna/collect-updates" "6.0.1"
+    "@lerna/filter-packages" "6.0.1"
     dedent "^0.7.0"
     npmlog "^6.0.2"
 
-"@lerna/filter-packages@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-5.6.2.tgz#1118a9318f3e08f9e21fb03d23f91e1f77f4a72a"
-  integrity sha512-el9V2lTEG0Bbz+Omo45hATkRVnChCTJhcTpth19cMJ6mQ4M5H4IgbWCJdFMBi/RpTnOhz9BhJxDbj95kuIvvzw==
+"@lerna/filter-packages@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-6.0.1.tgz#07f10dc78e852bbba44843b785ebc16f386cedaa"
+  integrity sha512-2bKhexeF07Urs2b0xYX2OgYUN0EzmS2FSgvw0KT6He48PGOkqgJjU7PIiWdPyOvZdukwm07qXTmJZulAHftceA==
   dependencies:
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/validation-error" "6.0.1"
     multimatch "^5.0.0"
     npmlog "^6.0.2"
 
-"@lerna/get-npm-exec-opts@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-5.6.2.tgz#a5e1a93f62eba817961210b7be148c0768ee4eee"
-  integrity sha512-0RbSDJ+QC9D5UWZJh3DN7mBIU1NhBmdHOE289oHSkjDY+uEjdzMPkEUy+wZ8fCzMLFnnNQkAEqNaOAzZ7dmFLA==
+"@lerna/get-npm-exec-opts@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-6.0.1.tgz#c766588d030c0ec7170650808957998e8ad70831"
+  integrity sha512-y2T+ODP8HNzHQn1ldrrPW+n823fGsN2sY0r78yURFxYZnxA9ZINyQ6IAejo5LqHrYN8Qhr++0RHo2tUisIHdKg==
   dependencies:
     npmlog "^6.0.2"
 
-"@lerna/get-packed@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-5.6.2.tgz#cc5008008442ae00cfa5ed9484e76a44d48e37b6"
-  integrity sha512-pp5nNDmtrtd21aKHjwwOY5CS7XNIHxINzGa+Jholn1jMDYUtdskpN++ZqYbATGpW831++NJuiuBVyqAWi9xbXg==
+"@lerna/get-packed@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-6.0.1.tgz#d31c10ec10658eeee4306886c100cd9600d6dd78"
+  integrity sha512-Z/5J5vbjdeGqZcPvUSiszvyizHdsTRiFlpPORWK3YfIsHllUB7QZnVHLg92UnSJrpPE0O1gH+k6ByhhR+3qEdA==
   dependencies:
     fs-extra "^9.1.0"
     ssri "^9.0.1"
     tar "^6.1.0"
 
-"@lerna/github-client@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/github-client/-/github-client-5.6.2.tgz#b40a71ddf5d40aefe178a48713aa107ef735f056"
-  integrity sha512-pjALazZoRZtKqfwLBwmW3HPptVhQm54PvA8s3qhCQ+3JkqrZiIFwkkxNZxs3jwzr+aaSOzfhSzCndg0urb0GXA==
+"@lerna/github-client@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/github-client/-/github-client-6.0.1.tgz#081d13c2debf312d0e5a2bb2fad6e0c69e1501d6"
+  integrity sha512-UA7V3XUunJnrfCL2eyW9QsCjBWShv4dCRGUITXmpQJrNIMZIqVbBJzqN9LVHDNc/hEVZGt0EjtHWdpFCgD4ypg==
   dependencies:
-    "@lerna/child-process" "5.6.2"
+    "@lerna/child-process" "6.0.1"
     "@octokit/plugin-enterprise-rest" "^6.0.1"
     "@octokit/rest" "^19.0.3"
     git-url-parse "^13.1.0"
     npmlog "^6.0.2"
 
-"@lerna/gitlab-client@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-5.6.2.tgz#3bb3c350d28f38f719ddbba083ca28dbd353494e"
-  integrity sha512-TInJmbrsmYIwUyrRxytjO82KjJbRwm67F7LoZs1shAq6rMvNqi4NxSY9j+hT/939alFmEq1zssoy/caeLXHRfQ==
+"@lerna/gitlab-client@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-6.0.1.tgz#1863b621a1530bc482113cac8791247664dedb2a"
+  integrity sha512-yyaBKf/OqBAau6xDk1tnMjfkxRpC/j3OwUyXFFGfJFSulWRHpbHoFSfvIgOn/hkjAr9FfHC7TXItRg8qdm38Wg==
   dependencies:
     node-fetch "^2.6.1"
     npmlog "^6.0.2"
 
-"@lerna/global-options@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/global-options/-/global-options-5.6.2.tgz#30bec81cdb4ac0bb47588e4a502ce908a982ff7c"
-  integrity sha512-kaKELURXTlczthNJskdOvh6GGMyt24qat0xMoJZ8plYMdofJfhz24h1OFcvB/EwCUwP/XV1+ohE5P+vdktbrEg==
+"@lerna/global-options@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/global-options/-/global-options-6.0.1.tgz#83061d85759c105120ff55716959642ba6eb0eea"
+  integrity sha512-vzjDI3Bg2NR+cSgfjHWax2bF1HmQYjJF2tmZlT/hJbwhaVMIEnhzHnJ9Yycmm98cdV77xEMlbmk5YD7xgFdG2w==
 
-"@lerna/has-npm-version@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-5.6.2.tgz#5359e9870941f66fb3b859995120801800880944"
-  integrity sha512-kXCnSzffmTWsaK0ol30coyCfO8WH26HFbmJjRBzKv7VGkuAIcB6gX2gqRRgNLLlvI+Yrp+JSlpVNVnu15SEH2g==
+"@lerna/has-npm-version@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-6.0.1.tgz#ed27a27cad2090069feb3108b105ceec765bec5e"
+  integrity sha512-ol1onJaauMXK0cQsfRX2rvbhNRyNBY9Ne5trrRjfMROa7Tnr8c3I4+aKQs7m4z1JdWaGBV4xBH+NSZ/esPuaWA==
   dependencies:
-    "@lerna/child-process" "5.6.2"
+    "@lerna/child-process" "6.0.1"
     semver "^7.3.4"
 
-"@lerna/import@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/import/-/import-5.6.2.tgz#7be2321fbc41fa0f7fdd233eb62571e8418fcb75"
-  integrity sha512-xQUE49mtcP0z3KUdXBsyvp8rGDz6phuYUoQbhcFRJ7WPcQKzMvtm0XYrER6c2YWEX7QOuDac6tU82P8zTrTBaA==
-  dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/prompt" "5.6.2"
-    "@lerna/pulse-till-done" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+"@lerna/import@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/import/-/import-6.0.1.tgz#9e869d6bbe82446ee3620c4310ca6232881b7952"
+  integrity sha512-GrTtIWUCnDf+FqRjenV2OKWU+khoZj0h/etgfXus45PBO2+V/SkkzIY4xof23XphiydUYrSrYtwx2i1aEmk3Wg==
+  dependencies:
+    "@lerna/child-process" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/prompt" "6.0.1"
+    "@lerna/pulse-till-done" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     dedent "^0.7.0"
     fs-extra "^9.1.0"
     p-map-series "^2.1.0"
 
-"@lerna/info@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/info/-/info-5.6.2.tgz#82280cdae6e08aab5b3017c359f6e496116a62ae"
-  integrity sha512-MPjY5Olj+fiZHgfEdwXUFRKamdEuLr9Ob/qut8JsB/oQSQ4ALdQfnrOcMT8lJIcC2R67EA5yav2lHPBIkezm8A==
+"@lerna/info@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/info/-/info-6.0.1.tgz#68395061ffbd81c7716d60b99b5220c90ade2862"
+  integrity sha512-QEW7JtJjoR1etUrcft7BnrwPZFHE2JPmt2DoSvSmLISLyy+HlmdXHK+p6Ej3g1ql8gS0GWCacgwmlRZ27CDp5A==
   dependencies:
-    "@lerna/command" "5.6.2"
-    "@lerna/output" "5.6.2"
+    "@lerna/command" "6.0.1"
+    "@lerna/output" "6.0.1"
     envinfo "^7.7.4"
 
-"@lerna/init@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/init/-/init-5.6.2.tgz#8f92868c3f9081245f5a8e0b94ce6b5979b8541e"
-  integrity sha512-ahU3/lgF+J8kdJAQysihFJROHthkIDXfHmvhw7AYnzf94HjxGNXj7nz6i3At1/dM/1nQhR+4/uNR1/OU4tTYYQ==
+"@lerna/init@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/init/-/init-6.0.1.tgz#babee56707bd19b3c1b82967e3360d1083c04cf9"
+  integrity sha512-zOMrSij09LSAVUUujpD3y32wkHp8dQ+/dVCp4USlfcGfI+kIPc5prkYCGDO8dEcqkze0pMfDMF23pVNvAf9g7w==
   dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/project" "5.6.2"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/project" "6.0.1"
     fs-extra "^9.1.0"
     p-map "^4.0.0"
     write-json-file "^4.3.0"
 
-"@lerna/link@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/link/-/link-5.6.2.tgz#6af5addff89cd455c1837a47a36f430a2c6ae6a5"
-  integrity sha512-hXxQ4R3z6rUF1v2x62oIzLyeHL96u7ZBhxqYMJrm763D1VMSDcHKF9CjJfc6J9vH5Z2ZbL6CQg50Hw5mUpJbjg==
+"@lerna/link@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/link/-/link-6.0.1.tgz#a94cf3aead92538835d955c6de281c65097f3471"
+  integrity sha512-VXZ77AWsJCycTu219ZLUHyRzMd5hgivLk5ZyBD1s/emArFvdEmGLscj2RXn3P3w/951b+DNG2Zbi6nek0iJ6DA==
   dependencies:
-    "@lerna/command" "5.6.2"
-    "@lerna/package-graph" "5.6.2"
-    "@lerna/symlink-dependencies" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/command" "6.0.1"
+    "@lerna/package-graph" "6.0.1"
+    "@lerna/symlink-dependencies" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     p-map "^4.0.0"
     slash "^3.0.0"
 
-"@lerna/list@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/list/-/list-5.6.2.tgz#5fdf8c678891eacef1d90afb84fb461deb6bb662"
-  integrity sha512-WjE5O2tQ3TcS+8LqXUaxi0YdldhxUhNihT5+Gg4vzGdIlrPDioO50Zjo9d8jOU7i3LMIk6EzCma0sZr2CVfEGg==
+"@lerna/list@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/list/-/list-6.0.1.tgz#ab6d056c5d7b99ca0ed6a17d48bf907afd9d970a"
+  integrity sha512-M9Vneh866E1nlpU88rcUMLR+XTVi3VY0fLPr1OqXdYF+eTe6RkEHUQj8HIk94Rnt02HsWc4+FO31T4i5sf+PaA==
   dependencies:
-    "@lerna/command" "5.6.2"
-    "@lerna/filter-options" "5.6.2"
-    "@lerna/listable" "5.6.2"
-    "@lerna/output" "5.6.2"
+    "@lerna/command" "6.0.1"
+    "@lerna/filter-options" "6.0.1"
+    "@lerna/listable" "6.0.1"
+    "@lerna/output" "6.0.1"
 
-"@lerna/listable@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/listable/-/listable-5.6.2.tgz#1a35e8da081f2dc286647cbf4a4a7fb3c7fb1102"
-  integrity sha512-8Yp49BwkY/5XqVru38Zko+6Wj/sgbwzJfIGEPy3Qu575r1NA/b9eI1gX22aMsEeXUeGOybR7nWT5ewnPQHjqvA==
+"@lerna/listable@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/listable/-/listable-6.0.1.tgz#444e81f6642c198d116e9e6b86d96d10ddf2e147"
+  integrity sha512-+xEByVX0sbnBW3EBu3XCg71Bz9/dahncmCjNK0kVnZLnQZzfULCndaQeSt+f9KO0VCs8h1tnXdo2uLPm4lThnw==
   dependencies:
-    "@lerna/query-graph" "5.6.2"
+    "@lerna/query-graph" "6.0.1"
     chalk "^4.1.0"
     columnify "^1.6.0"
 
-"@lerna/log-packed@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-5.6.2.tgz#05d26f038ce64e8ce8395c1745dfeb7589f89790"
-  integrity sha512-O9GODG7tMtWk+2fufn2MOkIDBYMRoKBhYMHshO5Aw/VIsH76DIxpX1koMzWfUngM/C70R4uNAKcVWineX4qzIw==
+"@lerna/log-packed@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-6.0.1.tgz#20fe38b5f18e65392b42bf84cfdda0afc0b62330"
+  integrity sha512-HTJdZzfBbb5jyk/QU2O6o+yaWRwLoaPruhK+Q3ESTzQ2mlNCr0CI4UKWDcWURWx0EsVsYqsoUHuPZInpIHqCnA==
   dependencies:
     byte-size "^7.0.0"
     columnify "^1.6.0"
     has-unicode "^2.0.1"
     npmlog "^6.0.2"
 
-"@lerna/npm-conf@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-5.6.2.tgz#3b72fc528c8a1cd0acc9b277749a6153bd8de083"
-  integrity sha512-gWDPhw1wjXYXphk/PAghTLexO5T6abVFhXb+KOMCeem366mY0F5bM88PiorL73aErTNUoR8n+V4X29NTZzDZpQ==
+"@lerna/npm-conf@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-6.0.1.tgz#fa242a36ef687c7b5207a9d9a85b9e7a4f38bdc5"
+  integrity sha512-VjxODCnl6QJGoQ8z8AWEID1GO9CtCr2yRyn6NoRdBOTYmzI5KhBBM+nWmyMSOUe0EZI+K5j04/GRzKHg2KXTAQ==
   dependencies:
     config-chain "^1.1.12"
     pify "^5.0.0"
 
-"@lerna/npm-dist-tag@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-5.6.2.tgz#6115aa4b005b57520d76428926ee7d12030f5e53"
-  integrity sha512-t2RmxV6Eog4acXkUI+EzWuYVbeVVY139pANIWS9qtdajfgp4GVXZi1S8mAIb70yeHdNpCp1mhK0xpCrFH9LvGQ==
+"@lerna/npm-dist-tag@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-6.0.1.tgz#4718bdedd82f375ba619319070b694f1113e627b"
+  integrity sha512-jJKDgnhj6xGqSWGcbwdcbPtoo2m4mHRwqu8iln9e3TMOEyUO9aA4uvd0/18tEAsboOMiLUhhcQ8709iKv21ZEA==
   dependencies:
-    "@lerna/otplease" "5.6.2"
+    "@lerna/otplease" "6.0.1"
     npm-package-arg "8.1.1"
     npm-registry-fetch "^13.3.0"
     npmlog "^6.0.2"
 
-"@lerna/npm-install@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-5.6.2.tgz#d5bd1e10c1c31f69a9ca5351b0cbe72dbc288dc2"
-  integrity sha512-AT226zdEo+uGENd37jwYgdALKJAIJK4pNOfmXWZWzVb9oMOr8I2YSjPYvSYUNG7gOo2YJQU8x5Zd7OShv2924Q==
+"@lerna/npm-install@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-6.0.1.tgz#5d6f0c62b34f2bfeb8f20b81b08f01ca0d3ed60b"
+  integrity sha512-saDJSyhhl/wxgZSzRx2/pr0wsMR+hZpdhLGd1lZgo5XzLq3ogK+BxPFz3AK3xhRnNaMq96gDQ3xmeetoV53lwQ==
   dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/get-npm-exec-opts" "5.6.2"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/get-npm-exec-opts" "6.0.1"
     fs-extra "^9.1.0"
     npm-package-arg "8.1.1"
     npmlog "^6.0.2"
     signal-exit "^3.0.3"
     write-pkg "^4.0.0"
 
-"@lerna/npm-publish@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-5.6.2.tgz#4e5e225b47589a7f8f96b7eee68b547e8ce432a2"
-  integrity sha512-ldSyewCfv9fAeC5xNjL0HKGSUxcC048EJoe/B+KRUmd+IPidvZxMEzRu08lSC/q3V9YeUv9ZvRnxATXOM8CffA==
+"@lerna/npm-publish@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-6.0.1.tgz#ffbca4be5b971df978a60917460ee8f28b1c62b7"
+  integrity sha512-hgzF9fOfp010z7PJtqNLxNXiHr6u4UDVwiX8g22rhJKBh9Ekrq7N9NS3mF0l+RcleRU/jJKYtZ0Ci3fICaaRUg==
   dependencies:
-    "@lerna/otplease" "5.6.2"
-    "@lerna/run-lifecycle" "5.6.2"
+    "@lerna/otplease" "6.0.1"
+    "@lerna/run-lifecycle" "6.0.1"
     fs-extra "^9.1.0"
     libnpmpublish "^6.0.4"
     npm-package-arg "8.1.1"
@@ -1319,85 +1344,85 @@
     pify "^5.0.0"
     read-package-json "^5.0.1"
 
-"@lerna/npm-run-script@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-5.6.2.tgz#66e3391ebdd6136312277be37a1b62ce48c12abf"
-  integrity sha512-MOQoWNcAyJivM8SYp0zELM7vg/Dj07j4YMdxZkey+S1UO0T4/vKBxb575o16hH4WeNzC3Pd7WBlb7C8dLOfNwQ==
+"@lerna/npm-run-script@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-6.0.1.tgz#3a255aa6f37a5e2369a37a8ddcb2709f84019ed1"
+  integrity sha512-K+D4LEoVRuBoKRImprkVRHIORu0xouX+c6yI1B93KWHKJ60H8qCeB0gQkA30pFALx3qG07bXVnFmfK9SGQXD3Q==
   dependencies:
-    "@lerna/child-process" "5.6.2"
-    "@lerna/get-npm-exec-opts" "5.6.2"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/get-npm-exec-opts" "6.0.1"
     npmlog "^6.0.2"
 
-"@lerna/otplease@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/otplease/-/otplease-5.6.2.tgz#a94e4daf9d3d42bfc0366a6889b8809ed32dbdd0"
-  integrity sha512-dGS4lzkEQVTMAgji82jp8RK6UK32wlzrBAO4P4iiVHCUTuwNLsY9oeBXvVXSMrosJnl6Hbe0NOvi43mqSucGoA==
+"@lerna/otplease@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/otplease/-/otplease-6.0.1.tgz#da5467c603565940c1f91e65d077abf25d96df7f"
+  integrity sha512-RrP8GtfE9yz37GuuCFqddR3mVIQc1ulUpAaaDNK4AOTb7gM0aCsTN7V2gCGBk1zdIsBuvNvNqt5jpWm4U6/EAA==
   dependencies:
-    "@lerna/prompt" "5.6.2"
+    "@lerna/prompt" "6.0.1"
 
-"@lerna/output@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/output/-/output-5.6.2.tgz#fa97315d16cfe005a2891a3fc98f6f4fd3f518ed"
-  integrity sha512-++d+bfOQwY66yo7q1XuAvRcqtRHCG45e/awP5xQomTZ6R1rhWiZ3whWdc9Z6lF7+UtBB9toSYYffKU/xc3L0yQ==
+"@lerna/output@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/output/-/output-6.0.1.tgz#5e301ad0bed607ee139cf207fd75ed1e5fac7908"
+  integrity sha512-4jZ3fgaCbnsTZ353/lXE/3w20Cge6G3iUoESVip+JE2yhZ8rWgPISG8RFR0YGEtSgq2yC9AgGnGlvmOnAc4SAQ==
   dependencies:
     npmlog "^6.0.2"
 
-"@lerna/pack-directory@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-5.6.2.tgz#ced0287d13d8575fe928ad7d9ad92dc6554cc86d"
-  integrity sha512-w5Jk5fo+HkN4Le7WMOudTcmAymcf0xPd302TqAQncjXpk0cb8tZbj+5bbNHsGb58GRjOIm5icQbHXooQUxbHhA==
+"@lerna/pack-directory@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-6.0.1.tgz#4a0bf61b7cb1b1b3f1fb95afec987a7c63ff9f95"
+  integrity sha512-vNgS5Rs7s6khOYuHE5nTds0VDfHBH8YNGvV1s0yGAg/Zkivi7bOTs8jDQFiYhQX3HOTC1/85BLhGQ3zcDHlrew==
   dependencies:
-    "@lerna/get-packed" "5.6.2"
-    "@lerna/package" "5.6.2"
-    "@lerna/run-lifecycle" "5.6.2"
-    "@lerna/temp-write" "5.6.2"
+    "@lerna/get-packed" "6.0.1"
+    "@lerna/package" "6.0.1"
+    "@lerna/run-lifecycle" "6.0.1"
+    "@lerna/temp-write" "6.0.1"
     npm-packlist "^5.1.1"
     npmlog "^6.0.2"
     tar "^6.1.0"
 
-"@lerna/package-graph@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-5.6.2.tgz#cb0a70b83afc418c5b5363bb96746d501decdbeb"
-  integrity sha512-TmL61qBBvA3Tc4qICDirZzdFFwWOA6qicIXUruLiE2PblRowRmCO1bKrrP6XbDOspzwrkPef6N2F2/5gHQAnkQ==
+"@lerna/package-graph@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-6.0.1.tgz#db72ab9ed45933d1518de7f7389a6c79e6059336"
+  integrity sha512-OMppRWpfSaI6HO/Tc5FVpNefgOsCc3/DzaMLme6QTTpbEwD3EhvQ3Xx0MgsGMPdmZhWp/WOoAJsVRnLa+l03gg==
   dependencies:
-    "@lerna/prerelease-id-from-version" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/prerelease-id-from-version" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     npm-package-arg "8.1.1"
     npmlog "^6.0.2"
     semver "^7.3.4"
 
-"@lerna/package@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/package/-/package-5.6.2.tgz#da73b350693fdd4154cf5b19799bfaadff57442e"
-  integrity sha512-LaOC8moyM5J9WnRiWZkedjOninSclBOJyPqhif6mHb2kCFX6jAroNYzE8KM4cphu8CunHuhI6Ixzswtv+Dultw==
+"@lerna/package@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/package/-/package-6.0.1.tgz#cb950e574b1ea3ef5cd8cf62b3c4308f6c869122"
+  integrity sha512-vCwyiLVJ4K3SR6KZleglq1dUXIiYGmk3b+NrFWP/Z3dhVE0C+RqgxSsAS4aaUNMSO2KSI0dBdce7BT/D+FdpIQ==
   dependencies:
     load-json-file "^6.2.0"
     npm-package-arg "8.1.1"
     write-pkg "^4.0.0"
 
-"@lerna/prerelease-id-from-version@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-5.6.2.tgz#63002662024a261310c6fbf01a50cb5f50569ca8"
-  integrity sha512-7gIm9fecWFVNy2kpj/KbH11bRcpyANAwpsft3X5m6J7y7A6FTUscCbEvl3ZNdpQKHNuvnHgCtkm3A5PMSCEgkA==
+"@lerna/prerelease-id-from-version@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-6.0.1.tgz#a47980aa6c78deaa36430d03b6300bc889960b50"
+  integrity sha512-aZBs/FinztKjNXlk0cW99FpABynZzZwlmJuW4h9nMrQPgWoaDAERfImbefIH/lcpxdRuuGtClyZUFBOSq8ppfg==
   dependencies:
     semver "^7.3.4"
 
-"@lerna/profiler@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/profiler/-/profiler-5.6.2.tgz#5bfd52fb666ad0506cac3b8d2839e904d0acf90a"
-  integrity sha512-okwkagP5zyRIOYTceu/9/esW7UZFt7lyL6q6ZgpSG3TYC5Ay+FXLtS6Xiha/FQdVdumFqKULDWTGovzUlxcwaw==
+"@lerna/profiler@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/profiler/-/profiler-6.0.1.tgz#2b7a043e6999823ad97a7ddaea0ed7f338032f92"
+  integrity sha512-vZrgF5pDhYWY/Gx7MjtyOgTVMA6swDV2+xPZwkvRD1Z0XpWEIn5d79zRN/1SBpdMNozC7Lj++1oEbCGNWhy/ow==
   dependencies:
     fs-extra "^9.1.0"
     npmlog "^6.0.2"
     upath "^2.0.1"
 
-"@lerna/project@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/project/-/project-5.6.2.tgz#a893851cdceeace36d30fdfdbc2da9159a9e2041"
-  integrity sha512-kPIMcIy/0DVWM91FPMMFmXyAnCuuLm3NdhnA8NusE//VuY9wC6QC/3OwuCY39b2dbko/fPZheqKeAZkkMH6sGg==
+"@lerna/project@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/project/-/project-6.0.1.tgz#0d4a6dbca1943478d554d4a3a610968caf9b303a"
+  integrity sha512-/n2QuAEgImbwUqrJND15FxYu29p/mLTUpL/8cSg6IUlOQRFyXteESRyl8A2Ex7Wj00FMbtB13vgbmTdkTgKL0A==
   dependencies:
-    "@lerna/package" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+    "@lerna/package" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     cosmiconfig "^7.0.0"
     dedent "^0.7.0"
     dot-prop "^6.0.1"
@@ -1410,38 +1435,38 @@
     resolve-from "^5.0.0"
     write-json-file "^4.3.0"
 
-"@lerna/prompt@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/prompt/-/prompt-5.6.2.tgz#7ea10fd3543aced0bf5521741808d86ffcf4b320"
-  integrity sha512-4hTNmVYADEr0GJTMegWV+GW6n+dzKx1vN9v2ISqyle283Myv930WxuyO0PeYGqTrkneJsyPreCMovuEGCvZ0iQ==
+"@lerna/prompt@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/prompt/-/prompt-6.0.1.tgz#2a744b168ce4a29b7c66d500258a3f65b3f028e2"
+  integrity sha512-faR7oVdHBO3QTJ6o9kUEDPpyjCftd/CCa1rAC6q8f3vlLfCPrTym0qT+DcOBFGpDQh4m2dmGfJZgpXIVi6bMbg==
   dependencies:
     inquirer "^8.2.4"
     npmlog "^6.0.2"
 
-"@lerna/publish@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/publish/-/publish-5.6.2.tgz#c8a26610c4fb2c7c5a232e04852bf545b242ee65"
-  integrity sha512-QaW0GjMJMuWlRNjeDCjmY/vjriGSWgkLS23yu8VKNtV5U3dt5yIKA3DNGV3HgZACuu45kQxzMDsfLzgzbGNtYA==
-  dependencies:
-    "@lerna/check-working-tree" "5.6.2"
-    "@lerna/child-process" "5.6.2"
-    "@lerna/collect-updates" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/describe-ref" "5.6.2"
-    "@lerna/log-packed" "5.6.2"
-    "@lerna/npm-conf" "5.6.2"
-    "@lerna/npm-dist-tag" "5.6.2"
-    "@lerna/npm-publish" "5.6.2"
-    "@lerna/otplease" "5.6.2"
-    "@lerna/output" "5.6.2"
-    "@lerna/pack-directory" "5.6.2"
-    "@lerna/prerelease-id-from-version" "5.6.2"
-    "@lerna/prompt" "5.6.2"
-    "@lerna/pulse-till-done" "5.6.2"
-    "@lerna/run-lifecycle" "5.6.2"
-    "@lerna/run-topologically" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
-    "@lerna/version" "5.6.2"
+"@lerna/publish@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/publish/-/publish-6.0.1.tgz#9448a35a87e2c986c8919114698f3a314a9a2574"
+  integrity sha512-xIleRwCuPHtShNSPc6RDH33Z+EO1E4O0LOhPq5qTwanNPYh5eL6bDHBsox44BbMD9dhhI4PUrqIGTu3AoKdDxg==
+  dependencies:
+    "@lerna/check-working-tree" "6.0.1"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/collect-updates" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/describe-ref" "6.0.1"
+    "@lerna/log-packed" "6.0.1"
+    "@lerna/npm-conf" "6.0.1"
+    "@lerna/npm-dist-tag" "6.0.1"
+    "@lerna/npm-publish" "6.0.1"
+    "@lerna/otplease" "6.0.1"
+    "@lerna/output" "6.0.1"
+    "@lerna/pack-directory" "6.0.1"
+    "@lerna/prerelease-id-from-version" "6.0.1"
+    "@lerna/prompt" "6.0.1"
+    "@lerna/pulse-till-done" "6.0.1"
+    "@lerna/run-lifecycle" "6.0.1"
+    "@lerna/run-topologically" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
+    "@lerna/version" "6.0.1"
     fs-extra "^9.1.0"
     libnpmaccess "^6.0.3"
     npm-package-arg "8.1.1"
@@ -1452,99 +1477,99 @@
     pacote "^13.6.1"
     semver "^7.3.4"
 
-"@lerna/pulse-till-done@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-5.6.2.tgz#061c4ba2894fa08333fe4502299f9f9f24bdb91c"
-  integrity sha512-eA/X1RCxU5YGMNZmbgPi+Kyfx1Q3bn4P9jo/LZy+/NRRr1po3ASXP2GJZ1auBh/9A2ELDvvKTOXCVHqczKC6rA==
+"@lerna/pulse-till-done@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-6.0.1.tgz#d23985aea1ba25bb33cf74b39f36f2b7a5d21791"
+  integrity sha512-DK5Ylh/O7Vzn9ObEggvoHdLxc1hiXsDZ4fUvSmi50kc5QrMrk+xo6OyPgIaDBhYxj6lm3TQ1KkvWnRgiEynKAg==
   dependencies:
     npmlog "^6.0.2"
 
-"@lerna/query-graph@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-5.6.2.tgz#c507e9a9cb613c6d4d163d7d115a52ef8c1a9d3f"
-  integrity sha512-KRngr96yBP8XYDi9/U62fnGO+ZXqm04Qk6a2HtoTr/ha8QvO1s7Tgm0xs/G7qWXDQHZgunWIbmK/LhxM7eFQrw==
+"@lerna/query-graph@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-6.0.1.tgz#f72b55f0ee4662d06167e639e975019e5c004c59"
+  integrity sha512-X8Z63Ax5a9nXgNBG+IAXEdCL4MG88akr7L4mBvKiTPrK5VgP46YzuZSaSoPI8bU67MlWBkSYQWAJJ5t0HEtKTw==
   dependencies:
-    "@lerna/package-graph" "5.6.2"
+    "@lerna/package-graph" "6.0.1"
 
-"@lerna/resolve-symlink@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-5.6.2.tgz#51b6f4bbee36a1dcbf52634d05dcd08bb286f2cf"
-  integrity sha512-PDQy+7M8JEFtwIVHJgWvSxHkxJf9zXCENkvIWDB+SsoDPhw9+caewt46bTeP5iGm9pOMu3oZukaWo/TvF7sNjg==
+"@lerna/resolve-symlink@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-6.0.1.tgz#30c3ccf4c730451754ce7aa002772f26dd757c20"
+  integrity sha512-btosycLN+2lpqou6pz0Oeq4XIKHDIn0NvdnuCBLxtuBOBNIkdlx5QWKCtZ31GYKbCUt55w1DSGL64kfVuejVQQ==
   dependencies:
     fs-extra "^9.1.0"
     npmlog "^6.0.2"
     read-cmd-shim "^3.0.0"
 
-"@lerna/rimraf-dir@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-5.6.2.tgz#219c51a46c27b94789d683fc0424539f14505fea"
-  integrity sha512-jgEfzz7uBUiQKteq3G8MtJiA2D2VoKmZSSY3VSiW/tPOSXYxxSHxEsClQdCeNa6+sYrDNDT8fP6MJ3lPLjDeLA==
+"@lerna/rimraf-dir@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-6.0.1.tgz#e52ba283a4c39ade75792c23d0c6dcec65dcbbf4"
+  integrity sha512-rBFkwrxEQWFfZV5IMiPfGVubOquvOTNsPJPUf5tZoPAqKHXVQi5iYZGB65VG8JA7eFenZxh5mVErX2gtWFh1Ew==
   dependencies:
-    "@lerna/child-process" "5.6.2"
+    "@lerna/child-process" "6.0.1"
     npmlog "^6.0.2"
     path-exists "^4.0.0"
     rimraf "^3.0.2"
 
-"@lerna/run-lifecycle@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-5.6.2.tgz#b6954f334b40ca80caeb9e0cb7ca936222f39915"
-  integrity sha512-u9gGgq/50Fm8dvfcc/TSHOCAQvzLD7poVanDMhHYWOAqRDnellJEEmA1K/Yka4vZmySrzluahkry9G6jcREt+g==
+"@lerna/run-lifecycle@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-6.0.1.tgz#ab94838cf7daa1edd6228be0a161b38ec1a42a0b"
+  integrity sha512-gC7rnV3mrgFFIM8GlHc3d22ovYHoExu9CuIAxN26CVrMq7iEYxWoxYvweqVANsCHR7CVbs+dsDx8/TP1pQG8wg==
   dependencies:
-    "@lerna/npm-conf" "5.6.2"
+    "@lerna/npm-conf" "6.0.1"
     "@npmcli/run-script" "^4.1.7"
     npmlog "^6.0.2"
     p-queue "^6.6.2"
 
-"@lerna/run-topologically@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-5.6.2.tgz#ef00aa6751b4164ae4825244917cdd4bc2562501"
-  integrity sha512-QQ/jGOIsVvUg3izShWsd67RlWYh9UOH2yw97Ol1zySX9+JspCMVQrn9eKq1Pk8twQOFhT87LpT/aaxbTBgREPw==
+"@lerna/run-topologically@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-6.0.1.tgz#dcf26259e57b224d4aad2e3b259555ecd2f226ea"
+  integrity sha512-p4J9RvOUyDUjQ21tDh7Durci9YnuBu3T8WXD8xu5ZwcxVnawK1h5B8kP4V1R5L/jwNqkXsAnlLwikPVGQ5Iptw==
   dependencies:
-    "@lerna/query-graph" "5.6.2"
+    "@lerna/query-graph" "6.0.1"
     p-queue "^6.6.2"
 
-"@lerna/run@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/run/-/run-5.6.2.tgz#a964110d2fd13e4a3fe0fb4d752d0497651b26cb"
-  integrity sha512-c2kJxdFrNg5KOkrhmgwKKUOsfSrGNlFCe26EttufOJ3xfY0VnXlEw9rHOkTgwtu7969rfCdyaVP1qckMrF1Dgw==
-  dependencies:
-    "@lerna/command" "5.6.2"
-    "@lerna/filter-options" "5.6.2"
-    "@lerna/npm-run-script" "5.6.2"
-    "@lerna/output" "5.6.2"
-    "@lerna/profiler" "5.6.2"
-    "@lerna/run-topologically" "5.6.2"
-    "@lerna/timer" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
+"@lerna/run@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/run/-/run-6.0.1.tgz#20d3c77fa8faad01b915214b95477ae5390c8b45"
+  integrity sha512-F1vvpaevsWCjaQs3NlBegH54izm3cO3Qbg/cRRzPZMK4Jo7gE1ddL7+zCIq0zGt6aeVqRGBOtUMk4SvNGkzI4w==
+  dependencies:
+    "@lerna/command" "6.0.1"
+    "@lerna/filter-options" "6.0.1"
+    "@lerna/npm-run-script" "6.0.1"
+    "@lerna/output" "6.0.1"
+    "@lerna/profiler" "6.0.1"
+    "@lerna/run-topologically" "6.0.1"
+    "@lerna/timer" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
     fs-extra "^9.1.0"
     p-map "^4.0.0"
 
-"@lerna/symlink-binary@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-5.6.2.tgz#f8c68273f8a4f382bc0420593815dc13027f245a"
-  integrity sha512-Cth+miwYyO81WAmrQbPBrLHuF+F0UUc0el5kRXLH6j5zzaRS3kMM68r40M7MmfH8m3GPi7691UARoWFEotW5jw==
+"@lerna/symlink-binary@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-6.0.1.tgz#b9278650c3360cc518e0d313d9999cd740a2c054"
+  integrity sha512-TcwxDMgU9w+hGl0EeYihPytVRKV0KTeZZW4Bq6NEtjTCIIuKWxZjcY5ocxW22i6BClBvfFAJqkf+e+i3Nixlhg==
   dependencies:
-    "@lerna/create-symlink" "5.6.2"
-    "@lerna/package" "5.6.2"
+    "@lerna/create-symlink" "6.0.1"
+    "@lerna/package" "6.0.1"
     fs-extra "^9.1.0"
     p-map "^4.0.0"
 
-"@lerna/symlink-dependencies@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-5.6.2.tgz#263866a869c253db805a9a385741e8919b0aa341"
-  integrity sha512-dUVNQLEcjVOIQiT9OlSAKt0ykjyJPy8l9i4NJDe2/0XYaUjo8PWsxJ0vrutz27jzi2aZUy07ASmowQZEmnLHAw==
+"@lerna/symlink-dependencies@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-6.0.1.tgz#28c01b3f910c1d13b1d447d27c47f5c76efd0096"
+  integrity sha512-ImyqjLjMBu0ORGO9gYHr9oDgN/5QeeGuELtYNweLS5vMNSH1dokQW9fqZSrgfCJPbxeCizBcDTi/Knqg17ebkA==
   dependencies:
-    "@lerna/create-symlink" "5.6.2"
-    "@lerna/resolve-symlink" "5.6.2"
-    "@lerna/symlink-binary" "5.6.2"
+    "@lerna/create-symlink" "6.0.1"
+    "@lerna/resolve-symlink" "6.0.1"
+    "@lerna/symlink-binary" "6.0.1"
     fs-extra "^9.1.0"
     p-map "^4.0.0"
     p-map-series "^2.1.0"
 
-"@lerna/temp-write@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/temp-write/-/temp-write-5.6.2.tgz#724fcadfe12bfaa723c1ea0fbc14804653816db0"
-  integrity sha512-S5ZNVTurSwWBmc9kh5alfSjmO3+BnRT6shYtOlmVIUYqWeYVYA5C1Htj322bbU4CSNCMFK6NQl4qGKL17HMuig==
+"@lerna/temp-write@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/temp-write/-/temp-write-6.0.1.tgz#84f8aa3f74b6150706a70430c68815517f5301cf"
+  integrity sha512-9eklYncDnwTnGF9o14GOrZU05ZK5n6/x5XYRQHbuLfK5T9pmOiUyl6sO1613cZygUMaWHHi7BLtBPiw2CklqXQ==
   dependencies:
     graceful-fs "^4.1.15"
     is-stream "^2.0.0"
@@ -1552,38 +1577,38 @@
     temp-dir "^1.0.0"
     uuid "^8.3.2"
 
-"@lerna/timer@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/timer/-/timer-5.6.2.tgz#57de5dde716539c699f295b8a8c182dd41801b2e"
-  integrity sha512-AjMOiLc2B+5Nzdd9hNORetAdZ/WK8YNGX/+2ypzM68TMAPfIT5C40hMlSva9Yg4RsBz22REopXgM5s2zQd5ZQA==
+"@lerna/timer@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/timer/-/timer-6.0.1.tgz#eb10242c48a1246e1bf216af305974fbd6332d39"
+  integrity sha512-FLoga8iprKmRkh9jO+LP4Bm7MZLO4wNHM4LML4Dlh9CPwcIOWTteI8wSgRXvEJpt33IRIoPOUnfL3iHh8WwaYA==
 
-"@lerna/validation-error@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-5.6.2.tgz#75310749d94395f009c67a8fd47e146a86ce2943"
-  integrity sha512-4WlDUHaa+RSJNyJRtX3gVIAPVzjZD2tle8AJ0ZYBfdZnZmG0VlB2pD1FIbOQPK8sY2h5m0cHLRvfLoLncqHvdQ==
+"@lerna/validation-error@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-6.0.1.tgz#afcf6b193eae86d64df9561afb7698696257304f"
+  integrity sha512-kjAxfFY1pDltwoCTvMQCbnpBwMXBFuvE4hdi8qePhBQ1Lf0PlTOI4ZqMFIkaTud+oujzysDXraTJbYTjc+C+zw==
   dependencies:
     npmlog "^6.0.2"
 
-"@lerna/version@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/version/-/version-5.6.2.tgz#211ed1c0af3be0bb6bf6f79ef0d3e8daa1266ff0"
-  integrity sha512-odNSR2rTbHW++xMZSQKu/F6Syrd/sUvwDLPaMKktoOSPKmycHt/eWcuQQyACdtc43Iqeu4uQd7PCLsniqOVFrw==
-  dependencies:
-    "@lerna/check-working-tree" "5.6.2"
-    "@lerna/child-process" "5.6.2"
-    "@lerna/collect-updates" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/conventional-commits" "5.6.2"
-    "@lerna/github-client" "5.6.2"
-    "@lerna/gitlab-client" "5.6.2"
-    "@lerna/output" "5.6.2"
-    "@lerna/prerelease-id-from-version" "5.6.2"
-    "@lerna/prompt" "5.6.2"
-    "@lerna/run-lifecycle" "5.6.2"
-    "@lerna/run-topologically" "5.6.2"
-    "@lerna/temp-write" "5.6.2"
-    "@lerna/validation-error" "5.6.2"
-    "@nrwl/devkit" ">=14.8.1 < 16"
+"@lerna/version@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/version/-/version-6.0.1.tgz#988675be8ea29f1548cb4554c257c2cc94b78084"
+  integrity sha512-d/addeHVsRFWx3fb/XZIh6f23KuEC9Fn3ytpaMzA8rlLF3Nob1opIR98ZfUz7Nf+skpIV1QiIbXdJTZzIKvd9g==
+  dependencies:
+    "@lerna/check-working-tree" "6.0.1"
+    "@lerna/child-process" "6.0.1"
+    "@lerna/collect-updates" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/conventional-commits" "6.0.1"
+    "@lerna/github-client" "6.0.1"
+    "@lerna/gitlab-client" "6.0.1"
+    "@lerna/output" "6.0.1"
+    "@lerna/prerelease-id-from-version" "6.0.1"
+    "@lerna/prompt" "6.0.1"
+    "@lerna/run-lifecycle" "6.0.1"
+    "@lerna/run-topologically" "6.0.1"
+    "@lerna/temp-write" "6.0.1"
+    "@lerna/validation-error" "6.0.1"
+    "@nrwl/devkit" ">=14.8.6 < 16"
     chalk "^4.1.0"
     dedent "^0.7.0"
     load-json-file "^6.2.0"
@@ -1597,10 +1622,10 @@
     slash "^3.0.0"
     write-json-file "^4.3.0"
 
-"@lerna/write-log-file@5.6.2":
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-5.6.2.tgz#a297307c80356abe4c3cfc75664febfa4658ec31"
-  integrity sha512-J09l18QnWQ3sXIRwuJkjXY3+KwPR2uO5NgbZGE3GXJK1V/LzOBRMvjGAIbuQHXw25uqe7vpLUpB8drtnFrubCQ==
+"@lerna/write-log-file@6.0.1":
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-6.0.1.tgz#4335d5e08686f8250ebae9d7f56b64452bd90cd3"
+  integrity sha512-fJGDE8rlE35DwKSqV8M1VV2xw/vQlgwTwURjNOMvd1Ar23Aa9CkJC4XAwc9uUgIku34IsWUM8MNbw9ClSsJaqw==
   dependencies:
     npmlog "^6.0.2"
     write-file-atomic "^4.0.1"
@@ -1894,17 +1919,17 @@
     read-package-json-fast "^2.0.3"
     which "^2.0.2"
 
-"@nrwl/cli@15.0.0":
-  version "15.0.0"
-  resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.0.0.tgz#7b00d95a6502f83fdd84f8888fd1ba7a180cdd07"
-  integrity sha512-D0zAhZ375bQnoUM2HLifMzAa75A3/lC9OkkewsiVVbqaznjEIry8ezHZepgfjFRVzLr3ue7FIpDEH3iJIYzvVw==
+"@nrwl/cli@15.0.1":
+  version "15.0.1"
+  resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.0.1.tgz#10faac9a94aed644d50416d7713c55b2f72fdc12"
+  integrity sha512-ZehVNZOajNG7i5qg4vDeIcf88PuyFZhAwNhT9G7yjG6v+23zFwOVUsweQeQbY0GxIGc9d+jXGzEe6hU+UYovPQ==
   dependencies:
-    nx "15.0.0"
+    nx "15.0.1"
 
-"@nrwl/devkit@>=14.8.1 < 16":
-  version "15.0.0"
-  resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.0.0.tgz#755bc07581a57e0ae87f68a7562ab86ff737e919"
-  integrity sha512-ALtPfILlxLDg77rV/XNdDGbhUkh0gZPj/4Ehy3ScvVqPhTrDIZNLGX13dXgUUF9xhGb7SXPmvzZkduBpqmHnfQ==
+"@nrwl/devkit@>=14.8.6 < 16":
+  version "15.0.1"
+  resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.0.1.tgz#e33b0a7faa9099cfc8b5c4cf667f4fd08011befe"
+  integrity sha512-KdKEENjZX/EA7FuWDBFYOldbVxd4eZT9MHOLUZADg2QQEgFfBNJUb1/R7JWVal8RPseeJSx8ber2iohjQkaN2A==
   dependencies:
     "@phenomnomnominal/tsquery" "4.1.1"
     ejs "^3.1.7"
@@ -1912,12 +1937,12 @@
     semver "7.3.4"
     tslib "^2.3.0"
 
-"@nrwl/tao@15.0.0":
-  version "15.0.0"
-  resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.0.0.tgz#128499a4256e408716f7347131a3ed32d1fec5f0"
-  integrity sha512-qup1eSWYwp/KVrw/wxeWBvYttQ9dcbQnqpXb5NQMD31SpXEZSpJB1i3GV/o6CF5qQQSNLwICXZx25rNTTQAqpg==
+"@nrwl/tao@15.0.1":
+  version "15.0.1"
+  resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.0.1.tgz#0002294b4d64c86a1e07dcd78bcceefc9bd25789"
+  integrity sha512-CytTfL7W6xkl1rW5fwO1nGF0Ft/Tk3ilc7/7I9+1NlNGdu/joFMOWub5YEQFIe488BJt2mxZ9m2n6sFJPVD19Q==
   dependencies:
-    nx "15.0.0"
+    nx "15.0.1"
 
 "@octokit/auth-token@^3.0.0":
   version "3.0.2"
@@ -3636,6 +3661,14 @@ css-loader@^5.0.1:
     schema-utils "^3.0.0"
     semver "^7.3.5"
 
+css-vendor@^2.0.8:
+  version "2.0.8"
+  resolved "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d"
+  integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==
+  dependencies:
+    "@babel/runtime" "^7.8.3"
+    is-in-browser "^1.0.2"
+
 cssesc@^3.0.0:
   version "3.0.0"
   resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@@ -5339,6 +5372,11 @@ humanize-ms@^1.2.1:
   dependencies:
     ms "^2.0.0"
 
+hyphenate-style-name@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
+  integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
+
 iconv-lite@0.4.24, iconv-lite@^0.4.24:
   version "0.4.24"
   resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -5594,6 +5632,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
   dependencies:
     is-extglob "^2.1.1"
 
+is-in-browser@^1.0.2, is-in-browser@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
+  integrity sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==
+
 is-interactive@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
@@ -6050,6 +6093,140 @@ jsprim@^1.2.2:
     json-schema "0.4.0"
     verror "1.10.0"
 
+jss-plugin-camel-case@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.2.tgz#76dddfa32f9e62d17daa4e3504991fd0933b89e1"
+  integrity sha512-wgBPlL3WS0WDJ1lPJcgjux/SHnDuu7opmgQKSraKs4z8dCCyYMx9IDPFKBXQ8Q5dVYij1FFV0WdxyhuOOAXuTg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    hyphenate-style-name "^1.0.3"
+    jss "10.9.2"
+
+jss-plugin-compose@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-compose/-/jss-plugin-compose-10.9.2.tgz#276c463ceea0abaf266a17e0fdb6a998a7189ba0"
+  integrity sha512-XvsGar4D791VgOMqbEk1XYY5s84Ew57OMLYjbnTXl3MSaBTvmR5M3dTqQbBquJGp4pLyyqlfTcijfolZII1w4Q==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
+jss-plugin-default-unit@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.2.tgz#3e7f4a1506b18d8fe231554fd982439feb2a9c53"
+  integrity sha512-pYg0QX3bBEFtTnmeSI3l7ad1vtHU42YEEpgW7pmIh+9pkWNWb5dwS/4onSfAaI0kq+dOZHzz4dWe+8vWnanoSg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
+jss-plugin-expand@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-expand/-/jss-plugin-expand-10.9.2.tgz#d9a1b52ff72c7f5214ed8d1adde2f302374f65c9"
+  integrity sha512-D3PGLUJu3YbHhX6vANooCa1gqfv68wLssDp08wH21YVTCt6u8jWfqkoj9NmPz5ea1Fc0WMoJtofJTlgb6ApZvw==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
+jss-plugin-extend@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.9.2.tgz#8774a3ad79a7112437e62389fb0baa36f32d8e40"
+  integrity sha512-55lXOQ7yyRtrMRYOcWUeZ3Ea4/Cd/oTndvb9j/5O3+E816nRoYbDsqKI8ob0Yx8PnfHBsQN0u10JcLnqq+8aPA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
+jss-plugin-global@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.2.tgz#e7f2ad4a5e8e674fb703b04b57a570b8c3e5c2c2"
+  integrity sha512-GcX0aE8Ef6AtlasVrafg1DItlL/tWHoC4cGir4r3gegbWwF5ZOBYhx04gurPvWHC8F873aEGqge7C17xpwmp2g==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
+jss-plugin-nested@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.9.2.tgz#3aa2502816089ecf3981e1a07c49b276d67dca63"
+  integrity sha512-VgiOWIC6bvgDaAL97XCxGD0BxOKM0K0zeB/ECyNaVF6FqvdGB9KBBWRdy2STYAss4VVA7i5TbxFZN+WSX1kfQA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
+jss-plugin-props-sort@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.2.tgz#645f6c8f179309667b3e6212f66b59a32fb3f01f"
+  integrity sha512-AP1AyUTbi2szylgr+O0OB7gkIxEGzySLITZ2GpsaoX72YMCGI2jYAc+WUhPfvUnZYiauF4zTnN4V4TGuvFjJlw==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
+jss-plugin-rule-value-function@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.2.tgz#9afe07596e477123cbf11120776be6a64494541f"
+  integrity sha512-vf5ms8zvLFMub6swbNxvzsurHfUZ5Shy5aJB2gIpY6WNA3uLinEcxYyraQXItRHi5ivXGqYciFDRM2ZoVoRZ4Q==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
+jss-plugin-rule-value-observable@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.9.2.tgz#3e024ccc3f1188116ccbf5e6b7825c42ccee57c2"
+  integrity sha512-SSqBD4s/k2mwsOUg6+LI/oEmvUxokIWi+5bZOyer/2nP4kMxeo3gHURc2yiAEu3v62Sf3GHhgC6pBAugxhLL9A==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    symbol-observable "^1.2.0"
+
+jss-plugin-template@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-template/-/jss-plugin-template-10.9.2.tgz#df03c552d171948e061bdb7fa660245fbd9a5450"
+  integrity sha512-f+ANQg8n+tkYea4Fu1Qt4skv9UJiNllzJB1Ga0QyumDZZJVpCzl8/mbFT1cvQSW7h+yB31GexFYVF3ct5fFGzA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
+jss-plugin-vendor-prefixer@10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.2.tgz#410a0f3b9f8dbbfba58f4d329134df4849aa1237"
+  integrity sha512-SxcEoH+Rttf9fEv6KkiPzLdXRmI6waOTcMkbbEFgdZLDYNIP9UKNHFy6thhbRKqv0XMQZdrEsbDyV464zE/dUA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    css-vendor "^2.0.8"
+    jss "10.9.2"
+
+jss-preset-default@^10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-10.9.2.tgz#684e0c0a2ce3b1127e990457ebc0ba71272780f3"
+  integrity sha512-HMkTLgYPRjwdiu8n8ZB2VEfpO95cZ5AmmSYvFSvt76MQJMp/xDh6cP49MmZHwMpIvXwNj0LI8Peglgwz+rHKBQ==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    jss-plugin-camel-case "10.9.2"
+    jss-plugin-compose "10.9.2"
+    jss-plugin-default-unit "10.9.2"
+    jss-plugin-expand "10.9.2"
+    jss-plugin-extend "10.9.2"
+    jss-plugin-global "10.9.2"
+    jss-plugin-nested "10.9.2"
+    jss-plugin-props-sort "10.9.2"
+    jss-plugin-rule-value-function "10.9.2"
+    jss-plugin-rule-value-observable "10.9.2"
+    jss-plugin-template "10.9.2"
+    jss-plugin-vendor-prefixer "10.9.2"
+
+jss@10.9.2, jss@^10.9.2:
+  version "10.9.2"
+  resolved "https://registry.npmjs.org/jss/-/jss-10.9.2.tgz#9379be1f195ef98011dfd31f9448251bd61b95a9"
+  integrity sha512-b8G6rWpYLR4teTUbGd4I4EsnWjg7MN0Q5bSsjKhVkJVjhQDy2KzkbD2AW3TuT0RYZVmZZHKIrXDn6kjU14qkUg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    csstype "^3.0.2"
+    is-in-browser "^1.1.3"
+    tiny-warning "^1.0.2"
+
 "jsx-ast-utils@^2.4.1 || ^3.0.0":
   version "3.3.3"
   resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
@@ -6114,33 +6291,33 @@ known-css-properties@^0.25.0:
   resolved "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776"
   integrity sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==
 
-lerna@^5.5.2:
-  version "5.6.2"
-  resolved "https://registry.npmjs.org/lerna/-/lerna-5.6.2.tgz#cdcdfe4e8bf07eccb4ecff1c216def9c67e62af2"
-  integrity sha512-Y0yMPslvnBnTZi7Nrs/gDyYZYauNf61xWNCehISHIORxZmmpoluNkcWTfcyb47is5uJQCv5QJX5xKKubbs+a6w==
-  dependencies:
-    "@lerna/add" "5.6.2"
-    "@lerna/bootstrap" "5.6.2"
-    "@lerna/changed" "5.6.2"
-    "@lerna/clean" "5.6.2"
-    "@lerna/cli" "5.6.2"
-    "@lerna/command" "5.6.2"
-    "@lerna/create" "5.6.2"
-    "@lerna/diff" "5.6.2"
-    "@lerna/exec" "5.6.2"
-    "@lerna/import" "5.6.2"
-    "@lerna/info" "5.6.2"
-    "@lerna/init" "5.6.2"
-    "@lerna/link" "5.6.2"
-    "@lerna/list" "5.6.2"
-    "@lerna/publish" "5.6.2"
-    "@lerna/run" "5.6.2"
-    "@lerna/version" "5.6.2"
-    "@nrwl/devkit" ">=14.8.1 < 16"
+lerna@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.npmjs.org/lerna/-/lerna-6.0.1.tgz#7b14f05d1e17dc628478d33f225a579a6088d317"
+  integrity sha512-aNodtj1jyuEqzYmkYh+vTfRuzLkG3RZkvYxFCuLeXXzIYD5pjMHtf+1q4m03SPsZt+cElhhwkgjdg6GjihraBw==
+  dependencies:
+    "@lerna/add" "6.0.1"
+    "@lerna/bootstrap" "6.0.1"
+    "@lerna/changed" "6.0.1"
+    "@lerna/clean" "6.0.1"
+    "@lerna/cli" "6.0.1"
+    "@lerna/command" "6.0.1"
+    "@lerna/create" "6.0.1"
+    "@lerna/diff" "6.0.1"
+    "@lerna/exec" "6.0.1"
+    "@lerna/import" "6.0.1"
+    "@lerna/info" "6.0.1"
+    "@lerna/init" "6.0.1"
+    "@lerna/link" "6.0.1"
+    "@lerna/list" "6.0.1"
+    "@lerna/publish" "6.0.1"
+    "@lerna/run" "6.0.1"
+    "@lerna/version" "6.0.1"
+    "@nrwl/devkit" ">=14.8.6 < 16"
     import-local "^3.0.2"
     inquirer "^8.2.4"
     npmlog "^6.0.2"
-    nx ">=14.8.1 < 16"
+    nx ">=14.8.6 < 16"
     typescript "^3 || ^4"
 
 level-codec@^9.0.0:
@@ -7108,13 +7285,13 @@ nwsapi@^2.2.0:
   resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0"
   integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==
 
-nx@15.0.0, "nx@>=14.8.1 < 16":
-  version "15.0.0"
-  resolved "https://registry.npmjs.org/nx/-/nx-15.0.0.tgz#8f1a291b7393861242b5c0f0d03c6317aed9c182"
-  integrity sha512-uh9Ou5oj7yr6Uyp4QhqW1vIVoanYn1sJM1jzOyoT17GAhhODfS0BtQgUvlmInDuRqP8LMaPg4LXFMby07U1HXg==
+nx@15.0.1, "nx@>=14.8.6 < 16":
+  version "15.0.1"
+  resolved "https://registry.npmjs.org/nx/-/nx-15.0.1.tgz#f4a4b1f90e8fdba8da1c0daf102ae5562095b74c"
+  integrity sha512-4pGy6f0SMQpg5kr38I95OkzufgkeMf4n/ui9o2Xk65mFdqXcCzRgRXbKdDhABhdZmhbzV33M+BUPJmMrTw3XDg==
   dependencies:
-    "@nrwl/cli" "15.0.0"
-    "@nrwl/tao" "15.0.0"
+    "@nrwl/cli" "15.0.1"
+    "@nrwl/tao" "15.0.1"
     "@parcel/watcher" "2.0.4"
     "@yarnpkg/lockfile" "^1.1.0"
     "@yarnpkg/parsers" "^3.0.0-rc.18"
@@ -8993,6 +9170,11 @@ svg-url-loader@~6.0.0:
     file-loader "~6.0.0"
     loader-utils "~2.0.0"
 
+symbol-observable@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
+  integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
+
 symbol-tree@^3.2.4:
   version "3.2.4"
   resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
@@ -9125,6 +9307,11 @@ timers-ext@^0.1.7:
     es5-ext "~0.10.46"
     next-tick "1"
 
+tiny-warning@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
+  integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
 tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"


Test patch:
diff --git a/.github/environment-test.yml b/.github/environment-test.yml
index 47a3c2d..9edc47e 100644
--- a/.github/environment-test.yml
+++ b/.github/environment-test.yml
@@ -7,11 +7,12 @@ channels:
 dependencies:
   # a more precise python pin is added in CI
   ### environment-base.yml ###
-  - python >=3.7,<3.11
-  - pip
   - doit-with-toml
-  - jupyterlab >=3.4.8,<4
   - ipywidgets >=8
+  - jupyterlab >=3.4.8,<4
+  - jupyterlab-fonts >=2.1.1
+  - pip
+  - python >=3.7,<3.11
   ### environment-base.yml ###
   ### environment-build.yml ###
   # runtimes
diff --git a/atest/fixtures/jupyter_config.json b/atest/fixtures/jupyter_config.json
new file mode 100644
index 0000000..b2ef6be
--- /dev/null
+++ b/atest/fixtures/jupyter_config.json
@@ -0,0 +1,14 @@
+{
+  "LabApp": {
+    "log_level": "DEBUG",
+    "open_browser": false
+  },
+  "ServerApp": {
+    "tornado_settings": {
+      "page_config_data": {
+        "buildCheck": false,
+        "buildAvailable": false
+      }
+    }
+  }
+}
diff --git a/atest/resources/Deck.resource b/atest/resources/Deck.resource
index 9b264a7..9adb6ac 100644
--- a/atest/resources/Deck.resource
+++ b/atest/resources/Deck.resource
@@ -14,6 +14,7 @@ ${ZERO_PAD}     {0:03d}
 Start Deck With Notebook Toolbar Button
     [Documentation]    Use the notebook toolbar to start deck.
     Wait Until Element Is Not Visible    css:${CSS_LAB_SPINNER}
+    Click Element    css:${JLAB CSS ACTIVE DOC}
     Click Element    css:${CSS_DECK_NOTEBOOK_BUTTON}
     Wait Until Element Is Visible    css:${CSS_DECK_PRESENTING}
     Wait Until Element Is Visible    css:${CSS_DECK_VISIBLE}
@@ -89,7 +90,7 @@ Really Back Up Deck With Keyboard
     Really Advance Deck With Keyboard    ${screenshot}    ${expect}    backup=${TRUE}
 
 Make Cell Layer
-    [Documentation]    Use the Property Inspector to make
+    [Documentation]    Use the Property Inspector to make a cell a layer
     [Arguments]    ${idx}    ${layer}    ${screenshot}=${EMPTY}
     Click Element    css:${JLAB CSS ACTIVE DOC CELLS}:nth-child(${idx})
     Maybe Open JupyterLab Sidebar    Property Inspector
@@ -101,3 +102,14 @@ Make Cell Layer
         Wait Until Cell Metadata Does Not Contain    jupyterlab-deck
     END
     IF    ${screenshot.__len__()}    Capture Page Screenshot    ${screenshot}
+
+Use Cell Style Preset
+    [Documentation]    Use the Property Inspector to use a cell preset
+    [Arguments]    ${idx}    ${preset}    ${expect}=${EMPTY}    ${screenshot}=${EMPTY}
+    Click Element    css:${JLAB CSS ACTIVE DOC CELLS}:nth-child(${idx})
+    Maybe Open JupyterLab Sidebar    Property Inspector
+    Maybe Open Cell Metadata JSON
+    Select From List By Value    css:${CSS_DECK_PRESET_SELECT}    ${preset}
+    Click Element    css:${CSS_DECK_TOOL_PRESET} button
+    IF    ${expect.__len__()}    Wait Until Cell Metadata Contains    ${expect}
+    IF    ${screenshot.__len__()}    Capture Page Screenshot    ${screenshot}
diff --git a/atest/resources/DeckSelectors.resource b/atest/resources/DeckSelectors.resource
index d756f8e..5b3238a 100644
--- a/atest/resources/DeckSelectors.resource
+++ b/atest/resources/DeckSelectors.resource
@@ -23,3 +23,5 @@ ${CSS_DECK_DIR_STEM}            .jp-Deck-Remote .jp-deck-mod-direction
 
 # metadata
 ${CSS_DECK_LAYER_SELECT}        \#id-jp-decktools-select-layer
+${CSS_DECK_PRESET_SELECT}       \#id-jp-decktools-select-preset
+${CSS_DECK_TOOL_PRESET}         .jp-Deck-Tool-preset
diff --git a/atest/resources/Docs.resource b/atest/resources/Docs.resource
new file mode 100644
index 0000000..2b2fa2b
--- /dev/null
+++ b/atest/resources/Docs.resource
@@ -0,0 +1,42 @@
+*** Settings ***
+Documentation       Keywords for interactive tests
+
+Library             OperatingSystem
+Library             JupyterLibrary
+Resource            ./Coverage.resource
+Resource            ./Deck.resource
+Resource            ./Lab.resource
+Resource            ./Screenshots.resource
+
+
+*** Keywords ***
+Start Empty Notebook Deck
+    [Documentation]    Start an empty deck
+    Launch A New JupyterLab Document
+    Wait Until JupyterLab Kernel Is Idle
+    Really Start Deck With Notebook Toolbar Button
+
+Start Basic Notebook Deck
+    [Documentation]    Make a few cells
+    Start Empty Notebook Deck
+    Click Element    css:${JLAB CSS ACTIVE CELL}
+    Make Markdown Cell    \# Hello World    Hello World    new=${FALSE}    screenshot=s0-00-hello.png
+    Make Markdown Cell    - item1234    item1234    screenshot=s0-01-1234.png
+    Make Markdown Cell    - item4567    item4567    screenshot=s0-02-4567.png
+
+Tear Down Interactive Suite
+    [Documentation]    Clean up after this suite.
+    Execute JupyterLab Command    Close All Tabs
+
+Reset Interactive Test
+    [Documentation]    Clean up after each test.
+    Maybe Open JupyterLab Sidebar    Commands
+    Execute JupyterLab Command    Save Notebook
+    ${nbdir} =    Get Jupyter Directory
+    Remove File    Untitled.ipynb
+    Execute JupyterLab Command    Close All Tabs
+
+Set Up Interactive Suite
+    [Documentation]    Prepare for this suite.
+    [Arguments]    ${screens}
+    Set Attempt Screenshot Directory    lab${/}${screens}
diff --git a/atest/resources/Fixtures.resource b/atest/resources/Fixtures.resource
index 13a5106..d059e04 100644
--- a/atest/resources/Fixtures.resource
+++ b/atest/resources/Fixtures.resource
@@ -44,9 +44,3 @@ Open Example
         Wait Until Element Is Visible    css:${sel}
         Double Click Element    css:${sel}
     END
-
-Clean Examples With Coverage
-    [Documentation]    Remove the examples directory and gather coverage.
-    Execute JupyterLab Command    Close All Tabs
-    Reset JupyterLab And Close With Coverage
-    Clean Examples
diff --git a/atest/resources/Screenshots.resource b/atest/resources/Screenshots.resource
new file mode 100644
index 0000000..42b132c
--- /dev/null
+++ b/atest/resources/Screenshots.resource
@@ -0,0 +1,12 @@
+*** Settings ***
+Documentation       Keywords for working with screenshots
+
+Library             JupyterLibrary
+
+
+*** Keywords ***
+Set Attempt Screenshot Directory
+    [Documentation]    Set a screenshot directory that includes the attempt
+    [Arguments]    ${path}
+    Set Screenshot Directory
+    ...    ${OUTPUT_DIR}${/}screenshots${/}${OS.lower()[:2]}_${ATTEMPT}${/}${path}
diff --git a/atest/suites/__init__.robot b/atest/suites/__init__.robot
index ec346fc..566e25a 100644
--- a/atest/suites/__init__.robot
+++ b/atest/suites/__init__.robot
@@ -1,9 +1,12 @@
 *** Settings ***
 Documentation       Global test configuration.
 
+Library             Process
 Library             JupyterLibrary
+Resource            ../resources/Screenshots.resource
 
 Suite Setup         Set Up Root Suite
+Suite Teardown      Tear Down Root Suite
 
 Force Tags          attempt:${attempt}    os:${os}    py:${py}
 
@@ -11,4 +14,9 @@ Force Tags          attempt:${attempt}    os:${os}    py:${py}
 *** Keywords ***
 Set Up Root Suite
     [Documentation]    Do global suite setup.
-    Log    Nothing to do here yet
+    Set Attempt Screenshot Directory    ${EMPTY}
+
+Tear Down Root Suite
+    [Documentation]    Do global suite teardown.
+    Close All Browsers
+    Terminate All Processes
diff --git a/atest/suites/lab/00-smoke.robot b/atest/suites/lab/00-smoke.robot
index 3271e2f..4e2978e 100644
--- a/atest/suites/lab/00-smoke.robot
+++ b/atest/suites/lab/00-smoke.robot
@@ -3,8 +3,9 @@ Documentation       JupyterLab is not broken.
 
 Library             JupyterLibrary
 Resource            ../../resources/Coverage.resource
+Resource            ../../resources/Screenshots.resource
 
-Suite Setup         Set Screenshot Directory    ${OUTPUT_DIR}${/}lab${/}smoke
+Suite Setup         Set Attempt Screenshot Directory    lab${/}smoke
 
 Force Tags          suite:smoke
 
@@ -12,5 +13,4 @@ Force Tags          suite:smoke
 *** Test Cases ***
 JupyterLab Opens
     [Documentation]    JupyterLab opens.
-    Open JupyterLab
     Capture Page Screenshot    00-smoke.png
diff --git a/atest/suites/lab/01-examples.robot b/atest/suites/lab/01-examples.robot
index 2f90146..b32fa8f 100644
--- a/atest/suites/lab/01-examples.robot
+++ b/atest/suites/lab/01-examples.robot
@@ -5,10 +5,10 @@ Library             OperatingSystem
 Library             JupyterLibrary
 Resource            ../../resources/Fixtures.resource
 Resource            ../../resources/Deck.resource
+Resource            ../../resources/Screenshots.resource
 
 Suite Setup         Set Up Example Suite
-Suite Teardown      Tear Down Example Suite
-Test Teardown       Reset Example Test
+Suite Teardown      Clean Examples
 
 Force Tags          suite:examples
 
@@ -43,19 +43,10 @@ Visit All Example Slides And Fragments
 
 Set Up Example Suite
     [Documentation]    Prepare for this suite.
-    Set Screenshot Directory    ${OUTPUT_DIR}${/}lab${/}examples
+    Set Attempt Screenshot Directory    lab${/}examples
     Copy Examples
-    Open JupyterLab
-    Disable JupyterLab Modal Command Palette
-    Reload Page
-    Maybe Wait For JupyterLab Splash Screen
-
-Tear Down Example Suite
-    [Documentation]    Clean up after this suite.
-    Clean Examples With Coverage
 
 Reset Example Test
     [Documentation]    Clean up after each test.
     Maybe Open JupyterLab Sidebar    Commands
     Execute JupyterLab Command    Close All Tabs
-    Execute JupyterLab Command    Shut Down All Kernels
diff --git a/atest/suites/lab/02-interactive.robot b/atest/suites/lab/02-interactive.robot
deleted file mode 100644
index 83e095e..0000000
--- a/atest/suites/lab/02-interactive.robot
+++ /dev/null
@@ -1,75 +0,0 @@
-*** Settings ***
-Documentation       Building a deck interactively is fun.
-
-Library             OperatingSystem
-Library             JupyterLibrary
-Resource            ../../resources/Coverage.resource
-Resource            ../../resources/Deck.resource
-Resource            ../../resources/Lab.resource
-
-Suite Setup         Set Up Interactive Suite
-Suite Teardown      Tear Down Interactive Suite
-Test Teardown       Reset Interactive Test
-
-Force Tags          suite:interactive
-
-
-*** Test Cases ***
-Build and Navigate a Notebook Slide
-    [Documentation]    Build a basic slide.
-    Set Screenshot Directory    ${OUTPUT_DIR}${/}lab${/}interactive${/}slide
-    Start Basic Notebook Deck
-    Really Back Up Deck With Keyboard    s0-03-backup.png    item1234
-    Really Back Up Deck With Keyboard    s0-04-backup.png    World
-    Really Advance Deck With Keyboard    s0-05-advance.png    item1234
-    Really Advance Deck With Keyboard    s0-06-advance.png    item4567
-
-Build A Slide With Layers
-    [Documentation]    Use the metadata sidebar to work with layers.
-    Set Screenshot Directory    ${OUTPUT_DIR}${/}lab${/}interactive${/}layers
-    Start Basic Notebook Deck
-    Make Markdown Cell    - item91011    item91011    screenshot=s0-03-91011.png
-    Make Markdown Cell    - item121314    item121314    screenshot=s0-04-121314.png
-    Make Cell Layer    2    deck    s0-05-deck.png
-    Make Cell Layer    3    stack    s0-06-stack.png
-    Make Cell Layer    4    slide    s0-07-slide.png
-    Make Cell Layer    4    -    s0-08-null.png
-    Make Cell Layer    5    fragment    s0-09-fragment.png
-
-
-*** Keywords ***
-Start Empty Notebook Deck
-    [Documentation]    Start an empty deck
-    Launch A New JupyterLab Document
-    Wait Until JupyterLab Kernel Is Idle
-    Really Start Deck With Notebook Toolbar Button
-
-Start Basic Notebook Deck
-    [Documentation]    Make a few cells
-    Start Empty Notebook Deck
-    Click Element    css:${JLAB CSS ACTIVE CELL}
-    Make Markdown Cell    \# Hello World    Hello World    new=${FALSE}    screenshot=s0-00-hello.png
-    Make Markdown Cell    - item1234    item1234    screenshot=s0-01-1234.png
-    Make Markdown Cell    - item4567    item4567    screenshot=s0-02-4567.png
-
-Set Up Interactive Suite
-    [Documentation]    Prepare for this suite.
-    Set Screenshot Directory    ${OUTPUT_DIR}${/}lab${/}interactive
-    Open JupyterLab
-    Disable JupyterLab Modal Command Palette
-    Reload Page
-    Maybe Wait For JupyterLab Splash Screen
-
-Tear Down Interactive Suite
-    [Documentation]    Clean up after this suite.
-    Execute JupyterLab Command    Close All Tabs
-    Reset JupyterLab And Close With Coverage
-
-Reset Interactive Test
-    [Documentation]    Clean up after each test.
-    Maybe Open JupyterLab Sidebar    Commands
-    Execute JupyterLab Command    Save Notebook
-    ${nbdir} =    Get Jupyter Directory
-    Remove File    Untitled.ipynb
-    Execute JupyterLab Command    Close All Tabs
-    Execute JupyterLab Command    Shut Down All Kernels
diff --git a/atest/suites/lab/02-keyboard.robot b/atest/suites/lab/02-keyboard.robot
new file mode 100644
index 0000000..da5a6dc
--- /dev/null
+++ b/atest/suites/lab/02-keyboard.robot
@@ -0,0 +1,27 @@
+*** Settings ***
+Documentation       Building a deck interactively is fun.
+
+Library             OperatingSystem
+Library             JupyterLibrary
+Resource            ../../resources/Coverage.resource
+Resource            ../../resources/Deck.resource
+Resource            ../../resources/Lab.resource
+Resource            ../../resources/Screenshots.resource
+Resource            ../../resources/Docs.resource
+
+Suite Setup         Set Up Interactive Suite    keyboard
+Suite Teardown      Tear Down Interactive Suite
+Test Teardown       Reset Interactive Test
+
+Force Tags          suite:keyboard
+
+
+*** Test Cases ***
+Build and Navigate a Notebook Slide With Keyboard
+    [Documentation]    Build and navigate a basic slide.
+    Set Attempt Screenshot Directory    lab${/}interactive${/}slide
+    Start Basic Notebook Deck
+    Really Back Up Deck With Keyboard    s0-03-backup.png    item1234
+    Really Back Up Deck With Keyboard    s0-04-backup.png    World
+    Really Advance Deck With Keyboard    s0-05-advance.png    item1234
+    Really Advance Deck With Keyboard    s0-06-advance.png    item4567
diff --git a/atest/suites/lab/03-layers.robot b/atest/suites/lab/03-layers.robot
new file mode 100644
index 0000000..2b39fd7
--- /dev/null
+++ b/atest/suites/lab/03-layers.robot
@@ -0,0 +1,43 @@
+*** Settings ***
+Documentation       Building a deck interactively is fun.
+
+Library             OperatingSystem
+Library             JupyterLibrary
+Resource            ../../resources/Coverage.resource
+Resource            ../../resources/Deck.resource
+Resource            ../../resources/Lab.resource
+Resource            ../../resources/Screenshots.resource
+Resource            ../../resources/Docs.resource
+
+Suite Setup         Set Up Interactive Suite    layers
+Suite Teardown      Tear Down Interactive Suite
+Test Teardown       Reset Interactive Test
+
+Force Tags          suite:layers
+
+
+*** Variables ***
+${FADE_JSON}    "opacity": "0.125"
+
+
+*** Test Cases ***
+Build A Slide With Layers
+    [Documentation]    Use the sidebar to work with layers.
+    Set Attempt Screenshot Directory    lab${/}interactive${/}layers
+    Start Basic Notebook Deck
+    Make Markdown Cell    - item91011    item91011    screenshot=s0-03-91011.png
+    Make Markdown Cell    - item121314    item121314    screenshot=s0-04-121314.png
+    Make Cell Layer    2    deck    s0-05-deck.png
+    Make Cell Layer    3    stack    s0-06-stack.png
+    Make Cell Layer    4    slide    s0-07-slide.png
+    Make Cell Layer    4    -    s0-08-null.png
+    Make Cell Layer    5    fragment    s0-09-fragment.png
+
+Build A Slide With Style Presets
+    [Documentation]    Use the sidebar to work with presets.
+    Set Attempt Screenshot Directory    lab${/}interactive${/}presets
+    Start Basic Notebook Deck
+    Use Cell Style Preset    2    fade-out    ${FADE_JSON}    s0-03-fragment-fade.png
+    Make Cell Layer    2    deck    s0-04-deck-layer.png
+    Capture Page Screenshot    s0-05-deck.png
+    [Teardown]    Stop Deck With Remote
diff --git a/atest/suites/lab/__init__.robot b/atest/suites/lab/__init__.robot
index 5b9c6a1..cf2c3b3 100644
--- a/atest/suites/lab/__init__.robot
+++ b/atest/suites/lab/__init__.robot
@@ -1,11 +1,48 @@
 *** Settings ***
 Documentation       Tests for JupyterLab.
 
+Library             uuid
 Library             JupyterLibrary
 Resource            ../../resources/Coverage.resource
 
-Suite Setup         Wait For New Jupyter Server To Be Ready
-Suite Teardown      Terminate All Jupyter Servers
-Test Teardown       Reset JupyterLab And Close With Coverage
+Suite Setup         Set Up Lab Suite
+Suite Teardown      Tear Down Lab Suite
 
 Force Tags          app:lab
+
+
+*** Variables ***
+${LOG_DIR}      ${OUTPUT_DIR}${/}logs
+
+
+*** Keywords ***
+Set Up Lab Suite
+    [Documentation]    Ensure a testable server is running
+    ${port} =    Get Unused Port
+    ${base_url} =    Set Variable    /@rf/
+    ${token} =    UUID4
+    Create Directory    ${LOG_DIR}
+    Wait For New Jupyter Server To Be Ready
+    ...    jupyter-lab
+    ...    ${port}
+    ...    ${base_url}
+    ...    ${NONE}    # notebook_dir
+    ...    ${token.__str__()}
+    ...    --config\=${ROOT}${/}atest${/}fixtures${/}jupyter_config.json
+    ...    --no-browser
+    ...    --debug
+    ...    --port\=${port}
+    ...    --NotebookApp.token\='${token.__str__()}'
+    ...    --NotebookApp.base_url\='${base_url}'
+    ...    stdout=${LOG_DIR}${/}lab.log
+    Open JupyterLab
+    Disable JupyterLab Modal Command Palette
+    Set Window Size    1366    768
+    Reload Page
+    Wait For JupyterLab Splash Screen
+
+Tear Down Lab Suite
+    [Documentation]    Do clean up stuff
+    Execute JupyterLab Command    Close All Tabs
+    Execute JupyterLab Command    Shut Down All Kernels
+    Reset JupyterLab And Close With Coverage