@theia/notebook 1.54.0 → 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-cell-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.js +5 -1
- 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/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 +26 -3
- 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 +1 -1
- package/lib/browser/notebook-frontend-module.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 +3 -0
- package/lib/browser/service/notebook-cell-editor-service.d.ts.map +1 -1
- package/lib/browser/service/notebook-cell-editor-service.js +26 -2
- package/lib/browser/service/notebook-cell-editor-service.js.map +1 -1
- 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-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 +17 -9
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.js +53 -70
- package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.d.ts +1 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.js +9 -2
- 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 +7 -7
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +4 -1
- package/src/browser/contributions/notebook-status-bar-contribution.ts +23 -34
- package/src/browser/notebook-editor-widget.tsx +34 -9
- package/src/browser/notebook-frontend-module.ts +4 -2
- package/src/browser/renderers/cell-output-webview.ts +21 -3
- package/src/browser/service/notebook-cell-editor-service.ts +21 -3
- package/src/browser/service/notebook-editor-widget-service.ts +20 -0
- package/src/browser/style/index.css +35 -9
- package/src/browser/view/notebook-cell-list-view.tsx +44 -13
- package/src/browser/view/notebook-code-cell-view.tsx +78 -88
- package/src/browser/view/notebook-markdown-cell-view.tsx +10 -3
- 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
|
@@ -18,7 +18,7 @@ import * as React from '@theia/core/shared/react';
|
|
|
18
18
|
import { CommandRegistry, MenuModelRegistry, URI } from '@theia/core';
|
|
19
19
|
import { ReactWidget, Navigatable, SaveableSource, Message, DelegatingSaveable, lock, unlock, animationFrame } from '@theia/core/lib/browser';
|
|
20
20
|
import { ReactNode } from '@theia/core/shared/react';
|
|
21
|
-
import { CellKind } from '../common';
|
|
21
|
+
import { CellKind, NotebookCellsChangeType } from '../common';
|
|
22
22
|
import { CellRenderer as CellRenderer, NotebookCellListView } from './view/notebook-cell-list-view';
|
|
23
23
|
import { NotebookCodeCellRenderer } from './view/notebook-code-cell-view';
|
|
24
24
|
import { NotebookMarkdownCellRenderer } from './view/notebook-markdown-cell-view';
|
|
@@ -35,6 +35,8 @@ import { NotebookViewportService } from './view/notebook-viewport-service';
|
|
|
35
35
|
import { NotebookCellCommands } from './contributions/notebook-cell-actions-contribution';
|
|
36
36
|
import { NotebookFindWidget } from './view/notebook-find-widget';
|
|
37
37
|
import debounce = require('lodash/debounce');
|
|
38
|
+
import { CellOutputWebview, CellOutputWebviewFactory } from './renderers/cell-output-webview';
|
|
39
|
+
import { NotebookCellOutputModel } from './view-model/notebook-cell-output-model';
|
|
38
40
|
const PerfectScrollbar = require('react-perfect-scrollbar');
|
|
39
41
|
|
|
40
42
|
export const NotebookEditorWidgetContainerFactory = Symbol('NotebookEditorWidgetContainerFactory');
|
|
@@ -44,6 +46,9 @@ export function createNotebookEditorWidgetContainer(parent: interfaces.Container
|
|
|
44
46
|
|
|
45
47
|
child.bind(NotebookEditorProps).toConstantValue(props);
|
|
46
48
|
|
|
49
|
+
const cellOutputWebviewFactory: CellOutputWebviewFactory = parent.get(CellOutputWebviewFactory);
|
|
50
|
+
child.bind(CellOutputWebview).toConstantValue(cellOutputWebviewFactory());
|
|
51
|
+
|
|
47
52
|
child.bind(NotebookContextManager).toSelf().inSingletonScope();
|
|
48
53
|
child.bind(NotebookMainToolbarRenderer).toSelf().inSingletonScope();
|
|
49
54
|
child.bind(NotebookCellToolbarFactory).toSelf().inSingletonScope();
|
|
@@ -104,6 +109,9 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
104
109
|
@inject(NotebookViewportService)
|
|
105
110
|
protected readonly viewportService: NotebookViewportService;
|
|
106
111
|
|
|
112
|
+
@inject(CellOutputWebview)
|
|
113
|
+
protected readonly cellOutputWebview: CellOutputWebview;
|
|
114
|
+
|
|
107
115
|
protected readonly onDidChangeModelEmitter = new Emitter<void>();
|
|
108
116
|
readonly onDidChangeModel = this.onDidChangeModelEmitter.event;
|
|
109
117
|
|
|
@@ -173,11 +181,18 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
173
181
|
this.commandRegistry.executeCommand(NotebookCellCommands.EDIT_COMMAND.id, model, model.cells[0]);
|
|
174
182
|
model.setSelectedCell(model.cells[0]);
|
|
175
183
|
}
|
|
184
|
+
model.onDidChangeContent(changeEvents => {
|
|
185
|
+
const cellEvent = changeEvents.filter(event => event.kind === NotebookCellsChangeType.Move || event.kind === NotebookCellsChangeType.ModelChange);
|
|
186
|
+
if (cellEvent.length > 0) {
|
|
187
|
+
this.cellOutputWebview.cellsChanged(cellEvent);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
176
190
|
});
|
|
177
191
|
}
|
|
178
192
|
|
|
179
193
|
protected async waitForData(): Promise<NotebookModel> {
|
|
180
194
|
this._model = await this.props.notebookData;
|
|
195
|
+
this.cellOutputWebview.init(this._model, this);
|
|
181
196
|
this.saveable.delegate = this._model;
|
|
182
197
|
this.toDispose.push(this._model);
|
|
183
198
|
this.toDispose.push(this._model.onDidChangeContent(() => {
|
|
@@ -212,7 +227,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
212
227
|
|
|
213
228
|
protected override onActivateRequest(msg: Message): void {
|
|
214
229
|
super.onActivateRequest(msg);
|
|
215
|
-
this.node.focus();
|
|
230
|
+
(this.node.getElementsByClassName('theia-notebook-main-container')[0] as HTMLDivElement)?.focus();
|
|
216
231
|
}
|
|
217
232
|
|
|
218
233
|
getResourceUri(): URI | undefined {
|
|
@@ -261,17 +276,20 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
261
276
|
<PerfectScrollbar className='theia-notebook-scroll-container'
|
|
262
277
|
ref={this.scrollBarRef}
|
|
263
278
|
onScrollY={(e: HTMLDivElement) => this.viewportService.onScroll(e)}>
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
279
|
+
<div className='theia-notebook-scroll-area'>
|
|
280
|
+
{this.cellOutputWebview.render()}
|
|
281
|
+
<NotebookCellListView renderers={this.renderers}
|
|
282
|
+
notebookModel={this._model}
|
|
283
|
+
notebookContext={this.notebookContextManager}
|
|
284
|
+
toolbarRenderer={this.cellToolbarFactory}
|
|
285
|
+
commandRegistry={this.commandRegistry}
|
|
286
|
+
menuRegistry={this.menuRegistry} />
|
|
287
|
+
</div>
|
|
270
288
|
</PerfectScrollbar>
|
|
271
289
|
</div>
|
|
272
290
|
</div>;
|
|
273
291
|
} else {
|
|
274
|
-
return <div className='theia-notebook-main-container'>
|
|
292
|
+
return <div className='theia-notebook-main-container' tabIndex={-1}>
|
|
275
293
|
<div className='theia-notebook-main-loading-indicator'></div>
|
|
276
294
|
</div>;
|
|
277
295
|
}
|
|
@@ -282,6 +300,12 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
282
300
|
this.notebookEditorService.removeNotebookEditor(this);
|
|
283
301
|
}
|
|
284
302
|
|
|
303
|
+
requestOuputPresentationChange(cellHandle: number, output?: NotebookCellOutputModel): void {
|
|
304
|
+
if (output) {
|
|
305
|
+
this.cellOutputWebview.requestOutputPresentationUpdate(cellHandle, output);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
285
309
|
postKernelMessage(message: unknown): void {
|
|
286
310
|
this.onDidPostKernelMessageEmitter.fire(message);
|
|
287
311
|
}
|
|
@@ -307,6 +331,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
307
331
|
}
|
|
308
332
|
|
|
309
333
|
override dispose(): void {
|
|
334
|
+
this.cellOutputWebview.dispose();
|
|
310
335
|
this.notebookContextManager.dispose();
|
|
311
336
|
this.onDidChangeModelEmitter.dispose();
|
|
312
337
|
this.onDidPostKernelMessageEmitter.dispose();
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
import '../../src/browser/style/index.css';
|
|
17
17
|
|
|
18
18
|
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory, WidgetStatusBarContribution
|
|
21
|
+
} from '@theia/core/lib/browser';
|
|
20
22
|
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
|
21
23
|
import { NotebookOpenHandler } from './notebook-open-handler';
|
|
22
24
|
import { CommandContribution, MenuContribution, ResourceResolver, } from '@theia/core';
|
|
@@ -117,5 +119,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
117
119
|
bind(UndoRedoHandler).toService(NotebookUndoRedoHandler);
|
|
118
120
|
|
|
119
121
|
bind(NotebookStatusBarContribution).toSelf().inSingletonScope();
|
|
120
|
-
bind(
|
|
122
|
+
bind(WidgetStatusBarContribution).toService(NotebookStatusBarContribution);
|
|
121
123
|
});
|
|
@@ -14,20 +14,38 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { Disposable } from '@theia/core';
|
|
18
|
-
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
17
|
+
import { Disposable, Event } from '@theia/core';
|
|
19
18
|
import { NotebookModel } from '../view-model/notebook-model';
|
|
19
|
+
import { NotebookEditorWidget } from '../notebook-editor-widget';
|
|
20
|
+
import { NotebookContentChangedEvent } from '../notebook-types';
|
|
21
|
+
import { NotebookCellOutputModel } from '../view-model/notebook-cell-output-model';
|
|
22
|
+
import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
20
23
|
|
|
21
24
|
export const CellOutputWebviewFactory = Symbol('outputWebviewFactory');
|
|
25
|
+
export const CellOutputWebview = Symbol('outputWebview');
|
|
22
26
|
|
|
23
|
-
export type CellOutputWebviewFactory = (
|
|
27
|
+
export type CellOutputWebviewFactory = () => Promise<CellOutputWebview>;
|
|
28
|
+
|
|
29
|
+
export interface OutputRenderEvent {
|
|
30
|
+
cellHandle: number;
|
|
31
|
+
outputId: string;
|
|
32
|
+
outputHeight: number;
|
|
33
|
+
}
|
|
24
34
|
|
|
25
35
|
export interface CellOutputWebview extends Disposable {
|
|
26
36
|
|
|
27
37
|
readonly id: string;
|
|
28
38
|
|
|
39
|
+
init(notebook: NotebookModel, editor: NotebookEditorWidget): void;
|
|
40
|
+
|
|
29
41
|
render(): React.ReactNode;
|
|
30
42
|
|
|
43
|
+
setCellHeight(cell: NotebookCellModel, height: number): void;
|
|
44
|
+
cellsChanged(cellEvent: NotebookContentChangedEvent[]): void;
|
|
45
|
+
onDidRenderOutput: Event<OutputRenderEvent>
|
|
46
|
+
|
|
47
|
+
requestOutputPresentationUpdate(cellHandle: number, output: NotebookCellOutputModel): void;
|
|
48
|
+
|
|
31
49
|
attachWebview(): void;
|
|
32
50
|
isAttached(): boolean
|
|
33
51
|
}
|
|
@@ -15,12 +15,17 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { Emitter, URI } from '@theia/core';
|
|
18
|
-
import { injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
19
19
|
import { SimpleMonacoEditor } from '@theia/monaco/lib/browser/simple-monaco-editor';
|
|
20
|
+
import { NotebookEditorWidgetService } from './notebook-editor-widget-service';
|
|
21
|
+
import { CellUri } from '../../common';
|
|
20
22
|
|
|
21
23
|
@injectable()
|
|
22
24
|
export class NotebookCellEditorService {
|
|
23
25
|
|
|
26
|
+
@inject(NotebookEditorWidgetService)
|
|
27
|
+
protected readonly notebookEditorWidgetService: NotebookEditorWidgetService;
|
|
28
|
+
|
|
24
29
|
protected onDidChangeCellEditorsEmitter = new Emitter<void>();
|
|
25
30
|
readonly onDidChangeCellEditors = this.onDidChangeCellEditorsEmitter.event;
|
|
26
31
|
|
|
@@ -31,6 +36,17 @@ export class NotebookCellEditorService {
|
|
|
31
36
|
|
|
32
37
|
protected currentCellEditors: Map<string, SimpleMonacoEditor> = new Map();
|
|
33
38
|
|
|
39
|
+
@postConstruct()
|
|
40
|
+
protected init(): void {
|
|
41
|
+
this.notebookEditorWidgetService.onDidChangeCurrentEditor(editor => {
|
|
42
|
+
// if defocus notebook editor or another notebook editor is focused, clear the active cell
|
|
43
|
+
if (!editor || (this.currentActiveCell && CellUri.parse(this.currentActiveCell.uri)?.notebook.toString() !== editor?.model?.uri.toString())) {
|
|
44
|
+
this.currentActiveCell = undefined;
|
|
45
|
+
this.onDidChangeFocusedCellEditorEmitter.fire(undefined);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
34
50
|
get allCellEditors(): SimpleMonacoEditor[] {
|
|
35
51
|
return Array.from(this.currentCellEditors.values());
|
|
36
52
|
}
|
|
@@ -46,8 +62,10 @@ export class NotebookCellEditorService {
|
|
|
46
62
|
}
|
|
47
63
|
|
|
48
64
|
editorFocusChanged(editor?: SimpleMonacoEditor): void {
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
if (editor) {
|
|
66
|
+
this.currentActiveCell = editor;
|
|
67
|
+
this.onDidChangeFocusedCellEditorEmitter.fire(editor);
|
|
68
|
+
}
|
|
51
69
|
}
|
|
52
70
|
|
|
53
71
|
getActiveCell(): SimpleMonacoEditor | undefined {
|
|
@@ -45,13 +45,23 @@ export class NotebookEditorWidgetService {
|
|
|
45
45
|
protected readonly onDidChangeFocusedEditorEmitter = new Emitter<NotebookEditorWidget | undefined>();
|
|
46
46
|
readonly onDidChangeFocusedEditor = this.onDidChangeFocusedEditorEmitter.event;
|
|
47
47
|
|
|
48
|
+
protected readonly onDidChangeCurrentEditorEmitter = new Emitter<NotebookEditorWidget | undefined>();
|
|
49
|
+
readonly onDidChangeCurrentEditor = this.onDidChangeCurrentEditorEmitter.event;
|
|
50
|
+
|
|
48
51
|
focusedEditor?: NotebookEditorWidget = undefined;
|
|
49
52
|
|
|
53
|
+
currentEditor?: NotebookEditorWidget = undefined;
|
|
54
|
+
|
|
50
55
|
@postConstruct()
|
|
51
56
|
protected init(): void {
|
|
52
57
|
this.applicationShell.onDidChangeActiveWidget(event => {
|
|
53
58
|
this.notebookEditorFocusChanged(event.newValue as NotebookEditorWidget, event.newValue instanceof NotebookEditorWidget);
|
|
54
59
|
});
|
|
60
|
+
this.applicationShell.onDidChangeCurrentWidget(event => {
|
|
61
|
+
if (event.newValue instanceof NotebookEditorWidget || event.oldValue instanceof NotebookEditorWidget) {
|
|
62
|
+
this.currentNotebookEditorChanged(event.newValue);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
// --- editor management
|
|
@@ -98,4 +108,14 @@ export class NotebookEditorWidgetService {
|
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
|
|
111
|
+
currentNotebookEditorChanged(newEditor: unknown): void {
|
|
112
|
+
if (newEditor instanceof NotebookEditorWidget) {
|
|
113
|
+
this.currentEditor = newEditor;
|
|
114
|
+
this.onDidChangeCurrentEditorEmitter.fire(newEditor);
|
|
115
|
+
} else if (this.currentEditor?.isDisposed || !this.currentEditor?.isVisible) {
|
|
116
|
+
this.currentEditor = undefined;
|
|
117
|
+
this.onDidChangeCurrentEditorEmitter.fire(undefined);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
101
121
|
}
|
|
@@ -20,10 +20,24 @@
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.theia-notebook-cell-list {
|
|
23
|
+
position: absolute;
|
|
24
|
+
top: 0;
|
|
25
|
+
width: 100%;
|
|
23
26
|
overflow-y: auto;
|
|
24
27
|
list-style: none;
|
|
25
28
|
padding-left: 0px;
|
|
26
29
|
background-color: var(--theia-notebook-editorBackground);
|
|
30
|
+
z-index: 0;
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
.theia-notebook-cell-output-webview {
|
|
36
|
+
padding: 5px 0px;
|
|
37
|
+
margin: 0px 15px 0px 50px;
|
|
38
|
+
width: calc(100% - 60px);
|
|
39
|
+
position: absolute;
|
|
40
|
+
z-index: 0;
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
.theia-notebook-cell {
|
|
@@ -69,7 +83,8 @@
|
|
|
69
83
|
/* Rendered Markdown Content */
|
|
70
84
|
|
|
71
85
|
.theia-notebook-markdown-content {
|
|
72
|
-
|
|
86
|
+
pointer-events: all;
|
|
87
|
+
padding: 8px 16px 8px 0px;
|
|
73
88
|
font-size: var(--theia-notebook-markdown-size);
|
|
74
89
|
}
|
|
75
90
|
|
|
@@ -87,9 +102,13 @@
|
|
|
87
102
|
padding-bottom: 0;
|
|
88
103
|
}
|
|
89
104
|
|
|
105
|
+
.theia-notebook-markdown-sidebar {
|
|
106
|
+
width: 35px;
|
|
107
|
+
}
|
|
108
|
+
|
|
90
109
|
/* Markdown cell edit mode */
|
|
91
110
|
.theia-notebook-cell-content:has(.theia-notebook-markdown-editor-container>.theia-notebook-cell-editor) {
|
|
92
|
-
|
|
111
|
+
pointer-events: all;
|
|
93
112
|
margin-right: var(--theia-notebook-cell-editor-margin-right);
|
|
94
113
|
outline: 1px solid var(--theia-notebook-cellBorderColor);
|
|
95
114
|
}
|
|
@@ -108,6 +127,7 @@
|
|
|
108
127
|
}
|
|
109
128
|
|
|
110
129
|
.theia-notebook-cell-editor-container {
|
|
130
|
+
pointer-events: all;
|
|
111
131
|
width: calc(100% - 46px);
|
|
112
132
|
flex: 1;
|
|
113
133
|
outline: 1px solid var(--theia-notebook-cellBorderColor);
|
|
@@ -149,6 +169,7 @@
|
|
|
149
169
|
}
|
|
150
170
|
|
|
151
171
|
.theia-notebook-cell-toolbar {
|
|
172
|
+
pointer-events: all;
|
|
152
173
|
border: 1px solid var(--theia-notebook-cellToolbarSeparator);
|
|
153
174
|
display: flex;
|
|
154
175
|
position: absolute;
|
|
@@ -161,11 +182,15 @@
|
|
|
161
182
|
display: flex;
|
|
162
183
|
flex-direction: column;
|
|
163
184
|
padding: 2px;
|
|
164
|
-
background-color: var(--theia-editor-background);
|
|
165
185
|
flex-grow: 1;
|
|
166
186
|
}
|
|
167
187
|
|
|
168
188
|
.theia-notebook-cell-sidebar {
|
|
189
|
+
pointer-events: all;
|
|
190
|
+
display: flex;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.theia-notebook-cell-sidebar-actions {
|
|
169
194
|
display: flex;
|
|
170
195
|
flex-direction: column;
|
|
171
196
|
}
|
|
@@ -194,6 +219,7 @@
|
|
|
194
219
|
}
|
|
195
220
|
|
|
196
221
|
.theia-notebook-cell-divider {
|
|
222
|
+
pointer-events: all;
|
|
197
223
|
height: 25px;
|
|
198
224
|
width: 100%;
|
|
199
225
|
}
|
|
@@ -303,19 +329,19 @@
|
|
|
303
329
|
margin: 1px 0 0 4px;
|
|
304
330
|
}
|
|
305
331
|
|
|
306
|
-
.theia-notebook-cell-output-webview {
|
|
307
|
-
padding: 5px 0px;
|
|
308
|
-
margin: 0px 15px 0px 9px;
|
|
309
|
-
width: 100%;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
332
|
.theia-notebook-cell-drop-indicator {
|
|
313
333
|
height: 2px;
|
|
314
334
|
background-color: var(--theia-notebook-focusedCellBorder);
|
|
315
335
|
width: 100%;
|
|
316
336
|
}
|
|
317
337
|
|
|
338
|
+
.theia-notebook-collapsed-output-container {
|
|
339
|
+
width: 0;
|
|
340
|
+
overflow: visible;
|
|
341
|
+
}
|
|
342
|
+
|
|
318
343
|
.theia-notebook-collapsed-output {
|
|
344
|
+
text-wrap: nowrap;
|
|
319
345
|
padding: 4px 8px;
|
|
320
346
|
color: var(--theia-foreground);
|
|
321
347
|
margin-left: 30px;
|
|
@@ -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
|
}
|