@marimo-team/islands 0.25.3-dev266 → 0.25.3-dev268
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-C_hj7Poi.js → ConnectedDataExplorerComponent-eLHPh6uu.js} +9 -9
- package/dist/{ErrorBoundary-CvxlC3F1.js → ErrorBoundary-CQYAoD7X.js} +64 -69
- package/dist/{abnfDiagram-VCTEODGH-DzrZZXRD.js → abnfDiagram-VCTEODGH-hqd0IBtX.js} +2 -2
- package/dist/{any-language-editor-CFeWfC3o.js → any-language-editor-DnG26QXh.js} +1 -1
- package/dist/{architectureDiagram-5GKGNRK7-iF_snyFL.js → architectureDiagram-5GKGNRK7-BzLAFcc0.js} +1 -1
- package/dist/{strings-BCKpLFNU.js → assertNever-DIU3JJbt.js} +14 -14
- package/dist/{chat-ui-DFxNgzXF.js → chat-ui-BAnLgpTe.js} +1964 -1740
- package/dist/{chunk-IMKFNOWR-B7xytD4B.js → chunk-IMKFNOWR-DOeVvuyE.js} +1 -1
- package/dist/{chunk-SHT3W25Y-I8ZFP5L1.js → chunk-SHT3W25Y-DZoFI8wR.js} +1 -1
- package/dist/{chunk-SVP7TREG-Di-uAPdT.js → chunk-SVP7TREG-CWu86PSW.js} +1 -1
- package/dist/{chunk-TICWLB2K-BFpUy0ud.js → chunk-TICWLB2K-BrM0GoP3.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-Cqm4JGpx.js → classDiagram-ZZMXUADV-DYi4V2bB.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-DFHRJpN3.js → classDiagram-v2-VYDZK3BY-tN7FIk-m.js} +2 -2
- package/dist/{code-visibility-SRM1JiD_.js → code-visibility-DcZ_RwaH.js} +44 -47
- package/dist/{common-yiRhZ6ZZ.js → common-BGeQilvh.js} +5846 -5519
- 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-cuGOeTBC.js → cynefinDiagram-5FMLGOSQ-D5nCnDc-.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-DJ76aC4k.js → dagre-GXQ25YYZ-BHkd7f_i.js} +1 -1
- package/dist/{data-grid-overlay-editor-DLTzcQ4O.js → data-grid-overlay-editor-Dc4lW4A3.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-DLLc0sw7.js → diagram-S7CK7UJ4-D1ALppT2.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-Tz_d6qmk.js → diagram-UQ7AKVKN-DLv0b83L.js} +1 -1
- package/dist/{diagram-VX7I27RA-D7SzPrDN.js → diagram-VX7I27RA-7XJ7J6qg.js} +1 -1
- package/dist/{diagram-Z3DM3KII-qr37XV58.js → diagram-Z3DM3KII-7M7zbHp_.js} +1 -1
- package/dist/{dialog-BtprQCUw.js → dialog-DzCj1qQv.js} +1 -1
- package/dist/{dropdown-menu-CkJ7ErY6.js → dropdown-menu-CdXE15an.js} +1214 -1208
- package/dist/{ebnfDiagram-PWID7BFC-BKOQb4J0.js → ebnfDiagram-PWID7BFC-DHH1qlmV.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-CM15Vq68.js → erDiagram-RLTQ6QDP-fI_0dGef.js} +1 -1
- package/dist/{error-banner-DbRFOd2O.js → error-banner-DPc9eIw5.js} +3 -3
- package/dist/{error-entries-CMoaUX9V.js → error-entries-CxN-Nq3V.js} +524 -456
- package/dist/{feedback-button-DBUrE4OL.js → feedback-button-BqaeQcvX.js} +77 -77
- package/dist/{flowDiagram-HODETNUW-Dt3N5yFT.js → flowDiagram-HODETNUW-Brg9MA6i.js} +2 -2
- package/dist/{formats-gGospKWJ.js → formats-DbSvAPY-.js} +1 -1
- package/dist/{glide-data-editor-Cfv4HeOh.js → glide-data-editor-CiijPXA7.js} +2042 -2041
- package/dist/{glide-utils-Ba9WD2IN.js → glide-utils-BSw3SSHF.js} +29 -35
- package/dist/{globals-dIbBIR5-.js → globals-CpmSWKI_.js} +2 -2
- package/dist/{html-to-image-D_5CMreP.js → html-to-image-8sywF4my.js} +5452 -5751
- package/dist/{infoDiagram-27XIBGKW-C7axJMCl.js → infoDiagram-27XIBGKW-E9e403YT.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-CdC9Eur7.js → ishikawaDiagram-5VMMS53U-C-RlYDRo.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-BHnMIgD7.js → kanban-definition-UXKFOSKX-CLFl_uqK.js} +1 -1
- package/dist/main.js +6294 -6324
- package/dist/{mermaid-DFYN_PXd.js → mermaid-rd09e1JL.js} +35 -35
- package/dist/{mindmap-definition-YA3MSWOX-BagHoCGU.js → mindmap-definition-YA3MSWOX-BQ8TWtyB.js} +1 -1
- package/dist/{number-overlay-editor-CTiJp5Mj.js → number-overlay-editor-Ft4NiAEN.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-8IIZczip.js → pegDiagram-XKGWAZYB-CN8UHFPi.js} +2 -2
- package/dist/pencil-DcT8AE0h.js +10 -0
- package/dist/{pieDiagram-E7YTZNPT-CE6dKBIr.js → pieDiagram-E7YTZNPT-DGuJ0EBd.js} +1 -1
- package/dist/{process-output-CGFNVC60.js → process-output-Dku5POvm.js} +3 -3
- package/dist/{railroadDiagram-O6MQD6OU-CkexPq3b.js → railroadDiagram-O6MQD6OU-BPDA8wy8.js} +2 -2
- package/dist/{requirementDiagram-BXWQKSXE-B0-OkuAe.js → requirementDiagram-BXWQKSXE-ChzLGbGW.js} +1 -1
- package/dist/{reveal-component-DH09ygHo.js → reveal-component-D0cfwbbl.js} +1094 -1094
- package/dist/{select-C33FVPPN.js → select-OxgozOC8.js} +1 -1
- package/dist/{sequenceDiagram-WJ2MYXX4-Dxysg8DX.js → sequenceDiagram-WJ2MYXX4-DFX-bE6O.js} +1 -1
- package/dist/{spec-DH1lmF7Q.js → spec-oJn0RhpQ.js} +2 -2
- package/dist/{stateDiagram-D77RDMKH-DTEN3-OJ.js → stateDiagram-D77RDMKH-BR7cI3wK.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-vktk3Xc5.js → stateDiagram-v2-MP3YSRHH-oGqB5UDI.js} +2 -2
- package/dist/{static-state-BldGd99T.js → static-state-CuV6Pc3a.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-Cjveh9OM.js → swimlanes-42K2YHIH-DwSZl1yC.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-Bdr7Ev_2.js → swimlanesDiagram-VR7AAH4N-BHlcd-Ri.js} +2 -2
- package/dist/{timeline-definition-24CTP7MA-KIuDcefn.js → timeline-definition-24CTP7MA-DMmP-G2O.js} +1 -1
- package/dist/{toast-CY1_Qv41.js → toast-DbBHmxmB.js} +2 -2
- 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-C-lqjV0q.js → vega-component-rxIxAAh9.js} +7 -7
- package/dist/{vennDiagram-4TSXK5OY-DrIOUHfb.js → vennDiagram-4TSXK5OY-Db8GtH1G.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-CJNjf4OH.js → wardleyDiagram-VM6X3IG4-DmIiC3FU.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-DEshFho-.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/chat/__tests__/chat-display.test.tsx +157 -86
- package/src/components/chat/__tests__/chat-utils.test.ts +42 -0
- package/src/components/chat/__tests__/turn-timing.test.ts +84 -0
- package/src/components/chat/__tests__/use-assistant-turn.test.ts +95 -0
- package/src/components/chat/__tests__/user-message.test.tsx +27 -0
- package/src/components/chat/acp/agent-panel.tsx +2 -0
- package/src/components/chat/agent-activity.tsx +132 -0
- package/src/components/chat/chat-display.tsx +125 -96
- package/src/components/chat/chat-panel.tsx +123 -106
- package/src/components/chat/chat-utils.ts +12 -24
- package/src/components/chat/tool-call/__tests__/tool-labels.test.ts +76 -0
- package/src/components/chat/tool-call/__tests__/tool-step.test.tsx +57 -0
- package/src/components/chat/tool-call/shared.ts +6 -0
- package/src/components/chat/tool-call/tool-call-view.tsx +22 -76
- package/src/components/chat/tool-call/tool-labels.ts +172 -0
- package/src/components/chat/tool-call/tool-step.tsx +145 -0
- package/src/components/chat/turn-timing.ts +73 -0
- package/src/components/chat/use-assistant-turn.ts +65 -0
- package/src/components/chat/use-chat-generation.ts +5 -4
- package/src/components/chat/user-message.tsx +145 -0
- 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 +19 -1
- package/src/components/editor/actions/useCellActionButton.tsx +10 -3
- package/src/components/editor/ai/completion-handlers.tsx +0 -37
- 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/StagedAICell.tsx +51 -144
- 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/__tests__/pending-ai-cells.test.tsx +193 -32
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +2 -2
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +145 -81
- package/src/components/editor/chrome/wrapper/pending-ai-changes-badge.tsx +25 -0
- package/src/components/editor/chrome/wrapper/sidebar.tsx +8 -4
- package/src/components/editor/header/status.tsx +4 -2
- package/src/components/editor/links/cell-link.tsx +4 -4
- package/src/components/editor/navigation/navigation.ts +3 -2
- package/src/components/editor/notebook-cell.tsx +85 -94
- 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/components/ui/toast.tsx +1 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +74 -126
- package/src/core/ai/staged-cells.ts +48 -38
- 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/scrollCellIntoView.ts +6 -0
- package/src/core/cells/types.ts +13 -36
- package/src/core/cells/utils.ts +37 -68
- package/src/core/codemirror/placeholder/__tests__/extensions.test.ts +59 -0
- package/src/core/codemirror/placeholder/extensions.ts +23 -0
- 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/__tests__/useNotebookSession.hook.test.tsx +34 -0
- package/src/core/session/useNotebookSession.tsx +10 -5
- package/src/core/wasm/bridge.ts +1 -1
- package/src/css/app/Cell.css +7 -36
- package/src/plugins/core/registerReactComponent.tsx +4 -13
- package/src/plugins/impl/chat/chat-ui.tsx +2 -3
- package/src/plugins/impl/common/error-banner.tsx +5 -3
- 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/components/chat/reasoning-accordion.tsx +0 -61
- package/src/components/chat/tool-call/tool-activity-group.tsx +0 -49
- package/src/components/chat/tool-call/tool-error-card.tsx +0 -81
- package/src/components/chat/tool-call/tool-history-row.tsx +0 -147
- package/src/components/icons/loading-ellipsis.tsx +0 -46
|
@@ -5,7 +5,7 @@ import { HourglassIcon, UnlinkIcon } from "lucide-react";
|
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
7
7
|
import { notebookScrollToRunning } from "@/core/cells/actions";
|
|
8
|
-
import {
|
|
8
|
+
import { cellExecutionInputsAtom, onlyScratchRunning } from "@/core/executions";
|
|
9
9
|
import { viewStateAtom } from "@/core/mode";
|
|
10
10
|
import {
|
|
11
11
|
type ConnectionStatus,
|
|
@@ -77,7 +77,9 @@ const DisconnectedIcon: React.FC<{ onReconnect?: () => void }> = ({
|
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
const RunningIcon = () => {
|
|
80
|
-
const scratchpadOnly =
|
|
80
|
+
const scratchpadOnly = onlyScratchRunning(
|
|
81
|
+
useAtomValue(cellExecutionInputsAtom).executions,
|
|
82
|
+
);
|
|
81
83
|
const tooltip = scratchpadOnly
|
|
82
84
|
? "Scratchpad is running"
|
|
83
85
|
: "Jump to running cell";
|
|
@@ -5,6 +5,7 @@ import { useCellIds, useCellNames } from "@/core/cells/cells";
|
|
|
5
5
|
import { useCellActions } from "@/core/cells/actions";
|
|
6
6
|
import { type CellId, HTMLCellId, SCRATCH_CELL_ID } from "@/core/cells/ids";
|
|
7
7
|
import { displayCellName } from "@/core/cells/names";
|
|
8
|
+
import { scrollToCell } from "@/core/cells/scrollCellIntoView";
|
|
8
9
|
import { goToCellLine } from "@/core/codemirror/go-to-definition/utils";
|
|
9
10
|
import { useFilename } from "@/core/saving/filename";
|
|
10
11
|
import { cn } from "@/utils/cn";
|
|
@@ -106,16 +107,15 @@ export function scrollAndHighlightCell(
|
|
|
106
107
|
skipScroll?: boolean,
|
|
107
108
|
): boolean {
|
|
108
109
|
const cellHtmlId = HTMLCellId.create(cellId);
|
|
109
|
-
const cell
|
|
110
|
+
const cell = skipScroll
|
|
111
|
+
? document.getElementById(cellHtmlId)
|
|
112
|
+
: scrollToCell(cellId);
|
|
110
113
|
const isCellErrored = cell?.classList.contains("has-error");
|
|
111
114
|
|
|
112
115
|
if (cell === null) {
|
|
113
116
|
Logger.error(`Cell ${cellHtmlId} not found on page.`);
|
|
114
117
|
return false;
|
|
115
118
|
}
|
|
116
|
-
if (!skipScroll) {
|
|
117
|
-
cell.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
118
|
-
}
|
|
119
119
|
|
|
120
120
|
if (variant === "destructive" || (isCellErrored && variant === undefined)) {
|
|
121
121
|
cell.classList.add("error-outline");
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
visibleNeighbor,
|
|
23
23
|
} from "@/core/cells/layout";
|
|
24
24
|
import { useCellActions } from "@/core/cells/actions";
|
|
25
|
+
import { cellExecutionInputsAtom, cellExecutionView } from "@/core/executions";
|
|
25
26
|
import { useNotebookDocumentEdit } from "@/core/notebook/document";
|
|
26
27
|
import { useCellFocusActions } from "@/core/cells/focus";
|
|
27
28
|
import type { CellId } from "@/core/cells/ids";
|
|
@@ -582,9 +583,9 @@ export function useCellNavigationProps(
|
|
|
582
583
|
selectedCells.size >= 2 ? [...selectedCells] : [cellId];
|
|
583
584
|
|
|
584
585
|
// Cannot delete running cells
|
|
585
|
-
const
|
|
586
|
+
const executions = store.get(cellExecutionInputsAtom);
|
|
586
587
|
const hasRunningCell = cellIds.some((id) => {
|
|
587
|
-
const { status } =
|
|
588
|
+
const { status } = cellExecutionView(executions, id);
|
|
588
589
|
return status === "running" || status === "queued";
|
|
589
590
|
});
|
|
590
591
|
|
|
@@ -37,10 +37,14 @@ import { isErrorMime } from "@/core/mime";
|
|
|
37
37
|
import type { AppMode } from "@/core/mode";
|
|
38
38
|
import { connectionAtom } from "@/core/network/connection";
|
|
39
39
|
import { useRequestClient } from "@/core/network/requests";
|
|
40
|
-
import
|
|
40
|
+
import {
|
|
41
|
+
type CellExecutionView,
|
|
42
|
+
type CellRunStatus,
|
|
43
|
+
useCellExecution,
|
|
44
|
+
} from "@/core/executions";
|
|
45
|
+
import type { CellConfig } from "@/core/network/types";
|
|
41
46
|
import { useResizeObserver } from "@/hooks/useResizeObserver";
|
|
42
47
|
import { cn } from "@/utils/cn";
|
|
43
|
-
import type { Milliseconds, Seconds } from "@/utils/time";
|
|
44
48
|
import {
|
|
45
49
|
useCellData,
|
|
46
50
|
useCellHandle,
|
|
@@ -78,10 +82,7 @@ import { CollapsedCellBanner, CollapseToggle } from "./cell/collapse";
|
|
|
78
82
|
import { DeleteButton } from "./cell/DeleteButton";
|
|
79
83
|
import { PendingDeleteConfirmation } from "./cell/PendingDeleteConfirmation";
|
|
80
84
|
import { RunButton } from "./cell/RunButton";
|
|
81
|
-
import {
|
|
82
|
-
StagedAICellBackground,
|
|
83
|
-
StagedAICellFooter,
|
|
84
|
-
} from "./cell/StagedAICell";
|
|
85
|
+
import { StagedAIDeletionMarker } from "./cell/StagedAICell";
|
|
85
86
|
import { useDeleteCellCallback } from "./cell/useDeleteCell";
|
|
86
87
|
import { useRunCell } from "./cell/useRunCells";
|
|
87
88
|
import { cellDomProps } from "./common";
|
|
@@ -318,6 +319,10 @@ const ReadonlyCellComponent = forwardRef(
|
|
|
318
319
|
const { cellId } = props;
|
|
319
320
|
const cellData = useCellData(cellId);
|
|
320
321
|
const cellRuntime = useCellRuntime(cellId);
|
|
322
|
+
const execution = useCellExecution(cellId);
|
|
323
|
+
const errored = execution.outcome === "error";
|
|
324
|
+
const interrupted = execution.outcome === "interrupted";
|
|
325
|
+
const stopped = execution.outcome === "skipped";
|
|
321
326
|
|
|
322
327
|
const className = clsx("marimo-cell", "hover-actions-parent z-10", {
|
|
323
328
|
published: true,
|
|
@@ -325,9 +330,9 @@ const ReadonlyCellComponent = forwardRef(
|
|
|
325
330
|
|
|
326
331
|
// Hide the output if it's an error or stopped.
|
|
327
332
|
const hidden = shouldHidePublishedCell({
|
|
328
|
-
errored
|
|
329
|
-
interrupted
|
|
330
|
-
stopped
|
|
333
|
+
errored,
|
|
334
|
+
interrupted,
|
|
335
|
+
stopped,
|
|
331
336
|
output: cellRuntime.output,
|
|
332
337
|
showErrorTracebacks: false,
|
|
333
338
|
});
|
|
@@ -349,8 +354,12 @@ const ReadonlyCellComponent = forwardRef(
|
|
|
349
354
|
className={CSSClasses.outputArea}
|
|
350
355
|
cellId={cellId}
|
|
351
356
|
output={cellRuntime.output}
|
|
352
|
-
stale={outputIsStale(
|
|
353
|
-
|
|
357
|
+
stale={outputIsStale(
|
|
358
|
+
execution,
|
|
359
|
+
cellRuntime.staleInputs,
|
|
360
|
+
cellData.edited,
|
|
361
|
+
)}
|
|
362
|
+
loading={outputIsLoading(execution.status)}
|
|
354
363
|
/>
|
|
355
364
|
</div>
|
|
356
365
|
);
|
|
@@ -377,6 +386,10 @@ const EditableCellComponent = ({
|
|
|
377
386
|
const cellRef = useRef<HTMLDivElement>(null);
|
|
378
387
|
const cellData = useCellData(cellId);
|
|
379
388
|
const cellRuntime = useCellRuntime(cellId);
|
|
389
|
+
const execution = useCellExecution(cellId);
|
|
390
|
+
const errored = execution.outcome === "error";
|
|
391
|
+
const interrupted = execution.outcome === "interrupted";
|
|
392
|
+
const stopped = execution.outcome === "skipped";
|
|
380
393
|
const cellActionDropdownRef = useRef<CellActionsDropdownHandle>(null);
|
|
381
394
|
// DOM node where the editorView will be mounted
|
|
382
395
|
const editorViewParentRef = useRef<HTMLDivElement>(null);
|
|
@@ -392,23 +405,17 @@ const EditableCellComponent = ({
|
|
|
392
405
|
|
|
393
406
|
const [languageAdapter, setLanguageAdapter] = useState<LanguageAdapterType>();
|
|
394
407
|
|
|
395
|
-
const uninstantiated = isUninstantiated(
|
|
396
|
-
executionTime: cellRuntime.runElapsedTimeMs ?? cellData.lastExecutionTime,
|
|
397
|
-
status: cellRuntime.status,
|
|
398
|
-
errored: cellRuntime.errored,
|
|
399
|
-
interrupted: cellRuntime.interrupted,
|
|
400
|
-
stopped: cellRuntime.stopped,
|
|
401
|
-
});
|
|
408
|
+
const uninstantiated = isUninstantiated(execution);
|
|
402
409
|
|
|
403
410
|
const needsRun = cellNeedsRun({
|
|
404
411
|
edited: cellData.edited,
|
|
405
|
-
interrupted
|
|
412
|
+
interrupted,
|
|
406
413
|
staleInputs: cellRuntime.staleInputs,
|
|
407
414
|
disabled: cellData.config.disabled,
|
|
408
|
-
|
|
415
|
+
blocked: execution.blocked,
|
|
409
416
|
});
|
|
410
417
|
|
|
411
|
-
const loading = outputIsLoading(
|
|
418
|
+
const loading = outputIsLoading(execution.status);
|
|
412
419
|
|
|
413
420
|
const isPresenting = mode === "present";
|
|
414
421
|
|
|
@@ -417,9 +424,9 @@ const EditableCellComponent = ({
|
|
|
417
424
|
const presentHidden =
|
|
418
425
|
isPresenting &&
|
|
419
426
|
shouldHidePublishedCell({
|
|
420
|
-
errored
|
|
421
|
-
interrupted
|
|
422
|
-
stopped
|
|
427
|
+
errored,
|
|
428
|
+
interrupted,
|
|
429
|
+
stopped,
|
|
423
430
|
output: cellRuntime.output,
|
|
424
431
|
showErrorTracebacks: userConfig.runtime.show_tracebacks ?? false,
|
|
425
432
|
});
|
|
@@ -435,10 +442,10 @@ const EditableCellComponent = ({
|
|
|
435
442
|
// console output is cleared immediately on run, so check for queued instead
|
|
436
443
|
// of loading to determine staleness
|
|
437
444
|
const consoleOutputStale =
|
|
438
|
-
(
|
|
445
|
+
(execution.status === "queued" ||
|
|
439
446
|
cellData.edited ||
|
|
440
447
|
cellRuntime.staleInputs) &&
|
|
441
|
-
!
|
|
448
|
+
!interrupted;
|
|
442
449
|
|
|
443
450
|
// This getter is called during render, so useEvent cannot be used here.
|
|
444
451
|
// oxlint-disable-next-line react/preserve-manual-memoization
|
|
@@ -475,7 +482,8 @@ const EditableCellComponent = ({
|
|
|
475
482
|
// While presenting, pending edits do not dim the output as stale,
|
|
476
483
|
// matching the read view.
|
|
477
484
|
const isStaleCell = outputIsStale(
|
|
478
|
-
|
|
485
|
+
execution,
|
|
486
|
+
cellRuntime.staleInputs,
|
|
479
487
|
cellData.edited && !isPresenting,
|
|
480
488
|
);
|
|
481
489
|
const hasConsoleOutput = cellRuntime.consoleOutputs.length > 0;
|
|
@@ -571,7 +579,7 @@ const EditableCellComponent = ({
|
|
|
571
579
|
cellId={cellId}
|
|
572
580
|
output={cellRuntime.output}
|
|
573
581
|
stale={isStaleCell}
|
|
574
|
-
loading={outputIsLoading(
|
|
582
|
+
loading={outputIsLoading(execution.status)}
|
|
575
583
|
/>
|
|
576
584
|
</div>
|
|
577
585
|
);
|
|
@@ -582,18 +590,18 @@ const EditableCellComponent = ({
|
|
|
582
590
|
isPresenting
|
|
583
591
|
? // Match the published styling of the read view
|
|
584
592
|
publishedCellClasses({
|
|
585
|
-
errored
|
|
586
|
-
stopped
|
|
593
|
+
errored,
|
|
594
|
+
stopped,
|
|
587
595
|
})
|
|
588
596
|
: {
|
|
589
597
|
"z-10": true,
|
|
590
598
|
interactive: true,
|
|
591
599
|
...cellStatusClasses({
|
|
592
600
|
needsRun,
|
|
593
|
-
errored
|
|
594
|
-
stopped
|
|
601
|
+
errored,
|
|
602
|
+
stopped,
|
|
595
603
|
disabled: cellData.config.disabled,
|
|
596
|
-
|
|
604
|
+
blocked: execution.blocked,
|
|
597
605
|
}),
|
|
598
606
|
borderless:
|
|
599
607
|
isMarkdownCodeHidden &&
|
|
@@ -620,7 +628,7 @@ const EditableCellComponent = ({
|
|
|
620
628
|
if (cellData.config.disabled) {
|
|
621
629
|
return "This cell is disabled";
|
|
622
630
|
}
|
|
623
|
-
if (
|
|
631
|
+
if (execution.blocked) {
|
|
624
632
|
return "This cell has a disabled ancestor";
|
|
625
633
|
}
|
|
626
634
|
return undefined;
|
|
@@ -638,7 +646,7 @@ const EditableCellComponent = ({
|
|
|
638
646
|
<SortableCell
|
|
639
647
|
tabIndex={-1}
|
|
640
648
|
ref={cellRef}
|
|
641
|
-
data-status={
|
|
649
|
+
data-status={execution.status}
|
|
642
650
|
onBlur={closeCompletionHandler}
|
|
643
651
|
onKeyDown={resumeCompletionHandler}
|
|
644
652
|
cellId={cellId}
|
|
@@ -674,11 +682,12 @@ const EditableCellComponent = ({
|
|
|
674
682
|
data-has-output-above={hasOutputAbove}
|
|
675
683
|
data-hidden={isMarkdownCodeHidden}
|
|
676
684
|
>
|
|
677
|
-
<
|
|
685
|
+
<StagedAIDeletionMarker cellId={cellId} />
|
|
678
686
|
<div className="absolute right-2 -top-4 z-10">
|
|
679
687
|
<CellToolbar
|
|
680
688
|
edited={cellData.edited}
|
|
681
|
-
status={
|
|
689
|
+
status={execution.status}
|
|
690
|
+
blocked={execution.blocked}
|
|
682
691
|
cellConfig={cellData.config}
|
|
683
692
|
needsRun={needsRun}
|
|
684
693
|
hasOutput={hasOutput}
|
|
@@ -696,7 +705,7 @@ const EditableCellComponent = ({
|
|
|
696
705
|
id={cellId}
|
|
697
706
|
code={cellData.code}
|
|
698
707
|
config={cellData.config}
|
|
699
|
-
status={
|
|
708
|
+
status={execution.status}
|
|
700
709
|
runCell={runCell}
|
|
701
710
|
setEditorView={setEditorView}
|
|
702
711
|
userConfig={userConfig}
|
|
@@ -717,21 +726,17 @@ const EditableCellComponent = ({
|
|
|
717
726
|
isMarkdownCodeHidden && cellOutput === "below" && "top-14",
|
|
718
727
|
)}
|
|
719
728
|
edited={cellData.edited}
|
|
720
|
-
|
|
729
|
+
execution={execution}
|
|
721
730
|
isCellStatusInline={isCellStatusInline}
|
|
722
731
|
uninstantiated={uninstantiated}
|
|
723
732
|
disabled={cellData.config.disabled}
|
|
724
|
-
runElapsedTimeMs={cellRuntime.runElapsedTimeMs}
|
|
725
|
-
runStartTimestamp={cellRuntime.runStartTimestamp}
|
|
726
|
-
lastRunStartTimestamp={cellRuntime.lastRunStartTimestamp}
|
|
727
733
|
staleInputs={cellRuntime.staleInputs}
|
|
728
|
-
interrupted={cellRuntime.interrupted}
|
|
729
734
|
/>
|
|
730
735
|
)}
|
|
731
736
|
<div className="shoulder-bottom hover-action">
|
|
732
737
|
{canDelete && isCellCodeShown && (
|
|
733
738
|
<DeleteButton
|
|
734
|
-
status={
|
|
739
|
+
status={execution.status}
|
|
735
740
|
connectionState={connection.state}
|
|
736
741
|
onClick={() => {
|
|
737
742
|
if (
|
|
@@ -748,7 +753,7 @@ const EditableCellComponent = ({
|
|
|
748
753
|
{!isPresenting && (
|
|
749
754
|
<SqlValidationErrorBanner
|
|
750
755
|
cellId={cellId}
|
|
751
|
-
hide={
|
|
756
|
+
hide={errored && !isStaleCell}
|
|
752
757
|
/>
|
|
753
758
|
)}
|
|
754
759
|
{cellOutput === "below" && (outputArea || emptyMarkdownPlaceholder)}
|
|
@@ -814,7 +819,7 @@ const EditableCellComponent = ({
|
|
|
814
819
|
<ConsoleOutput
|
|
815
820
|
consoleOutputs={cellRuntime.consoleOutputs}
|
|
816
821
|
stale={consoleOutputStale}
|
|
817
|
-
interrupted={
|
|
822
|
+
interrupted={interrupted}
|
|
818
823
|
// Empty name if serialization triggered
|
|
819
824
|
cellName={cellRuntime.serialization ? "_" : cellData.name}
|
|
820
825
|
onRefactorWithAI={handleRefactorWithAI}
|
|
@@ -837,7 +842,6 @@ const EditableCellComponent = ({
|
|
|
837
842
|
/>
|
|
838
843
|
)}
|
|
839
844
|
<PendingDeleteConfirmation cellId={cellId} />
|
|
840
|
-
{!isPresenting && <StagedAICellFooter cellId={cellId} />}
|
|
841
845
|
</div>
|
|
842
846
|
{isCollapsed && !isPresenting && (
|
|
843
847
|
<CollapsedCellBanner
|
|
@@ -857,41 +861,33 @@ const CellRightSideActions = memo(
|
|
|
857
861
|
className?: string;
|
|
858
862
|
disabled: boolean | undefined;
|
|
859
863
|
edited: boolean;
|
|
860
|
-
|
|
864
|
+
execution: CellExecutionView;
|
|
861
865
|
isCellStatusInline: boolean;
|
|
862
|
-
lastRunStartTimestamp: Seconds | null;
|
|
863
|
-
runElapsedTimeMs: Milliseconds | null;
|
|
864
|
-
runStartTimestamp: Seconds | null;
|
|
865
866
|
staleInputs: boolean;
|
|
866
|
-
status: RuntimeState;
|
|
867
867
|
uninstantiated: boolean;
|
|
868
868
|
}) => {
|
|
869
869
|
const {
|
|
870
870
|
className,
|
|
871
871
|
disabled = false,
|
|
872
872
|
edited,
|
|
873
|
-
|
|
873
|
+
execution,
|
|
874
874
|
isCellStatusInline,
|
|
875
|
-
lastRunStartTimestamp,
|
|
876
|
-
runElapsedTimeMs,
|
|
877
|
-
runStartTimestamp,
|
|
878
875
|
staleInputs,
|
|
879
|
-
status,
|
|
880
876
|
uninstantiated,
|
|
881
877
|
} = props;
|
|
882
878
|
|
|
883
879
|
const cellStatusComponent = (
|
|
884
880
|
<CellStatusComponent
|
|
885
|
-
status={status}
|
|
881
|
+
status={execution.status}
|
|
886
882
|
staleInputs={staleInputs}
|
|
887
|
-
interrupted={interrupted}
|
|
883
|
+
interrupted={execution.outcome === "interrupted"}
|
|
888
884
|
editing={true}
|
|
889
885
|
edited={edited}
|
|
890
886
|
disabled={disabled}
|
|
891
|
-
elapsedTime={
|
|
892
|
-
|
|
887
|
+
elapsedTime={execution.duration}
|
|
888
|
+
startedAt={execution.startedAt}
|
|
889
|
+
blocked={execution.blocked}
|
|
893
890
|
uninstantiated={uninstantiated}
|
|
894
|
-
lastRunStartTimestamp={lastRunStartTimestamp}
|
|
895
891
|
/>
|
|
896
892
|
);
|
|
897
893
|
|
|
@@ -964,7 +960,8 @@ CellLeftSideActions.displayName = "CellLeftSideActions";
|
|
|
964
960
|
|
|
965
961
|
interface CellToolbarProps {
|
|
966
962
|
edited: boolean;
|
|
967
|
-
status:
|
|
963
|
+
status: CellRunStatus;
|
|
964
|
+
blocked: boolean;
|
|
968
965
|
cellConfig: CellConfig;
|
|
969
966
|
needsRun: boolean;
|
|
970
967
|
hasOutput: boolean;
|
|
@@ -981,6 +978,7 @@ const CellToolbar = memo(
|
|
|
981
978
|
({
|
|
982
979
|
edited,
|
|
983
980
|
status,
|
|
981
|
+
blocked,
|
|
984
982
|
cellConfig,
|
|
985
983
|
needsRun,
|
|
986
984
|
hasOutput,
|
|
@@ -1006,6 +1004,7 @@ const CellToolbar = memo(
|
|
|
1006
1004
|
onClick={onRun}
|
|
1007
1005
|
connectionState={connection.state}
|
|
1008
1006
|
status={status}
|
|
1007
|
+
blocked={blocked}
|
|
1009
1008
|
config={cellConfig}
|
|
1010
1009
|
needsRun={needsRun}
|
|
1011
1010
|
/>
|
|
@@ -1015,6 +1014,7 @@ const CellToolbar = memo(
|
|
|
1015
1014
|
ref={cellActionDropdownRef}
|
|
1016
1015
|
cellId={cellId}
|
|
1017
1016
|
status={status}
|
|
1017
|
+
blocked={blocked}
|
|
1018
1018
|
getEditorView={getEditorView}
|
|
1019
1019
|
name={name}
|
|
1020
1020
|
config={cellConfig}
|
|
@@ -1058,6 +1058,10 @@ const SetupCellComponent = ({
|
|
|
1058
1058
|
const cellRef = useRef<HTMLDivElement>(null);
|
|
1059
1059
|
const cellData = useCellData(cellId);
|
|
1060
1060
|
const cellRuntime = useCellRuntime(cellId);
|
|
1061
|
+
const execution = useCellExecution(cellId);
|
|
1062
|
+
const errored = execution.outcome === "error";
|
|
1063
|
+
const interrupted = execution.outcome === "interrupted";
|
|
1064
|
+
const stopped = execution.outcome === "skipped";
|
|
1061
1065
|
const cellActionDropdownRef = useRef<CellActionsDropdownHandle>(null);
|
|
1062
1066
|
// DOM node where the editorView will be mounted
|
|
1063
1067
|
const editorViewParentRef = useRef<HTMLDivElement>(null);
|
|
@@ -1069,31 +1073,25 @@ const SetupCellComponent = ({
|
|
|
1069
1073
|
const setAiCompletionCell = useSetAtom(aiCompletionCellAtom);
|
|
1070
1074
|
const runCell = useRunCell(cellId);
|
|
1071
1075
|
|
|
1072
|
-
const uninstantiated = isUninstantiated(
|
|
1073
|
-
executionTime: cellRuntime.runElapsedTimeMs ?? cellData.lastExecutionTime,
|
|
1074
|
-
status: cellRuntime.status,
|
|
1075
|
-
errored: cellRuntime.errored,
|
|
1076
|
-
interrupted: cellRuntime.interrupted,
|
|
1077
|
-
stopped: cellRuntime.stopped,
|
|
1078
|
-
});
|
|
1076
|
+
const uninstantiated = isUninstantiated(execution);
|
|
1079
1077
|
|
|
1080
1078
|
const needsRun = cellNeedsRun({
|
|
1081
1079
|
edited: cellData.edited,
|
|
1082
|
-
interrupted
|
|
1080
|
+
interrupted,
|
|
1083
1081
|
staleInputs: cellRuntime.staleInputs,
|
|
1084
1082
|
disabled: cellData.config.disabled,
|
|
1085
|
-
|
|
1083
|
+
blocked: execution.blocked,
|
|
1086
1084
|
});
|
|
1087
1085
|
const loading =
|
|
1088
|
-
|
|
1086
|
+
execution.status === "running" || execution.status === "queued";
|
|
1089
1087
|
|
|
1090
1088
|
// console output is cleared immediately on run, so check for queued instead
|
|
1091
1089
|
// of loading to determine staleness
|
|
1092
1090
|
const consoleOutputStale =
|
|
1093
|
-
(
|
|
1091
|
+
(execution.status === "queued" ||
|
|
1094
1092
|
cellData.edited ||
|
|
1095
1093
|
cellRuntime.staleInputs) &&
|
|
1096
|
-
!
|
|
1094
|
+
!interrupted;
|
|
1097
1095
|
|
|
1098
1096
|
// This getter is called during render, so useEvent cannot be used here.
|
|
1099
1097
|
// oxlint-disable-next-line react/preserve-manual-memoization
|
|
@@ -1127,10 +1125,10 @@ const SetupCellComponent = ({
|
|
|
1127
1125
|
interactive: true,
|
|
1128
1126
|
...cellStatusClasses({
|
|
1129
1127
|
needsRun,
|
|
1130
|
-
errored
|
|
1131
|
-
stopped
|
|
1128
|
+
errored,
|
|
1129
|
+
stopped,
|
|
1132
1130
|
disabled: cellData.config.disabled,
|
|
1133
|
-
|
|
1131
|
+
blocked: execution.blocked,
|
|
1134
1132
|
}),
|
|
1135
1133
|
});
|
|
1136
1134
|
|
|
@@ -1151,7 +1149,7 @@ const SetupCellComponent = ({
|
|
|
1151
1149
|
if (cellData.config.disabled) {
|
|
1152
1150
|
return "This cell is disabled";
|
|
1153
1151
|
}
|
|
1154
|
-
if (
|
|
1152
|
+
if (execution.blocked) {
|
|
1155
1153
|
return "This cell has a disabled ancestor";
|
|
1156
1154
|
}
|
|
1157
1155
|
return undefined;
|
|
@@ -1178,7 +1176,7 @@ const SetupCellComponent = ({
|
|
|
1178
1176
|
mounted) while presenting. */}
|
|
1179
1177
|
<div hidden={isPresenting}>
|
|
1180
1178
|
<div
|
|
1181
|
-
data-status={
|
|
1179
|
+
data-status={execution.status}
|
|
1182
1180
|
ref={cellRef}
|
|
1183
1181
|
{...mergeProps(navigationProps, {
|
|
1184
1182
|
className: cn(
|
|
@@ -1198,14 +1196,12 @@ const SetupCellComponent = ({
|
|
|
1198
1196
|
data-has-output-above={false}
|
|
1199
1197
|
data-hidden={!isCellCodeShown}
|
|
1200
1198
|
>
|
|
1201
|
-
<
|
|
1202
|
-
cellId={cellId}
|
|
1203
|
-
className="mo-ai-setup-cell"
|
|
1204
|
-
/>
|
|
1199
|
+
<StagedAIDeletionMarker cellId={cellId} />
|
|
1205
1200
|
<div className="absolute right-2 -top-4 z-10">
|
|
1206
1201
|
<CellToolbar
|
|
1207
1202
|
edited={cellData.edited}
|
|
1208
|
-
status={
|
|
1203
|
+
status={execution.status}
|
|
1204
|
+
blocked={execution.blocked}
|
|
1209
1205
|
cellConfig={cellData.config}
|
|
1210
1206
|
needsRun={needsRun}
|
|
1211
1207
|
hasOutput={hasOutput}
|
|
@@ -1224,7 +1220,7 @@ const SetupCellComponent = ({
|
|
|
1224
1220
|
id={cellId}
|
|
1225
1221
|
code={cellData.code}
|
|
1226
1222
|
config={cellData.config}
|
|
1227
|
-
status={
|
|
1223
|
+
status={execution.status}
|
|
1228
1224
|
runCell={runCell}
|
|
1229
1225
|
setEditorView={setEditorView}
|
|
1230
1226
|
userConfig={userConfig}
|
|
@@ -1242,22 +1238,18 @@ const SetupCellComponent = ({
|
|
|
1242
1238
|
{!isPresenting && (
|
|
1243
1239
|
<CellRightSideActions
|
|
1244
1240
|
edited={cellData.edited}
|
|
1245
|
-
|
|
1241
|
+
execution={execution}
|
|
1246
1242
|
isCellStatusInline={false}
|
|
1247
1243
|
uninstantiated={uninstantiated}
|
|
1248
1244
|
disabled={cellData.config.disabled}
|
|
1249
|
-
runElapsedTimeMs={cellRuntime.runElapsedTimeMs}
|
|
1250
|
-
runStartTimestamp={cellRuntime.runStartTimestamp}
|
|
1251
|
-
lastRunStartTimestamp={cellRuntime.lastRunStartTimestamp}
|
|
1252
1245
|
staleInputs={cellRuntime.staleInputs}
|
|
1253
|
-
interrupted={cellRuntime.interrupted}
|
|
1254
1246
|
/>
|
|
1255
1247
|
)}
|
|
1256
1248
|
<div className="shoulder-bottom hover-action">
|
|
1257
1249
|
{canDelete && (
|
|
1258
1250
|
<DeleteButton
|
|
1259
1251
|
connectionState={connection.state}
|
|
1260
|
-
status={
|
|
1252
|
+
status={execution.status}
|
|
1261
1253
|
onClick={() => {
|
|
1262
1254
|
if (
|
|
1263
1255
|
!loading &&
|
|
@@ -1305,7 +1297,7 @@ const SetupCellComponent = ({
|
|
|
1305
1297
|
<ConsoleOutput
|
|
1306
1298
|
consoleOutputs={cellRuntime.consoleOutputs}
|
|
1307
1299
|
stale={consoleOutputStale}
|
|
1308
|
-
interrupted={
|
|
1300
|
+
interrupted={interrupted}
|
|
1309
1301
|
// Don't show name
|
|
1310
1302
|
cellName={"_"}
|
|
1311
1303
|
onRefactorWithAI={handleRefactorWithAI}
|
|
@@ -1326,7 +1318,6 @@ const SetupCellComponent = ({
|
|
|
1326
1318
|
cellId={cellId}
|
|
1327
1319
|
debuggerActive={cellRuntime.debuggerActive}
|
|
1328
1320
|
/>
|
|
1329
|
-
<StagedAICellFooter cellId={cellId} />
|
|
1330
1321
|
</div>
|
|
1331
1322
|
</div>
|
|
1332
1323
|
</CellActionsContextMenu>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import { createStore, Provider } from "jotai";
|
|
5
|
+
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { MockExecutions } from "@/__mocks__/executions";
|
|
7
|
+
import { MockNotebook } from "@/__mocks__/notebook";
|
|
8
|
+
import { cellId } from "@/__tests__/branded";
|
|
9
|
+
import { parseAppConfig } from "@/core/config/config-schema";
|
|
10
|
+
import { GridLayoutRenderer } from "../grid-layout";
|
|
11
|
+
import type { GridLayout } from "../types";
|
|
12
|
+
|
|
13
|
+
vi.mock("@/components/editor/Output", () => ({
|
|
14
|
+
OutputArea: ({ cellId }: { cellId: string }) => (
|
|
15
|
+
<div data-testid={`output-${cellId}`} />
|
|
16
|
+
),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const ERRORED = cellId("errored");
|
|
20
|
+
|
|
21
|
+
function renderErroredCell(cells: GridLayout["cells"]) {
|
|
22
|
+
const store = createStore();
|
|
23
|
+
MockExecutions.seed(store, [MockExecutions.errored(ERRORED)]);
|
|
24
|
+
const notebook = MockNotebook.notebookState({
|
|
25
|
+
cellData: { [ERRORED]: { code: "raise ValueError('boom')" } },
|
|
26
|
+
cellRuntime: {
|
|
27
|
+
[ERRORED]: {
|
|
28
|
+
output: {
|
|
29
|
+
channel: "marimo-error",
|
|
30
|
+
mimetype: "application/vnd.marimo+error",
|
|
31
|
+
data: [MockNotebook.errors.exception("boom")],
|
|
32
|
+
timestamp: 1,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
render(
|
|
38
|
+
<Provider store={store}>
|
|
39
|
+
<GridLayoutRenderer
|
|
40
|
+
appConfig={parseAppConfig({})}
|
|
41
|
+
mode="edit"
|
|
42
|
+
layout={{
|
|
43
|
+
columns: 12,
|
|
44
|
+
rowHeight: 20,
|
|
45
|
+
cells,
|
|
46
|
+
scrollableCells: new Set(),
|
|
47
|
+
cellSide: new Map(),
|
|
48
|
+
}}
|
|
49
|
+
setLayout={vi.fn()}
|
|
50
|
+
cells={[
|
|
51
|
+
{ ...notebook.cellData[ERRORED], ...notebook.cellRuntime[ERRORED] },
|
|
52
|
+
]}
|
|
53
|
+
/>
|
|
54
|
+
</Provider>,
|
|
55
|
+
);
|
|
56
|
+
return screen.getAllByTestId(`output-${ERRORED}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe("GridLayoutRenderer", () => {
|
|
60
|
+
it("hides an errored cell placed in the grid", () => {
|
|
61
|
+
const [placed] = renderErroredCell([
|
|
62
|
+
{ i: ERRORED, x: 0, y: 0, w: 4, h: 4 },
|
|
63
|
+
]);
|
|
64
|
+
expect(placed.closest(".invisible")).not.toBeNull();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("keeps an errored cell visible in the Outputs tray", () => {
|
|
68
|
+
const outputs = renderErroredCell([]);
|
|
69
|
+
expect(screen.getByText("Outputs")).toBeTruthy();
|
|
70
|
+
expect(outputs.length).toBeGreaterThan(0);
|
|
71
|
+
for (const output of outputs) {
|
|
72
|
+
expect(output.closest(".invisible")).toBeNull();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|