@jupyterlab/notebook 4.6.0-alpha.3 → 4.6.0-alpha.5
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/actions.d.ts +9 -3
- package/lib/actions.js +65 -21
- package/lib/actions.js.map +1 -1
- package/lib/cellcounterstatus.d.ts +78 -0
- package/lib/cellcounterstatus.js +281 -0
- package/lib/cellcounterstatus.js.map +1 -0
- package/lib/default-toolbar.js +1 -1
- package/lib/default-toolbar.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/model.js +1 -0
- package/lib/model.js.map +1 -1
- package/lib/widget.d.ts +3 -0
- package/lib/widget.js +82 -11
- package/lib/widget.js.map +1 -1
- package/package.json +20 -20
- package/src/actions.tsx +90 -29
- package/src/cellcounterstatus.tsx +523 -0
- package/src/default-toolbar.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/model.ts +1 -0
- package/src/widget.ts +90 -11
- package/style/base.css +9 -80
- package/style/executionindicator.css +0 -6
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DOMUtils } from '@jupyterlab/apputils';
|
|
7
|
+
import type { Popup } from '@jupyterlab/statusbar';
|
|
8
|
+
import { showPopup, TextItem } from '@jupyterlab/statusbar';
|
|
9
|
+
import type { ITranslator, TranslationBundle } from '@jupyterlab/translation';
|
|
10
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
11
|
+
import {
|
|
12
|
+
classes,
|
|
13
|
+
lineFormIcon,
|
|
14
|
+
ReactWidget,
|
|
15
|
+
VDomModel,
|
|
16
|
+
VDomRenderer
|
|
17
|
+
} from '@jupyterlab/ui-components';
|
|
18
|
+
import React from 'react';
|
|
19
|
+
import type { Notebook } from '.';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A namespace for CellNumberFormComponent statics.
|
|
23
|
+
*/
|
|
24
|
+
namespace CellNumberFormComponent {
|
|
25
|
+
/**
|
|
26
|
+
* Props for the form component.
|
|
27
|
+
*/
|
|
28
|
+
export interface IProps {
|
|
29
|
+
/**
|
|
30
|
+
* A callback for when the form is submitted.
|
|
31
|
+
*/
|
|
32
|
+
handleSubmit: (value: number) => void;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The maximum cell number the form can take.
|
|
36
|
+
*/
|
|
37
|
+
maxCell: number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The application language translator.
|
|
41
|
+
*/
|
|
42
|
+
translator?: ITranslator;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* State for the form component.
|
|
47
|
+
*/
|
|
48
|
+
export interface IState {
|
|
49
|
+
/**
|
|
50
|
+
* The current value of the form.
|
|
51
|
+
*/
|
|
52
|
+
value: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Whether the form has focus.
|
|
56
|
+
*/
|
|
57
|
+
hasFocus: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A generated ID for the input field.
|
|
61
|
+
*/
|
|
62
|
+
textInputId: string;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A component for rendering a "go-to-cell" form.
|
|
68
|
+
*/
|
|
69
|
+
class CellNumberFormComponent extends React.Component<
|
|
70
|
+
CellNumberFormComponent.IProps,
|
|
71
|
+
CellNumberFormComponent.IState
|
|
72
|
+
> {
|
|
73
|
+
/**
|
|
74
|
+
* Construct a new CellNumberFormComponent.
|
|
75
|
+
*/
|
|
76
|
+
constructor(props: CellNumberFormComponent.IProps) {
|
|
77
|
+
super(props);
|
|
78
|
+
const translator = props.translator || nullTranslator;
|
|
79
|
+
this._trans = translator.load('jupyterlab');
|
|
80
|
+
this.state = {
|
|
81
|
+
value: '',
|
|
82
|
+
hasFocus: false,
|
|
83
|
+
textInputId: DOMUtils.createDomID() + '-cell-number-input'
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Focus the element on mount.
|
|
89
|
+
*/
|
|
90
|
+
componentDidMount() {
|
|
91
|
+
this._textInput?.focus();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Render the CellNumberFormComponent.
|
|
96
|
+
*/
|
|
97
|
+
render() {
|
|
98
|
+
return (
|
|
99
|
+
<div className="jp-lineFormSearch">
|
|
100
|
+
<form name="cellNumberForm" onSubmit={this._handleSubmit} noValidate>
|
|
101
|
+
<div
|
|
102
|
+
className={classes(
|
|
103
|
+
'jp-lineFormWrapper',
|
|
104
|
+
'lm-lineForm-wrapper',
|
|
105
|
+
this.state.hasFocus ? 'jp-lineFormWrapperFocusWithin' : undefined
|
|
106
|
+
)}
|
|
107
|
+
>
|
|
108
|
+
<input
|
|
109
|
+
type="number"
|
|
110
|
+
id={this.state.textInputId}
|
|
111
|
+
className="jp-lineFormInput"
|
|
112
|
+
min={1}
|
|
113
|
+
max={this.props.maxCell}
|
|
114
|
+
onChange={this._handleChange}
|
|
115
|
+
onFocus={this._handleFocus}
|
|
116
|
+
onBlur={this._handleBlur}
|
|
117
|
+
value={this.state.value}
|
|
118
|
+
ref={input => {
|
|
119
|
+
this._textInput = input;
|
|
120
|
+
}}
|
|
121
|
+
/>
|
|
122
|
+
<div className="jp-baseLineForm jp-lineFormButtonContainer">
|
|
123
|
+
<lineFormIcon.react
|
|
124
|
+
className="jp-baseLineForm jp-lineFormButtonIcon"
|
|
125
|
+
elementPosition="center"
|
|
126
|
+
/>
|
|
127
|
+
<input
|
|
128
|
+
type="submit"
|
|
129
|
+
className="jp-baseLineForm jp-lineFormButton"
|
|
130
|
+
value=""
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
<label
|
|
135
|
+
className="jp-lineFormCaption"
|
|
136
|
+
htmlFor={this.state.textInputId}
|
|
137
|
+
>
|
|
138
|
+
{this._trans.__(
|
|
139
|
+
'Go to cell number between 1 and %1',
|
|
140
|
+
this.props.maxCell
|
|
141
|
+
)}
|
|
142
|
+
</label>
|
|
143
|
+
</form>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Handle a change to the value in the input field.
|
|
150
|
+
*/
|
|
151
|
+
private _handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
152
|
+
this.setState({ value: event.currentTarget.value });
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Handle submission of the input field.
|
|
157
|
+
*/
|
|
158
|
+
private _handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
|
|
161
|
+
const value = parseInt(this._textInput?.value ?? '', 10);
|
|
162
|
+
if (
|
|
163
|
+
!isNaN(value) &&
|
|
164
|
+
isFinite(value) &&
|
|
165
|
+
1 <= value &&
|
|
166
|
+
value <= this.props.maxCell
|
|
167
|
+
) {
|
|
168
|
+
this.props.handleSubmit(value);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return false;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Handle focusing of the input field.
|
|
176
|
+
*/
|
|
177
|
+
private _handleFocus = () => {
|
|
178
|
+
this.setState({ hasFocus: true });
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Handle blurring of the input field.
|
|
183
|
+
*/
|
|
184
|
+
private _handleBlur = () => {
|
|
185
|
+
this.setState({ hasFocus: false });
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
private _trans: TranslationBundle;
|
|
189
|
+
private _textInput: HTMLInputElement | null = null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Props for CellCounterComponent.
|
|
194
|
+
*/
|
|
195
|
+
namespace CellCounterComponent {
|
|
196
|
+
export interface IProps {
|
|
197
|
+
/**
|
|
198
|
+
* Current active cell number (1-based).
|
|
199
|
+
*/
|
|
200
|
+
activeCell: number;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* First selected cell number (1-based).
|
|
204
|
+
*/
|
|
205
|
+
selectionStart: number;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Last selected cell number (1-based).
|
|
209
|
+
*/
|
|
210
|
+
selectionEnd: number;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Total number of notebook cells.
|
|
214
|
+
*/
|
|
215
|
+
totalCells: number;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* The application language translator.
|
|
219
|
+
*/
|
|
220
|
+
translator?: ITranslator;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Click handler used to launch the go-to-cell form.
|
|
224
|
+
*/
|
|
225
|
+
handleClick: () => void;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* A pure functional component for rendering a notebook cell counter.
|
|
231
|
+
*/
|
|
232
|
+
function CellCounterComponent(
|
|
233
|
+
props: CellCounterComponent.IProps
|
|
234
|
+
): React.ReactElement<CellCounterComponent.IProps> {
|
|
235
|
+
const translator = props.translator || nullTranslator;
|
|
236
|
+
const trans = translator.load('jupyterlab');
|
|
237
|
+
const source =
|
|
238
|
+
props.selectionStart > 0 && props.selectionStart !== props.selectionEnd
|
|
239
|
+
? trans.__(
|
|
240
|
+
'%1:%2/%3',
|
|
241
|
+
props.selectionStart,
|
|
242
|
+
props.selectionEnd,
|
|
243
|
+
props.totalCells
|
|
244
|
+
)
|
|
245
|
+
: trans.__('Cell %1/%2', props.activeCell, props.totalCells);
|
|
246
|
+
const keydownHandler = (event: React.KeyboardEvent<HTMLImageElement>) => {
|
|
247
|
+
if (
|
|
248
|
+
event.key === 'Enter' ||
|
|
249
|
+
event.key === 'Spacebar' ||
|
|
250
|
+
event.key === ' '
|
|
251
|
+
) {
|
|
252
|
+
event.preventDefault();
|
|
253
|
+
event.stopPropagation();
|
|
254
|
+
props.handleClick();
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
return (
|
|
259
|
+
<TextItem
|
|
260
|
+
role="button"
|
|
261
|
+
aria-haspopup
|
|
262
|
+
onClick={props.handleClick}
|
|
263
|
+
source={source}
|
|
264
|
+
title={trans.__('Go to cell…')}
|
|
265
|
+
tabIndex={0}
|
|
266
|
+
onKeyDown={keydownHandler}
|
|
267
|
+
/>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* A widget implementing a notebook cell counter status item.
|
|
273
|
+
*/
|
|
274
|
+
export class CellCounterStatus extends VDomRenderer<CellCounterStatus.Model> {
|
|
275
|
+
/**
|
|
276
|
+
* Construct a new CellCounterStatus status item.
|
|
277
|
+
*/
|
|
278
|
+
constructor(options: CellCounterStatus.IOptions = {}) {
|
|
279
|
+
super(new CellCounterStatus.Model());
|
|
280
|
+
this.addClass('jp-mod-highlighted');
|
|
281
|
+
this._translator = options.translator || nullTranslator;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Render the status item.
|
|
286
|
+
*/
|
|
287
|
+
render(): JSX.Element | null {
|
|
288
|
+
if (this.model === null) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return (
|
|
293
|
+
<CellCounterComponent
|
|
294
|
+
activeCell={this.model.activeCell}
|
|
295
|
+
selectionStart={this.model.selectionStart}
|
|
296
|
+
selectionEnd={this.model.selectionEnd}
|
|
297
|
+
totalCells={this.model.totalCells}
|
|
298
|
+
translator={this._translator}
|
|
299
|
+
handleClick={() => this._handleClick()}
|
|
300
|
+
/>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* A click handler for the widget.
|
|
306
|
+
*/
|
|
307
|
+
private _handleClick(): void {
|
|
308
|
+
if (this.model!.totalCells < 1) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (this._popup) {
|
|
313
|
+
this._popup.dispose();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const body = ReactWidget.create(
|
|
317
|
+
<CellNumberFormComponent
|
|
318
|
+
handleSubmit={value => this._handleSubmit(value)}
|
|
319
|
+
maxCell={this.model!.totalCells}
|
|
320
|
+
translator={this._translator}
|
|
321
|
+
/>
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
this._popup = showPopup({
|
|
325
|
+
body,
|
|
326
|
+
anchor: this,
|
|
327
|
+
align: 'right'
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Handle submission for the widget.
|
|
333
|
+
*/
|
|
334
|
+
private _handleSubmit(value: number): void {
|
|
335
|
+
const notebook = this.model!.notebook;
|
|
336
|
+
if (!notebook) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const cellIndex = value - 1;
|
|
341
|
+
notebook.activeCellIndex = cellIndex;
|
|
342
|
+
notebook.deselectAll();
|
|
343
|
+
void notebook.scrollToItem(cellIndex).catch(reason => {
|
|
344
|
+
console.error('Go to cell', reason);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
this._popup?.dispose();
|
|
348
|
+
notebook.activate();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private _translator: ITranslator;
|
|
352
|
+
private _popup: Popup | null = null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* A namespace for CellCounterStatus statics.
|
|
357
|
+
*/
|
|
358
|
+
export namespace CellCounterStatus {
|
|
359
|
+
/**
|
|
360
|
+
* Options for creating a CellCounterStatus item.
|
|
361
|
+
*/
|
|
362
|
+
export interface IOptions {
|
|
363
|
+
/**
|
|
364
|
+
* The application language translator.
|
|
365
|
+
*/
|
|
366
|
+
translator?: ITranslator;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Snapshot of the model state used for change detection.
|
|
371
|
+
*/
|
|
372
|
+
interface IState {
|
|
373
|
+
/**
|
|
374
|
+
* Current active cell number (1-based).
|
|
375
|
+
*/
|
|
376
|
+
activeCell: number;
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* First selected cell number (1-based).
|
|
380
|
+
*/
|
|
381
|
+
selectionStart: number;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Last selected cell number (1-based).
|
|
385
|
+
*/
|
|
386
|
+
selectionEnd: number;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Total number of cells.
|
|
390
|
+
*/
|
|
391
|
+
totalCells: number;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* A VDom model for a status item tracking active and total notebook cells.
|
|
396
|
+
*/
|
|
397
|
+
export class Model extends VDomModel {
|
|
398
|
+
/**
|
|
399
|
+
* The notebook tracked by this model.
|
|
400
|
+
*/
|
|
401
|
+
get notebook(): Notebook | null {
|
|
402
|
+
return this._notebook;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
set notebook(notebook: Notebook | null) {
|
|
406
|
+
const oldNotebook = this._notebook;
|
|
407
|
+
if (oldNotebook) {
|
|
408
|
+
oldNotebook.activeCellChanged.disconnect(this._onChanged, this);
|
|
409
|
+
oldNotebook.modelContentChanged.disconnect(this._onChanged, this);
|
|
410
|
+
oldNotebook.selectionChanged.disconnect(this._onChanged, this);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const oldState = this._getAllState();
|
|
414
|
+
this._notebook = notebook;
|
|
415
|
+
|
|
416
|
+
if (!this._notebook) {
|
|
417
|
+
this._activeCell = 0;
|
|
418
|
+
this._selectionStart = 0;
|
|
419
|
+
this._selectionEnd = 0;
|
|
420
|
+
this._totalCells = 0;
|
|
421
|
+
} else {
|
|
422
|
+
this._notebook.activeCellChanged.connect(this._onChanged, this);
|
|
423
|
+
this._notebook.modelContentChanged.connect(this._onChanged, this);
|
|
424
|
+
this._notebook.selectionChanged.connect(this._onChanged, this);
|
|
425
|
+
this._updateStateFromNotebook(this._notebook);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this._triggerChange(oldState, this._getAllState());
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* The current active cell index shown to users (1-based).
|
|
433
|
+
*/
|
|
434
|
+
get activeCell(): number {
|
|
435
|
+
return this._activeCell;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* The first selected cell index shown to users (1-based).
|
|
440
|
+
*/
|
|
441
|
+
get selectionStart(): number {
|
|
442
|
+
return this._selectionStart;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* The last selected cell index shown to users (1-based).
|
|
447
|
+
*/
|
|
448
|
+
get selectionEnd(): number {
|
|
449
|
+
return this._selectionEnd;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* The total number of cells.
|
|
454
|
+
*/
|
|
455
|
+
get totalCells(): number {
|
|
456
|
+
return this._totalCells;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* React to notebook changes by refreshing the tracked state.
|
|
461
|
+
*/
|
|
462
|
+
private _onChanged(notebook: Notebook): void {
|
|
463
|
+
const oldState = this._getAllState();
|
|
464
|
+
this._updateStateFromNotebook(notebook);
|
|
465
|
+
this._triggerChange(oldState, this._getAllState());
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
private _updateStateFromNotebook(notebook: Notebook): void {
|
|
469
|
+
const activeCellIndex = notebook.activeCellIndex;
|
|
470
|
+
this._activeCell = activeCellIndex >= 0 ? activeCellIndex + 1 : 0;
|
|
471
|
+
this._totalCells = notebook.widgets.length;
|
|
472
|
+
|
|
473
|
+
let selectionStart = this._activeCell;
|
|
474
|
+
let selectionEnd = this._activeCell;
|
|
475
|
+
let seenSelection = false;
|
|
476
|
+
|
|
477
|
+
notebook.widgets.forEach((cell, index) => {
|
|
478
|
+
if (!notebook.isSelectedOrActive(cell)) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const oneBasedIndex = index + 1;
|
|
483
|
+
if (!seenSelection) {
|
|
484
|
+
selectionStart = oneBasedIndex;
|
|
485
|
+
selectionEnd = oneBasedIndex;
|
|
486
|
+
seenSelection = true;
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
selectionEnd = oneBasedIndex;
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
this._selectionStart = seenSelection ? selectionStart : 0;
|
|
494
|
+
this._selectionEnd = seenSelection ? selectionEnd : 0;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
private _getAllState(): IState {
|
|
498
|
+
return {
|
|
499
|
+
activeCell: this._activeCell,
|
|
500
|
+
selectionStart: this._selectionStart,
|
|
501
|
+
selectionEnd: this._selectionEnd,
|
|
502
|
+
totalCells: this._totalCells
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
private _triggerChange(oldState: IState, newState: IState) {
|
|
507
|
+
if (
|
|
508
|
+
oldState.activeCell !== newState.activeCell ||
|
|
509
|
+
oldState.selectionStart !== newState.selectionStart ||
|
|
510
|
+
oldState.selectionEnd !== newState.selectionEnd ||
|
|
511
|
+
oldState.totalCells !== newState.totalCells
|
|
512
|
+
) {
|
|
513
|
+
this.stateChanged.emit(void 0);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
private _activeCell = 0;
|
|
518
|
+
private _selectionStart = 0;
|
|
519
|
+
private _selectionEnd = 0;
|
|
520
|
+
private _totalCells = 0;
|
|
521
|
+
private _notebook: Notebook | null = null;
|
|
522
|
+
}
|
|
523
|
+
}
|
package/src/default-toolbar.tsx
CHANGED
|
@@ -363,7 +363,7 @@ export class CellTypeSwitcher extends ReactWidget {
|
|
|
363
363
|
* Handle `keydown` events for the HTMLSelect component.
|
|
364
364
|
*/
|
|
365
365
|
handleKeyDown = (event: React.KeyboardEvent): void => {
|
|
366
|
-
if (event.
|
|
366
|
+
if (event.key === 'Enter') {
|
|
367
367
|
this._notebook.activate();
|
|
368
368
|
}
|
|
369
369
|
};
|
package/src/index.ts
CHANGED
package/src/model.ts
CHANGED
|
@@ -395,6 +395,7 @@ close the notebook without saving it.`,
|
|
|
395
395
|
list: CellList,
|
|
396
396
|
change: IObservableList.IChangedArgs<ICellModel>
|
|
397
397
|
): void {
|
|
398
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
398
399
|
switch (change.type) {
|
|
399
400
|
case 'add':
|
|
400
401
|
change.newValues.forEach(cell => {
|