@marimo-team/islands 0.25.3-dev267 → 0.25.3-dev269
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/dist/{ConnectedDataExplorerComponent-C4yCN38h.js → ConnectedDataExplorerComponent-eLHPh6uu.js} +8 -8
- package/dist/{ErrorBoundary-CewXPyL5.js → ErrorBoundary-DCtynjHZ.js} +4 -4
- package/dist/{abnfDiagram-VCTEODGH-o6Ay6Q63.js → abnfDiagram-VCTEODGH-hqd0IBtX.js} +2 -2
- package/dist/{architectureDiagram-5GKGNRK7-BhiwwlVg.js → architectureDiagram-5GKGNRK7-BzLAFcc0.js} +1 -1
- package/dist/{strings-BCKpLFNU.js → assertNever-DIU3JJbt.js} +14 -14
- package/dist/{chat-ui-CbgR5ivy.js → chat-ui-BWIkve2R.js} +17 -17
- package/dist/{chunk-IMKFNOWR-WMSMf4Nj.js → chunk-IMKFNOWR-DOeVvuyE.js} +1 -1
- package/dist/{chunk-SHT3W25Y-BRfADrzD.js → chunk-SHT3W25Y-DZoFI8wR.js} +1 -1
- package/dist/{chunk-SVP7TREG-CuK5QFre.js → chunk-SVP7TREG-CWu86PSW.js} +1 -1
- package/dist/{chunk-TICWLB2K-Bcun_jhJ.js → chunk-TICWLB2K-BrM0GoP3.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-CgWDbUDT.js → classDiagram-ZZMXUADV-DYi4V2bB.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-DYmc9SFU.js → classDiagram-v2-VYDZK3BY-tN7FIk-m.js} +2 -2
- package/dist/{code-visibility-BKBl9Rh6.js → code-visibility-CMF5tcNj.js} +44 -47
- package/dist/{common-N3Jd_6m9.js → common-DYAjQ1bK.js} +4866 -4857
- package/dist/{config-CmeG_Pb6.js → config-BsPruWMR.js} +2 -2
- package/dist/{createReducer-C_syF8Td.js → createReducer-DdtT_7ji.js} +1 -1
- package/dist/{cynefinDiagram-5FMLGOSQ-PPKWipjT.js → cynefinDiagram-5FMLGOSQ-D5nCnDc-.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-niRBZh--.js → dagre-GXQ25YYZ-BHkd7f_i.js} +1 -1
- package/dist/{data-grid-overlay-editor-Cp59CrqZ.js → data-grid-overlay-editor-B6oND8pX.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-DPiP9rot.js → diagram-S7CK7UJ4-D1ALppT2.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-B0WZuaxV.js → diagram-UQ7AKVKN-DLv0b83L.js} +1 -1
- package/dist/{diagram-VX7I27RA-Rn42WBuN.js → diagram-VX7I27RA-7XJ7J6qg.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BB93--ry.js → diagram-Z3DM3KII-7M7zbHp_.js} +1 -1
- package/dist/{dialog-BtprQCUw.js → dialog-DzCj1qQv.js} +1 -1
- package/dist/{dropdown-menu-BpImEfn3.js → dropdown-menu-CdXE15an.js} +3 -3
- package/dist/{ebnfDiagram-PWID7BFC-V4t5h6mZ.js → ebnfDiagram-PWID7BFC-DHH1qlmV.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-C1MsAKXd.js → erDiagram-RLTQ6QDP-fI_0dGef.js} +1 -1
- package/dist/{error-entries-CJGdD2ky.js → error-entries-CxN-Nq3V.js} +519 -458
- package/dist/{feedback-button-Qc1f9iPq.js → feedback-button-BelKx6R5.js} +22 -22
- package/dist/{flowDiagram-HODETNUW-DHjeJP96.js → flowDiagram-HODETNUW-Brg9MA6i.js} +2 -2
- package/dist/{formats-gGospKWJ.js → formats-DbSvAPY-.js} +1 -1
- package/dist/{glide-data-editor-hCq3K0sd.js → glide-data-editor-CMZ-kv0S.js} +11 -11
- package/dist/{glide-utils-DC3sk6EX.js → glide-utils-BSw3SSHF.js} +1 -1
- package/dist/{globals-B2_uMYDY.js → globals-DV77npCG.js} +2 -2
- package/dist/{html-to-image-S7spRQCi.js → html-to-image-Bc2AvXHG.js} +5121 -5121
- package/dist/{infoDiagram-27XIBGKW-Dovv6iKx.js → infoDiagram-27XIBGKW-E9e403YT.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-D2nyygsc.js → ishikawaDiagram-5VMMS53U-C-RlYDRo.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-KyVx0uTY.js → kanban-definition-UXKFOSKX-CLFl_uqK.js} +1 -1
- package/dist/main.js +5972 -6003
- package/dist/{mermaid-B-jKSwGt.js → mermaid-rd09e1JL.js} +34 -34
- package/dist/{mindmap-definition-YA3MSWOX-Bz9tKQFl.js → mindmap-definition-YA3MSWOX-BQ8TWtyB.js} +1 -1
- package/dist/{number-overlay-editor-CfNYvbdz.js → number-overlay-editor-CFTuKnrY.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-C_qpq6Tv.js → pegDiagram-XKGWAZYB-CN8UHFPi.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-Bp9ucgI4.js → pieDiagram-E7YTZNPT-DGuJ0EBd.js} +1 -1
- package/dist/{process-output-f34bkXTm.js → process-output-qecD7Dk8.js} +3 -3
- package/dist/{railroadDiagram-O6MQD6OU-tq-VEH6j.js → railroadDiagram-O6MQD6OU-BPDA8wy8.js} +2 -2
- package/dist/{requirementDiagram-BXWQKSXE-DW-vHadb.js → requirementDiagram-BXWQKSXE-ChzLGbGW.js} +1 -1
- package/dist/{reveal-component-CUxv-kkP.js → reveal-component-Doix35eL.js} +1094 -1094
- package/dist/{select-C33FVPPN.js → select-OxgozOC8.js} +1 -1
- package/dist/{sequenceDiagram-WJ2MYXX4-Dv9U9qRP.js → sequenceDiagram-WJ2MYXX4-DFX-bE6O.js} +1 -1
- package/dist/{spec-DH1lmF7Q.js → spec-oJn0RhpQ.js} +2 -2
- package/dist/{stateDiagram-D77RDMKH-DTmPQ0EB.js → stateDiagram-D77RDMKH-BR7cI3wK.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-CkCif0Iw.js → stateDiagram-v2-MP3YSRHH-oGqB5UDI.js} +2 -2
- package/dist/{static-state-BldGd99T.js → static-state-CuV6Pc3a.js} +1 -1
- package/dist/{swimlanes-42K2YHIH-21kCq6l8.js → swimlanes-42K2YHIH-DwSZl1yC.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-BpRJP6KU.js → swimlanesDiagram-VR7AAH4N-BHlcd-Ri.js} +2 -2
- package/dist/{timeline-definition-24CTP7MA-Ckgh4lS4.js → timeline-definition-24CTP7MA-DMmP-G2O.js} +1 -1
- package/dist/{toast-DpczUryP.js → toast-DbBHmxmB.js} +1 -1
- package/dist/{useAsyncData-DsZMvNXn.js → useAsyncData-BYIAoMqn.js} +1 -1
- package/dist/{useDateFormatter-Dk_xFci4.js → useDateFormatter-ButWkdcK.js} +1 -1
- package/dist/{useDeepCompareMemoize-KMBBux8C.js → useDeepCompareMemoize-Bz0c5GN6.js} +1 -1
- package/dist/{useTheme-BZ2GGLgm.js → useTheme-DPLobSFs.js} +7 -7
- package/dist/{utils-DXkj82sK.js → utils-EBklsC5R.js} +31 -31
- package/dist/{vega-component-CF9kI6C4.js → vega-component-rxIxAAh9.js} +6 -6
- package/dist/{vennDiagram-4TSXK5OY-CDei2Bt3.js → vennDiagram-4TSXK5OY-Db8GtH1G.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-CXavT601.js → wardleyDiagram-VM6X3IG4-DmIiC3FU.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CvJhcZri.js → xychartDiagram-S5SC5T6Z-DS9OPrNq.js} +1 -1
- package/package.json +1 -1
- package/src/__mocks__/executions.ts +195 -0
- package/src/__mocks__/notebook.ts +0 -1
- package/src/__tests__/CellStatus.test.tsx +19 -20
- package/src/components/dependency-graph/minimap-content.tsx +3 -2
- package/src/components/editor/__tests__/data-attributes.test.tsx +0 -7
- package/src/components/editor/__tests__/output-persistence.test.tsx +2 -2
- package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +1 -0
- package/src/components/editor/actions/useCellActionButton.tsx +7 -3
- package/src/components/editor/alerts/stdin-blocking-alert.tsx +3 -1
- package/src/components/editor/cell/CellStatus.tsx +23 -19
- package/src/components/editor/cell/RunButton.tsx +16 -6
- package/src/components/editor/cell/__tests__/useRunCells.test.ts +45 -0
- package/src/components/editor/cell/cell-context-menu.tsx +4 -1
- package/src/components/editor/cell/code/cell-editor.tsx +7 -5
- package/src/components/editor/cell/collapse.tsx +4 -0
- package/src/components/editor/cell/useRunCells.ts +18 -3
- package/src/components/editor/chrome/wrapper/sidebar.tsx +2 -4
- package/src/components/editor/header/status.tsx +4 -2
- package/src/components/editor/navigation/navigation.ts +3 -2
- package/src/components/editor/notebook-cell.tsx +82 -83
- package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +22 -16
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +12 -33
- package/src/components/editor/stdin-blocking-alert.tsx +3 -1
- package/src/components/scratchpad/scratchpad.tsx +4 -1
- package/src/components/slides/minimap.tsx +4 -2
- package/src/components/slides/reveal-component.tsx +14 -10
- package/src/components/slides/slide-cell-view.tsx +28 -24
- package/src/components/slides/slide.tsx +3 -4
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -389
- package/src/core/cells/__tests__/cell.test.ts +49 -154
- package/src/core/cells/__tests__/cells.test.ts +18 -127
- package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
- package/src/core/cells/__tests__/utils.test.ts +75 -247
- package/src/core/cells/actions.ts +5 -2
- package/src/core/cells/cell.ts +31 -133
- package/src/core/cells/cells.ts +14 -29
- package/src/core/cells/document.ts +3 -3
- package/src/core/cells/focus.ts +27 -6
- package/src/core/cells/layout.ts +1 -1
- package/src/core/cells/pending-delete-service.ts +5 -7
- package/src/core/cells/types.ts +13 -36
- package/src/core/cells/utils.ts +37 -68
- package/src/core/edit-app.tsx +2 -1
- package/src/core/executions/__tests__/atoms.test.ts +99 -0
- package/src/core/executions/__tests__/select.test.ts +268 -0
- package/src/core/executions/atoms.ts +206 -0
- package/src/core/executions/hooks.ts +31 -0
- package/src/core/executions/index.ts +31 -0
- package/src/core/executions/select.ts +175 -0
- package/src/core/export/__tests__/hooks.test.ts +0 -5
- package/src/core/islands/bootstrap.ts +4 -1
- package/src/core/islands/components/output-wrapper.tsx +5 -5
- package/src/core/kernel/handlers.ts +2 -11
- package/src/core/kernel/state.ts +0 -15
- package/src/core/lifecycle/render-policy.ts +12 -26
- package/src/core/network/__tests__/requests-lazy.test.ts +5 -5
- package/src/core/network/requests-lazy.ts +3 -3
- package/src/core/notebook/operations.ts +1 -1
- package/src/core/run-app.tsx +2 -1
- package/src/core/runtime/__tests__/adapter.test.ts +3 -3
- package/src/core/runtime/adapter.ts +4 -4
- package/src/core/session/useNotebookSession.tsx +3 -3
- package/src/core/wasm/bridge.ts +1 -1
- package/src/plugins/core/RenderHTML.tsx +3 -5
- package/src/plugins/core/__test__/RenderHTML-copy.test.tsx +60 -0
- package/src/plugins/core/registerReactComponent.tsx +4 -13
- package/src/stories/cell-status.stories.tsx +17 -10
- package/src/stories/cell.stories.tsx +0 -31
- package/src/stories/layout/vertical/one-column.stories.tsx +0 -9
- package/src/utils/time.ts +10 -0
package/src/core/cells/cells.ts
CHANGED
|
@@ -6,6 +6,11 @@ import { atomFamily, selectAtom, splitAtom } from "jotai/utils";
|
|
|
6
6
|
import { createRef, type ReducerWithoutAction } from "react";
|
|
7
7
|
import type { CellHandle } from "@/components/editor/notebook-cell";
|
|
8
8
|
import type { EditableDocument, Placement } from "@/core/notebook/document";
|
|
9
|
+
import {
|
|
10
|
+
cellExecutionInputsAtom,
|
|
11
|
+
cellExecutionView,
|
|
12
|
+
withdrawCells,
|
|
13
|
+
} from "@/core/executions";
|
|
9
14
|
import type { CellColumnId } from "./layout";
|
|
10
15
|
import { invariant } from "@/utils/invariant";
|
|
11
16
|
import { Logger } from "@/utils/Logger";
|
|
@@ -21,7 +26,7 @@ import { isErrorMime } from "../mime";
|
|
|
21
26
|
import type { CellConfig } from "../network/types";
|
|
22
27
|
import { createDeepEqualAtom, store } from "../state/jotai";
|
|
23
28
|
import { isWasm } from "../wasm/utils";
|
|
24
|
-
import {
|
|
29
|
+
import { transitionCell } from "./cell";
|
|
25
30
|
import { applyDocument } from "./document";
|
|
26
31
|
import { isCodeHidden, shownHiddenCodeAtom } from "./editor";
|
|
27
32
|
import { type CellId, SCRATCH_CELL_ID } from "./ids";
|
|
@@ -40,9 +45,7 @@ import {
|
|
|
40
45
|
disabledCellIds,
|
|
41
46
|
enabledCellIds,
|
|
42
47
|
getUndoLabel,
|
|
43
|
-
notebookIsRunning,
|
|
44
48
|
notebookNeedsRun,
|
|
45
|
-
notebookQueueOrRunningCount,
|
|
46
49
|
} from "./utils";
|
|
47
50
|
|
|
48
51
|
/** A deleted cell as it was, with where it went in the document. */
|
|
@@ -190,9 +193,7 @@ const {
|
|
|
190
193
|
const newState = updateCellRuntimeState({
|
|
191
194
|
state,
|
|
192
195
|
cellId: action.cellId,
|
|
193
|
-
cellReducer: (cell) => {
|
|
194
|
-
return prepareCellForExecution(cell);
|
|
195
|
-
},
|
|
196
|
+
cellReducer: (cell) => ({ ...cell, debuggerActive: false }),
|
|
196
197
|
});
|
|
197
198
|
return updateCellData({
|
|
198
199
|
state: newState,
|
|
@@ -286,13 +287,7 @@ const {
|
|
|
286
287
|
});
|
|
287
288
|
},
|
|
288
289
|
/** Record what the kernel last ran for each cell. */
|
|
289
|
-
setLastRun: (
|
|
290
|
-
state,
|
|
291
|
-
action: {
|
|
292
|
-
lastCodeRun: Record<CellId, string>;
|
|
293
|
-
lastExecutionTime: Record<CellId, number>;
|
|
294
|
-
},
|
|
295
|
-
) => {
|
|
290
|
+
setLastRun: (state, action: { lastCodeRun: Record<CellId, string> }) => {
|
|
296
291
|
const cellData = { ...state.cellData };
|
|
297
292
|
for (const cellId of state.cellIds) {
|
|
298
293
|
const cell = state.cellData[cellId];
|
|
@@ -300,7 +295,6 @@ const {
|
|
|
300
295
|
cellData[cellId] = {
|
|
301
296
|
...cell,
|
|
302
297
|
lastCodeRun,
|
|
303
|
-
lastExecutionTime: action.lastExecutionTime[cellId] ?? null,
|
|
304
298
|
// A cell the kernel never ran is not stale on load.
|
|
305
299
|
edited: lastCodeRun !== null && isEdited(lastCodeRun, cell.code),
|
|
306
300
|
};
|
|
@@ -497,7 +491,9 @@ export const canUndoDeletesAtom = atom((get) =>
|
|
|
497
491
|
|
|
498
492
|
export const undoLabelAtom = atom((get) => getUndoLabel(get(notebookAtom)));
|
|
499
493
|
|
|
500
|
-
export const needsRunAtom = atom((get) =>
|
|
494
|
+
export const needsRunAtom = atom((get) =>
|
|
495
|
+
notebookNeedsRun(get(notebookAtom), get(cellExecutionInputsAtom)),
|
|
496
|
+
);
|
|
501
497
|
|
|
502
498
|
export const cellErrorsAtom = atom((get) => {
|
|
503
499
|
const { cellIds, cellRuntime, cellData } = get(notebookAtom);
|
|
@@ -629,19 +625,6 @@ export const useCellDataAtoms = () => useAtom(cellDataAtoms);
|
|
|
629
625
|
|
|
630
626
|
export const cellsRuntimeAtom = atom((get) => get(notebookAtom).cellRuntime);
|
|
631
627
|
|
|
632
|
-
export const notebookIsRunningAtom = atom((get) =>
|
|
633
|
-
notebookIsRunning(get(notebookAtom)),
|
|
634
|
-
);
|
|
635
|
-
export const onlyScratchpadIsRunningAtom = atom((get) => {
|
|
636
|
-
const { cellRuntime } = get(notebookAtom);
|
|
637
|
-
return Object.entries(cellRuntime).every(
|
|
638
|
-
([id, rt]) => rt.status !== "running" || id === SCRATCH_CELL_ID,
|
|
639
|
-
);
|
|
640
|
-
});
|
|
641
|
-
export const notebookQueuedOrRunningCountAtom = atom((get) =>
|
|
642
|
-
notebookQueueOrRunningCount(get(notebookAtom)),
|
|
643
|
-
);
|
|
644
|
-
|
|
645
628
|
export const hasCellsAtom = atom((get) => get(notebookAtom).cellIds.length > 0);
|
|
646
629
|
export const cellDataAtom = atomFamily((cellId: CellId) =>
|
|
647
630
|
atom((get) => get(notebookAtom).cellData[cellId]),
|
|
@@ -666,6 +649,7 @@ export function releaseCellAtoms(cellId: CellId) {
|
|
|
666
649
|
cellDataAtom.remove(cellId);
|
|
667
650
|
cellRuntimeAtom.remove(cellId);
|
|
668
651
|
cellHandleAtom.remove(cellId);
|
|
652
|
+
withdrawCells(store, [cellId]);
|
|
669
653
|
}
|
|
670
654
|
|
|
671
655
|
/** Subscribes to reactive updates of the cell's data. */
|
|
@@ -726,7 +710,8 @@ export function createTracebackInfoAtom(
|
|
|
726
710
|
return undefined;
|
|
727
711
|
}
|
|
728
712
|
|
|
729
|
-
|
|
713
|
+
const { status } = cellExecutionView(get(cellExecutionInputsAtom), cellId);
|
|
714
|
+
if (status === "queued" || status === "running") {
|
|
730
715
|
return undefined;
|
|
731
716
|
}
|
|
732
717
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* both. Edits go the other way through the document model directly: the
|
|
6
6
|
* cell operations write it, and each cell editor is bound to its cell.
|
|
7
7
|
*
|
|
8
|
-
* TODO(MO-
|
|
8
|
+
* TODO(MO-8349): Delete this module once components read cells from the
|
|
9
9
|
* document model and `notebookAtom` holds only runtime and editor state.
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -64,7 +64,7 @@ function followCell(current: CellData, cell: EditableCell): CellData {
|
|
|
64
64
|
* Returns the same state when nothing differs, so a local edit that the
|
|
65
65
|
* document already reflects changes nothing.
|
|
66
66
|
*
|
|
67
|
-
* TODO(MO-
|
|
67
|
+
* TODO(MO-8349): Delete with `reconcileDocument` once cells are read from
|
|
68
68
|
* the document model.
|
|
69
69
|
*/
|
|
70
70
|
export function applyDocument(
|
|
@@ -134,7 +134,7 @@ export function applyDocument(
|
|
|
134
134
|
* Reconcile the model's document and name its columns, now and on each
|
|
135
135
|
* change, until the signal aborts.
|
|
136
136
|
*
|
|
137
|
-
* TODO(MO-
|
|
137
|
+
* TODO(MO-8349): Delete with `applyDocument`.
|
|
138
138
|
*/
|
|
139
139
|
export function followDocument({
|
|
140
140
|
store,
|
package/src/core/cells/focus.ts
CHANGED
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
import type { EditorView } from "@codemirror/view";
|
|
4
4
|
import { atom, useAtomValue } from "jotai";
|
|
5
5
|
import { createReducerAndAtoms } from "@/utils/createReducer";
|
|
6
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
type CellExecutionInputs,
|
|
8
|
+
type CellRunStatus,
|
|
9
|
+
cellExecutionInputsAtom,
|
|
10
|
+
cellExecutionView,
|
|
11
|
+
} from "@/core/executions";
|
|
12
|
+
import type { CellConfig } from "../network/types";
|
|
7
13
|
import { type NotebookState, notebookAtom } from "./cells";
|
|
8
14
|
import type { CellId } from "./ids";
|
|
9
15
|
import { SCRATCH_CELL_ID } from "./ids";
|
|
@@ -75,7 +81,8 @@ export const lastFocusedCellAtom = atom<{
|
|
|
75
81
|
name: string;
|
|
76
82
|
config: CellConfig;
|
|
77
83
|
cellId: CellId;
|
|
78
|
-
status:
|
|
84
|
+
status: CellRunStatus;
|
|
85
|
+
blocked: boolean;
|
|
79
86
|
getEditorView: () => EditorView | null;
|
|
80
87
|
hasOutput: boolean;
|
|
81
88
|
hasConsoleOutput: boolean;
|
|
@@ -89,16 +96,28 @@ export const lastFocusedCellAtom = atom<{
|
|
|
89
96
|
return null;
|
|
90
97
|
}
|
|
91
98
|
|
|
92
|
-
return cellFocusDetails(
|
|
99
|
+
return cellFocusDetails(
|
|
100
|
+
cellId,
|
|
101
|
+
get(notebookAtom),
|
|
102
|
+
get(cellExecutionInputsAtom),
|
|
103
|
+
);
|
|
93
104
|
});
|
|
94
105
|
|
|
95
106
|
export function cellFocusDetailsAtom(cellId: CellId) {
|
|
96
107
|
return atom((get) => {
|
|
97
|
-
return cellFocusDetails(
|
|
108
|
+
return cellFocusDetails(
|
|
109
|
+
cellId,
|
|
110
|
+
get(notebookAtom),
|
|
111
|
+
get(cellExecutionInputsAtom),
|
|
112
|
+
);
|
|
98
113
|
});
|
|
99
114
|
}
|
|
100
115
|
|
|
101
|
-
function cellFocusDetails(
|
|
116
|
+
function cellFocusDetails(
|
|
117
|
+
cellId: CellId,
|
|
118
|
+
notebookState: NotebookState,
|
|
119
|
+
executions: CellExecutionInputs,
|
|
120
|
+
) {
|
|
102
121
|
const { cellData, cellHandles, cellRuntime } = notebookState;
|
|
103
122
|
const data = cellData[cellId];
|
|
104
123
|
const runtime = cellRuntime[cellId];
|
|
@@ -107,12 +126,14 @@ function cellFocusDetails(cellId: CellId, notebookState: NotebookState) {
|
|
|
107
126
|
return null;
|
|
108
127
|
}
|
|
109
128
|
const getEditorView = () => handle.editorViewOrNull;
|
|
129
|
+
const execution = cellExecutionView(executions, cellId);
|
|
110
130
|
|
|
111
131
|
return {
|
|
112
132
|
cellId,
|
|
113
133
|
name: data.name,
|
|
114
134
|
config: data.config,
|
|
115
|
-
status:
|
|
135
|
+
status: execution.status,
|
|
136
|
+
blocked: execution.blocked,
|
|
116
137
|
getEditorView: getEditorView,
|
|
117
138
|
hasOutput: runtime?.output != null,
|
|
118
139
|
hasConsoleOutput: runtime?.consoleOutputs != null,
|
package/src/core/cells/layout.ts
CHANGED
|
@@ -140,7 +140,7 @@ export function deriveLayout(
|
|
|
140
140
|
* The layout of the notebook's cells: the document's order and columns,
|
|
141
141
|
* this browser's column ids and folds, and the kernel's outlines.
|
|
142
142
|
*
|
|
143
|
-
* TODO(MO-
|
|
143
|
+
* TODO(MO-8404): Outlines come from the host.
|
|
144
144
|
*/
|
|
145
145
|
export const layoutAtom = atom((get): Layout => {
|
|
146
146
|
const model = get(activeDocumentModelAtom);
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "@/components/editor/cell/useDeleteCell";
|
|
8
8
|
import { notebookAtom } from "@/core/cells/cells";
|
|
9
9
|
import type { CellId } from "@/core/cells/ids";
|
|
10
|
+
import { cellExecutionInputsAtom, cellExecutionView } from "@/core/executions";
|
|
10
11
|
import type { JotaiStore } from "@/core/state/jotai";
|
|
11
12
|
import { variablesAtom } from "@/core/variables/state";
|
|
12
13
|
import type { VariableName } from "@/core/variables/types";
|
|
@@ -46,6 +47,7 @@ const { valueAtom: pendingDeleteStateAtom, useActions } = createReducerAndAtoms(
|
|
|
46
47
|
) => {
|
|
47
48
|
const { cellIds, deleteCell, deleteManyCells, store } = action;
|
|
48
49
|
const notebook = store.get(notebookAtom);
|
|
50
|
+
const executions = store.get(cellExecutionInputsAtom);
|
|
49
51
|
const variables = store.get(variablesAtom);
|
|
50
52
|
|
|
51
53
|
const emptyCells = new Set(
|
|
@@ -62,8 +64,6 @@ const { valueAtom: pendingDeleteStateAtom, useActions } = createReducerAndAtoms(
|
|
|
62
64
|
continue;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
const runtimeInfo = notebook.cellRuntime[cellId];
|
|
66
|
-
|
|
67
67
|
// Build defs map for this cell
|
|
68
68
|
const defs = new Map<VariableName, readonly CellId[]>();
|
|
69
69
|
for (const variable of Object.values(variables)) {
|
|
@@ -77,11 +77,9 @@ const { valueAtom: pendingDeleteStateAtom, useActions } = createReducerAndAtoms(
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
let executionDurationMs: number | undefined;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
) {
|
|
84
|
-
executionDurationMs = runtimeInfo.runElapsedTimeMs;
|
|
80
|
+
const { duration } = cellExecutionView(executions, cellId);
|
|
81
|
+
if (duration !== null && duration > 2000) {
|
|
82
|
+
executionDurationMs = duration;
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
if (defs.size === 0 && executionDurationMs === undefined) {
|
package/src/core/cells/types.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import type { Milliseconds, Seconds } from "@/utils/time";
|
|
4
3
|
import type { OutputMessage } from "../kernel/messages";
|
|
5
|
-
import type { CellConfig
|
|
4
|
+
import type { CellConfig } from "../network/types";
|
|
6
5
|
import type { CellId } from "./ids";
|
|
7
6
|
import { DEFAULT_CELL_NAME } from "./names";
|
|
8
7
|
import type { Outline } from "./outline";
|
|
@@ -11,7 +10,7 @@ import type { Outline } from "./outline";
|
|
|
11
10
|
* Whether a cell's code has changed since it last ran. A cell that never ran
|
|
12
11
|
* is edited once it has code. Whitespace at the ends does not count.
|
|
13
12
|
*
|
|
14
|
-
* TODO(MO-
|
|
13
|
+
* TODO(MO-8403): Delete with `lastCodeRun`.
|
|
15
14
|
*/
|
|
16
15
|
export function isEdited(lastCodeRun: string | null, code: string): boolean {
|
|
17
16
|
return lastCodeRun === null
|
|
@@ -27,7 +26,6 @@ export function createCell({
|
|
|
27
26
|
name = DEFAULT_CELL_NAME,
|
|
28
27
|
code = "",
|
|
29
28
|
lastCodeRun = null,
|
|
30
|
-
lastExecutionTime = null,
|
|
31
29
|
edited = false,
|
|
32
30
|
config,
|
|
33
31
|
}: Partial<CellData> & { id: CellId }): CellData {
|
|
@@ -43,7 +41,6 @@ export function createCell({
|
|
|
43
41
|
code: code,
|
|
44
42
|
edited: edited,
|
|
45
43
|
lastCodeRun: lastCodeRun,
|
|
46
|
-
lastExecutionTime: lastExecutionTime,
|
|
47
44
|
};
|
|
48
45
|
}
|
|
49
46
|
|
|
@@ -64,14 +61,7 @@ export function createCellRuntimeState(
|
|
|
64
61
|
outline: null,
|
|
65
62
|
output: null,
|
|
66
63
|
consoleOutputs: [],
|
|
67
|
-
status: "idle" as RuntimeState,
|
|
68
64
|
staleInputs: false,
|
|
69
|
-
interrupted: false,
|
|
70
|
-
errored: false,
|
|
71
|
-
stopped: false,
|
|
72
|
-
runElapsedTimeMs: null,
|
|
73
|
-
runStartTimestamp: null,
|
|
74
|
-
lastRunStartTimestamp: null,
|
|
75
65
|
debuggerActive: false,
|
|
76
66
|
...state,
|
|
77
67
|
};
|
|
@@ -90,41 +80,28 @@ export interface CellData {
|
|
|
90
80
|
edited: boolean;
|
|
91
81
|
/** snapshot of code that was last run */
|
|
92
82
|
lastCodeRun: string | null;
|
|
93
|
-
/** execution time on session start / resume */
|
|
94
|
-
lastExecutionTime: number | null;
|
|
95
83
|
/** cell configuration */
|
|
96
84
|
config: CellConfig;
|
|
97
85
|
}
|
|
98
86
|
|
|
87
|
+
/**
|
|
88
|
+
* What the kernel's cell-ops still own. Status, timing, and how a cell last
|
|
89
|
+
* ended come from the host's executions (see `@/core/executions`).
|
|
90
|
+
*
|
|
91
|
+
* TODO(MO-8407): Delete.
|
|
92
|
+
*/
|
|
99
93
|
export interface CellRuntimeState {
|
|
100
|
-
/** a message encoding the cell's output */
|
|
94
|
+
/** a message encoding the cell's output. TODO(MO-8404) */
|
|
101
95
|
output: OutputMessage | null;
|
|
102
|
-
/** TOC outline */
|
|
96
|
+
/** TOC outline. TODO(MO-8404) */
|
|
103
97
|
outline: Outline | null;
|
|
104
|
-
/** messages encoding the cell's console outputs. */
|
|
98
|
+
/** messages encoding the cell's console outputs. TODO(MO-8405) */
|
|
105
99
|
consoleOutputs: ConsoleOutputMessage[];
|
|
106
|
-
/**
|
|
107
|
-
status: RuntimeState;
|
|
108
|
-
/** whether the cell has stale inputs*/
|
|
100
|
+
/** whether the cell has stale inputs. TODO(MO-8403) */
|
|
109
101
|
staleInputs: boolean;
|
|
110
|
-
/** whether this cell has been interrupted since its last run */
|
|
111
|
-
interrupted: boolean;
|
|
112
|
-
/** whether this cell was stopped with mo.stop */
|
|
113
|
-
stopped: boolean;
|
|
114
|
-
/**
|
|
115
|
-
* whether marimo encountered an error when trying to register or run
|
|
116
|
-
* this cell (such as a multiple definition error)
|
|
117
|
-
*/
|
|
118
|
-
errored: boolean;
|
|
119
|
-
/** run start time, as seconds since epoch */
|
|
120
|
-
runStartTimestamp: Seconds | null;
|
|
121
|
-
/** run elapsed time, in milliseconds */
|
|
122
|
-
runElapsedTimeMs: Milliseconds | null;
|
|
123
|
-
/** last run timestamp, as seconds since epoch */
|
|
124
|
-
lastRunStartTimestamp: Seconds | null;
|
|
125
102
|
/** debugger active */
|
|
126
103
|
debuggerActive: boolean;
|
|
127
|
-
/** serialization message */
|
|
104
|
+
/** serialization message. TODO(MO-8414) */
|
|
128
105
|
serialization?: string | null;
|
|
129
106
|
}
|
|
130
107
|
|
package/src/core/cells/utils.ts
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import type { EditorView } from "@codemirror/view";
|
|
4
|
+
import {
|
|
5
|
+
type CellExecutionInputs,
|
|
6
|
+
type CellExecutionView,
|
|
7
|
+
cellExecutionView,
|
|
8
|
+
} from "@/core/executions";
|
|
4
9
|
import { Objects } from "@/utils/objects";
|
|
5
10
|
import type { MarimoError, OutputMessage } from "../kernel/messages";
|
|
6
11
|
import { isErrorMime } from "../mime";
|
|
7
|
-
import type { RuntimeState } from "../network/types";
|
|
8
12
|
import type { NotebookState } from "./cells";
|
|
9
13
|
import type { CellId } from "./ids";
|
|
10
14
|
|
|
11
|
-
export function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export function notebookQueueOrRunningCount(state: NotebookState) {
|
|
18
|
-
return Object.values(state.cellRuntime).filter(
|
|
19
|
-
(cell) => cell.status === "running" || cell.status === "queued",
|
|
20
|
-
).length;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function notebookNeedsRun(state: NotebookState) {
|
|
24
|
-
return staleCellIds(state).length > 0;
|
|
15
|
+
export function notebookNeedsRun(
|
|
16
|
+
state: NotebookState,
|
|
17
|
+
executions: CellExecutionInputs,
|
|
18
|
+
) {
|
|
19
|
+
return staleCellIds(state, executions).length > 0;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
export function notebookCells(state: NotebookState) {
|
|
@@ -84,16 +79,16 @@ export function getUndoLabel(state: NotebookState): string {
|
|
|
84
79
|
*/
|
|
85
80
|
export function getDescendantsStatus(
|
|
86
81
|
state: NotebookState,
|
|
82
|
+
executions: CellExecutionInputs,
|
|
87
83
|
descendants: readonly CellId[],
|
|
88
84
|
) {
|
|
85
|
+
const views = descendants.map((id) => cellExecutionView(executions, id));
|
|
89
86
|
const stale = descendants.some(
|
|
90
87
|
(id) => state.cellRuntime[id]?.staleInputs || state.cellData[id]?.edited,
|
|
91
88
|
);
|
|
92
|
-
const errored =
|
|
93
|
-
const runningOrQueued =
|
|
94
|
-
(
|
|
95
|
-
state.cellRuntime[id]?.status === "running" ||
|
|
96
|
-
state.cellRuntime[id]?.status === "queued",
|
|
89
|
+
const errored = views.some((view) => view.outcome === "error");
|
|
90
|
+
const runningOrQueued = views.some(
|
|
91
|
+
(view) => view.status === "running" || view.status === "queued",
|
|
97
92
|
);
|
|
98
93
|
|
|
99
94
|
return {
|
|
@@ -106,54 +101,30 @@ export function getDescendantsStatus(
|
|
|
106
101
|
/**
|
|
107
102
|
* Cells that are stale and can be run.
|
|
108
103
|
*/
|
|
109
|
-
export function staleCellIds(
|
|
104
|
+
export function staleCellIds(
|
|
105
|
+
state: NotebookState,
|
|
106
|
+
executions: CellExecutionInputs,
|
|
107
|
+
) {
|
|
110
108
|
const { cellIds, cellData, cellRuntime } = state;
|
|
111
|
-
return cellIds.filter(
|
|
112
|
-
(cellId)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
executionTime:
|
|
116
|
-
cellRuntime[cellId].runElapsedTimeMs ??
|
|
117
|
-
// lastExecutionTime is what was seen on session start/resume
|
|
118
|
-
cellData[cellId].lastExecutionTime,
|
|
119
|
-
status: cellRuntime[cellId].status,
|
|
120
|
-
errored: cellRuntime[cellId].errored,
|
|
121
|
-
interrupted: cellRuntime[cellId].interrupted,
|
|
122
|
-
stopped: cellRuntime[cellId].stopped,
|
|
123
|
-
}) ||
|
|
109
|
+
return cellIds.filter((cellId) => {
|
|
110
|
+
const execution = cellExecutionView(executions, cellId);
|
|
111
|
+
return (
|
|
112
|
+
isUninstantiated(execution) ||
|
|
124
113
|
cellData[cellId].edited ||
|
|
125
|
-
|
|
114
|
+
execution.outcome === "interrupted" ||
|
|
126
115
|
(cellRuntime[cellId].staleInputs &&
|
|
127
116
|
// if a cell is disabled, it can't be run ...
|
|
128
|
-
!(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
)),
|
|
132
|
-
);
|
|
117
|
+
!(execution.blocked || cellData[cellId].config.disabled))
|
|
118
|
+
);
|
|
119
|
+
});
|
|
133
120
|
}
|
|
134
121
|
|
|
122
|
+
/** Whether a cell has never run: no result to show and nothing in flight. */
|
|
135
123
|
export function isUninstantiated({
|
|
136
|
-
executionTime,
|
|
137
124
|
status,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}: {
|
|
142
|
-
executionTime: number | null;
|
|
143
|
-
status: RuntimeState;
|
|
144
|
-
errored: boolean;
|
|
145
|
-
interrupted: boolean;
|
|
146
|
-
stopped: boolean;
|
|
147
|
-
}) {
|
|
148
|
-
return (
|
|
149
|
-
// hasn't run ...
|
|
150
|
-
executionTime === null &&
|
|
151
|
-
// isn't currently queued/running &&
|
|
152
|
-
status !== "queued" &&
|
|
153
|
-
status !== "running" &&
|
|
154
|
-
// and isn't in an error state.
|
|
155
|
-
!(errored || interrupted || stopped)
|
|
156
|
-
);
|
|
125
|
+
outcome,
|
|
126
|
+
}: Pick<CellExecutionView, "status" | "outcome">) {
|
|
127
|
+
return outcome === null && status !== "queued" && status !== "running";
|
|
157
128
|
}
|
|
158
129
|
|
|
159
130
|
/**
|
|
@@ -166,17 +137,15 @@ export function cellNeedsRun({
|
|
|
166
137
|
interrupted,
|
|
167
138
|
staleInputs,
|
|
168
139
|
disabled,
|
|
169
|
-
|
|
140
|
+
blocked,
|
|
170
141
|
}: {
|
|
171
142
|
edited: boolean;
|
|
172
143
|
interrupted: boolean;
|
|
173
144
|
staleInputs: boolean;
|
|
174
145
|
disabled: boolean | undefined;
|
|
175
|
-
|
|
146
|
+
blocked: boolean;
|
|
176
147
|
}): boolean {
|
|
177
|
-
|
|
178
|
-
disabled || status === "disabled-transitively";
|
|
179
|
-
return edited || interrupted || (staleInputs && !disabledOrAncestorDisabled);
|
|
148
|
+
return edited || interrupted || (staleInputs && !(disabled || blocked));
|
|
180
149
|
}
|
|
181
150
|
|
|
182
151
|
export function cellStatusClasses({
|
|
@@ -184,20 +153,20 @@ export function cellStatusClasses({
|
|
|
184
153
|
errored,
|
|
185
154
|
stopped,
|
|
186
155
|
disabled,
|
|
187
|
-
|
|
156
|
+
blocked,
|
|
188
157
|
}: {
|
|
189
158
|
needsRun: boolean;
|
|
190
159
|
errored: boolean;
|
|
191
160
|
stopped: boolean;
|
|
192
161
|
disabled: boolean | undefined;
|
|
193
|
-
|
|
162
|
+
blocked: boolean;
|
|
194
163
|
}) {
|
|
195
164
|
return {
|
|
196
165
|
"needs-run": needsRun,
|
|
197
166
|
"has-error": errored,
|
|
198
167
|
stopped,
|
|
199
168
|
disabled: disabled ?? false,
|
|
200
|
-
stale:
|
|
169
|
+
stale: blocked,
|
|
201
170
|
};
|
|
202
171
|
}
|
|
203
172
|
|
package/src/core/edit-app.tsx
CHANGED
|
@@ -27,7 +27,8 @@ import { useSetOutputsExpanded } from "../components/editor/actions/useSetOutput
|
|
|
27
27
|
import { CellArray } from "../components/editor/renderers/cell-array";
|
|
28
28
|
import { CellsRenderer } from "../components/editor/renderers/cells-renderer";
|
|
29
29
|
import { useHotkey } from "../hooks/useHotkey";
|
|
30
|
-
import { hasCellsAtom
|
|
30
|
+
import { hasCellsAtom } from "./cells/cells";
|
|
31
|
+
import { notebookIsRunningAtom } from "./executions";
|
|
31
32
|
import { numColumnsAtom } from "./cells/layout";
|
|
32
33
|
import { useCellActions } from "./cells/actions";
|
|
33
34
|
import type { AppConfig, UserConfig } from "./config/config-schema";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { createStore } from "jotai";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { MockExecutions } from "@/__mocks__/executions";
|
|
6
|
+
import { cellId } from "@/__tests__/branded";
|
|
7
|
+
import type { CellMessage } from "@/core/kernel/messages";
|
|
8
|
+
import {
|
|
9
|
+
cellExecutionInputsAtom,
|
|
10
|
+
notebookQueuedOrRunningCountAtom,
|
|
11
|
+
observeCellMessage,
|
|
12
|
+
submitCells,
|
|
13
|
+
} from "../atoms";
|
|
14
|
+
import { cellExecutionView } from "../select";
|
|
15
|
+
|
|
16
|
+
const C1 = cellId("c1");
|
|
17
|
+
|
|
18
|
+
function cellOp(status: CellMessage["status"]): CellMessage {
|
|
19
|
+
return {
|
|
20
|
+
cell_id: C1,
|
|
21
|
+
output: null,
|
|
22
|
+
console: null,
|
|
23
|
+
status,
|
|
24
|
+
stale_inputs: null,
|
|
25
|
+
timestamp: 1,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("observeCellMessage", () => {
|
|
30
|
+
it("withdraws a submission once the kernel reports the cell blocked", () => {
|
|
31
|
+
const store = createStore();
|
|
32
|
+
MockExecutions.seed(store, []);
|
|
33
|
+
submitCells(store, [C1]);
|
|
34
|
+
expect(
|
|
35
|
+
cellExecutionView(store.get(cellExecutionInputsAtom), C1).status,
|
|
36
|
+
).toBe("queued");
|
|
37
|
+
|
|
38
|
+
observeCellMessage(store, cellOp("disabled-transitively"));
|
|
39
|
+
|
|
40
|
+
const view = cellExecutionView(store.get(cellExecutionInputsAtom), C1);
|
|
41
|
+
expect(view.status).toBe("idle");
|
|
42
|
+
expect(view.blocked).toBe(true);
|
|
43
|
+
expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(0);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("forgets submissions and blocked cells with the replica they were made for", () => {
|
|
47
|
+
const store = createStore();
|
|
48
|
+
MockExecutions.seed(store, []);
|
|
49
|
+
submitCells(store, [C1]);
|
|
50
|
+
observeCellMessage(store, cellOp("disabled-transitively"));
|
|
51
|
+
|
|
52
|
+
MockExecutions.seed(store, []);
|
|
53
|
+
|
|
54
|
+
const view = cellExecutionView(store.get(cellExecutionInputsAtom), C1);
|
|
55
|
+
expect(view.status).toBe("idle");
|
|
56
|
+
expect(view.blocked).toBe(false);
|
|
57
|
+
expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(0);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("keeps a submission while the cell is merely queued", () => {
|
|
61
|
+
const store = createStore();
|
|
62
|
+
MockExecutions.seed(store, []);
|
|
63
|
+
submitCells(store, [C1]);
|
|
64
|
+
|
|
65
|
+
observeCellMessage(store, cellOp("queued"));
|
|
66
|
+
|
|
67
|
+
expect(
|
|
68
|
+
cellExecutionView(store.get(cellExecutionInputsAtom), C1).status,
|
|
69
|
+
).toBe("queued");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("forgets acknowledged submissions and blocked cells when the replica follows a new notebook", () => {
|
|
73
|
+
const store = createStore();
|
|
74
|
+
const replica = MockExecutions.seed(store, []);
|
|
75
|
+
submitCells(store, [C1]);
|
|
76
|
+
observeCellMessage(store, {
|
|
77
|
+
...cellOp("disabled-transitively"),
|
|
78
|
+
cell_id: cellId("c2"),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const completed = MockExecutions.inputs([MockExecutions.completed(C1)]);
|
|
82
|
+
store.set(replica.executionsAtom, completed.executions);
|
|
83
|
+
store.set(replica.resultsAtom, completed.results);
|
|
84
|
+
expect(
|
|
85
|
+
cellExecutionView(store.get(cellExecutionInputsAtom), C1).status,
|
|
86
|
+
).toBe("idle");
|
|
87
|
+
|
|
88
|
+
const empty = MockExecutions.inputs([]);
|
|
89
|
+
store.set(replica.executionsAtom, empty.executions);
|
|
90
|
+
store.set(replica.resultsAtom, empty.results);
|
|
91
|
+
store.set(replica.notebookAtom, {
|
|
92
|
+
...store.get(replica.notebookAtom),
|
|
93
|
+
id: "n2",
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(store.get(cellExecutionInputsAtom)).toEqual(empty);
|
|
97
|
+
expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(0);
|
|
98
|
+
});
|
|
99
|
+
});
|