From 7ca1011b7076324a9ccfac1b57d79684d01c7679 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Fri, 13 Sep 2024 13:29:24 +0200 Subject: [PATCH] Notebook Readonly (#313) * fix: build * chore: add index.ts * chore: favor jupyterlabtheme * chore: jupyter react theme * chore: evolving example * chore: toolbar * lint * chore: colormode * chore: lite * fix: build * fix: mount * fix: mount * lint * lint --- packages/react/package.json | 4 +- .../button/index.ts} | 2 +- packages/react/src/components/cell/index.ts | 10 + .../react/src/components/codemirror/index.ts | 9 + .../react/src/components/commands/index.ts | 8 + .../react/src/components/console/index.ts | 9 + packages/react/src/components/dialog/index.ts | 8 + .../react/src/components/environment/index.ts | 7 + .../react/src/components/filebrowser/index.ts | 7 + .../react/src/components/filemanager/index.ts | 8 + .../src/components/filemanager/lab/index.ts | 7 + packages/react/src/components/index.ts | 24 + .../components/jupyterlab/JupyterLabApp.tsx | 4 +- .../jupyterlab/JupyterLabAppCss.tsx | 4 +- .../react/src/components/jupyterlab/index.ts | 9 + packages/react/src/components/kernel/index.ts | 2 + .../src/components/kernel/inspector/index.ts | 8 + .../src/components/kernel/variables/index.ts | 13 + .../react/src/components/lumino/Lumino.tsx | 12 +- .../src/components/lumino/LuminoRedux.ts | 15 - packages/react/src/components/lumino/index.ts | 11 + .../src/components/notebook/Notebook.tsx | 298 ++++----- .../components/notebook/NotebookAdapter.ts | 582 +++++++++--------- .../components/notebook/NotebookCommands.ts | 30 +- .../src/components/notebook/NotebookState.ts | 43 +- .../src/components/notebook/cell/index.ts | 9 + .../cell/metadata/CellMetadataEditor.tsx | 4 +- .../notebook/cell/metadata/index.ts | 8 + .../notebook/cell/prompt/Countdown.tsx | 2 +- .../components/notebook/cell/prompt/index.ts | 9 + .../notebook/cell/sidebar/CellSidebar.tsx | 4 +- .../cell/sidebar/CellSidebarButton.tsx | 6 +- .../notebook/cell/sidebar/CellSidebarRun.tsx | 4 +- .../cell/sidebar/CellSidebarWidget.tsx | 6 +- .../components/notebook/cell/sidebar/index.ts | 10 + .../content/JupyterReactContentFactory.ts | 9 +- .../src/components/notebook/content/index.ts | 7 + .../react/src/components/notebook/index.ts | 15 + .../src/components/notebook/marked/index.ts | 7 + .../model/JupyterReactNotebookModelFactory.ts | 15 +- .../src/components/notebook/model/index.ts | 7 + .../notebook/toolbar}/NotebookToolbar.tsx | 8 +- .../src/components/notebook/toolbar/index.ts | 7 + packages/react/src/components/output/index.ts | 12 + .../react/src/components/settings/index.ts | 8 + .../src/components/terminal/Terminal.tsx | 4 +- .../components/terminal/TerminalAdapter.ts | 4 +- .../react/src/components/terminal/index.ts | 9 + .../react/src/components/textinput/index.ts | 7 + .../react/src/components/viewer/Viewer.tsx | 4 +- packages/react/src/components/viewer/index.ts | 9 + .../src/components/viewer/input/index.ts | 8 + .../components/viewer/output/OutputViewer.tsx | 4 +- ...utputAdapter.ts => OutputViewerAdapter.ts} | 4 +- .../src/components/viewer/output/index.ts | 8 + packages/react/src/examples/Bokeh.tsx | 12 +- packages/react/src/examples/Bqplot.tsx | 12 +- packages/react/src/examples/CellLite.tsx | 2 +- packages/react/src/examples/Cells.tsx | 6 +- packages/react/src/examples/CellsExecute.tsx | 12 +- packages/react/src/examples/Console.tsx | 6 +- packages/react/src/examples/ConsoleLite.tsx | 2 +- packages/react/src/examples/Dashboard.tsx | 12 +- packages/react/src/examples/Deno.tsx | 10 +- packages/react/src/examples/FileBrowser.tsx | 6 +- packages/react/src/examples/GeoJson.tsx | 14 +- packages/react/src/examples/IPyLeaflet.tsx | 12 +- packages/react/src/examples/IPyReact.tsx | 12 +- packages/react/src/examples/IPyWidgets.tsx | 12 +- ...dgetsWithState.tsx => IPyWidgetsState.tsx} | 16 +- .../examples/{All.tsx => JupyterContext.tsx} | 99 +-- packages/react/src/examples/JupyterLabApp.tsx | 9 +- .../src/examples/JupyterLabAppHeadless.tsx | 8 +- .../JupyterLabAppHeadlessServerless.tsx | 10 +- .../src/examples/JupyterLabAppServerless.tsx | 6 +- .../examples/JupyterLabAppServiceManager.tsx | 19 +- packages/react/src/examples/KernelExecute.tsx | 6 +- .../react/src/examples/KernelExecutor.tsx | 11 +- packages/react/src/examples/Kernels.tsx | 6 +- packages/react/src/examples/Matplotlib.tsx | 12 +- packages/react/src/examples/Notebook.tsx | 17 +- .../src/examples/NotebookCellSidebar.tsx | 10 +- ...ookColorMode.tsx => NotebookColormode.tsx} | 24 +- .../src/examples/NotebookExternalContent.tsx | 14 +- packages/react/src/examples/NotebookInit.tsx | 2 +- .../src/examples/NotebookKernelChange.tsx | 64 +- packages/react/src/examples/NotebookLite.tsx | 8 +- .../react/src/examples/NotebookMutations.tsx | 107 ++++ ...ebookNbFormat.tsx => NotebookNbformat.tsx} | 16 +- ...tChange.tsx => NotebookNbformatChange.tsx} | 22 +- .../react/src/examples/NotebookNoContext.tsx | 16 +- ...ntextNoPrimer.tsx => NotebookNoPrimer.tsx} | 12 +- packages/react/src/examples/NotebookPath.tsx | 14 +- .../react/src/examples/NotebookPathChange.tsx | 26 +- .../react/src/examples/NotebookReadonly.tsx | 35 ++ .../src/examples/NotebookServiceManager.tsx | 68 +- .../react/src/examples/NotebookSkeleton.tsx | 10 +- packages/react/src/examples/NotebookTheme.tsx | 10 +- ...lorMode.tsx => NotebookThemeColormode.tsx} | 26 +- .../react/src/examples/NotebookUnmount.tsx | 10 +- packages/react/src/examples/NotebookUrl.tsx | 30 - packages/react/src/examples/ObservableHQ.tsx | 8 +- .../react/src/examples/OutputIPyWidgets.tsx | 10 +- .../src/examples/OutputWithErrorHandle.tsx | 1 - packages/react/src/examples/Outputs.tsx | 6 +- packages/react/src/examples/Panel.tsx | 14 +- packages/react/src/examples/Plotly.tsx | 12 +- .../react/src/examples/RunningSessions.tsx | 8 +- packages/react/src/examples/Terminal.tsx | 4 +- packages/react/src/examples/Vega.tsx | 14 +- packages/react/src/examples/Viewer.tsx | 2 +- .../examples/sidebars/CellSidebarSource.tsx | 4 +- packages/react/src/index.ts | 89 +-- packages/react/src/jupyter/Jupyter.tsx | 23 +- packages/react/src/jupyter/JupyterConfig.ts | 18 +- packages/react/src/jupyter/JupyterContext.tsx | 35 +- .../react/src/jupyter/JupyterDefaults.tsx | 11 + packages/react/src/jupyter/index.ts | 19 + .../src/jupyter/ipywidgets/classic/index.ts | 8 + .../react/src/jupyter/ipywidgets/index.ts | 11 + .../react/src/jupyter/ipywidgets/lab/index.ts | 8 + .../src/jupyter/ipywidgets/lab/renderer.ts | 2 +- .../src/jupyter/ipywidgets/libembed-amd.ts | 1 + packages/react/src/jupyter/kernel/index.ts | 1 + .../react/src/jupyter/lab/JupyterLabTheme.tsx | 38 -- packages/react/src/jupyter/lab/index.ts | 112 +--- .../src/jupyter/lab/notebook/content/index.ts | 5 + packages/react/src/jupyter/lab/plugin.ts | 120 ++++ packages/react/src/jupyter/lite/Lite.ts | 11 + packages/react/src/jupyter/lite/index.ts | 8 + packages/react/src/jupyter/renderers/index.ts | 2 + .../src/jupyter/renderers/plotly/index.ts | 7 + ...ceManagerLess.ts => ServiceManagerLess.ts} | 34 +- .../jupyter/services/ServiceManagerLite.ts | 41 ++ packages/react/src/jupyter/services/index.ts | 3 +- ...pyerReactState.ts => JupyterReactState.ts} | 77 +-- packages/react/src/state/index.ts | 2 +- .../react/src/theme/JupyterLabColormode.tsx | 7 + .../{jupyter/lab => theme}/JupyterLabCss.tsx | 14 +- .../lab => theme}/JupyterLabCssImports.ts | 0 .../JupyterPrimerTheme.ts} | 0 .../react/src/theme/JupyterReactTheme.tsx | 37 ++ packages/react/src/theme/index.ts | 11 + packages/react/webpack.config.js | 25 +- 144 files changed, 1811 insertions(+), 1277 deletions(-) rename packages/react/src/{jupyter/lab/JupyterLabColorMode.tsx => components/button/index.ts} (62%) create mode 100644 packages/react/src/components/cell/index.ts create mode 100644 packages/react/src/components/codemirror/index.ts create mode 100644 packages/react/src/components/commands/index.ts create mode 100644 packages/react/src/components/console/index.ts create mode 100644 packages/react/src/components/dialog/index.ts create mode 100644 packages/react/src/components/environment/index.ts create mode 100644 packages/react/src/components/filebrowser/index.ts create mode 100644 packages/react/src/components/filemanager/index.ts create mode 100644 packages/react/src/components/filemanager/lab/index.ts create mode 100644 packages/react/src/components/index.ts create mode 100644 packages/react/src/components/jupyterlab/index.ts create mode 100755 packages/react/src/components/kernel/inspector/index.ts create mode 100755 packages/react/src/components/kernel/variables/index.ts delete mode 100644 packages/react/src/components/lumino/LuminoRedux.ts create mode 100644 packages/react/src/components/lumino/index.ts create mode 100644 packages/react/src/components/notebook/cell/index.ts create mode 100644 packages/react/src/components/notebook/cell/metadata/index.ts create mode 100644 packages/react/src/components/notebook/cell/prompt/index.ts create mode 100644 packages/react/src/components/notebook/cell/sidebar/index.ts create mode 100644 packages/react/src/components/notebook/content/index.ts create mode 100644 packages/react/src/components/notebook/index.ts create mode 100644 packages/react/src/components/notebook/marked/index.ts create mode 100644 packages/react/src/components/notebook/model/index.ts rename packages/react/src/{examples/toolbars => components/notebook/toolbar}/NotebookToolbar.tsx (96%) create mode 100644 packages/react/src/components/notebook/toolbar/index.ts create mode 100644 packages/react/src/components/output/index.ts create mode 100644 packages/react/src/components/settings/index.ts create mode 100644 packages/react/src/components/terminal/index.ts create mode 100644 packages/react/src/components/textinput/index.ts create mode 100644 packages/react/src/components/viewer/index.ts create mode 100644 packages/react/src/components/viewer/input/index.ts rename packages/react/src/components/viewer/output/{OutputAdapter.ts => OutputViewerAdapter.ts} (96%) create mode 100644 packages/react/src/components/viewer/output/index.ts rename packages/react/src/examples/{IPyWidgetsWithState.tsx => IPyWidgetsState.tsx} (60%) rename packages/react/src/examples/{All.tsx => JupyterContext.tsx} (69%) rename packages/react/src/examples/{NotebookColorMode.tsx => NotebookColormode.tsx} (70%) create mode 100644 packages/react/src/examples/NotebookMutations.tsx rename packages/react/src/examples/{NotebookNbFormat.tsx => NotebookNbformat.tsx} (60%) rename packages/react/src/examples/{NotebookNbFormatChange.tsx => NotebookNbformatChange.tsx} (74%) rename packages/react/src/examples/{NotebookNoContextNoPrimer.tsx => NotebookNoPrimer.tsx} (57%) create mode 100644 packages/react/src/examples/NotebookReadonly.tsx rename packages/react/src/examples/{NotebookThemeColorMode.tsx => NotebookThemeColormode.tsx} (79%) delete mode 100644 packages/react/src/examples/NotebookUrl.tsx create mode 100644 packages/react/src/jupyter/JupyterDefaults.tsx create mode 100644 packages/react/src/jupyter/index.ts create mode 100644 packages/react/src/jupyter/ipywidgets/classic/index.ts create mode 100644 packages/react/src/jupyter/ipywidgets/index.ts create mode 100644 packages/react/src/jupyter/ipywidgets/lab/index.ts delete mode 100644 packages/react/src/jupyter/lab/JupyterLabTheme.tsx create mode 100644 packages/react/src/jupyter/lab/notebook/content/index.ts create mode 100644 packages/react/src/jupyter/lab/plugin.ts create mode 100644 packages/react/src/jupyter/lite/Lite.ts create mode 100644 packages/react/src/jupyter/lite/index.ts create mode 100644 packages/react/src/jupyter/renderers/plotly/index.ts rename packages/react/src/jupyter/services/{JupyterServiceManagerLess.ts => ServiceManagerLess.ts} (92%) create mode 100644 packages/react/src/jupyter/services/ServiceManagerLite.ts rename packages/react/src/state/{JupyerReactState.ts => JupyterReactState.ts} (77%) create mode 100644 packages/react/src/theme/JupyterLabColormode.tsx rename packages/react/src/{jupyter/lab => theme}/JupyterLabCss.tsx (91%) rename packages/react/src/{jupyter/lab => theme}/JupyterLabCssImports.ts (100%) rename packages/react/src/{themes/primerTheme.ts => theme/JupyterPrimerTheme.ts} (100%) create mode 100644 packages/react/src/theme/JupyterReactTheme.tsx create mode 100644 packages/react/src/theme/index.ts diff --git a/packages/react/package.json b/packages/react/package.json index d5e8ea7f..9021715d 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@datalayer/jupyter-react", - "version": "0.18.6", + "version": "0.18.7", "description": "Jupyter React - React.js components 100% compatible with Jupyter.", "license": "MIT", "main": "lib/index.js", @@ -260,7 +260,7 @@ } } }, - "extension": "./lib/jupyter/lab/index.js", + "extension": "./lib/jupyter/lab/plugin.js", "outputDir": "jupyter_react/labextension", "schemaDir": "schema", "webpackConfig": "./webpack.lab-config.js" diff --git a/packages/react/src/jupyter/lab/JupyterLabColorMode.tsx b/packages/react/src/components/button/index.ts similarity index 62% rename from packages/react/src/jupyter/lab/JupyterLabColorMode.tsx rename to packages/react/src/components/button/index.ts index fb736a05..ca1901de 100644 --- a/packages/react/src/jupyter/lab/JupyterLabColorMode.tsx +++ b/packages/react/src/components/button/index.ts @@ -4,4 +4,4 @@ * MIT License */ -export type ColorMode = 'light' | 'dark'; +export * from './Button'; diff --git a/packages/react/src/components/cell/index.ts b/packages/react/src/components/cell/index.ts new file mode 100644 index 00000000..96be2e93 --- /dev/null +++ b/packages/react/src/components/cell/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Cell'; +export * from './CellAdapter'; +export * from './CellCommands'; +export * from './CellState'; diff --git a/packages/react/src/components/codemirror/index.ts b/packages/react/src/components/codemirror/index.ts new file mode 100644 index 00000000..7f7e8c74 --- /dev/null +++ b/packages/react/src/components/codemirror/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './CodeMirrorEditor'; +export * from './CodeMirrorOutputToolbar'; +export * from './CodeMirrorTheme'; diff --git a/packages/react/src/components/commands/index.ts b/packages/react/src/components/commands/index.ts new file mode 100644 index 00000000..2d22db7c --- /dev/null +++ b/packages/react/src/components/commands/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Commands'; +export * from './CommandsAdapter'; diff --git a/packages/react/src/components/console/index.ts b/packages/react/src/components/console/index.ts new file mode 100644 index 00000000..7364f99d --- /dev/null +++ b/packages/react/src/components/console/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Console'; +export * from './ConsoleAdapter'; +export * from './ConsoleState'; diff --git a/packages/react/src/components/dialog/index.ts b/packages/react/src/components/dialog/index.ts new file mode 100644 index 00000000..d05d8f0d --- /dev/null +++ b/packages/react/src/components/dialog/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Dialog'; +export * from './DialogAdapter'; diff --git a/packages/react/src/components/environment/index.ts b/packages/react/src/components/environment/index.ts new file mode 100644 index 00000000..1efdf86c --- /dev/null +++ b/packages/react/src/components/environment/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Environment'; diff --git a/packages/react/src/components/filebrowser/index.ts b/packages/react/src/components/filebrowser/index.ts new file mode 100644 index 00000000..8a57bd72 --- /dev/null +++ b/packages/react/src/components/filebrowser/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './FileBrowser'; diff --git a/packages/react/src/components/filemanager/index.ts b/packages/react/src/components/filemanager/index.ts new file mode 100644 index 00000000..ea8d0900 --- /dev/null +++ b/packages/react/src/components/filemanager/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './FileManagerJupyterLab'; +export * from './lab'; diff --git a/packages/react/src/components/filemanager/lab/index.ts b/packages/react/src/components/filemanager/lab/index.ts new file mode 100644 index 00000000..12c28254 --- /dev/null +++ b/packages/react/src/components/filemanager/lab/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './FileManagerAdapter'; diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts new file mode 100644 index 00000000..ab6f6fde --- /dev/null +++ b/packages/react/src/components/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './button'; +export * from './cell'; +export * from './codemirror'; +export * from './commands'; +export * from './console'; +export * from './dialog'; +export * from './environment'; +export * from './filebrowser'; +export * from './filemanager'; +export * from './jupyterlab'; +export * from './kernel'; +export * from './lumino'; +export * from './notebook'; +export * from './output'; +export * from './settings'; +export * from './terminal'; +export * from './textinput'; +export * from './viewer'; diff --git a/packages/react/src/components/jupyterlab/JupyterLabApp.tsx b/packages/react/src/components/jupyterlab/JupyterLabApp.tsx index 0cbaf824..042a4acf 100644 --- a/packages/react/src/components/jupyterlab/JupyterLabApp.tsx +++ b/packages/react/src/components/jupyterlab/JupyterLabApp.tsx @@ -11,7 +11,7 @@ import { PageConfig } from '@jupyterlab/coreutils'; import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; import { ServiceManager } from '@jupyterlab/services'; import { useJupyter } from '../../jupyter/JupyterContext'; -import { ColorMode } from '../../jupyter/lab/JupyterLabColorMode'; +import { Colormode } from '../../theme/JupyterLabColormode'; import { JupyterLabAppCorePlugins } from './JupyterLabAppPlugins'; import JupyterLabAppAdapter from './JupyterLabAppAdapter'; import JupyterLabAppCss from './JupyterLabAppCss'; @@ -39,7 +39,7 @@ export type JupyterLabAppProps = { serverless: boolean; serviceManager: ServiceManager.IManager; startDefaultKernel: boolean; - theme: ColorMode; + theme: Colormode; width: string | number; }; diff --git a/packages/react/src/components/jupyterlab/JupyterLabAppCss.tsx b/packages/react/src/components/jupyterlab/JupyterLabAppCss.tsx index 65483a7c..70a55c7f 100644 --- a/packages/react/src/components/jupyterlab/JupyterLabAppCss.tsx +++ b/packages/react/src/components/jupyterlab/JupyterLabAppCss.tsx @@ -5,7 +5,7 @@ */ import { useEffect } from 'react'; -import { ColorMode } from '../../jupyter/lab/JupyterLabColorMode'; +import { Colormode } from '../../theme/JupyterLabColormode'; import '@jupyterlab/application-extension/style/index.js'; import '@jupyterlab/apputils-extension/style/index.js'; @@ -31,7 +31,7 @@ import '@jupyterlab/translation-extension/style/index.js'; import '@jupyterlab/ui-components-extension/style/index.js'; type Props = { - theme?: ColorMode; + theme?: Colormode; }; export const JupyterLabAppCss = (props: Props) => { diff --git a/packages/react/src/components/jupyterlab/index.ts b/packages/react/src/components/jupyterlab/index.ts new file mode 100644 index 00000000..4767fb32 --- /dev/null +++ b/packages/react/src/components/jupyterlab/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './JupyterLabApp'; +export * from './JupyterLabAppAdapter'; +export * from './JupyterLabAppPlugins'; diff --git a/packages/react/src/components/kernel/index.ts b/packages/react/src/components/kernel/index.ts index aee6b6a5..e31daf27 100755 --- a/packages/react/src/components/kernel/index.ts +++ b/packages/react/src/components/kernel/index.ts @@ -14,3 +14,5 @@ export * from './KernelSelector'; export * from './Kernelndicator'; export * from './KernelUsage'; export * from './KernelVariables'; +export * from './inspector'; +export * from './variables'; diff --git a/packages/react/src/components/kernel/inspector/index.ts b/packages/react/src/components/kernel/inspector/index.ts new file mode 100755 index 00000000..cc4cca9b --- /dev/null +++ b/packages/react/src/components/kernel/inspector/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './model'; +export * from './widget'; diff --git a/packages/react/src/components/kernel/variables/index.ts b/packages/react/src/components/kernel/variables/index.ts new file mode 100755 index 00000000..df7e821e --- /dev/null +++ b/packages/react/src/components/kernel/variables/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './handler'; +export * from './inspectorscripts'; +export * from './kernelconnector'; +export * from './manager'; +export * from './tokens'; +export * from './variablesinspector'; +export * from './widget'; diff --git a/packages/react/src/components/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index dc7fdc3b..e726bcf2 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -33,19 +33,23 @@ export const Lumino = (props: LuminoProps) => { } } catch (e) { // no-op. - // console.debug('Exception while detaching Lumino widget.', e); + // console.debug('Exception while detaching Lumino widget.', e); } }; } }, [ref, children]); return ( -
+
); -}; +} Lumino.defaultProps = { id: 'lumino-id', height: '100%', -}; +} export default Lumino; diff --git a/packages/react/src/components/lumino/LuminoRedux.ts b/packages/react/src/components/lumino/LuminoRedux.ts deleted file mode 100644 index 71c9cf87..00000000 --- a/packages/react/src/components/lumino/LuminoRedux.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2021-2023 Datalayer, Inc. - * - * MIT License - */ - -/** - * A LuminoRedux interface to enforce the usage of - * the injextRedux method. - */ -interface LuminoRedux { - injectRedux: () => void; -} - -export default LuminoRedux; diff --git a/packages/react/src/components/lumino/index.ts b/packages/react/src/components/lumino/index.ts new file mode 100644 index 00000000..ff9c9c90 --- /dev/null +++ b/packages/react/src/components/lumino/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Lumino'; +export * from './LuminoBox'; +export * from './LuminoDetached'; +export * from './LuminoObservable'; +export * from './ReactPortalWidget'; diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index a67c443a..5fd260a8 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -10,15 +10,15 @@ import { Box } from '@primer/react'; import { Cell, ICellModel } from '@jupyterlab/cells'; import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { useJupyter } from './../../jupyter/JupyterContext'; -import { Kernel } from '../../jupyter/kernel/Kernel'; -import Lumino from '../lumino/Lumino'; -import { asObservable } from '../lumino/LuminoObservable'; -import { CellSidebarProps } from './cell/sidebar/CellSidebarWidget'; -import CellMetadataEditor from './cell/metadata/CellMetadataEditor'; -import { newUuid } from '../../utils/Utils'; -import NotebookAdapter from './NotebookAdapter'; -import useNotebookStore from './NotebookState'; +import { ServiceManager } from '@jupyterlab/services'; +import { useJupyter, Lite, Kernel } from './../../jupyter'; +import { asObservable, Lumino } from '../lumino'; +import { CellMetadataEditor } from './cell/metadata/CellMetadataEditor'; +import { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget'; +import { INotebookToolbarProps } from './toolbar/NotebookToolbar'; +import { newUuid } from '../../utils'; +import { useNotebookStore } from './NotebookState'; +import { NotebookAdapter } from './NotebookAdapter'; import './Notebook.css'; @@ -32,172 +32,185 @@ export type BundledIPyWidgets = ExternalIPyWidgets & { }; export type INotebookProps = { + CellSidebar?: (props: ICellSidebarProps) => JSX.Element; + Toolbar?: (props: INotebookToolbarProps) => JSX.Element; cellMetadataPanel: boolean; cellSidebarMargin: number; height?: string; - /* - Example: - bundledIPyWidgets={[ - { - name: 'jupyter-matplotlib', - version: '0.11.3', - module: require('jupyter-matplotlib'), - }, - ]} - */ - bundledIPyWidgets?: BundledIPyWidgets[]; - /* - Example: - externalIPyWidgets={[ - { name: '@widgetti/jupyter-react', version: '0.3.0' }, - { name: 'bqplot', version: '0.5.42' }, - { name: 'jupyter-leaflet', version: '0.18.0' }, - { name: 'jupyter-matplotlib', version: '0.11.3' }, - ]} - */ - externalIPyWidgets?: ExternalIPyWidgets[]; + id: string; + lite?: Lite; kernel?: Kernel; maxHeight?: string; nbformat?: INotebookContent; nbgrader: boolean; path?: string; - readOnly: boolean; + readonly: boolean; renderers: IRenderMime.IRendererFactory[]; - id: string; + serverless: boolean, + serviceManager?: ServiceManager.IManager, url?: string; - CellSidebar?: (props: CellSidebarProps) => JSX.Element; - Toolbar?: (props: any) => JSX.Element; }; /** - * This component creates a Notebook as a collection of snippets + * This component creates a Notebook as a collection of cells * with sidebars. * * @param props The notebook properties. * @returns A Notebook React.js component. */ export const Notebook = (props: INotebookProps) => { - const { serviceManager, defaultKernel, kernelManager, lite } = useJupyter(); + const { serviceManager, defaultKernel, lite } = useJupyter({ + lite: props.lite, + serverless: props.serverless, + serviceManager: props.serviceManager, + }); const { - path, - kernel: propsKernel, - readOnly, - nbgrader, + Toolbar, height, maxHeight, nbformat, - Toolbar, + nbgrader, + path, + readonly, + url, + serverless, } = props; - const notebookStore = useNotebookStore(); - const [id] = useState(props.id || newUuid()); + const [id, _] = useState(props.id || newUuid()); const [adapter, setAdapter] = useState(); - const kernel = propsKernel || defaultKernel; + const kernel = props.kernel ?? defaultKernel; const portals = notebookStore.selectNotebookPortals(id); - const newAdapterState = () => { - if (id && serviceManager && kernelManager && kernel) { - kernel.ready.then(() => { - const adapter = new NotebookAdapter( - { - ...props, - kernel, - id, - }, - serviceManager, - lite - ); - setAdapter(adapter); - notebookStore.update({ id, partialState: { adapter: adapter } }) - adapter.serviceManager.ready.then(() => { - if (!readOnly) { - const activeCell = adapter.notebookPanel!.content.activeCell; - if (activeCell) { - notebookStore.activeCellChange({ - id, - cellModel: activeCell, - }); - } - const activeCellChanged$ = asObservable( - adapter.notebookPanel!.content.activeCellChanged + const bootstrapAdapter = () => { + const adapter = new NotebookAdapter( + { + ...props, + id, + lite, + kernel, + serviceManager, + } + ); + console.log('Notebook Adapter is created', adapter); + // Update the local state. + setAdapter(adapter); + // Update the global state. + notebookStore.update({ id, state: { adapter } }); + // Update the global state based on events. + adapter.notebookPanel?.model?.contentChanged.connect( + (notebookModel, _) => { notebookStore.changeModel({ id, notebookModel }) } + ); + /* + adapter.notebookPanel?.model!.sharedModel.changed.connect((_, notebookChange) => { + notebookStore.notebookChange({ id, notebookChange }); + }); + adapter.notebookPanel?.content.modelChanged.connect((notebook, _) => { + dispatÅch(notebookStore.notebookChange({ id, notebook })); + }); + */ + adapter.notebookPanel?.content.activeCellChanged.connect((_, cellModel) => { + if (cellModel === null) { + notebookStore.activeCellChange({ id, cellModel: undefined }); + } else { + notebookStore.activeCellChange({ id, cellModel }); + } + } + ); + adapter.notebookPanel?.sessionContext.statusChanged.connect((_, kernelStatus) => { + notebookStore.changeKernelStatus({ id, kernelStatus }); + }); + // Add more behavior for the UI. + adapter.serviceManager.ready.then(() => { + if (!readonly) { + const cellModel = adapter.notebookPanel!.content.activeCell; + if (cellModel) { + notebookStore.activeCellChange({ id, cellModel }); + } + const activeCellChanged$ = asObservable(adapter.notebookPanel!.content.activeCellChanged); + activeCellChanged$.subscribe((cellModel: Cell) => { + notebookStore.activeCellChange({ id, cellModel }); + const panelDiv = document.getElementById('right-panel-id') as HTMLDivElement; + if (panelDiv) { + const cellMetadataOptions = ( + + + ); - activeCellChanged$.subscribe((cellModel: Cell) => { - notebookStore.activeCellChange({ id, cellModel }); - const panelDiv = document.getElementById( - 'right-panel-id' - ) as HTMLDivElement; - if (panelDiv) { - const cellMetadataOptions = ( - - - - ); - const portal = createPortal(cellMetadataOptions, panelDiv); - notebookStore.setPortalDisplay({ - id, - portalDisplay: { portal, pinned: false }, - }); - } - }); + const portal = createPortal(cellMetadataOptions, panelDiv); + notebookStore.setPortalDisplay({ id, portalDisplay: { portal, pinned: false } }); } - adapter.notebookPanel?.model?.contentChanged.connect( - (notebookModel, _) => { - notebookStore.modelChange({ id, notebookModel }); - } - ); - /* - adapter.notebookPanel?.model!.sharedModel.changed.connect((_, notebookChange) => { - notebookStore.notebookChange({ id, notebookChange }); - }); - adapter.notebookPanel?.content.modelChanged.connect((notebook, _) => { - dispatÅch(notebookStore.notebookChange({ id, notebook })); - }); - */ - adapter.notebookPanel?.content.activeCellChanged.connect( - (_, cellModel) => { - if (cellModel === null) { - notebookStore.activeCellChange({ - id, - cellModel: undefined, - }); - } else { - notebookStore.activeCellChange({ id, cellModel }); - } - } - ); - adapter.notebookPanel?.sessionContext.statusChanged.connect( - (_, kernelStatus) => { - notebookStore.kernelStatusChanged({ id, kernelStatus }); - } - ); }); + } + }); + } + const createAdapter = (kernel?: Kernel) => { + if (!kernel) { + bootstrapAdapter(); + } else { + kernel.ready.then(() => { + bootstrapAdapter(); }); } - }; - useEffect(() => { + } + const disposeAdapter = () => { if (adapter) { - adapter.dispose(); + notebookStore.dispose(id); + setAdapter(undefined); } - newAdapterState(); + } + useEffect(() => { return () => { - notebookStore.setPortalDisplay({ id, portalDisplay: undefined }); - notebookStore.dispose(id); - }; - }, [id, serviceManager, kernelManager, kernel, path]); + disposeAdapter(); + } + }, []); useEffect(() => { - if (adapter && nbformat) { + /* + if (adapter && (adapter.lite !== lite || adapter.serviceManager !== serviceManager)) { + if (adapter) { + adapter.setServiceManager(serviceManager!, lite!); + } else { + createAdapter(kernel); + } + } else + */ + if (serviceManager && (kernel || serverless)) { + if (adapter) { + disposeAdapter(); + } + createAdapter(kernel); + } + }, [serviceManager, kernel, serverless, lite]); + useEffect(() => { + if (adapter && nbformat && adapter.nbformat !== nbformat) { adapter.setNbformat(nbformat); } }, [nbformat]); + useEffect(() => { + if (adapter && path && adapter.path !== path) { + disposeAdapter(); + createAdapter(); + } + }, [path]); + useEffect(() => { + if (adapter && url && adapter.url !== url) { + disposeAdapter(); + createAdapter(); + } + }, [url]); + useEffect(() => { + if (adapter && url && adapter.readonly !== readonly) { + adapter.setReadonly(readonly); + } + }, [readonly]); return ( -
- {Toolbar && } + {Toolbar && } { }, }} > - <>{portals?.map((portal: React.ReactPortal) => portal)} - {adapter && {adapter.panel}} + <> + {portals?.map((portal: React.ReactPortal) => portal)} + + + {adapter && + ( + + {adapter.panel} + + ) + } + -
+ ); -}; +} Notebook.defaultProps = { cellMetadataPanel: false, @@ -270,8 +293,9 @@ Notebook.defaultProps = { height: '100vh', maxHeight: '100vh', nbgrader: false, - readOnly: false, + readonly: false, renderers: [], + serverless: false, } as Partial; export default Notebook; diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 661e37b0..f9ef6c73 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -9,102 +9,69 @@ import { CommandRegistry } from '@lumino/commands'; import { BoxPanel, Widget } from '@lumino/widgets'; import { IChangedArgs } from '@jupyterlab/coreutils'; import { Cell, ICellModel, MarkdownCell } from '@jupyterlab/cells'; -import { - Contents, - ServiceManager, - Kernel as JupyterKernel, - SessionManager, -} from '@jupyterlab/services'; +import { Contents, ServiceManager, Kernel as JupyterKernel, SessionManager } from '@jupyterlab/services'; import { DocumentRegistry, Context } from '@jupyterlab/docregistry'; import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; -import { - standardRendererFactories, - RenderMimeRegistry, -} from '@jupyterlab/rendermime'; +import { standardRendererFactories, RenderMimeRegistry } from '@jupyterlab/rendermime'; import { rendererFactory as jsonRendererFactory } from '@jupyterlab/json-extension'; import { rendererFactory as javascriptRendererFactory } from '@jupyterlab/javascript-extension'; -import { - NotebookPanel, - NotebookWidgetFactory, - NotebookTracker, - INotebookModel, -} from '@jupyterlab/notebook'; -import { - CodeMirrorEditorFactory, - CodeMirrorMimeTypeService, - EditorLanguageRegistry, - EditorExtensionRegistry, - EditorThemeRegistry, - ybinding, -} from '@jupyterlab/codemirror'; +import { Notebook, NotebookPanel, NotebookWidgetFactory, NotebookTracker, INotebookModel } from '@jupyterlab/notebook'; +import { ybinding, CodeMirrorEditorFactory, CodeMirrorMimeTypeService, EditorLanguageRegistry, EditorExtensionRegistry, EditorThemeRegistry } from '@jupyterlab/codemirror'; import { IEditorServices } from '@jupyterlab/codeeditor'; -import { - Completer, - CompleterModel, - CompletionHandler, - ProviderReconciliator, - KernelCompleterProvider, -} from '@jupyterlab/completer'; +import { Completer, CompleterModel, CompletionHandler, ProviderReconciliator, KernelCompleterProvider } from '@jupyterlab/completer'; import { MathJaxTypesetter } from '@jupyterlab/mathjax-extension'; import { INotebookContent, CellType, IAttachments } from '@jupyterlab/nbformat'; import { ISharedAttachmentsCell, IYText } from '@jupyter/ydoc'; import { WIDGET_MIMETYPE } from '@jupyter-widgets/html-manager/lib/output_renderers'; -import { Lite } from '../../jupyter/JupyterContext'; -import { Kernel } from '../../jupyter/kernel/Kernel'; -import JupyterReactContentFactory from './content/JupyterReactContentFactory'; -import JupyterReactNotebookModelFactory from './model/JupyterReactNotebookModelFactory'; -import { - INotebookProps, -// ExternalIPyWidgets, -// BundledIPyWidgets, -} from './Notebook'; +import { Lite } from '../../jupyter/lite'; +import { Kernel } from '../../jupyter/kernel'; +import { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget'; +import { JupyterReactContentFactory } from './content/JupyterReactContentFactory'; +import { JupyterReactNotebookModelFactory } from './model/JupyterReactNotebookModelFactory'; +import { INotebookProps } from './Notebook'; import { NotebookCommands } from './NotebookCommands'; -import getMarked from './marked/marked'; -import { WidgetManager } from '../../jupyter/ipywidgets/lab/manager'; -import { WidgetRenderer } from '../../jupyter/ipywidgets/lab/renderer'; +import { getMarked } from './marked/marked'; +import { WidgetManager, WidgetLabRenderer } from '../../jupyter/ipywidgets'; -const FALLBACK_PATH = 'ping.ipynb'; +const FALLBACK_NOTEBOOK_PATH = 'ping.ipynb'; export class NotebookAdapter { + + private _CellSidebar?: (props: ICellSidebarProps) => JSX.Element; private _boxPanel: BoxPanel; private _commandRegistry: CommandRegistry; private _context?: Context; -// private _bundledIPyWidgets?: BundledIPyWidgets[]; -// private _externalIPyWidgets?: ExternalIPyWidgets[]; + private _documentRegistry?: DocumentRegistry; private _iPyWidgetsManager?: WidgetManager; - private _kernel: Kernel; + private _id: string; + private _kernel?: Kernel; private _lite?: Lite; private _nbformat?: INotebookContent; private _nbgrader: boolean; + private _notebookModelFactory?: JupyterReactNotebookModelFactory; private _notebookPanel?: NotebookPanel; + private _url?: string; private _path?: string; - private _readOnly: boolean; + private _readonly: boolean; private _renderers: IRenderMime.IRendererFactory[]; private _rendermime?: RenderMimeRegistry; + private _serverless: boolean; private _serviceManager: ServiceManager.IManager; private _tracker?: NotebookTracker; - private _id: string; - private _CellSidebar?: (props: any) => JSX.Element; - - constructor( - props: INotebookProps, - serviceManager: ServiceManager.IManager, - lite?: Lite - ) { -// this._bundledIPyWidgets = props.bundledIPyWidgets; -// this._externalIPyWidgets = props.externalIPyWidgets; - this._kernel = props.kernel!; - this._lite = lite; + + constructor(props: INotebookProps) { + this._CellSidebar = props.CellSidebar; + this._id = props.id; + this._kernel = props.kernel; + this._lite = props.lite; this._nbformat = props.nbformat; this._nbgrader = props.nbgrader; this._path = props.path; - this._readOnly = props.readOnly; + this._readonly = props.readonly; this._renderers = props.renderers; - this._id = props.id; - - this._CellSidebar = props.CellSidebar; - - this._serviceManager = serviceManager; + this._serverless = props.serverless; + this._serviceManager = props.serviceManager!; + this._url = props.url; this._boxPanel = new BoxPanel(); this._boxPanel.addClass('dla-Jupyter-Notebook'); @@ -127,7 +94,6 @@ export class NotebookAdapter { return fetch(url).then(response => { return response.text(); }).then(nb => { -// const nbformat = nb.replaceAll('\\n', ''); return JSON.parse(nb); }); } @@ -136,135 +102,61 @@ export class NotebookAdapter { this._commandRegistry?.processKeydownEvent(event); } - private setupAdapter(): void { - const useCapture = true; - - document.addEventListener( 'keydown', this.notebookKeydownListener, useCapture); - - const initialFactories = standardRendererFactories.filter( - factory => factory.mimeTypes[0] !== 'text/javascript' - ); - - const ipywidgetsRendererFactory: IRenderMime.IRendererFactory = { - safe: true, - mimeTypes: [WIDGET_MIMETYPE], - defaultRank: 1, - createRenderer: options => - new WidgetRenderer(options, this._iPyWidgetsManager!), - }; - - initialFactories.push(ipywidgetsRendererFactory); - initialFactories.push(jsonRendererFactory); - initialFactories.push(javascriptRendererFactory); - - this._renderers.map(renderer => initialFactories.push(renderer)); - - const languages = new EditorLanguageRegistry(); - // Register default languages. - for (const language of EditorLanguageRegistry.getDefaultLanguages()) { - languages.addLanguage(language); - } - // Add Jupyter Markdown flavor here to support code block highlighting. - languages.addLanguage({ - name: 'ipythongfm', - mime: 'text/x-ipythongfm', - load: async () => { - // TODO: add support for LaTeX. - const m = await import('@codemirror/lang-markdown'); - return m.markdown({ - codeLanguages: (info: string) => languages.findBest(info) as any, - }); + setupCompleter(notebookPanel: NotebookPanel) { + const editor = + notebookPanel.content.activeCell && + notebookPanel.content.activeCell.editor; + const sessionContext = notebookPanel.context.sessionContext; + const model = new CompleterModel(); + const completer = new Completer({ editor, model }); + const timeout = 1000; + const provider = new KernelCompleterProvider(); + const reconciliator = new ProviderReconciliator({ + context: { + widget: notebookPanel, + editor, + session: sessionContext.session, }, + providers: [provider], + timeout, }); - - this._rendermime = new RenderMimeRegistry({ - initialFactories, - latexTypesetter: new MathJaxTypesetter(), - markdownParser: getMarked(languages), - }); - - const documentRegistry = new DocumentRegistry({}); - const mimeTypeService = new CodeMirrorMimeTypeService(languages); - - const themes = new EditorThemeRegistry(); - for (const theme of EditorThemeRegistry.getDefaultThemes()) { - themes.addTheme(theme); - } - const editorExtensions = () => { - const registry = new EditorExtensionRegistry(); - for (const extensionFactory of EditorExtensionRegistry.getDefaultExtensions( - { themes } - )) { - registry.addExtension(extensionFactory); - } - registry.addExtension({ - name: 'shared-model-binding', - factory: options => { - const sharedModel = options.model.sharedModel as IYText; - return EditorExtensionRegistry.createImmutableExtension( - ybinding({ - ytext: sharedModel.ysource, - undoManager: sharedModel.undoManager ?? undefined, - }) - ); + const handler = new CompletionHandler({ completer, reconciliator }); + void sessionContext.ready.then(() => { + const provider = new KernelCompleterProvider(); + const reconciliator = new ProviderReconciliator({ + context: { + widget: this._notebookPanel!, + editor, + session: sessionContext.session, }, + providers: [provider], + timeout: timeout, }); - return registry; - }; - const factoryService = new CodeMirrorEditorFactory({ - extensions: editorExtensions(), - languages, - }); - const editorServices: IEditorServices = { - factoryService, - mimeTypeService, - }; - const editorFactory = editorServices.factoryService.newInlineEditor; - const contentFactory = this._CellSidebar - ? new JupyterReactContentFactory( - this._CellSidebar, - this._id, - this._nbgrader, - this._commandRegistry, - { editorFactory }, - ) - : new NotebookPanel.ContentFactory({ editorFactory }); - - this._tracker = new NotebookTracker({ namespace: this._id }); - - const notebookWidgetFactory = new NotebookWidgetFactory({ - name: 'Notebook', - modelName: 'viewer', - fileTypes: ['notebook'], - defaultFor: ['notebook'], - preferKernel: true, - autoStartDefault: false, - canStartKernel: false, - shutdownOnClose: false, - rendermime: this._rendermime, - contentFactory, - mimeTypeService: editorServices.mimeTypeService, - }); - notebookWidgetFactory.widgetCreated.connect((sender, notebookPanel) => { - notebookPanel.context.pathChanged.connect(() => { - this._tracker?.save(notebookPanel); - }); - this._tracker?.add(notebookPanel); + handler.reconciliator = reconciliator; }); - documentRegistry.addWidgetFactory(notebookWidgetFactory); + handler.editor = editor; + notebookPanel.content.activeCellChanged.connect( + (notebook: Notebook, cell: Cell | null) => { + if (cell) { + cell.ready.then(() => { + handler.editor = cell && cell.editor; + }); + } + } + ); + completer.hide(); + Widget.attach(completer, document.body); + return handler; + } - const notebookModelFactory = new JupyterReactNotebookModelFactory({ - nbformat: this._nbformat, - readOnly: this._readOnly, - }); - documentRegistry.addModelFactory(notebookModelFactory); + initializeContext() { this._context = new Context({ manager: this._serviceManager, - factory: notebookModelFactory, - path: this._path ?? FALLBACK_PATH, + factory: this._notebookModelFactory!, + path: this._path ?? FALLBACK_NOTEBOOK_PATH, kernelPreference: { - id: this._kernel.id, + id: this._kernel?.id, shouldStart: false, canStart: false, autoStartDefault: false, @@ -272,7 +164,8 @@ export class NotebookAdapter { }, }); - this._iPyWidgetsManager = new WidgetManager(this._context, this._rendermime, {saveState: false}); + this._iPyWidgetsManager = new WidgetManager(this._context, this._rendermime!, {saveState: false}); + /* this._rendermime!.addFactory( { @@ -284,6 +177,7 @@ export class NotebookAdapter { 1 ); */ + /* // This code block was causing https://github.com/datalayer/jupyter-ui/issues/195 // TODO Double check there is not side effect. @@ -295,18 +189,7 @@ export class NotebookAdapter { ); }); */ - /* - if (this._bundledIPyWidgets) { - this._iPyWidgetsManager.loadBundledIPyWidgets( - this._bundledIPyWidgets - ); - } - if (this._externalIPyWidgets) { - this._iPyWidgetsManager.loadExternalIPyWidgets( - this._externalIPyWidgets - ); - } - */ + // These are fixes to have more control on the kernel launch. (this._context.sessionContext as any)._initialize = async (): Promise => { @@ -315,7 +198,7 @@ export class NotebookAdapter { await manager.ready; await manager.refreshRunning(); const model = find(manager.running(), model => { - return model.kernel?.id === this._kernel.id; + return model.kernel?.id === this._kernel?.id; }); if (model) { try { @@ -356,6 +239,7 @@ export class NotebookAdapter { ); } }); + /* // Alternative way to create a NotebookPanel. const content = new Notebook({ @@ -372,17 +256,18 @@ export class NotebookAdapter { content, }); */ - this._notebookPanel = documentRegistry - .getWidgetFactory('Notebook') - ?.createNew(this._context) as NotebookPanel; - this._iPyWidgetsManager?.registerWithKernel( - this._kernel.connection - ); + this._notebookPanel = this._documentRegistry?.getWidgetFactory('Notebook')?.createNew(this._context) as NotebookPanel; + + if (this._kernel) { + this._iPyWidgetsManager?.registerWithKernel( + this._kernel.connection + ); + } - this._notebookPanel!.sessionContext.kernelChanged.connect( + this._notebookPanel?.sessionContext.kernelChanged.connect( ( - sender: any, + _: any, args: IChangedArgs< JupyterKernel.IKernelConnection | null, JupyterKernel.IKernelConnection | null, @@ -394,27 +279,29 @@ export class NotebookAdapter { ); const completerHandler = this.setupCompleter(this._notebookPanel!); - - NotebookCommands( - this._commandRegistry, - this._notebookPanel, - completerHandler, - this._tracker, - this._path - ); + try { + NotebookCommands( + this._commandRegistry, + this._notebookPanel, + completerHandler, + this._tracker!, + this._path + ); + } + catch { + // No op - the commands may already be registered. + } this._boxPanel.addWidget(this._notebookPanel); BoxPanel.setStretch(this._notebookPanel, 0); window.addEventListener('resize', () => { this._notebookPanel?.update(); }); - const isNbFormat = - this._path !== undefined && this._path !== '' ? false : true; + + const isNbFormat = this._path !== undefined && this._path !== '' ? false : true; if (isNbFormat && !this._lite) { // Fixes if nbformat is provided and we don't want to interact with the content manager. - (this._context as any).initialize = async ( - isNew: boolean - ): Promise => { + (this._context as any).initialize = async (isNew: boolean): Promise => { (this._context as Context).model.dirty = false; const now = new Date().toISOString(); const model: Contents.IModel = { @@ -430,105 +317,239 @@ export class NotebookAdapter { }; (this._context as any)._updateContentsModel(model); await (this._context as any)._populate(); - ( - this._context as Context - ).model.sharedModel.clearUndoHistory(); + (this._context as Context).model.sharedModel.clearUndoHistory(); }; } + this._context.initialize(isNbFormat).then(() => { if (isNbFormat) { this._notebookPanel?.model?.fromJSON(this._nbformat!); } }); + } - setupCompleter(notebookPanel: NotebookPanel) { - const editor = - notebookPanel.content.activeCell && - notebookPanel.content.activeCell.editor; - const sessionContext = notebookPanel.context.sessionContext; - const model = new CompleterModel(); - const completer = new Completer({ editor, model }); - const timeout = 1000; - const provider = new KernelCompleterProvider(); - const reconciliator = new ProviderReconciliator({ - context: { - widget: notebookPanel, - editor, - session: sessionContext.session, + private setupAdapter(): void { + + document.addEventListener('keydown', this.notebookKeydownListener, true); + + const initialFactories = standardRendererFactories.filter( + factory => factory.mimeTypes[0] !== 'text/javascript' + ); + + const ipywidgetsRendererFactory: IRenderMime.IRendererFactory = { + safe: true, + mimeTypes: [WIDGET_MIMETYPE], + defaultRank: 1, + createRenderer: options => + new WidgetLabRenderer(options, this._iPyWidgetsManager!), + }; + + initialFactories.push(ipywidgetsRendererFactory); + initialFactories.push(jsonRendererFactory); + initialFactories.push(javascriptRendererFactory); + + this._renderers.map(renderer => initialFactories.push(renderer)); + + const languages = new EditorLanguageRegistry(); + // Register default languages. + for (const language of EditorLanguageRegistry.getDefaultLanguages()) { + languages.addLanguage(language); + } + // Add Jupyter Markdown flavor here to support code block highlighting. + languages.addLanguage({ + name: 'ipythongfm', + mime: 'text/x-ipythongfm', + load: async () => { + // TODO: add support for LaTeX. + const m = await import('@codemirror/lang-markdown'); + return m.markdown({ + codeLanguages: (info: string) => languages.findBest(info) as any, + }); }, - providers: [provider], - timeout, }); - const handler = new CompletionHandler({ completer, reconciliator }); - void sessionContext.ready.then(() => { - const provider = new KernelCompleterProvider(); - const reconciliator = new ProviderReconciliator({ - context: { - widget: this._notebookPanel!, - editor, - session: sessionContext.session, + + this._rendermime = new RenderMimeRegistry({ + initialFactories, + latexTypesetter: new MathJaxTypesetter(), + markdownParser: getMarked(languages), + }); + + this._documentRegistry = new DocumentRegistry({}); + const mimeTypeService = new CodeMirrorMimeTypeService(languages); + + const themes = new EditorThemeRegistry(); + for (const theme of EditorThemeRegistry.getDefaultThemes()) { + themes.addTheme(theme); + } + const editorExtensions = () => { + const registry = new EditorExtensionRegistry(); + for (const extensionFactory of EditorExtensionRegistry.getDefaultExtensions( + { themes } + )) { + registry.addExtension(extensionFactory); + } + registry.addExtension({ + name: 'shared-model-binding', + factory: options => { + const sharedModel = options.model.sharedModel as IYText; + return EditorExtensionRegistry.createImmutableExtension( + ybinding({ + ytext: sharedModel.ysource, + undoManager: sharedModel.undoManager ?? undefined, + }) + ); }, - providers: [provider], - timeout: timeout, }); - handler.reconciliator = reconciliator; + return registry; + }; + const factoryService = new CodeMirrorEditorFactory({ + extensions: editorExtensions(), + languages, }); - handler.editor = editor; - notebookPanel.content.activeCellChanged.connect( - (sender: any, cell: Cell) => { - cell.ready.then(() => { - handler.editor = cell && cell.editor; - }); - } - ); - completer.hide(); - Widget.attach(completer, document.body); - return handler; - } + const editorServices: IEditorServices = { + factoryService, + mimeTypeService, + }; + const editorFactory = editorServices.factoryService.newInlineEditor; + const contentFactory = this._CellSidebar ? + new JupyterReactContentFactory( + this._CellSidebar, + this._id, + this._nbgrader, + this._commandRegistry, + { editorFactory }, + ) + : + new NotebookPanel.ContentFactory({ editorFactory }); - assignKernel(kernel: Kernel) { - this._kernel = kernel; - this._context?.sessionContext.changeKernel({ - id: kernel.id, + this._tracker = new NotebookTracker({ namespace: this._id }); + + const notebookWidgetFactory = new NotebookWidgetFactory({ + name: 'Notebook', + modelName: 'viewer', + fileTypes: ['notebook'], + defaultFor: ['notebook'], + preferKernel: true, + autoStartDefault: false, + canStartKernel: false, + shutdownOnClose: false, + rendermime: this._rendermime, + contentFactory, + mimeTypeService: editorServices.mimeTypeService, }); + notebookWidgetFactory.widgetCreated.connect((sender, notebookPanel) => { + notebookPanel.context.pathChanged.connect(() => { + this._tracker?.save(notebookPanel); + }); + this._tracker?.add(notebookPanel); + }); + this._documentRegistry.addWidgetFactory(notebookWidgetFactory); + + this._notebookModelFactory = new JupyterReactNotebookModelFactory({ + nbformat: this._nbformat, + readonly: this._readonly, + }); + this._documentRegistry.addModelFactory(this._notebookModelFactory); + + this.initializeContext(); + } get id(): string { return this._id; } - get notebookPanel(): NotebookPanel | undefined { - return this._notebookPanel; + get readonly(): boolean { + return this._readonly; } - get commands(): CommandRegistry { - return this._commandRegistry; + get serverless(): boolean { + return this._serverless; + } + + get lite(): Lite | undefined { + return this._lite; + } + + get path(): string | undefined { + return this._path; + } + + get url(): string | undefined { + return this._url; + } + + get nbformat(): INotebookContent | undefined { + return this._nbformat; + } + + get kernel(): Kernel | undefined { + return this._kernel; + } + + get notebookPanel(): NotebookPanel | undefined { + return this._notebookPanel; } get panel(): BoxPanel { return this._boxPanel; } + get commands(): CommandRegistry { + return this._commandRegistry; + } + get serviceManager(): ServiceManager.IManager { return this._serviceManager; } /* - * Only use this method to change an already existing nbformat. + * Only use this method to change an adapter with a nbformat. */ setNbformat(nbformat: INotebookContent) { if (nbformat === null) { - throw new Error( - 'The nbformat should first be set via the constructor of NotebookAdapter' - ); + throw new Error('The nbformat should first be set via the constructor of NotebookAdapter'); } - this._nbformat = nbformat; - if (this._nbformat) { + if (this._nbformat !== nbformat) { + this._nbformat = nbformat; this._notebookPanel?.model?.fromJSON(nbformat); } } + setServiceManager(serviceManager: ServiceManager.IManager, lite: Lite) { + console.log('-------', serviceManager); + if (this._lite !== lite) { + this._lite = lite; + } + if (this._serviceManager !== serviceManager) { + this._serviceManager = serviceManager; + } + this._nbformat = this._notebookPanel?.model?.toJSON() as INotebookContent; + this.initializeContext(); + } + + setReadonly(readonly: boolean) { + if (this._readonly !== readonly) { + this._readonly = readonly; + Array.from(this._context?.model.cells!).forEach(cell => cell.setMetadata('editable', !readonly)); + } + } + + setPath(path: string) { + if (this._path !== path) { + this._path = path; + this.initializeContext(); + } + } + + assignKernel(kernel: Kernel) { + this._kernel = kernel; + this._context?.sessionContext.changeKernel({ + id: kernel.id, + }); + } + setDefaultCellType = (cellType: CellType) => { this._notebookPanel!.content!.notebookConfig!.defaultCell! = cellType; }; @@ -607,10 +628,11 @@ export class NotebookAdapter { dispose = () => { document.removeEventListener('keydown', this.notebookKeydownListener, true); - // this._boxPanel.dispose(); - // this._notebookPanel?.dispose(); - // this._context?.dispose(); + this._context?.dispose(); + this._notebookPanel?.dispose(); + this._boxPanel.dispose(); }; + } export default NotebookAdapter; diff --git a/packages/react/src/components/notebook/NotebookCommands.ts b/packages/react/src/components/notebook/NotebookCommands.ts index f59aa1f7..d904b437 100644 --- a/packages/react/src/components/notebook/NotebookCommands.ts +++ b/packages/react/src/components/notebook/NotebookCommands.ts @@ -68,6 +68,19 @@ export const NotebookCommands = ( tracker: NotebookTracker, path?: string ): void => { + + if (path) { + commandRegistry.addCommand(cmdIds.save, { + label: 'Save', + execute: () => notebookPanel.context.save(), + }); + commandRegistry.addKeyBinding({ + selector: '.jp-Notebook', + keys: ['Accel S'], + command: cmdIds.save, + }); + } + // Add commands. commandRegistry.addCommand(cmdIds.invoke, { label: 'Completer: Invoke', @@ -93,12 +106,6 @@ export const NotebookCommands = ( } }, }); - if (path) { - commandRegistry.addCommand(cmdIds.save, { - label: 'Save', - execute: () => notebookPanel.context.save(), - }); - } let searchInstance: SearchDocumentView | undefined; commandRegistry.addCommand(cmdIds.startSearch, { label: 'Find…', @@ -452,7 +459,7 @@ export const NotebookCommands = ( keys: ['Shift J'], command: cmdIds.extendBelow, }, -{ + { selector: '.jp-Notebook', keys: ['Ctrl Z'], command: cmdIds.undo, @@ -480,13 +487,6 @@ export const NotebookCommands = ( ]; bindings.map(binding => commandRegistry.addKeyBinding(binding)); - if (path) { - commandRegistry.addKeyBinding({ - selector: '.jp-Notebook', - keys: ['Accel S'], - command: cmdIds.save, - }); - } -}; +} export default NotebookCommands; diff --git a/packages/react/src/components/notebook/NotebookState.ts b/packages/react/src/components/notebook/NotebookState.ts index ed36cfb7..6cfb666e 100644 --- a/packages/react/src/components/notebook/NotebookState.ts +++ b/packages/react/src/components/notebook/NotebookState.ts @@ -4,7 +4,6 @@ * MIT License */ -import NotebookAdapter from './NotebookAdapter'; import { createStore } from 'zustand/vanilla'; import { useStore } from 'zustand'; import { ReactPortal } from 'react'; @@ -13,8 +12,9 @@ import * as nbformat from '@jupyterlab/nbformat'; import { Cell, ICellModel } from '@jupyterlab/cells'; import { NotebookChange } from '@jupyter/ydoc'; import { Kernel as JupyterKernel } from '@jupyterlab/services'; +import { Kernel } from '../../jupyter/kernel/Kernel'; import { cmdIds } from './NotebookCommands'; -import Kernel from '../../jupyter/kernel/Kernel'; +import { NotebookAdapter } from './NotebookAdapter'; export type PortalDisplay = { portal: ReactPortal; @@ -36,9 +36,9 @@ export interface INotebooksState { notebooks: Map; } -type UpdateId = { +type NotebookUpdate = { id: string; - partialState: Partial; + state: Partial; }; type NotebookChangeId = { id: string; @@ -96,11 +96,11 @@ export type NotebookState = INotebooksState & { changeCellType: (mutation: CellMutation) => void; save: (mutation: DateMutation) => void; reset: () => void; - update: (update: UpdateId) => void; + update: (update: NotebookUpdate) => void; activeCellChange: (cellModelId: CellModelId) => void; - modelChange: (notebookModelId: NotebookModelId) => void; - notebookChange: (notebookChangeId: NotebookChangeId) => void; - kernelStatusChanged: (kernelStatusId: KernelStatusMutation) => void; + changeModel: (notebookModelId: NotebookModelId) => void; + changeNotebook: (notebookChangeId: NotebookChangeId) => void; + changeKernelStatus: (kernelStatusId: KernelStatusMutation) => void; changeKernel: (kernelChange: KernelChangeMutation) => void; addPortals: (portalsId: ReactPortalsMutation) => void; dispose: (id: string) => void; @@ -163,15 +163,18 @@ export const notebookStore = createStore((set, get) => ({ } }, reset: () => set((state: NotebookState) => ({ notebooks: new Map() })), - update: (update: UpdateId) => { + update: (update: NotebookUpdate) => { const notebooks = get().notebooks; let notebook = notebooks.get(update.id); if (notebook) { - notebook = { ...notebook, ...update.partialState }; + notebook = { + ...notebook, + ...update.state, + }; set((state: NotebookState) => ({ notebooks })); } else { notebooks.set(update.id, { - adapter: update.partialState.adapter, + adapter: update.state.adapter, portals: [], }); set((state: NotebookState) => ({ notebooks })); @@ -185,7 +188,7 @@ export const notebookStore = createStore((set, get) => ({ set((state: NotebookState) => ({ notebooks })); } }, - modelChange: (notebookModelId: NotebookModelId) => { + changeModel: (notebookModelId: NotebookModelId) => { const notebooks = get().notebooks; const notebook = notebooks.get(notebookModelId.id); if (notebook) { @@ -193,7 +196,7 @@ export const notebookStore = createStore((set, get) => ({ set((state: NotebookState) => ({ notebooks })); } }, - notebookChange: (notebookChangeId: NotebookChangeId) => { + changeNotebook: (notebookChangeId: NotebookChangeId) => { const notebooks = get().notebooks; const notebook = notebooks.get(notebookChangeId.id); if (notebook) { @@ -201,19 +204,19 @@ export const notebookStore = createStore((set, get) => ({ set((state: NotebookState) => ({ notebooks })); } }, - kernelStatusChanged: (kernelStatusId: KernelStatusMutation) => { + changeKernel: (kernelChange: KernelChangeMutation) => { const notebooks = get().notebooks; - const notebook = notebooks.get(kernelStatusId.id); + const notebook = notebooks.get(kernelChange.id); if (notebook) { - notebook.kernelStatus = kernelStatusId.kernelStatus; + notebook.adapter?.assignKernel(kernelChange.kernel); set((state: NotebookState) => ({ notebooks })); } }, - changeKernel: (kernelChange: KernelChangeMutation) => { + changeKernelStatus: (kernelStatusId: KernelStatusMutation) => { const notebooks = get().notebooks; - const notebook = notebooks.get(kernelChange.id); + const notebook = notebooks.get(kernelStatusId.id); if (notebook) { - notebook.adapter?.assignKernel(kernelChange.kernel); + notebook.kernelStatus = kernelStatusId.kernelStatus; set((state: NotebookState) => ({ notebooks })); } }, @@ -226,10 +229,10 @@ export const notebookStore = createStore((set, get) => ({ } }, dispose: (id: string): void => { + get().setPortalDisplay({ id, portalDisplay: undefined }); const notebooks = get().notebooks; const notebook = notebooks.get(id); if(notebook){ - notebook.adapter?.dispose(); notebooks.delete(id); } set((state: NotebookState) => ({ notebooks })); diff --git a/packages/react/src/components/notebook/cell/index.ts b/packages/react/src/components/notebook/cell/index.ts new file mode 100644 index 00000000..28ec2032 --- /dev/null +++ b/packages/react/src/components/notebook/cell/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './metadata'; +export * from './prompt'; +export * from './sidebar'; diff --git a/packages/react/src/components/notebook/cell/metadata/CellMetadataEditor.tsx b/packages/react/src/components/notebook/cell/metadata/CellMetadataEditor.tsx index ec75ba00..a609a6c9 100644 --- a/packages/react/src/components/notebook/cell/metadata/CellMetadataEditor.tsx +++ b/packages/react/src/components/notebook/cell/metadata/CellMetadataEditor.tsx @@ -11,13 +11,13 @@ import { Cell, ICellModel } from '@jupyterlab/cells'; import NbGraderType, { getNbGraderType } from './NbGraderCells'; import { newUlid } from '../../../../utils'; -type Props = { +type ICellMetadataEditorProps = { notebookId: string; cell: Cell; nbgrader: boolean; }; -export const CellMetadataEditor = (props: Props) => { +export const CellMetadataEditor = (props: ICellMetadataEditorProps) => { const { cell } = props; const [cellGradeType, setCellGradeType] = useState(getNbGraderType(cell)); const [nbGrade, setNbGrade] = useState<{grade_id: string; points: number}>( diff --git a/packages/react/src/components/notebook/cell/metadata/index.ts b/packages/react/src/components/notebook/cell/metadata/index.ts new file mode 100644 index 00000000..8212c372 --- /dev/null +++ b/packages/react/src/components/notebook/cell/metadata/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './CellMetadataEditor'; +export * from './NbGraderCells'; diff --git a/packages/react/src/components/notebook/cell/prompt/Countdown.tsx b/packages/react/src/components/notebook/cell/prompt/Countdown.tsx index d0cf5724..406f81ea 100644 --- a/packages/react/src/components/notebook/cell/prompt/Countdown.tsx +++ b/packages/react/src/components/notebook/cell/prompt/Countdown.tsx @@ -18,4 +18,4 @@ export const Countdown = (props: { count: number }) => { return () => clearInterval(intervalRef.current); }, []); return <>[{count}]; -}; +} diff --git a/packages/react/src/components/notebook/cell/prompt/index.ts b/packages/react/src/components/notebook/cell/prompt/index.ts new file mode 100644 index 00000000..73a2a8c2 --- /dev/null +++ b/packages/react/src/components/notebook/cell/prompt/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Countdown'; +export * from './CountdownInputPrompt'; +export * from './CountdownOutputPrompt'; diff --git a/packages/react/src/components/notebook/cell/sidebar/CellSidebar.tsx b/packages/react/src/components/notebook/cell/sidebar/CellSidebar.tsx index 7deecb23..dfb27518 100644 --- a/packages/react/src/components/notebook/cell/sidebar/CellSidebar.tsx +++ b/packages/react/src/components/notebook/cell/sidebar/CellSidebar.tsx @@ -14,13 +14,13 @@ import { ChevronDownIcon, SquareIcon, } from '@primer/octicons-react'; -import { CellSidebarProps } from './CellSidebarWidget'; +import { ICellSidebarProps } from './CellSidebarWidget'; import CellMetadataEditor from '../metadata/CellMetadataEditor'; import useNotebookStore from '../../NotebookState'; import { DATALAYER_CELL_HEADER_CLASS } from './CellSidebarWidget'; -export const CellSidebar = (props: CellSidebarProps) => { +export const CellSidebar = (props: ICellSidebarProps) => { const { notebookId, cellId, nbgrader } = props; const [visible, setVisible] = useState(false); const notebookStore = useNotebookStore() diff --git a/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx b/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx index 96f39119..556e74ab 100644 --- a/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx +++ b/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx @@ -14,12 +14,12 @@ import { SquareIcon, XIcon, } from '@primer/octicons-react'; -import { CellSidebarProps } from './CellSidebarWidget'; +import { ICellSidebarProps } from './CellSidebarWidget'; import useNotebookStore from '../../NotebookState'; import { DATALAYER_CELL_HEADER_CLASS } from './CellSidebarWidget'; -export const CellSidebarNew = (props: CellSidebarProps) => { +export const CellSidebarButton = (props: ICellSidebarProps) => { const { notebookId, cellId } = props; const notebookStore = useNotebookStore(); const [visible, setVisible] = useState(false); @@ -185,4 +185,4 @@ export const CellSidebarNew = (props: CellSidebarProps) => { ); }; -export default CellSidebarNew; +export default CellSidebarButton; diff --git a/packages/react/src/components/notebook/cell/sidebar/CellSidebarRun.tsx b/packages/react/src/components/notebook/cell/sidebar/CellSidebarRun.tsx index 991e65c9..3eac3969 100644 --- a/packages/react/src/components/notebook/cell/sidebar/CellSidebarRun.tsx +++ b/packages/react/src/components/notebook/cell/sidebar/CellSidebarRun.tsx @@ -8,12 +8,12 @@ import { useState } from 'react'; import { PanelLayout } from '@lumino/widgets'; import { Box, Button } from '@primer/react'; import { PlayIcon } from '@primer/octicons-react'; -import { CellSidebarProps } from './CellSidebarWidget'; +import { ICellSidebarProps } from './CellSidebarWidget'; import useNotebookStore from '../../NotebookState'; import { DATALAYER_CELL_HEADER_CLASS } from './CellSidebarWidget'; -export const CellSidebarRun = (props: CellSidebarProps) => { +export const CellSidebarRun = (props: ICellSidebarProps) => { const { notebookId } = props; const notebookStore = useNotebookStore(); const [visible, setVisible] = useState(false); diff --git a/packages/react/src/components/notebook/cell/sidebar/CellSidebarWidget.tsx b/packages/react/src/components/notebook/cell/sidebar/CellSidebarWidget.tsx index 26ab666c..51d207c7 100644 --- a/packages/react/src/components/notebook/cell/sidebar/CellSidebarWidget.tsx +++ b/packages/react/src/components/notebook/cell/sidebar/CellSidebarWidget.tsx @@ -14,7 +14,7 @@ import { notebookStore } from '../../NotebookState'; export const DATALAYER_CELL_HEADER_CLASS = 'dla-CellHeader-Container'; -export type CellSidebarProps = { +export type ICellSidebarProps = { notebookId: string; cellId: string; command: CommandRegistry; @@ -27,7 +27,7 @@ export class CellSidebarWidget { private readonly commands: CommandRegistry; constructor( - CellSidebar: (props: CellSidebarProps) => JSX.Element, + CellSidebar: (props: ICellSidebarProps) => JSX.Element, notebookId: string, nbgrader: boolean, commands: CommandRegistry, @@ -36,7 +36,7 @@ export class CellSidebarWidget this.commands = commands; this.addClass('jp-CellHeader'); this.id = newUuid(); - const props: CellSidebarProps = { + const props: ICellSidebarProps = { notebookId: notebookId, cellId: this.id, command: this.commands, diff --git a/packages/react/src/components/notebook/cell/sidebar/index.ts b/packages/react/src/components/notebook/cell/sidebar/index.ts new file mode 100644 index 00000000..e684f1b2 --- /dev/null +++ b/packages/react/src/components/notebook/cell/sidebar/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './CellSidebar'; +export * from './CellSidebarButton'; +export * from './CellSidebarRun'; +export * from './CellSidebarWidget'; diff --git a/packages/react/src/components/notebook/content/JupyterReactContentFactory.ts b/packages/react/src/components/notebook/content/JupyterReactContentFactory.ts index 1082f13a..34e03a02 100644 --- a/packages/react/src/components/notebook/content/JupyterReactContentFactory.ts +++ b/packages/react/src/components/notebook/content/JupyterReactContentFactory.ts @@ -7,10 +7,7 @@ import { CommandRegistry } from '@lumino/commands'; import { NotebookPanel } from '@jupyterlab/notebook'; import { ICellHeader, Cell } from '@jupyterlab/cells'; -import { - CellSidebarWidget, - CellSidebarProps, -} from '../cell/sidebar/CellSidebarWidget'; +import { CellSidebarWidget, ICellSidebarProps } from '../cell/sidebar/CellSidebarWidget'; // import { IInputPrompt } from '@jupyterlab/cells'; // import { NotebookInputPrompt } from './../cell/InputPrompt'; @@ -18,13 +15,13 @@ import { * Extend the default implementation NotebookPanel.ContentFactory of `IContentFactory`. */ export class JupyterReactContentFactory extends NotebookPanel.ContentFactory { - private readonly CellSidebar: (props: CellSidebarProps) => JSX.Element; + private readonly CellSidebar: (props: ICellSidebarProps) => JSX.Element; private readonly notebookId: string; private readonly nbgrader: boolean; private readonly commands: CommandRegistry; constructor( - CellSidebar: (props: CellSidebarProps) => JSX.Element, + CellSidebar: (props: ICellSidebarProps) => JSX.Element, notebookId: string, nbgrader: boolean, commands: CommandRegistry, diff --git a/packages/react/src/components/notebook/content/index.ts b/packages/react/src/components/notebook/content/index.ts new file mode 100644 index 00000000..3e769f8c --- /dev/null +++ b/packages/react/src/components/notebook/content/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './JupyterReactContentFactory'; diff --git a/packages/react/src/components/notebook/index.ts b/packages/react/src/components/notebook/index.ts new file mode 100644 index 00000000..c7f501a3 --- /dev/null +++ b/packages/react/src/components/notebook/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Notebook'; +export * from './NotebookAdapter'; +export * from './NotebookCommands'; +export * from './NotebookState'; +export * from './cell'; +export * from './content'; +export * from './marked'; +export * from './model'; +export * from './toolbar'; diff --git a/packages/react/src/components/notebook/marked/index.ts b/packages/react/src/components/notebook/marked/index.ts new file mode 100644 index 00000000..bd301b21 --- /dev/null +++ b/packages/react/src/components/notebook/marked/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './marked'; diff --git a/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts b/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts index 862fc0d1..4cd443bd 100644 --- a/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts +++ b/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts @@ -15,26 +15,27 @@ import type { ISharedNotebook } from '@jupyter/ydoc'; export class JupyterReactNotebookModelFactory extends NotebookModelFactory { private _nbformat?: INotebookContent; - private _readOnly: boolean; + private _readonly: boolean; /** @override */ constructor(options: DatalayerNotebookModelFactory.IOptions) { super(options); this._nbformat = options.nbformat; - this._readOnly = options.readOnly; + this._readonly = options.readonly; } /** @override */ - createNew( - options: DocumentRegistry.IModelOptions - ): INotebookModel { + createNew(options: DocumentRegistry.IModelOptions): INotebookModel { if (this._nbformat) { + this._nbformat.cells.forEach(cell => { + cell.metadata['editable'] = !this._readonly; + }); const notebookModel = new NotebookModel(); notebookModel.fromJSON(this._nbformat); return notebookModel; } else { const notebookModel = super.createNew(options); - notebookModel.readOnly = this._readOnly; + notebookModel.readOnly = this._readonly; return notebookModel; } } @@ -43,7 +44,7 @@ export class JupyterReactNotebookModelFactory extends NotebookModelFactory { export declare namespace DatalayerNotebookModelFactory { interface IOptions extends NotebookModelFactory.IOptions { nbformat?: INotebookContent; - readOnly: boolean; + readonly: boolean; } } diff --git a/packages/react/src/components/notebook/model/index.ts b/packages/react/src/components/notebook/model/index.ts new file mode 100644 index 00000000..670dfbe6 --- /dev/null +++ b/packages/react/src/components/notebook/model/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './JupyterReactNotebookModelFactory'; diff --git a/packages/react/src/examples/toolbars/NotebookToolbar.tsx b/packages/react/src/components/notebook/toolbar/NotebookToolbar.tsx similarity index 96% rename from packages/react/src/examples/toolbars/NotebookToolbar.tsx rename to packages/react/src/components/notebook/toolbar/NotebookToolbar.tsx index 5a1c295c..f2235fd0 100644 --- a/packages/react/src/examples/toolbars/NotebookToolbar.tsx +++ b/packages/react/src/components/notebook/toolbar/NotebookToolbar.tsx @@ -14,9 +14,13 @@ import { ZapIcon, PaperAirplaneIcon, } from '@primer/octicons-react'; -import useNotebookStore from '../../components/notebook/NotebookState'; +import useNotebookStore from '../NotebookState'; -export const NotebookToolbar = (props: { notebookId: string }) => { +export type INotebookToolbarProps = { + notebookId: string; +} + +export const NotebookToolbar = (props: INotebookToolbarProps) => { const { notebookId } = props; const notebookStore = useNotebookStore(); const [type, setType] = useState('code'); diff --git a/packages/react/src/components/notebook/toolbar/index.ts b/packages/react/src/components/notebook/toolbar/index.ts new file mode 100644 index 00000000..5e7df671 --- /dev/null +++ b/packages/react/src/components/notebook/toolbar/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './NotebookToolbar'; diff --git a/packages/react/src/components/output/index.ts b/packages/react/src/components/output/index.ts new file mode 100644 index 00000000..cb3d23b9 --- /dev/null +++ b/packages/react/src/components/output/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Output'; +export * from './OutputAdapter'; +export * from './OutputExecutor'; +export * from './OutputIPyWidgets'; +export * from './OutputRenderer'; +export * from './OutputState'; diff --git a/packages/react/src/components/settings/index.ts b/packages/react/src/components/settings/index.ts new file mode 100644 index 00000000..227385f6 --- /dev/null +++ b/packages/react/src/components/settings/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Settings'; +export * from './SettingsAdapter'; diff --git a/packages/react/src/components/terminal/Terminal.tsx b/packages/react/src/components/terminal/Terminal.tsx index 78e84d54..348fcdea 100644 --- a/packages/react/src/components/terminal/Terminal.tsx +++ b/packages/react/src/components/terminal/Terminal.tsx @@ -45,7 +45,7 @@ export const Terminal = (props: Terminal.ITerminalOptions) => { export namespace Terminal { export interface ITerminalOptions { height?: string; - colorMode?: ITerminal.Theme; + colormode?: ITerminal.Theme; /** * Code to be executed at terminal startup */ @@ -55,7 +55,7 @@ export namespace Terminal { Terminal.defaultProps = { height: '100%', - colorMode: 'dark', + colormode: 'dark', } as Partial; export default Terminal; diff --git a/packages/react/src/components/terminal/TerminalAdapter.ts b/packages/react/src/components/terminal/TerminalAdapter.ts index be5ea6e6..f9aeb220 100755 --- a/packages/react/src/components/terminal/TerminalAdapter.ts +++ b/packages/react/src/components/terminal/TerminalAdapter.ts @@ -14,7 +14,7 @@ export class TerminalAdapter { private terminalPanel: BoxPanel; constructor(options: TerminalAdapter.ITerminalAdapterOptions) { - const { serverSettings, colorMode, initCode } = options; + const { serverSettings, colormode, initCode } = options; this.terminalPanel = new BoxPanel(); this.terminalPanel.spacing = 0; this.terminalPanel.addClass('dla-JupyterLab-Terminal-id'); @@ -26,7 +26,7 @@ export class TerminalAdapter { console.log('Jupyter Terminal status', status); }); this.terminal = new JupyterTerminal(terminalConnection, { - theme: colorMode, + theme: colormode, }); if (initCode) { await this.terminal.ready; diff --git a/packages/react/src/components/terminal/index.ts b/packages/react/src/components/terminal/index.ts new file mode 100644 index 00000000..57ba9400 --- /dev/null +++ b/packages/react/src/components/terminal/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Terminal'; +export * from './TerminalAdapter'; +export * from './TerminalState'; diff --git a/packages/react/src/components/textinput/index.ts b/packages/react/src/components/textinput/index.ts new file mode 100644 index 00000000..47f091a9 --- /dev/null +++ b/packages/react/src/components/textinput/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './TextInput'; diff --git a/packages/react/src/components/viewer/Viewer.tsx b/packages/react/src/components/viewer/Viewer.tsx index 0518a71c..32b5ab31 100644 --- a/packages/react/src/components/viewer/Viewer.tsx +++ b/packages/react/src/components/viewer/Viewer.tsx @@ -10,13 +10,13 @@ import InputViewer from './input/InputViewer'; // import OutputViewer from './output/OutputViewer'; import { newUuid } from '../../utils/Utils'; -type Props = { +type IViewerProps = { nbformat?: INotebookContent; nbformatUrl?: string; outputs: boolean; }; -export const Viewer = (props: Props) => { +export const Viewer = (props: IViewerProps) => { const { nbformat, nbformatUrl } = props; const [model, setModel] = useState(); useEffect(() => { diff --git a/packages/react/src/components/viewer/index.ts b/packages/react/src/components/viewer/index.ts new file mode 100644 index 00000000..6dd1bc68 --- /dev/null +++ b/packages/react/src/components/viewer/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Viewer'; +export * from './input'; +export * from './output'; diff --git a/packages/react/src/components/viewer/input/index.ts b/packages/react/src/components/viewer/input/index.ts new file mode 100644 index 00000000..44476b47 --- /dev/null +++ b/packages/react/src/components/viewer/input/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './CodemirrorView'; +export * from './CodemirrorViewer'; diff --git a/packages/react/src/components/viewer/output/OutputViewer.tsx b/packages/react/src/components/viewer/output/OutputViewer.tsx index 763f09fa..33b626d3 100644 --- a/packages/react/src/components/viewer/output/OutputViewer.tsx +++ b/packages/react/src/components/viewer/output/OutputViewer.tsx @@ -6,7 +6,7 @@ import { ICell, IOutput } from '@jupyterlab/nbformat'; import Lumino from '../../lumino/Lumino'; -import OutputAdapter from './OutputAdapter'; +import OutputViewerAdapter from './OutputViewerAdapter'; type Props = { cell: ICell; @@ -16,7 +16,7 @@ type Props = { export const OutputViewer = (props: Props) => { const { cell, adaptPlotly } = props; const outputs = cell.outputs ? (cell.outputs as IOutput[]) : undefined; - const outputAdapter = new OutputAdapter(adaptPlotly, outputs); + const outputAdapter = new OutputViewerAdapter(adaptPlotly, outputs); switch (cell.cell_type) { case 'code': { return ( diff --git a/packages/react/src/components/viewer/output/OutputAdapter.ts b/packages/react/src/components/viewer/output/OutputViewerAdapter.ts similarity index 96% rename from packages/react/src/components/viewer/output/OutputAdapter.ts rename to packages/react/src/components/viewer/output/OutputViewerAdapter.ts index 3f3dd5a0..328ee01a 100755 --- a/packages/react/src/components/viewer/output/OutputAdapter.ts +++ b/packages/react/src/components/viewer/output/OutputViewerAdapter.ts @@ -14,7 +14,7 @@ import { import { rendererFactory as jsonRendererFactory } from '@jupyterlab/json-extension'; import { rendererFactory as javascriptRendererFactory } from '@jupyterlab/javascript-extension'; -export class OutputAdapter { +export class OutputViewerAdapter { private _renderers: IRenderMime.IRendererFactory[]; private _outputArea: OutputArea; private _rendermime: RenderMimeRegistry; @@ -58,4 +58,4 @@ export class OutputAdapter { } } -export default OutputAdapter; +export default OutputViewerAdapter; diff --git a/packages/react/src/components/viewer/output/index.ts b/packages/react/src/components/viewer/output/index.ts new file mode 100644 index 00000000..da6b8249 --- /dev/null +++ b/packages/react/src/components/viewer/output/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './OutputViewer'; +export * from './OutputViewerAdapter'; diff --git a/packages/react/src/examples/Bokeh.tsx b/packages/react/src/examples/Bokeh.tsx index f2aa2df7..f00205c3 100644 --- a/packages/react/src/examples/Bokeh.tsx +++ b/packages/react/src/examples/Bokeh.tsx @@ -5,13 +5,13 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Bokeh = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/Bqplot.tsx b/packages/react/src/examples/Bqplot.tsx index ac9b18fc..02a8ecb6 100644 --- a/packages/react/src/examples/Bqplot.tsx +++ b/packages/react/src/examples/Bqplot.tsx @@ -5,13 +5,13 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Bqplot = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/CellLite.tsx b/packages/react/src/examples/CellLite.tsx index bafbd736..be1dbb14 100644 --- a/packages/react/src/examples/CellLite.tsx +++ b/packages/react/src/examples/CellLite.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { Box } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import Cell from '../components/cell/Cell'; const div = document.createElement('div'); diff --git a/packages/react/src/examples/Cells.tsx b/packages/react/src/examples/Cells.tsx index 08f18795..a960bb18 100644 --- a/packages/react/src/examples/Cells.tsx +++ b/packages/react/src/examples/Cells.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { Box } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const div = document.createElement('div'); @@ -14,7 +14,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + Jupyter Cells wrapped in a single Jupyter Context @@ -23,5 +23,5 @@ root.render( r = random.randint(0,9)`} /> - + ); diff --git a/packages/react/src/examples/CellsExecute.tsx b/packages/react/src/examples/CellsExecute.tsx index 77d0bf7b..c285520a 100644 --- a/packages/react/src/examples/CellsExecute.tsx +++ b/packages/react/src/examples/CellsExecute.tsx @@ -7,16 +7,18 @@ import { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; import { Button, Box } from '@primer/react'; import { cellsStore, ICellsState } from '../components/cell/CellState'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const CODE_CELL_1 = `import time +print("Cell 1 start...") time.sleep(3) -print("Cell 1 done.")` +print("Cell 1 end.")` const CODE_CELL_2 = `import time +print("Cell 2 start...") time.sleep(3) -print("Cell 2 done.")` +print("Cell 2 end.")` const CellsExecute = () => { const [executionDisable, setExecutionDisable] = useState(false); @@ -33,7 +35,7 @@ const CellsExecute = () => { cellsStore.getState().execute(); } return ( - + { Execute all - + ) }; diff --git a/packages/react/src/examples/Console.tsx b/packages/react/src/examples/Console.tsx index 29322a6d..15dd70c4 100644 --- a/packages/react/src/examples/Console.tsx +++ b/packages/react/src/examples/Console.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { Box } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Console from '../components/console/Console'; const div = document.createElement('div'); @@ -14,8 +14,8 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + A Jupyter Console - + ); diff --git a/packages/react/src/examples/ConsoleLite.tsx b/packages/react/src/examples/ConsoleLite.tsx index 22bca2e2..626f1eec 100644 --- a/packages/react/src/examples/ConsoleLite.tsx +++ b/packages/react/src/examples/ConsoleLite.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { Box } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import Console from '../components/console/Console'; const div = document.createElement('div'); diff --git a/packages/react/src/examples/Dashboard.tsx b/packages/react/src/examples/Dashboard.tsx index 4ad6870d..2e9456cd 100644 --- a/packages/react/src/examples/Dashboard.tsx +++ b/packages/react/src/examples/Dashboard.tsx @@ -6,15 +6,15 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExample.ipynb.json'; const Dashboard = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/Deno.tsx b/packages/react/src/examples/Deno.tsx index 21ef10e9..a80355d5 100644 --- a/packages/react/src/examples/Deno.tsx +++ b/packages/react/src/examples/Deno.tsx @@ -5,15 +5,15 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Jupyter } from '../jupyter/Jupyter'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Deno = () => ( + - + ); diff --git a/packages/react/src/examples/GeoJson.tsx b/packages/react/src/examples/GeoJson.tsx index fded7852..9884bd76 100644 --- a/packages/react/src/examples/GeoJson.tsx +++ b/packages/react/src/examples/GeoJson.tsx @@ -6,22 +6,22 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as geojsonRenderer } from '@jupyterlab/geojson-extension'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import CellSidebarButton from '../components/notebook/cell/sidebar/CellSidebarButton'; const GeoJson = () => ( - + - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/IPyLeaflet.tsx b/packages/react/src/examples/IPyLeaflet.tsx index a8474019..93629f74 100644 --- a/packages/react/src/examples/IPyLeaflet.tsx +++ b/packages/react/src/examples/IPyLeaflet.tsx @@ -5,13 +5,13 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const IPyLeaflet = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/IPyReact.tsx b/packages/react/src/examples/IPyReact.tsx index ab5b1fcc..9f0139a9 100644 --- a/packages/react/src/examples/IPyReact.tsx +++ b/packages/react/src/examples/IPyReact.tsx @@ -5,13 +5,13 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const IPyReact = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/IPyWidgets.tsx b/packages/react/src/examples/IPyWidgets.tsx index 00ab1f1e..86ae7c8e 100644 --- a/packages/react/src/examples/IPyWidgets.tsx +++ b/packages/react/src/examples/IPyWidgets.tsx @@ -6,15 +6,15 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExample.ipynb.json'; const IPyWidgets = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/IPyWidgetsWithState.tsx b/packages/react/src/examples/IPyWidgetsState.tsx similarity index 60% rename from packages/react/src/examples/IPyWidgetsWithState.tsx rename to packages/react/src/examples/IPyWidgetsState.tsx index d3f5bf7f..f115f3a7 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsState.tsx @@ -6,15 +6,15 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExampleWithState.ipynb.json'; -const IPyWidgetsWithState = () => ( - +const IPyWidgetsState = () => ( + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); -root.render(); +root.render(); diff --git a/packages/react/src/examples/All.tsx b/packages/react/src/examples/JupyterContext.tsx similarity index 69% rename from packages/react/src/examples/All.tsx rename to packages/react/src/examples/JupyterContext.tsx index 87d17abe..248244aa 100644 --- a/packages/react/src/examples/All.tsx +++ b/packages/react/src/examples/JupyterContext.tsx @@ -4,20 +4,22 @@ * MIT License */ +import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { IOutput, INotebookContent } from '@jupyterlab/nbformat'; -import { Box, Button, ButtonGroup } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { Box, Button, ButtonGroup, SegmentedControl } from '@primer/react'; +import { DEFAULT_JUPYTER_SERVER_URL, DEFAULT_JUPYTER_SERVER_TOKEN } from '../jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import { useJupyter } from '../jupyter/JupyterContext'; import { Kernel } from '../jupyter/kernel/Kernel'; import Cell from '../components/cell/Cell'; -import Notebook from '../components/notebook/Notebook'; +import { Notebook } from '../components/notebook/Notebook'; import Output from '../components/output/Output'; import FileBrowser from '../components/filebrowser/FileBrowser'; import FileManagerJupyterLab from '../components/filemanager/FileManagerJupyterLab'; import Terminal from '../components/terminal/Terminal'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import CellSidebarButton from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import Console from '../components/console/Console'; import { useCellsStore } from '../components/cell/CellState'; import useNotebookStore from '../components/notebook/NotebookState'; @@ -185,43 +187,60 @@ const Outputs = () => { ); }; +const JuptyerContextExample = () => { + const [index, setIndex] = useState(1); + return ( + <> + + setIndex(index)} aria-label="jupyter-react-example"> + Serverless + Server + +
+ + + +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+ + ); +} + const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); const cellId = 'my-cell-1' -root.render( - - -
- -
- - - -
- -
- - -
- -
- -
- -
- -
-); +root.render(); diff --git a/packages/react/src/examples/JupyterLabApp.tsx b/packages/react/src/examples/JupyterLabApp.tsx index f5721622..d311ece4 100644 --- a/packages/react/src/examples/JupyterLabApp.tsx +++ b/packages/react/src/examples/JupyterLabApp.tsx @@ -6,14 +6,13 @@ import { createRoot } from 'react-dom/client'; import { NotebookPanel } from '@jupyterlab/notebook'; -import Jupyter from '../jupyter/Jupyter'; -import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; -import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; +import { Jupyter } from '../jupyter/Jupyter'; +import { JupyterLabApp, JupyterLabAppAdapter } from '../components/jupyterlab'; import * as lightThemePlugins from '@jupyterlab/theme-light-extension'; import * as ipywidgetsPlugins from '@jupyter-widgets/jupyterlab-manager'; import * as plotlyPlugins from 'jupyterlab-plotly/lib/jupyterlab-plugin'; -import * as reactPlugins from './../jupyter/lab/index'; +import * as reactPlugins from './../jupyter/lab/plugin'; import * as plotlyMimeRenderers from 'jupyterlab-plotly/lib/plotly-renderer'; @@ -42,7 +41,7 @@ const JupyterLabAppExample = () => { onJupyterLab={onJupyterLab} /> ); -}; +} const div = document.createElement('div'); document.body.appendChild(div); diff --git a/packages/react/src/examples/JupyterLabAppHeadless.tsx b/packages/react/src/examples/JupyterLabAppHeadless.tsx index 51bfb8c9..f77c2b2c 100644 --- a/packages/react/src/examples/JupyterLabAppHeadless.tsx +++ b/packages/react/src/examples/JupyterLabAppHeadless.tsx @@ -10,9 +10,9 @@ import { Box, Text, ToggleSwitch, ThemeProvider, useTheme } from '@primer/react' import { BoxPanel } from '@lumino/widgets'; import { ThemeManager } from '@jupyterlab/apputils'; // import { NotebookTracker } from '@jupyterlab/notebook'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import Lumino from '../components/lumino/Lumino'; -import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; +import { Colormode } from '../theme/JupyterLabColormode'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; @@ -34,7 +34,7 @@ const PATH_INDEX = 1; const JupyterLabAppHeadless = () => { const [notebookBoxPanel, setNotebookBoxPanel] = useState(); - const [theme, setTheme] = useState('light'); + const [theme, setTheme] = useState('light'); const [jupyterLabAdapter, setJupyterlabAdapter] = useState(); const { setColorMode } = useTheme(); const [isDark, setDark] = useState(false); @@ -66,7 +66,7 @@ const JupyterLabAppHeadless = () => { { const [notebookBoxPanel, setNotebookBoxPanel] = useState(); - const [theme, setTheme] = useState('light'); + const [theme, setTheme] = useState('light'); const [jupyterLabAdapter, setJupyterlabAdapter] = useState(); const { setColorMode } = useTheme(); const [isDark, setDark] = useState(false); @@ -63,7 +63,7 @@ const JupyterLabAppHeadless = () => { }; return ( <> - + { PluginType={ThemeManager} onPlugin={onPlugin} /> - + ); }; diff --git a/packages/react/src/examples/JupyterLabAppServerless.tsx b/packages/react/src/examples/JupyterLabAppServerless.tsx index 597fb0d0..64afd664 100644 --- a/packages/react/src/examples/JupyterLabAppServerless.tsx +++ b/packages/react/src/examples/JupyterLabAppServerless.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterLabTheme } from '../jupyter/lab/JupyterLabTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; @@ -52,8 +52,8 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - +

JupyterLab Serverless Application

-
+ ); diff --git a/packages/react/src/examples/JupyterLabAppServiceManager.tsx b/packages/react/src/examples/JupyterLabAppServiceManager.tsx index 4f09b2ad..f53fcd06 100644 --- a/packages/react/src/examples/JupyterLabAppServiceManager.tsx +++ b/packages/react/src/examples/JupyterLabAppServiceManager.tsx @@ -7,20 +7,19 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { NotebookPanel } from '@jupyterlab/notebook'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; -import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; -import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; -import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { ServiceManagerLess } from '../jupyter'; +import { JupyterLabApp, JupyterLabAppAdapter } from '../components/jupyterlab'; import * as lightThemePlugins from '@jupyterlab/theme-light-extension'; import * as ipywidgetsPlugins from '@jupyter-widgets/jupyterlab-manager'; import * as plotlyPlugins from 'jupyterlab-plotly/lib/jupyterlab-plugin'; -// import * as reactPlugins from './../jupyter/lab/index'; +// import * as reactPlugins from './../jupyter/lab/plugin'; import * as plotlyMimeRenderers from 'jupyterlab-plotly/lib/plotly-renderer'; const JupyterLabAppServiceManager = () => { - const [serviceManager, _] = useState(new JupyterServiceManagerLess()); + const [serviceManager, _] = useState(new ServiceManagerLess()); const onJupyterLab = async (jupyterLabAdapter: JupyterLabAppAdapter) => { const jupyterLab = jupyterLabAdapter.jupyterLab; console.log('JupyterLab is ready', jupyterLab); @@ -49,15 +48,15 @@ const JupyterLabAppServiceManager = () => { onJupyterLab={onJupyterLab} /> ); -}; +} const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); root.render( - -

JupyterLab Application with Service Manager property

+ +

JupyterLab Application with Service Manager

-
+ ); diff --git a/packages/react/src/examples/KernelExecute.tsx b/packages/react/src/examples/KernelExecute.tsx index de7233b1..896b6148 100644 --- a/packages/react/src/examples/KernelExecute.tsx +++ b/packages/react/src/examples/KernelExecute.tsx @@ -8,7 +8,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Heading, Textarea, Button } from '@primer/react'; import { useJupyter } from '../jupyter/JupyterContext'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import KernelProgressBar from './../components/kernel/KernelProgressBar'; export const KernelExecuteView = () => { @@ -83,9 +83,9 @@ export const KernelExecuteView = () => { const KernelExecute = () => { return ( - + - + ); } diff --git a/packages/react/src/examples/KernelExecutor.tsx b/packages/react/src/examples/KernelExecutor.tsx index 0d59e7a7..edec011e 100644 --- a/packages/react/src/examples/KernelExecutor.tsx +++ b/packages/react/src/examples/KernelExecutor.tsx @@ -9,13 +9,10 @@ import { createRoot } from 'react-dom/client'; import { Box, Heading } from '@primer/react'; import { IOutputAreaModel } from '@jupyterlab/outputarea'; import { KernelMessage } from '@jupyterlab/services'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { Output } from '../components/output/Output'; -import { - IOPubMessageHook, - ShellMessageHook, -} from '../jupyter/kernel/KernelExecutor'; +import { IOPubMessageHook, ShellMessageHook } from '../jupyter/kernel/KernelExecutor'; const CODE = `from time import sleep for i in range(0, 15): @@ -83,9 +80,9 @@ const KernelExecutorView = () => { const KernelExecutor = () => { return ( - + - + ); }; diff --git a/packages/react/src/examples/Kernels.tsx b/packages/react/src/examples/Kernels.tsx index 9a6237ac..8e335fa8 100644 --- a/packages/react/src/examples/Kernels.tsx +++ b/packages/react/src/examples/Kernels.tsx @@ -9,7 +9,7 @@ import { useState } from 'react'; import { Box, Heading, Textarea, Button, Pagehead, Text } from '@primer/react'; import { IModel } from '@jupyterlab/services/lib/kernel/kernel'; import { ISpecModel } from '@jupyterlab/services/lib/kernelspec/kernelspec'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { KERNEL_STATES, @@ -295,8 +295,8 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + The Kernel Components - + ); diff --git a/packages/react/src/examples/Matplotlib.tsx b/packages/react/src/examples/Matplotlib.tsx index 2ab94a94..da4347f2 100644 --- a/packages/react/src/examples/Matplotlib.tsx +++ b/packages/react/src/examples/Matplotlib.tsx @@ -6,17 +6,17 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import JupyterLabCss from '../jupyter/lab/JupyterLabCss'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Jupyter } from '../jupyter/Jupyter'; +import { JupyterLabCss } from '../theme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/Matplotlib.ipynb.json'; const Matplotlib = () => ( - + + - + ); diff --git a/packages/react/src/examples/NotebookCellSidebar.tsx b/packages/react/src/examples/NotebookCellSidebar.tsx index 799c32c4..76bdc3a2 100644 --- a/packages/react/src/examples/NotebookCellSidebar.tsx +++ b/packages/react/src/examples/NotebookCellSidebar.tsx @@ -6,15 +6,15 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebarSource from './sidebars/CellSidebarSource'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; const NotebookCellSidebar = () => ( - + ( CellSidebar={CellSidebarSource} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/NotebookColorMode.tsx b/packages/react/src/examples/NotebookColormode.tsx similarity index 70% rename from packages/react/src/examples/NotebookColorMode.tsx rename to packages/react/src/examples/NotebookColormode.tsx index 349e8e1f..0a254adc 100644 --- a/packages/react/src/examples/NotebookColorMode.tsx +++ b/packages/react/src/examples/NotebookColormode.tsx @@ -8,22 +8,22 @@ import { useCallback, useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Text, ToggleSwitch } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Jupyter } from '../jupyter/Jupyter'; +import { Colormode } from '../theme/JupyterLabColormode'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; -const NotebookColorMode = () => { - const [colorMode, setColorMode] = useState('light'); +const NotebookColormode = () => { + const [colormode, setColormode] = useState('light'); const [isOn, setIsOn] = useState(false); useEffect(() => { if (isOn) { - setColorMode('dark'); + setColormode('dark'); } else { - setColorMode('light'); + setColormode('light'); } }, [isOn]); const onClick = useCallback(() => { @@ -34,7 +34,7 @@ const NotebookColorMode = () => { }, []); return ( <> - + { display="block" mb={1} > - { colorMode === 'light' ? 'Light' : 'Dark' } Mode + { colormode === 'light' ? 'Light' : 'Dark' } Mode ); +root.render(); diff --git a/packages/react/src/examples/NotebookExternalContent.tsx b/packages/react/src/examples/NotebookExternalContent.tsx index 8e98d047..3289d08d 100644 --- a/packages/react/src/examples/NotebookExternalContent.tsx +++ b/packages/react/src/examples/NotebookExternalContent.tsx @@ -9,9 +9,9 @@ import { createRoot } from 'react-dom/client'; import { Box, IconButton } from '@primer/react'; import { ZapIcon } from '@primer/octicons-react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import { notebookStore } from '../components/notebook/NotebookState'; import notebook from './notebooks/NotebookExample1.ipynb.json'; @@ -19,13 +19,13 @@ import notebook from './notebooks/NotebookExample1.ipynb.json'; const NOTEBOOK_ID = 'notebook-model-id'; const NotebookExternalContent = () => { - const [nbformat, setNbFormat] = useState(); + const [nbformat, setNbformat] = useState(); const [updatedNbFormat, setUpdatedNbFormat] = useState(); const model = notebookStore.getState().selectNotebookModel(NOTEBOOK_ID)?.model; useEffect(() => { // Set nbformat with any content. // This may come from an external storage that you fetch in this react effect. - setNbFormat(notebook); + setNbformat(notebook); }, []); useEffect(() => { if (model) { @@ -74,7 +74,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookInit.tsx b/packages/react/src/examples/NotebookInit.tsx index 8de181ef..4b2716bb 100644 --- a/packages/react/src/examples/NotebookInit.tsx +++ b/packages/react/src/examples/NotebookInit.tsx @@ -13,7 +13,7 @@ import { Kernel, Notebook, } from '../index'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; import useNotebookStore from '../components/notebook/NotebookState'; const NOTEBOOK_ID = 'notebook'; diff --git a/packages/react/src/examples/NotebookKernelChange.tsx b/packages/react/src/examples/NotebookKernelChange.tsx index 51030c70..1acf26cd 100755 --- a/packages/react/src/examples/NotebookKernelChange.tsx +++ b/packages/react/src/examples/NotebookKernelChange.tsx @@ -4,51 +4,75 @@ * MIT License */ +import { useState } from 'react'; import { createRoot } from 'react-dom/client'; -import { Box, Button } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { Box, Button, Flash } from '@primer/react'; +import { Jupyter } from '../jupyter/Jupyter'; import { useJupyter } from '../jupyter/JupyterContext'; import { Kernel } from '../jupyter/kernel/Kernel'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Notebook } from '../components/notebook/Notebook'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import useNotebookStore from '../components/notebook/NotebookState'; -const NOTEBOOK_ID = 'notebook-kernel-id'; +const NOTEBOOK_ID = 'notebook-kernel-change-id'; -const NEW_KERNEL_NAME = 'deno'; +const PYTHON_KERNEL_NAME = 'python'; + +const DENO_KERNEL_NAME = 'deno'; const NotebookKernelChange = () => { - const { kernelManager, serviceManager } = useJupyter(); + const { kernelManager, serviceManager, kernel } = useJupyter(); + const [message, setMessage] = useState(""); const notebookStore = useNotebookStore(); + const notebook = notebookStore.selectNotebook(NOTEBOOK_ID); const changeKernel = () => { if (kernelManager && serviceManager) { - const kernel = new Kernel({ + const newKernel = new Kernel({ kernelManager, - kernelName: NEW_KERNEL_NAME, - kernelSpecName: NEW_KERNEL_NAME, + kernelName: DENO_KERNEL_NAME, + kernelSpecName: DENO_KERNEL_NAME, kernelspecsManager: serviceManager.kernelspecs, sessionManager: serviceManager.sessions, }); - kernel.ready.then(() => { - notebookStore.changeKernel({ id: NOTEBOOK_ID, kernel }); - alert(`The kernel is changed (was python3, now ${NEW_KERNEL_NAME}). Bummer, all your variables are lost!`); + newKernel.ready.then(() => { + notebookStore.changeKernel({ id: NOTEBOOK_ID, kernel: newKernel }); + setMessage(`🥺 Bummer, all your variables are lost! The kernel was ${PYTHON_KERNEL_NAME} and is now ${DENO_KERNEL_NAME}). Try with: import pl from "npm:nodejs-polars";`); }); } }; return ( - <> + - + + + + + Kernel ID: {kernel?.id} + + + Kernel Client ID: {notebook?.adapter?.kernel?.clientId} + + + Kernel Session ID: {notebook?.adapter?.kernel?.session.id} + + + Kernel Info: {notebook?.adapter?.kernel?.info?.language_info.name} + + {message && + + {message} + + } - + ); }; @@ -57,7 +81,5 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - - ); diff --git a/packages/react/src/examples/NotebookLite.tsx b/packages/react/src/examples/NotebookLite.tsx index e5f34896..5b2070e8 100644 --- a/packages/react/src/examples/NotebookLite.tsx +++ b/packages/react/src/examples/NotebookLite.tsx @@ -7,10 +7,10 @@ import { createRoot } from 'react-dom/client'; import { Box } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Jupyter } from '../jupyter/Jupyter'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; diff --git a/packages/react/src/examples/NotebookMutations.tsx b/packages/react/src/examples/NotebookMutations.tsx new file mode 100644 index 00000000..39f1040a --- /dev/null +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { useState } from 'react'; +import { createRoot } from 'react-dom/client'; +import { INotebookContent } from '@jupyterlab/nbformat'; +import { ServiceManager } from '@jupyterlab/services'; +import { Box, SegmentedControl } from '@primer/react'; +import { createServiceManagerLite, createServerSettings, getJupyterServerUrl, getJupyterServerToken, ServiceManagerLess } from '../jupyter'; +import { useNotebookStore, Notebook} from './../components'; +import { JupyterReactTheme } from '../theme'; + +import nbformat from './notebooks/NotebookExample1.ipynb.json'; + +const NOTEBOOK_ID = 'notebook-mutations-id'; + +const NotebookMutations = () => { + const [index, setIndex] = useState(0); + const [readonly, setReadonly] = useState(true); + const [serverless, setServerless] = useState(true); + const [lite, setLite] = useState(false); + const [serviceManager, setServiceManager] = useState(new ServiceManagerLess()); + const notebookStore = useNotebookStore(); + const notebook = notebookStore.selectNotebook(NOTEBOOK_ID); + const changeIndex = (index: number) => { + setIndex(index); + switch(index) { + case 0: { + setReadonly(true); + setServerless(true); + setLite(false); + setServiceManager(new ServiceManagerLess()); + break; + } + case 1: { + setReadonly(false); + setServerless(true); + setLite(true); + createServiceManagerLite().then(serviceManager => { + console.log('Created Service Manager Lite', serviceManager); + setServiceManager(serviceManager); + }); + break; + } + case 2: { + setReadonly(false); + setServerless(false); + setLite(false); + const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); + const serviceManager = new ServiceManager({ serverSettings }); + setServiceManager(serviceManager); + break; + } + } + } + return ( + + + + changeIndex(index)} aria-label="jupyter-react-example"> + Readonly + Browser Kernel + OSS Kernel + Datalayer CPU Kernel + Datalayer GPU Kernel + + + + Readonly: {String(notebook?.adapter?.readonly)} + + + Serverless: {String(notebook?.adapter?.serverless)} + + + Lite: {String(notebook?.adapter?.lite)} + + + Kernel: {notebook?.adapter?.kernel?.id} ({notebook?.adapter?.kernel?.info?.banner}) + + + Service Manager Ready: {String(notebook?.adapter?.serviceManager.isReady)} + + + Service Manager URL: {notebook?.adapter?.serviceManager.serverSettings.baseUrl} + + + + + ); +} + +const div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); diff --git a/packages/react/src/examples/NotebookNbFormat.tsx b/packages/react/src/examples/NotebookNbformat.tsx similarity index 60% rename from packages/react/src/examples/NotebookNbFormat.tsx rename to packages/react/src/examples/NotebookNbformat.tsx index e977013b..37d866b4 100644 --- a/packages/react/src/examples/NotebookNbFormat.tsx +++ b/packages/react/src/examples/NotebookNbformat.tsx @@ -6,15 +6,15 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; -const NotebookNbFormat = () => ( - +const NotebookNbformat = () => ( + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); -root.render(); +root.render(); diff --git a/packages/react/src/examples/NotebookNbFormatChange.tsx b/packages/react/src/examples/NotebookNbformatChange.tsx similarity index 74% rename from packages/react/src/examples/NotebookNbFormatChange.tsx rename to packages/react/src/examples/NotebookNbformatChange.tsx index 7c41ca92..b63a8702 100755 --- a/packages/react/src/examples/NotebookNbFormatChange.tsx +++ b/packages/react/src/examples/NotebookNbformatChange.tsx @@ -8,9 +8,9 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button, ButtonGroup } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import useNotebookStore from '../components/notebook/NotebookState'; import nbformat1 from './notebooks/NotebookExample1.ipynb.json'; @@ -18,12 +18,12 @@ import nbformat2 from './notebooks/NotebookExample2.ipynb.json'; const NOTEBOOK_ID = 'notebook-model-change-id'; -const NotebookNbFormatChange = () => { +const NotebookNbformatChange = () => { const notebookStore = useNotebookStore(); const [nbformat, setNbformat] = useState(nbformat1); - const changeModel = () => { + const changeNbformat = () => { console.log( - 'Notebook NbFormat from store', + 'Notebook Nbformat from store', notebookStore.notebooks.get(NOTEBOOK_ID)?.model?.toJSON() as INotebookContent ); nbformat === nbformat1 ? setNbformat(nbformat2) : setNbformat(nbformat1); @@ -32,8 +32,8 @@ const NotebookNbFormatChange = () => { <> - @@ -52,7 +52,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - - - + + + ); diff --git a/packages/react/src/examples/NotebookNoContext.tsx b/packages/react/src/examples/NotebookNoContext.tsx index 476ab51e..26ca6a26 100644 --- a/packages/react/src/examples/NotebookNoContext.tsx +++ b/packages/react/src/examples/NotebookNoContext.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterLabTheme } from '../jupyter/lab/JupyterLabTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebarButton } from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; @@ -16,17 +16,17 @@ const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); -const colorMode = 'light'; +const colormode = 'light'; root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookNoContextNoPrimer.tsx b/packages/react/src/examples/NotebookNoPrimer.tsx similarity index 57% rename from packages/react/src/examples/NotebookNoContextNoPrimer.tsx rename to packages/react/src/examples/NotebookNoPrimer.tsx index 50d8397f..8856b2e8 100644 --- a/packages/react/src/examples/NotebookNoContextNoPrimer.tsx +++ b/packages/react/src/examples/NotebookNoPrimer.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; -import JupyterLabCss from '../jupyter/lab/JupyterLabCss'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebarButton } from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterLabCss } from '../theme'; const NOTEBOOK_ID = 'notebook-id'; @@ -18,13 +18,13 @@ const root = createRoot(div); root.render( <> - + diff --git a/packages/react/src/examples/NotebookPath.tsx b/packages/react/src/examples/NotebookPath.tsx index 2d4c008d..b7a8c0a4 100644 --- a/packages/react/src/examples/NotebookPath.tsx +++ b/packages/react/src/examples/NotebookPath.tsx @@ -5,24 +5,24 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import CellSidebarButton from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; const NotebookPath = () => ( - + - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/NotebookPathChange.tsx b/packages/react/src/examples/NotebookPathChange.tsx index d4a36d38..3afe20f4 100755 --- a/packages/react/src/examples/NotebookPathChange.tsx +++ b/packages/react/src/examples/NotebookPathChange.tsx @@ -7,23 +7,22 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button, Text } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const PATH_1 = 'ipywidgets.ipynb'; + const PATH_2 = 'matplotlib.ipynb'; const NotebookPathChange = () => { const [path, setPath] = useState(PATH_1); - const changePath = () => { - path === PATH_1 ? setPath(PATH_2) : setPath(PATH_1); - }; + const changePath = () => { path === PATH_1 ? setPath(PATH_2) : setPath(PATH_1) }; return ( - <> + @@ -37,18 +36,15 @@ const NotebookPathChange = () => { - + ); -}; +} const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); -root.render( - - - -); +root.render(); diff --git a/packages/react/src/examples/NotebookReadonly.tsx b/packages/react/src/examples/NotebookReadonly.tsx new file mode 100644 index 00000000..2e8f8884 --- /dev/null +++ b/packages/react/src/examples/NotebookReadonly.tsx @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { createRoot } from 'react-dom/client'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; + +import nbformat from './notebooks/NotebookExample1.ipynb.json'; + +const NotebookReadonly = () => { + return ( + + + + ); +} + +const div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); diff --git a/packages/react/src/examples/NotebookServiceManager.tsx b/packages/react/src/examples/NotebookServiceManager.tsx index a9c5ae82..6cb6f61f 100644 --- a/packages/react/src/examples/NotebookServiceManager.tsx +++ b/packages/react/src/examples/NotebookServiceManager.tsx @@ -4,52 +4,62 @@ * MIT License */ -import { useState, useEffect } from 'react'; +import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager } from '@jupyterlab/services'; -import Jupyter from '../jupyter/Jupyter'; +import { Button , Box } from '@primer/react'; +import { JupyterReactTheme } from '../theme'; import { createServerSettings } from '../jupyter/JupyterContext'; -import { getJupyterServerUrl, getJupyterServerToken } from '../jupyter/JupyterConfig'; -import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; -import { Kernel } from '../jupyter/kernel/Kernel'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { getJupyterServerUrl, getJupyterServerToken, ServiceManagerLess } from '../jupyter'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; -const KERNEL_NAME = 'python3'; - const NotebookServiceManager = () => { - const [serviceManagerLess, _] = useState(new JupyterServiceManagerLess()); - const [kernel, setKernel] = useState(); - useEffect(() => { - const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); - const serviceManager = new ServiceManager({ serverSettings }); - const kernel = new Kernel({ - kernelManager: serviceManager.kernels, - kernelName: KERNEL_NAME, - kernelSpecName: KERNEL_NAME, - kernelspecsManager: serviceManager.kernelspecs, - sessionManager: serviceManager.sessions, - }); - setKernel(kernel); - }, []) + const [serverless, setServerless] = useState(true); + const [readonly, setReadonly] = useState(true); + const [serviceManager, setServiceManager] = useState(new ServiceManagerLess()); + const changeServiceManager = () => { + if (serverless) { + setServerless(false); + setReadonly(false); + const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); + const serviceManager = new ServiceManager({ serverSettings }); + setServiceManager(serviceManager); + } else { + setServerless(true); + setReadonly(true); + const serviceManager = new ServiceManagerLess(); + setServiceManager(serviceManager); + } + }; return ( - + + + + + + + Token: {serviceManager.serverSettings.token} + + - + ); } diff --git a/packages/react/src/examples/NotebookSkeleton.tsx b/packages/react/src/examples/NotebookSkeleton.tsx index d9671b0f..1a64983e 100644 --- a/packages/react/src/examples/NotebookSkeleton.tsx +++ b/packages/react/src/examples/NotebookSkeleton.tsx @@ -6,10 +6,10 @@ import { createRoot } from 'react-dom/client'; import { ContentLoader } from '@datalayer/primer-addons'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { Jupyter } from '../jupyter/Jupyter'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebarButton } from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; @@ -24,7 +24,7 @@ root.render( id={NOTEBOOK_ID} height="calc(100vh - 2.6rem)" // (Height - Toolbar Height). cellSidebarMargin={60} - CellSidebar={CellSidebar} + CellSidebar={CellSidebarButton} Toolbar={NotebookToolbar} /> diff --git a/packages/react/src/examples/NotebookTheme.tsx b/packages/react/src/examples/NotebookTheme.tsx index 4d3c12b4..b2c799e5 100644 --- a/packages/react/src/examples/NotebookTheme.tsx +++ b/packages/react/src/examples/NotebookTheme.tsx @@ -9,11 +9,11 @@ import { createRoot } from 'react-dom/client'; import { Text, ToggleSwitch, theme as primerTheme } from '@primer/react'; import { Theme } from '@primer/react/lib/ThemeProvider'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; -import { jupyterTheme } from '../themes/primerTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Jupyter } from '../jupyter/Jupyter'; +import { jupyterTheme } from '../theme/JupyterPrimerTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; diff --git a/packages/react/src/examples/NotebookThemeColorMode.tsx b/packages/react/src/examples/NotebookThemeColormode.tsx similarity index 79% rename from packages/react/src/examples/NotebookThemeColorMode.tsx rename to packages/react/src/examples/NotebookThemeColormode.tsx index d1c32e27..21897bf1 100644 --- a/packages/react/src/examples/NotebookThemeColorMode.tsx +++ b/packages/react/src/examples/NotebookThemeColormode.tsx @@ -9,19 +9,19 @@ import { createRoot } from 'react-dom/client'; import { Text, ToggleSwitch, theme as primerTheme, Box } from '@primer/react'; import { Theme } from '@primer/react/lib/ThemeProvider'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; -import Jupyter from '../jupyter/Jupyter'; -import { jupyterTheme } from '../themes/primerTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Colormode } from '../theme/JupyterLabColormode'; +import { Jupyter } from '../jupyter/Jupyter'; +import { jupyterTheme } from '../theme/JupyterPrimerTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; -const NotebookThemeColorMode = () => { +const NotebookThemeColormode = () => { const [theme, setTheme] = useState(jupyterTheme); const [isThemeOn, setIsThemeOn] = useState(false); - const [colorMode, setColorMode] = useState('light'); + const [colormode, setColormode] = useState('light'); const [isOn, setIsOn] = useState(false); useEffect(() => { @@ -40,9 +40,9 @@ const NotebookThemeColorMode = () => { useEffect(() => { if (isOn) { - setColorMode('dark'); + setColormode('dark'); } else { - setColorMode('light'); + setColormode('light'); } }, [isOn]); const onClick = useCallback(() => { @@ -53,7 +53,7 @@ const NotebookThemeColorMode = () => { }, []); return ( <> - + { display="block" mb={1} > - { colorMode === 'light' ? 'Light' : 'Dark' } Mode + { colormode === 'light' ? 'Light' : 'Dark' } Mode ); +root.render(); diff --git a/packages/react/src/examples/NotebookUnmount.tsx b/packages/react/src/examples/NotebookUnmount.tsx index fc7caa1f..a90bd36e 100755 --- a/packages/react/src/examples/NotebookUnmount.tsx +++ b/packages/react/src/examples/NotebookUnmount.tsx @@ -8,11 +8,11 @@ import { useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import Kernel from '../jupyter/kernel/Kernel'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Notebook } from '../components/notebook/Notebook'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/NotebookExample1.ipynb.json'; @@ -76,7 +76,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookUrl.tsx b/packages/react/src/examples/NotebookUrl.tsx deleted file mode 100644 index 2fd8c9fc..00000000 --- a/packages/react/src/examples/NotebookUrl.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2021-2023 Datalayer, Inc. - * - * MIT License - */ - -import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; - -const NOTEBOOK_ID = 'notebook-id'; - -const div = document.createElement('div'); -document.body.appendChild(div); -const root = createRoot(div); - -root.render( - - - -); diff --git a/packages/react/src/examples/ObservableHQ.tsx b/packages/react/src/examples/ObservableHQ.tsx index 12fd6508..6b72f6a5 100644 --- a/packages/react/src/examples/ObservableHQ.tsx +++ b/packages/react/src/examples/ObservableHQ.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { Jupyter } from '../jupyter/Jupyter'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const ObservableHQ = () => ( diff --git a/packages/react/src/examples/OutputIPyWidgets.tsx b/packages/react/src/examples/OutputIPyWidgets.tsx index 30877c18..e923bc07 100755 --- a/packages/react/src/examples/OutputIPyWidgets.tsx +++ b/packages/react/src/examples/OutputIPyWidgets.tsx @@ -6,12 +6,12 @@ import { render } from 'react-dom'; import { Text } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import OutputIPyWidgets from '../components/output/OutputIPyWidgets'; import { view, state } from './notebooks/OutputIPyWidgetsExample'; -const Example = () => { +const OutputIPyWidgetsExample = () => { return ( <> Output IPyWidgets @@ -24,8 +24,8 @@ const div = document.createElement('div'); document.body.appendChild(div); render( - - - , + + + , div ); diff --git a/packages/react/src/examples/OutputWithErrorHandle.tsx b/packages/react/src/examples/OutputWithErrorHandle.tsx index 2b0e1dbb..80100837 100644 --- a/packages/react/src/examples/OutputWithErrorHandle.tsx +++ b/packages/react/src/examples/OutputWithErrorHandle.tsx @@ -4,7 +4,6 @@ * MIT License */ -import { IOutput } from '@jupyterlab/nbformat'; import { Button, Text } from '@primer/react'; import { useState } from 'react'; import { createRoot } from 'react-dom/client'; diff --git a/packages/react/src/examples/Outputs.tsx b/packages/react/src/examples/Outputs.tsx index 954fdbf8..f1e71459 100644 --- a/packages/react/src/examples/Outputs.tsx +++ b/packages/react/src/examples/Outputs.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent, IOutput } from '@jupyterlab/nbformat'; import { Text } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Output from '../components/output/Output'; import { cellSourceAsString } from './../utils/Utils'; @@ -41,7 +41,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/Panel.tsx b/packages/react/src/examples/Panel.tsx index 48cde2a8..dfc482fa 100644 --- a/packages/react/src/examples/Panel.tsx +++ b/packages/react/src/examples/Panel.tsx @@ -5,22 +5,22 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import CellSidebarButton from '../components/notebook/cell/sidebar/CellSidebarButton'; const Panel = () => { return ( - + - + ); }; diff --git a/packages/react/src/examples/Plotly.tsx b/packages/react/src/examples/Plotly.tsx index 8c5e4649..6aa3aaf7 100644 --- a/packages/react/src/examples/Plotly.tsx +++ b/packages/react/src/examples/Plotly.tsx @@ -5,13 +5,13 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Plotly = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/RunningSessions.tsx b/packages/react/src/examples/RunningSessions.tsx index d7e2d6a0..1ed771b7 100644 --- a/packages/react/src/examples/RunningSessions.tsx +++ b/packages/react/src/examples/RunningSessions.tsx @@ -9,9 +9,9 @@ import { createRoot } from 'react-dom/client'; import { Box, Text, ToggleSwitch, ThemeProvider, useTheme } from '@primer/react'; import { ThemeManager } from '@jupyterlab/apputils'; import { RunningSessions } from '@jupyterlab/running'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; +import { Colormode } from '../theme/JupyterLabColormode'; import Lumino from '../components/lumino/Lumino'; -import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; @@ -21,7 +21,7 @@ import * as runningPlugins from '@jupyterlab/running-extension'; const RunningSessionsExample = () => { const [runningSessions, setRunningSessions] = useState(); - const [theme, setTheme] = useState('light'); + const [theme, setTheme] = useState('light'); const [jupyterLabAdapter, setJupyterlabAdapter] = useState(); const { setColorMode } = useTheme(); @@ -55,7 +55,7 @@ const RunningSessionsExample = () => { - + ); diff --git a/packages/react/src/examples/Vega.tsx b/packages/react/src/examples/Vega.tsx index 8b687d79..5c220fc5 100644 --- a/packages/react/src/examples/Vega.tsx +++ b/packages/react/src/examples/Vega.tsx @@ -6,22 +6,22 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as vega3Renderer } from '@jupyterlab/vega3-extension'; -import Jupyter from '../jupyter/Jupyter'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import CellSidebarButton from '../components/notebook/cell/sidebar/CellSidebarButton'; const Vega = () => ( - + - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/Viewer.tsx b/packages/react/src/examples/Viewer.tsx index 0611b6bc..3480ddfb 100644 --- a/packages/react/src/examples/Viewer.tsx +++ b/packages/react/src/examples/Viewer.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { Box, Text } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import Viewer from '../components/viewer/Viewer'; import matplotlib from './notebooks/Matplotlib.ipynb.json'; diff --git a/packages/react/src/examples/sidebars/CellSidebarSource.tsx b/packages/react/src/examples/sidebars/CellSidebarSource.tsx index 694da06b..660fd26a 100644 --- a/packages/react/src/examples/sidebars/CellSidebarSource.tsx +++ b/packages/react/src/examples/sidebars/CellSidebarSource.tsx @@ -14,13 +14,13 @@ import { ChevronDownIcon, SquareIcon, } from '@primer/octicons-react'; -import { CellSidebarProps } from '../../components/notebook/cell/sidebar/CellSidebarWidget'; +import { ICellSidebarProps } from '../../components/notebook/cell/sidebar/CellSidebarWidget'; import CellMetadataEditor from '../../components/notebook/cell/metadata/CellMetadataEditor'; import useNotebookStore from '../../components/notebook/NotebookState'; import { DATALAYER_CELL_HEADER_CLASS } from '../../components/notebook/cell/sidebar/CellSidebarWidget'; -export const CellSidebarSource = (props: CellSidebarProps) => { +export const CellSidebarSource = (props: ICellSidebarProps) => { const { notebookId, cellId, nbgrader } = props; const notebookStore = useNotebookStore(); const [visible, setVisible] = useState(false); diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 9eed535e..32a136e6 100755 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -4,91 +4,8 @@ * MIT License */ -// Jupyter. -export * from './jupyter/Jupyter'; -export * from './jupyter/JupyterContext'; -export * from './jupyter/JupyterConfig'; -// Jupyter Services. -export * from './jupyter/services'; -// Jupyter Kernel. -export * from './jupyter/kernel'; -// Jupyter Lab. -export * from './jupyter/lab/JupyterLabCss'; -export * from './jupyter/lab/JupyterLabColorMode'; -export * from './jupyter/lab/JupyterLabTheme'; -// Jupyter Themes. -export * from './themes/primerTheme'; -// Jupyter Lite -export * from './jupyter/lite/LiteServer'; -// Jupyter IPyWidgets. -export * from './jupyter/ipywidgets/classic/manager'; -export * from './jupyter/ipywidgets/lab/manager'; -// Jupyter State. +export * from './components'; +export * from './jupyter'; export * from './state'; - -// Button Components. -export * from './components/button/Button'; -// Cell Components. -export * from './components/cell/Cell'; -export * from './components/cell/CellAdapter'; -export * from './components/cell/CellState'; -// Commands Components. -export * from './components/commands/Commands'; -// Console Components. -export * from './components/console/Console'; -export * from './components/console/ConsoleState'; -// Dialog Components. -export * from './components/dialog/Dialog'; -// File Browser Components. -export * from './components/filebrowser/FileBrowser'; -// File Manager Component (JupyterLab variant). -export * from './components/filemanager/FileManagerJupyterLab'; -// IPyWidgets Components. -export * from './components/output/ipywidgets/IPyWidgetsAttached'; -export * from './components/output/ipywidgets/IPyWidgetsViewManager'; -// JupyterLab Components. -export * from './components/jupyterlab/JupyterLabApp'; -export * from './components/jupyterlab/JupyterLabAppAdapter'; -export * from './components/jupyterlab/JupyterLabAppPlugins'; -export * from './components/jupyterlab/JupyterLabAppCss'; -// CodeMirrorEditor Components. -export * from './components/codemirror/CodeMirrorEditor'; -// Kernel Components. -export * from './components/kernel'; -// Lumino Components. -export * from './components/lumino/Lumino'; -export * from './components/lumino/LuminoBox'; -export * from './components/lumino/LuminoDetached'; -export * from './components/lumino/LuminoObservable'; -export * from './components/lumino/LuminoRedux'; -export * from './components/lumino/ReactPortalWidget'; -// Notebook Components. -export * from './components/notebook/Notebook'; -export * from './components/notebook/NotebookAdapter'; -export * from './components/notebook/NotebookState'; -export * from './components/notebook/content/JupyterReactContentFactory'; -export * from './components/notebook/cell/metadata/CellMetadataEditor'; -export * from './components/notebook/cell/metadata/NbGraderCells'; -export * from './components/notebook/cell/prompt/CountdownInputPrompt'; -export * from './components/notebook/cell/sidebar/CellSidebarWidget'; -export * from './components/notebook/cell/sidebar/CellSidebar'; -export * from './components/notebook/cell/sidebar/CellSidebarRun'; -// Output Components. -export * from './components/output/Output'; -export * from './components/output/OutputAdapter'; -export * from './components/output/OutputState'; -export * from './components/output/OutputIPyWidgets'; -// Settings Components. -export * from './components/settings/Settings'; -// Terminal Components. -export * from './components/terminal/Terminal'; -export * from './components/terminal/TerminalState'; -// TextInput Components. -export * from './components/textinput/TextInput'; -// Viewer Components. -export * from './components/viewer/Viewer'; -export * from './components/viewer/input/InputViewer'; -export * from './components/viewer/output/OutputViewer'; - -// Utils +export * from './theme'; export * from './utils'; diff --git a/packages/react/src/jupyter/Jupyter.tsx b/packages/react/src/jupyter/Jupyter.tsx index 3362022c..bcc22865 100644 --- a/packages/react/src/jupyter/Jupyter.tsx +++ b/packages/react/src/jupyter/Jupyter.tsx @@ -10,8 +10,7 @@ import { useMemo } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { loadJupyterConfig } from './JupyterConfig'; import { JupyterContextProps, JupyterContextProvider } from './JupyterContext'; -import { ColorMode } from './lab/JupyterLabColorMode'; -import JupyterLabCss from './lab/JupyterLabCss'; +import { Colormode, JupyterLabCss } from '../theme'; /** * Definition of the properties that can be passed @@ -21,7 +20,7 @@ export type JupyterProps = Omit< JupyterContextProps, 'variant' > & { - colorMode?: ColorMode; + colormode?: Colormode; disableCssLoading?: boolean; theme?: Theme; terminals?: boolean; @@ -50,7 +49,7 @@ export const Jupyter = (props: JupyterProps) => { const { children, collaborative, - colorMode = 'light', + colormode = 'light', defaultKernelName, disableCssLoading = false, initCode = '', @@ -74,30 +73,22 @@ export const Jupyter = (props: JupyterProps) => { lite, terminals, }); - }, [ - collaborative, - jupyterServerUrl, - jupyterServerToken, - lite, - terminals, - ]); + }, [props]); return ( { - console.log('Error Boundary reset has been invoked...'); - }} + onReset={() => {console.log('Error Boundary reset has been invoked...');}} > {!config.insideJupyterLab && !disableCssLoading && ( - + )} [] }>; +import { Lite } from './lite'; +import { Kernel } from './kernel'; /** * The type for Jupyter props. @@ -143,12 +139,16 @@ export type JupyterContextType = { * `lite: import('@jupyterlite/javascript-kernel-extension')` => Load dynamically */ lite?: Lite; + /* + * Create a serveless Jupyter. + */ + serverless: boolean /** - * Jupyter service manager + * Jupyter service manager. */ serviceManager?: ServiceManager.IManager; /** - * Jupyter Server settings + * Jupyter Server settings. * * This is useless if running an in-browser kernel via {@link lite}. */ @@ -178,30 +178,33 @@ export const JupyterContextConsumer = JupyterContext.Consumer; const JupyterProvider = JupyterContext.Provider; /* - * + * User Jupyter hook. */ export const useJupyter = (props?: JupyterPropsType): JupyterContextType => { const context = useContext(JupyterContext); if (context) { - // We are with in a Jupyter context, returning fast the context. + // We are within a React Context, just return the JupyterContext. + // The provided props are irrelevant in this case. return context; } - // We are not within a Jupyter context, so create it from the store. + // We are not within a React Context, so create a JupyterContext + // from the store based on the provided props. const { + jupyterConfig, kernel, kernelIsLoading, serviceManager, - jupyterConfig, } = useJupyterReactStoreFromProps(props ?? {}); const storeContext: JupyterContextType = { - collaborative: false, + collaborative: props?.collaborative, defaultKernel: kernel, defaultKernelIsLoading: kernelIsLoading, jupyterServerUrl: jupyterConfig!.jupyterServerUrl, kernel, kernelIsLoading, kernelManager: serviceManager?.kernels, - lite: false, + lite: props?.lite, + serverless: props?.serverless ?? false, serverSettings: serviceManager?.serverSettings, serviceManager, } @@ -264,14 +267,14 @@ export const JupyterContextProvider: React.FC = (props) => collaborative, defaultKernel: kernel, defaultKernelIsLoading: kernelIsLoading, - // FIXME we should not expose sub attributes to promote single source of truth - // (like URLs come from serverSettings) + // FIXME we should not expose sub attributes to promote single source of truth (like URLs coming from serverSettings). jupyterServerUrl, kernel, kernelIsLoading, kernelManager: serviceManager?.kernels, lite, serverSettings, + serverless: props.serverless ?? false, serviceManager, }} > diff --git a/packages/react/src/jupyter/JupyterDefaults.tsx b/packages/react/src/jupyter/JupyterDefaults.tsx new file mode 100644 index 00000000..83fac02e --- /dev/null +++ b/packages/react/src/jupyter/JupyterDefaults.tsx @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export const DEFAULT_JUPYTER_SERVER_URL = 'https://oss.datalayer.run/api/jupyter-server'; + +export const DEFAULT_JUPYTER_SERVER_TOKEN = '60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6'; + +export const DEFAULT_KERNEL_NAME = 'python'; diff --git a/packages/react/src/jupyter/index.ts b/packages/react/src/jupyter/index.ts new file mode 100644 index 00000000..9ee04f36 --- /dev/null +++ b/packages/react/src/jupyter/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Jupyter'; +export * from './JupyterAuthError'; +export * from './JupyterConfig'; +export * from './JupyterContext'; +export * from './JupyterDefaults'; +export * from './JupyterHandlers'; +export * from './Jupyter'; +export * from './ipywidgets'; +export * from './kernel'; +export * from './lab'; +export * from './lite'; +export * from './renderers'; +export * from './services'; diff --git a/packages/react/src/jupyter/ipywidgets/classic/index.ts b/packages/react/src/jupyter/ipywidgets/classic/index.ts new file mode 100644 index 00000000..bd4004b3 --- /dev/null +++ b/packages/react/src/jupyter/ipywidgets/classic/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './manager'; +export * from './renderer'; diff --git a/packages/react/src/jupyter/ipywidgets/index.ts b/packages/react/src/jupyter/ipywidgets/index.ts new file mode 100644 index 00000000..186142f3 --- /dev/null +++ b/packages/react/src/jupyter/ipywidgets/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './libembed-amd'; +export * from './mimetypes'; +export * from './semvercache'; +export * from './classic'; +export * from './lab'; diff --git a/packages/react/src/jupyter/ipywidgets/lab/index.ts b/packages/react/src/jupyter/ipywidgets/lab/index.ts new file mode 100644 index 00000000..bd4004b3 --- /dev/null +++ b/packages/react/src/jupyter/ipywidgets/lab/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './manager'; +export * from './renderer'; diff --git a/packages/react/src/jupyter/ipywidgets/lab/renderer.ts b/packages/react/src/jupyter/ipywidgets/lab/renderer.ts index 921cff11..89529cb0 100644 --- a/packages/react/src/jupyter/ipywidgets/lab/renderer.ts +++ b/packages/react/src/jupyter/ipywidgets/lab/renderer.ts @@ -14,7 +14,7 @@ import { DOMWidgetModel } from '@jupyter-widgets/base'; /** * A renderer for widgets. */ -export class WidgetRenderer +export class WidgetLabRenderer extends Panel implements IRenderMime.IRenderer, IDisposable { diff --git a/packages/react/src/jupyter/ipywidgets/libembed-amd.ts b/packages/react/src/jupyter/ipywidgets/libembed-amd.ts index 433c938b..86a92fb2 100644 --- a/packages/react/src/jupyter/ipywidgets/libembed-amd.ts +++ b/packages/react/src/jupyter/ipywidgets/libembed-amd.ts @@ -10,6 +10,7 @@ import * as libembed from '@jupyter-widgets/html-manager/lib/libembed'; let cdn = 'https://cdn.jsdelivr.net/npm/'; + let onlyCDN = true; // find the data-cdn for any script tag, assuming it is only used for embed-amd.js diff --git a/packages/react/src/jupyter/kernel/index.ts b/packages/react/src/jupyter/kernel/index.ts index 10063969..52daac75 100644 --- a/packages/react/src/jupyter/kernel/index.ts +++ b/packages/react/src/jupyter/kernel/index.ts @@ -6,3 +6,4 @@ export * from './Kernel'; export * from './KernelExecutor'; +export * from './KernelState'; diff --git a/packages/react/src/jupyter/lab/JupyterLabTheme.tsx b/packages/react/src/jupyter/lab/JupyterLabTheme.tsx deleted file mode 100644 index eab3e4aa..00000000 --- a/packages/react/src/jupyter/lab/JupyterLabTheme.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2021-2023 Datalayer, Inc. - * - * MIT License - */ - -import { BaseStyles, ThemeProvider, theme } from '@primer/react'; -import JupyterLabCss from './JupyterLabCss'; -import { ColorMode } from './JupyterLabColorMode'; - -type IJupyterLabThemeProps = { - colorMode: ColorMode; -} - -export const JupyterLabTheme = (props: React.PropsWithChildren) => { - const { children, colorMode } = props; - return ( - <> - - - - {children} - - - - ) -} - -JupyterLabTheme.defaultProps = { - colorMode: 'light', -} as IJupyterLabThemeProps; - -export default JupyterLabTheme; diff --git a/packages/react/src/jupyter/lab/index.ts b/packages/react/src/jupyter/lab/index.ts index d850cfa1..f7ac5730 100644 --- a/packages/react/src/jupyter/lab/index.ts +++ b/packages/react/src/jupyter/lab/index.ts @@ -4,114 +4,4 @@ * MIT License */ -import { - JupyterFrontEnd, - JupyterFrontEndPlugin, - ILayoutRestorer, -} from '@jupyterlab/application'; -import { - MainAreaWidget, - ICommandPalette, - WidgetTracker, -} from '@jupyterlab/apputils'; -import { ILauncher } from '@jupyterlab/launcher'; -import { ISettingRegistry } from '@jupyterlab/settingregistry'; -import { ServerConnection } from '@jupyterlab/services'; -import icon from '@datalayer/icons-react/data2/AtomSymbolIconJupyterLab'; -import { requestAPI } from './../JupyterHandlers'; -import { JupyterReactWidget } from './widget'; -import notebookContentFactoryPlugin from './notebook/content/plugin'; - -import '../../../style/index.css'; - -/** - * The command IDs used by the plugin. - */ -namespace CommandIDs { - export const create = 'create-jupyter-react-widget'; -} - -/** - * Initialization data for the @datalayer/jupyter-react extension. - */ -const jupyterReactPlugin: JupyterFrontEndPlugin = { - id: '@datalayer/jupyter-react:plugin', - autoStart: true, - requires: [ICommandPalette], - optional: [ISettingRegistry, ILauncher, ILayoutRestorer], - activate: ( - app: JupyterFrontEnd, - palette: ICommandPalette, - settingRegistry?: ISettingRegistry, - launcher?: ILauncher, - restorer?: ILayoutRestorer - ) => { - const { commands } = app; - const command = CommandIDs.create; - const tracker = new WidgetTracker>({ - namespace: 'jupyter-react', - }); - if (restorer) { - void restorer.restore(tracker, { - command, - name: () => 'jupyter-react', - }); - } - commands.addCommand(command, { - caption: 'Show Jupyter React', - label: 'Jupyter React', - icon, - execute: () => { - const content = new JupyterReactWidget(app); - const widget = new MainAreaWidget({ content }); - widget.title.label = 'Jupyter React'; - widget.title.icon = icon; - app.shell.add(widget, 'main'); - tracker.add(widget); - }, - }); - const category = 'Datalayer'; - palette.addItem({ command, category, args: { origin: 'from palette' } }); - const settingsUpdated = (settings: ISettingRegistry.ISettings) => { - const showInLauncher = settings.get('showInLauncher') - .composite as boolean; - if (launcher && showInLauncher) { - launcher.add({ - command, - category, - rank: 2.4, - }); - } - }; - if (settingRegistry) { - settingRegistry - .load(jupyterReactPlugin.id) - .then(settings => { - console.log( - '@datalayer/jupyter-react settings loaded:', - settings.composite - ); - settingsUpdated(settings); - settings.changed.connect(settingsUpdated); - }) - .catch(reason => { - console.error( - 'Failed to load settings for @datalayer/jupyter-react.', - reason - ); - }); - } - requestAPI(ServerConnection.makeSettings(), 'jupyter_react', 'config') - .then(data => { - console.log(data); - }) - .catch(reason => { - console.error( - `The Jupyter Server jupyter_react extension extension.\n${reason}` - ); - }); - console.log('JupyterLab plugin @datalayer/jupyter-react is activated.'); - }, -}; - -export default [jupyterReactPlugin, notebookContentFactoryPlugin]; +export * from './widget'; diff --git a/packages/react/src/jupyter/lab/notebook/content/index.ts b/packages/react/src/jupyter/lab/notebook/content/index.ts new file mode 100644 index 00000000..9ab0e630 --- /dev/null +++ b/packages/react/src/jupyter/lab/notebook/content/index.ts @@ -0,0 +1,5 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ diff --git a/packages/react/src/jupyter/lab/plugin.ts b/packages/react/src/jupyter/lab/plugin.ts new file mode 100644 index 00000000..731d3526 --- /dev/null +++ b/packages/react/src/jupyter/lab/plugin.ts @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { + JupyterFrontEnd, + JupyterFrontEndPlugin, + ILayoutRestorer, +} from '@jupyterlab/application'; +import { + MainAreaWidget, + ICommandPalette, + WidgetTracker, +} from '@jupyterlab/apputils'; +import { ILauncher } from '@jupyterlab/launcher'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; +import { ServerConnection } from '@jupyterlab/services'; +import icon from '@datalayer/icons-react/data2/AtomSymbolIconJupyterLab'; +import { requestAPI } from './../JupyterHandlers'; +import { JupyterReactWidget } from './widget'; +import notebookContentFactoryPlugin from './notebook/content/plugin'; + +import '../../../style/index.css'; + +/** + * The command IDs used by the plugin. + */ +namespace CommandIDs { + export const create = 'create-jupyter-react-widget'; +} + +/** + * Initialization data for the @datalayer/jupyter-react extension. + */ +const jupyterReactPlugin: JupyterFrontEndPlugin = { + id: '@datalayer/jupyter-react:plugin', + autoStart: true, + requires: [ICommandPalette], + optional: [ISettingRegistry, ILauncher, ILayoutRestorer], + activate: ( + app: JupyterFrontEnd, + palette: ICommandPalette, + settingRegistry?: ISettingRegistry, + launcher?: ILauncher, + restorer?: ILayoutRestorer + ) => { + const { commands } = app; + const command = CommandIDs.create; + const tracker = new WidgetTracker>({ + namespace: 'jupyter-react', + }); + if (restorer) { + void restorer.restore(tracker, { + command, + name: () => 'jupyter-react', + }); + } + commands.addCommand(command, { + caption: 'Show Jupyter React', + label: 'Jupyter React', + icon, + execute: () => { + const content = new JupyterReactWidget(app); + const widget = new MainAreaWidget({ content }); + widget.title.label = 'Jupyter React'; + widget.title.icon = icon; + app.shell.add(widget, 'main'); + tracker.add(widget); + }, + }); + const category = 'Datalayer'; + palette.addItem({ command, category, args: { origin: 'from palette' } }); + const settingsUpdated = (settings: ISettingRegistry.ISettings) => { + const showInLauncher = settings.get('showInLauncher') + .composite as boolean; + if (launcher && showInLauncher) { + launcher.add({ + command, + category, + rank: 2.4, + }); + } + }; + if (settingRegistry) { + settingRegistry + .load(jupyterReactPlugin.id) + .then(settings => { + console.log( + '@datalayer/jupyter-react settings loaded:', + settings.composite + ); + settingsUpdated(settings); + settings.changed.connect(settingsUpdated); + }) + .catch(reason => { + console.error( + 'Failed to load settings for @datalayer/jupyter-react.', + reason + ); + }); + } + requestAPI(ServerConnection.makeSettings(), 'jupyter_react', 'config') + .then(data => { + console.log(data); + }) + .catch(reason => { + console.error( + `The Jupyter Server jupyter_react extension extension.\n${reason}` + ); + }); + console.log('JupyterLab plugin @datalayer/jupyter-react is activated.'); + }, +}; + +export default [ + jupyterReactPlugin, + notebookContentFactoryPlugin +]; diff --git a/packages/react/src/jupyter/lite/Lite.ts b/packages/react/src/jupyter/lite/Lite.ts new file mode 100644 index 00000000..e1469f74 --- /dev/null +++ b/packages/react/src/jupyter/lite/Lite.ts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import type { JupyterLiteServerPlugin } from '@jupyterlite/server'; + +export type Lite = + | boolean + | Promise<{ default: JupyterLiteServerPlugin[] }>; diff --git a/packages/react/src/jupyter/lite/index.ts b/packages/react/src/jupyter/lite/index.ts new file mode 100644 index 00000000..7a23b82a --- /dev/null +++ b/packages/react/src/jupyter/lite/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Lite'; +export * from './LiteServer'; diff --git a/packages/react/src/jupyter/renderers/index.ts b/packages/react/src/jupyter/renderers/index.ts index 9ab0e630..fa93ff60 100644 --- a/packages/react/src/jupyter/renderers/index.ts +++ b/packages/react/src/jupyter/renderers/index.ts @@ -3,3 +3,5 @@ * * MIT License */ + +export * from './plotly'; \ No newline at end of file diff --git a/packages/react/src/jupyter/renderers/plotly/index.ts b/packages/react/src/jupyter/renderers/plotly/index.ts new file mode 100644 index 00000000..1474e708 --- /dev/null +++ b/packages/react/src/jupyter/renderers/plotly/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './PlotlyRenderer'; \ No newline at end of file diff --git a/packages/react/src/jupyter/services/JupyterServiceManagerLess.ts b/packages/react/src/jupyter/services/ServiceManagerLess.ts similarity index 92% rename from packages/react/src/jupyter/services/JupyterServiceManagerLess.ts rename to packages/react/src/jupyter/services/ServiceManagerLess.ts index b34c5ec3..119c014f 100644 --- a/packages/react/src/jupyter/services/JupyterServiceManagerLess.ts +++ b/packages/react/src/jupyter/services/ServiceManagerLess.ts @@ -386,7 +386,7 @@ export class NbConvertManagerLess { } } -export class JupyterServiceManagerLess implements ServiceManager.IManager { +export class ServiceManagerLess implements ServiceManager.IManager { isReady: boolean = true; ready: Promise = Promise.resolve(void 0); isDisposed: boolean = false; @@ -403,19 +403,23 @@ export class JupyterServiceManagerLess implements ServiceManager.IManager { user: User.IManager; workspaces: Workspace.IManager; nbconvert: NbConvert.IManager; - constructor(serverSettings: ServerConnection.ISettings = ServerConnection.makeSettings()) { - this.serverSettings = serverSettings; - this.builder = new BuilderManagerLess(serverSettings) as Builder.IManager; - this.contents = new ContentsManagerLess(serverSettings); - this.events = new EventsManagerLess(serverSettings); - this.kernels = new KernelsManagerLess(serverSettings); - this.kernelspecs = new KernelspecManagerLess(serverSettings); - this.nbconvert = new NbConvertManagerLess(serverSettings) as unknown as NbConvert.IManager; - this.sessions = new SessionManagerLess(serverSettings); - this.settings = new SettingManagerLess(serverSettings) - this.terminals = new TerminalManagerLess(serverSettings); - this.user = new UserManagerLess(serverSettings) - this.workspaces = new WorkspaceManagerLess(serverSettings); + constructor(serverSettings?: ServerConnection.ISettings) { + this.serverSettings = serverSettings ?? ServerConnection.makeSettings({ +// baseUrl: 'https://', +// wsUrl: 'wss://', +// token: 'less-token', + }); + this.builder = new BuilderManagerLess(this.serverSettings) as Builder.IManager; + this.contents = new ContentsManagerLess(this.serverSettings); + this.events = new EventsManagerLess(this.serverSettings); + this.kernels = new KernelsManagerLess(this.serverSettings); + this.kernelspecs = new KernelspecManagerLess(this.serverSettings); + this.nbconvert = new NbConvertManagerLess(this.serverSettings) as unknown as NbConvert.IManager; + this.sessions = new SessionManagerLess(this.serverSettings); + this.settings = new SettingManagerLess(this.serverSettings) + this.terminals = new TerminalManagerLess(this.serverSettings); + this.user = new UserManagerLess(this.serverSettings) + this.workspaces = new WorkspaceManagerLess(this.serverSettings); /* const serviceManager = new ServiceManager({ serverSettings, @@ -437,4 +441,4 @@ export class JupyterServiceManagerLess implements ServiceManager.IManager { } } -export default JupyterServiceManagerLess; +export default ServiceManagerLess; diff --git a/packages/react/src/jupyter/services/ServiceManagerLite.ts b/packages/react/src/jupyter/services/ServiceManagerLite.ts new file mode 100644 index 00000000..39d26a42 --- /dev/null +++ b/packages/react/src/jupyter/services/ServiceManagerLite.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ +import { ServiceManager } from '@jupyterlab/services'; +import { Lite } from '../lite'; +import { createLiteServer } from '../lite/LiteServer'; + +export const createServiceManagerLite = (lite: Lite = true): Promise => { + return createLiteServer().then(async liteServer => { + // Load the browser kernel. + const mod = + typeof lite === 'boolean' + ? await import('@jupyterlite/pyodide-kernel-extension') + : await lite; + // Load the module manually to get the list of plugin IDs + let data = mod.default; + // Handle commonjs exports. + if (!Object.prototype.hasOwnProperty.call(mod, '__esModule')) { + data = mod as any; + } + if (!Array.isArray(data)) { + data = [data]; + } + const pluginIDs = data.map(item => { + try { + liteServer.registerPlugin(item); + return item.id; + } catch (error) { + console.error(error); + return null; + } + }); + // Activate the loaded plugins. + await Promise.all( + pluginIDs.filter(id => id).map(id => liteServer.activatePlugin(id!)) + ); + return liteServer.serviceManager; + }); +} diff --git a/packages/react/src/jupyter/services/index.ts b/packages/react/src/jupyter/services/index.ts index 2ce4c8b3..51692e76 100644 --- a/packages/react/src/jupyter/services/index.ts +++ b/packages/react/src/jupyter/services/index.ts @@ -4,5 +4,6 @@ * MIT License */ -export * from './JupyterServiceManagerLess'; export * from './JupyterServices'; +export * from './ServiceManagerLite'; +export * from './ServiceManagerLess'; diff --git a/packages/react/src/state/JupyerReactState.ts b/packages/react/src/state/JupyterReactState.ts similarity index 77% rename from packages/react/src/state/JupyerReactState.ts rename to packages/react/src/state/JupyterReactState.ts index cb1239c2..cd8ba753 100644 --- a/packages/react/src/state/JupyerReactState.ts +++ b/packages/react/src/state/JupyterReactState.ts @@ -15,11 +15,10 @@ import { consoleStore, ConsoleState } from '../components/console/ConsoleState'; import { notebookStore, NotebookState } from '../components/notebook/NotebookState'; import { outputsStore, OutputState } from '../components/output/OutputState'; import { terminalStore, TerminalState } from '../components/terminal/TerminalState'; -import { createLiteServer } from '../jupyter/lite/LiteServer'; -import { getJupyterServerUrl } from '../jupyter/JupyterConfig'; -import { ensureJupyterAuth, createServerSettings, JupyterPropsType } from '../jupyter/JupyterContext'; -import { JupyterServiceManagerLess } from '../jupyter/services'; -import Kernel from '../jupyter/kernel/Kernel'; +import { getJupyterServerUrl, createServiceManagerLite, ensureJupyterAuth, createServerSettings, JupyterPropsType } from '../jupyter'; +import { DEFAULT_KERNEL_NAME } from '../jupyter'; +import { ServiceManagerLess } from '../jupyter/services'; +import { Kernel } from '../jupyter/kernel/Kernel'; export type JupyterReactState = { cellsStore: CellsState; @@ -34,6 +33,7 @@ export type JupyterReactState = { terminalStore: TerminalState; version: string; setDatalayerConfig: (configuration?: IJupyterReactConfig) => void; + setJupyterConfig: (configuration?: IJupyterConfig) => void; setServiceManager: (serviceManager?: ServiceManager.IManager) => void; setVersion: (version: string) => void; }; @@ -62,8 +62,11 @@ export const jupyterReactStore = createStore((set, get) => ({ notebookStore: notebookStore.getState(), outputStore: outputsStore.getState(), terminalStore: terminalStore.getState(), - setDatalayerConfig: (configuration?: IJupyterReactConfig) => { - set(state => ({ datalayerConfig: configuration })); + setDatalayerConfig: (datalayerConfig?: IJupyterReactConfig) => { + set(state => ({ datalayerConfig })); + }, + setJupyterConfig: (jupyterConfig?: IJupyterConfig) => { + set(state => ({ jupyterConfig })); }, setServiceManager: (serviceManager?: ServiceManager.IManager) => { set(state => ({ serviceManager })); @@ -77,18 +80,20 @@ export const jupyterReactStore = createStore((set, get) => ({ // TODO Reuse code portions from JupyterContext export function useJupyterReactStore(): JupyterReactState; + export function useJupyterReactStore(selector: (state: JupyterReactState) => T): T; export function useJupyterReactStore(selector?: (state: JupyterReactState) => T) { return useStore(jupyterReactStore, selector!); } + export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterReactState; export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterReactState { const { collaborative = false, - defaultKernelName = 'python', + defaultKernelName = DEFAULT_KERNEL_NAME, initCode = '', - jupyterServerToken = '60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6', - jupyterServerUrl = 'https://oss.datalayer.run/api/jupyter-server', + jupyterServerToken = props.serviceManager?.serverSettings.token ?? '', + jupyterServerUrl = props.serviceManager?.serverSettings.baseUrl ?? '', lite = false, serverless, serviceManager: propsServiceManager, @@ -98,7 +103,7 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR useRunningKernelIndex = -1, } = props; - const config = useMemo(() => { + const jupyterConfig = useMemo(() => { const config = loadJupyterConfig({ lite, jupyterServerUrl, @@ -106,7 +111,7 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR collaborative, terminals, }); - jupyterReactStore.getState().jupyterConfig = config; + jupyterReactStore.getState().setJupyterConfig(config); return config; }, []); @@ -116,63 +121,37 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR useEffect(() => { if (propsServiceManager) { + console.log('Setting Service Manager from props', propsServiceManager); setServiceManager(propsServiceManager); jupyterReactStore.getState().setServiceManager(propsServiceManager); } }, [propsServiceManager]); - // Setup a service manager if needed. + // Setup a Service Manager if needed. useEffect(() => { if (serverless) { - const serviceManager = new JupyterServiceManagerLess(); + const serviceManager = new ServiceManagerLess(); setServiceManager(serviceManager); jupyterReactStore.getState().setServiceManager(serviceManager); return; } if (!serviceManager) { if (lite) { - createLiteServer().then(async liteServer => { - // Load the browser kernel - const mod = - typeof lite === 'boolean' - ? await import('@jupyterlite/pyodide-kernel-extension') - : await lite; - // Load the module manually to get the list of plugin IDs - let data = mod.default; - // Handle commonjs exports. - if (!Object.prototype.hasOwnProperty.call(mod, '__esModule')) { - data = mod as any; - } - if (!Array.isArray(data)) { - data = [data]; - } - const pluginIDs = data.map(item => { - try { - liteServer.registerPlugin(item); - return item.id; - } catch (error) { - console.error(error); - return null; - } - }); - // Activate the loaded plugins - await Promise.all( - pluginIDs.filter(id => id).map(id => liteServer.activatePlugin(id!)) - ); - setServiceManager(liteServer.serviceManager); - jupyterReactStore.getState().setServiceManager(liteServer.serviceManager); + createServiceManagerLite(lite).then(serviceManager => { + setServiceManager(serviceManager); + jupyterReactStore.getState().setServiceManager(serviceManager); }); return; } const serverSettings = createServerSettings( - config.jupyterServerUrl, - config.jupyterServerToken, + jupyterConfig.jupyterServerUrl, + jupyterConfig.jupyterServerToken, ); ensureJupyterAuth(serverSettings).then(isAuth => { if (!isAuth) { const loginUrl = getJupyterServerUrl() + '/login?next=' + window.location; console.warn('You need to authenticate on the Jupyter Server URL', loginUrl); -// window.location.replace(loginUrl); + // window.location.replace(loginUrl); } if (useRunningKernelId && useRunningKernelIndex > -1) { throw new Error('You can not ask for useRunningKernelId and useRunningKernelIndex at the same time.'); @@ -186,11 +165,11 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR const serviceManager = new ServiceManager({ serverSettings }); setServiceManager(serviceManager); jupyterReactStore.getState().setServiceManager(serviceManager); - }); + }); } }, [lite, serverless, jupyterServerUrl]); - // Setup a kernel if needed. + // Setup a Kernel if needed. useEffect(() => { serviceManager?.kernels.ready.then(async () => { const kernelManager = serviceManager.kernels; diff --git a/packages/react/src/state/index.ts b/packages/react/src/state/index.ts index 8ed4339b..2d4d0f31 100644 --- a/packages/react/src/state/index.ts +++ b/packages/react/src/state/index.ts @@ -5,4 +5,4 @@ */ export * from "./IJupyterReactConfig"; -export * from "./JupyerReactState"; +export * from "./JupyterReactState"; diff --git a/packages/react/src/theme/JupyterLabColormode.tsx b/packages/react/src/theme/JupyterLabColormode.tsx new file mode 100644 index 00000000..0c4fc625 --- /dev/null +++ b/packages/react/src/theme/JupyterLabColormode.tsx @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export type Colormode = 'light' | 'dark'; diff --git a/packages/react/src/jupyter/lab/JupyterLabCss.tsx b/packages/react/src/theme/JupyterLabCss.tsx similarity index 91% rename from packages/react/src/jupyter/lab/JupyterLabCss.tsx rename to packages/react/src/theme/JupyterLabCss.tsx index 12f75ac6..1a48dbab 100644 --- a/packages/react/src/jupyter/lab/JupyterLabCss.tsx +++ b/packages/react/src/theme/JupyterLabCss.tsx @@ -5,12 +5,12 @@ */ import { useEffect } from 'react'; -import { ColorMode } from './JupyterLabColorMode'; +import { Colormode } from './JupyterLabColormode'; const DATASET_LAB_THEME = 'data-lab-theme'; type Props = { - colorMode: ColorMode; + colormode: Colormode; }; /** @@ -22,7 +22,7 @@ let isLoaded = false; * Components loading the JupyterLab CSS stylesheets. */ export const JupyterLabCss = (props: Props) => { - const { colorMode } = props; + const { colormode } = props; useEffect(() => { if (isLoaded) { // no-op @@ -53,7 +53,7 @@ export const JupyterLabCss = (props: Props) => { document.body.querySelector(`style[${DATASET_LAB_THEME}]`)?.remove(); let theme; - switch (colorMode) { + switch (colormode) { case 'light': { theme = import('!!raw-loader!@jupyterlab/theme-light-extension/style/variables.css'); break; @@ -73,18 +73,18 @@ export const JupyterLabCss = (props: Props) => { if (module.default) { document.body.insertAdjacentHTML( 'afterbegin', - `` ); } }); - }, [colorMode]); + }, [colormode]); return
; }; JupyterLabCss.defaultProps = { - colorMode: 'light', + colormode: 'light', }; export default JupyterLabCss; diff --git a/packages/react/src/jupyter/lab/JupyterLabCssImports.ts b/packages/react/src/theme/JupyterLabCssImports.ts similarity index 100% rename from packages/react/src/jupyter/lab/JupyterLabCssImports.ts rename to packages/react/src/theme/JupyterLabCssImports.ts diff --git a/packages/react/src/themes/primerTheme.ts b/packages/react/src/theme/JupyterPrimerTheme.ts similarity index 100% rename from packages/react/src/themes/primerTheme.ts rename to packages/react/src/theme/JupyterPrimerTheme.ts diff --git a/packages/react/src/theme/JupyterReactTheme.tsx b/packages/react/src/theme/JupyterReactTheme.tsx new file mode 100644 index 00000000..b3c4b169 --- /dev/null +++ b/packages/react/src/theme/JupyterReactTheme.tsx @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { BaseStyles, ThemeProvider, theme } from '@primer/react'; +import { Colormode, JupyterLabCss } from './../theme'; + +type IJupyterLabThemeProps = { + colormode: Colormode; +} + +export const JupyterReactTheme = (props: React.PropsWithChildren) => { + const { children, colormode } = props; + return ( + <> + + + + {children} + + + + ) +} + +JupyterReactTheme.defaultProps = { + colormode: 'light', +} as IJupyterLabThemeProps; + +export default JupyterReactTheme; diff --git a/packages/react/src/theme/index.ts b/packages/react/src/theme/index.ts new file mode 100644 index 00000000..e00ca9ea --- /dev/null +++ b/packages/react/src/theme/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './JupyterLabColormode'; +export * from './JupyterLabCss'; +// export * from './JupyterLabCssImports'; // Leave this commented otherwise webpack may break in consumers. +export * from './JupyterPrimerTheme'; +export * from './JupyterReactTheme'; diff --git a/packages/react/webpack.config.js b/packages/react/webpack.config.js index 1db4a437..4fc5a660 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -18,40 +18,45 @@ function shim(regExp) { const ENTRY = // './src/app/App'; + // './src/examples/Bokeh'; // './src/examples/Cell'; + // './src/examples/CellLite'; // './src/examples/Cells'; // './src/examples/CellsExecute'; - // './src/examples/CellLite'; // './src/examples/Console'; // './src/examples/ConsoleLite'; // './src/examples/Deno'; // './src/examples/IPyLeaflet'; // './src/examples/IPyReact'; // './src/examples/IPyWidgets'; - // './src/examples/IPyWidgetsWithState'; + // './src/examples/IPyWidgetsState'; + // './src/examples/JupyterContext'; // './src/examples/JupyterLabApp'; // './src/examples/JupyterLabAppHeadless'; // './src/examples/JupyterLabAppHeadlessServerless'; // './src/examples/JupyterLabAppServerless'; // './src/examples/JupyterLabAppServiceManager'; - // './src/examples/Kernels'; // './src/examples/KernelExecute'; // './src/examples/KernelExecutor'; + // './src/examples/Kernels'; // './src/examples/Lumino'; // './src/examples/Matplotlib'; - './src/examples/Notebook'; - // './src/examples/NotebookUrl'; - // './src/examples/NotebookColorMode'; + // './src/examples/Notebook'; + // './src/examples/NotebookColormode'; // './src/examples/NotebookKernelChange'; // './src/examples/NotebookLite'; - // './src/examples/NotebookNbFormat'; - // './src/examples/NotebookNbFormatChange'; + './src/examples/NotebookMutations'; + // './src/examples/NotebookNbformat'; + // './src/examples/NotebookNbformatChange'; // './src/examples/NotebookNoContext'; - // './src/examples/NotebookNoContextNoPrimer'; + // './src/examples/NotebookNoPrimer'; + // './src/examples/NotebookPathChange'; + // './src/examples/NotebookReadonly'; // './src/examples/NotebookServiceManager'; // './src/examples/NotebookSkeleton'; // './src/examples/NotebookTheme'; - // './src/examples/NotebookThemeColorMode'; + // './src/examples/NotebookThemeColormode'; + // './src/examples/NotebookURL'; // './src/examples/ObservableHQ'; // './src/examples/Output'; // './src/examples/OutputWithErrorHandle';