@jupyterlab/notebook 4.6.0-alpha.5 → 4.6.0-beta.1

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/src/widget.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
4
 
4
5
  import { DOMUtils } from '@jupyterlab/apputils';
5
6
  import type {
@@ -1785,8 +1786,30 @@ export class Notebook extends StaticNotebook {
1785
1786
  this.activeCellIndex = newActiveCellIndex;
1786
1787
  }
1787
1788
  }
1789
+ switch (args.type) {
1790
+ case 'add':
1791
+ case 'set':
1792
+ args.oldValues.forEach(model => {
1793
+ model.contentChanged.disconnect(this._onCellContentChanged, this);
1794
+ });
1795
+ args.newValues.forEach(model => {
1796
+ model.contentChanged.connect(this._onCellContentChanged, this);
1797
+ });
1798
+ break;
1799
+ case 'remove':
1800
+ case 'clear':
1801
+ args.oldValues.forEach(model => {
1802
+ if (model) {
1803
+ model.contentChanged.disconnect(this._onCellContentChanged, this);
1804
+ }
1805
+ });
1806
+ break;
1807
+ case 'move':
1808
+ break;
1809
+ default:
1810
+ break;
1811
+ }
1788
1812
  }
1789
-
1790
1813
  /**
1791
1814
  * A signal emitted when the active cell changes.
1792
1815
  *
@@ -2427,6 +2450,90 @@ export class Notebook extends StaticNotebook {
2427
2450
  }
2428
2451
  }
2429
2452
 
2453
+ /**
2454
+ * Pop and return the top cell from the back stack, pushing to forward stack.
2455
+ * @experimental
2456
+ */
2457
+ popLastModifiedCell(): Cell | null {
2458
+ const activeId = this.activeCell?.model.id;
2459
+
2460
+ while (this._lastModifiedCellBackStack.length) {
2461
+ const id = this._lastModifiedCellBackStack.pop()!;
2462
+
2463
+ // Skip active cell
2464
+ if (id === activeId) {
2465
+ this._lastModifiedCellForwardStack.push(id);
2466
+ continue;
2467
+ }
2468
+
2469
+ const cell = this.widgets.find(c => c.model.id === id);
2470
+ if (cell && !cell.isDisposed) {
2471
+ this._lastModifiedCellForwardStack.push(id);
2472
+ return cell;
2473
+ }
2474
+ }
2475
+ return null;
2476
+ }
2477
+ /**
2478
+ * Pop and return the top cell from the forward stack, pushing to back stack.
2479
+ * @experimental
2480
+ */
2481
+ popNextModifiedCell(): Cell | null {
2482
+ const activeId = this.activeCell?.model.id;
2483
+
2484
+ while (this._lastModifiedCellForwardStack.length) {
2485
+ const id = this._lastModifiedCellForwardStack.pop()!;
2486
+
2487
+ if (id === activeId) {
2488
+ this._lastModifiedCellBackStack.push(id);
2489
+ continue;
2490
+ }
2491
+
2492
+ const cell = this.widgets.find(c => c.model.id === id);
2493
+ if (cell && !cell.isDisposed) {
2494
+ this._lastModifiedCellBackStack.push(id);
2495
+ return cell;
2496
+ }
2497
+ }
2498
+ return null;
2499
+ }
2500
+
2501
+ /**
2502
+ * Check if there is a navigable cell in the back stack.
2503
+ * @experimental
2504
+ */
2505
+ hasNavigableModifiedCellBack(): boolean {
2506
+ const activeId = this.activeCell?.model.id;
2507
+ for (let i = this._lastModifiedCellBackStack.length - 1; i >= 0; i--) {
2508
+ const id = this._lastModifiedCellBackStack[i];
2509
+ if (id !== activeId) {
2510
+ const cell = this.widgets.find(c => c.model.id === id);
2511
+ if (cell && !cell.isDisposed) {
2512
+ return true;
2513
+ }
2514
+ }
2515
+ }
2516
+ return false;
2517
+ }
2518
+
2519
+ /**
2520
+ * Check if there is a navigable cell in the forward stack.
2521
+ * @experimental
2522
+ */
2523
+ hasNavigableModifiedCellForward(): boolean {
2524
+ const activeId = this.activeCell?.model.id;
2525
+ for (let i = this._lastModifiedCellForwardStack.length - 1; i >= 0; i--) {
2526
+ const id = this._lastModifiedCellForwardStack[i];
2527
+ if (id !== activeId) {
2528
+ const cell = this.widgets.find(c => c.model.id === id);
2529
+ if (cell && !cell.isDisposed) {
2530
+ return true;
2531
+ }
2532
+ }
2533
+ }
2534
+ return false;
2535
+ }
2536
+
2430
2537
  /**
2431
2538
  * Handle `after-attach` messages for the widget.
2432
2539
  */
@@ -3483,6 +3590,40 @@ export class Notebook extends StaticNotebook {
3483
3590
  }
3484
3591
  }
3485
3592
 
3593
+ /**
3594
+ * Handle a cell content change.
3595
+ */
3596
+ private _onCellContentChanged(sender: ICellModel): void {
3597
+ const id = sender.id;
3598
+ const backStack = this._lastModifiedCellBackStack;
3599
+
3600
+ // Do nothing if the last modified cell is the same as this one
3601
+ if (backStack.length > 0 && backStack[backStack.length - 1] === id) {
3602
+ return;
3603
+ }
3604
+
3605
+ // Remove if already present elsewhere in the stack to move it to the top
3606
+ const idx = backStack.lastIndexOf(id);
3607
+ if (idx !== -1) {
3608
+ backStack.splice(idx, 1);
3609
+ }
3610
+ backStack.push(id);
3611
+ if (backStack.length > Notebook.MAX_MODIFIED_STACK) {
3612
+ backStack.shift();
3613
+ }
3614
+
3615
+ // Clear forward stack when a new cell is modified
3616
+ this._lastModifiedCellForwardStack = [];
3617
+ this._stateChanged.emit({
3618
+ name: 'lastModifiedCellStack',
3619
+ oldValue: null,
3620
+ newValue: null
3621
+ });
3622
+ }
3623
+
3624
+ private _lastModifiedCellBackStack: string[] = [];
3625
+ private _lastModifiedCellForwardStack: string[] = [];
3626
+ private static readonly MAX_MODIFIED_STACK = 50;
3486
3627
  private _activeCellIndex = -1;
3487
3628
  private _activeCell: Cell | null = null;
3488
3629
  private _mode: NotebookMode = 'command';
@@ -1,5 +1,6 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
4
 
4
5
  import type { IEditorMimeTypeService } from '@jupyterlab/codeeditor';
5
6
  import type { DocumentRegistry } from '@jupyterlab/docregistry';
package/style/base.css CHANGED
@@ -151,7 +151,7 @@
151
151
  outline: none;
152
152
  border: none;
153
153
  border-radius: 2px;
154
- box-shadow: 0 0 0 1px var(--jp-brand-color1);
154
+ box-shadow: 0 0 0 1px var(--jp-focus-outline-color);
155
155
  z-index: 1;
156
156
  }
157
157