diff --git a/packages/controls/css/widgets-base.css b/packages/controls/css/widgets-base.css index 6a16589ddc..52815a2fe8 100644 --- a/packages/controls/css/widgets-base.css +++ b/packages/controls/css/widgets-base.css @@ -125,6 +125,14 @@ flex-direction: column; } +.jupyter-widget-output { + box-sizing: border-box; + display: flex; + margin: 0; + overflow: auto; + flex-direction: column; +} + /* General Tags Styling */ .jupyter-widget-tagsinput { @@ -907,7 +915,7 @@ flex: 1 1 var(--jp-widgets-inline-width-short); outline: none !important; overflow: auto; - height: inherit; + height: 100%; /* Because Firefox defines the baseline of a select as the bottom of the control, we align the entire control to the top and add padding to the diff --git a/python/jupyterlab_widgets/src/output.ts b/python/jupyterlab_widgets/src/output.ts index 37793bf193..424bcff279 100644 --- a/python/jupyterlab_widgets/src/output.ts +++ b/python/jupyterlab_widgets/src/output.ts @@ -3,13 +3,13 @@ import * as outputBase from '@jupyter-widgets/output'; -import { JupyterLuminoPanelWidget } from '@jupyter-widgets/base'; - -import { Panel } from '@lumino/widgets'; - import { LabWidgetManager, WidgetManager } from './manager'; -import { OutputAreaModel, OutputArea } from '@jupyterlab/outputarea'; +import { + OutputArea, + SimplifiedOutputArea, + OutputAreaModel, +} from '@jupyterlab/outputarea'; import * as nbformat from '@jupyterlab/nbformat'; @@ -17,6 +17,8 @@ import { KernelMessage, Session } from '@jupyterlab/services'; import $ from 'jquery'; +import type { Message } from '@lumino/messaging'; + export const OUTPUT_WIDGET_VERSION = outputBase.OUTPUT_WIDGET_VERSION; export class OutputModel extends outputBase.OutputModel { @@ -125,7 +127,15 @@ export class OutputModel extends outputBase.OutputModel { export class OutputView extends outputBase.OutputView { _createElement(tagName: string): HTMLElement { - this.luminoWidget = new JupyterLuminoPanelWidget({ view: this }); + this.luminoWidget = new JupyterOutputArea({ + view: this, + rendermime: this.model.widget_manager.rendermime, + contentFactory: OutputArea.defaultContentFactory, + model: this.model.outputs, + promptOverlay: false, + }); + this.luminoWidget.addClass('jupyter-widgets'); + this.luminoWidget.addClass('jupyter-widget-output'); return this.luminoWidget.node; } @@ -139,33 +149,41 @@ export class OutputView extends outputBase.OutputView { this.$el = $(this.luminoWidget.node); } - /** - * Called when view is rendered. - */ - render(): void { - super.render(); - this._outputView = new OutputArea({ - rendermime: this.model.widget_manager.rendermime, - contentFactory: OutputArea.defaultContentFactory, - model: this.model.outputs, - }); - // TODO: why is this a readonly property now? - // this._outputView.model = this.model.outputs; - // TODO: why is this on the model now? - // this._outputView.trusted = true; - this.luminoWidget.insertWidget(0, this._outputView); + model: OutputModel; + luminoWidget: JupyterOutputArea; +} - this.luminoWidget.addClass('jupyter-widgets'); - this.luminoWidget.addClass('widget-output'); - this.update(); // Set defaults. +class JupyterOutputArea extends SimplifiedOutputArea { + constructor(options: JupyterOutputArea.IOptions & OutputArea.IOptions) { + const view = options.view; + delete (options as any).view; + super(options); + this._view = view; } - remove(): any { - this._outputView.dispose(); - return super.remove(); + processMessage(msg: Message): void { + super.processMessage(msg); + this._view?.processLuminoMessage(msg); + } + /** + * Dispose the widget. + * + * This causes the view to be destroyed as well with 'remove' + */ + dispose(): void { + if (this.isDisposed) { + return; + } + super.dispose(); + this._view?.remove(); + this._view = null!; } - model: OutputModel; - _outputView: OutputArea; - luminoWidget: Panel; + private _view: OutputView; +} + +export namespace JupyterOutputArea { + export interface IOptions { + view: OutputView; + } }