Explorar el Código

Merge branch 'menuarea' of github.com:jasongrout/jupyterlab into menuarea

Jason Grout hace 4 años
padre
commit
c00c88f547
Se han modificado 42 ficheros con 328 adiciones y 191 borrados
  1. 1 1
      builder/src/build.ts
  2. 2 2
      dev_mode/package.json
  3. 2 2
      examples/app/package.json
  4. 2 2
      examples/federated/core_package/package.json
  5. 2 2
      jupyterlab/staging/package.json
  6. 2 1
      packages/application-extension/package.json
  7. 58 2
      packages/application-extension/src/index.tsx
  8. 0 45
      packages/application/src/shell.ts
  9. 0 4
      packages/application/style/base.css
  10. 0 54
      packages/application/style/buttons.css
  11. 9 8
      packages/application/test/shell.spec.ts
  12. 4 4
      packages/apputils/package.json
  13. 2 2
      packages/cells/package.json
  14. 1 1
      packages/codemirror/package.json
  15. 1 1
      packages/debugger-extension/package.json
  16. 2 2
      packages/debugger/package.json
  17. 1 1
      packages/docmanager/package.json
  18. 1 1
      packages/documentsearch/package.json
  19. 2 2
      packages/extensionmanager-extension/examples/listings/package.json
  20. 1 1
      packages/extensionmanager/package.json
  21. 1 1
      packages/filebrowser/package.json
  22. 1 1
      packages/fileeditor/package.json
  23. 1 1
      packages/help-extension/package.json
  24. 1 1
      packages/htmlviewer/package.json
  25. 4 4
      packages/json-extension/package.json
  26. 2 2
      packages/launcher/package.json
  27. 1 1
      packages/logconsole-extension/package.json
  28. 1 1
      packages/notebook/package.json
  29. 1 1
      packages/property-inspector/package.json
  30. 1 1
      packages/running/package.json
  31. 4 4
      packages/settingeditor/package.json
  32. 2 2
      packages/statusbar-extension/package.json
  33. 1 1
      packages/statusbar/package.json
  34. 4 7
      packages/toc/package.json
  35. 4 4
      packages/ui-components/package.json
  36. 1 0
      packages/ui-components/src/components/index.ts
  37. 103 0
      packages/ui-components/src/components/switch.ts
  38. 1 0
      packages/ui-components/style/base.css
  39. 55 0
      packages/ui-components/style/switch.css
  40. 4 4
      packages/vdom/package.json
  41. 10 10
      scripts/ci_script.sh
  42. 32 7
      yarn.lock

+ 1 - 1
builder/src/build.ts

@@ -199,7 +199,7 @@ export namespace Build {
       themeConfig.push({
         mode: 'production',
         entry: {
-          index: path.join(name, themePath)
+          index: path.join(packageDir, themePath)
         },
         output: {
           path: path.resolve(path.join(themeOutput, 'themes', name)),

+ 2 - 2
dev_mode/package.json

@@ -116,8 +116,8 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "dependencies": {
     "@jupyterlab/application": "~3.0.0-rc.6",

+ 2 - 2
examples/app/package.json

@@ -40,8 +40,8 @@
     "@jupyterlab/translation-extension": "^3.0.0-rc.6",
     "@jupyterlab/ui-components-extension": "^3.0.0-rc.6",
     "es6-promise": "~4.2.8",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "devDependencies": {
     "css-loader": "~3.2.0",

+ 2 - 2
examples/federated/core_package/package.json

@@ -107,8 +107,8 @@
     "@lumino/signaling": "^1.3.5",
     "@lumino/virtualdom": "^1.6.1",
     "@lumino/widgets": "^1.11.1",
-    "react": "~16.9.0",
-    "react-dom": "~16.9.0"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "dependencies": {
     "@jupyterlab/application": "^3.0.0-rc.6",

+ 2 - 2
jupyterlab/staging/package.json

@@ -116,8 +116,8 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "dependencies": {
     "@jupyterlab/application": "~3.0.0-rc.6",

+ 2 - 1
packages/application-extension/package.json

@@ -45,10 +45,11 @@
     "@jupyterlab/translation": "^3.0.0-rc.6",
     "@jupyterlab/ui-components": "^3.0.0-rc.6",
     "@lumino/algorithm": "^1.3.3",
+    "@lumino/commands": "^1.11.3",
     "@lumino/coreutils": "^1.5.3",
     "@lumino/disposable": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 58 - 2
packages/application-extension/src/index.tsx

@@ -39,10 +39,12 @@ import { IStateDB } from '@jupyterlab/statedb';
 
 import { ITranslator, TranslationBundle } from '@jupyterlab/translation';
 
-import { buildIcon } from '@jupyterlab/ui-components';
+import { buildIcon, Switch } from '@jupyterlab/ui-components';
 
 import { each, iter, toArray } from '@lumino/algorithm';
 
+import { CommandRegistry } from '@lumino/commands';
+
 import { PromiseDelegate } from '@lumino/coreutils';
 
 import { DisposableDelegate, DisposableSet } from '@lumino/disposable';
@@ -940,6 +942,59 @@ const propertyInspector: JupyterFrontEndPlugin<IPropertyInspectorProvider> = {
   }
 };
 
+/**
+ * The single-document mode switch in the top area.
+ */
+const modeSwitch: JupyterFrontEndPlugin<void> = {
+  id: '@jupyterlab/application-extension:mode-switch',
+  requires: [ILabShell, ITranslator],
+  activate: (
+    app: JupyterFrontEnd,
+    shell: ILabShell,
+    translator: ITranslator
+  ) => {
+    const trans = translator.load('jupyterlab');
+
+    const spacer = new Widget();
+    spacer.id = 'jp-top-spacer';
+    spacer.node.style.flexGrow = '1';
+    shell.add(spacer, 'top', { rank: 1000 });
+
+    const modeSwitch = new Switch();
+    modeSwitch.id = 'jp-single-document-mode';
+
+    modeSwitch.valueChanged.connect((_, args) => {
+      shell.mode = args.newValue ? 'single-document' : 'multiple-document';
+    });
+    shell.modeChanged.connect((_, mode) => {
+      modeSwitch.value = mode === 'single-document';
+    });
+    modeSwitch.value = shell.mode === 'single-document';
+
+    // Show the current file browser shortcut in its title.
+    const updateModeSwitchTitle = () => {
+      const binding = app.commands.keyBindings.find(
+        b => b.command === CommandIDs.toggleMode
+      );
+      if (binding) {
+        const ks = CommandRegistry.formatKeystroke(binding.keys.join(' '));
+        modeSwitch.caption = trans.__('Single-Document Mode (%1)', ks);
+      } else {
+        modeSwitch.caption = trans.__('Single-Document Mode');
+      }
+    };
+    updateModeSwitchTitle();
+    app.commands.keyBindingChanged.connect(() => {
+      updateModeSwitchTitle();
+    });
+
+    modeSwitch.label = trans.__('Mode');
+
+    shell.add(modeSwitch, 'top', { rank: 1010 });
+  },
+  autoStart: true
+};
+
 /**
  * Export the plugins as default.
  */
@@ -955,7 +1010,8 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
   status,
   info,
   paths,
-  propertyInspector
+  propertyInspector,
+  modeSwitch
 ];
 
 export default plugins;

+ 0 - 45
packages/application/src/shell.ts

@@ -309,51 +309,6 @@ export class LabShell extends Widget implements JupyterFrontEnd.IShell {
     logo.id = 'jp-MainLogo';
     this._topHandler.addWidget(logo, 0);
 
-    // Set up single-document mode switch in menu bar
-    const spacer = new Widget();
-    spacer.id = 'jp-top-spacer';
-    this.add(spacer, 'top', { rank: 1000 });
-
-    // switch accessibility refs:
-    // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Switch_role
-    // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Accessibility_concerns
-    const sdmSwitch = document.createElement('button');
-    sdmSwitch.className = 'jp-slider jp-slider-sdm';
-    sdmSwitch.setAttribute('role', 'switch');
-    sdmSwitch.value = 'single-document';
-    sdmSwitch.title = 'Single-Document Mode';
-    this.modeChanged.connect((_, mode) => {
-      sdmSwitch.setAttribute(
-        'aria-checked',
-        mode === 'single-document' ? 'true' : 'false'
-      );
-    });
-    sdmSwitch.setAttribute(
-      'aria-checked',
-      this.mode === 'single-document' ? 'true' : 'false'
-    );
-    sdmSwitch.addEventListener('click', () => {
-      this.mode =
-        sdmSwitch.getAttribute('aria-checked') === 'true'
-          ? 'multiple-document'
-          : 'single-document';
-    });
-
-    const sdmLabel = document.createElement('label');
-    sdmLabel.className = 'jp-slider-label';
-    sdmLabel.textContent = 'Single-Document Mode';
-    sdmLabel.title = 'Single-Document Mode';
-    const sdmTrack = document.createElement('div');
-    sdmTrack.className = 'jp-slider-track';
-    sdmTrack.setAttribute('aria-hidden', 'true');
-    sdmSwitch.appendChild(sdmLabel);
-    sdmSwitch.appendChild(sdmTrack);
-
-    const sdmSwitchWidget = new Widget();
-    sdmSwitchWidget.node.appendChild(sdmSwitch);
-    sdmSwitchWidget.id = 'jp-single-document-mode';
-    this.add(sdmSwitchWidget, 'top', { rank: 1010 });
-
     // Wire up signals to update the title panel of the single document mode to
     // follow the title of this.currentWidget
     this.currentChanged.connect((sender, args) => {

+ 0 - 4
packages/application/style/base.css

@@ -76,10 +76,6 @@ body {
   display: flex;
 }
 
-#jp-top-spacer {
-  flex-grow: 1;
-}
-
 #jp-single-document-mode {
   margin: 0px 8px;
   display: flex;

+ 0 - 54
packages/application/style/buttons.css

@@ -79,57 +79,3 @@ button.jp-mod-styled.jp-mod-warn:active {
   box-shadow: none;
   background-color: rgba(153, 153, 153, 0.2);
 }
-
-.jp-slider {
-  display: flex;
-  align-items: center;
-  font-size: var(--jp-ui-font-size1);
-}
-
-.jp-slider-sdm {
-  border: none;
-  height: 20px;
-  background-color: transparent;
-  color: var(--jp-ui-font-color1);
-}
-
-.jp-slider:hover {
-  background-color: var(--jp-layout-color2);
-}
-
-.jp-slider-label {
-  margin-right: 5px;
-}
-
-.jp-slider-track {
-  cursor: pointer;
-  background-color: var(--jp-border-color1);
-  -webkit-transition: 0.4s;
-  transition: 0.4s;
-  border-radius: 34px;
-  height: 16px;
-  width: 35px;
-  position: relative;
-}
-
-.jp-slider-track::before {
-  content: '';
-  position: absolute;
-  height: 10px;
-  width: 10px;
-  margin: 3px;
-  left: 0px;
-  background-color: white;
-  -webkit-transition: 0.4s;
-  transition: 0.4s;
-  border-radius: 50%;
-}
-
-.jp-slider[aria-checked='true'] .jp-slider-track {
-  background-color: var(--jp-warn-color0);
-}
-
-.jp-slider[aria-checked='true'] .jp-slider-track::before {
-  /* track width (35) - margins (3 + 3) - thumb width (10) */
-  left: 19px;
-}

+ 9 - 8
packages/application/test/shell.spec.ts

@@ -91,8 +91,11 @@ describe('LabShell', () => {
       expect(shell.isEmpty('main')).toBe(false);
     });
 
-    it('should test whether the top area is not empty', () => {
-      // account for builtin sdm slider widget
+    it('should test whether the top area is empty', () => {
+      expect(shell.isEmpty('top')).toBe(true);
+      const widget = new Widget();
+      widget.id = 'foo';
+      shell.add(widget, 'top');
       expect(shell.isEmpty('top')).toBe(false);
     });
 
@@ -149,24 +152,22 @@ describe('LabShell', () => {
       const widget = new Widget();
       widget.id = 'foo';
       shell.add(widget, 'top');
-      // the added widget plus the builtin spacer and sdm slider widgets
+      // the added widget
       console.log(toArray(shell.widgets('top')));
-      expect(toArray(shell.widgets('top')).length).toEqual(3);
+      expect(toArray(shell.widgets('top')).length).toEqual(1);
     });
 
     it('should be a no-op if the widget has no id', () => {
       const widget = new Widget();
       shell.add(widget, 'top');
-      // the builtin spacer and sdm slider widgets alone
-      expect(toArray(shell.widgets('top')).length).toEqual(2);
+      expect(toArray(shell.widgets('top')).length).toEqual(0);
     });
 
     it('should accept options', () => {
       const widget = new Widget();
       widget.id = 'foo';
       shell.add(widget, 'top', { rank: 10 });
-      // the added widget plus the builtin spacer and sdm slider widgets
-      expect(toArray(shell.widgets('top')).length).toEqual(3);
+      expect(toArray(shell.widgets('top')).length).toEqual(1);
     });
 
     it('should add widgets according to their ranks', () => {

+ 4 - 4
packages/apputils/package.json

@@ -61,17 +61,17 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "@types/react": "~16.9.48",
+    "@types/react": "^16.9.48",
     "buffer": "^5.6.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1",
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1",
     "sanitize-html": "~1.27.4",
     "url": "^0.11.0"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",
     "@types/jest": "^26.0.10",
-    "@types/react-dom": "~16.9.8",
+    "@types/react-dom": "^16.9.8",
     "@types/sanitize-html": "^1.23.3",
     "jest": "^26.4.2",
     "rimraf": "~3.0.0",

+ 2 - 2
packages/cells/package.json

@@ -59,12 +59,12 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",
     "@types/jest": "^26.0.10",
-    "@types/react": "~16.9.48",
+    "@types/react": "^16.9.48",
     "jest": "^26.4.2",
     "rimraf": "~3.0.0",
     "ts-jest": "^26.3.0",

+ 1 - 1
packages/codemirror/package.json

@@ -54,7 +54,7 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
     "codemirror": "~5.57.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",

+ 1 - 1
packages/debugger-extension/package.json

@@ -66,7 +66,7 @@
     "@jupyterlab/testutils": "^3.0.0-rc.6",
     "@types/codemirror": "^0.0.97",
     "@types/jest": "^26.0.10",
-    "@types/react-dom": "~16.9.8",
+    "@types/react-dom": "^16.9.8",
     "jest": "^26.4.2",
     "jest-junit": "^11.1.0",
     "jest-raw-loader": "^1.0.1",

+ 2 - 2
packages/debugger/package.json

@@ -69,7 +69,7 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
     "codemirror": "~5.57.0",
-    "react": "~16.13.1",
+    "react": "^17.0.1",
     "vscode-debugprotocol": "^1.37.0"
   },
   "devDependencies": {
@@ -78,7 +78,7 @@
     "@jupyterlab/testutils": "^3.0.0-rc.6",
     "@types/codemirror": "^0.0.97",
     "@types/jest": "^26.0.10",
-    "@types/react-dom": "~16.9.8",
+    "@types/react-dom": "^16.9.8",
     "@types/text-encoding": "^0.0.35",
     "canvas": "^2.6.1",
     "jest": "^26.4.2",

+ 1 - 1
packages/docmanager/package.json

@@ -53,7 +53,7 @@
     "@lumino/properties": "^1.2.3",
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",

+ 1 - 1
packages/documentsearch/package.json

@@ -47,7 +47,7 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
     "codemirror": "~5.57.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 2 - 2
packages/extensionmanager-extension/examples/listings/package.json

@@ -39,8 +39,8 @@
     "@jupyterlab/tooltip-extension": "^2.0.2",
     "@jupyterlab/ui-components-extension": "^2.0.2",
     "es6-promise": "~4.2.8",
-    "react": "~16.9.0",
-    "react-dom": "~16.9.0"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "devDependencies": {
     "css-loader": "~3.2.0",

+ 1 - 1
packages/extensionmanager/package.json

@@ -45,7 +45,7 @@
     "@lumino/messaging": "^1.4.3",
     "@lumino/polling": "^1.3.3",
     "@lumino/signaling": "^1.4.3",
-    "react": "~16.13.1",
+    "react": "^17.0.1",
     "react-paginate": "^6.3.2",
     "semver": "^7.3.2"
   },

+ 1 - 1
packages/filebrowser/package.json

@@ -59,7 +59,7 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",

+ 1 - 1
packages/fileeditor/package.json

@@ -49,7 +49,7 @@
     "@lumino/coreutils": "^1.5.3",
     "@lumino/messaging": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",

+ 1 - 1
packages/help-extension/package.json

@@ -45,7 +45,7 @@
     "@jupyterlab/translation": "^3.0.0-rc.6",
     "@jupyterlab/ui-components": "^3.0.0-rc.6",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 1 - 1
packages/htmlviewer/package.json

@@ -39,7 +39,7 @@
     "@jupyterlab/ui-components": "^3.0.0-rc.6",
     "@lumino/coreutils": "^1.5.3",
     "@lumino/signaling": "^1.4.3",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 4 - 4
packages/json-extension/package.json

@@ -41,14 +41,14 @@
     "@lumino/coreutils": "^1.5.3",
     "@lumino/messaging": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1",
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1",
     "react-highlighter": "^0.4.3",
     "react-json-tree": "^0.12.1"
   },
   "devDependencies": {
-    "@types/react": "~16.9.48",
-    "@types/react-dom": "~16.9.8",
+    "@types/react": "^16.9.48",
+    "@types/react-dom": "^16.9.8",
     "@types/react-highlighter": "^0.3.4",
     "@types/react-json-tree": "^0.6.11",
     "rimraf": "~3.0.0",

+ 2 - 2
packages/launcher/package.json

@@ -44,10 +44,10 @@
     "@lumino/disposable": "^1.4.3",
     "@lumino/properties": "^1.2.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
-    "@types/react": "~16.9.48",
+    "@types/react": "^16.9.48",
     "rimraf": "~3.0.0",
     "typedoc": "0.17.0-3",
     "typescript": "~4.0.2"

+ 1 - 1
packages/logconsole-extension/package.json

@@ -47,7 +47,7 @@
     "@lumino/coreutils": "^1.5.3",
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 1 - 1
packages/notebook/package.json

@@ -61,7 +61,7 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "@jupyterlab/testutils": "^3.0.0-rc.6",

+ 1 - 1
packages/property-inspector/package.json

@@ -40,7 +40,7 @@
     "@lumino/disposable": "^1.4.3",
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 1 - 1
packages/running/package.json

@@ -41,7 +41,7 @@
     "@lumino/coreutils": "^1.5.3",
     "@lumino/disposable": "^1.4.3",
     "@lumino/signaling": "^1.4.3",
-    "react": "~16.13.1"
+    "react": "^17.0.1"
   },
   "devDependencies": {
     "rimraf": "~3.0.0",

+ 4 - 4
packages/settingeditor/package.json

@@ -48,12 +48,12 @@
     "@lumino/messaging": "^1.4.3",
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "devDependencies": {
-    "@types/react": "~16.9.48",
-    "@types/react-dom": "~16.9.8",
+    "@types/react": "^16.9.48",
+    "@types/react-dom": "^16.9.8",
     "rimraf": "~3.0.0",
     "typedoc": "0.17.0-3",
     "typescript": "~4.0.2"

+ 2 - 2
packages/statusbar-extension/package.json

@@ -50,8 +50,8 @@
     "@lumino/widgets": "^1.14.0"
   },
   "devDependencies": {
-    "@types/react": "~16.9.48",
-    "@types/react-dom": "~16.9.8",
+    "@types/react": "^16.9.48",
+    "@types/react-dom": "^16.9.8",
     "rimraf": "~3.0.0",
     "typedoc": "0.17.0-3",
     "typescript": "~4.0.2"

+ 1 - 1
packages/statusbar/package.json

@@ -50,7 +50,7 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
     "csstype": "~3.0.3",
-    "react": "~16.13.1",
+    "react": "^17.0.1",
     "typestyle": "^2.0.4"
   },
   "devDependencies": {

+ 4 - 7
packages/toc/package.json

@@ -38,9 +38,6 @@
     "test:debug:watch": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
     "watch": "tsc -b --watch"
   },
-  "resolutions": {
-    "@types/react": "~16.4.13"
-  },
   "dependencies": {
     "@jupyterlab/apputils": "^3.0.0-rc.6",
     "@jupyterlab/cells": "^3.0.0-rc.6",
@@ -57,16 +54,16 @@
     "@lumino/messaging": "^1.4.3",
     "@lumino/signaling": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "devDependencies": {
     "@babel/core": "^7.10.2",
     "@babel/preset-env": "^7.10.2",
     "@jupyterlab/testutils": "^3.0.0-rc.6",
     "@types/jest": "^26.0.10",
-    "@types/react": "~16.9.48",
-    "@types/react-dom": "~16.9.8",
+    "@types/react": "^16.9.48",
+    "@types/react-dom": "^16.9.8",
     "jest": "^26.4.2",
     "rimraf": "~3.0.0",
     "ts-jest": "^26.3.0",

+ 4 - 4
packages/ui-components/package.json

@@ -49,8 +49,8 @@
     "@lumino/signaling": "^1.4.3",
     "@lumino/virtualdom": "^1.7.3",
     "@lumino/widgets": "^1.14.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1",
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1",
     "typestyle": "^2.0.4"
   },
   "devDependencies": {
@@ -60,7 +60,7 @@
     "@storybook/addon-actions": "^6.0.19",
     "@storybook/react": "^6.0.19",
     "@types/jest": "^26.0.10",
-    "@types/react": "~16.9.48",
+    "@types/react": "^16.9.48",
     "@types/webpack-env": "^1.14.1",
     "awesome-typescript-loader": "^5.2.1",
     "babel-loader": "^8.0.6",
@@ -73,7 +73,7 @@
     "typescript": "~4.0.2"
   },
   "peerDependencies": {
-    "react": "~16.9.0"
+    "react": "^17.0.1"
   },
   "publishConfig": {
     "access": "public"

+ 1 - 0
packages/ui-components/src/components/index.ts

@@ -3,3 +3,4 @@
 
 export * from './htmlselect';
 export * from './interface';
+export * from './switch';

+ 103 - 0
packages/ui-components/src/components/switch.ts

@@ -0,0 +1,103 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { ISignal, Signal } from '@lumino/signaling';
+import { Widget } from '@lumino/widgets';
+import { IChangedArgs } from '@jupyterlab/coreutils';
+
+/**
+ * A Switch widget
+ */
+export class Switch extends Widget {
+  constructor() {
+    super();
+
+    // switch accessibility refs:
+    // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Switch_role
+    // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Accessibility_concerns
+
+    this._button.className = 'jp-switch';
+    this._button.setAttribute('role', 'switch');
+
+    this._label.className = 'jp-switch-label';
+
+    const track = document.createElement('div');
+    track.className = 'jp-switch-track';
+    track.setAttribute('aria-hidden', 'true');
+
+    this._button.appendChild(this._label);
+    this._button.appendChild(track);
+    this.node.appendChild(this._button);
+  }
+
+  /**
+   * The value of the switch.
+   */
+  get value() {
+    return this._value;
+  }
+  set value(newValue: boolean) {
+    const oldValue = this._value;
+    if (oldValue === newValue) {
+      return;
+    }
+    this._button.setAttribute('aria-checked', newValue.toString());
+    this._value = newValue;
+    this._valueChanged.emit({ name: 'value', oldValue, newValue });
+  }
+
+  /**
+   * A signal emitted when the value changes.
+   */
+  get valueChanged(): ISignal<this, IChangedArgs<boolean, boolean, 'value'>> {
+    return this._valueChanged;
+  }
+
+  /**
+   * The visible label of the switch.
+   */
+  get label(): string {
+    return this._label.textContent ?? '';
+  }
+  set label(x: string) {
+    this._label.textContent = x;
+  }
+
+  /**
+   * The caption (title) of the switch.
+   */
+  get caption(): string {
+    return this._button.title;
+  }
+  set caption(x: string) {
+    this._button.title = x;
+    this._label.title = x;
+  }
+
+  handleEvent(event: Event): void {
+    switch (event.type) {
+      case 'click':
+        this.value = !this.value;
+        break;
+      default:
+        break;
+    }
+  }
+
+  protected onAfterAttach(): void {
+    this._button.addEventListener('click', this);
+  }
+
+  protected onBeforeDetach() {
+    this._button.removeEventListener('click', this);
+  }
+
+  private _button = document.createElement('button');
+  private _label = document.createElement('label');
+
+  private _value: boolean;
+  private _valueChanged = new Signal<
+    this,
+    IChangedArgs<boolean, boolean, 'value'>
+  >(this);
+}

+ 1 - 0
packages/ui-components/style/base.css

@@ -9,6 +9,7 @@
 @import './icons.css';
 @import './iconsalt.css';
 @import './iconshover.css';
+@import './switch.css';
 
 /* Override Blueprint's _reset.scss styles */
 html {

+ 55 - 0
packages/ui-components/style/switch.css

@@ -0,0 +1,55 @@
+/*-----------------------------------------------------------------------------
+| Copyright (c) Jupyter Development Team.
+| Distributed under the terms of the Modified BSD License.
+|----------------------------------------------------------------------------*/
+
+.jp-switch {
+  display: flex;
+  align-items: center;
+  font-size: var(--jp-ui-font-size1);
+  background-color: transparent;
+  color: var(--jp-ui-font-color1);
+  border: none;
+  height: 20px;
+}
+
+.jp-switch:hover {
+  background-color: var(--jp-layout-color2);
+}
+
+.jp-switch-label {
+  margin-right: 5px;
+}
+
+.jp-switch-track {
+  cursor: pointer;
+  background-color: var(--jp-border-color1);
+  -webkit-transition: 0.4s;
+  transition: 0.4s;
+  border-radius: 34px;
+  height: 16px;
+  width: 35px;
+  position: relative;
+}
+
+.jp-switch-track::before {
+  content: '';
+  position: absolute;
+  height: 10px;
+  width: 10px;
+  margin: 3px;
+  left: 0px;
+  background-color: var(--jp-ui-inverse-font-color1);
+  -webkit-transition: 0.4s;
+  transition: 0.4s;
+  border-radius: 50%;
+}
+
+.jp-switch[aria-checked='true'] .jp-switch-track {
+  background-color: var(--jp-warn-color0);
+}
+
+.jp-switch[aria-checked='true'] .jp-switch-track::before {
+  /* track width (35) - margins (3 + 3) - thumb width (10) */
+  left: 19px;
+}

+ 4 - 4
packages/vdom/package.json

@@ -42,12 +42,12 @@
     "@lumino/messaging": "^1.4.3",
     "@lumino/widgets": "^1.14.0",
     "@nteract/transform-vdom": "^4.0.16-alpha.0",
-    "react": "~16.13.1",
-    "react-dom": "~16.13.1"
+    "react": "^17.0.1",
+    "react-dom": "^17.0.1"
   },
   "devDependencies": {
-    "@types/react": "~16.9.48",
-    "@types/react-dom": "~16.9.8",
+    "@types/react": "^16.9.48",
+    "@types/react-dom": "^16.9.8",
     "rimraf": "~3.0.0",
     "typedoc": "0.17.0-3",
     "typescript": "~4.0.2"

+ 10 - 10
scripts/ci_script.sh

@@ -174,17 +174,17 @@ if [[ $GROUP == usage ]]; then
     jupyter lab build --debug
     jupyter lab path --debug
     pushd jupyterlab/tests/mock_packages
-    jupyter labextension link extension --no-build --debug
-    jupyter labextension unlink extension --no-build --debug
-    jupyter labextension link extension --no-build --debug
-    jupyter labextension unlink  @jupyterlab/mock-extension --no-build --debug
+    jupyter labextension link mimeextension --no-build --debug
+    jupyter labextension unlink mimeextension --no-build --debug
+    jupyter labextension link mimeextension --no-build --debug
+    jupyter labextension unlink  @jupyterlab/mock-mime-extension --no-build --debug
     # Test with a full install
-    jupyter labextension install extension  --no-build --debug
+    jupyter labextension install mimeextension  --no-build --debug
     jupyter labextension list --debug
-    jupyter labextension disable @jupyterlab/mock-extension --debug
-    jupyter labextension enable @jupyterlab/mock-extension --debug
+    jupyter labextension disable @jupyterlab/mock-mime-extension --debug
+    jupyter labextension enable @jupyterlab/mock-mime-extension --debug
     jupyter labextension disable @jupyterlab/notebook-extension --debug
-    jupyter labextension uninstall @jupyterlab/mock-extension --no-build --debug
+    jupyter labextension uninstall @jupyterlab/mock-mime-extension --no-build --debug
     jupyter labextension uninstall @jupyterlab/notebook-extension --no-build --debug
     # Test with a dynamic install
     jupyter labextension develop extension --debug
@@ -198,8 +198,8 @@ if [[ $GROUP == usage ]]; then
     jupyter labextension enable @jupyterlab/mock-extension --debug
     jupyter labextension uninstall @jupyterlab/mock-extension --debug
     jupyter labextension list 1>labextensions 2>&1
-    # bail if mock-extension was listed
-    cat labextensions | grep -q "mock-extension" && exit 1
+    # check the federated extension is still listed after jupyter labextension uninstall
+    cat labextensions | grep -q "mock-extension"
     popd
 
     jupyter lab workspaces export > workspace.json --debug

+ 32 - 7
yarn.lock

@@ -3262,7 +3262,7 @@
     "@types/react" "*"
     "@types/reactcss" "*"
 
-"@types/react-dom@~16.9.8":
+"@types/react-dom@^16.9.8":
   version "16.9.8"
   resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
   integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
@@ -3297,10 +3297,10 @@
   dependencies:
     "@types/react" "*"
 
-"@types/react@*", "@types/react@~16.9.48":
-  version "16.9.48"
-  resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.48.tgz#d3387329f070d1b1bc0ff4a54a54ceefd5a8485c"
-  integrity sha512-4ykBVswgYitPGMXFRxJCHkxJDU2rjfU3/zw67f8+dB7sNdVJXsrwqoYxz/stkAucymnEEbRPFmX7Ce5Mc/kJCw==
+"@types/react@*", "@types/react@^16.9.48":
+  version "16.9.53"
+  resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23"
+  integrity sha512-4nW60Sd4L7+WMXH1D6jCdVftuW7j4Za6zdp6tJ33Rqv0nk1ZAmQKML9ZLD4H0dehA3FZxXR/GM8gXplf82oNGw==
   dependencies:
     "@types/prop-types" "*"
     csstype "^3.0.2"
@@ -12898,7 +12898,7 @@ react-docgen@^5.0.0:
     node-dir "^0.1.10"
     strip-indent "^3.0.0"
 
-react-dom@^16.8.3, react-dom@~16.13.1:
+react-dom@^16.8.3:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
   integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
@@ -12908,6 +12908,15 @@ react-dom@^16.8.3, react-dom@~16.13.1:
     prop-types "^15.6.2"
     scheduler "^0.19.1"
 
+react-dom@^17.0.1:
+  version "17.0.1"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
+  integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    scheduler "^0.20.1"
+
 react-draggable@^4.0.3:
   version "4.4.3"
   resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3"
@@ -13049,7 +13058,7 @@ react-transition-group@^2.9.0:
     prop-types "^15.6.2"
     react-lifecycles-compat "^3.0.4"
 
-react@^16.8.3, react@~16.13.1:
+react@^16.8.3:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
   integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
@@ -13058,6 +13067,14 @@ react@^16.8.3, react@~16.13.1:
     object-assign "^4.1.1"
     prop-types "^15.6.2"
 
+react@^17.0.1:
+  version "17.0.1"
+  resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
+  integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+
 reactcss@^1.2.0:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
@@ -13700,6 +13717,14 @@ scheduler@^0.19.1:
     loose-envify "^1.1.0"
     object-assign "^4.1.1"
 
+scheduler@^0.20.1:
+  version "0.20.1"
+  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c"
+  integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+
 schema-utils@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"