jupyter-specta 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/app.js +1 -1
  2. package/lib/components/cellSkeleton.d.ts +6 -0
  3. package/lib/components/cellSkeleton.js +19 -0
  4. package/lib/components/divider.d.ts +2 -0
  5. package/lib/components/divider.js +4 -0
  6. package/lib/components/icon/gear.d.ts +2 -0
  7. package/lib/components/icon/gear.js +17 -0
  8. package/lib/components/iconButton.d.ts +8 -0
  9. package/lib/components/iconButton.js +4 -0
  10. package/lib/document/factory.d.ts +5 -1
  11. package/lib/document/factory.js +12 -3
  12. package/lib/document/plugin.js +5 -1
  13. package/lib/extension_plugins.js +7 -1
  14. package/lib/layout/article.d.ts +12 -0
  15. package/lib/layout/article.js +35 -0
  16. package/lib/layout/default.js +2 -5
  17. package/lib/layout/layout_registry.d.ts +1 -0
  18. package/lib/layout/layout_registry.js +6 -0
  19. package/lib/layout/plugin.js +5 -0
  20. package/lib/shell.js +0 -1
  21. package/lib/specta_cell_output.d.ts +9 -2
  22. package/lib/specta_cell_output.js +20 -1
  23. package/lib/specta_model.d.ts +1 -2
  24. package/lib/specta_model.js +74 -12
  25. package/lib/specta_widget.d.ts +5 -1
  26. package/lib/specta_widget.js +23 -7
  27. package/lib/specta_widget_factory.d.ts +2 -1
  28. package/lib/specta_widget_factory.js +6 -2
  29. package/lib/token.d.ts +13 -0
  30. package/lib/tool.d.ts +3 -1
  31. package/lib/tool.js +5 -16
  32. package/lib/topbar/kernelStatus.d.ts +28 -0
  33. package/lib/topbar/kernelStatus.js +20 -0
  34. package/lib/topbar/plugin.d.ts +5 -0
  35. package/lib/topbar/plugin.js +32 -0
  36. package/lib/topbar/settingDialog.d.ts +7 -0
  37. package/lib/topbar/settingDialog.js +73 -0
  38. package/lib/topbar/widget.d.ts +9 -0
  39. package/lib/topbar/widget.js +41 -0
  40. package/package.json +18 -11
  41. package/style/article.css +314 -0
  42. package/style/base.css +125 -0
  43. package/style/index.css +2 -0
  44. package/style/index.js +3 -1
  45. package/style/skeleton.css +87 -0
  46. package/style/style.css +9 -4
package/lib/app.js CHANGED
@@ -8,7 +8,7 @@ export class SpectaApp extends JupyterFrontEnd {
8
8
  /**
9
9
  * The name of the application.
10
10
  */
11
- this.name = 'Voila';
11
+ this.name = 'specta';
12
12
  /**
13
13
  * A namespace/prefix plugins may use to denote their provenance.
14
14
  */
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare function SkeletonBarChart({ bars }: {
3
+ bars?: number;
4
+ }): React.JSX.Element;
5
+ export declare function SkeletonLineChart(): React.JSX.Element;
6
+ export declare function RandomSkeleton(): React.JSX.Element;
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ export function SkeletonBarChart({ bars = 5 }) {
3
+ return (React.createElement("div", { className: "skeleton-bar-chart vertical" },
4
+ React.createElement("div", { className: "skeleton-label" }, "Executing cell"),
5
+ Array.from({ length: bars }).map((_, i) => (React.createElement("div", { key: i, className: "bar vertical-bar", style: { animationDelay: `${i * 0.4}s` } })))));
6
+ }
7
+ export function SkeletonLineChart() {
8
+ return (React.createElement("div", { className: "skeleton-line-chart" },
9
+ React.createElement("div", { className: "skeleton-label" }, "Executing cell"),
10
+ React.createElement("svg", { viewBox: "0 0 100 40", preserveAspectRatio: "none" },
11
+ React.createElement("polyline", { points: "0,30 20,20 40,25 60,15 80,10 100,20" }))));
12
+ }
13
+ export function RandomSkeleton() {
14
+ const random = Math.random();
15
+ if (random < 0.5) {
16
+ return React.createElement(SkeletonLineChart, null);
17
+ }
18
+ return React.createElement(SkeletonBarChart, null);
19
+ }
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const Divider: () => React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export const Divider = () => {
3
+ return React.createElement("div", { className: "specta-divider" });
4
+ };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const GearIcon: ({ ...props }: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
@@ -0,0 +1,17 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React from 'react';
13
+ export const GearIcon = (_a) => {
14
+ var props = __rest(_a, []);
15
+ return (React.createElement("svg", Object.assign({ xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px" }, props),
16
+ React.createElement("path", { d: "m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" })));
17
+ };
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export declare const IconButton: React.ForwardRefExoticComponent<{
3
+ icon: JSX.Element;
4
+ onClick: () => void;
5
+ title?: string | undefined;
6
+ disabled?: boolean | undefined;
7
+ className?: string | undefined;
8
+ } & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,4 @@
1
+ import React, { forwardRef } from 'react';
2
+ export const IconButton = forwardRef(({ icon, onClick, title, disabled, className }, ref) => {
3
+ return (React.createElement("button", { ref: ref, className: `jp-Button specta-icon-button ${className !== null && className !== void 0 ? className : ''}`, title: title, disabled: disabled, onClick: onClick }, icon));
4
+ });
@@ -1,9 +1,13 @@
1
+ import { IThemeManager } from '@jupyterlab/apputils';
1
2
  import { ABCWidgetFactory, DocumentRegistry } from '@jupyterlab/docregistry';
2
- import { NotebookSpectaDocWidget } from './widget';
3
3
  import { INotebookModel } from '@jupyterlab/notebook';
4
4
  import { SpectaWidgetFactory } from '../specta_widget_factory';
5
+ import { ISpectaLayoutRegistry } from '../token';
6
+ import { NotebookSpectaDocWidget } from './widget';
5
7
  interface IOptions extends DocumentRegistry.IWidgetFactoryOptions {
6
8
  spectaWidgetFactory: SpectaWidgetFactory;
9
+ layoutRegistry?: ISpectaLayoutRegistry;
10
+ themeManager?: IThemeManager;
7
11
  }
8
12
  export declare class NotebookGridWidgetFactory extends ABCWidgetFactory<NotebookSpectaDocWidget, INotebookModel> {
9
13
  constructor(options: IOptions);
@@ -1,20 +1,29 @@
1
1
  import { ABCWidgetFactory } from '@jupyterlab/docregistry';
2
+ import { ReactWidget } from '@jupyterlab/ui-components';
3
+ import { Panel } from '@lumino/widgets';
4
+ import * as React from 'react';
5
+ import { isSpectaApp } from '../tool';
6
+ import { TopbarElement } from '../topbar/widget';
2
7
  import { NotebookSpectaDocWidget } from './widget';
3
- import { Widget } from '@lumino/widgets';
4
8
  export class NotebookGridWidgetFactory extends ABCWidgetFactory {
5
9
  constructor(options) {
6
10
  super(options);
7
11
  this._spectaWidgetFactory = options.spectaWidgetFactory;
8
12
  }
9
13
  createNewWidget(context) {
10
- const content = new Widget();
14
+ const content = new Panel();
11
15
  content.addClass('jp-specta-notebook-panel');
16
+ if (!isSpectaApp()) {
17
+ // Not a specta app, add topbar to document widget
18
+ const topbar = ReactWidget.create(React.createElement(TopbarElement, null));
19
+ content.addWidget(topbar);
20
+ }
12
21
  context.ready.then(async () => {
13
22
  const spectaWidget = await this._spectaWidgetFactory.createNew({
14
23
  context
15
24
  });
16
25
  if (spectaWidget) {
17
- Widget.attach(spectaWidget, content.node);
26
+ content.addWidget(spectaWidget);
18
27
  }
19
28
  });
20
29
  const widget = new NotebookSpectaDocWidget({
@@ -6,9 +6,12 @@ import { IDocumentManager } from '@jupyterlab/docmanager';
6
6
  import { createFileBrowser, hideAppLoadingIndicator, isSpectaApp, registerDocumentFactory } from '../tool';
7
7
  import { ISpectaDocTracker, ISpectaLayoutRegistry } from '../token';
8
8
  import { IKernelSpecManager } from '@jupyterlab/services';
9
+ import { PageConfig } from '@jupyterlab/coreutils';
9
10
  const activate = (app, rendermime, tracker, editorServices, contentFactory, spectaLayoutRegistry) => {
11
+ var _a;
10
12
  const namespace = 'specta';
11
13
  const spectaTracker = new WidgetTracker({ namespace });
14
+ const spectaConfig = JSON.parse((_a = PageConfig.getOption('spectaConfig')) !== null && _a !== void 0 ? _a : '{}');
12
15
  registerDocumentFactory({
13
16
  factoryName: 'specta',
14
17
  app,
@@ -17,7 +20,8 @@ const activate = (app, rendermime, tracker, editorServices, contentFactory, spec
17
20
  editorServices,
18
21
  contentFactory,
19
22
  spectaTracker,
20
- spectaLayoutRegistry
23
+ spectaLayoutRegistry,
24
+ spectaConfig
21
25
  });
22
26
  return spectaTracker;
23
27
  };
@@ -1,5 +1,11 @@
1
1
  import { spectaDocument, spectaOpener } from './document/plugin';
2
2
  import { spectaLayoutRegistry } from './layout/plugin';
3
+ import { topbarPlugin } from './topbar/plugin';
3
4
  export * from './tool';
4
5
  export * from './token';
5
- export default [spectaDocument, spectaOpener, spectaLayoutRegistry];
6
+ export default [
7
+ spectaDocument,
8
+ spectaOpener,
9
+ spectaLayoutRegistry,
10
+ topbarPlugin
11
+ ];
@@ -0,0 +1,12 @@
1
+ import { Panel } from '@lumino/widgets';
2
+ import { SpectaCellOutput } from '../specta_cell_output';
3
+ import * as nbformat from '@jupyterlab/nbformat';
4
+ import { ISpectaLayout } from '../token';
5
+ export declare class ArticleLayout implements ISpectaLayout {
6
+ render(options: {
7
+ host: Panel;
8
+ items: SpectaCellOutput[];
9
+ notebook: nbformat.INotebookContent;
10
+ readyCallback: () => Promise<void>;
11
+ }): Promise<void>;
12
+ }
@@ -0,0 +1,35 @@
1
+ import { Panel } from '@lumino/widgets';
2
+ class HostPanel extends Panel {
3
+ constructor() {
4
+ super();
5
+ this.addClass('specta-article-host-widget');
6
+ this._outputs = new Panel();
7
+ this._outputs.addClass('specta-article-outputs-panel');
8
+ this.addWidget(this._outputs);
9
+ }
10
+ addOutput(widget) {
11
+ this._outputs.addWidget(widget);
12
+ }
13
+ }
14
+ export class ArticleLayout {
15
+ async render(options) {
16
+ const { host, items, readyCallback } = options;
17
+ const hostPanel = new HostPanel();
18
+ for (const el of items) {
19
+ const cellModel = el.info.cellModel;
20
+ const info = el.info;
21
+ if ((cellModel === null || cellModel === void 0 ? void 0 : cellModel.cell_type) === 'code') {
22
+ if (!info.hidden) {
23
+ hostPanel.addOutput(el);
24
+ }
25
+ }
26
+ else {
27
+ if (!info.hidden) {
28
+ hostPanel.addOutput(el);
29
+ }
30
+ }
31
+ }
32
+ host.addWidget(hostPanel);
33
+ await readyCallback();
34
+ }
35
+ }
@@ -2,14 +2,11 @@ export class DefaultLayout {
2
2
  async render(options) {
3
3
  const { host, items, readyCallback } = options;
4
4
  for (const el of items) {
5
- const outputNode = el.cellOutput.node;
6
5
  const cellModel = el.info.cellModel;
7
6
  const info = el.info;
8
7
  if ((cellModel === null || cellModel === void 0 ? void 0 : cellModel.cell_type) === 'code') {
9
- if (outputNode.childNodes.length > 0) {
10
- if (!info.hidden) {
11
- host.addWidget(el);
12
- }
8
+ if (!info.hidden) {
9
+ host.addWidget(el);
13
10
  }
14
11
  }
15
12
  else {
@@ -12,6 +12,7 @@ export declare class SpectaLayoutRegistry implements ISpectaLayoutRegistry {
12
12
  layout: ISpectaLayout;
13
13
  }>;
14
14
  get(name: string): ISpectaLayout | undefined;
15
+ getDefaultLayout(): ISpectaLayout;
15
16
  setSelectedLayout(name: string): void;
16
17
  register(name: string, layout: ISpectaLayout): void;
17
18
  allLayouts(): string[];
@@ -1,5 +1,6 @@
1
1
  import { Signal } from '@lumino/signaling';
2
2
  import { DefaultLayout } from './default';
3
+ import { ArticleLayout } from './article';
3
4
  export class SpectaLayoutRegistry {
4
5
  constructor() {
5
6
  this._registry = new Map();
@@ -8,6 +9,7 @@ export class SpectaLayoutRegistry {
8
9
  const defaultLayout = new DefaultLayout();
9
10
  this._registry = new Map();
10
11
  this._registry.set('default', defaultLayout);
12
+ this._registry.set('article', new ArticleLayout());
11
13
  this._selectedLayout = {
12
14
  name: 'default',
13
15
  layout: defaultLayout
@@ -25,11 +27,15 @@ export class SpectaLayoutRegistry {
25
27
  get(name) {
26
28
  return this._registry.get(name);
27
29
  }
30
+ getDefaultLayout() {
31
+ return this._registry.get('default');
32
+ }
28
33
  setSelectedLayout(name) {
29
34
  if (!this._registry.has(name)) {
30
35
  throw new Error(`Layout with name ${name} does not exist`);
31
36
  }
32
37
  this._selectedLayout = { name, layout: this._registry.get(name) };
38
+ this._selectedLayoutChanged.emit(this._selectedLayout);
33
39
  }
34
40
  register(name, layout) {
35
41
  if (this._registry.has(name)) {
@@ -1,11 +1,16 @@
1
1
  import { SpectaLayoutRegistry } from './layout_registry';
2
2
  import { ISpectaLayoutRegistry } from '../token';
3
+ import { PageConfig } from '@jupyterlab/coreutils';
3
4
  export const spectaLayoutRegistry = {
4
5
  id: 'specta:layout-registry',
5
6
  autoStart: true,
6
7
  provides: ISpectaLayoutRegistry,
7
8
  activate: (app) => {
9
+ var _a, _b;
8
10
  const layoutRegistry = new SpectaLayoutRegistry();
11
+ const spectaConfig = JSON.parse((_a = PageConfig.getOption('spectaConfig')) !== null && _a !== void 0 ? _a : '{}');
12
+ const defaultLayout = (_b = spectaConfig.layout) !== null && _b !== void 0 ? _b : 'default';
13
+ layoutRegistry.setSelectedLayout(defaultLayout);
9
14
  return layoutRegistry;
10
15
  }
11
16
  };
package/lib/shell.js CHANGED
@@ -30,7 +30,6 @@ export class SpectaShell extends Widget {
30
30
  topHandler.panel.id = 'specta-top-panel';
31
31
  topHandler.panel.node.setAttribute('role', 'banner');
32
32
  BoxLayout.setStretch(topHandler.panel, 0);
33
- topHandler.panel.hide();
34
33
  rootLayout.addWidget(topHandler.panel);
35
34
  const hboxPanel = (this._mainPanel = new BoxPanel());
36
35
  hboxPanel.id = 'jp-main-content-panel';
@@ -1,14 +1,21 @@
1
- import { Panel, Widget } from '@lumino/widgets';
2
1
  import * as nbformat from '@jupyterlab/nbformat';
2
+ import { Panel, Widget } from '@lumino/widgets';
3
3
  export interface ICellInfo {
4
4
  hidden?: boolean;
5
5
  cellModel?: nbformat.ICell;
6
6
  }
7
7
  export declare class SpectaCellOutput extends Panel {
8
- constructor(cellIdentity: string, cell: Widget, info: ICellInfo);
8
+ constructor({ cellIdentity, cell, sourceCell, info }: {
9
+ cellIdentity: string;
10
+ cell: Widget;
11
+ sourceCell?: Widget;
12
+ info: ICellInfo;
13
+ });
9
14
  readonly cellIdentity: string;
10
15
  get cellOutput(): Widget;
11
16
  get info(): ICellInfo;
17
+ removePlaceholder(): void;
12
18
  private _info;
13
19
  private _cellOutput;
20
+ private _placeholder?;
14
21
  }
@@ -1,19 +1,32 @@
1
+ import { ReactWidget } from '@jupyterlab/ui-components';
1
2
  import { Panel } from '@lumino/widgets';
3
+ import React from 'react';
4
+ import { RandomSkeleton } from './components/cellSkeleton';
2
5
  export class SpectaCellOutput extends Panel {
3
- constructor(cellIdentity, cell, info) {
6
+ constructor({ cellIdentity, cell, sourceCell, info }) {
7
+ var _a;
4
8
  super();
5
9
  this._info = {};
10
+ this._placeholder = undefined;
6
11
  this.removeClass('lm-Widget');
7
12
  this.removeClass('p-Widget');
8
13
  this.addClass('specta-cell-output');
9
14
  const content = new Panel();
10
15
  content.addClass('specta-cell-content');
11
16
  cell.addClass('specta-item-widget');
17
+ if (sourceCell) {
18
+ content.addWidget(sourceCell);
19
+ }
12
20
  content.addWidget(cell);
13
21
  this.addWidget(content);
14
22
  this._cellOutput = cell;
15
23
  this.cellIdentity = cellIdentity;
16
24
  this._info = info !== null && info !== void 0 ? info : {};
25
+ if (((_a = info.cellModel) === null || _a === void 0 ? void 0 : _a.cell_type) === 'code') {
26
+ this._placeholder = ReactWidget.create(React.createElement(RandomSkeleton, null));
27
+ this._placeholder.addClass('specta-cell-placeholder');
28
+ this.addWidget(this._placeholder);
29
+ }
17
30
  }
18
31
  get cellOutput() {
19
32
  return this._cellOutput;
@@ -21,4 +34,10 @@ export class SpectaCellOutput extends Panel {
21
34
  get info() {
22
35
  return this._info;
23
36
  }
37
+ removePlaceholder() {
38
+ var _a;
39
+ if (this._placeholder) {
40
+ (_a = this._placeholder) === null || _a === void 0 ? void 0 : _a.dispose();
41
+ }
42
+ }
24
43
  }
@@ -2,7 +2,6 @@ import { ICellModel } from '@jupyterlab/cells';
2
2
  import { IEditorMimeTypeService, IEditorServices } from '@jupyterlab/codeeditor';
3
3
  import { DocumentRegistry } from '@jupyterlab/docregistry';
4
4
  import { CellList, INotebookModel, INotebookTracker, NotebookPanel, StaticNotebook } from '@jupyterlab/notebook';
5
- import { SimplifiedOutputArea } from '@jupyterlab/outputarea';
6
5
  import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
7
6
  import { ServiceManager } from '@jupyterlab/services';
8
7
  import { IExecuteReplyMsg } from '@jupyterlab/services/lib/kernel/messages';
@@ -22,7 +21,7 @@ export declare class AppModel {
22
21
  get panel(): NotebookPanel | undefined;
23
22
  initialize(): Promise<void>;
24
23
  createCell(cellModel: ICellModel): SpectaCellOutput;
25
- executeCell(cell: ICellModel, output: SimplifiedOutputArea): Promise<IExecuteReplyMsg | undefined>;
24
+ executeCell(cell: ICellModel, outputWrapper: SpectaCellOutput): Promise<IExecuteReplyMsg | undefined>;
26
25
  private _notebookPanel?;
27
26
  private _context;
28
27
  private _isDisposed;
@@ -1,7 +1,9 @@
1
- import { MarkdownCell, RawCell } from '@jupyterlab/cells';
1
+ import { CodeCell, MarkdownCell, RawCell } from '@jupyterlab/cells';
2
2
  import { OutputAreaModel, SimplifiedOutputArea } from '@jupyterlab/outputarea';
3
3
  import { createNotebookPanel } from './create_notebook_panel';
4
4
  import { SpectaCellOutput } from './specta_cell_output';
5
+ import { PromiseDelegate } from '@lumino/coreutils';
6
+ import { SPECTA_CELL_VISIBLE_TAG } from './tool';
5
7
  export const VIEW = 'grid_default';
6
8
  export class AppModel {
7
9
  constructor(options) {
@@ -38,16 +40,40 @@ export class AppModel {
38
40
  return this._notebookPanel;
39
41
  }
40
42
  async initialize() {
41
- var _a;
43
+ var _a, _b;
44
+ const pd = new PromiseDelegate();
42
45
  await ((_a = this._context) === null || _a === void 0 ? void 0 : _a.sessionContext.ready);
43
- this._notebookPanel = createNotebookPanel({
44
- context: this._context,
45
- rendermime: this.options.rendermime,
46
- editorServices: this.options.editorServices
47
- });
48
- this.options.tracker.widgetAdded.emit(this._notebookPanel);
46
+ const connectKernel = () => {
47
+ pd.resolve();
48
+ this._notebookPanel = createNotebookPanel({
49
+ context: this._context,
50
+ rendermime: this.options.rendermime,
51
+ editorServices: this.options.editorServices
52
+ });
53
+ this.options.tracker.widgetAdded.emit(this._notebookPanel);
54
+ };
55
+ const kernel = (_b = this._context.sessionContext.session) === null || _b === void 0 ? void 0 : _b.kernel;
56
+ if (kernel) {
57
+ const status = kernel.status;
58
+ if (status !== 'unknown') {
59
+ // Connected to an existing kernel.
60
+ connectKernel();
61
+ return;
62
+ }
63
+ }
64
+ this._context.sessionContext.connectionStatusChanged.connect((_, status) => {
65
+ var _a;
66
+ if (status === 'connected') {
67
+ const kernel = (_a = this._context.sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel;
68
+ if (kernel) {
69
+ connectKernel();
70
+ }
71
+ }
72
+ }, this);
73
+ return pd.promise;
49
74
  }
50
75
  createCell(cellModel) {
76
+ var _a, _b;
51
77
  let item;
52
78
  const cellModelJson = cellModel.toJSON();
53
79
  const info = {
@@ -55,12 +81,35 @@ export class AppModel {
55
81
  };
56
82
  switch (cellModel.type) {
57
83
  case 'code': {
84
+ cellModel.setMetadata('editable', false);
85
+ const codeCell = new CodeCell({
86
+ model: cellModel,
87
+ rendermime: this.options.rendermime,
88
+ contentFactory: this.options.contentFactory,
89
+ editorConfig: {
90
+ lineNumbers: false,
91
+ lineWrap: false,
92
+ tabFocusable: false,
93
+ editable: false
94
+ }
95
+ });
96
+ codeCell.loadEditableState();
58
97
  const outputareamodel = new OutputAreaModel({ trusted: true });
59
98
  const out = new SimplifiedOutputArea({
60
99
  model: outputareamodel,
61
100
  rendermime: this.options.rendermime
62
101
  });
63
- item = new SpectaCellOutput(cellModel.id, out, info);
102
+ const tags = ((_b = (_a = cellModel === null || cellModel === void 0 ? void 0 : cellModel.metadata) === null || _a === void 0 ? void 0 : _a.tags) !== null && _b !== void 0 ? _b : []);
103
+ let sourceCell;
104
+ if (tags.includes(SPECTA_CELL_VISIBLE_TAG)) {
105
+ sourceCell = codeCell;
106
+ }
107
+ item = new SpectaCellOutput({
108
+ cellIdentity: cellModel.id,
109
+ cell: out,
110
+ sourceCell,
111
+ info
112
+ });
64
113
  break;
65
114
  }
66
115
  case 'markdown': {
@@ -70,11 +119,16 @@ export class AppModel {
70
119
  contentFactory: this.options.contentFactory,
71
120
  editorConfig: this.options.editorConfig.markdown
72
121
  });
122
+ markdownCell.initializeState();
73
123
  markdownCell.inputHidden = false;
74
124
  markdownCell.rendered = true;
75
125
  Private.removeElements(markdownCell.node, 'jp-Collapser');
76
126
  Private.removeElements(markdownCell.node, 'jp-InputPrompt');
77
- item = new SpectaCellOutput(cellModel.id, markdownCell, info);
127
+ item = new SpectaCellOutput({
128
+ cellIdentity: cellModel.id,
129
+ cell: markdownCell,
130
+ info
131
+ });
78
132
  break;
79
133
  }
80
134
  default: {
@@ -86,18 +140,26 @@ export class AppModel {
86
140
  rawCell.inputHidden = false;
87
141
  Private.removeElements(rawCell.node, 'jp-Collapser');
88
142
  Private.removeElements(rawCell.node, 'jp-InputPrompt');
89
- item = new SpectaCellOutput(cellModel.id, rawCell, info);
143
+ item = new SpectaCellOutput({
144
+ cellIdentity: cellModel.id,
145
+ cell: rawCell,
146
+ info
147
+ });
90
148
  break;
91
149
  }
92
150
  }
93
151
  return item;
94
152
  }
95
- async executeCell(cell, output) {
153
+ async executeCell(cell, outputWrapper) {
96
154
  if (cell.type !== 'code' || !this._context) {
97
155
  return;
98
156
  }
157
+ const output = outputWrapper.cellOutput;
99
158
  const source = cell.sharedModel.source;
100
159
  const rep = await SimplifiedOutputArea.execute(source, output, this._context.sessionContext);
160
+ output.future.done.then(() => {
161
+ outputWrapper.removePlaceholder();
162
+ });
101
163
  return rep;
102
164
  }
103
165
  }
@@ -1,7 +1,7 @@
1
1
  import { Message } from '@lumino/messaging';
2
2
  import { Panel } from '@lumino/widgets';
3
3
  import { AppModel } from './specta_model';
4
- import { ISpectaLayoutRegistry } from './token';
4
+ import { ISpectaAppConfig, ISpectaLayoutRegistry } from './token';
5
5
  export declare class AppWidget extends Panel {
6
6
  constructor(options: AppWidget.IOptions);
7
7
  /**
@@ -13,11 +13,14 @@ export declare class AppWidget extends Panel {
13
13
  dispose(): void;
14
14
  render(): Promise<void>;
15
15
  protected onCloseRequest(msg: Message): void;
16
+ private _onSelectedLayoutChanged;
16
17
  private _model;
17
18
  private _ready;
18
19
  private _host;
19
20
  private _layoutRegistry;
20
21
  private _loaderHost?;
22
+ private _outputs;
23
+ private _spectaAppConfig;
21
24
  }
22
25
  export declare namespace AppWidget {
23
26
  interface IOptions {
@@ -25,5 +28,6 @@ export declare namespace AppWidget {
25
28
  label: string;
26
29
  model: AppModel;
27
30
  layoutRegistry: ISpectaLayoutRegistry;
31
+ spectaConfig: ISpectaAppConfig;
28
32
  }
29
33
  }
@@ -5,12 +5,13 @@ export class AppWidget extends Panel {
5
5
  constructor(options) {
6
6
  super();
7
7
  this._ready = new PromiseDelegate();
8
+ this._outputs = [];
8
9
  this.node.id = options.id;
9
10
  this.title.label = options.label;
10
11
  this.title.closable = true;
11
12
  this._model = options.model;
13
+ this._spectaAppConfig = options.spectaConfig;
12
14
  this._layoutRegistry = options.layoutRegistry;
13
- this.node.style.padding = '5px';
14
15
  this._host = new Panel();
15
16
  this._host.addClass('specta-output-host');
16
17
  this.addWidget(this._host);
@@ -24,6 +25,7 @@ export class AppWidget extends Panel {
24
25
  .catch(console.error)
25
26
  .then(() => window.dispatchEvent(new Event('resize')));
26
27
  });
28
+ this._layoutRegistry.selectedLayoutChanged.connect(this._onSelectedLayoutChanged, this);
27
29
  }
28
30
  /**
29
31
  * A promise that is fulfilled when the model is ready.
@@ -54,17 +56,17 @@ export class AppWidget extends Panel {
54
56
  super.dispose();
55
57
  }
56
58
  async render() {
57
- var _a;
59
+ var _a, _b, _c, _d;
58
60
  const cellList = (_a = this._model.cells) !== null && _a !== void 0 ? _a : [];
59
- const outputs = [];
61
+ const layout = (_c = (_b = this._spectaAppConfig) === null || _b === void 0 ? void 0 : _b.layout) !== null && _c !== void 0 ? _c : 'default';
60
62
  for (const cell of cellList) {
61
63
  const src = cell.sharedModel.source;
62
64
  if (src.length === 0) {
63
65
  continue;
64
66
  }
65
67
  const el = this._model.createCell(cell);
66
- await this._model.executeCell(cell, el.cellOutput);
67
- outputs.push(el);
68
+ this._model.executeCell(cell, el);
69
+ this._outputs.push(el);
68
70
  }
69
71
  const readyCallback = async () => {
70
72
  if (this._loaderHost) {
@@ -78,9 +80,10 @@ export class AppWidget extends Panel {
78
80
  hideAppLoadingIndicator();
79
81
  }
80
82
  };
81
- await this._layoutRegistry.selectedLayout.layout.render({
83
+ const spectaLayout = (_d = this._layoutRegistry.get(layout)) !== null && _d !== void 0 ? _d : this._layoutRegistry.getDefaultLayout();
84
+ await spectaLayout.render({
82
85
  host: this._host,
83
- items: outputs,
86
+ items: this._outputs,
84
87
  notebook: this._model.context.model.toJSON(),
85
88
  readyCallback
86
89
  });
@@ -89,4 +92,17 @@ export class AppWidget extends Panel {
89
92
  this._model.dispose();
90
93
  super.onCloseRequest(msg);
91
94
  }
95
+ _onSelectedLayoutChanged(sender, args) {
96
+ const currentEls = [...this._host.widgets];
97
+ currentEls.forEach(el => {
98
+ var _a;
99
+ (_a = this._host.layout) === null || _a === void 0 ? void 0 : _a.removeWidget(el);
100
+ });
101
+ args.layout.render({
102
+ host: this._host,
103
+ items: this._outputs,
104
+ notebook: this._model.context.model.toJSON(),
105
+ readyCallback: async () => { }
106
+ });
107
+ }
92
108
  }