diff --git a/.changeset/tiny-cobras-bake.md b/.changeset/tiny-cobras-bake.md new file mode 100644 index 00000000..4b2ba891 --- /dev/null +++ b/.changeset/tiny-cobras-bake.md @@ -0,0 +1,33 @@ +--- +"@difizen/libro-cofine-editor-contribution": patch +"@difizen/libro-cofine-editor-core": patch +"@difizen/libro-search-code-cell": patch +"@difizen/libro-cofine-textmate": patch +"@difizen/libro-language-client": patch +"@difizen/libro-cofine-editor": patch +"@difizen/libro-markdown-cell": patch +"@difizen/libro-shared-model": patch +"@difizen/libro-code-editor": patch +"@difizen/libro-prompt-cell": patch +"@difizen/libro-virtualized": patch +"@difizen/libro-codemirror": patch +"@difizen/libro-rendermime": patch +"@difizen/libro-code-cell": patch +"@difizen/libro-markdown": patch +"@difizen/libro-raw-cell": patch +"@difizen/libro-terminal": patch +"@difizen/libro-jupyter": patch +"@difizen/libro-common": patch +"@difizen/libro-kernel": patch +"@difizen/libro-output": patch +"@difizen/libro-search": patch +"@difizen/libro-widget": patch +"@difizen/libro-core": patch +"@difizen/libro-l10n": patch +"@difizen/libro-lab": patch +"@difizen/libro-lsp": patch +"@difizen/libro-toc": patch +"@difizen/libro-docs": patch +--- + +Jupyter: integrate jupyter-widgets diff --git a/packages/libro-jupyter/package.json b/packages/libro-jupyter/package.json index 3181e626..03dde5e2 100644 --- a/packages/libro-jupyter/package.json +++ b/packages/libro-jupyter/package.json @@ -60,6 +60,7 @@ "@difizen/libro-markdown-cell": "^0.1.30", "@difizen/libro-raw-cell": "^0.1.30", "@difizen/libro-language-client": "^0.1.30", + "@difizen/libro-widget": "^0.1.30", "@difizen/mana-app": "latest", "@difizen/mana-l10n": "latest", "@ant-design/colors": "^7.0.0", diff --git a/packages/libro-jupyter/src/module.ts b/packages/libro-jupyter/src/module.ts index edd88a48..e412897f 100644 --- a/packages/libro-jupyter/src/module.ts +++ b/packages/libro-jupyter/src/module.ts @@ -25,6 +25,7 @@ import { import { RawCellModule } from '@difizen/libro-raw-cell'; import { LibroSearchModule } from '@difizen/libro-search'; import { SearchCodeCellModule } from '@difizen/libro-search-code-cell'; +import { WidgetModule } from '@difizen/libro-widget'; import { ManaModule } from '@difizen/mana-app'; import { LibroBetweenCellModule } from './add-between-cell/index.js'; @@ -56,6 +57,7 @@ import { LibroJupyterToolbarContribution, SaveFileErrorContribution, } from './toolbar/index.js'; +import { LibroWidgetMimeContribution } from './widget/index.js'; export const LibroJupyterModule = ManaModule.create() .register( @@ -74,6 +76,7 @@ export const LibroJupyterModule = ManaModule.create() LibroJupyterSettingContribution, JupyterServerLaunchManager, LibroJupyterView, + LibroWidgetMimeContribution, { token: CellExecutionTimeProvider, useValue: CellExecutionTip, @@ -114,4 +117,5 @@ export const LibroJupyterModule = ManaModule.create() PlotlyModule, LibroJupyterFileModule, LibroLanguageClientModule, + WidgetModule, ); diff --git a/packages/libro-jupyter/src/widget/index.less b/packages/libro-jupyter/src/widget/index.less new file mode 100644 index 00000000..da2971f3 --- /dev/null +++ b/packages/libro-jupyter/src/widget/index.less @@ -0,0 +1,7 @@ +.libro-widget-render { + margin: 10px 24px; +} + +.libro-widget-render:empty { + margin: unset; +} diff --git a/packages/libro-jupyter/src/widget/index.ts b/packages/libro-jupyter/src/widget/index.ts new file mode 100644 index 00000000..edb5f0ab --- /dev/null +++ b/packages/libro-jupyter/src/widget/index.ts @@ -0,0 +1,2 @@ +export * from './widget-render.js'; +export * from './widget-rendermime-contribution.js'; diff --git a/packages/libro-jupyter/src/widget/widget-render.tsx b/packages/libro-jupyter/src/widget/widget-render.tsx new file mode 100644 index 00000000..2b955b86 --- /dev/null +++ b/packages/libro-jupyter/src/widget/widget-render.tsx @@ -0,0 +1,47 @@ +import type { BaseOutputView } from '@difizen/libro-core'; +import { RenderMimeRegistry } from '@difizen/libro-rendermime'; +import type { IRenderMimeRegistry } from '@difizen/libro-rendermime'; +import { LibroWidgetManager } from '@difizen/libro-widget'; +import { getOrigin, useInject, ViewRender } from '@difizen/mana-app'; +import React from 'react'; +import './index.less'; + +import { LibroJupyterModel } from '../libro-jupyter-model.js'; + +export const WidgetRender: React.FC<{ model: BaseOutputView }> = (props: { + model: BaseOutputView; +}) => { + const { model } = props; + + const widgetManager = useInject(LibroWidgetManager); + const defaultRenderMime = useInject(RenderMimeRegistry); + const libro = model.cell.parent; + if (!(libro.model instanceof LibroJupyterModel) || !libro.model.kernelConnection) { + return null; + } + const widgets = widgetManager.getOrCreateWidgets( + getOrigin(libro.model.kernelConnection), + ); + const mimeType = defaultRenderMime.preferredMimeType(model); + if (mimeType) { + const model_id = JSON.parse(JSON.stringify(model.data[mimeType])).model_id; + if (model_id) { + const widgetView = widgets.getModel(model_id); + if (widgetView.isCommClosed) { + return null; + } + return ( +
+
+ +
+
+ ); + } + } + return ( +
+
+
+ ); +}; diff --git a/packages/libro-jupyter/src/widget/widget-rendermime-contribution.ts b/packages/libro-jupyter/src/widget/widget-rendermime-contribution.ts new file mode 100644 index 00000000..4e4310cf --- /dev/null +++ b/packages/libro-jupyter/src/widget/widget-rendermime-contribution.ts @@ -0,0 +1,35 @@ +import type { BaseOutputView } from '@difizen/libro-core'; +import { RenderMimeContribution } from '@difizen/libro-rendermime'; +import { LibroWidgetManager } from '@difizen/libro-widget'; +import { inject, singleton } from '@difizen/mana-app'; + +import { LibroJupyterModel } from '../libro-jupyter-model.js'; + +import { WidgetRender } from './widget-render.js'; + +@singleton({ contrib: RenderMimeContribution }) +export class LibroWidgetMimeContribution implements RenderMimeContribution { + @inject(LibroWidgetManager) libroWidgetManager: LibroWidgetManager; + canHandle = (model: BaseOutputView) => { + const libroModel = model.cell.parent.model; + let rank = 0; + if (libroModel instanceof LibroJupyterModel && libroModel.kernelConnection) { + const kc = libroModel.kernelConnection; + const widget = this.libroWidgetManager.getOrCreateWidgets(kc); + this.mimeTypes.forEach((mimeType) => { + const mimeData = model.data[mimeType]; + if (mimeData && mimeData !== null) { + const data = JSON.parse(JSON.stringify(mimeData)).model_id; + if (Object.keys(model.data).includes(mimeType) && widget.hasModel(data)) { + rank = 100; + } + } + }); + } + return rank; + }; + renderType = 'widgetRenderer'; + safe = true; + mimeTypes = ['application/vnd.jupyter.widget-view+json']; + render = WidgetRender; +} diff --git a/packages/libro-kernel/src/kernel/kernel-connection.ts b/packages/libro-kernel/src/kernel/kernel-connection.ts index 3b92f992..4cc51837 100644 --- a/packages/libro-kernel/src/kernel/kernel-connection.ts +++ b/packages/libro-kernel/src/kernel/kernel-connection.ts @@ -1287,7 +1287,7 @@ export class KernelConnection implements IKernelConnection { // Close the comm asynchronously. We cannot block message processing on // kernel messages to wait for another kernel message. comm.close(); - console.error('Exception opening new comm'); + console.error('Exception opening new comm', e); throw e; } }