From fdb1ac7a007dcba3b1933184b80e8221b73f665d Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Wed, 11 Sep 2024 10:39:23 +0200 Subject: [PATCH 01/14] fix: build --- packages/react/package.json | 2 +- packages/react/src/examples/OutputWithErrorHandle.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react/package.json b/packages/react/package.json index d5e8ea7f..230aa9ea 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", 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'; From 293f3c96c888a1aaf74d55af3d2c82716ddf5e31 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Wed, 11 Sep 2024 15:31:00 +0200 Subject: [PATCH 02/14] chore: add index.ts --- packages/react/src/components/button/index.ts | 7 ++ 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 +++++ .../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 +++ .../src/components/lumino/LuminoRedux.ts | 15 ---- packages/react/src/components/lumino/index.ts | 11 +++ .../src/components/notebook/Notebook.tsx | 54 ++++++----- .../components/notebook/NotebookAdapter.ts | 30 +++---- .../src/components/notebook/cell/index.ts | 9 ++ .../notebook/cell/metadata/index.ts | 8 ++ .../components/notebook/cell/prompt/index.ts | 9 ++ .../components/notebook/cell/sidebar/index.ts | 10 +++ .../src/components/notebook/content/index.ts | 7 ++ .../react/src/components/notebook/index.ts | 14 +++ .../src/components/notebook/marked/index.ts | 7 ++ .../model/JupyterReactNotebookModelFactory.ts | 8 +- .../src/components/notebook/model/index.ts | 7 ++ packages/react/src/components/output/index.ts | 12 +++ .../react/src/components/settings/index.ts | 8 ++ .../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 ++ .../examples/{All.tsx => JupyterContext.tsx} | 77 ++++++++-------- .../react/src/examples/NotebookReadonly.tsx | 44 +++++++++ packages/react/src/index.ts | 89 +------------------ packages/react/src/jupyter/index.ts | 18 ++++ .../react/src/jupyter/ipywidgets/index.ts | 8 ++ packages/react/src/jupyter/kernel/index.ts | 1 + packages/react/src/jupyter/lite/index.ts | 7 ++ packages/react/src/jupyter/renderers/index.ts | 2 + .../src/jupyter/renderers/plotly/index.ts | 7 ++ packages/react/src/themes/index.ts | 7 ++ packages/react/webpack.config.js | 4 +- 49 files changed, 472 insertions(+), 190 deletions(-) create mode 100644 packages/react/src/components/button/index.ts 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 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/{All.tsx => JupyterContext.tsx} (84%) create mode 100644 packages/react/src/examples/NotebookReadonly.tsx create mode 100644 packages/react/src/jupyter/index.ts create mode 100644 packages/react/src/jupyter/ipywidgets/index.ts create mode 100644 packages/react/src/jupyter/lite/index.ts create mode 100644 packages/react/src/jupyter/renderers/plotly/index.ts create mode 100644 packages/react/src/themes/index.ts diff --git a/packages/react/src/components/button/index.ts b/packages/react/src/components/button/index.ts new file mode 100644 index 00000000..ca1901de --- /dev/null +++ b/packages/react/src/components/button/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +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/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/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..80dd6fec 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -10,7 +10,8 @@ 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 { ServiceManager } from '@jupyterlab/services'; +import { useJupyter, Lite } from './../../jupyter/JupyterContext'; import { Kernel } from '../../jupyter/kernel/Kernel'; import Lumino from '../lumino/Lumino'; import { asObservable } from '../lumino/LuminoObservable'; @@ -32,9 +33,8 @@ export type BundledIPyWidgets = ExternalIPyWidgets & { }; export type INotebookProps = { - cellMetadataPanel: boolean; - cellSidebarMargin: number; - height?: string; + CellSidebar?: (props: CellSidebarProps) => JSX.Element; + Toolbar?: (props: any) => JSX.Element; /* Example: bundledIPyWidgets={[ @@ -44,8 +44,10 @@ export type INotebookProps = { module: require('jupyter-matplotlib'), }, ]} - */ bundledIPyWidgets?: BundledIPyWidgets[]; + */ + cellMetadataPanel: boolean; + cellSidebarMargin: number; /* Example: externalIPyWidgets={[ @@ -54,19 +56,20 @@ export type INotebookProps = { { name: 'jupyter-leaflet', version: '0.18.0' }, { name: 'jupyter-matplotlib', version: '0.11.3' }, ]} - */ externalIPyWidgets?: ExternalIPyWidgets[]; + */ + height?: string; + id: string; + lite?: Lite; kernel?: Kernel; maxHeight?: string; nbformat?: INotebookContent; nbgrader: boolean; path?: string; - readOnly: boolean; + readonly: boolean; renderers: IRenderMime.IRendererFactory[]; - id: string; + serviceManager?: ServiceManager.IManager, url?: string; - CellSidebar?: (props: CellSidebarProps) => JSX.Element; - Toolbar?: (props: any) => JSX.Element; }; /** @@ -79,14 +82,16 @@ export type INotebookProps = { export const Notebook = (props: INotebookProps) => { const { serviceManager, defaultKernel, kernelManager, lite } = useJupyter(); const { - path, - kernel: propsKernel, - readOnly, - nbgrader, + Toolbar, height, + kernel: propsKernel, + lite: propsLite, maxHeight, nbformat, - Toolbar, + nbgrader, + path, + readonly, + serviceManager: propsServiceManager, } = props; const notebookStore = useNotebookStore(); @@ -94,22 +99,25 @@ export const Notebook = (props: INotebookProps) => { const [adapter, setAdapter] = useState(); const kernel = propsKernel || defaultKernel; const portals = notebookStore.selectNotebookPortals(id); - const newAdapterState = () => { + const createAdapter = () => { if (id && serviceManager && kernelManager && kernel) { kernel.ready.then(() => { const adapter = new NotebookAdapter( { ...props, - kernel, id, + lite: lite ?? propsLite, + kernel, + serviceManager: serviceManager ?? propsServiceManager, }, - serviceManager, - lite ); setAdapter(adapter); - notebookStore.update({ id, partialState: { adapter: adapter } }) + notebookStore.update({ + id, + partialState: { adapter: adapter } + }); adapter.serviceManager.ready.then(() => { - if (!readOnly) { + if (!readonly) { const activeCell = adapter.notebookPanel!.content.activeCell; if (activeCell) { notebookStore.activeCellChange({ @@ -181,7 +189,7 @@ export const Notebook = (props: INotebookProps) => { if (adapter) { adapter.dispose(); } - newAdapterState(); + createAdapter(); return () => { notebookStore.setPortalDisplay({ id, portalDisplay: undefined }); notebookStore.dispose(id); @@ -270,7 +278,7 @@ Notebook.defaultProps = { height: '100vh', maxHeight: '100vh', nbgrader: false, - readOnly: false, + readonly: false, renderers: [], } as Partial; diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 661e37b0..15f0c819 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -53,17 +53,13 @@ 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 { 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'; -const FALLBACK_PATH = 'ping.ipynb'; +const FALLBACK_NOTEBOOK_PATH = 'ping.ipynb'; export class NotebookAdapter { private _boxPanel: BoxPanel; @@ -78,7 +74,7 @@ export class NotebookAdapter { private _nbgrader: boolean; private _notebookPanel?: NotebookPanel; private _path?: string; - private _readOnly: boolean; + private _readonly: boolean; private _renderers: IRenderMime.IRendererFactory[]; private _rendermime?: RenderMimeRegistry; private _serviceManager: ServiceManager.IManager; @@ -86,26 +82,20 @@ export class NotebookAdapter { private _id: string; private _CellSidebar?: (props: any) => JSX.Element; - constructor( - props: INotebookProps, - serviceManager: ServiceManager.IManager, - lite?: Lite - ) { + constructor(props: INotebookProps) { // this._bundledIPyWidgets = props.bundledIPyWidgets; // this._externalIPyWidgets = props.externalIPyWidgets; + this._id = props.id; this._kernel = props.kernel!; - this._lite = lite; + 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._serviceManager = props.serviceManager!; this._CellSidebar = props.CellSidebar; - this._serviceManager = serviceManager; - this._boxPanel = new BoxPanel(); this._boxPanel.addClass('dla-Jupyter-Notebook'); this._boxPanel.spacing = 0; @@ -255,14 +245,14 @@ export class NotebookAdapter { const notebookModelFactory = new JupyterReactNotebookModelFactory({ nbformat: this._nbformat, - readOnly: this._readOnly, + readonly: this._readonly, }); documentRegistry.addModelFactory(notebookModelFactory); this._context = new Context({ manager: this._serviceManager, factory: notebookModelFactory, - path: this._path ?? FALLBACK_PATH, + path: this._path ?? FALLBACK_NOTEBOOK_PATH, kernelPreference: { id: this._kernel.id, shouldStart: false, 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/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/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/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/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..b05b46dd --- /dev/null +++ b/packages/react/src/components/notebook/index.ts @@ -0,0 +1,14 @@ +/* + * 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'; 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..3cd3c8db 100644 --- a/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts +++ b/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts @@ -15,13 +15,13 @@ 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 */ @@ -34,7 +34,7 @@ export class JupyterReactNotebookModelFactory extends NotebookModelFactory { return notebookModel; } else { const notebookModel = super.createNew(options); - notebookModel.readOnly = this._readOnly; + notebookModel.readOnly = this._readonly; return notebookModel; } } @@ -43,7 +43,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/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/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/All.tsx b/packages/react/src/examples/JupyterContext.tsx similarity index 84% rename from packages/react/src/examples/All.tsx rename to packages/react/src/examples/JupyterContext.tsx index 87d17abe..2653f0cc 100644 --- a/packages/react/src/examples/All.tsx +++ b/packages/react/src/examples/JupyterContext.tsx @@ -185,43 +185,50 @@ const Outputs = () => { ); }; +const JuptyerContextExample = () => { + + return ( + + +
+ +
+ + + +
+ +
+ + +
+ +
+ +
+ +
+ +
+ ); +} + 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/NotebookReadonly.tsx b/packages/react/src/examples/NotebookReadonly.tsx new file mode 100644 index 00000000..2744d77b --- /dev/null +++ b/packages/react/src/examples/NotebookReadonly.tsx @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { useState, useEffect } from 'react'; +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 nbformatExample from './notebooks/NotebookExample1.ipynb.json'; + +const NotebookReadonly = () => { + const [content, setContent] = useState() + useEffect(() => { + const exampleNotebook = nbformatExample as INotebookContent; + exampleNotebook.cells.forEach(cell => { + cell.metadata['editable'] = false; + }) + setContent(exampleNotebook); + }, []); + return ( + + + + ); +} + +const div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 9eed535e..1750cf0b 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 './themes'; export * from './utils'; diff --git a/packages/react/src/jupyter/index.ts b/packages/react/src/jupyter/index.ts new file mode 100644 index 00000000..3a48b284 --- /dev/null +++ b/packages/react/src/jupyter/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './Jupyter'; +export * from './JupyterAuthError'; +export * from './JupyterConfig'; +export * from './JupyterContext'; +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/index.ts b/packages/react/src/jupyter/ipywidgets/index.ts new file mode 100644 index 00000000..0c3425fd --- /dev/null +++ b/packages/react/src/jupyter/ipywidgets/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './libembed-amd'; +export * from './mimetypes'; 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/lite/index.ts b/packages/react/src/jupyter/lite/index.ts new file mode 100644 index 00000000..00064040 --- /dev/null +++ b/packages/react/src/jupyter/lite/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +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/themes/index.ts b/packages/react/src/themes/index.ts new file mode 100644 index 00000000..0d984bb9 --- /dev/null +++ b/packages/react/src/themes/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +export * from './primerTheme'; diff --git a/packages/react/webpack.config.js b/packages/react/webpack.config.js index 1db4a437..16e711a3 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -29,6 +29,7 @@ const ENTRY = // './src/examples/IPyReact'; // './src/examples/IPyWidgets'; // './src/examples/IPyWidgetsWithState'; + './src/examples/JupyterContext'; // './src/examples/JupyterLabApp'; // './src/examples/JupyterLabAppHeadless'; // './src/examples/JupyterLabAppHeadlessServerless'; @@ -39,7 +40,8 @@ const ENTRY = // './src/examples/KernelExecutor'; // './src/examples/Lumino'; // './src/examples/Matplotlib'; - './src/examples/Notebook'; + // './src/examples/Notebook'; + // './src/examples/NotebookReadonly'; // './src/examples/NotebookUrl'; // './src/examples/NotebookColorMode'; // './src/examples/NotebookKernelChange'; From 09b646e9cc0a37a5169fbdd2f555149f01280363 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Wed, 11 Sep 2024 16:37:00 +0200 Subject: [PATCH 03/14] chore: favor jupyterlabtheme --- .../components/notebook/NotebookAdapter.ts | 4 +- packages/react/src/examples/Bokeh.tsx | 6 +- packages/react/src/examples/Bqplot.tsx | 6 +- packages/react/src/examples/Cells.tsx | 6 +- packages/react/src/examples/Console.tsx | 6 +- packages/react/src/examples/Dashboard.tsx | 6 +- packages/react/src/examples/FileBrowser.tsx | 6 +- packages/react/src/examples/GeoJson.tsx | 6 +- packages/react/src/examples/IPyLeaflet.tsx | 6 +- packages/react/src/examples/IPyReact.tsx | 6 +- packages/react/src/examples/IPyWidgets.tsx | 6 +- .../src/examples/IPyWidgetsWithState.tsx | 6 +- .../react/src/examples/JupyterContext.tsx | 83 ++++++++------ packages/react/src/examples/KernelExecute.tsx | 6 +- .../react/src/examples/KernelExecutor.tsx | 6 +- packages/react/src/examples/Kernels.tsx | 6 +- .../src/examples/NotebookCellSidebar.tsx | 6 +- .../src/examples/NotebookExternalContent.tsx | 6 +- .../react/src/examples/NotebookNbFormat.tsx | 6 +- .../src/examples/NotebookNbFormatChange.tsx | 6 +- ...ntextNoPrimer.tsx => NotebookNoPrimer.tsx} | 0 packages/react/src/examples/NotebookPath.tsx | 6 +- .../react/src/examples/NotebookPathChange.tsx | 6 +- .../react/src/examples/NotebookReadonly.tsx | 6 +- .../react/src/examples/NotebookUnmount.tsx | 6 +- packages/react/src/examples/NotebookUrl.tsx | 6 +- .../react/src/examples/OutputIPyWidgets.tsx | 10 +- packages/react/src/examples/Outputs.tsx | 6 +- packages/react/src/examples/Panel.tsx | 6 +- packages/react/src/examples/Plotly.tsx | 6 +- packages/react/src/examples/Vega.tsx | 6 +- packages/react/src/jupyter/Jupyter.tsx | 12 +- packages/react/src/jupyter/JupyterContext.tsx | 9 +- .../src/jupyter/ipywidgets/classic/index.ts | 8 ++ .../react/src/jupyter/ipywidgets/index.ts | 3 + .../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/state/JupyerReactState.ts | 108 +++++++++--------- packages/react/webpack.config.js | 7 +- 40 files changed, 221 insertions(+), 196 deletions(-) rename packages/react/src/examples/{NotebookNoContextNoPrimer.tsx => NotebookNoPrimer.tsx} (100%) create mode 100644 packages/react/src/jupyter/ipywidgets/classic/index.ts create mode 100644 packages/react/src/jupyter/ipywidgets/lab/index.ts diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 15f0c819..84a90575 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -57,7 +57,7 @@ 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 { WidgetLabRenderer } from '../../jupyter/ipywidgets/lab/renderer'; const FALLBACK_NOTEBOOK_PATH = 'ping.ipynb'; @@ -140,7 +140,7 @@ export class NotebookAdapter { mimeTypes: [WIDGET_MIMETYPE], defaultRank: 1, createRenderer: options => - new WidgetRenderer(options, this._iPyWidgetsManager!), + new WidgetLabRenderer(options, this._iPyWidgetsManager!), }; initialFactories.push(ipywidgetsRendererFactory); diff --git a/packages/react/src/examples/Bokeh.tsx b/packages/react/src/examples/Bokeh.tsx index f2aa2df7..57487ce4 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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..1ba65a8c 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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/Cells.tsx b/packages/react/src/examples/Cells.tsx index 08f18795..e768d5e2 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; 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/Console.tsx b/packages/react/src/examples/Console.tsx index 29322a6d..6e9f8277 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; 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/Dashboard.tsx b/packages/react/src/examples/Dashboard.tsx index 4ad6870d..7e1b7abb 100644 --- a/packages/react/src/examples/Dashboard.tsx +++ b/packages/react/src/examples/Dashboard.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ 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/FileBrowser.tsx b/packages/react/src/examples/FileBrowser.tsx index 5467ba8b..4425f28a 100644 --- a/packages/react/src/examples/FileBrowser.tsx +++ b/packages/react/src/examples/FileBrowser.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import FileBrowser from '../components/filebrowser/FileBrowser'; const div = document.createElement('div'); @@ -13,7 +13,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/GeoJson.tsx b/packages/react/src/examples/GeoJson.tsx index fded7852..9204225c 100644 --- a/packages/react/src/examples/GeoJson.tsx +++ b/packages/react/src/examples/GeoJson.tsx @@ -6,13 +6,13 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as geojsonRenderer } from '@jupyterlab/geojson-extension'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const GeoJson = () => ( - + ( CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/IPyLeaflet.tsx b/packages/react/src/examples/IPyLeaflet.tsx index a8474019..e47526d9 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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..45a4002f 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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..151771cc 100644 --- a/packages/react/src/examples/IPyWidgets.tsx +++ b/packages/react/src/examples/IPyWidgets.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ 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/IPyWidgetsWithState.tsx index d3f5bf7f..0da24cfe 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsWithState.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExampleWithState.ipynb.json'; const IPyWidgetsWithState = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/JupyterContext.tsx b/packages/react/src/examples/JupyterContext.tsx index 2653f0cc..6d3ddb3e 100644 --- a/packages/react/src/examples/JupyterContext.tsx +++ b/packages/react/src/examples/JupyterContext.tsx @@ -4,9 +4,10 @@ * 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 { Box, Button, ButtonGroup, SegmentedControl } from '@primer/react'; import Jupyter from '../jupyter/Jupyter'; import { useJupyter } from '../jupyter/JupyterContext'; import { Kernel } from '../jupyter/kernel/Kernel'; @@ -186,43 +187,51 @@ const Outputs = () => { }; const JuptyerContextExample = () => { - + const [index, setIndex] = useState(0); return ( - - -
- -
- - - -
- -
- - -
- -
- -
- -
- -
+ <> + + setIndex(index)}> + Serverless + Server + +
+ + + +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+ ); } diff --git a/packages/react/src/examples/KernelExecute.tsx b/packages/react/src/examples/KernelExecute.tsx index de7233b1..5ff15cac 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; 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..dc4e31f9 100644 --- a/packages/react/src/examples/KernelExecutor.tsx +++ b/packages/react/src/examples/KernelExecutor.tsx @@ -9,7 +9,7 @@ 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { Output } from '../components/output/Output'; import { @@ -83,9 +83,9 @@ const KernelExecutorView = () => { const KernelExecutor = () => { return ( - + - + ); }; diff --git a/packages/react/src/examples/Kernels.tsx b/packages/react/src/examples/Kernels.tsx index 9a6237ac..6447aabf 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; 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/NotebookCellSidebar.tsx b/packages/react/src/examples/NotebookCellSidebar.tsx index 799c32c4..bbc4a2ea 100644 --- a/packages/react/src/examples/NotebookCellSidebar.tsx +++ b/packages/react/src/examples/NotebookCellSidebar.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarSource from './sidebars/CellSidebarSource'; @@ -14,7 +14,7 @@ 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/NotebookExternalContent.tsx b/packages/react/src/examples/NotebookExternalContent.tsx index 8e98d047..43dec18d 100644 --- a/packages/react/src/examples/NotebookExternalContent.tsx +++ b/packages/react/src/examples/NotebookExternalContent.tsx @@ -9,7 +9,7 @@ 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import { notebookStore } from '../components/notebook/NotebookState'; @@ -74,7 +74,7 @@ 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 index e977013b..a6819de5 100644 --- a/packages/react/src/examples/NotebookNbFormat.tsx +++ b/packages/react/src/examples/NotebookNbFormat.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; const NotebookNbFormat = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/NotebookNbFormatChange.tsx b/packages/react/src/examples/NotebookNbFormatChange.tsx index 7c41ca92..ebca858f 100755 --- a/packages/react/src/examples/NotebookNbFormatChange.tsx +++ b/packages/react/src/examples/NotebookNbFormatChange.tsx @@ -8,7 +8,7 @@ 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import useNotebookStore from '../components/notebook/NotebookState'; @@ -52,7 +52,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookNoContextNoPrimer.tsx b/packages/react/src/examples/NotebookNoPrimer.tsx similarity index 100% rename from packages/react/src/examples/NotebookNoContextNoPrimer.tsx rename to packages/react/src/examples/NotebookNoPrimer.tsx diff --git a/packages/react/src/examples/NotebookPath.tsx b/packages/react/src/examples/NotebookPath.tsx index 2d4c008d..30be4399 100644 --- a/packages/react/src/examples/NotebookPath.tsx +++ b/packages/react/src/examples/NotebookPath.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; @@ -13,7 +13,7 @@ import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButto const NOTEBOOK_ID = 'notebook-id'; const NotebookPath = () => ( - + ( CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/NotebookPathChange.tsx b/packages/react/src/examples/NotebookPathChange.tsx index d4a36d38..d9ed9641 100755 --- a/packages/react/src/examples/NotebookPathChange.tsx +++ b/packages/react/src/examples/NotebookPathChange.tsx @@ -7,7 +7,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button, Text } from '@primer/react'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -48,7 +48,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookReadonly.tsx b/packages/react/src/examples/NotebookReadonly.tsx index 2744d77b..19ba0e00 100644 --- a/packages/react/src/examples/NotebookReadonly.tsx +++ b/packages/react/src/examples/NotebookReadonly.tsx @@ -7,7 +7,7 @@ import { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -24,7 +24,7 @@ const NotebookReadonly = () => { setContent(exampleNotebook); }, []); return ( - + { CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); } diff --git a/packages/react/src/examples/NotebookUnmount.tsx b/packages/react/src/examples/NotebookUnmount.tsx index fc7caa1f..d7bf2387 100755 --- a/packages/react/src/examples/NotebookUnmount.tsx +++ b/packages/react/src/examples/NotebookUnmount.tsx @@ -8,7 +8,7 @@ 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import Kernel from '../jupyter/kernel/Kernel'; import Notebook from '../components/notebook/Notebook'; @@ -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 index 2fd8c9fc..8ebdd7b8 100644 --- a/packages/react/src/examples/NotebookUrl.tsx +++ b/packages/react/src/examples/NotebookUrl.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; +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'; @@ -17,7 +17,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/OutputIPyWidgets.tsx b/packages/react/src/examples/OutputIPyWidgets.tsx index 30877c18..12f82325 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; 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/Outputs.tsx b/packages/react/src/examples/Outputs.tsx index 954fdbf8..6dca9cb5 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; 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..3384796d 100644 --- a/packages/react/src/examples/Panel.tsx +++ b/packages/react/src/examples/Panel.tsx @@ -5,14 +5,14 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const Panel = () => { return ( - + { CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); }; diff --git a/packages/react/src/examples/Plotly.tsx b/packages/react/src/examples/Plotly.tsx index 8c5e4649..f0bfc7e2 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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/Vega.tsx b/packages/react/src/examples/Vega.tsx index 8b687d79..ee6cece2 100644 --- a/packages/react/src/examples/Vega.tsx +++ b/packages/react/src/examples/Vega.tsx @@ -6,13 +6,13 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as vega3Renderer } from '@jupyterlab/vega3-extension'; -import Jupyter from '../jupyter/Jupyter'; +import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const Vega = () => ( - + ( CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/jupyter/Jupyter.tsx b/packages/react/src/jupyter/Jupyter.tsx index 3362022c..d2f6bcfd 100644 --- a/packages/react/src/jupyter/Jupyter.tsx +++ b/packages/react/src/jupyter/Jupyter.tsx @@ -74,19 +74,11 @@ 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...');}} > Load dynamically */ lite?: Lite; + /* + * Create a serveless Jupyter. + */ + serverless: boolean /** * Jupyter service manager */ @@ -202,6 +206,7 @@ export const useJupyter = (props?: JupyterPropsType): JupyterContextType => { kernelIsLoading, kernelManager: serviceManager?.kernels, lite: false, + serverless: props?.serverless ?? false, serverSettings: serviceManager?.serverSettings, serviceManager, } @@ -264,14 +269,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/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 index 0c3425fd..186142f3 100644 --- a/packages/react/src/jupyter/ipywidgets/index.ts +++ b/packages/react/src/jupyter/ipywidgets/index.ts @@ -6,3 +6,6 @@ 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/state/JupyerReactState.ts b/packages/react/src/state/JupyerReactState.ts index cb1239c2..0ed5bb00 100644 --- a/packages/react/src/state/JupyerReactState.ts +++ b/packages/react/src/state/JupyerReactState.ts @@ -129,65 +129,63 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR 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); - }); - return; - } - const serverSettings = createServerSettings( - config.jupyterServerUrl, - config.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); + 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 (useRunningKernelId && useRunningKernelIndex > -1) { - throw new Error('You can not ask for useRunningKernelId and useRunningKernelIndex at the same time.'); + if (!Array.isArray(data)) { + data = [data]; } - if ( - startDefaultKernel && - (useRunningKernelId || useRunningKernelIndex > -1) - ) { - throw new Error('You can not ask for startDefaultKernel and (useRunningKernelId or useRunningKernelIndex) at the same time.'); - } - const serviceManager = new ServiceManager({ serverSettings }); - setServiceManager(serviceManager); - jupyterReactStore.getState().setServiceManager(serviceManager); + 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); }); + return; } + const serverSettings = createServerSettings( + config.jupyterServerUrl, + config.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); + } + if (useRunningKernelId && useRunningKernelIndex > -1) { + throw new Error('You can not ask for useRunningKernelId and useRunningKernelIndex at the same time.'); + } + if ( + startDefaultKernel && + (useRunningKernelId || useRunningKernelIndex > -1) + ) { + throw new Error('You can not ask for startDefaultKernel and (useRunningKernelId or useRunningKernelIndex) at the same time.'); + } + const serviceManager = new ServiceManager({ serverSettings }); + setServiceManager(serviceManager); + jupyterReactStore.getState().setServiceManager(serviceManager); + }); }, [lite, serverless, jupyterServerUrl]); // Setup a kernel if needed. diff --git a/packages/react/webpack.config.js b/packages/react/webpack.config.js index 16e711a3..a0f9e1b5 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -18,7 +18,8 @@ function shim(regExp) { const ENTRY = // './src/app/App'; - // './src/examples/Cell'; + // './src/examples/Bokeh'; + './src/examples/Cell'; // './src/examples/Cells'; // './src/examples/CellsExecute'; // './src/examples/CellLite'; @@ -29,7 +30,7 @@ const ENTRY = // './src/examples/IPyReact'; // './src/examples/IPyWidgets'; // './src/examples/IPyWidgetsWithState'; - './src/examples/JupyterContext'; + // './src/examples/JupyterContext'; // './src/examples/JupyterLabApp'; // './src/examples/JupyterLabAppHeadless'; // './src/examples/JupyterLabAppHeadlessServerless'; @@ -49,7 +50,7 @@ const ENTRY = // './src/examples/NotebookNbFormat'; // './src/examples/NotebookNbFormatChange'; // './src/examples/NotebookNoContext'; - // './src/examples/NotebookNoContextNoPrimer'; + // './src/examples/NotebookNoPrimer'; // './src/examples/NotebookServiceManager'; // './src/examples/NotebookSkeleton'; // './src/examples/NotebookTheme'; From 2b3e40d9a9dcd5e007a67563536a7e40171bc165 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Wed, 11 Sep 2024 17:33:45 +0200 Subject: [PATCH 04/14] chore: jupyter react theme --- .../src/components/notebook/Notebook.tsx | 26 +------------ .../components/notebook/NotebookAdapter.ts | 17 +-------- .../model/JupyterReactNotebookModelFactory.ts | 5 +++ packages/react/src/examples/Bokeh.tsx | 6 +-- packages/react/src/examples/Bqplot.tsx | 6 +-- packages/react/src/examples/Cells.tsx | 6 +-- packages/react/src/examples/CellsExecute.tsx | 6 +-- packages/react/src/examples/Console.tsx | 6 +-- packages/react/src/examples/Dashboard.tsx | 6 +-- packages/react/src/examples/FileBrowser.tsx | 6 +-- packages/react/src/examples/GeoJson.tsx | 6 +-- packages/react/src/examples/IPyLeaflet.tsx | 6 +-- packages/react/src/examples/IPyReact.tsx | 6 +-- packages/react/src/examples/IPyWidgets.tsx | 6 +-- .../src/examples/IPyWidgetsWithState.tsx | 6 +-- packages/react/src/examples/JupyterLabApp.tsx | 2 +- .../JupyterLabAppHeadlessServerless.tsx | 6 +-- .../src/examples/JupyterLabAppServerless.tsx | 6 +-- .../examples/JupyterLabAppServiceManager.tsx | 10 ++--- packages/react/src/examples/KernelExecute.tsx | 6 +-- .../react/src/examples/KernelExecutor.tsx | 6 +-- packages/react/src/examples/Kernels.tsx | 6 +-- .../src/examples/NotebookCellSidebar.tsx | 6 +-- .../react/src/examples/NotebookEvolving.tsx | 38 +++++++++++++++++++ .../src/examples/NotebookExternalContent.tsx | 6 +-- .../react/src/examples/NotebookNbFormat.tsx | 6 +-- .../src/examples/NotebookNbFormatChange.tsx | 6 +-- .../react/src/examples/NotebookNoContext.tsx | 6 +-- packages/react/src/examples/NotebookPath.tsx | 6 +-- .../react/src/examples/NotebookPathChange.tsx | 6 +-- .../react/src/examples/NotebookReadonly.tsx | 21 +++------- packages/react/src/examples/NotebookTheme.tsx | 2 +- .../src/examples/NotebookThemeColorMode.tsx | 2 +- .../react/src/examples/NotebookUnmount.tsx | 6 +-- packages/react/src/examples/NotebookUrl.tsx | 6 +-- .../react/src/examples/OutputIPyWidgets.tsx | 6 +-- packages/react/src/examples/Outputs.tsx | 6 +-- packages/react/src/examples/Panel.tsx | 6 +-- packages/react/src/examples/Plotly.tsx | 6 +-- packages/react/src/examples/Vega.tsx | 6 +-- packages/react/src/jupyter/index.ts | 3 ++ packages/react/src/jupyter/lab/index.ts | 5 ++- .../{primerTheme.ts => JupyterPrimerTheme.ts} | 0 .../JupyterReactTheme.tsx} | 9 ++--- packages/react/src/themes/index.ts | 3 +- packages/react/webpack.config.js | 11 +++--- 46 files changed, 172 insertions(+), 168 deletions(-) create mode 100644 packages/react/src/examples/NotebookEvolving.tsx rename packages/react/src/themes/{primerTheme.ts => JupyterPrimerTheme.ts} (100%) rename packages/react/src/{jupyter/lab/JupyterLabTheme.tsx => themes/JupyterReactTheme.tsx} (70%) diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index 80dd6fec..2f278909 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -35,29 +35,8 @@ export type BundledIPyWidgets = ExternalIPyWidgets & { export type INotebookProps = { CellSidebar?: (props: CellSidebarProps) => JSX.Element; Toolbar?: (props: any) => JSX.Element; - /* - Example: - bundledIPyWidgets={[ - { - name: 'jupyter-matplotlib', - version: '0.11.3', - module: require('jupyter-matplotlib'), - }, - ]} - bundledIPyWidgets?: BundledIPyWidgets[]; - */ cellMetadataPanel: boolean; cellSidebarMargin: number; - /* - 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[]; - */ height?: string; id: string; lite?: Lite; @@ -93,11 +72,10 @@ export const Notebook = (props: INotebookProps) => { readonly, serviceManager: propsServiceManager, } = 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 = propsKernel ?? defaultKernel; const portals = notebookStore.selectNotebookPortals(id); const createAdapter = () => { if (id && serviceManager && kernelManager && kernel) { diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 84a90575..e66235c1 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -65,8 +65,6 @@ export class NotebookAdapter { private _boxPanel: BoxPanel; private _commandRegistry: CommandRegistry; private _context?: Context; -// private _bundledIPyWidgets?: BundledIPyWidgets[]; -// private _externalIPyWidgets?: ExternalIPyWidgets[]; private _iPyWidgetsManager?: WidgetManager; private _kernel: Kernel; private _lite?: Lite; @@ -83,8 +81,6 @@ export class NotebookAdapter { private _CellSidebar?: (props: any) => JSX.Element; constructor(props: INotebookProps) { -// this._bundledIPyWidgets = props.bundledIPyWidgets; -// this._externalIPyWidgets = props.externalIPyWidgets; this._id = props.id; this._kernel = props.kernel!; this._lite = props.lite; @@ -94,6 +90,7 @@ export class NotebookAdapter { this._readonly = props.readonly; this._renderers = props.renderers; this._serviceManager = props.serviceManager!; + this._CellSidebar = props.CellSidebar; this._boxPanel = new BoxPanel(); @@ -285,18 +282,6 @@ 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 => { diff --git a/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts b/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts index 3cd3c8db..9056a4f0 100644 --- a/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts +++ b/packages/react/src/components/notebook/model/JupyterReactNotebookModelFactory.ts @@ -29,6 +29,11 @@ export class JupyterReactNotebookModelFactory extends NotebookModelFactory { options: DocumentRegistry.IModelOptions ): INotebookModel { if (this._nbformat) { + if (this._readonly) { + this._nbformat.cells.forEach(cell => { + cell.metadata['editable'] = false; + }); + } const notebookModel = new NotebookModel(); notebookModel.fromJSON(this._nbformat); return notebookModel; diff --git a/packages/react/src/examples/Bokeh.tsx b/packages/react/src/examples/Bokeh.tsx index 57487ce4..8909751a 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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 1ba65a8c..37cdb507 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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/Cells.tsx b/packages/react/src/examples/Cells.tsx index e768d5e2..fd95e8a8 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/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..7ca6d2f8 100644 --- a/packages/react/src/examples/CellsExecute.tsx +++ b/packages/react/src/examples/CellsExecute.tsx @@ -7,7 +7,7 @@ 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 '../themes/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const CODE_CELL_1 = `import time @@ -33,7 +33,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 6e9f8277..1d0d3c3f 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/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/Dashboard.tsx b/packages/react/src/examples/Dashboard.tsx index 7e1b7abb..d0b7ccbd 100644 --- a/packages/react/src/examples/Dashboard.tsx +++ b/packages/react/src/examples/Dashboard.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ 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/FileBrowser.tsx b/packages/react/src/examples/FileBrowser.tsx index 4425f28a..6533aa84 100644 --- a/packages/react/src/examples/FileBrowser.tsx +++ b/packages/react/src/examples/FileBrowser.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import FileBrowser from '../components/filebrowser/FileBrowser'; const div = document.createElement('div'); @@ -13,7 +13,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/GeoJson.tsx b/packages/react/src/examples/GeoJson.tsx index 9204225c..d1e9fbb8 100644 --- a/packages/react/src/examples/GeoJson.tsx +++ b/packages/react/src/examples/GeoJson.tsx @@ -6,13 +6,13 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as geojsonRenderer } from '@jupyterlab/geojson-extension'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const GeoJson = () => ( - + ( CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/IPyLeaflet.tsx b/packages/react/src/examples/IPyLeaflet.tsx index e47526d9..93ed03c8 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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 45a4002f..0cfa3c67 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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 151771cc..ee60e6c7 100644 --- a/packages/react/src/examples/IPyWidgets.tsx +++ b/packages/react/src/examples/IPyWidgets.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ 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/IPyWidgetsWithState.tsx index 0da24cfe..b608d5bc 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsWithState.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExampleWithState.ipynb.json'; const IPyWidgetsWithState = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/JupyterLabApp.tsx b/packages/react/src/examples/JupyterLabApp.tsx index f5721622..fd0f9d4c 100644 --- a/packages/react/src/examples/JupyterLabApp.tsx +++ b/packages/react/src/examples/JupyterLabApp.tsx @@ -42,7 +42,7 @@ const JupyterLabAppExample = () => { onJupyterLab={onJupyterLab} /> ); -}; +} const div = document.createElement('div'); document.body.appendChild(div); diff --git a/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx b/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx index a54539f5..906713ac 100644 --- a/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx +++ b/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx @@ -10,7 +10,7 @@ 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Lumino from '../components/lumino/Lumino'; import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; @@ -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..2523a666 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 '../themes/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..f1eb3a9c 100644 --- a/packages/react/src/examples/JupyterLabAppServiceManager.tsx +++ b/packages/react/src/examples/JupyterLabAppServiceManager.tsx @@ -7,7 +7,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { NotebookPanel } from '@jupyterlab/notebook'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; @@ -49,15 +49,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 5ff15cac..93d940f6 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/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 dc4e31f9..be4f355a 100644 --- a/packages/react/src/examples/KernelExecutor.tsx +++ b/packages/react/src/examples/KernelExecutor.tsx @@ -9,7 +9,7 @@ import { createRoot } from 'react-dom/client'; import { Box, Heading } from '@primer/react'; import { IOutputAreaModel } from '@jupyterlab/outputarea'; import { KernelMessage } from '@jupyterlab/services'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { Output } from '../components/output/Output'; import { @@ -83,9 +83,9 @@ const KernelExecutorView = () => { const KernelExecutor = () => { return ( - + - + ); }; diff --git a/packages/react/src/examples/Kernels.tsx b/packages/react/src/examples/Kernels.tsx index 6447aabf..31399617 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/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/NotebookCellSidebar.tsx b/packages/react/src/examples/NotebookCellSidebar.tsx index bbc4a2ea..7898d13b 100644 --- a/packages/react/src/examples/NotebookCellSidebar.tsx +++ b/packages/react/src/examples/NotebookCellSidebar.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarSource from './sidebars/CellSidebarSource'; @@ -14,7 +14,7 @@ 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/NotebookEvolving.tsx b/packages/react/src/examples/NotebookEvolving.tsx new file mode 100644 index 00000000..3cd8de35 --- /dev/null +++ b/packages/react/src/examples/NotebookEvolving.tsx @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { useState } from 'react'; +import { createRoot } from 'react-dom/client'; +import { INotebookContent } from '@jupyterlab/nbformat'; +import { SegmentedControl } from '@primer/react'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; +import Notebook from '../components/notebook/Notebook'; + +import nbformat from './notebooks/NotebookExample1.ipynb.json'; + +const NotebookEvolving = () => { + const [index, setIndex] = useState(0); + return ( + + setIndex(index)}> + Readonly + Browser Kernel + CPU Kernel + + + + ); +} + +const div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); diff --git a/packages/react/src/examples/NotebookExternalContent.tsx b/packages/react/src/examples/NotebookExternalContent.tsx index 43dec18d..49bf57f1 100644 --- a/packages/react/src/examples/NotebookExternalContent.tsx +++ b/packages/react/src/examples/NotebookExternalContent.tsx @@ -9,7 +9,7 @@ import { createRoot } from 'react-dom/client'; import { Box, IconButton } from '@primer/react'; import { ZapIcon } from '@primer/octicons-react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import { notebookStore } from '../components/notebook/NotebookState'; @@ -74,7 +74,7 @@ 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 index a6819de5..864ad9a6 100644 --- a/packages/react/src/examples/NotebookNbFormat.tsx +++ b/packages/react/src/examples/NotebookNbFormat.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -14,7 +14,7 @@ import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; const NotebookNbFormat = () => ( - + ( CellSidebar={CellSidebar} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/NotebookNbFormatChange.tsx b/packages/react/src/examples/NotebookNbFormatChange.tsx index ebca858f..b9978497 100755 --- a/packages/react/src/examples/NotebookNbFormatChange.tsx +++ b/packages/react/src/examples/NotebookNbFormatChange.tsx @@ -8,7 +8,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button, ButtonGroup } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import useNotebookStore from '../components/notebook/NotebookState'; @@ -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..1f076902 100644 --- a/packages/react/src/examples/NotebookNoContext.tsx +++ b/packages/react/src/examples/NotebookNoContext.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterLabTheme } from '../jupyter/lab/JupyterLabTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; @@ -19,7 +19,7 @@ const root = createRoot(div); const colorMode = 'light'; root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookPath.tsx b/packages/react/src/examples/NotebookPath.tsx index 30be4399..2772f9f9 100644 --- a/packages/react/src/examples/NotebookPath.tsx +++ b/packages/react/src/examples/NotebookPath.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; @@ -13,7 +13,7 @@ import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButto const NOTEBOOK_ID = 'notebook-id'; const NotebookPath = () => ( - + ( CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/examples/NotebookPathChange.tsx b/packages/react/src/examples/NotebookPathChange.tsx index d9ed9641..9be0774e 100755 --- a/packages/react/src/examples/NotebookPathChange.tsx +++ b/packages/react/src/examples/NotebookPathChange.tsx @@ -7,7 +7,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button, Text } from '@primer/react'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; @@ -48,7 +48,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookReadonly.tsx b/packages/react/src/examples/NotebookReadonly.tsx index 19ba0e00..c9804b5a 100644 --- a/packages/react/src/examples/NotebookReadonly.tsx +++ b/packages/react/src/examples/NotebookReadonly.tsx @@ -4,36 +4,27 @@ * MIT License */ -import { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; -import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; -import nbformatExample from './notebooks/NotebookExample1.ipynb.json'; +import nbformat from './notebooks/NotebookExample1.ipynb.json'; const NotebookReadonly = () => { - const [content, setContent] = useState() - useEffect(() => { - const exampleNotebook = nbformatExample as INotebookContent; - exampleNotebook.cells.forEach(cell => { - cell.metadata['editable'] = false; - }) - setContent(exampleNotebook); - }, []); return ( - + - + ); } diff --git a/packages/react/src/examples/NotebookTheme.tsx b/packages/react/src/examples/NotebookTheme.tsx index 4d3c12b4..4ee37605 100644 --- a/packages/react/src/examples/NotebookTheme.tsx +++ b/packages/react/src/examples/NotebookTheme.tsx @@ -10,7 +10,7 @@ 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 { jupyterTheme } from '../themes/JupyterPrimerTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; diff --git a/packages/react/src/examples/NotebookThemeColorMode.tsx b/packages/react/src/examples/NotebookThemeColorMode.tsx index d1c32e27..e80c9d92 100644 --- a/packages/react/src/examples/NotebookThemeColorMode.tsx +++ b/packages/react/src/examples/NotebookThemeColorMode.tsx @@ -11,7 +11,7 @@ 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 { jupyterTheme } from '../themes/JupyterPrimerTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; diff --git a/packages/react/src/examples/NotebookUnmount.tsx b/packages/react/src/examples/NotebookUnmount.tsx index d7bf2387..392bfebf 100755 --- a/packages/react/src/examples/NotebookUnmount.tsx +++ b/packages/react/src/examples/NotebookUnmount.tsx @@ -8,7 +8,7 @@ import { useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import Kernel from '../jupyter/kernel/Kernel'; import Notebook from '../components/notebook/Notebook'; @@ -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 index 8ebdd7b8..e51807aa 100644 --- a/packages/react/src/examples/NotebookUrl.tsx +++ b/packages/react/src/examples/NotebookUrl.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; @@ -17,7 +17,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/OutputIPyWidgets.tsx b/packages/react/src/examples/OutputIPyWidgets.tsx index 12f82325..c68bf6d3 100755 --- a/packages/react/src/examples/OutputIPyWidgets.tsx +++ b/packages/react/src/examples/OutputIPyWidgets.tsx @@ -6,7 +6,7 @@ import { render } from 'react-dom'; import { Text } from '@primer/react'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import OutputIPyWidgets from '../components/output/OutputIPyWidgets'; import { view, state } from './notebooks/OutputIPyWidgetsExample'; @@ -24,8 +24,8 @@ const div = document.createElement('div'); document.body.appendChild(div); render( - + - , + , div ); diff --git a/packages/react/src/examples/Outputs.tsx b/packages/react/src/examples/Outputs.tsx index 6dca9cb5..4e8cb7d2 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/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 3384796d..db2c1e0c 100644 --- a/packages/react/src/examples/Panel.tsx +++ b/packages/react/src/examples/Panel.tsx @@ -5,14 +5,14 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const Panel = () => { return ( - + { CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); }; diff --git a/packages/react/src/examples/Plotly.tsx b/packages/react/src/examples/Plotly.tsx index f0bfc7e2..af7c9390 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 JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/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/Vega.tsx b/packages/react/src/examples/Vega.tsx index ee6cece2..5eb69dac 100644 --- a/packages/react/src/examples/Vega.tsx +++ b/packages/react/src/examples/Vega.tsx @@ -6,13 +6,13 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as vega3Renderer } from '@jupyterlab/vega3-extension'; -import JupyterLabTheme from '../jupyter/lab/JupyterLabTheme'; +import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const Vega = () => ( - + ( CellSidebar={CellSidebarNew} Toolbar={NotebookToolbar} /> - + ); const div = document.createElement('div'); diff --git a/packages/react/src/jupyter/index.ts b/packages/react/src/jupyter/index.ts index 3a48b284..55c3f36b 100644 --- a/packages/react/src/jupyter/index.ts +++ b/packages/react/src/jupyter/index.ts @@ -13,6 +13,9 @@ export * from './Jupyter'; export * from './ipywidgets'; export * from './kernel'; export * from './lab'; +export * from './lab/JupyterLabColorMode'; +export * from './lab/JupyterLabCss'; +export * from './lab/JupyterLabCssImports'; export * from './lite'; export * from './renderers'; export * from './services'; diff --git a/packages/react/src/jupyter/lab/index.ts b/packages/react/src/jupyter/lab/index.ts index d850cfa1..731d3526 100644 --- a/packages/react/src/jupyter/lab/index.ts +++ b/packages/react/src/jupyter/lab/index.ts @@ -114,4 +114,7 @@ const jupyterReactPlugin: JupyterFrontEndPlugin = { }, }; -export default [jupyterReactPlugin, notebookContentFactoryPlugin]; +export default [ + jupyterReactPlugin, + notebookContentFactoryPlugin +]; diff --git a/packages/react/src/themes/primerTheme.ts b/packages/react/src/themes/JupyterPrimerTheme.ts similarity index 100% rename from packages/react/src/themes/primerTheme.ts rename to packages/react/src/themes/JupyterPrimerTheme.ts diff --git a/packages/react/src/jupyter/lab/JupyterLabTheme.tsx b/packages/react/src/themes/JupyterReactTheme.tsx similarity index 70% rename from packages/react/src/jupyter/lab/JupyterLabTheme.tsx rename to packages/react/src/themes/JupyterReactTheme.tsx index eab3e4aa..b48dee97 100644 --- a/packages/react/src/jupyter/lab/JupyterLabTheme.tsx +++ b/packages/react/src/themes/JupyterReactTheme.tsx @@ -5,14 +5,13 @@ */ import { BaseStyles, ThemeProvider, theme } from '@primer/react'; -import JupyterLabCss from './JupyterLabCss'; -import { ColorMode } from './JupyterLabColorMode'; +import { ColorMode, JupyterLabCss } from './../jupyter'; type IJupyterLabThemeProps = { colorMode: ColorMode; } -export const JupyterLabTheme = (props: React.PropsWithChildren) => { +export const JupyterReactTheme = (props: React.PropsWithChildren) => { const { children, colorMode } = props; return ( <> @@ -31,8 +30,8 @@ export const JupyterLabTheme = (props: React.PropsWithChildren Date: Wed, 11 Sep 2024 18:39:05 +0200 Subject: [PATCH 05/14] chore: evolving example --- .../react/src/components/lumino/Lumino.tsx | 2 +- .../src/components/notebook/Notebook.tsx | 25 ++++++---- .../components/notebook/NotebookAdapter.ts | 1 - .../react/src/examples/JupyterContext.tsx | 2 +- .../react/src/examples/NotebookEvolving.tsx | 48 +++++++++++++++++-- .../src/examples/NotebookExternalContent.tsx | 4 +- .../src/examples/NotebookServiceManager.tsx | 2 +- 7 files changed, 64 insertions(+), 20 deletions(-) diff --git a/packages/react/src/components/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index dc7fdc3b..c9242a35 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -33,7 +33,7 @@ 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); } }; } diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index 2f278909..e2b5665d 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -13,8 +13,7 @@ import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager } from '@jupyterlab/services'; import { useJupyter, Lite } from './../../jupyter/JupyterContext'; import { Kernel } from '../../jupyter/kernel/Kernel'; -import Lumino from '../lumino/Lumino'; -import { asObservable } from '../lumino/LuminoObservable'; +import { asObservable, Lumino } from '../lumino'; import { CellSidebarProps } from './cell/sidebar/CellSidebarWidget'; import CellMetadataEditor from './cell/metadata/CellMetadataEditor'; import { newUuid } from '../../utils/Utils'; @@ -47,6 +46,7 @@ export type INotebookProps = { path?: string; readonly: boolean; renderers: IRenderMime.IRendererFactory[]; + serverless: boolean, serviceManager?: ServiceManager.IManager, url?: string; }; @@ -59,23 +59,24 @@ export type INotebookProps = { * @returns A Notebook React.js component. */ export const Notebook = (props: INotebookProps) => { - const { serviceManager, defaultKernel, kernelManager, lite } = useJupyter(); + const { serviceManager, defaultKernel, kernelManager, lite } = useJupyter({ + serverless: props.serverless, + serviceManager: props.serviceManager, + lite: props.lite, + }); const { Toolbar, height, - kernel: propsKernel, - lite: propsLite, maxHeight, nbformat, nbgrader, path, readonly, - serviceManager: propsServiceManager, } = props; const notebookStore = useNotebookStore(); 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 createAdapter = () => { if (id && serviceManager && kernelManager && kernel) { @@ -84,9 +85,9 @@ export const Notebook = (props: INotebookProps) => { { ...props, id, - lite: lite ?? propsLite, + lite: lite || props.lite, kernel, - serviceManager: serviceManager ?? propsServiceManager, + serviceManager: serviceManager ?? props.serviceManager, }, ); setAdapter(adapter); @@ -164,15 +165,18 @@ export const Notebook = (props: INotebookProps) => { } }; useEffect(() => { + /* if (adapter) { adapter.dispose(); } + */ createAdapter(); return () => { +// adapter?.dispose(); notebookStore.setPortalDisplay({ id, portalDisplay: undefined }); notebookStore.dispose(id); }; - }, [id, serviceManager, kernelManager, kernel, path]); + }, [id, serviceManager, kernelManager, kernel, path, lite, readonly]); useEffect(() => { if (adapter && nbformat) { adapter.setNbformat(nbformat); @@ -258,6 +262,7 @@ Notebook.defaultProps = { nbgrader: 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 e66235c1..16402ac3 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -114,7 +114,6 @@ export class NotebookAdapter { return fetch(url).then(response => { return response.text(); }).then(nb => { -// const nbformat = nb.replaceAll('\\n', ''); return JSON.parse(nb); }); } diff --git a/packages/react/src/examples/JupyterContext.tsx b/packages/react/src/examples/JupyterContext.tsx index 6d3ddb3e..7cf381fd 100644 --- a/packages/react/src/examples/JupyterContext.tsx +++ b/packages/react/src/examples/JupyterContext.tsx @@ -194,7 +194,7 @@ const JuptyerContextExample = () => { terminals serverless={index === 0} > - setIndex(index)}> + setIndex(index)} aria-label="jupyter-react-example"> Serverless Server diff --git a/packages/react/src/examples/NotebookEvolving.tsx b/packages/react/src/examples/NotebookEvolving.tsx index 3cd8de35..47b91dff 100644 --- a/packages/react/src/examples/NotebookEvolving.tsx +++ b/packages/react/src/examples/NotebookEvolving.tsx @@ -7,24 +7,64 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; +import { ServiceManager } from '@jupyterlab/services'; import { SegmentedControl } from '@primer/react'; +import { JupyterServiceManagerLess } from '../jupyter'; +import { createServerSettings } from '../jupyter/JupyterContext'; +import { getJupyterServerUrl, getJupyterServerToken } from '../jupyter/JupyterConfig'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import nbformat from './notebooks/NotebookExample1.ipynb.json'; +import nbformat1 from './notebooks/NotebookExample1.ipynb.json'; +import nbformat2 from './notebooks/NotebookExample2.ipynb.json'; const NotebookEvolving = () => { const [index, setIndex] = useState(0); + const [readonly, setReadonly] = useState(true); + const [lite, setLite] = useState(false); + const [nbformat, setNbformat] = useState(nbformat1); + const [serviceManager, setServiceManager] = useState(new JupyterServiceManagerLess()); + const changeIndex = (index: number) => { + setIndex(index); + switch(index) { + case 0: { + setReadonly(true); + setLite(false); + setNbformat(nbformat1) + setServiceManager(new JupyterServiceManagerLess()); + break; + } + case 1: { + setReadonly(false); + setLite(true); + setNbformat(nbformat2) + setServiceManager(new JupyterServiceManagerLess()); + break; + } + case 2: { + setReadonly(false); + setLite(false); + setNbformat(nbformat2) + const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); + const serviceManager = new ServiceManager({ serverSettings }); + setServiceManager(serviceManager); + break; + } + } + } return ( - setIndex(index)}> + changeIndex(index)} aria-label="jupyter-react-example"> Readonly Browser Kernel CPU Kernel diff --git a/packages/react/src/examples/NotebookExternalContent.tsx b/packages/react/src/examples/NotebookExternalContent.tsx index 49bf57f1..2fac2e65 100644 --- a/packages/react/src/examples/NotebookExternalContent.tsx +++ b/packages/react/src/examples/NotebookExternalContent.tsx @@ -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) { diff --git a/packages/react/src/examples/NotebookServiceManager.tsx b/packages/react/src/examples/NotebookServiceManager.tsx index a9c5ae82..8791f35f 100644 --- a/packages/react/src/examples/NotebookServiceManager.tsx +++ b/packages/react/src/examples/NotebookServiceManager.tsx @@ -11,8 +11,8 @@ import { ServiceManager } from '@jupyterlab/services'; import Jupyter from '../jupyter/Jupyter'; import { createServerSettings } from '../jupyter/JupyterContext'; import { getJupyterServerUrl, getJupyterServerToken } from '../jupyter/JupyterConfig'; -import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; import { Kernel } from '../jupyter/kernel/Kernel'; +import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; import Notebook from '../components/notebook/Notebook'; import NotebookToolbar from './toolbars/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; From 86bd956c02423efd3feb9d82e26af0ba696fe8a8 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Thu, 12 Sep 2024 07:51:16 +0200 Subject: [PATCH 06/14] chore: toolbar --- packages/react/package.json | 2 +- .../src/components/notebook/Notebook.tsx | 216 ++++++++++-------- .../components/notebook/NotebookAdapter.ts | 9 +- .../src/components/notebook/NotebookState.ts | 31 +-- .../cell/metadata/CellMetadataEditor.tsx | 4 +- .../notebook/cell/prompt/Countdown.tsx | 2 +- .../notebook/cell/sidebar/CellSidebar.tsx | 4 +- .../cell/sidebar/CellSidebarButton.tsx | 4 +- .../notebook/cell/sidebar/CellSidebarRun.tsx | 4 +- .../cell/sidebar/CellSidebarWidget.tsx | 6 +- .../content/JupyterReactContentFactory.ts | 9 +- .../react/src/components/notebook/index.ts | 1 + .../notebook/toolbar}/NotebookToolbar.tsx | 8 +- .../src/components/notebook/toolbar/index.ts | 7 + packages/react/src/examples/Bokeh.tsx | 2 +- packages/react/src/examples/Bqplot.tsx | 2 +- packages/react/src/examples/Dashboard.tsx | 2 +- packages/react/src/examples/Deno.tsx | 2 +- packages/react/src/examples/GeoJson.tsx | 2 +- packages/react/src/examples/IPyLeaflet.tsx | 2 +- packages/react/src/examples/IPyReact.tsx | 2 +- packages/react/src/examples/IPyWidgets.tsx | 2 +- .../src/examples/IPyWidgetsWithState.tsx | 2 +- packages/react/src/examples/JupyterLabApp.tsx | 7 +- packages/react/src/examples/Matplotlib.tsx | 2 +- packages/react/src/examples/Notebook.tsx | 2 +- .../src/examples/NotebookCellSidebar.tsx | 2 +- .../react/src/examples/NotebookColorMode.tsx | 2 +- packages/react/src/examples/NotebookInit.tsx | 2 +- packages/react/src/examples/NotebookLite.tsx | 2 +- ...bookEvolving.tsx => NotebookMutations.tsx} | 45 ++-- .../react/src/examples/NotebookNbFormat.tsx | 2 +- .../react/src/examples/NotebookNoContext.tsx | 2 +- .../react/src/examples/NotebookNoPrimer.tsx | 2 +- packages/react/src/examples/NotebookPath.tsx | 2 +- .../react/src/examples/NotebookReadonly.tsx | 2 +- .../src/examples/NotebookServiceManager.tsx | 2 +- .../react/src/examples/NotebookSkeleton.tsx | 2 +- packages/react/src/examples/NotebookTheme.tsx | 2 +- .../src/examples/NotebookThemeColorMode.tsx | 2 +- packages/react/src/examples/NotebookUrl.tsx | 2 +- packages/react/src/examples/ObservableHQ.tsx | 2 +- packages/react/src/examples/Panel.tsx | 2 +- packages/react/src/examples/Plotly.tsx | 2 +- packages/react/src/examples/Vega.tsx | 2 +- .../examples/sidebars/CellSidebarSource.tsx | 4 +- packages/react/src/jupyter/JupyterContext.tsx | 6 +- packages/react/src/jupyter/lab/index.ts | 118 +--------- .../src/jupyter/lab/notebook/content/index.ts | 5 + packages/react/src/jupyter/lab/plugin.ts | 120 ++++++++++ packages/react/webpack.config.js | 2 +- 51 files changed, 366 insertions(+), 306 deletions(-) rename packages/react/src/{examples/toolbars => components/notebook/toolbar}/NotebookToolbar.tsx (96%) create mode 100644 packages/react/src/components/notebook/toolbar/index.ts rename packages/react/src/examples/{NotebookEvolving.tsx => NotebookMutations.tsx} (55%) create mode 100644 packages/react/src/jupyter/lab/notebook/content/index.ts create mode 100644 packages/react/src/jupyter/lab/plugin.ts diff --git a/packages/react/package.json b/packages/react/package.json index 230aa9ea..9021715d 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -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/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index e2b5665d..181c00e8 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -14,11 +14,12 @@ import { ServiceManager } from '@jupyterlab/services'; import { useJupyter, Lite } from './../../jupyter/JupyterContext'; import { Kernel } from '../../jupyter/kernel/Kernel'; import { asObservable, Lumino } from '../lumino'; -import { CellSidebarProps } from './cell/sidebar/CellSidebarWidget'; -import CellMetadataEditor from './cell/metadata/CellMetadataEditor'; +import { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget'; +import { INotebookToolbarProps } from './toolbar/NotebookToolbar'; import { newUuid } from '../../utils/Utils'; -import NotebookAdapter from './NotebookAdapter'; -import useNotebookStore from './NotebookState'; +import { useNotebookStore } from './NotebookState'; +import { CellMetadataEditor } from './cell/metadata/CellMetadataEditor'; +import { NotebookAdapter } from './NotebookAdapter'; import './Notebook.css'; @@ -32,8 +33,8 @@ export type BundledIPyWidgets = ExternalIPyWidgets & { }; export type INotebookProps = { - CellSidebar?: (props: CellSidebarProps) => JSX.Element; - Toolbar?: (props: any) => JSX.Element; + CellSidebar?: (props: ICellSidebarProps) => JSX.Element; + Toolbar?: (props: INotebookToolbarProps) => JSX.Element; cellMetadataPanel: boolean; cellSidebarMargin: number; height?: string; @@ -77,117 +78,132 @@ export const Notebook = (props: INotebookProps) => { const [id, _] = useState(props.id ?? newUuid()); const [adapter, setAdapter] = useState(); const kernel = props.kernel ?? defaultKernel; +// const notebook = notebookStore.selectNotebook(id); const portals = notebookStore.selectNotebookPortals(id); - const createAdapter = () => { - if (id && serviceManager && kernelManager && kernel) { - kernel.ready.then(() => { - const adapter = new NotebookAdapter( - { - ...props, - id, - lite: lite || props.lite, - kernel, - serviceManager: serviceManager ?? props.serviceManager, - }, - ); - setAdapter(adapter); - notebookStore.update({ + const createAdapter = (kernel: Kernel) => { + kernel.ready.then(() => { + const adapter = new NotebookAdapter( + { + ...props, id, - partialState: { adapter: adapter } + lite: lite || props.lite, + kernel, + serviceManager: serviceManager ?? props.serviceManager, + }, + ); + setAdapter(adapter); + notebookStore.update({ + id, + state: { 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 + ); + 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 }, + }); + } + }); + } + 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.serviceManager.ready.then(() => { - if (!readonly) { - const activeCell = adapter.notebookPanel!.content.activeCell; - if (activeCell) { + */ + adapter.notebookPanel?.content.activeCellChanged.connect( + (_, cellModel) => { + if (cellModel === null) { notebookStore.activeCellChange({ id, - cellModel: activeCell, + cellModel: undefined, }); - } - const activeCellChanged$ = asObservable( - adapter.notebookPanel!.content.activeCellChanged - ); - activeCellChanged$.subscribe((cellModel: Cell) => { + } else { 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 }, - }); - } - }); - } - 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 }); - } - ); - }); + } + ); + adapter.notebookPanel?.sessionContext.statusChanged.connect( + (_, kernelStatus) => { + notebookStore.changeKernelStatus({ id, kernelStatus }); + } + ); }); - } + }); }; + const clearAdapter = () => { + adapter?.dispose(); + notebookStore.setPortalDisplay({ id, portalDisplay: undefined }); + notebookStore.dispose(id); + setAdapter(undefined); + } useEffect(() => { - /* - if (adapter) { - adapter.dispose(); + if (id && serviceManager && kernelManager && kernel) { + createAdapter(kernel); } - */ - createAdapter(); return () => { -// adapter?.dispose(); - notebookStore.setPortalDisplay({ id, portalDisplay: undefined }); - notebookStore.dispose(id); + clearAdapter(); }; - }, [id, serviceManager, kernelManager, kernel, path, lite, readonly]); + }, [id, serviceManager, kernelManager, kernel, lite]); useEffect(() => { if (adapter && nbformat) { adapter.setNbformat(nbformat); } - }, [nbformat]); + return () => { + clearAdapter(); + }; + }, [adapter, nbformat]); + useEffect(() => { + if (adapter) { + } + return () => { + clearAdapter(); + }; + }, [adapter, path]); + useEffect(() => { + if (adapter) { + adapter.setReadonly(readonly); + } + }, [adapter, readonly]); return ( -
- {Toolbar && } + {Toolbar && } { }, }} > - <>{portals?.map((portal: React.ReactPortal) => portal)} - {adapter && {adapter.panel}} + <> + {portals?.map((portal: React.ReactPortal) => portal)} + + + {adapter && {adapter.panel}} + -
+ ); }; diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 16402ac3..0497253b 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -356,7 +356,7 @@ export class NotebookAdapter { this._notebookPanel!.sessionContext.kernelChanged.connect( ( - sender: any, + _: any, args: IChangedArgs< JupyterKernel.IKernelConnection | null, JupyterKernel.IKernelConnection | null, @@ -503,6 +503,13 @@ export class NotebookAdapter { } } + setReadonly(readonly: boolean) { + if (this._readonly !== readonly) { + this._readonly = readonly; + Array.from(this._context?.model.cells!).forEach(cell => cell.setMetadata('editable', !readonly)); + } + } + setDefaultCellType = (cellType: CellType) => { this._notebookPanel!.content!.notebookConfig!.defaultCell! = cellType; }; diff --git a/packages/react/src/components/notebook/NotebookState.ts b/packages/react/src/components/notebook/NotebookState.ts index ed36cfb7..b12d88c4 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,7 +204,7 @@ export const notebookStore = createStore((set, get) => ({ set((state: NotebookState) => ({ notebooks })); } }, - kernelStatusChanged: (kernelStatusId: KernelStatusMutation) => { + changeKernelStatus: (kernelStatusId: KernelStatusMutation) => { const notebooks = get().notebooks; const notebook = notebooks.get(kernelStatusId.id); if (notebook) { 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/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/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..129aa52e 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 CellSidebarNew = (props: ICellSidebarProps) => { const { notebookId, cellId } = props; const notebookStore = useNotebookStore(); const [visible, setVisible] = useState(false); 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/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/index.ts b/packages/react/src/components/notebook/index.ts index b05b46dd..c7f501a3 100644 --- a/packages/react/src/components/notebook/index.ts +++ b/packages/react/src/components/notebook/index.ts @@ -12,3 +12,4 @@ export * from './cell'; export * from './content'; export * from './marked'; export * from './model'; +export * from './toolbar'; 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/examples/Bokeh.tsx b/packages/react/src/examples/Bokeh.tsx index 8909751a..601815f2 100644 --- a/packages/react/src/examples/Bokeh.tsx +++ b/packages/react/src/examples/Bokeh.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; const Bokeh = () => ( diff --git a/packages/react/src/examples/Bqplot.tsx b/packages/react/src/examples/Bqplot.tsx index 37cdb507..20354956 100644 --- a/packages/react/src/examples/Bqplot.tsx +++ b/packages/react/src/examples/Bqplot.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; const Bqplot = () => ( diff --git a/packages/react/src/examples/Dashboard.tsx b/packages/react/src/examples/Dashboard.tsx index d0b7ccbd..660ad04d 100644 --- a/packages/react/src/examples/Dashboard.tsx +++ b/packages/react/src/examples/Dashboard.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExample.ipynb.json'; diff --git a/packages/react/src/examples/Deno.tsx b/packages/react/src/examples/Deno.tsx index 21ef10e9..f358327a 100644 --- a/packages/react/src/examples/Deno.tsx +++ b/packages/react/src/examples/Deno.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import Jupyter from '../jupyter/Jupyter'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +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 d1e9fbb8..438222ac 100644 --- a/packages/react/src/examples/GeoJson.tsx +++ b/packages/react/src/examples/GeoJson.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as geojsonRenderer } from '@jupyterlab/geojson-extension'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const GeoJson = () => ( diff --git a/packages/react/src/examples/IPyLeaflet.tsx b/packages/react/src/examples/IPyLeaflet.tsx index 93ed03c8..d20d31ca 100644 --- a/packages/react/src/examples/IPyLeaflet.tsx +++ b/packages/react/src/examples/IPyLeaflet.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; const IPyLeaflet = () => ( diff --git a/packages/react/src/examples/IPyReact.tsx b/packages/react/src/examples/IPyReact.tsx index 0cfa3c67..b3ad12ad 100644 --- a/packages/react/src/examples/IPyReact.tsx +++ b/packages/react/src/examples/IPyReact.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; const IPyReact = () => ( diff --git a/packages/react/src/examples/IPyWidgets.tsx b/packages/react/src/examples/IPyWidgets.tsx index ee60e6c7..65e9b67a 100644 --- a/packages/react/src/examples/IPyWidgets.tsx +++ b/packages/react/src/examples/IPyWidgets.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExample.ipynb.json'; diff --git a/packages/react/src/examples/IPyWidgetsWithState.tsx b/packages/react/src/examples/IPyWidgetsWithState.tsx index b608d5bc..9b4c4824 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsWithState.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExampleWithState.ipynb.json'; diff --git a/packages/react/src/examples/JupyterLabApp.tsx b/packages/react/src/examples/JupyterLabApp.tsx index fd0f9d4c..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'; diff --git a/packages/react/src/examples/Matplotlib.tsx b/packages/react/src/examples/Matplotlib.tsx index 2ab94a94..a85598f9 100644 --- a/packages/react/src/examples/Matplotlib.tsx +++ b/packages/react/src/examples/Matplotlib.tsx @@ -9,7 +9,7 @@ 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 NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/Matplotlib.ipynb.json'; diff --git a/packages/react/src/examples/Notebook.tsx b/packages/react/src/examples/Notebook.tsx index 5ccdec5e..b8a09f46 100644 --- a/packages/react/src/examples/Notebook.tsx +++ b/packages/react/src/examples/Notebook.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import Jupyter from '../jupyter/Jupyter'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; diff --git a/packages/react/src/examples/NotebookCellSidebar.tsx b/packages/react/src/examples/NotebookCellSidebar.tsx index 7898d13b..43881f32 100644 --- a/packages/react/src/examples/NotebookCellSidebar.tsx +++ b/packages/react/src/examples/NotebookCellSidebar.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebarSource from './sidebars/CellSidebarSource'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; diff --git a/packages/react/src/examples/NotebookColorMode.tsx b/packages/react/src/examples/NotebookColorMode.tsx index 349e8e1f..4b11a27a 100644 --- a/packages/react/src/examples/NotebookColorMode.tsx +++ b/packages/react/src/examples/NotebookColorMode.tsx @@ -11,7 +11,7 @@ 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 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/NotebookInit.tsx b/packages/react/src/examples/NotebookInit.tsx index 8de181ef..bf81cc63 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/NotebookLite.tsx b/packages/react/src/examples/NotebookLite.tsx index e5f34896..a97c1d7e 100644 --- a/packages/react/src/examples/NotebookLite.tsx +++ b/packages/react/src/examples/NotebookLite.tsx @@ -9,7 +9,7 @@ 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 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/NotebookEvolving.tsx b/packages/react/src/examples/NotebookMutations.tsx similarity index 55% rename from packages/react/src/examples/NotebookEvolving.tsx rename to packages/react/src/examples/NotebookMutations.tsx index 47b91dff..6c9b0a05 100644 --- a/packages/react/src/examples/NotebookEvolving.tsx +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -8,21 +8,22 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager } from '@jupyterlab/services'; -import { SegmentedControl } from '@primer/react'; -import { JupyterServiceManagerLess } from '../jupyter'; -import { createServerSettings } from '../jupyter/JupyterContext'; -import { getJupyterServerUrl, getJupyterServerToken } from '../jupyter/JupyterConfig'; +import { Box, SegmentedControl } from '@primer/react'; +import { getJupyterServerUrl, getJupyterServerToken, createServerSettings, JupyterServiceManagerLess } from '../jupyter'; +import { Notebook } from '../components/notebook/Notebook'; +import { useNotebookStore } from './../components'; import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import nbformat1 from './notebooks/NotebookExample1.ipynb.json'; -import nbformat2 from './notebooks/NotebookExample2.ipynb.json'; +import nbformat from './notebooks/NotebookExample1.ipynb.json'; -const NotebookEvolving = () => { +const NOTEBOOK_ID = 'notebook-mutations-id'; + +const NotebookMutations = () => { const [index, setIndex] = useState(0); const [readonly, setReadonly] = useState(true); const [lite, setLite] = useState(false); - const [nbformat, setNbformat] = useState(nbformat1); + const notebookStore = useNotebookStore(); + const notebook = notebookStore.selectNotebook(NOTEBOOK_ID); const [serviceManager, setServiceManager] = useState(new JupyterServiceManagerLess()); const changeIndex = (index: number) => { setIndex(index); @@ -30,21 +31,18 @@ const NotebookEvolving = () => { case 0: { setReadonly(true); setLite(false); - setNbformat(nbformat1) setServiceManager(new JupyterServiceManagerLess()); break; } case 1: { setReadonly(false); setLite(true); - setNbformat(nbformat2) setServiceManager(new JupyterServiceManagerLess()); break; } case 2: { setReadonly(false); setLite(false); - setNbformat(nbformat2) const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); const serviceManager = new ServiceManager({ serverSettings }); setServiceManager(serviceManager); @@ -54,17 +52,24 @@ const NotebookEvolving = () => { } return ( - changeIndex(index)} aria-label="jupyter-react-example"> - Readonly - Browser Kernel - CPU Kernel - + + + changeIndex(index)} aria-label="jupyter-react-example"> + Readonly + Browser Kernel + CPU Kernel + + + + Lite: {String(notebook?.adapter?.id)} + + @@ -75,4 +80,4 @@ const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); -root.render(); +root.render(); diff --git a/packages/react/src/examples/NotebookNbFormat.tsx b/packages/react/src/examples/NotebookNbFormat.tsx index 864ad9a6..2f4b9729 100644 --- a/packages/react/src/examples/NotebookNbFormat.tsx +++ b/packages/react/src/examples/NotebookNbFormat.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +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/NotebookNoContext.tsx b/packages/react/src/examples/NotebookNoContext.tsx index 1f076902..c43e866c 100644 --- a/packages/react/src/examples/NotebookNoContext.tsx +++ b/packages/react/src/examples/NotebookNoContext.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; diff --git a/packages/react/src/examples/NotebookNoPrimer.tsx b/packages/react/src/examples/NotebookNoPrimer.tsx index 50d8397f..52693eeb 100644 --- a/packages/react/src/examples/NotebookNoPrimer.tsx +++ b/packages/react/src/examples/NotebookNoPrimer.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; import JupyterLabCss from '../jupyter/lab/JupyterLabCss'; diff --git a/packages/react/src/examples/NotebookPath.tsx b/packages/react/src/examples/NotebookPath.tsx index 2772f9f9..ecf19fc3 100644 --- a/packages/react/src/examples/NotebookPath.tsx +++ b/packages/react/src/examples/NotebookPath.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; diff --git a/packages/react/src/examples/NotebookReadonly.tsx b/packages/react/src/examples/NotebookReadonly.tsx index c9804b5a..29df10c4 100644 --- a/packages/react/src/examples/NotebookReadonly.tsx +++ b/packages/react/src/examples/NotebookReadonly.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +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/NotebookServiceManager.tsx b/packages/react/src/examples/NotebookServiceManager.tsx index 8791f35f..c63858f5 100644 --- a/packages/react/src/examples/NotebookServiceManager.tsx +++ b/packages/react/src/examples/NotebookServiceManager.tsx @@ -14,7 +14,7 @@ import { getJupyterServerUrl, getJupyterServerToken } from '../jupyter/JupyterCo import { Kernel } from '../jupyter/kernel/Kernel'; import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +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/NotebookSkeleton.tsx b/packages/react/src/examples/NotebookSkeleton.tsx index d9671b0f..330374cf 100644 --- a/packages/react/src/examples/NotebookSkeleton.tsx +++ b/packages/react/src/examples/NotebookSkeleton.tsx @@ -8,7 +8,7 @@ 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 NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; diff --git a/packages/react/src/examples/NotebookTheme.tsx b/packages/react/src/examples/NotebookTheme.tsx index 4ee37605..e8c99f1a 100644 --- a/packages/react/src/examples/NotebookTheme.tsx +++ b/packages/react/src/examples/NotebookTheme.tsx @@ -12,7 +12,7 @@ import { INotebookContent } from '@jupyterlab/nbformat'; import Jupyter from '../jupyter/Jupyter'; import { jupyterTheme } from '../themes/JupyterPrimerTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +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 index e80c9d92..cb916497 100644 --- a/packages/react/src/examples/NotebookThemeColorMode.tsx +++ b/packages/react/src/examples/NotebookThemeColorMode.tsx @@ -13,7 +13,7 @@ import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; import Jupyter from '../jupyter/Jupyter'; import { jupyterTheme } from '../themes/JupyterPrimerTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +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/NotebookUrl.tsx b/packages/react/src/examples/NotebookUrl.tsx index e51807aa..a2bf6e29 100644 --- a/packages/react/src/examples/NotebookUrl.tsx +++ b/packages/react/src/examples/NotebookUrl.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; const NOTEBOOK_ID = 'notebook-id'; diff --git a/packages/react/src/examples/ObservableHQ.tsx b/packages/react/src/examples/ObservableHQ.tsx index 12fd6508..1c0e76f4 100644 --- a/packages/react/src/examples/ObservableHQ.tsx +++ b/packages/react/src/examples/ObservableHQ.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import Jupyter from '../jupyter/Jupyter'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; const ObservableHQ = () => ( diff --git a/packages/react/src/examples/Panel.tsx b/packages/react/src/examples/Panel.tsx index db2c1e0c..bd8b5063 100644 --- a/packages/react/src/examples/Panel.tsx +++ b/packages/react/src/examples/Panel.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const Panel = () => { diff --git a/packages/react/src/examples/Plotly.tsx b/packages/react/src/examples/Plotly.tsx index af7c9390..65d2ee16 100644 --- a/packages/react/src/examples/Plotly.tsx +++ b/packages/react/src/examples/Plotly.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; const Plotly = () => ( diff --git a/packages/react/src/examples/Vega.tsx b/packages/react/src/examples/Vega.tsx index 5eb69dac..dc93ce67 100644 --- a/packages/react/src/examples/Vega.tsx +++ b/packages/react/src/examples/Vega.tsx @@ -8,7 +8,7 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as vega3Renderer } from '@jupyterlab/vega3-extension'; import JupyterReactTheme from '../themes/JupyterReactTheme'; import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './toolbars/NotebookToolbar'; +import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; const Vega = () => ( 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/jupyter/JupyterContext.tsx b/packages/react/src/jupyter/JupyterContext.tsx index 8e307d84..5913f0ff 100644 --- a/packages/react/src/jupyter/JupyterContext.tsx +++ b/packages/react/src/jupyter/JupyterContext.tsx @@ -187,10 +187,12 @@ const JupyterProvider = JupyterContext.Provider; 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 Jupyter context, just return the that context. + // 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 Jupyter context, so create it + // from the store based on the provided props. const { kernel, kernelIsLoading, diff --git a/packages/react/src/jupyter/lab/index.ts b/packages/react/src/jupyter/lab/index.ts index 731d3526..5151d6f3 100644 --- a/packages/react/src/jupyter/lab/index.ts +++ b/packages/react/src/jupyter/lab/index.ts @@ -4,117 +4,7 @@ * 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 './JupyterLabColorMode'; +export * from './JupyterLabCss'; +export * from './JupyterLabCssImports'; +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/webpack.config.js b/packages/react/webpack.config.js index 3fb771e4..cc7be2c9 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -43,9 +43,9 @@ const ENTRY = // './src/examples/Matplotlib'; // './src/examples/Notebook'; // './src/examples/NotebookColorMode'; - './src/examples/NotebookEvolving'; // './src/examples/NotebookKernelChange'; // './src/examples/NotebookLite'; + './src/examples/NotebookMutations'; // './src/examples/NotebookNbFormat'; // './src/examples/NotebookNbFormatChange'; // './src/examples/NotebookNoContext'; From d9ade164371539cbe1f9a93d4af37a5a51961319 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Thu, 12 Sep 2024 10:49:23 +0200 Subject: [PATCH 07/14] lint --- .../react/src/components/lumino/Lumino.tsx | 2 + .../src/components/notebook/Notebook.tsx | 19 ++---- .../components/notebook/NotebookAdapter.ts | 40 ++++++++---- .../src/components/notebook/NotebookState.ts | 13 ++-- .../cell/sidebar/CellSidebarButton.tsx | 4 +- packages/react/src/examples/Bokeh.tsx | 8 +-- packages/react/src/examples/Bqplot.tsx | 8 +-- packages/react/src/examples/CellLite.tsx | 2 +- packages/react/src/examples/Cells.tsx | 2 +- packages/react/src/examples/CellsExecute.tsx | 2 +- packages/react/src/examples/Console.tsx | 2 +- packages/react/src/examples/ConsoleLite.tsx | 2 +- packages/react/src/examples/Dashboard.tsx | 8 +-- packages/react/src/examples/Deno.tsx | 10 +-- packages/react/src/examples/FileBrowser.tsx | 2 +- packages/react/src/examples/GeoJson.tsx | 10 +-- packages/react/src/examples/IPyLeaflet.tsx | 8 +-- packages/react/src/examples/IPyReact.tsx | 8 +-- packages/react/src/examples/IPyWidgets.tsx | 8 +-- .../src/examples/IPyWidgetsWithState.tsx | 8 +-- .../react/src/examples/JupyterContext.tsx | 10 +-- .../src/examples/JupyterLabAppHeadless.tsx | 2 +- .../JupyterLabAppHeadlessServerless.tsx | 2 +- .../examples/JupyterLabAppServiceManager.tsx | 2 +- packages/react/src/examples/KernelExecute.tsx | 2 +- .../react/src/examples/KernelExecutor.tsx | 7 +- packages/react/src/examples/Kernels.tsx | 2 +- packages/react/src/examples/Matplotlib.tsx | 8 +-- packages/react/src/examples/Notebook.tsx | 10 +-- .../src/examples/NotebookCellSidebar.tsx | 6 +- .../react/src/examples/NotebookColorMode.tsx | 8 +-- .../src/examples/NotebookExternalContent.tsx | 6 +- packages/react/src/examples/NotebookInit.tsx | 2 +- .../src/examples/NotebookKernelChange.tsx | 64 +++++++++++++------ packages/react/src/examples/NotebookLite.tsx | 8 +-- .../react/src/examples/NotebookMutations.tsx | 19 ++++-- .../react/src/examples/NotebookNbFormat.tsx | 33 ---------- .../src/examples/NotebookNbFormatChange.tsx | 58 ----------------- .../react/src/examples/NotebookNoContext.tsx | 8 +-- .../react/src/examples/NotebookNoPrimer.tsx | 8 +-- packages/react/src/examples/NotebookPath.tsx | 10 +-- .../react/src/examples/NotebookPathChange.tsx | 7 +- .../react/src/examples/NotebookReadonly.tsx | 8 +-- .../src/examples/NotebookServiceManager.tsx | 8 +-- .../react/src/examples/NotebookSkeleton.tsx | 10 +-- packages/react/src/examples/NotebookTheme.tsx | 8 +-- .../src/examples/NotebookThemeColorMode.tsx | 8 +-- .../react/src/examples/NotebookUnmount.tsx | 6 +- packages/react/src/examples/NotebookUrl.tsx | 10 +-- packages/react/src/examples/ObservableHQ.tsx | 8 +-- .../react/src/examples/OutputIPyWidgets.tsx | 2 +- packages/react/src/examples/Outputs.tsx | 2 +- packages/react/src/examples/Panel.tsx | 10 +-- packages/react/src/examples/Plotly.tsx | 8 +-- .../react/src/examples/RunningSessions.tsx | 2 +- packages/react/src/examples/Terminal.tsx | 2 +- packages/react/src/examples/Vega.tsx | 10 +-- packages/react/src/examples/Viewer.tsx | 2 +- packages/react/src/jupyter/JupyterContext.tsx | 6 +- packages/react/webpack.config.js | 4 +- 60 files changed, 257 insertions(+), 305 deletions(-) delete mode 100644 packages/react/src/examples/NotebookNbFormat.tsx delete mode 100755 packages/react/src/examples/NotebookNbFormatChange.tsx diff --git a/packages/react/src/components/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index c9242a35..87ca3827 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -26,11 +26,13 @@ export const Lumino = (props: LuminoProps) => { } return () => { try { + /* unmountComponentAtNode(children.node); if (children.isAttached || children.node.isConnected) { children.dispose(); Widget.detach(children); } + */ } catch (e) { // no-op. // console.debug('Exception while detaching Lumino widget.', e); diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index 181c00e8..d4e5be78 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -14,11 +14,11 @@ import { ServiceManager } from '@jupyterlab/services'; import { useJupyter, Lite } from './../../jupyter/JupyterContext'; import { Kernel } from '../../jupyter/kernel/Kernel'; 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/Utils'; import { useNotebookStore } from './NotebookState'; -import { CellMetadataEditor } from './cell/metadata/CellMetadataEditor'; import { NotebookAdapter } from './NotebookAdapter'; import './Notebook.css'; @@ -164,34 +164,27 @@ export const Notebook = (props: INotebookProps) => { }); }); }; - const clearAdapter = () => { - adapter?.dispose(); - notebookStore.setPortalDisplay({ id, portalDisplay: undefined }); - notebookStore.dispose(id); - setAdapter(undefined); + const disposeAdapter = () => { + if (adapter) { + notebookStore.dispose(id); + } } useEffect(() => { if (id && serviceManager && kernelManager && kernel) { createAdapter(kernel); } return () => { - clearAdapter(); + disposeAdapter(); }; }, [id, serviceManager, kernelManager, kernel, lite]); useEffect(() => { if (adapter && nbformat) { adapter.setNbformat(nbformat); } - return () => { - clearAdapter(); - }; }, [adapter, nbformat]); useEffect(() => { if (adapter) { } - return () => { - clearAdapter(); - }; }, [adapter, path]); useEffect(() => { if (adapter) { diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 0497253b..60c60590 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -24,6 +24,7 @@ import { import { rendererFactory as jsonRendererFactory } from '@jupyterlab/json-extension'; import { rendererFactory as javascriptRendererFactory } from '@jupyterlab/javascript-extension'; import { + Notebook, NotebookPanel, NotebookWidgetFactory, NotebookTracker, @@ -51,6 +52,7 @@ 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 { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget'; import JupyterReactContentFactory from './content/JupyterReactContentFactory'; import JupyterReactNotebookModelFactory from './model/JupyterReactNotebookModelFactory'; import { INotebookProps } from './Notebook'; @@ -78,7 +80,7 @@ export class NotebookAdapter { private _serviceManager: ServiceManager.IManager; private _tracker?: NotebookTracker; private _id: string; - private _CellSidebar?: (props: any) => JSX.Element; + private _CellSidebar?: (props: ICellSidebarProps) => JSX.Element; constructor(props: INotebookProps) { this._id = props.id; @@ -450,10 +452,12 @@ export class NotebookAdapter { }); handler.editor = editor; notebookPanel.content.activeCellChanged.connect( - (sender: any, cell: Cell) => { - cell.ready.then(() => { - handler.editor = cell && cell.editor; - }); + (notebook: Notebook, cell: Cell | null) => { + if (cell) { + cell.ready.then(() => { + handler.editor = cell && cell.editor; + }); + } } ); completer.hide(); @@ -472,18 +476,30 @@ export class NotebookAdapter { return this._id; } - get notebookPanel(): NotebookPanel | undefined { - return this._notebookPanel; + get readonly(): boolean { + return this._readonly; } - get commands(): CommandRegistry { - return this._commandRegistry; + get lite(): Lite | undefined { + return this._lite; + } + + get kernel(): Kernel { + 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; } @@ -588,9 +604,9 @@ export class NotebookAdapter { dispose = () => { document.removeEventListener('keydown', this.notebookKeydownListener, true); - // this._boxPanel.dispose(); - // this._notebookPanel?.dispose(); - // this._context?.dispose(); +// this._notebookPanel?.dispose(); +// this._boxPanel.dispose(); +// this._context?.dispose(); }; } diff --git a/packages/react/src/components/notebook/NotebookState.ts b/packages/react/src/components/notebook/NotebookState.ts index b12d88c4..cfeac520 100644 --- a/packages/react/src/components/notebook/NotebookState.ts +++ b/packages/react/src/components/notebook/NotebookState.ts @@ -204,19 +204,19 @@ export const notebookStore = createStore((set, get) => ({ set((state: NotebookState) => ({ notebooks })); } }, - changeKernelStatus: (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 })); } }, @@ -229,6 +229,7 @@ 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){ diff --git a/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx b/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx index 129aa52e..556e74ab 100644 --- a/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx +++ b/packages/react/src/components/notebook/cell/sidebar/CellSidebarButton.tsx @@ -19,7 +19,7 @@ import useNotebookStore from '../../NotebookState'; import { DATALAYER_CELL_HEADER_CLASS } from './CellSidebarWidget'; -export const CellSidebarNew = (props: ICellSidebarProps) => { +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: ICellSidebarProps) => { ); }; -export default CellSidebarNew; +export default CellSidebarButton; diff --git a/packages/react/src/examples/Bokeh.tsx b/packages/react/src/examples/Bokeh.tsx index 601815f2..8511aed6 100644 --- a/packages/react/src/examples/Bokeh.tsx +++ b/packages/react/src/examples/Bokeh.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Bokeh = () => ( diff --git a/packages/react/src/examples/Bqplot.tsx b/packages/react/src/examples/Bqplot.tsx index 20354956..4875cba4 100644 --- a/packages/react/src/examples/Bqplot.tsx +++ b/packages/react/src/examples/Bqplot.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Bqplot = () => ( 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 fd95e8a8..8ce66996 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const div = document.createElement('div'); diff --git a/packages/react/src/examples/CellsExecute.tsx b/packages/react/src/examples/CellsExecute.tsx index 7ca6d2f8..0bfdd933 100644 --- a/packages/react/src/examples/CellsExecute.tsx +++ b/packages/react/src/examples/CellsExecute.tsx @@ -7,7 +7,7 @@ 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const CODE_CELL_1 = `import time diff --git a/packages/react/src/examples/Console.tsx b/packages/react/src/examples/Console.tsx index 1d0d3c3f..449dae21 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Console from '../components/console/Console'; const div = document.createElement('div'); 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 660ad04d..fb8db893 100644 --- a/packages/react/src/examples/Dashboard.tsx +++ b/packages/react/src/examples/Dashboard.tsx @@ -6,10 +6,10 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/Deno.tsx b/packages/react/src/examples/Deno.tsx index f358327a..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 './../components/notebook/toolbar/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 = () => ( ( @@ -18,7 +18,7 @@ const GeoJson = () => ( id="notebook-geojson-id" renderers={[geojsonRenderer]} height="calc(100vh - 2.6rem)" // (Height - Toolbar Height). - CellSidebar={CellSidebarNew} + CellSidebar={CellSidebarButton} Toolbar={NotebookToolbar} /> diff --git a/packages/react/src/examples/IPyLeaflet.tsx b/packages/react/src/examples/IPyLeaflet.tsx index d20d31ca..92994e02 100644 --- a/packages/react/src/examples/IPyLeaflet.tsx +++ b/packages/react/src/examples/IPyLeaflet.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const IPyLeaflet = () => ( diff --git a/packages/react/src/examples/IPyReact.tsx b/packages/react/src/examples/IPyReact.tsx index b3ad12ad..d045b920 100644 --- a/packages/react/src/examples/IPyReact.tsx +++ b/packages/react/src/examples/IPyReact.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const IPyReact = () => ( diff --git a/packages/react/src/examples/IPyWidgets.tsx b/packages/react/src/examples/IPyWidgets.tsx index 65e9b67a..c195cb2b 100644 --- a/packages/react/src/examples/IPyWidgets.tsx +++ b/packages/react/src/examples/IPyWidgets.tsx @@ -6,10 +6,10 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/IPyWidgetsWithState.tsx b/packages/react/src/examples/IPyWidgetsWithState.tsx index 9b4c4824..ebc49889 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsWithState.tsx @@ -6,10 +6,10 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/JupyterContext.tsx b/packages/react/src/examples/JupyterContext.tsx index 7cf381fd..b44f1377 100644 --- a/packages/react/src/examples/JupyterContext.tsx +++ b/packages/react/src/examples/JupyterContext.tsx @@ -8,17 +8,17 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { IOutput, INotebookContent } from '@jupyterlab/nbformat'; import { Box, Button, ButtonGroup, SegmentedControl } from '@primer/react'; -import Jupyter from '../jupyter/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'; @@ -208,7 +208,7 @@ const JuptyerContextExample = () => { id={NOTEBOOK_ID_3} height="300px" cellSidebarMargin={60} - CellSidebar={CellSidebarNew} + CellSidebar={CellSidebarButton} Toolbar={NotebookToolbar} />
diff --git a/packages/react/src/examples/JupyterLabAppHeadless.tsx b/packages/react/src/examples/JupyterLabAppHeadless.tsx index 51bfb8c9..41308eef 100644 --- a/packages/react/src/examples/JupyterLabAppHeadless.tsx +++ b/packages/react/src/examples/JupyterLabAppHeadless.tsx @@ -10,7 +10,7 @@ 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 JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; diff --git a/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx b/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx index 906713ac..2b4f942c 100644 --- a/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx +++ b/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx @@ -10,7 +10,7 @@ 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Lumino from '../components/lumino/Lumino'; import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; diff --git a/packages/react/src/examples/JupyterLabAppServiceManager.tsx b/packages/react/src/examples/JupyterLabAppServiceManager.tsx index f1eb3a9c..496de2ce 100644 --- a/packages/react/src/examples/JupyterLabAppServiceManager.tsx +++ b/packages/react/src/examples/JupyterLabAppServiceManager.tsx @@ -7,7 +7,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { NotebookPanel } from '@jupyterlab/notebook'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; diff --git a/packages/react/src/examples/KernelExecute.tsx b/packages/react/src/examples/KernelExecute.tsx index 93d940f6..ed3f8d81 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import KernelProgressBar from './../components/kernel/KernelProgressBar'; export const KernelExecuteView = () => { diff --git a/packages/react/src/examples/KernelExecutor.tsx b/packages/react/src/examples/KernelExecutor.tsx index be4f355a..86ecec9b 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/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): diff --git a/packages/react/src/examples/Kernels.tsx b/packages/react/src/examples/Kernels.tsx index 31399617..f10dec85 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { KERNEL_STATES, diff --git a/packages/react/src/examples/Matplotlib.tsx b/packages/react/src/examples/Matplotlib.tsx index a85598f9..abb22efe 100644 --- a/packages/react/src/examples/Matplotlib.tsx +++ b/packages/react/src/examples/Matplotlib.tsx @@ -6,11 +6,11 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import JupyterLabCss from '../jupyter/lab/JupyterLabCss'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +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'; diff --git a/packages/react/src/examples/Notebook.tsx b/packages/react/src/examples/Notebook.tsx index b8a09f46..8f933e78 100644 --- a/packages/react/src/examples/Notebook.tsx +++ b/packages/react/src/examples/Notebook.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 './../components/notebook/toolbar/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'; @@ -26,7 +26,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/NotebookCellSidebar.tsx b/packages/react/src/examples/NotebookCellSidebar.tsx index 43881f32..04cec7b0 100644 --- a/packages/react/src/examples/NotebookCellSidebar.tsx +++ b/packages/react/src/examples/NotebookCellSidebar.tsx @@ -6,9 +6,9 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/NotebookColorMode.tsx b/packages/react/src/examples/NotebookColorMode.tsx index 4b11a27a..6b4a59ad 100644 --- a/packages/react/src/examples/NotebookColorMode.tsx +++ b/packages/react/src/examples/NotebookColorMode.tsx @@ -8,11 +8,11 @@ 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 { Jupyter } from '../jupyter/Jupyter'; import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +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/NotebookExternalContent.tsx b/packages/react/src/examples/NotebookExternalContent.tsx index 2fac2e65..197ef2c6 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 JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/NotebookInit.tsx b/packages/react/src/examples/NotebookInit.tsx index bf81cc63..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 './../components/notebook/toolbar/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 a97c1d7e..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 './../components/notebook/toolbar/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 index 6c9b0a05..d6cc3c12 100644 --- a/packages/react/src/examples/NotebookMutations.tsx +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -12,7 +12,7 @@ import { Box, SegmentedControl } from '@primer/react'; import { getJupyterServerUrl, getJupyterServerToken, createServerSettings, JupyterServiceManagerLess } from '../jupyter'; import { Notebook } from '../components/notebook/Notebook'; import { useNotebookStore } from './../components'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; @@ -31,21 +31,23 @@ const NotebookMutations = () => { case 0: { setReadonly(true); setLite(false); - setServiceManager(new JupyterServiceManagerLess()); +// setServiceManager(new JupyterServiceManagerLess()); break; } case 1: { setReadonly(false); setLite(true); - setServiceManager(new JupyterServiceManagerLess()); +// setServiceManager(new JupyterServiceManagerLess()); break; } case 2: { setReadonly(false); setLite(false); + /* const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); const serviceManager = new ServiceManager({ serverSettings }); setServiceManager(serviceManager); + */ break; } } @@ -61,7 +63,16 @@ const NotebookMutations = () => {
- Lite: {String(notebook?.adapter?.id)} + Readonly: {String(notebook?.adapter?.readonly)} + + + Lite: {String(notebook?.adapter?.lite)} + + + Kernel ID: {notebook?.adapter?.kernel.id} + + + Service Manager: {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/NotebookNbFormatChange.tsx b/packages/react/src/examples/NotebookNbFormatChange.tsx deleted file mode 100755 index b9978497..00000000 --- a/packages/react/src/examples/NotebookNbFormatChange.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2021-2023 Datalayer, Inc. - * - * MIT License - */ - -import { useState } from 'react'; -import { createRoot } from 'react-dom/client'; -import { Box, Button, ButtonGroup } from '@primer/react'; -import { INotebookContent } from '@jupyterlab/nbformat'; -import JupyterReactTheme from '../themes/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'; -import nbformat2 from './notebooks/NotebookExample2.ipynb.json'; - -const NOTEBOOK_ID = 'notebook-model-change-id'; - -const NotebookNbFormatChange = () => { - const notebookStore = useNotebookStore(); - const [nbformat, setNbformat] = useState(nbformat1); - const changeModel = () => { - console.log( - 'Notebook NbFormat from store', - notebookStore.notebooks.get(NOTEBOOK_ID)?.model?.toJSON() as INotebookContent - ); - nbformat === nbformat1 ? setNbformat(nbformat2) : setNbformat(nbformat1); - }; - return ( - <> - - - - - - - - ); -}; - -const div = document.createElement('div'); -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 c43e866c..863bc64e 100644 --- a/packages/react/src/examples/NotebookNoContext.tsx +++ b/packages/react/src/examples/NotebookNoContext.tsx @@ -6,9 +6,9 @@ import { createRoot } from 'react-dom/client'; import { JupyterReactTheme } from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; +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'; @@ -25,7 +25,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/NotebookNoPrimer.tsx b/packages/react/src/examples/NotebookNoPrimer.tsx index 52693eeb..d61ac2d8 100644 --- a/packages/react/src/examples/NotebookNoPrimer.tsx +++ b/packages/react/src/examples/NotebookNoPrimer.tsx @@ -5,9 +5,9 @@ */ import { createRoot } from 'react-dom/client'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebarButton } from '../components/notebook/cell/sidebar/CellSidebarButton'; import JupyterLabCss from '../jupyter/lab/JupyterLabCss'; 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/NotebookPath.tsx b/packages/react/src/examples/NotebookPath.tsx index ecf19fc3..840d8aa1 100644 --- a/packages/react/src/examples/NotebookPath.tsx +++ b/packages/react/src/examples/NotebookPath.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../themes/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'; @@ -19,7 +19,7 @@ const NotebookPath = () => ( id={NOTEBOOK_ID} height="calc(100vh - 2.6rem)" // (Height - Toolbar Height). cellSidebarMargin={60} - CellSidebar={CellSidebarNew} + CellSidebar={CellSidebarButton} Toolbar={NotebookToolbar} /> diff --git a/packages/react/src/examples/NotebookPathChange.tsx b/packages/react/src/examples/NotebookPathChange.tsx index 9be0774e..f1ad3c07 100755 --- a/packages/react/src/examples/NotebookPathChange.tsx +++ b/packages/react/src/examples/NotebookPathChange.tsx @@ -7,11 +7,12 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button, Text } from '@primer/react'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/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 = () => { diff --git a/packages/react/src/examples/NotebookReadonly.tsx b/packages/react/src/examples/NotebookReadonly.tsx index 29df10c4..1c5f9dc5 100644 --- a/packages/react/src/examples/NotebookReadonly.tsx +++ b/packages/react/src/examples/NotebookReadonly.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/NotebookServiceManager.tsx b/packages/react/src/examples/NotebookServiceManager.tsx index c63858f5..d60236ed 100644 --- a/packages/react/src/examples/NotebookServiceManager.tsx +++ b/packages/react/src/examples/NotebookServiceManager.tsx @@ -8,14 +8,14 @@ import { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager } from '@jupyterlab/services'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import { createServerSettings } from '../jupyter/JupyterContext'; import { getJupyterServerUrl, getJupyterServerToken } from '../jupyter/JupyterConfig'; import { Kernel } from '../jupyter/kernel/Kernel'; import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +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/NotebookSkeleton.tsx b/packages/react/src/examples/NotebookSkeleton.tsx index 330374cf..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 './../components/notebook/toolbar/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 e8c99f1a..5934bdc6 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 { Jupyter } from '../jupyter/Jupyter'; import { jupyterTheme } from '../themes/JupyterPrimerTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +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 index cb916497..82ebcb3a 100644 --- a/packages/react/src/examples/NotebookThemeColorMode.tsx +++ b/packages/react/src/examples/NotebookThemeColorMode.tsx @@ -10,11 +10,11 @@ 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 { Jupyter } from '../jupyter/Jupyter'; import { jupyterTheme } from '../themes/JupyterPrimerTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +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/NotebookUnmount.tsx b/packages/react/src/examples/NotebookUnmount.tsx index 392bfebf..678f6666 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/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'; diff --git a/packages/react/src/examples/NotebookUrl.tsx b/packages/react/src/examples/NotebookUrl.tsx index a2bf6e29..4d95b200 100644 --- a/packages/react/src/examples/NotebookUrl.tsx +++ b/packages/react/src/examples/NotebookUrl.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../themes/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'; @@ -23,7 +23,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/ObservableHQ.tsx b/packages/react/src/examples/ObservableHQ.tsx index 1c0e76f4..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 './../components/notebook/toolbar/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 c68bf6d3..1619fd66 100755 --- a/packages/react/src/examples/OutputIPyWidgets.tsx +++ b/packages/react/src/examples/OutputIPyWidgets.tsx @@ -6,7 +6,7 @@ import { render } from 'react-dom'; import { Text } from '@primer/react'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import OutputIPyWidgets from '../components/output/OutputIPyWidgets'; import { view, state } from './notebooks/OutputIPyWidgetsExample'; diff --git a/packages/react/src/examples/Outputs.tsx b/packages/react/src/examples/Outputs.tsx index 4e8cb7d2..c6229c27 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 JupyterReactTheme from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; import Output from '../components/output/Output'; import { cellSourceAsString } from './../utils/Utils'; diff --git a/packages/react/src/examples/Panel.tsx b/packages/react/src/examples/Panel.tsx index bd8b5063..6f7b4a00 100644 --- a/packages/react/src/examples/Panel.tsx +++ b/packages/react/src/examples/Panel.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../themes/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 ( @@ -17,7 +17,7 @@ const Panel = () => { path="panel.ipynb" id="notebook-panel-id" height="calc(100vh - 2.6rem)" // (Height - Toolbar Height). - CellSidebar={CellSidebarNew} + CellSidebar={CellSidebarButton} Toolbar={NotebookToolbar} /> diff --git a/packages/react/src/examples/Plotly.tsx b/packages/react/src/examples/Plotly.tsx index 65d2ee16..84b5ae33 100644 --- a/packages/react/src/examples/Plotly.tsx +++ b/packages/react/src/examples/Plotly.tsx @@ -5,10 +5,10 @@ */ import { createRoot } from 'react-dom/client'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebar from '../components/notebook/cell/sidebar/CellSidebar'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; const Plotly = () => ( diff --git a/packages/react/src/examples/RunningSessions.tsx b/packages/react/src/examples/RunningSessions.tsx index d7e2d6a0..781ab972 100644 --- a/packages/react/src/examples/RunningSessions.tsx +++ b/packages/react/src/examples/RunningSessions.tsx @@ -9,7 +9,7 @@ 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 Lumino from '../components/lumino/Lumino'; import { ColorMode } from '../jupyter/lab/JupyterLabColorMode'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; diff --git a/packages/react/src/examples/Terminal.tsx b/packages/react/src/examples/Terminal.tsx index f31602ac..6ed60c47 100644 --- a/packages/react/src/examples/Terminal.tsx +++ b/packages/react/src/examples/Terminal.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import Jupyter from '../jupyter/Jupyter'; +import { Jupyter } from '../jupyter/Jupyter'; import Terminal from '../components/terminal/Terminal'; const div = document.createElement('div'); diff --git a/packages/react/src/examples/Vega.tsx b/packages/react/src/examples/Vega.tsx index dc93ce67..4e4ddbe0 100644 --- a/packages/react/src/examples/Vega.tsx +++ b/packages/react/src/examples/Vega.tsx @@ -6,10 +6,10 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as vega3Renderer } from '@jupyterlab/vega3-extension'; -import JupyterReactTheme from '../themes/JupyterReactTheme'; -import Notebook from '../components/notebook/Notebook'; -import NotebookToolbar from './../components/notebook/toolbar/NotebookToolbar'; -import CellSidebarNew from '../components/notebook/cell/sidebar/CellSidebarButton'; +import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { Notebook } from '../components/notebook/Notebook'; +import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; +import CellSidebarButton from '../components/notebook/cell/sidebar/CellSidebarButton'; const Vega = () => ( @@ -18,7 +18,7 @@ const Vega = () => ( id="notebook-vega-id" renderers={[vega3Renderer]} height="calc(100vh - 2.6rem)" // (Height - Toolbar Height). - CellSidebar={CellSidebarNew} + CellSidebar={CellSidebarButton} Toolbar={NotebookToolbar} /> 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/jupyter/JupyterContext.tsx b/packages/react/src/jupyter/JupyterContext.tsx index 5913f0ff..33d8ae51 100644 --- a/packages/react/src/jupyter/JupyterContext.tsx +++ b/packages/react/src/jupyter/JupyterContext.tsx @@ -194,20 +194,20 @@ export const useJupyter = (props?: JupyterPropsType): JupyterContextType => { // We are not within a Jupyter context, so create it // 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, diff --git a/packages/react/webpack.config.js b/packages/react/webpack.config.js index cc7be2c9..efe047cb 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -46,8 +46,8 @@ const ENTRY = // './src/examples/NotebookKernelChange'; // './src/examples/NotebookLite'; './src/examples/NotebookMutations'; - // './src/examples/NotebookNbFormat'; - // './src/examples/NotebookNbFormatChange'; + // './src/examples/NotebookNbformat'; + // './src/examples/NotebookNbformatChange'; // './src/examples/NotebookNoContext'; // './src/examples/NotebookNoPrimer'; // './src/examples/NotebookReadonly'; From a5f557dcd52f79b834b33a9c2b5818cdc1d44e11 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Thu, 12 Sep 2024 11:01:44 +0200 Subject: [PATCH 08/14] chore: colormode --- .../components/jupyterlab/JupyterLabApp.tsx | 4 +- .../jupyterlab/JupyterLabAppCss.tsx | 4 +- .../react/src/components/lumino/Lumino.tsx | 2 +- .../src/components/terminal/Terminal.tsx | 4 +- .../components/terminal/TerminalAdapter.ts | 4 +- packages/react/src/examples/Bokeh.tsx | 2 +- packages/react/src/examples/Bqplot.tsx | 2 +- packages/react/src/examples/Cells.tsx | 2 +- packages/react/src/examples/CellsExecute.tsx | 2 +- packages/react/src/examples/Console.tsx | 2 +- packages/react/src/examples/Dashboard.tsx | 2 +- packages/react/src/examples/FileBrowser.tsx | 2 +- packages/react/src/examples/GeoJson.tsx | 2 +- packages/react/src/examples/IPyLeaflet.tsx | 2 +- packages/react/src/examples/IPyReact.tsx | 2 +- packages/react/src/examples/IPyWidgets.tsx | 2 +- .../src/examples/IPyWidgetsWithState.tsx | 2 +- .../src/examples/JupyterLabAppHeadless.tsx | 6 +- .../JupyterLabAppHeadlessServerless.tsx | 6 +- .../src/examples/JupyterLabAppServerless.tsx | 2 +- .../examples/JupyterLabAppServiceManager.tsx | 2 +- packages/react/src/examples/KernelExecute.tsx | 2 +- .../react/src/examples/KernelExecutor.tsx | 2 +- packages/react/src/examples/Kernels.tsx | 2 +- packages/react/src/examples/Matplotlib.tsx | 4 +- .../src/examples/NotebookCellSidebar.tsx | 2 +- .../react/src/examples/NotebookColorMode.tsx | 72 ------------------- .../src/examples/NotebookExternalContent.tsx | 2 +- .../react/src/examples/NotebookMutations.tsx | 2 +- .../react/src/examples/NotebookNbformat.tsx | 33 +++++++++ .../src/examples/NotebookNbformatChange.tsx | 58 +++++++++++++++ .../react/src/examples/NotebookNoContext.tsx | 6 +- .../react/src/examples/NotebookNoPrimer.tsx | 4 +- packages/react/src/examples/NotebookPath.tsx | 2 +- .../react/src/examples/NotebookPathChange.tsx | 2 +- .../react/src/examples/NotebookReadonly.tsx | 2 +- packages/react/src/examples/NotebookTheme.tsx | 2 +- .../src/examples/NotebookThemeColorMode.tsx | 18 ++--- .../react/src/examples/NotebookUnmount.tsx | 2 +- packages/react/src/examples/NotebookUrl.tsx | 2 +- .../react/src/examples/OutputIPyWidgets.tsx | 2 +- packages/react/src/examples/Outputs.tsx | 2 +- packages/react/src/examples/Panel.tsx | 2 +- packages/react/src/examples/Plotly.tsx | 2 +- .../react/src/examples/RunningSessions.tsx | 6 +- packages/react/src/examples/Terminal.tsx | 2 +- packages/react/src/examples/Vega.tsx | 2 +- packages/react/src/index.ts | 2 +- packages/react/src/jupyter/Jupyter.tsx | 11 ++- packages/react/src/jupyter/index.ts | 3 - packages/react/src/jupyter/lab/index.ts | 3 - .../JupyterLabColormode.tsx} | 2 +- .../{jupyter/lab => theme}/JupyterLabCss.tsx | 14 ++-- .../lab => theme}/JupyterLabCssImports.ts | 0 .../{themes => theme}/JupyterPrimerTheme.ts | 0 .../{themes => theme}/JupyterReactTheme.tsx | 12 ++-- packages/react/src/{themes => theme}/index.ts | 3 + packages/react/webpack.config.js | 6 +- 58 files changed, 183 insertions(+), 168 deletions(-) delete mode 100644 packages/react/src/examples/NotebookColorMode.tsx create mode 100644 packages/react/src/examples/NotebookNbformat.tsx create mode 100755 packages/react/src/examples/NotebookNbformatChange.tsx rename packages/react/src/{jupyter/lab/JupyterLabColorMode.tsx => theme/JupyterLabColormode.tsx} (62%) 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 => theme}/JupyterPrimerTheme.ts (100%) rename packages/react/src/{themes => theme}/JupyterReactTheme.tsx (70%) rename packages/react/src/{themes => theme}/index.ts (56%) 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/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index 87ca3827..2a8778e5 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -5,7 +5,7 @@ */ import { useRef, useEffect } from 'react'; -import { unmountComponentAtNode } from 'react-dom'; +// import { unmountComponentAtNode } from 'react-dom'; import { Widget } from '@lumino/widgets'; type LuminoProps = { 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/examples/Bokeh.tsx b/packages/react/src/examples/Bokeh.tsx index 8511aed6..f00205c3 100644 --- a/packages/react/src/examples/Bokeh.tsx +++ b/packages/react/src/examples/Bokeh.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/Bqplot.tsx b/packages/react/src/examples/Bqplot.tsx index 4875cba4..02a8ecb6 100644 --- a/packages/react/src/examples/Bqplot.tsx +++ b/packages/react/src/examples/Bqplot.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/Cells.tsx b/packages/react/src/examples/Cells.tsx index 8ce66996..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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const div = document.createElement('div'); diff --git a/packages/react/src/examples/CellsExecute.tsx b/packages/react/src/examples/CellsExecute.tsx index 0bfdd933..25aaae3b 100644 --- a/packages/react/src/examples/CellsExecute.tsx +++ b/packages/react/src/examples/CellsExecute.tsx @@ -7,7 +7,7 @@ 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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Cell from '../components/cell/Cell'; const CODE_CELL_1 = `import time diff --git a/packages/react/src/examples/Console.tsx b/packages/react/src/examples/Console.tsx index 449dae21..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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; 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 fb8db893..2e9456cd 100644 --- a/packages/react/src/examples/Dashboard.tsx +++ b/packages/react/src/examples/Dashboard.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/FileBrowser.tsx b/packages/react/src/examples/FileBrowser.tsx index 3da723ec..f4af4ba1 100644 --- a/packages/react/src/examples/FileBrowser.tsx +++ b/packages/react/src/examples/FileBrowser.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import FileBrowser from '../components/filebrowser/FileBrowser'; const div = document.createElement('div'); diff --git a/packages/react/src/examples/GeoJson.tsx b/packages/react/src/examples/GeoJson.tsx index b3c09592..9884bd76 100644 --- a/packages/react/src/examples/GeoJson.tsx +++ b/packages/react/src/examples/GeoJson.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as geojsonRenderer } from '@jupyterlab/geojson-extension'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/IPyLeaflet.tsx b/packages/react/src/examples/IPyLeaflet.tsx index 92994e02..93629f74 100644 --- a/packages/react/src/examples/IPyLeaflet.tsx +++ b/packages/react/src/examples/IPyLeaflet.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/IPyReact.tsx b/packages/react/src/examples/IPyReact.tsx index d045b920..9f0139a9 100644 --- a/packages/react/src/examples/IPyReact.tsx +++ b/packages/react/src/examples/IPyReact.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/IPyWidgets.tsx b/packages/react/src/examples/IPyWidgets.tsx index c195cb2b..86ae7c8e 100644 --- a/packages/react/src/examples/IPyWidgets.tsx +++ b/packages/react/src/examples/IPyWidgets.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/IPyWidgetsWithState.tsx b/packages/react/src/examples/IPyWidgetsWithState.tsx index ebc49889..d03c263c 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsWithState.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/JupyterLabAppHeadless.tsx b/packages/react/src/examples/JupyterLabAppHeadless.tsx index 41308eef..f77c2b2c 100644 --- a/packages/react/src/examples/JupyterLabAppHeadless.tsx +++ b/packages/react/src/examples/JupyterLabAppHeadless.tsx @@ -12,7 +12,7 @@ import { ThemeManager } from '@jupyterlab/apputils'; // import { NotebookTracker } from '@jupyterlab/notebook'; 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); diff --git a/packages/react/src/examples/JupyterLabAppServerless.tsx b/packages/react/src/examples/JupyterLabAppServerless.tsx index 2523a666..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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; diff --git a/packages/react/src/examples/JupyterLabAppServiceManager.tsx b/packages/react/src/examples/JupyterLabAppServiceManager.tsx index 496de2ce..d7173fce 100644 --- a/packages/react/src/examples/JupyterLabAppServiceManager.tsx +++ b/packages/react/src/examples/JupyterLabAppServiceManager.tsx @@ -7,7 +7,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { NotebookPanel } from '@jupyterlab/notebook'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; diff --git a/packages/react/src/examples/KernelExecute.tsx b/packages/react/src/examples/KernelExecute.tsx index ed3f8d81..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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import KernelProgressBar from './../components/kernel/KernelProgressBar'; export const KernelExecuteView = () => { diff --git a/packages/react/src/examples/KernelExecutor.tsx b/packages/react/src/examples/KernelExecutor.tsx index 86ecec9b..edec011e 100644 --- a/packages/react/src/examples/KernelExecutor.tsx +++ b/packages/react/src/examples/KernelExecutor.tsx @@ -9,7 +9,7 @@ import { createRoot } from 'react-dom/client'; import { Box, Heading } from '@primer/react'; import { IOutputAreaModel } from '@jupyterlab/outputarea'; import { KernelMessage } from '@jupyterlab/services'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { Output } from '../components/output/Output'; import { IOPubMessageHook, ShellMessageHook } from '../jupyter/kernel/KernelExecutor'; diff --git a/packages/react/src/examples/Kernels.tsx b/packages/react/src/examples/Kernels.tsx index f10dec85..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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import { KERNEL_STATES, diff --git a/packages/react/src/examples/Matplotlib.tsx b/packages/react/src/examples/Matplotlib.tsx index abb22efe..da4347f2 100644 --- a/packages/react/src/examples/Matplotlib.tsx +++ b/packages/react/src/examples/Matplotlib.tsx @@ -7,7 +7,7 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import { Jupyter } from '../jupyter/Jupyter'; -import JupyterLabCss from '../jupyter/lab/JupyterLabCss'; +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'; @@ -16,7 +16,7 @@ import notebook from './notebooks/Matplotlib.ipynb.json'; const Matplotlib = () => ( - + { - const [colorMode, setColorMode] = useState('light'); - const [isOn, setIsOn] = useState(false); - useEffect(() => { - if (isOn) { - setColorMode('dark'); - } else { - setColorMode('light'); - } - }, [isOn]); - const onClick = useCallback(() => { - setIsOn(!isOn); - }, [isOn]); - const handleSwitchChange = useCallback((on: boolean) => { - setIsOn(on); - }, []); - return ( - <> - - - { colorMode === 'light' ? 'Light' : 'Dark' } Mode - - - - - - ); -}; - -const div = document.createElement('div'); -document.body.appendChild(div); -const root = createRoot(div); - -root.render(); diff --git a/packages/react/src/examples/NotebookExternalContent.tsx b/packages/react/src/examples/NotebookExternalContent.tsx index 197ef2c6..3289d08d 100644 --- a/packages/react/src/examples/NotebookExternalContent.tsx +++ b/packages/react/src/examples/NotebookExternalContent.tsx @@ -9,7 +9,7 @@ import { createRoot } from 'react-dom/client'; import { Box, IconButton } from '@primer/react'; import { ZapIcon } from '@primer/octicons-react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/NotebookMutations.tsx b/packages/react/src/examples/NotebookMutations.tsx index d6cc3c12..a5dbea0f 100644 --- a/packages/react/src/examples/NotebookMutations.tsx +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -12,7 +12,7 @@ import { Box, SegmentedControl } from '@primer/react'; import { getJupyterServerUrl, getJupyterServerToken, createServerSettings, JupyterServiceManagerLess } from '../jupyter'; import { Notebook } from '../components/notebook/Notebook'; import { useNotebookStore } from './../components'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; diff --git a/packages/react/src/examples/NotebookNbformat.tsx b/packages/react/src/examples/NotebookNbformat.tsx new file mode 100644 index 00000000..37d866b4 --- /dev/null +++ b/packages/react/src/examples/NotebookNbformat.tsx @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { createRoot } from 'react-dom/client'; +import { INotebookContent } from '@jupyterlab/nbformat'; +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 div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); diff --git a/packages/react/src/examples/NotebookNbformatChange.tsx b/packages/react/src/examples/NotebookNbformatChange.tsx new file mode 100755 index 00000000..b63a8702 --- /dev/null +++ b/packages/react/src/examples/NotebookNbformatChange.tsx @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { useState } from 'react'; +import { createRoot } from 'react-dom/client'; +import { Box, Button, ButtonGroup } from '@primer/react'; +import { INotebookContent } from '@jupyterlab/nbformat'; +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'; +import nbformat2 from './notebooks/NotebookExample2.ipynb.json'; + +const NOTEBOOK_ID = 'notebook-model-change-id'; + +const NotebookNbformatChange = () => { + const notebookStore = useNotebookStore(); + const [nbformat, setNbformat] = useState(nbformat1); + const changeNbformat = () => { + console.log( + 'Notebook Nbformat from store', + notebookStore.notebooks.get(NOTEBOOK_ID)?.model?.toJSON() as INotebookContent + ); + nbformat === nbformat1 ? setNbformat(nbformat2) : setNbformat(nbformat1); + }; + return ( + <> + + + + + + + + ); +}; + +const div = document.createElement('div'); +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 863bc64e..26ca6a26 100644 --- a/packages/react/src/examples/NotebookNoContext.tsx +++ b/packages/react/src/examples/NotebookNoContext.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; @@ -16,10 +16,10 @@ const div = document.createElement('div'); document.body.appendChild(div); const root = createRoot(div); -const colorMode = 'light'; +const colormode = 'light'; root.render( - + - + { +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 678f6666..a90bd36e 100755 --- a/packages/react/src/examples/NotebookUnmount.tsx +++ b/packages/react/src/examples/NotebookUnmount.tsx @@ -8,7 +8,7 @@ import { useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Box, Button } from '@primer/react'; import { INotebookContent } from '@jupyterlab/nbformat'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import { useJupyter } from '../jupyter/JupyterContext'; import Kernel from '../jupyter/kernel/Kernel'; import { Notebook } from '../components/notebook/Notebook'; diff --git a/packages/react/src/examples/NotebookUrl.tsx b/packages/react/src/examples/NotebookUrl.tsx index 4d95b200..3db860f5 100644 --- a/packages/react/src/examples/NotebookUrl.tsx +++ b/packages/react/src/examples/NotebookUrl.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/OutputIPyWidgets.tsx b/packages/react/src/examples/OutputIPyWidgets.tsx index 1619fd66..e923bc07 100755 --- a/packages/react/src/examples/OutputIPyWidgets.tsx +++ b/packages/react/src/examples/OutputIPyWidgets.tsx @@ -6,7 +6,7 @@ import { render } from 'react-dom'; import { Text } from '@primer/react'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import OutputIPyWidgets from '../components/output/OutputIPyWidgets'; import { view, state } from './notebooks/OutputIPyWidgetsExample'; diff --git a/packages/react/src/examples/Outputs.tsx b/packages/react/src/examples/Outputs.tsx index c6229c27..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 { JupyterReactTheme } from '../themes/JupyterReactTheme'; +import { JupyterReactTheme } from '../theme/JupyterReactTheme'; import Output from '../components/output/Output'; import { cellSourceAsString } from './../utils/Utils'; diff --git a/packages/react/src/examples/Panel.tsx b/packages/react/src/examples/Panel.tsx index 6f7b4a00..dfc482fa 100644 --- a/packages/react/src/examples/Panel.tsx +++ b/packages/react/src/examples/Panel.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/Plotly.tsx b/packages/react/src/examples/Plotly.tsx index 84b5ae33..6aa3aaf7 100644 --- a/packages/react/src/examples/Plotly.tsx +++ b/packages/react/src/examples/Plotly.tsx @@ -5,7 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/examples/RunningSessions.tsx b/packages/react/src/examples/RunningSessions.tsx index 781ab972..1ed771b7 100644 --- a/packages/react/src/examples/RunningSessions.tsx +++ b/packages/react/src/examples/RunningSessions.tsx @@ -10,8 +10,8 @@ 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 { 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 4e4ddbe0..5c220fc5 100644 --- a/packages/react/src/examples/Vega.tsx +++ b/packages/react/src/examples/Vega.tsx @@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client'; import { rendererFactory as vega3Renderer } from '@jupyterlab/vega3-extension'; -import { JupyterReactTheme } from '../themes/JupyterReactTheme'; +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'; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 1750cf0b..32a136e6 100755 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -7,5 +7,5 @@ export * from './components'; export * from './jupyter'; export * from './state'; -export * from './themes'; +export * from './theme'; export * from './utils'; diff --git a/packages/react/src/jupyter/Jupyter.tsx b/packages/react/src/jupyter/Jupyter.tsx index d2f6bcfd..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 = '', @@ -82,14 +81,14 @@ export const Jupyter = (props: JupyterProps) => { > {!config.insideJupyterLab && !disableCssLoading && ( - + )} { - 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/JupyterPrimerTheme.ts b/packages/react/src/theme/JupyterPrimerTheme.ts similarity index 100% rename from packages/react/src/themes/JupyterPrimerTheme.ts rename to packages/react/src/theme/JupyterPrimerTheme.ts diff --git a/packages/react/src/themes/JupyterReactTheme.tsx b/packages/react/src/theme/JupyterReactTheme.tsx similarity index 70% rename from packages/react/src/themes/JupyterReactTheme.tsx rename to packages/react/src/theme/JupyterReactTheme.tsx index b48dee97..b3c4b169 100644 --- a/packages/react/src/themes/JupyterReactTheme.tsx +++ b/packages/react/src/theme/JupyterReactTheme.tsx @@ -5,20 +5,20 @@ */ import { BaseStyles, ThemeProvider, theme } from '@primer/react'; -import { ColorMode, JupyterLabCss } from './../jupyter'; +import { Colormode, JupyterLabCss } from './../theme'; type IJupyterLabThemeProps = { - colorMode: ColorMode; + colormode: Colormode; } export const JupyterReactTheme = (props: React.PropsWithChildren) => { - const { children, colorMode } = props; + const { children, colormode } = props; return ( <> - + @@ -31,7 +31,7 @@ export const JupyterReactTheme = (props: React.PropsWithChildren Date: Thu, 12 Sep 2024 13:19:56 +0200 Subject: [PATCH 09/14] chore: lite --- .../react/src/components/lumino/Lumino.tsx | 4 +- .../src/components/notebook/Notebook.tsx | 168 +++++++++--------- .../components/notebook/NotebookAdapter.ts | 34 ++-- .../src/components/notebook/NotebookState.ts | 2 +- .../JupyterLabAppHeadlessServerless.tsx | 2 +- .../examples/JupyterLabAppServiceManager.tsx | 9 +- packages/react/src/examples/Notebook.tsx | 5 +- .../react/src/examples/NotebookColormode.tsx | 72 ++++++++ .../react/src/examples/NotebookMutations.tsx | 30 ++-- .../src/examples/NotebookServiceManager.tsx | 4 +- packages/react/src/jupyter/JupyterConfig.ts | 4 +- packages/react/src/jupyter/JupyterContext.tsx | 14 +- .../react/src/jupyter/JupyterDefaults.tsx | 11 ++ packages/react/src/jupyter/index.ts | 1 + packages/react/src/jupyter/lite/Lite.ts | 11 ++ packages/react/src/jupyter/lite/index.ts | 1 + ...ceManagerLess.ts => ServiceManagerLess.ts} | 33 ++-- .../jupyter/services/ServiceManagerLite.ts | 41 +++++ packages/react/src/jupyter/services/index.ts | 3 +- ...pyerReactState.ts => JupyterReactState.ts} | 114 +++++------- packages/react/src/state/index.ts | 2 +- packages/react/webpack.config.js | 4 +- 22 files changed, 355 insertions(+), 214 deletions(-) create mode 100644 packages/react/src/examples/NotebookColormode.tsx create mode 100644 packages/react/src/jupyter/JupyterDefaults.tsx create mode 100644 packages/react/src/jupyter/lite/Lite.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} (69%) diff --git a/packages/react/src/components/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index 2a8778e5..40e17f4a 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -5,7 +5,7 @@ */ import { useRef, useEffect } from 'react'; -// import { unmountComponentAtNode } from 'react-dom'; +import { unmountComponentAtNode } from 'react-dom'; import { Widget } from '@lumino/widgets'; type LuminoProps = { @@ -26,8 +26,8 @@ export const Lumino = (props: LuminoProps) => { } return () => { try { - /* unmountComponentAtNode(children.node); + /* if (children.isAttached || children.node.isConnected) { children.dispose(); Widget.detach(children); diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index d4e5be78..9ec7796c 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -11,8 +11,7 @@ import { Cell, ICellModel } from '@jupyterlab/cells'; import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager } from '@jupyterlab/services'; -import { useJupyter, Lite } from './../../jupyter/JupyterContext'; -import { Kernel } from '../../jupyter/kernel/Kernel'; +import { useJupyter, Lite, Kernel } from './../../jupyter'; import { asObservable, Lumino } from '../lumino'; import { CellMetadataEditor } from './cell/metadata/CellMetadataEditor'; import { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget'; @@ -73,6 +72,7 @@ export const Notebook = (props: INotebookProps) => { nbgrader, path, readonly, + serverless, } = props; const notebookStore = useNotebookStore(); const [id, _] = useState(props.id ?? newUuid()); @@ -80,103 +80,111 @@ export const Notebook = (props: INotebookProps) => { const kernel = props.kernel ?? defaultKernel; // const notebook = notebookStore.selectNotebook(id); const portals = notebookStore.selectNotebookPortals(id); - const createAdapter = (kernel: Kernel) => { - kernel.ready.then(() => { - const adapter = new NotebookAdapter( - { - ...props, - id, - lite: lite || props.lite, - kernel, - serviceManager: serviceManager ?? props.serviceManager, - }, - ); - setAdapter(adapter); - notebookStore.update({ + const initAdapter = () => { + const adapter = new NotebookAdapter( + { + ...props, id, - state: { adapter } + lite: lite || props.lite, + kernel, + serviceManager: serviceManager ?? props.serviceManager, + }, + ); + setAdapter(adapter); + notebookStore.update({ + id, + state: { 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 + ); + 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 }, + }); + } + }); + } + 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.serviceManager.ready.then(() => { - if (!readonly) { - const activeCell = adapter.notebookPanel!.content.activeCell; - if (activeCell) { + */ + adapter.notebookPanel?.content.activeCellChanged.connect( + (_, cellModel) => { + if (cellModel === null) { notebookStore.activeCellChange({ id, - cellModel: activeCell, + cellModel: undefined, }); - } - const activeCellChanged$ = asObservable( - adapter.notebookPanel!.content.activeCellChanged - ); - activeCellChanged$.subscribe((cellModel: Cell) => { + } else { 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 }, - }); - } - }); - } - 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 }); - } - ); - }); + } + ); + adapter.notebookPanel?.sessionContext.statusChanged.connect( + (_, kernelStatus) => { + notebookStore.changeKernelStatus({ id, kernelStatus }); + } + ); }); - }; + } + const createAdapter = (kernel?: Kernel) => { + if (!kernel) { + initAdapter(); + } else { + kernel.ready.then(() => { + initAdapter(); + }); + } + } const disposeAdapter = () => { if (adapter) { notebookStore.dispose(id); + setAdapter(undefined); } } useEffect(() => { - if (id && serviceManager && kernelManager && kernel) { + if (id && serviceManager && kernelManager && (kernel || serverless)) { createAdapter(kernel); } return () => { disposeAdapter(); }; - }, [id, serviceManager, kernelManager, kernel, lite]); + }, [id, serviceManager, kernelManager, kernel, lite, serverless]); useEffect(() => { if (adapter && nbformat) { adapter.setNbformat(nbformat); diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 60c60590..4afe40d3 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -50,8 +50,8 @@ 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 { 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'; @@ -68,13 +68,14 @@ export class NotebookAdapter { private _commandRegistry: CommandRegistry; private _context?: Context; private _iPyWidgetsManager?: WidgetManager; - private _kernel: Kernel; + private _kernel?: Kernel; private _lite?: Lite; private _nbformat?: INotebookContent; private _nbgrader: boolean; private _notebookPanel?: NotebookPanel; private _path?: string; private _readonly: boolean; + private _serverless: boolean; private _renderers: IRenderMime.IRendererFactory[]; private _rendermime?: RenderMimeRegistry; private _serviceManager: ServiceManager.IManager; @@ -84,12 +85,13 @@ export class NotebookAdapter { constructor(props: INotebookProps) { this._id = props.id; - this._kernel = props.kernel!; + 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._serverless = props.serverless; this._renderers = props.renderers; this._serviceManager = props.serviceManager!; @@ -252,7 +254,7 @@ export class NotebookAdapter { factory: notebookModelFactory, path: this._path ?? FALLBACK_NOTEBOOK_PATH, kernelPreference: { - id: this._kernel.id, + id: this._kernel?.id, shouldStart: false, canStart: false, autoStartDefault: false, @@ -291,7 +293,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 { @@ -352,9 +354,11 @@ export class NotebookAdapter { .getWidgetFactory('Notebook') ?.createNew(this._context) as NotebookPanel; - this._iPyWidgetsManager?.registerWithKernel( - this._kernel.connection - ); + if (this._kernel) { + this._iPyWidgetsManager?.registerWithKernel( + this._kernel.connection + ); + } this._notebookPanel!.sessionContext.kernelChanged.connect( ( @@ -480,11 +484,15 @@ export class NotebookAdapter { return this._readonly; } + get serverless(): boolean { + return this._serverless; + } + get lite(): Lite | undefined { return this._lite; } - get kernel(): Kernel { + get kernel(): Kernel | undefined { return this._kernel; } @@ -604,9 +612,9 @@ export class NotebookAdapter { dispose = () => { document.removeEventListener('keydown', this.notebookKeydownListener, true); -// this._notebookPanel?.dispose(); -// this._boxPanel.dispose(); -// this._context?.dispose(); + this._context?.dispose(); + this._notebookPanel?.dispose(); + this._boxPanel.dispose(); }; } diff --git a/packages/react/src/components/notebook/NotebookState.ts b/packages/react/src/components/notebook/NotebookState.ts index cfeac520..d2cab409 100644 --- a/packages/react/src/components/notebook/NotebookState.ts +++ b/packages/react/src/components/notebook/NotebookState.ts @@ -233,7 +233,7 @@ export const notebookStore = createStore((set, get) => ({ const notebooks = get().notebooks; const notebook = notebooks.get(id); if(notebook){ - notebook.adapter?.dispose(); +// notebook.adapter?.dispose(); notebooks.delete(id); } set((state: NotebookState) => ({ notebooks })); diff --git a/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx b/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx index a8c7b91c..d1ce3cba 100644 --- a/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx +++ b/packages/react/src/examples/JupyterLabAppHeadlessServerless.tsx @@ -11,8 +11,8 @@ import { BoxPanel } from '@lumino/widgets'; import { ThemeManager } from '@jupyterlab/apputils'; // import { NotebookTracker } from '@jupyterlab/notebook'; import { JupyterReactTheme } from '../theme/JupyterReactTheme'; -import Lumino from '../components/lumino/Lumino'; import { Colormode } from '../theme/JupyterLabColormode'; +import Lumino from '../components/lumino/Lumino'; import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; diff --git a/packages/react/src/examples/JupyterLabAppServiceManager.tsx b/packages/react/src/examples/JupyterLabAppServiceManager.tsx index d7173fce..f53fcd06 100644 --- a/packages/react/src/examples/JupyterLabAppServiceManager.tsx +++ b/packages/react/src/examples/JupyterLabAppServiceManager.tsx @@ -8,19 +8,18 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { NotebookPanel } from '@jupyterlab/notebook'; import { JupyterReactTheme } from '../theme/JupyterReactTheme'; -import JupyterLabApp from '../components/jupyterlab/JupyterLabApp'; -import JupyterLabAppAdapter from '../components/jupyterlab/JupyterLabAppAdapter'; -import JupyterServiceManagerLess from '../jupyter/services/JupyterServiceManagerLess'; +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); diff --git a/packages/react/src/examples/Notebook.tsx b/packages/react/src/examples/Notebook.tsx index 8f933e78..6341c914 100644 --- a/packages/react/src/examples/Notebook.tsx +++ b/packages/react/src/examples/Notebook.tsx @@ -6,6 +6,7 @@ import { createRoot } from 'react-dom/client'; import { Jupyter } from '../jupyter/Jupyter'; +import { DEFAULT_JUPYTER_SERVER_URL, DEFAULT_JUPYTER_SERVER_TOKEN } from '../jupyter'; import { Notebook } from '../components/notebook/Notebook'; import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; import { CellSidebarButton } from '../components/notebook/cell/sidebar/CellSidebarButton'; @@ -18,8 +19,8 @@ const root = createRoot(div); root.render( { + const [colormode, setColormode] = useState('light'); + const [isOn, setIsOn] = useState(false); + useEffect(() => { + if (isOn) { + setColormode('dark'); + } else { + setColormode('light'); + } + }, [isOn]); + const onClick = useCallback(() => { + setIsOn(!isOn); + }, [isOn]); + const handleSwitchChange = useCallback((on: boolean) => { + setIsOn(on); + }, []); + return ( + <> + + + { colormode === 'light' ? 'Light' : 'Dark' } Mode + + + + + + ); +}; + +const div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); diff --git a/packages/react/src/examples/NotebookMutations.tsx b/packages/react/src/examples/NotebookMutations.tsx index a5dbea0f..967ded30 100644 --- a/packages/react/src/examples/NotebookMutations.tsx +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -9,10 +9,9 @@ import { createRoot } from 'react-dom/client'; import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager } from '@jupyterlab/services'; import { Box, SegmentedControl } from '@primer/react'; -import { getJupyterServerUrl, getJupyterServerToken, createServerSettings, JupyterServiceManagerLess } from '../jupyter'; -import { Notebook } from '../components/notebook/Notebook'; -import { useNotebookStore } from './../components'; -import { JupyterReactTheme } from '../theme/JupyterReactTheme'; +import { createServiceManagerLite, createServerSettings, getJupyterServerUrl, getJupyterServerToken, ServiceManagerLess } from '../jupyter'; +import { useNotebookStore, Notebook} from './../components'; +import { JupyterReactTheme } from '../theme'; import nbformat from './notebooks/NotebookExample1.ipynb.json'; @@ -21,33 +20,35 @@ 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 [serviceManager, setServiceManager] = useState(new JupyterServiceManagerLess()); const changeIndex = (index: number) => { setIndex(index); switch(index) { case 0: { setReadonly(true); + setServerless(true); setLite(false); -// setServiceManager(new JupyterServiceManagerLess()); + setServiceManager(new ServiceManagerLess()); break; } case 1: { setReadonly(false); + setServerless(true); setLite(true); -// setServiceManager(new JupyterServiceManagerLess()); + createServiceManagerLite().then(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; } } @@ -65,18 +66,25 @@ const NotebookMutations = () => { Readonly: {String(notebook?.adapter?.readonly)} + + Serverless: {String(notebook?.adapter?.serverless)} + Lite: {String(notebook?.adapter?.lite)} - Kernel ID: {notebook?.adapter?.kernel.id} + Kernel ID: {notebook?.adapter?.kernel?.id} + + + Service Manager Ready: {String(notebook?.adapter?.serviceManager.isReady)} - Service Manager: {notebook?.adapter?.serviceManager.serverSettings.baseUrl} + Service Manager URL: {notebook?.adapter?.serviceManager.serverSettings.baseUrl}
{ - const [serviceManagerLess, _] = useState(new JupyterServiceManagerLess()); + const [serviceManagerLess, _] = useState(new ServiceManagerLess()); const [kernel, setKernel] = useState(); useEffect(() => { const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken()); diff --git a/packages/react/src/jupyter/JupyterConfig.ts b/packages/react/src/jupyter/JupyterConfig.ts index d85b9cf3..7caec9d8 100644 --- a/packages/react/src/jupyter/JupyterConfig.ts +++ b/packages/react/src/jupyter/JupyterConfig.ts @@ -128,8 +128,8 @@ export const loadJupyterConfig = ( return config; } config = { - jupyterServerToken: '', - jupyterServerUrl: '', + jupyterServerToken: jupyterServerToken ?? '', + jupyterServerUrl: jupyterServerUrl ?? '', insideJupyterLab: false, insideJupyterHub: false, } diff --git a/packages/react/src/jupyter/JupyterContext.tsx b/packages/react/src/jupyter/JupyterContext.tsx index 33d8ae51..bb9660fb 100644 --- a/packages/react/src/jupyter/JupyterContext.tsx +++ b/packages/react/src/jupyter/JupyterContext.tsx @@ -6,14 +6,10 @@ import React, { createContext, useContext } from 'react'; import { Kernel as JupyterKernel, ServerConnection, ServiceManager } from '@jupyterlab/services'; -import type { JupyterLiteServerPlugin } from '@jupyterlite/server'; import { useJupyterReactStoreFromProps } from '../state'; import { requestAPI } from './JupyterHandlers'; -import Kernel from './kernel/Kernel'; - -export type Lite = - | boolean - | Promise<{ default: JupyterLiteServerPlugin[] }>; +import { Lite } from './lite'; +import { Kernel } from './kernel'; /** * The type for Jupyter props. @@ -148,11 +144,11 @@ export type JupyterContextType = { */ 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}. */ @@ -182,7 +178,7 @@ export const JupyterContextConsumer = JupyterContext.Consumer; const JupyterProvider = JupyterContext.Provider; /* - * + * User Jupyter hook. */ export const useJupyter = (props?: JupyterPropsType): JupyterContextType => { const context = useContext(JupyterContext); 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 index 3a48b284..9ee04f36 100644 --- a/packages/react/src/jupyter/index.ts +++ b/packages/react/src/jupyter/index.ts @@ -8,6 +8,7 @@ export * from './Jupyter'; export * from './JupyterAuthError'; export * from './JupyterConfig'; export * from './JupyterContext'; +export * from './JupyterDefaults'; export * from './JupyterHandlers'; export * from './Jupyter'; export * from './ipywidgets'; 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 index 00064040..7a23b82a 100644 --- a/packages/react/src/jupyter/lite/index.ts +++ b/packages/react/src/jupyter/lite/index.ts @@ -4,4 +4,5 @@ * MIT License */ +export * from './Lite'; export * from './LiteServer'; 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..0bec789a 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,22 @@ 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://', + }); + 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 +440,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 69% rename from packages/react/src/state/JupyerReactState.ts rename to packages/react/src/state/JupyterReactState.ts index 0ed5bb00..00007170 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; }, []); @@ -124,68 +129,43 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR // 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 (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 (!serviceManager) { + if (lite) { + createServiceManagerLite(lite).then(serviceManager => { + setServiceManager(serviceManager); + jupyterReactStore.getState().setServiceManager(serviceManager); + }); + return; + } + const serverSettings = createServerSettings( + 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); } - if (!Array.isArray(data)) { - data = [data]; + if (useRunningKernelId && useRunningKernelIndex > -1) { + throw new Error('You can not ask for useRunningKernelId and useRunningKernelIndex at the same time.'); } - 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); - }); - return; + if ( + startDefaultKernel && + (useRunningKernelId || useRunningKernelIndex > -1) + ) { + throw new Error('You can not ask for startDefaultKernel and (useRunningKernelId or useRunningKernelIndex) at the same time.'); + } + const serviceManager = new ServiceManager({ serverSettings }); + setServiceManager(serviceManager); + jupyterReactStore.getState().setServiceManager(serviceManager); + }); } - const serverSettings = createServerSettings( - config.jupyterServerUrl, - config.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); - } - if (useRunningKernelId && useRunningKernelIndex > -1) { - throw new Error('You can not ask for useRunningKernelId and useRunningKernelIndex at the same time.'); - } - if ( - startDefaultKernel && - (useRunningKernelId || useRunningKernelIndex > -1) - ) { - throw new Error('You can not ask for startDefaultKernel and (useRunningKernelId or useRunningKernelIndex) at the same time.'); - } - const serviceManager = new ServiceManager({ serverSettings }); - setServiceManager(serviceManager); - jupyterReactStore.getState().setServiceManager(serviceManager); - }); }, [lite, serverless, jupyterServerUrl]); // Setup a kernel if needed. 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/webpack.config.js b/packages/react/webpack.config.js index d11f4229..1d0176f8 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -35,7 +35,7 @@ const ENTRY = // './src/examples/JupyterLabAppHeadless'; // './src/examples/JupyterLabAppHeadlessServerless'; // './src/examples/JupyterLabAppServerless'; - './src/examples/JupyterLabAppServiceManager'; + // './src/examples/JupyterLabAppServiceManager'; // './src/examples/KernelExecute'; // './src/examples/KernelExecutor'; // './src/examples/Kernels'; @@ -45,7 +45,7 @@ const ENTRY = // './src/examples/NotebookColormode'; // './src/examples/NotebookKernelChange'; // './src/examples/NotebookLite'; - // './src/examples/NotebookMutations'; + './src/examples/NotebookMutations'; // './src/examples/NotebookNbformat'; // './src/examples/NotebookNbformatChange'; // './src/examples/NotebookNoContext'; From 71a5cc1cac6b25864a8d4b8ec44fc9e7532ff9cd Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Thu, 12 Sep 2024 13:38:32 +0200 Subject: [PATCH 10/14] fix: build --- packages/react/src/components/lumino/Lumino.tsx | 10 +++++++--- .../react/src/components/notebook/Notebook.tsx | 17 +++++++++-------- .../react/src/examples/NotebookMutations.tsx | 11 +++++++---- packages/react/src/state/JupyterReactState.ts | 1 + 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/react/src/components/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index 40e17f4a..c565e695 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -41,13 +41,17 @@ export const Lumino = (props: LuminoProps) => { } }, [ref, children]); return ( -
+
); -}; +} Lumino.defaultProps = { id: 'lumino-id', height: '100%', -}; +} export default Lumino; diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index 9ec7796c..a2c4ebed 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -16,7 +16,7 @@ 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/Utils'; +import { newUuid } from '../../utils'; import { useNotebookStore } from './NotebookState'; import { NotebookAdapter } from './NotebookAdapter'; @@ -52,7 +52,7 @@ export type INotebookProps = { }; /** - * 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. @@ -60,9 +60,9 @@ export type INotebookProps = { */ export const Notebook = (props: INotebookProps) => { const { serviceManager, defaultKernel, kernelManager, lite } = useJupyter({ + lite: props.lite, serverless: props.serverless, serviceManager: props.serviceManager, - lite: props.lite, }); const { Toolbar, @@ -80,7 +80,7 @@ export const Notebook = (props: INotebookProps) => { const kernel = props.kernel ?? defaultKernel; // const notebook = notebookStore.selectNotebook(id); const portals = notebookStore.selectNotebookPortals(id); - const initAdapter = () => { + const createAdapter = () => { const adapter = new NotebookAdapter( { ...props, @@ -90,6 +90,7 @@ export const Notebook = (props: INotebookProps) => { serviceManager: serviceManager ?? props.serviceManager, }, ); + console.log('Created Notebook Adapter', adapter); setAdapter(adapter); notebookStore.update({ id, @@ -162,12 +163,12 @@ export const Notebook = (props: INotebookProps) => { ); }); } - const createAdapter = (kernel?: Kernel) => { + const initAdapter = (kernel?: Kernel) => { if (!kernel) { - initAdapter(); + createAdapter(); } else { kernel.ready.then(() => { - initAdapter(); + createAdapter(); }); } } @@ -179,7 +180,7 @@ export const Notebook = (props: INotebookProps) => { } useEffect(() => { if (id && serviceManager && kernelManager && (kernel || serverless)) { - createAdapter(kernel); + initAdapter(kernel); } return () => { disposeAdapter(); diff --git a/packages/react/src/examples/NotebookMutations.tsx b/packages/react/src/examples/NotebookMutations.tsx index 967ded30..37278911 100644 --- a/packages/react/src/examples/NotebookMutations.tsx +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -39,7 +39,10 @@ const NotebookMutations = () => { setReadonly(false); setServerless(true); setLite(true); - createServiceManagerLite().then(serviceManager => setServiceManager(serviceManager)); + createServiceManagerLite().then(serviceManager => { + console.log('Created Service Manager Lite', serviceManager); + setServiceManager(serviceManager); + }); break; } case 2: { @@ -83,12 +86,12 @@ const NotebookMutations = () => { diff --git a/packages/react/src/state/JupyterReactState.ts b/packages/react/src/state/JupyterReactState.ts index 00007170..ef322754 100644 --- a/packages/react/src/state/JupyterReactState.ts +++ b/packages/react/src/state/JupyterReactState.ts @@ -121,6 +121,7 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR useEffect(() => { if (propsServiceManager) { + console.log('Setting service manager from props', propsServiceManager); setServiceManager(propsServiceManager); jupyterReactStore.getState().setServiceManager(propsServiceManager); } From 1e262efc87f6b7dfab903b4a98b290441e2a578e Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Thu, 12 Sep 2024 19:13:49 +0200 Subject: [PATCH 11/14] fix: mount --- .../react/src/components/lumino/Lumino.tsx | 2 - .../src/components/notebook/Notebook.tsx | 61 ++- .../components/notebook/NotebookAdapter.ts | 406 ++++++++++-------- .../components/notebook/NotebookCommands.ts | 30 +- .../react/src/examples/JupyterContext.tsx | 7 +- packages/react/src/examples/Notebook.tsx | 10 +- .../react/src/examples/NotebookPathChange.tsx | 19 +- .../src/examples/NotebookThemeColorMode.tsx | 114 ----- packages/react/src/jupyter/JupyterConfig.ts | 18 +- packages/react/src/theme/index.ts | 2 +- packages/react/webpack.config.js | 3 +- 11 files changed, 306 insertions(+), 366 deletions(-) delete mode 100644 packages/react/src/examples/NotebookThemeColorMode.tsx diff --git a/packages/react/src/components/lumino/Lumino.tsx b/packages/react/src/components/lumino/Lumino.tsx index c565e695..e726bcf2 100644 --- a/packages/react/src/components/lumino/Lumino.tsx +++ b/packages/react/src/components/lumino/Lumino.tsx @@ -27,12 +27,10 @@ export const Lumino = (props: LuminoProps) => { return () => { try { unmountComponentAtNode(children.node); - /* if (children.isAttached || children.node.isConnected) { children.dispose(); Widget.detach(children); } - */ } catch (e) { // no-op. // console.debug('Exception while detaching Lumino widget.', e); diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index a2c4ebed..3a65e050 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -72,15 +72,15 @@ export const Notebook = (props: INotebookProps) => { 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 = props.kernel ?? defaultKernel; -// const notebook = notebookStore.selectNotebook(id); const portals = notebookStore.selectNotebookPortals(id); - const createAdapter = () => { + const bootstrapAdapter = () => { const adapter = new NotebookAdapter( { ...props, @@ -163,12 +163,12 @@ export const Notebook = (props: INotebookProps) => { ); }); } - const initAdapter = (kernel?: Kernel) => { + const createAdapter = (kernel?: Kernel) => { if (!kernel) { - createAdapter(); + bootstrapAdapter(); } else { kernel.ready.then(() => { - createAdapter(); + bootstrapAdapter(); }); } } @@ -179,27 +179,48 @@ export const Notebook = (props: INotebookProps) => { } } useEffect(() => { - if (id && serviceManager && kernelManager && (kernel || serverless)) { - initAdapter(kernel); - } return () => { disposeAdapter(); - }; + } + }, []); + useEffect(() => { + if (id && serviceManager && kernelManager && (kernel || serverless)) { + createAdapter(kernel); + } }, [id, serviceManager, kernelManager, kernel, lite, serverless]); useEffect(() => { - if (adapter && nbformat) { + if (adapter && nbformat && adapter.nbformat !== nbformat) { adapter.setNbformat(nbformat); } - }, [adapter, nbformat]); + return () => { +// disposeAdapter(); + } + }, [nbformat]); useEffect(() => { - if (adapter) { + if (adapter && path && adapter.path !== path) { + disposeAdapter(); + createAdapter(); } - }, [adapter, path]); + return () => { +// disposeAdapter(); + } + }, [path]); useEffect(() => { - if (adapter) { + if (adapter && url && adapter.url !== url) { + createAdapter(); + } + return () => { +// disposeAdapter(); + } + }, [url]); + useEffect(() => { + if (adapter && url && adapter.readonly !== readonly) { adapter.setReadonly(readonly); } - }, [adapter, readonly]); + return () => { +// disposeAdapter(); + } + }, [readonly]); return ( { {portals?.map((portal: React.ReactPortal) => portal)} - {adapter && {adapter.panel}} + {adapter && + ( + + {adapter.panel} + + ) + } diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 4afe40d3..22488e4b 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -64,25 +64,28 @@ import { WidgetLabRenderer } from '../../jupyter/ipywidgets/lab/renderer'; 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 _documentRegistry?: DocumentRegistry; private _iPyWidgetsManager?: WidgetManager; + 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 _serverless: boolean; private _renderers: IRenderMime.IRendererFactory[]; private _rendermime?: RenderMimeRegistry; + private _serverless: boolean; private _serviceManager: ServiceManager.IManager; private _tracker?: NotebookTracker; - private _id: string; - private _CellSidebar?: (props: ICellSidebarProps) => JSX.Element; - constructor(props: INotebookProps) { this._id = props.id; this._kernel = props.kernel; @@ -90,6 +93,7 @@ export class NotebookAdapter { this._nbformat = props.nbformat; this._nbgrader = props.nbgrader; this._path = props.path; + this._url = props.url; this._readonly = props.readonly; this._serverless = props.serverless; this._renderers = props.renderers; @@ -126,132 +130,58 @@ 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 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, - }); + 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, + factory: this._notebookModelFactory!, path: this._path ?? FALLBACK_NOTEBOOK_PATH, kernelPreference: { id: this._kernel?.id, @@ -262,7 +192,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( { @@ -285,6 +216,7 @@ export class NotebookAdapter { ); }); */ + // These are fixes to have more control on the kernel launch. (this._context.sessionContext as any)._initialize = async (): Promise => { @@ -334,6 +266,7 @@ export class NotebookAdapter { ); } }); + /* // Alternative way to create a NotebookPanel. const content = new Notebook({ @@ -350,9 +283,8 @@ export class NotebookAdapter { content, }); */ - this._notebookPanel = documentRegistry - .getWidgetFactory('Notebook') - ?.createNew(this._context) as NotebookPanel; + + this._notebookPanel = this._documentRegistry?.getWidgetFactory('Notebook')?.createNew(this._context) as NotebookPanel; if (this._kernel) { this._iPyWidgetsManager?.registerWithKernel( @@ -360,7 +292,7 @@ export class NotebookAdapter { ); } - this._notebookPanel!.sessionContext.kernelChanged.connect( + this._notebookPanel?.sessionContext.kernelChanged.connect( ( _: any, args: IChangedArgs< @@ -374,27 +306,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 = { @@ -410,9 +344,7 @@ 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(() => { @@ -420,53 +352,135 @@ export class NotebookAdapter { 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 { + + 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 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( - (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 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); + }); + this._documentRegistry.addWidgetFactory(notebookWidgetFactory); + + this._notebookModelFactory = new JupyterReactNotebookModelFactory({ + nbformat: this._nbformat, + readonly: this._readonly, + }); + this._documentRegistry.addModelFactory(this._notebookModelFactory); + + this.initializeContext(); + } assignKernel(kernel: Kernel) { @@ -492,6 +506,18 @@ export class NotebookAdapter { 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; } @@ -517,12 +543,10 @@ export class NotebookAdapter { */ 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); } } @@ -534,6 +558,13 @@ export class NotebookAdapter { } } + setPath(path: string) { + if (this._path !== path) { + this._path = path; + this.initializeContext(); + } + } + setDefaultCellType = (cellType: CellType) => { this._notebookPanel!.content!.notebookConfig!.defaultCell! = cellType; }; @@ -616,6 +647,7 @@ export class NotebookAdapter { 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/examples/JupyterContext.tsx b/packages/react/src/examples/JupyterContext.tsx index b44f1377..248244aa 100644 --- a/packages/react/src/examples/JupyterContext.tsx +++ b/packages/react/src/examples/JupyterContext.tsx @@ -8,6 +8,7 @@ import { useState } from 'react'; import { createRoot } from 'react-dom/client'; import { IOutput, INotebookContent } from '@jupyterlab/nbformat'; 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'; @@ -187,12 +188,14 @@ const Outputs = () => { }; const JuptyerContextExample = () => { - const [index, setIndex] = useState(0); + const [index, setIndex] = useState(1); return ( <> setIndex(index)} aria-label="jupyter-react-example"> Serverless diff --git a/packages/react/src/examples/Notebook.tsx b/packages/react/src/examples/Notebook.tsx index 6341c914..ee1894ce 100644 --- a/packages/react/src/examples/Notebook.tsx +++ b/packages/react/src/examples/Notebook.tsx @@ -5,8 +5,7 @@ */ import { createRoot } from 'react-dom/client'; -import { Jupyter } from '../jupyter/Jupyter'; -import { DEFAULT_JUPYTER_SERVER_URL, DEFAULT_JUPYTER_SERVER_TOKEN } from '../jupyter'; +import { JupyterReactTheme } from '../theme'; import { Notebook } from '../components/notebook/Notebook'; import { NotebookToolbar } from './../components/notebook/toolbar/NotebookToolbar'; import { CellSidebarButton } from '../components/notebook/cell/sidebar/CellSidebarButton'; @@ -18,10 +17,7 @@ document.body.appendChild(div); const root = createRoot(div); root.render( - + - + ); diff --git a/packages/react/src/examples/NotebookPathChange.tsx b/packages/react/src/examples/NotebookPathChange.tsx index b417e429..3afe20f4 100755 --- a/packages/react/src/examples/NotebookPathChange.tsx +++ b/packages/react/src/examples/NotebookPathChange.tsx @@ -17,14 +17,12 @@ 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 ( - <> + @@ -38,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/NotebookThemeColorMode.tsx b/packages/react/src/examples/NotebookThemeColorMode.tsx deleted file mode 100644 index 21897bf1..00000000 --- a/packages/react/src/examples/NotebookThemeColorMode.tsx +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2021-2023 Datalayer, Inc. - * - * MIT License - */ - -import { useCallback, useEffect, useState } from 'react'; -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 '../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 [theme, setTheme] = useState(jupyterTheme); - const [isThemeOn, setIsThemeOn] = useState(false); - const [colormode, setColormode] = useState('light'); - const [isOn, setIsOn] = useState(false); - - useEffect(() => { - if (isThemeOn) { - setTheme(primerTheme); - } else { - setTheme(jupyterTheme); - } - }, [isThemeOn]); - const onThemeClick = useCallback(() => { - setIsThemeOn(!isThemeOn); - }, [isThemeOn]); - const handleThemeSwitchChange = useCallback((on: boolean) => { - setIsThemeOn(on); - }, []); - - useEffect(() => { - if (isOn) { - setColormode('dark'); - } else { - setColormode('light'); - } - }, [isOn]); - const onClick = useCallback(() => { - setIsOn(!isOn); - }, [isOn]); - const handleSwitchChange = useCallback((on: boolean) => { - setIsOn(on); - }, []); - return ( - <> - - - - - Primer Theme - - - - - - { colormode === 'light' ? 'Light' : 'Dark' } Mode - - - - - - - - ); -}; - -const div = document.createElement('div'); -document.body.appendChild(div); -const root = createRoot(div); - -root.render(); diff --git a/packages/react/src/jupyter/JupyterConfig.ts b/packages/react/src/jupyter/JupyterConfig.ts index 7caec9d8..9aff0825 100644 --- a/packages/react/src/jupyter/JupyterConfig.ts +++ b/packages/react/src/jupyter/JupyterConfig.ts @@ -6,6 +6,7 @@ import { PageConfig } from '@jupyterlab/coreutils'; import { JupyterProps } from './Jupyter'; +import { DEFAULT_JUPYTER_SERVER_URL, DEFAULT_JUPYTER_SERVER_TOKEN } from './JupyterDefaults'; /** * The URL prefix for the kernel api. @@ -128,8 +129,8 @@ export const loadJupyterConfig = ( return config; } config = { - jupyterServerToken: jupyterServerToken ?? '', - jupyterServerUrl: jupyterServerUrl ?? '', + jupyterServerUrl: jupyterServerUrl ?? DEFAULT_JUPYTER_SERVER_TOKEN, + jupyterServerToken: jupyterServerToken ?? DEFAULT_JUPYTER_SERVER_URL, insideJupyterLab: false, insideJupyterHub: false, } @@ -138,14 +139,15 @@ export const loadJupyterConfig = ( if (datalayerConfigLoaded) { // There is a Datalayer config, mix the configs... setJupyterServerUrl( - jupyterServerUrl ?? - config.jupyterServerUrl ?? - location.protocol + '//' + location.host + '/api/jupyter-server' + jupyterServerUrl || + config.jupyterServerUrl +// location.protocol + '//' + location.host + '/api/jupyter-server' + ); setJupyterServerToken( - jupyterServerToken ?? - config.jupyterServerToken ?? - '' + jupyterServerToken || + config.jupyterServerToken +// '' ); } else { // No Datalayer config, look for a Jupyter config. diff --git a/packages/react/src/theme/index.ts b/packages/react/src/theme/index.ts index d7805f18..e00ca9ea 100644 --- a/packages/react/src/theme/index.ts +++ b/packages/react/src/theme/index.ts @@ -6,6 +6,6 @@ export * from './JupyterLabColormode'; export * from './JupyterLabCss'; -export * from './JupyterLabCssImports'; +// 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 1d0176f8..7df1739f 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -50,11 +50,12 @@ const ENTRY = // './src/examples/NotebookNbformatChange'; // './src/examples/NotebookNoContext'; // './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'; From 8e254f276242f2aaad5e5c1fa174efb3bfff41b3 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Thu, 12 Sep 2024 20:19:12 +0200 Subject: [PATCH 12/14] fix: mount --- .../src/components/notebook/Notebook.tsx | 16 +-- .../components/notebook/NotebookAdapter.ts | 2 - .../model/JupyterReactNotebookModelFactory.ts | 12 +- .../src/examples/NotebookThemeColormode.tsx | 114 ++++++++++++++++++ 4 files changed, 122 insertions(+), 22 deletions(-) create mode 100644 packages/react/src/examples/NotebookThemeColormode.tsx diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index 3a65e050..03a0557b 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -185,6 +185,9 @@ export const Notebook = (props: INotebookProps) => { }, []); useEffect(() => { if (id && serviceManager && kernelManager && (kernel || serverless)) { + if (adapter) { + disposeAdapter(); + } createAdapter(kernel); } }, [id, serviceManager, kernelManager, kernel, lite, serverless]); @@ -192,34 +195,23 @@ export const Notebook = (props: INotebookProps) => { if (adapter && nbformat && adapter.nbformat !== nbformat) { adapter.setNbformat(nbformat); } - return () => { -// disposeAdapter(); - } }, [nbformat]); useEffect(() => { if (adapter && path && adapter.path !== path) { disposeAdapter(); createAdapter(); } - return () => { -// disposeAdapter(); - } }, [path]); useEffect(() => { if (adapter && url && adapter.url !== url) { + disposeAdapter(); createAdapter(); } - return () => { -// disposeAdapter(); - } }, [url]); useEffect(() => { if (adapter && url && adapter.readonly !== readonly) { adapter.setReadonly(readonly); } - return () => { -// disposeAdapter(); - } }, [readonly]); return ( - ): INotebookModel { + createNew(options: DocumentRegistry.IModelOptions): INotebookModel { if (this._nbformat) { - if (this._readonly) { - this._nbformat.cells.forEach(cell => { - cell.metadata['editable'] = false; - }); - } + this._nbformat.cells.forEach(cell => { + cell.metadata['editable'] = !this._readonly; + }); const notebookModel = new NotebookModel(); notebookModel.fromJSON(this._nbformat); return notebookModel; diff --git a/packages/react/src/examples/NotebookThemeColormode.tsx b/packages/react/src/examples/NotebookThemeColormode.tsx new file mode 100644 index 00000000..21897bf1 --- /dev/null +++ b/packages/react/src/examples/NotebookThemeColormode.tsx @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021-2023 Datalayer, Inc. + * + * MIT License + */ + +import { useCallback, useEffect, useState } from 'react'; +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 '../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 [theme, setTheme] = useState(jupyterTheme); + const [isThemeOn, setIsThemeOn] = useState(false); + const [colormode, setColormode] = useState('light'); + const [isOn, setIsOn] = useState(false); + + useEffect(() => { + if (isThemeOn) { + setTheme(primerTheme); + } else { + setTheme(jupyterTheme); + } + }, [isThemeOn]); + const onThemeClick = useCallback(() => { + setIsThemeOn(!isThemeOn); + }, [isThemeOn]); + const handleThemeSwitchChange = useCallback((on: boolean) => { + setIsThemeOn(on); + }, []); + + useEffect(() => { + if (isOn) { + setColormode('dark'); + } else { + setColormode('light'); + } + }, [isOn]); + const onClick = useCallback(() => { + setIsOn(!isOn); + }, [isOn]); + const handleSwitchChange = useCallback((on: boolean) => { + setIsOn(on); + }, []); + return ( + <> + + + + + Primer Theme + + + + + + { colormode === 'light' ? 'Light' : 'Dark' } Mode + + + + + + + + ); +}; + +const div = document.createElement('div'); +document.body.appendChild(div); +const root = createRoot(div); + +root.render(); From c22493ae7a6479b40a71715590f102de94600f29 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Fri, 13 Sep 2024 08:44:56 +0200 Subject: [PATCH 13/14] lint --- packages/react/src/components/notebook/NotebookAdapter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index bda41b74..9bf18b6f 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -86,6 +86,7 @@ export class NotebookAdapter { private _serverless: boolean; private _serviceManager: ServiceManager.IManager; private _tracker?: NotebookTracker; + constructor(props: INotebookProps) { this._id = props.id; this._kernel = props.kernel; @@ -203,6 +204,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. From a4ecd4ebad8cf8ae8252ecf2cf2c0c2c4b7ee685 Mon Sep 17 00:00:00 2001 From: Eric Charles Date: Fri, 13 Sep 2024 13:29:10 +0200 Subject: [PATCH 14/14] lint --- .../src/components/notebook/Notebook.tsx | 108 ++++++++---------- .../components/notebook/NotebookAdapter.ts | 93 +++++++-------- .../src/components/notebook/NotebookState.ts | 1 - packages/react/src/examples/CellsExecute.tsx | 6 +- ...dgetsWithState.tsx => IPyWidgetsState.tsx} | 4 +- .../react/src/examples/NotebookMutations.tsx | 6 +- .../src/examples/NotebookServiceManager.tsx | 62 +++++----- packages/react/src/examples/NotebookUrl.tsx | 30 ----- packages/react/src/jupyter/JupyterContext.tsx | 4 +- .../jupyter/services/ServiceManagerLess.ts | 1 + packages/react/src/state/JupyterReactState.ts | 6 +- packages/react/webpack.config.js | 4 +- 12 files changed, 143 insertions(+), 182 deletions(-) rename packages/react/src/examples/{IPyWidgetsWithState.tsx => IPyWidgetsState.tsx} (92%) delete mode 100644 packages/react/src/examples/NotebookUrl.tsx diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index 03a0557b..5fd260a8 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -59,7 +59,7 @@ export type INotebookProps = { * @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, @@ -85,34 +85,50 @@ export const Notebook = (props: INotebookProps) => { { ...props, id, - lite: lite || props.lite, + lite, kernel, - serviceManager: serviceManager ?? props.serviceManager, - }, + serviceManager, + } ); - console.log('Created Notebook Adapter', adapter); + console.log('Notebook Adapter is created', adapter); + // Update the local state. setAdapter(adapter); - notebookStore.update({ - id, - state: { 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 activeCell = adapter.notebookPanel!.content.activeCell; - if (activeCell) { - notebookStore.activeCellChange({ - id, - cellModel: activeCell, - }); + const cellModel = adapter.notebookPanel!.content.activeCell; + if (cellModel) { + notebookStore.activeCellChange({ id, cellModel }); } - const activeCellChanged$ = asObservable( - adapter.notebookPanel!.content.activeCellChanged - ); + const activeCellChanged$ = asObservable(adapter.notebookPanel!.content.activeCellChanged); activeCellChanged$.subscribe((cellModel: Cell) => { notebookStore.activeCellChange({ id, cellModel }); - const panelDiv = document.getElementById( - 'right-panel-id' - ) as HTMLDivElement; + const panelDiv = document.getElementById('right-panel-id') as HTMLDivElement; if (panelDiv) { const cellMetadataOptions = ( @@ -124,43 +140,10 @@ export const Notebook = (props: INotebookProps) => { ); const portal = createPortal(cellMetadataOptions, panelDiv); - notebookStore.setPortalDisplay({ - id, - portalDisplay: { portal, pinned: false }, - }); + notebookStore.setPortalDisplay({ id, portalDisplay: { portal, pinned: false } }); } }); } - 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 }); - } - ); }); } const createAdapter = (kernel?: Kernel) => { @@ -184,13 +167,22 @@ export const Notebook = (props: INotebookProps) => { } }, []); useEffect(() => { - if (id && serviceManager && kernelManager && (kernel || serverless)) { + /* + 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); } - }, [id, serviceManager, kernelManager, kernel, lite, serverless]); + }, [serviceManager, kernel, serverless, lite]); useEffect(() => { if (adapter && nbformat && adapter.nbformat !== nbformat) { adapter.setNbformat(nbformat); @@ -212,7 +204,7 @@ export const Notebook = (props: INotebookProps) => { if (adapter && url && adapter.readonly !== readonly) { adapter.setReadonly(readonly); } - }, [readonly]); + }, [readonly]); return ( { ); -}; +} Notebook.defaultProps = { cellMetadataPanel: false, diff --git a/packages/react/src/components/notebook/NotebookAdapter.ts b/packages/react/src/components/notebook/NotebookAdapter.ts index 9bf18b6f..f9ef6c73 100755 --- a/packages/react/src/components/notebook/NotebookAdapter.ts +++ b/packages/react/src/components/notebook/NotebookAdapter.ts @@ -9,43 +9,16 @@ 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 { - Notebook, - 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'; @@ -53,13 +26,12 @@ import { WIDGET_MIMETYPE } from '@jupyter-widgets/html-manager/lib/output_render 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 { 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 { WidgetLabRenderer } from '../../jupyter/ipywidgets/lab/renderer'; +import { getMarked } from './marked/marked'; +import { WidgetManager, WidgetLabRenderer } from '../../jupyter/ipywidgets'; const FALLBACK_NOTEBOOK_PATH = 'ping.ipynb'; @@ -88,18 +60,19 @@ export class NotebookAdapter { private _tracker?: NotebookTracker; 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._url = props.url; this._readonly = props.readonly; - this._serverless = props.serverless; this._renderers = props.renderers; + this._serverless = props.serverless; this._serviceManager = props.serviceManager!; - this._CellSidebar = props.CellSidebar; + this._url = props.url; + this._boxPanel = new BoxPanel(); this._boxPanel.addClass('dla-Jupyter-Notebook'); this._boxPanel.spacing = 0; @@ -347,6 +320,7 @@ export class NotebookAdapter { (this._context as Context).model.sharedModel.clearUndoHistory(); }; } + this._context.initialize(isNbFormat).then(() => { if (isNbFormat) { this._notebookPanel?.model?.fromJSON(this._nbformat!); @@ -357,9 +331,7 @@ export class NotebookAdapter { private setupAdapter(): void { - const useCapture = true; - - document.addEventListener( 'keydown', this.notebookKeydownListener, useCapture); + document.addEventListener('keydown', this.notebookKeydownListener, true); const initialFactories = standardRendererFactories.filter( factory => factory.mimeTypes[0] !== 'text/javascript' @@ -440,15 +412,16 @@ export class NotebookAdapter { mimeTypeService, }; const editorFactory = editorServices.factoryService.newInlineEditor; - const contentFactory = this._CellSidebar - ? new JupyterReactContentFactory( + const contentFactory = this._CellSidebar ? + new JupyterReactContentFactory( this._CellSidebar, this._id, this._nbgrader, this._commandRegistry, { editorFactory }, ) - : new NotebookPanel.ContentFactory({ editorFactory }); + : + new NotebookPanel.ContentFactory({ editorFactory }); this._tracker = new NotebookTracker({ namespace: this._id }); @@ -483,13 +456,6 @@ export class NotebookAdapter { } - assignKernel(kernel: Kernel) { - this._kernel = kernel; - this._context?.sessionContext.changeKernel({ - id: kernel.id, - }); - } - get id(): string { return this._id; } @@ -539,7 +505,7 @@ export class NotebookAdapter { } /* - * 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) { @@ -551,6 +517,18 @@ export class NotebookAdapter { } } + 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; @@ -565,6 +543,13 @@ export class NotebookAdapter { } } + assignKernel(kernel: Kernel) { + this._kernel = kernel; + this._context?.sessionContext.changeKernel({ + id: kernel.id, + }); + } + setDefaultCellType = (cellType: CellType) => { this._notebookPanel!.content!.notebookConfig!.defaultCell! = cellType; }; diff --git a/packages/react/src/components/notebook/NotebookState.ts b/packages/react/src/components/notebook/NotebookState.ts index d2cab409..6cfb666e 100644 --- a/packages/react/src/components/notebook/NotebookState.ts +++ b/packages/react/src/components/notebook/NotebookState.ts @@ -233,7 +233,6 @@ export const notebookStore = createStore((set, get) => ({ 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/examples/CellsExecute.tsx b/packages/react/src/examples/CellsExecute.tsx index 25aaae3b..c285520a 100644 --- a/packages/react/src/examples/CellsExecute.tsx +++ b/packages/react/src/examples/CellsExecute.tsx @@ -11,12 +11,14 @@ 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); diff --git a/packages/react/src/examples/IPyWidgetsWithState.tsx b/packages/react/src/examples/IPyWidgetsState.tsx similarity index 92% rename from packages/react/src/examples/IPyWidgetsWithState.tsx rename to packages/react/src/examples/IPyWidgetsState.tsx index d03c263c..f115f3a7 100644 --- a/packages/react/src/examples/IPyWidgetsWithState.tsx +++ b/packages/react/src/examples/IPyWidgetsState.tsx @@ -13,7 +13,7 @@ import { CellSidebar } from '../components/notebook/cell/sidebar/CellSidebar'; import notebook from './notebooks/IPyWidgetsExampleWithState.ipynb.json'; -const IPyWidgetsWithState = () => ( +const IPyWidgetsState = () => ( ); +root.render(); diff --git a/packages/react/src/examples/NotebookMutations.tsx b/packages/react/src/examples/NotebookMutations.tsx index 37278911..39f1040a 100644 --- a/packages/react/src/examples/NotebookMutations.tsx +++ b/packages/react/src/examples/NotebookMutations.tsx @@ -63,7 +63,9 @@ const NotebookMutations = () => { changeIndex(index)} aria-label="jupyter-react-example"> Readonly Browser Kernel - CPU Kernel + OSS Kernel + Datalayer CPU Kernel + Datalayer GPU Kernel @@ -76,7 +78,7 @@ const NotebookMutations = () => { Lite: {String(notebook?.adapter?.lite)} - Kernel ID: {notebook?.adapter?.kernel?.id} + Kernel: {notebook?.adapter?.kernel?.id} ({notebook?.adapter?.kernel?.info?.banner}) Service Manager Ready: {String(notebook?.adapter?.serviceManager.isReady)} diff --git a/packages/react/src/examples/NotebookServiceManager.tsx b/packages/react/src/examples/NotebookServiceManager.tsx index 97eb7778..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 { Kernel } from '../jupyter/kernel/Kernel'; -import ServiceManagerLess from '../jupyter/services/ServiceManagerLess'; +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 ServiceManagerLess()); - 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/NotebookUrl.tsx b/packages/react/src/examples/NotebookUrl.tsx deleted file mode 100644 index 3db860f5..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 { 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 div = document.createElement('div'); -document.body.appendChild(div); -const root = createRoot(div); - -root.render( - - - -); diff --git a/packages/react/src/jupyter/JupyterContext.tsx b/packages/react/src/jupyter/JupyterContext.tsx index bb9660fb..7a09de3a 100644 --- a/packages/react/src/jupyter/JupyterContext.tsx +++ b/packages/react/src/jupyter/JupyterContext.tsx @@ -183,11 +183,11 @@ const JupyterProvider = JupyterContext.Provider; export const useJupyter = (props?: JupyterPropsType): JupyterContextType => { const context = useContext(JupyterContext); if (context) { - // We are within a Jupyter context, just return the that 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 + // We are not within a React Context, so create a JupyterContext // from the store based on the provided props. const { jupyterConfig, diff --git a/packages/react/src/jupyter/services/ServiceManagerLess.ts b/packages/react/src/jupyter/services/ServiceManagerLess.ts index 0bec789a..119c014f 100644 --- a/packages/react/src/jupyter/services/ServiceManagerLess.ts +++ b/packages/react/src/jupyter/services/ServiceManagerLess.ts @@ -407,6 +407,7 @@ export class ServiceManagerLess implements ServiceManager.IManager { 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); diff --git a/packages/react/src/state/JupyterReactState.ts b/packages/react/src/state/JupyterReactState.ts index ef322754..cd8ba753 100644 --- a/packages/react/src/state/JupyterReactState.ts +++ b/packages/react/src/state/JupyterReactState.ts @@ -121,13 +121,13 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR useEffect(() => { if (propsServiceManager) { - console.log('Setting service manager from props', 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 ServiceManagerLess(); @@ -169,7 +169,7 @@ export function useJupyterReactStoreFromProps(props: JupyterPropsType): JupyterR } }, [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/webpack.config.js b/packages/react/webpack.config.js index 7df1739f..4fc5a660 100644 --- a/packages/react/webpack.config.js +++ b/packages/react/webpack.config.js @@ -29,7 +29,7 @@ const ENTRY = // './src/examples/IPyLeaflet'; // './src/examples/IPyReact'; // './src/examples/IPyWidgets'; - // './src/examples/IPyWidgetsWithState'; + // './src/examples/IPyWidgetsState'; // './src/examples/JupyterContext'; // './src/examples/JupyterLabApp'; // './src/examples/JupyterLabAppHeadless'; @@ -56,7 +56,7 @@ const ENTRY = // './src/examples/NotebookSkeleton'; // './src/examples/NotebookTheme'; // './src/examples/NotebookThemeColormode'; - // './src/examples/NotebookUrl'; + // './src/examples/NotebookURL'; // './src/examples/ObservableHQ'; // './src/examples/Output'; // './src/examples/OutputWithErrorHandle';