@theia/notebook 1.53.2 → 1.55.0-next.14
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.
- package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-actions-contribution.js +5 -2
- package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.js +10 -6
- package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
- package/lib/browser/contributions/notebook-status-bar-contribution.d.ts +7 -9
- package/lib/browser/contributions/notebook-status-bar-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-status-bar-contribution.js +21 -33
- package/lib/browser/contributions/notebook-status-bar-contribution.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/notebook-editor-widget.d.ts +4 -0
- package/lib/browser/notebook-editor-widget.d.ts.map +1 -1
- package/lib/browser/notebook-editor-widget.js +27 -4
- package/lib/browser/notebook-editor-widget.js.map +1 -1
- package/lib/browser/notebook-frontend-module.d.ts.map +1 -1
- package/lib/browser/notebook-frontend-module.js +3 -1
- package/lib/browser/notebook-frontend-module.js.map +1 -1
- package/lib/browser/notebook-open-handler.d.ts +3 -2
- package/lib/browser/notebook-open-handler.d.ts.map +1 -1
- package/lib/browser/notebook-open-handler.js +12 -5
- package/lib/browser/notebook-open-handler.js.map +1 -1
- package/lib/browser/renderers/cell-output-webview.d.ts +17 -3
- package/lib/browser/renderers/cell-output-webview.d.ts.map +1 -1
- package/lib/browser/renderers/cell-output-webview.js +2 -1
- package/lib/browser/renderers/cell-output-webview.js.map +1 -1
- package/lib/browser/service/notebook-cell-editor-service.d.ts +19 -0
- package/lib/browser/service/notebook-cell-editor-service.d.ts.map +1 -0
- package/lib/browser/service/notebook-cell-editor-service.js +77 -0
- package/lib/browser/service/notebook-cell-editor-service.js.map +1 -0
- package/lib/browser/service/notebook-editor-widget-service.d.ts +4 -0
- package/lib/browser/service/notebook-editor-widget-service.d.ts.map +1 -1
- package/lib/browser/service/notebook-editor-widget-service.js +19 -0
- package/lib/browser/service/notebook-editor-widget-service.js.map +1 -1
- package/lib/browser/view/notebook-cell-editor.d.ts +2 -0
- package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-editor.js +12 -1
- package/lib/browser/view/notebook-cell-editor.js.map +1 -1
- package/lib/browser/view/notebook-cell-list-view.d.ts +4 -1
- package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-list-view.js +36 -13
- package/lib/browser/view/notebook-cell-list-view.js.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.d.ts +19 -9
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.js +58 -70
- package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.d.ts +3 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.js +17 -5
- package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.d.ts +5 -0
- package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.js +10 -0
- package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-output-model.d.ts +0 -3
- package/lib/browser/view-model/notebook-cell-output-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-output-model.js +0 -6
- package/lib/browser/view-model/notebook-cell-output-model.js.map +1 -1
- package/lib/browser/view-model/notebook-model.d.ts +2 -1
- package/lib/browser/view-model/notebook-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-model.js +3 -0
- package/lib/browser/view-model/notebook-model.js.map +1 -1
- package/package.json +8 -8
- package/src/browser/contributions/notebook-actions-contribution.ts +4 -1
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +10 -7
- package/src/browser/contributions/notebook-status-bar-contribution.ts +23 -34
- package/src/browser/index.ts +1 -0
- package/src/browser/notebook-editor-widget.tsx +35 -10
- package/src/browser/notebook-frontend-module.ts +6 -2
- package/src/browser/notebook-open-handler.ts +13 -7
- package/src/browser/renderers/cell-output-webview.ts +21 -3
- package/src/browser/service/notebook-cell-editor-service.ts +74 -0
- package/src/browser/service/notebook-editor-widget-service.ts +20 -0
- package/src/browser/style/index.css +41 -10
- package/src/browser/view/notebook-cell-editor.tsx +18 -5
- package/src/browser/view/notebook-cell-list-view.tsx +44 -13
- package/src/browser/view/notebook-code-cell-view.tsx +82 -87
- package/src/browser/view/notebook-markdown-cell-view.tsx +19 -5
- package/src/browser/view-model/notebook-cell-model.ts +13 -0
- package/src/browser/view-model/notebook-cell-output-model.ts +0 -8
- package/src/browser/view-model/notebook-model.ts +5 -1
|
@@ -26,9 +26,19 @@ import { NotebookContextManager } from '../service/notebook-context-manager';
|
|
|
26
26
|
|
|
27
27
|
export interface CellRenderer {
|
|
28
28
|
render(notebookData: NotebookModel, cell: NotebookCellModel, index: number): React.ReactNode
|
|
29
|
+
renderSidebar(notebookModel: NotebookModel, cell: NotebookCellModel): React.ReactNode
|
|
29
30
|
renderDragImage(cell: NotebookCellModel): HTMLElement
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
export function observeCellHeight(ref: HTMLDivElement | null, cell: NotebookCellModel): void {
|
|
34
|
+
if (ref) {
|
|
35
|
+
cell.cellHeight = ref?.getBoundingClientRect().height ?? 0;
|
|
36
|
+
new ResizeObserver(entries =>
|
|
37
|
+
cell.cellHeight = ref?.getBoundingClientRect().height ?? 0
|
|
38
|
+
).observe(ref);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
interface CellListProps {
|
|
33
43
|
renderers: Map<CellKind, CellRenderer>;
|
|
34
44
|
notebookModel: NotebookModel;
|
|
@@ -109,7 +119,7 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
|
|
|
109
119
|
}
|
|
110
120
|
|
|
111
121
|
override render(): React.ReactNode {
|
|
112
|
-
return <ul className='theia-notebook-cell-list' ref={this.cellListRef}>
|
|
122
|
+
return <ul className='theia-notebook-cell-list' ref={this.cellListRef} onDragStart={e => this.onDragStart(e)}>
|
|
113
123
|
{this.props.notebookModel.cells
|
|
114
124
|
.map((cell, index) =>
|
|
115
125
|
<React.Fragment key={'cell-' + cell.handle}>
|
|
@@ -119,13 +129,8 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
|
|
|
119
129
|
onAddNewCell={(commandId: string) => this.onAddNewCell(commandId, index)}
|
|
120
130
|
onDrop={e => this.onDrop(e, index)}
|
|
121
131
|
onDragOver={e => this.onDragOver(e, cell, 'top')} />
|
|
122
|
-
{this.shouldRenderDragOverIndicator(cell, 'top')
|
|
132
|
+
<CellDropIndicator visible={this.shouldRenderDragOverIndicator(cell, 'top')} />
|
|
123
133
|
<li className={'theia-notebook-cell' + (this.state.selectedCell === cell ? ' focused' : '') + (this.isEnabled() ? ' draggable' : '')}
|
|
124
|
-
onClick={e => {
|
|
125
|
-
this.setState({ ...this.state, selectedCell: cell });
|
|
126
|
-
this.props.notebookModel.setSelectedCell(cell, false);
|
|
127
|
-
}}
|
|
128
|
-
onDragStart={e => this.onDragStart(e, index, cell)}
|
|
129
134
|
onDragEnd={e => {
|
|
130
135
|
NotebookCellListView.dragGhost?.remove();
|
|
131
136
|
this.setState({ ...this.state, dragOverIndicator: undefined });
|
|
@@ -134,6 +139,7 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
|
|
|
134
139
|
onDrop={e => this.onDrop(e, index)}
|
|
135
140
|
draggable={true}
|
|
136
141
|
tabIndex={-1}
|
|
142
|
+
data-cell-handle={cell.handle}
|
|
137
143
|
ref={ref => {
|
|
138
144
|
if (ref && cell === this.state.selectedCell && this.state.scrollIntoView) {
|
|
139
145
|
ref.scrollIntoView({ block: 'nearest' });
|
|
@@ -141,8 +147,16 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
|
|
|
141
147
|
ref.focus();
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
|
-
}}
|
|
145
|
-
|
|
150
|
+
}}
|
|
151
|
+
onClick={e => {
|
|
152
|
+
this.setState({ ...this.state, selectedCell: cell });
|
|
153
|
+
this.props.notebookModel.setSelectedCell(cell, false);
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
<div className='theia-notebook-cell-sidebar'>
|
|
157
|
+
<div className={'theia-notebook-cell-marker' + (this.state.selectedCell === cell ? ' theia-notebook-cell-marker-selected' : '')}></div>
|
|
158
|
+
{this.renderCellSidebar(cell)}
|
|
159
|
+
</div>
|
|
146
160
|
<div className='theia-notebook-cell-content'>
|
|
147
161
|
{this.renderCellContent(cell, index)}
|
|
148
162
|
</div>
|
|
@@ -152,7 +166,7 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
|
|
|
152
166
|
})
|
|
153
167
|
}
|
|
154
168
|
</li>
|
|
155
|
-
{this.shouldRenderDragOverIndicator(cell, 'bottom')
|
|
169
|
+
<CellDropIndicator visible={this.shouldRenderDragOverIndicator(cell, 'bottom')} />
|
|
156
170
|
</React.Fragment>
|
|
157
171
|
)
|
|
158
172
|
}
|
|
@@ -173,13 +187,30 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
|
|
|
173
187
|
return renderer.render(this.props.notebookModel, cell, index);
|
|
174
188
|
}
|
|
175
189
|
|
|
176
|
-
|
|
190
|
+
renderCellSidebar(cell: NotebookCellModel): React.ReactNode {
|
|
191
|
+
const renderer = this.props.renderers.get(cell.cellKind);
|
|
192
|
+
if (!renderer) {
|
|
193
|
+
throw new Error(`No renderer found for cell type ${cell.cellKind}`);
|
|
194
|
+
}
|
|
195
|
+
return renderer.renderSidebar(this.props.notebookModel, cell);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
protected onDragStart(event: React.DragEvent<HTMLElement>): void {
|
|
177
199
|
event.stopPropagation();
|
|
178
200
|
if (!this.isEnabled()) {
|
|
179
201
|
event.preventDefault();
|
|
180
202
|
return;
|
|
181
203
|
}
|
|
182
204
|
|
|
205
|
+
const cellHandle = (event.target as HTMLLIElement).getAttribute('data-cell-handle');
|
|
206
|
+
|
|
207
|
+
if (!cellHandle) {
|
|
208
|
+
throw new Error('Cell handle not found in element for cell drag event');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const index = this.props.notebookModel.getCellIndexByHandle(parseInt(cellHandle));
|
|
212
|
+
const cell = this.props.notebookModel.cells[index];
|
|
213
|
+
|
|
183
214
|
NotebookCellListView.dragGhost = document.createElement('div');
|
|
184
215
|
NotebookCellListView.dragGhost.classList.add('theia-notebook-drag-ghost-image');
|
|
185
216
|
NotebookCellListView.dragGhost.appendChild(this.props.renderers.get(cell.cellKind)?.renderDragImage(cell) ?? document.createElement('div'));
|
|
@@ -274,6 +305,6 @@ export function NotebookCellDivider({ isVisible, onAddNewCell, onDrop, onDragOve
|
|
|
274
305
|
</li>;
|
|
275
306
|
}
|
|
276
307
|
|
|
277
|
-
function CellDropIndicator(): React.JSX.Element {
|
|
278
|
-
return <div className='theia-notebook-cell-drop-indicator' />;
|
|
308
|
+
function CellDropIndicator(props: { visible: boolean }): React.JSX.Element {
|
|
309
|
+
return <div className='theia-notebook-cell-drop-indicator' style={{ visibility: props.visible ? 'visible' : 'hidden' }} />;
|
|
279
310
|
}
|
|
@@ -17,12 +17,11 @@
|
|
|
17
17
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
18
|
import * as React from '@theia/core/shared/react';
|
|
19
19
|
import { MonacoEditorServices } from '@theia/monaco/lib/browser/monaco-editor';
|
|
20
|
-
import { CellOutputWebviewFactory, CellOutputWebview } from '../renderers/cell-output-webview';
|
|
21
20
|
import { NotebookRendererRegistry } from '../notebook-renderer-registry';
|
|
22
21
|
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
23
22
|
import { NotebookModel } from '../view-model/notebook-model';
|
|
24
23
|
import { CellEditor } from './notebook-cell-editor';
|
|
25
|
-
import { CellRenderer } from './notebook-cell-list-view';
|
|
24
|
+
import { CellRenderer, observeCellHeight } from './notebook-cell-list-view';
|
|
26
25
|
import { NotebookCellToolbarFactory } from './notebook-cell-toolbar-factory';
|
|
27
26
|
import { NotebookCellActionContribution, NotebookCellCommands } from '../contributions/notebook-cell-actions-contribution';
|
|
28
27
|
import { CellExecution, NotebookExecutionStateService } from '../service/notebook-execution-state-service';
|
|
@@ -35,6 +34,8 @@ import { EditorPreferences } from '@theia/editor/lib/browser';
|
|
|
35
34
|
import { NotebookOptionsService } from '../service/notebook-options';
|
|
36
35
|
import { MarkdownRenderer } from '@theia/core/lib/browser/markdown-rendering/markdown-renderer';
|
|
37
36
|
import { MarkdownString } from '@theia/monaco-editor-core/esm/vs/base/common/htmlContent';
|
|
37
|
+
import { NotebookCellEditorService } from '../service/notebook-cell-editor-service';
|
|
38
|
+
import { CellOutputWebview } from '../renderers/cell-output-webview';
|
|
38
39
|
|
|
39
40
|
@injectable()
|
|
40
41
|
export class NotebookCodeCellRenderer implements CellRenderer {
|
|
@@ -44,9 +45,6 @@ export class NotebookCodeCellRenderer implements CellRenderer {
|
|
|
44
45
|
@inject(NotebookRendererRegistry)
|
|
45
46
|
protected readonly notebookRendererRegistry: NotebookRendererRegistry;
|
|
46
47
|
|
|
47
|
-
@inject(CellOutputWebviewFactory)
|
|
48
|
-
protected readonly cellOutputWebviewFactory: CellOutputWebviewFactory;
|
|
49
|
-
|
|
50
48
|
@inject(NotebookCellToolbarFactory)
|
|
51
49
|
protected readonly notebookCellToolbarFactory: NotebookCellToolbarFactory;
|
|
52
50
|
|
|
@@ -62,6 +60,9 @@ export class NotebookCodeCellRenderer implements CellRenderer {
|
|
|
62
60
|
@inject(EditorPreferences)
|
|
63
61
|
protected readonly editorPreferences: EditorPreferences;
|
|
64
62
|
|
|
63
|
+
@inject(NotebookCellEditorService)
|
|
64
|
+
protected readonly notebookCellEditorService: NotebookCellEditorService;
|
|
65
|
+
|
|
65
66
|
@inject(CommandRegistry)
|
|
66
67
|
protected readonly commandRegistry: CommandRegistry;
|
|
67
68
|
|
|
@@ -71,39 +72,39 @@ export class NotebookCodeCellRenderer implements CellRenderer {
|
|
|
71
72
|
@inject(MarkdownRenderer)
|
|
72
73
|
protected readonly markdownRenderer: MarkdownRenderer;
|
|
73
74
|
|
|
75
|
+
@inject(CellOutputWebview)
|
|
76
|
+
protected readonly outputWebview: CellOutputWebview;
|
|
77
|
+
|
|
74
78
|
render(notebookModel: NotebookModel, cell: NotebookCellModel, handle: number): React.ReactNode {
|
|
75
|
-
return <div>
|
|
76
|
-
<div className='theia-notebook-cell-
|
|
77
|
-
<
|
|
78
|
-
{this.
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
notebookContextManager={this.notebookContextManager}
|
|
88
|
-
notebookViewportService={this.notebookViewportService}
|
|
89
|
-
fontInfo={this.notebookOptionsService.editorFontInfo} />
|
|
90
|
-
<NotebookCodeCellStatus cell={cell} notebook={notebookModel}
|
|
91
|
-
commandRegistry={this.commandRegistry}
|
|
92
|
-
executionStateService={this.executionStateService}
|
|
93
|
-
onClick={() => cell.requestFocusEditor()} />
|
|
94
|
-
</div >
|
|
79
|
+
return <div className='theia-notebook-cell-with-sidebar' ref={ref => observeCellHeight(ref, cell)}>
|
|
80
|
+
<div className='theia-notebook-cell-editor-container'>
|
|
81
|
+
<CellEditor notebookModel={notebookModel} cell={cell}
|
|
82
|
+
monacoServices={this.monacoServices}
|
|
83
|
+
notebookContextManager={this.notebookContextManager}
|
|
84
|
+
notebookViewportService={this.notebookViewportService}
|
|
85
|
+
notebookCellEditorService={this.notebookCellEditorService}
|
|
86
|
+
fontInfo={this.notebookOptionsService.editorFontInfo} />
|
|
87
|
+
<NotebookCodeCellStatus cell={cell} notebook={notebookModel}
|
|
88
|
+
commandRegistry={this.commandRegistry}
|
|
89
|
+
executionStateService={this.executionStateService}
|
|
90
|
+
onClick={() => cell.requestFocusEditor()} />
|
|
95
91
|
</div >
|
|
96
|
-
<div className='theia-notebook-cell-with-sidebar'>
|
|
97
|
-
<NotebookCodeCellOutputs cell={cell} notebook={notebookModel} outputWebviewFactory={this.cellOutputWebviewFactory}
|
|
98
|
-
renderSidebar={() =>
|
|
99
|
-
this.notebookCellToolbarFactory.renderSidebar(NotebookCellActionContribution.OUTPUT_SIDEBAR_MENU, cell, {
|
|
100
|
-
contextMenuArgs: () => [notebookModel, cell, cell.outputs[0]]
|
|
101
|
-
})
|
|
102
|
-
} />
|
|
103
|
-
</div>
|
|
104
92
|
</div >;
|
|
105
93
|
}
|
|
106
94
|
|
|
95
|
+
renderSidebar(notebookModel: NotebookModel, cell: NotebookCellModel): React.ReactNode {
|
|
96
|
+
return <div>
|
|
97
|
+
<NotebookCodeCellSidebar cell={cell} notebook={notebookModel} notebookCellToolbarFactory={this.notebookCellToolbarFactory} />
|
|
98
|
+
<NotebookCodeCellOutputs cell={cell} notebook={notebookModel} outputWebview={this.outputWebview}
|
|
99
|
+
renderSidebar={() =>
|
|
100
|
+
this.notebookCellToolbarFactory.renderSidebar(NotebookCellActionContribution.OUTPUT_SIDEBAR_MENU, cell, {
|
|
101
|
+
contextMenuArgs: () => [notebookModel, cell, cell.outputs[0]]
|
|
102
|
+
})
|
|
103
|
+
} />
|
|
104
|
+
</div>;
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
107
108
|
renderDragImage(cell: NotebookCellModel): HTMLElement {
|
|
108
109
|
const dragImage = document.createElement('div');
|
|
109
110
|
dragImage.className = 'theia-notebook-drag-image';
|
|
@@ -146,6 +147,37 @@ export class NotebookCodeCellRenderer implements CellRenderer {
|
|
|
146
147
|
|
|
147
148
|
}
|
|
148
149
|
|
|
150
|
+
export interface NotebookCodeCellSidebarProps {
|
|
151
|
+
cell: NotebookCellModel;
|
|
152
|
+
notebook: NotebookModel;
|
|
153
|
+
notebookCellToolbarFactory: NotebookCellToolbarFactory
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export class NotebookCodeCellSidebar extends React.Component<NotebookCodeCellSidebarProps> {
|
|
157
|
+
|
|
158
|
+
protected toDispose = new DisposableCollection();
|
|
159
|
+
|
|
160
|
+
constructor(props: NotebookCodeCellSidebarProps) {
|
|
161
|
+
super(props);
|
|
162
|
+
|
|
163
|
+
this.toDispose.push(props.cell.onDidCellHeightChange(() => this.forceUpdate()));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
override componentWillUnmount(): void {
|
|
167
|
+
this.toDispose.dispose();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
override render(): React.ReactNode {
|
|
171
|
+
return <div className='theia-notebook-cell-sidebar-actions' style={{ height: `${this.props.cell.cellHeight}px` }}>
|
|
172
|
+
{this.props.notebookCellToolbarFactory.renderSidebar(NotebookCellActionContribution.CODE_CELL_SIDEBAR_MENU, this.props.cell, {
|
|
173
|
+
contextMenuArgs: () => [this.props.cell], commandArgs: () => [this.props.notebook, this.props.cell]
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
<CodeCellExecutionOrder cell={this.props.cell} />
|
|
177
|
+
</div>;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
149
181
|
export interface NotebookCodeCellStatusProps {
|
|
150
182
|
notebook: NotebookModel;
|
|
151
183
|
cell: NotebookCellModel;
|
|
@@ -255,79 +287,42 @@ export class NotebookCodeCellStatus extends React.Component<NotebookCodeCellStat
|
|
|
255
287
|
interface NotebookCellOutputProps {
|
|
256
288
|
cell: NotebookCellModel;
|
|
257
289
|
notebook: NotebookModel;
|
|
258
|
-
|
|
290
|
+
outputWebview: CellOutputWebview;
|
|
259
291
|
renderSidebar: () => React.ReactNode;
|
|
260
292
|
}
|
|
261
293
|
|
|
262
294
|
export class NotebookCodeCellOutputs extends React.Component<NotebookCellOutputProps> {
|
|
263
295
|
|
|
264
|
-
protected outputsWebview: CellOutputWebview | undefined;
|
|
265
|
-
protected outputsWebviewPromise: Promise<CellOutputWebview> | undefined;
|
|
266
|
-
|
|
267
296
|
protected toDispose = new DisposableCollection();
|
|
268
297
|
|
|
269
|
-
|
|
270
|
-
super(props);
|
|
271
|
-
}
|
|
298
|
+
protected outputHeight: number = 0;
|
|
272
299
|
|
|
273
300
|
override async componentDidMount(): Promise<void> {
|
|
274
|
-
const { cell
|
|
275
|
-
this.toDispose.push(cell.onDidChangeOutputs(() => this.
|
|
276
|
-
this.toDispose.push(cell.onDidChangeOutputVisibility(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this.
|
|
280
|
-
this.outputsWebviewPromise = undefined;
|
|
301
|
+
const { cell } = this.props;
|
|
302
|
+
this.toDispose.push(cell.onDidChangeOutputs(() => this.forceUpdate()));
|
|
303
|
+
this.toDispose.push(this.props.cell.onDidChangeOutputVisibility(() => this.forceUpdate()));
|
|
304
|
+
this.toDispose.push(this.props.outputWebview.onDidRenderOutput(event => {
|
|
305
|
+
if (event.cellHandle === this.props.cell.handle) {
|
|
306
|
+
this.outputHeight = event.outputHeight;
|
|
281
307
|
this.forceUpdate();
|
|
282
|
-
} else {
|
|
283
|
-
this.updateOutputs();
|
|
284
308
|
}
|
|
285
309
|
}));
|
|
286
|
-
if (cell.outputs.length > 0) {
|
|
287
|
-
this.outputsWebviewPromise = outputWebviewFactory(cell, notebook).then(webview => {
|
|
288
|
-
this.outputsWebview = webview;
|
|
289
|
-
this.forceUpdate();
|
|
290
|
-
return webview;
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
310
|
}
|
|
294
311
|
|
|
295
|
-
|
|
296
|
-
const { cell, notebook, outputWebviewFactory } = this.props;
|
|
297
|
-
if (!this.outputsWebviewPromise && cell.outputs.length > 0) {
|
|
298
|
-
this.outputsWebviewPromise = outputWebviewFactory(cell, notebook).then(webview => {
|
|
299
|
-
this.outputsWebview = webview;
|
|
300
|
-
this.forceUpdate();
|
|
301
|
-
return webview;
|
|
302
|
-
});
|
|
303
|
-
this.forceUpdate();
|
|
304
|
-
} else if (this.outputsWebviewPromise && cell.outputs.length === 0 && cell.internalMetadata.runEndTime) {
|
|
305
|
-
(await this.outputsWebviewPromise).dispose();
|
|
306
|
-
this.outputsWebview = undefined;
|
|
307
|
-
this.outputsWebviewPromise = undefined;
|
|
308
|
-
this.forceUpdate();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
override async componentDidUpdate(): Promise<void> {
|
|
313
|
-
if (!(await this.outputsWebviewPromise)?.isAttached()) {
|
|
314
|
-
(await this.outputsWebviewPromise)?.attachWebview();
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
override async componentWillUnmount(): Promise<void> {
|
|
312
|
+
override componentWillUnmount(): void {
|
|
319
313
|
this.toDispose.dispose();
|
|
320
|
-
(await this.outputsWebviewPromise)?.dispose();
|
|
321
314
|
}
|
|
322
315
|
|
|
323
316
|
override render(): React.ReactNode {
|
|
324
|
-
|
|
325
|
-
|
|
317
|
+
if (!this.props.cell.outputs?.length) {
|
|
318
|
+
return <></>;
|
|
319
|
+
}
|
|
320
|
+
if (this.props.cell.outputVisible) {
|
|
321
|
+
return <div style={{ minHeight: this.outputHeight }}>
|
|
326
322
|
{this.props.renderSidebar()}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
323
|
+
</div>;
|
|
324
|
+
}
|
|
325
|
+
return <div className='theia-notebook-collapsed-output-container'><i className='theia-notebook-collapsed-output'>{nls.localizeByDefault('Outputs are collapsed')}</i></div>;
|
|
331
326
|
}
|
|
332
327
|
|
|
333
328
|
}
|
|
@@ -18,7 +18,7 @@ import * as React from '@theia/core/shared/react';
|
|
|
18
18
|
import { MarkdownRenderer } from '@theia/core/lib/browser/markdown-rendering/markdown-renderer';
|
|
19
19
|
import { MarkdownStringImpl } from '@theia/core/lib/common/markdown-rendering/markdown-string';
|
|
20
20
|
import { NotebookModel } from '../view-model/notebook-model';
|
|
21
|
-
import { CellRenderer } from './notebook-cell-list-view';
|
|
21
|
+
import { CellRenderer, observeCellHeight } from './notebook-cell-list-view';
|
|
22
22
|
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
23
23
|
import { CellEditor } from './notebook-cell-editor';
|
|
24
24
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
@@ -29,6 +29,7 @@ import { NotebookOptionsService } from '../service/notebook-options';
|
|
|
29
29
|
import { NotebookCodeCellStatus } from './notebook-code-cell-view';
|
|
30
30
|
import { NotebookEditorFindMatch, NotebookEditorFindMatchOptions } from './notebook-find-widget';
|
|
31
31
|
import * as mark from 'advanced-mark.js';
|
|
32
|
+
import { NotebookCellEditorService } from '../service/notebook-cell-editor-service';
|
|
32
33
|
|
|
33
34
|
@injectable()
|
|
34
35
|
export class NotebookMarkdownCellRenderer implements CellRenderer {
|
|
@@ -47,6 +48,9 @@ export class NotebookMarkdownCellRenderer implements CellRenderer {
|
|
|
47
48
|
@inject(NotebookOptionsService)
|
|
48
49
|
protected readonly notebookOptionsService: NotebookOptionsService;
|
|
49
50
|
|
|
51
|
+
@inject(NotebookCellEditorService)
|
|
52
|
+
protected readonly notebookCellEditorService: NotebookCellEditorService;
|
|
53
|
+
|
|
50
54
|
render(notebookModel: NotebookModel, cell: NotebookCellModel): React.ReactNode {
|
|
51
55
|
return <MarkdownCell
|
|
52
56
|
markdownRenderer={this.markdownRenderer}
|
|
@@ -55,7 +59,12 @@ export class NotebookMarkdownCellRenderer implements CellRenderer {
|
|
|
55
59
|
notebookOptionsService={this.notebookOptionsService}
|
|
56
60
|
cell={cell}
|
|
57
61
|
notebookModel={notebookModel}
|
|
58
|
-
notebookContextManager={this.notebookContextManager}
|
|
62
|
+
notebookContextManager={this.notebookContextManager}
|
|
63
|
+
notebookCellEditorService={this.notebookCellEditorService} />;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
renderSidebar(notebookModel: NotebookModel, cell: NotebookCellModel): React.ReactNode {
|
|
67
|
+
return <div className='theia-notebook-markdown-sidebar'></div>;
|
|
59
68
|
}
|
|
60
69
|
|
|
61
70
|
renderDragImage(cell: NotebookCellModel): HTMLElement {
|
|
@@ -77,10 +86,11 @@ interface MarkdownCellProps {
|
|
|
77
86
|
notebookModel: NotebookModel;
|
|
78
87
|
notebookContextManager: NotebookContextManager;
|
|
79
88
|
notebookOptionsService: NotebookOptionsService;
|
|
89
|
+
notebookCellEditorService: NotebookCellEditorService
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
function MarkdownCell({
|
|
83
|
-
markdownRenderer, monacoServices, cell, notebookModel, notebookContextManager, notebookOptionsService, commandRegistry
|
|
93
|
+
markdownRenderer, monacoServices, cell, notebookModel, notebookContextManager, notebookOptionsService, commandRegistry, notebookCellEditorService
|
|
84
94
|
}: MarkdownCellProps): React.JSX.Element {
|
|
85
95
|
const [editMode, setEditMode] = React.useState(cell.editing);
|
|
86
96
|
let empty = false;
|
|
@@ -129,10 +139,11 @@ function MarkdownCell({
|
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
return editMode ?
|
|
132
|
-
(<div className='theia-notebook-markdown-editor-container' key="code">
|
|
142
|
+
(<div className='theia-notebook-markdown-editor-container' key="code" ref={ref => observeCellHeight(ref, cell)}>
|
|
133
143
|
<CellEditor notebookModel={notebookModel} cell={cell}
|
|
134
144
|
monacoServices={monacoServices}
|
|
135
145
|
notebookContextManager={notebookContextManager}
|
|
146
|
+
notebookCellEditorService={notebookCellEditorService}
|
|
136
147
|
fontInfo={notebookOptionsService.editorFontInfo} />
|
|
137
148
|
<NotebookCodeCellStatus cell={cell} notebook={notebookModel}
|
|
138
149
|
commandRegistry={commandRegistry}
|
|
@@ -140,7 +151,10 @@ function MarkdownCell({
|
|
|
140
151
|
</div >) :
|
|
141
152
|
(<div className='theia-notebook-markdown-content' key="markdown"
|
|
142
153
|
onDoubleClick={() => cell.requestEdit()}
|
|
143
|
-
ref={node =>
|
|
154
|
+
ref={node => {
|
|
155
|
+
node?.replaceChildren(...markdownContent);
|
|
156
|
+
observeCellHeight(node, cell);
|
|
157
|
+
}}
|
|
144
158
|
/>);
|
|
145
159
|
}
|
|
146
160
|
|
|
@@ -129,6 +129,9 @@ export class NotebookCellModel implements NotebookCell, Disposable {
|
|
|
129
129
|
protected onDidRequestCenterEditorEmitter = new Emitter<void>();
|
|
130
130
|
readonly onDidRequestCenterEditor = this.onDidRequestCenterEditorEmitter.event;
|
|
131
131
|
|
|
132
|
+
protected onDidCellHeightChangeEmitter = new Emitter<number>();
|
|
133
|
+
readonly onDidCellHeightChange = this.onDidCellHeightChangeEmitter.event;
|
|
134
|
+
|
|
132
135
|
@inject(NotebookCellModelProps)
|
|
133
136
|
protected readonly props: NotebookCellModelProps;
|
|
134
137
|
|
|
@@ -251,6 +254,16 @@ export class NotebookCellModel implements NotebookCell, Disposable {
|
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
|
|
257
|
+
protected _cellheight: number = 0;
|
|
258
|
+
get cellHeight(): number {
|
|
259
|
+
return this._cellheight;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
set cellHeight(height: number) {
|
|
263
|
+
this.onDidCellHeightChangeEmitter.fire(height);
|
|
264
|
+
this._cellheight = height;
|
|
265
|
+
}
|
|
266
|
+
|
|
254
267
|
@postConstruct()
|
|
255
268
|
protected init(): void {
|
|
256
269
|
this._outputs = this.props.outputs.map(op => new NotebookCellOutputModel(op));
|
|
@@ -23,9 +23,6 @@ export class NotebookCellOutputModel implements Disposable {
|
|
|
23
23
|
private didChangeDataEmitter = new Emitter<void>();
|
|
24
24
|
readonly onDidChangeData = this.didChangeDataEmitter.event;
|
|
25
25
|
|
|
26
|
-
private requestOutputPresentationChangeEmitter = new Emitter<void>();
|
|
27
|
-
readonly onRequestOutputPresentationChange = this.requestOutputPresentationChangeEmitter.event;
|
|
28
|
-
|
|
29
26
|
get outputId(): string {
|
|
30
27
|
return this.rawOutput.outputId;
|
|
31
28
|
}
|
|
@@ -54,11 +51,6 @@ export class NotebookCellOutputModel implements Disposable {
|
|
|
54
51
|
|
|
55
52
|
dispose(): void {
|
|
56
53
|
this.didChangeDataEmitter.dispose();
|
|
57
|
-
this.requestOutputPresentationChangeEmitter.dispose();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
requestOutputPresentationUpdate(): void {
|
|
61
|
-
this.requestOutputPresentationChangeEmitter.fire();
|
|
62
54
|
}
|
|
63
55
|
|
|
64
56
|
getData(): CellOutput {
|
|
@@ -509,10 +509,14 @@ export class NotebookModel implements Saveable, Disposable {
|
|
|
509
509
|
return true;
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
-
|
|
512
|
+
getCellIndexByHandle(handle: number): number {
|
|
513
513
|
return this.cells.findIndex(c => c.handle === handle);
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
+
getCellByHandle(handle: number): NotebookCellModel | undefined {
|
|
517
|
+
return this.cells.find(c => c.handle === handle);
|
|
518
|
+
}
|
|
519
|
+
|
|
516
520
|
protected isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata): boolean {
|
|
517
521
|
const keys = new Set<keyof NotebookCellMetadata>([...Object.keys(a || {}), ...Object.keys(b || {})]);
|
|
518
522
|
for (const key of keys) {
|