@marimo-team/islands 0.25.3-dev197 → 0.25.3-dev198
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-BRuwLOIx.js → ConnectedDataExplorerComponent-BsWiIPFk.js} +4 -4
- package/dist/{ErrorBoundary-jQVF8yMb.js → ErrorBoundary-D1Z3KAf_.js} +2 -2
- package/dist/{abnfDiagram-VCTEODGH-LlJTOOU_.js → abnfDiagram-VCTEODGH-I2x4Yu25.js} +2 -2
- package/dist/{architectureDiagram-5GKGNRK7-9PQtGLLZ.js → architectureDiagram-5GKGNRK7-1bSQMKzK.js} +1 -1
- package/dist/{arrays-DA6KkLfq.js → arrays-DoQ-AILx.js} +7 -21
- package/dist/{capabilities-CvWU-ey_.js → capabilities-C2QUNRXi.js} +1 -1
- package/dist/{chat-ui-Bl2euMBD.js → chat-ui-BAyHM_GD.js} +524 -524
- package/dist/{chunk-IMKFNOWR-DcXv-BD5.js → chunk-IMKFNOWR-fsCGAJ9G.js} +1 -1
- package/dist/{chunk-SHT3W25Y-VwnELN23.js → chunk-SHT3W25Y-D2STW4hj.js} +1 -1
- package/dist/{chunk-SVP7TREG-DgQpI5Zi.js → chunk-SVP7TREG-CiY7cQG-.js} +1 -1
- package/dist/{chunk-TICWLB2K-CTg6VTJT.js → chunk-TICWLB2K-C_t5RBp9.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-UzmcFrnW.js → classDiagram-ZZMXUADV-B2JvZAP4.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-DhjiI6IQ.js → classDiagram-v2-VYDZK3BY-L8VsZG5A.js} +2 -2
- package/dist/{code-visibility-CjZo_SV8.js → code-visibility-CInEQd1e.js} +19 -19
- package/dist/{common-CFLvScF3.js → common-W5HfVJPN.js} +4362 -4362
- package/dist/{cynefinDiagram-5FMLGOSQ-O4ShIbJX.js → cynefinDiagram-5FMLGOSQ-DdllC264.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-dtHhhcPu.js → dagre-GXQ25YYZ-BaWHw4_f.js} +1 -1
- package/dist/{data-grid-overlay-editor-CzW3mY6m.js → data-grid-overlay-editor-BQCaV0fI.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-ppPYVZ6W.js → diagram-S7CK7UJ4-pFt-tUDe.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-CMZDf--k.js → diagram-UQ7AKVKN-DqGJiBp4.js} +1 -1
- package/dist/{diagram-VX7I27RA-CFvJdx-C.js → diagram-VX7I27RA-Dr-yzMjf.js} +1 -1
- package/dist/{diagram-Z3DM3KII-Dt6_uFbv.js → diagram-Z3DM3KII-8xzJzv-w.js} +1 -1
- package/dist/{dropdown-menu-CeaOsjWZ.js → dropdown-menu-NlnsmNA6.js} +2 -2
- package/dist/{ebnfDiagram-PWID7BFC-DpRFrKK-.js → ebnfDiagram-PWID7BFC-Br04Wy-E.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-CqAU4b0u.js → erDiagram-RLTQ6QDP-D5-XVgvv.js} +1 -1
- package/dist/{error-entries-CYGwr5-O.js → error-entries-BacCWMWj.js} +4678 -5028
- package/dist/{feedback-button-GR_8U4Vo.js → feedback-button-DLXUcQ7l.js} +113 -113
- package/dist/{flowDiagram-HODETNUW-i8-Gw8HO.js → flowDiagram-HODETNUW-CVl2kREF.js} +2 -2
- package/dist/{formats-BtoHHy42.js → formats-BCYthwyc.js} +1 -1
- package/dist/{glide-data-editor-Dfdxc22H.js → glide-data-editor-D5YaHPKx.js} +5 -5
- package/dist/{globals-CxjzBEbP.js → globals-DjX1uxzy.js} +2 -2
- package/dist/{html-to-image-Cy5UDpQJ.js → html-to-image-DAmgSo5P.js} +624 -573
- package/dist/{infoDiagram-27XIBGKW-DpfOKdLL.js → infoDiagram-27XIBGKW-BJ4vNcZE.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-Dg7mrMG7.js → ishikawaDiagram-5VMMS53U-B_Jy1Dsm.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-QB6e3Jrj.js → kanban-definition-UXKFOSKX-C6MkS9vw.js} +1 -1
- package/dist/main.js +1117 -1117
- package/dist/{mermaid-CeWG4Egr.js → mermaid-Bh918qrq.js} +34 -34
- package/dist/{mindmap-definition-YA3MSWOX-BTz3uTGe.js → mindmap-definition-YA3MSWOX-BP3ZTuir.js} +1 -1
- package/dist/{number-overlay-editor-CwHYeI4e.js → number-overlay-editor-3C_K6w_0.js} +1 -1
- package/dist/{once-DWGO2mQ2.js → once-NnpX_HnX.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-3ZIEa3mB.js → pegDiagram-XKGWAZYB-nNGOQtnt.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-BJAlk046.js → pieDiagram-E7YTZNPT-CpRz5BZz.js} +1 -1
- package/dist/{process-output-q9MTAIMX.js → process-output-DweUmAmV.js} +3 -3
- package/dist/{railroadDiagram-O6MQD6OU-Dn3bsSRa.js → railroadDiagram-O6MQD6OU-BqOEN4I0.js} +2 -2
- package/dist/{requirementDiagram-BXWQKSXE-wcOmQQCL.js → requirementDiagram-BXWQKSXE-CEfg6vu9.js} +1 -1
- package/dist/{reveal-component-C5bOqXlB.js → reveal-component-JjJRTT9d.js} +17 -17
- package/dist/{sequenceDiagram-WJ2MYXX4-DSh_qxoF.js → sequenceDiagram-WJ2MYXX4-IOmpQcOi.js} +1 -1
- package/dist/{spec-C7Fos-If.js → spec-Dkp64vVQ.js} +1 -1
- package/dist/{stateDiagram-D77RDMKH-DH_H8NMH.js → stateDiagram-D77RDMKH-tgU-EY9_.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-D_JM7MEK.js → stateDiagram-v2-MP3YSRHH-BofhG6q1.js} +2 -2
- package/dist/{swimlanes-42K2YHIH-CfoTJO-9.js → swimlanes-42K2YHIH-DW4vWDBd.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-Z_QhvK0G.js → swimlanesDiagram-VR7AAH4N-BJcrqUJr.js} +2 -2
- package/dist/{swiper-component-D2geL1Ku.js → swiper-component-BVfnhbnt.js} +1 -1
- package/dist/{timeline-definition-24CTP7MA-BFtdScaL.js → timeline-definition-24CTP7MA-D_QU3NGs.js} +1 -1
- package/dist/{toDate-CQAFSwos.js → toDate-BNDEXbfV.js} +30 -30
- package/dist/{useAsyncData-BeyZyjso.js → useAsyncData-ASDni9vH.js} +1 -1
- package/dist/{useDeepCompareMemoize-DOQgae0W.js → useDeepCompareMemoize-B1Ogyf53.js} +1 -1
- package/dist/{useIframeCapabilities-DNvaj9wM.js → useIframeCapabilities-6a_yDNXp.js} +1 -1
- package/dist/{useLifecycle-n2lnCFS8.js → useLifecycle-Bfpa2m7k.js} +1 -1
- package/dist/{useTheme-CY777LXN.js → useTheme-5TwyOh3B.js} +66 -66
- package/dist/{vega-component-0nQzA-I8.js → vega-component-BHS9UOtC.js} +19 -19
- package/dist/{vennDiagram-4TSXK5OY-BXY8IGCA.js → vennDiagram-4TSXK5OY-YFYsNIAh.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-D0tFe6eC.js → wardleyDiagram-VM6X3IG4-i_n8mAWC.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-Dx8wFM-y.js → xychartDiagram-S5SC5T6Z-BYGN95wW.js} +1 -1
- package/package.json +1 -1
- package/src/__mocks__/document.tsx +13 -4
- package/src/__mocks__/notebook.ts +1 -2
- package/src/components/datasources/datasources.tsx +1 -1
- package/src/components/dependency-graph/custom-node.tsx +1 -1
- package/src/components/dependency-graph/minimap-content.tsx +12 -14
- package/src/components/editor/actions/useSetCodeVisibility.ts +1 -1
- package/src/components/editor/actions/useSetOutputsExpanded.ts +1 -1
- package/src/components/editor/alerts/stdin-blocking-alert.tsx +1 -1
- package/src/components/editor/cell/code/cell-editor.tsx +1 -1
- package/src/components/editor/cell/useSplitCell.tsx +8 -5
- package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/session-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/variable-panel.tsx +1 -5
- package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
- package/src/components/editor/columns/__tests__/cell-column.test.tsx +1 -1
- package/src/components/editor/columns/cell-column.tsx +1 -1
- package/src/components/editor/columns/sortable-column.tsx +1 -1
- package/src/components/editor/links/__tests__/cell-link.test.tsx +1 -1
- package/src/components/editor/links/cell-link-list.tsx +1 -1
- package/src/components/editor/links/cell-link.tsx +1 -1
- package/src/components/editor/navigation/__tests__/navigation.test.ts +20 -6
- package/src/components/editor/navigation/__tests__/selection.test.ts +1 -2
- package/src/components/editor/navigation/clipboard.ts +5 -3
- package/src/components/editor/renderers/cell-array.tsx +7 -12
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +1 -1
- package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +4 -4
- package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +1 -1
- package/src/components/editor/stdin-blocking-alert.tsx +1 -1
- package/src/components/slides/__tests__/minimap-actions.test.tsx +13 -4
- package/src/components/slides/__tests__/minimap.test.ts +38 -19
- package/src/components/slides/minimap.tsx +11 -10
- package/src/components/sort/SortableCellsProvider.tsx +2 -21
- package/src/components/tracing/tracing.tsx +1 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +1 -1
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
- package/src/core/ai/context/providers/cell-output.ts +2 -2
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +34 -66
- package/src/core/ai/tools/edit-notebook-tool.ts +12 -10
- package/src/core/cells/__tests__/actions.test.ts +64 -25
- package/src/core/cells/__tests__/arrange.test.ts +156 -4
- package/src/core/cells/__tests__/cells.test.ts +12 -290
- package/src/core/cells/__tests__/document.test.ts +2 -46
- package/src/core/cells/__tests__/harness.ts +28 -4
- package/src/core/cells/__tests__/layout.test.ts +42 -54
- package/src/core/cells/__tests__/session.test.ts +0 -2
- package/src/core/cells/__tests__/utils.test.ts +9 -107
- package/src/core/cells/actions.ts +112 -26
- package/src/core/cells/add-missing-import.ts +1 -1
- package/src/core/cells/arrange.ts +206 -13
- package/src/core/cells/cells.ts +28 -256
- package/src/core/cells/document.ts +18 -122
- package/src/core/cells/layout.ts +79 -10
- package/src/core/cells/pending-delete-service.ts +1 -1
- package/src/core/cells/utils.ts +4 -4
- package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +6 -7
- package/src/core/codemirror/copilot/getCodes.ts +2 -2
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
- package/src/core/codemirror/lsp/utils.ts +1 -1
- package/src/core/documentation/doc-lookup.ts +1 -1
- package/src/core/edit-app.tsx +2 -5
- package/src/core/errors/error-entries.ts +1 -1
- package/src/core/islands/__tests__/bootstrap.test.ts +2 -6
- package/src/core/islands/components/web-components.tsx +1 -1
- package/src/core/notebook/document/__tests__/codemirror.test.ts +8 -0
- package/src/core/session/__tests__/useNotebookSession.hook.test.tsx +1 -1
- package/src/stories/cell.stories.tsx +1 -2
- package/src/stories/layout/vertical/one-column.stories.tsx +1 -2
- package/src/stories/runtime-story.tsx +2 -3
- package/src/utils/__tests__/id-tree.test.ts +0 -617
- package/src/utils/id-tree.tsx +0 -609
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* document model and `notebookAtom` holds only runtime and editor state.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type * as Protocol from "@marimo-team/client/protocol";
|
|
12
11
|
import { dequal as isEqual } from "dequal";
|
|
13
12
|
import type { createStore } from "jotai";
|
|
14
13
|
import { createRef, type RefObject } from "react";
|
|
@@ -21,15 +20,13 @@ import type {
|
|
|
21
20
|
EditableDocument,
|
|
22
21
|
} from "@/core/notebook/document";
|
|
23
22
|
import type { DispatchedActionOf } from "@/utils/createReducer";
|
|
24
|
-
import { CollapsibleTree, MultiColumn } from "@/utils/id-tree";
|
|
25
23
|
import { prepareCellCodeUpdate } from "../codemirror/language/cell-code";
|
|
26
|
-
import type { CellConfig } from "../network/types";
|
|
27
24
|
import { canUseRtc, isRtcEnabled } from "../rtc/state";
|
|
28
25
|
import { store } from "../state/jotai";
|
|
29
26
|
import { activeDocumentModelAtom } from "../session/active-notebook";
|
|
30
27
|
import type { NotebookState, ReducerCellActions } from "./cells";
|
|
31
|
-
import { groupByColumn } from "./columns";
|
|
32
28
|
import type { CellId } from "./ids";
|
|
29
|
+
import { followColumnsAtom } from "./layout";
|
|
33
30
|
import {
|
|
34
31
|
type CellData,
|
|
35
32
|
createCell,
|
|
@@ -42,27 +39,6 @@ type CellAction = DispatchedActionOf<ReducerCellActions>;
|
|
|
42
39
|
|
|
43
40
|
// Following the document ----------------------------------------------------
|
|
44
41
|
|
|
45
|
-
/** Rebuild the tree for `columns`, keeping column ids. */
|
|
46
|
-
function reconcileColumns(
|
|
47
|
-
current: MultiColumn<CellId>,
|
|
48
|
-
columns: CellId[][],
|
|
49
|
-
): MultiColumn<CellId> {
|
|
50
|
-
const previous = current.getColumns();
|
|
51
|
-
// The document cannot hold an empty column, so keep the ones this client has.
|
|
52
|
-
while (previous[columns.length]?.length === 0) {
|
|
53
|
-
columns.push([]);
|
|
54
|
-
}
|
|
55
|
-
if (
|
|
56
|
-
columns.length === previous.length &&
|
|
57
|
-
columns.every((ids, index) => isEqual(ids, previous[index].inOrderIds))
|
|
58
|
-
) {
|
|
59
|
-
return current;
|
|
60
|
-
}
|
|
61
|
-
return new MultiColumn(
|
|
62
|
-
columns.map((ids, index) => CollapsibleTree.from(ids, previous[index]?.id)),
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
42
|
/** The cell's data with the document's fields, and its editor brought along. */
|
|
67
43
|
function followCell(
|
|
68
44
|
current: CellData,
|
|
@@ -115,9 +91,12 @@ export function applyDocument(
|
|
|
115
91
|
state: NotebookState,
|
|
116
92
|
document: EditableDocument,
|
|
117
93
|
): NotebookState {
|
|
118
|
-
|
|
94
|
+
// The protocol's ids are plain strings; the notebook brands them.
|
|
95
|
+
const cellIds = isEqual(document.order, state.cellIds)
|
|
96
|
+
? state.cellIds
|
|
97
|
+
: ([...document.order] as CellId[]);
|
|
119
98
|
let { cellData, cellRuntime, cellHandles } = state;
|
|
120
|
-
for (const id of cellIds
|
|
99
|
+
for (const id of cellIds) {
|
|
121
100
|
const cell = document.cells.get(id);
|
|
122
101
|
const current = state.cellData[id];
|
|
123
102
|
if (cell === undefined) {
|
|
@@ -149,8 +128,8 @@ export function applyDocument(
|
|
|
149
128
|
cellData = { ...cellData, [id]: next };
|
|
150
129
|
}
|
|
151
130
|
}
|
|
152
|
-
const present = new Set(cellIds
|
|
153
|
-
const removed = state.cellIds.
|
|
131
|
+
const present = new Set(cellIds);
|
|
132
|
+
const removed = state.cellIds.filter((id) => !present.has(id));
|
|
154
133
|
if (removed.length > 0) {
|
|
155
134
|
const gone = new Set(removed);
|
|
156
135
|
const keep = <V>(record: Record<CellId, V>): Record<CellId, V> =>
|
|
@@ -172,7 +151,8 @@ export function applyDocument(
|
|
|
172
151
|
}
|
|
173
152
|
|
|
174
153
|
/**
|
|
175
|
-
* Reconcile the model's document
|
|
154
|
+
* Reconcile the model's document and name its columns, now and on each
|
|
155
|
+
* change, until the signal aborts.
|
|
176
156
|
*
|
|
177
157
|
* TODO(MO-8028): Delete with `applyDocument`.
|
|
178
158
|
*/
|
|
@@ -191,6 +171,7 @@ export function followDocument({
|
|
|
191
171
|
const document = store.get(model.documentAtom);
|
|
192
172
|
if (document !== null) {
|
|
193
173
|
reconcile(document);
|
|
174
|
+
store.set(followColumnsAtom, document);
|
|
194
175
|
}
|
|
195
176
|
};
|
|
196
177
|
const unsubscribe = store.sub(model.documentAtom, follow);
|
|
@@ -200,107 +181,22 @@ export function followDocument({
|
|
|
200
181
|
|
|
201
182
|
// Editing the document ------------------------------------------------------
|
|
202
183
|
|
|
203
|
-
const CONFIG_FIELDS = ["disabled", "hide_code", "expand_output"] as const;
|
|
204
|
-
|
|
205
|
-
/** The fields of `after` that differ from `before`, leaving `column` to the tree. */
|
|
206
|
-
function configPatch(
|
|
207
|
-
before: CellConfig,
|
|
208
|
-
after: CellConfig,
|
|
209
|
-
): Partial<Protocol.CellConfig> | null {
|
|
210
|
-
const patch: Partial<Protocol.CellConfig> = {};
|
|
211
|
-
for (const field of CONFIG_FIELDS) {
|
|
212
|
-
if (before[field] !== after[field]) {
|
|
213
|
-
patch[field] = after[field] ?? false;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return Object.keys(patch).length === 0 ? null : patch;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
184
|
/**
|
|
220
|
-
* The
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* resolved column differs from their position need one.
|
|
185
|
+
* The edit that writes the code a reducer action changed, or null when none
|
|
186
|
+
* did. Order, creation, deletion, names and configs are edited on the model
|
|
187
|
+
* directly by their atoms.
|
|
224
188
|
*/
|
|
225
|
-
function columnFixes(state: NotebookState): Array<[CellId, number | null]> {
|
|
226
|
-
const fixes: Array<[CellId, number | null]> = [];
|
|
227
|
-
const columns = state.cellIds.getColumns();
|
|
228
|
-
if (columns.length === 1) {
|
|
229
|
-
for (const id of columns[0].inOrderIds) {
|
|
230
|
-
const column = state.cellData[id].config.column;
|
|
231
|
-
if (column != null && column !== 0) {
|
|
232
|
-
fixes.push([id, null]);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return fixes;
|
|
236
|
-
}
|
|
237
|
-
let inherited = 0;
|
|
238
|
-
columns.forEach((column, target) => {
|
|
239
|
-
for (const id of column.inOrderIds) {
|
|
240
|
-
const configured = state.cellData[id].config.column;
|
|
241
|
-
const resolved =
|
|
242
|
-
configured != null && configured >= 0 ? configured : inherited;
|
|
243
|
-
if (resolved !== target) {
|
|
244
|
-
fixes.push([id, target]);
|
|
245
|
-
}
|
|
246
|
-
inherited = target;
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
return fixes;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/** The edit that makes the document match `next`, or null when it already does. */
|
|
253
189
|
function diffNotebook(
|
|
254
190
|
prev: NotebookState,
|
|
255
191
|
next: NotebookState,
|
|
256
192
|
): DocumentEdit | null {
|
|
257
193
|
const steps: Array<(tx: DocumentEditor) => void> = [];
|
|
258
|
-
const
|
|
259
|
-
const nextOrder = next.cellIds.inOrderIds;
|
|
260
|
-
const prevIds = new Set(prevOrder);
|
|
261
|
-
const nextIds = new Set(nextOrder);
|
|
262
|
-
for (const id of prevOrder) {
|
|
263
|
-
if (!nextIds.has(id)) {
|
|
264
|
-
steps.push((tx) => tx.deleteCell(id));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
const created: CellId[] = [];
|
|
268
|
-
for (const id of nextOrder) {
|
|
194
|
+
for (const id of next.cellIds) {
|
|
269
195
|
const cell = next.cellData[id];
|
|
270
196
|
const before = prev.cellData[id];
|
|
271
|
-
if (
|
|
272
|
-
created.push(id);
|
|
273
|
-
steps.push((tx) =>
|
|
274
|
-
tx.createCell({
|
|
275
|
-
id,
|
|
276
|
-
code: cell.code,
|
|
277
|
-
name: cell.name,
|
|
278
|
-
config: cell.config,
|
|
279
|
-
}),
|
|
280
|
-
);
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
if (before === cell) {
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
if (before.code !== cell.code) {
|
|
197
|
+
if (before !== undefined && cell !== before && before.code !== cell.code) {
|
|
287
198
|
steps.push((tx) => tx.setCode(id, cell.code));
|
|
288
199
|
}
|
|
289
|
-
if (before.name !== cell.name) {
|
|
290
|
-
steps.push((tx) => tx.setName(id, cell.name));
|
|
291
|
-
}
|
|
292
|
-
const patch = configPatch(before.config, cell.config);
|
|
293
|
-
if (patch !== null) {
|
|
294
|
-
steps.push((tx) => tx.updateConfig(id, patch));
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
for (const [id, column] of columnFixes(next)) {
|
|
298
|
-
steps.push((tx) => tx.updateConfig(id, { column }));
|
|
299
|
-
}
|
|
300
|
-
// Created cells go to the end, so the order is set when they belong elsewhere.
|
|
301
|
-
const survivors = prevOrder.filter((id) => nextIds.has(id));
|
|
302
|
-
if (!isEqual(nextOrder, [...survivors, ...created])) {
|
|
303
|
-
steps.push((tx) => tx.setOrder(nextOrder));
|
|
304
200
|
}
|
|
305
201
|
if (steps.length === 0) {
|
|
306
202
|
return null;
|
|
@@ -316,8 +212,8 @@ function diffNotebook(
|
|
|
316
212
|
* Middleware for the notebook reducer. Writes what an action changed about
|
|
317
213
|
* the cells and their order into the document model as one edit.
|
|
318
214
|
*
|
|
319
|
-
* TODO(MO-8028):
|
|
320
|
-
*
|
|
215
|
+
* TODO(MO-8028): Only code is left in `diffNotebook`. The middleware goes
|
|
216
|
+
* with it, once the editors bind to the model.
|
|
321
217
|
*/
|
|
322
218
|
export function documentEditMiddleware(
|
|
323
219
|
prev: NotebookState,
|
package/src/core/cells/layout.ts
CHANGED
|
@@ -3,15 +3,83 @@
|
|
|
3
3
|
/** The cells as they appear on the page: by column, with folded sections hidden. */
|
|
4
4
|
|
|
5
5
|
import { atom, useAtomValue } from "jotai";
|
|
6
|
-
import type {
|
|
6
|
+
import type { EditableDocument } from "@/core/notebook/document";
|
|
7
7
|
import { findCollapseRange } from "../dom/outline";
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
8
|
+
import { activeDocumentModelAtom } from "../session/active-notebook";
|
|
9
|
+
import { cellOutlinesAtom } from "./cells";
|
|
10
|
+
import { groupByColumn } from "./columns";
|
|
11
|
+
import { CellId } from "./ids";
|
|
10
12
|
import type { Outline } from "./outline";
|
|
11
13
|
|
|
14
|
+
/** A column's identity on this page, as drag and drop and saved widths refer to it. */
|
|
15
|
+
export type CellColumnId = string & { __brand: "CellColumnId" };
|
|
16
|
+
|
|
12
17
|
/** The headers whose sections the user folded. Only this browser knows. */
|
|
13
18
|
export const collapsedAtom = atom<ReadonlySet<CellId>>(new Set<CellId>());
|
|
14
19
|
|
|
20
|
+
/**
|
|
21
|
+
* This browser's names for the document's columns, by position. The
|
|
22
|
+
* document knows columns only by position, so `followColumnsAtom` names
|
|
23
|
+
* a column as it appears and forgets one as it goes, and the column
|
|
24
|
+
* operations carry the names along as they rearrange.
|
|
25
|
+
*/
|
|
26
|
+
export const columnIdsAtom = atom<readonly CellColumnId[]>([]);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Trailing columns a rearrangement here emptied. The document cannot hold
|
|
30
|
+
* an empty column at its end, so the page keeps them, as drop targets for
|
|
31
|
+
* the cell being dragged, until a drop compacts them.
|
|
32
|
+
*/
|
|
33
|
+
export const emptyColumnIdsAtom = atom<readonly CellColumnId[]>([]);
|
|
34
|
+
|
|
35
|
+
export function newColumnId(): CellColumnId {
|
|
36
|
+
return `column-${CellId.create()}` as CellColumnId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isColumnId(id: unknown): id is CellColumnId {
|
|
40
|
+
return typeof id === "string" && id.startsWith("column-");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Name the document's columns as the document changes. A column that
|
|
45
|
+
* appears takes over an empty column the page keeps, or gets a fresh id;
|
|
46
|
+
* one that goes is forgotten.
|
|
47
|
+
*/
|
|
48
|
+
export const followColumnsAtom = atom(
|
|
49
|
+
null,
|
|
50
|
+
(get, set, document: EditableDocument): void => {
|
|
51
|
+
const count = groupByColumn(document).length;
|
|
52
|
+
const ids = get(columnIdsAtom);
|
|
53
|
+
if (ids.length === count) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const empty = get(emptyColumnIdsAtom);
|
|
57
|
+
const named = [...ids, ...empty].slice(0, count);
|
|
58
|
+
while (named.length < count) {
|
|
59
|
+
named.push(newColumnId());
|
|
60
|
+
}
|
|
61
|
+
set(columnIdsAtom, named);
|
|
62
|
+
set(emptyColumnIdsAtom, empty.slice(Math.max(0, count - ids.length)));
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/** The document's columns, each with its id, then the empty ones the page keeps. */
|
|
67
|
+
function columnsOf(
|
|
68
|
+
document: EditableDocument | null,
|
|
69
|
+
ids: readonly CellColumnId[],
|
|
70
|
+
empty: readonly CellColumnId[],
|
|
71
|
+
): Array<{ id: CellColumnId; ids: CellId[] }> {
|
|
72
|
+
const groups = document === null ? [[]] : groupByColumn(document);
|
|
73
|
+
return [
|
|
74
|
+
...groups.map((cells, index) => ({
|
|
75
|
+
// Before the first document names them, columns go by position.
|
|
76
|
+
id: ids[index] ?? (`column-${index}` as CellColumnId),
|
|
77
|
+
ids: cells,
|
|
78
|
+
})),
|
|
79
|
+
...empty.map((id) => ({ id, ids: [] as CellId[] })),
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
|
|
15
83
|
export interface LayoutColumn {
|
|
16
84
|
readonly id: CellColumnId;
|
|
17
85
|
/** Every cell of the column, in order. */
|
|
@@ -69,18 +137,17 @@ export function deriveLayout(
|
|
|
69
137
|
}
|
|
70
138
|
|
|
71
139
|
/**
|
|
72
|
-
* The layout of the notebook's cells
|
|
140
|
+
* The layout of the notebook's cells: the document's order and columns,
|
|
141
|
+
* this browser's column ids and folds, and the kernel's outlines.
|
|
73
142
|
*
|
|
74
|
-
* TODO(MO-8028):
|
|
75
|
-
* arrange family edits the document; then they derive from the document and
|
|
76
|
-
* the column ids this browser keeps. Outlines come from executions later.
|
|
143
|
+
* TODO(MO-8028): Outlines come from executions later.
|
|
77
144
|
*/
|
|
78
145
|
export const layoutAtom = atom((get): Layout => {
|
|
146
|
+
const model = get(activeDocumentModelAtom);
|
|
147
|
+
const document = model === null ? null : get(model.documentAtom);
|
|
79
148
|
const outlines = get(cellOutlinesAtom);
|
|
80
149
|
return deriveLayout(
|
|
81
|
-
get(
|
|
82
|
-
.getColumns()
|
|
83
|
-
.map((column) => ({ id: column.id, ids: column.inOrderIds })),
|
|
150
|
+
columnsOf(document, get(columnIdsAtom), get(emptyColumnIdsAtom)),
|
|
84
151
|
(id) => outlines[id] ?? null,
|
|
85
152
|
get(collapsedAtom),
|
|
86
153
|
);
|
|
@@ -88,6 +155,8 @@ export const layoutAtom = atom((get): Layout => {
|
|
|
88
155
|
|
|
89
156
|
export const useLayout = () => useAtomValue(layoutAtom);
|
|
90
157
|
|
|
158
|
+
export const numColumnsAtom = atom((get) => get(layoutAtom).columns.length);
|
|
159
|
+
|
|
91
160
|
export function findColumn(
|
|
92
161
|
layout: Layout,
|
|
93
162
|
columnId: CellColumnId,
|
|
@@ -49,7 +49,7 @@ const { valueAtom: pendingDeleteStateAtom, useActions } = createReducerAndAtoms(
|
|
|
49
49
|
const variables = store.get(variablesAtom);
|
|
50
50
|
|
|
51
51
|
const emptyCells = new Set(
|
|
52
|
-
notebook.cellIds.
|
|
52
|
+
notebook.cellIds.filter(
|
|
53
53
|
(id) => notebook.cellData[id].code.trim() === "",
|
|
54
54
|
),
|
|
55
55
|
);
|
package/src/core/cells/utils.ts
CHANGED
|
@@ -25,7 +25,7 @@ export function notebookNeedsRun(state: NotebookState) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export function notebookCells(state: NotebookState) {
|
|
28
|
-
return state.cellIds.
|
|
28
|
+
return state.cellIds.map((cellId) => state.cellData[cellId]);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export function notebookCellEditorViews({ cellHandles }: NotebookState) {
|
|
@@ -42,7 +42,7 @@ export function notebookCellEditorViews({ cellHandles }: NotebookState) {
|
|
|
42
42
|
export function disabledCellIds(state: NotebookState) {
|
|
43
43
|
const { cellIds, cellData } = state;
|
|
44
44
|
const disabledCells: CellId[] = [];
|
|
45
|
-
for (const cellId of cellIds
|
|
45
|
+
for (const cellId of cellIds) {
|
|
46
46
|
const cell = cellData[cellId];
|
|
47
47
|
if (cell.config.disabled) {
|
|
48
48
|
disabledCells.push(cellId);
|
|
@@ -54,7 +54,7 @@ export function disabledCellIds(state: NotebookState) {
|
|
|
54
54
|
export function enabledCellIds(state: NotebookState) {
|
|
55
55
|
const { cellIds, cellData } = state;
|
|
56
56
|
const enabledCells: CellId[] = [];
|
|
57
|
-
for (const cellId of cellIds
|
|
57
|
+
for (const cellId of cellIds) {
|
|
58
58
|
const cell = cellData[cellId];
|
|
59
59
|
if (!cell.config.disabled) {
|
|
60
60
|
enabledCells.push(cellId);
|
|
@@ -108,7 +108,7 @@ export function getDescendantsStatus(
|
|
|
108
108
|
*/
|
|
109
109
|
export function staleCellIds(state: NotebookState) {
|
|
110
110
|
const { cellIds, cellData, cellRuntime } = state;
|
|
111
|
-
return cellIds.
|
|
111
|
+
return cellIds.filter(
|
|
112
112
|
(cellId) =>
|
|
113
113
|
isUninstantiated({
|
|
114
114
|
// runElapstedTimeMs is what we've seen in this session
|
|
@@ -9,7 +9,6 @@ import { createCell } from "@/core/cells/types";
|
|
|
9
9
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
10
10
|
import { store } from "@/core/state/jotai";
|
|
11
11
|
import { variablesAtom } from "@/core/variables/state";
|
|
12
|
-
import { MultiColumn } from "@/utils/id-tree";
|
|
13
12
|
import { cellConfigExtension } from "../../config/extension";
|
|
14
13
|
import { adaptiveLanguageConfiguration } from "../../language/extension";
|
|
15
14
|
import {
|
|
@@ -159,7 +158,7 @@ describe("getCodes", () => {
|
|
|
159
158
|
];
|
|
160
159
|
store.set(notebookAtom, {
|
|
161
160
|
...initialNotebookState(),
|
|
162
|
-
cellIds:
|
|
161
|
+
cellIds: [Cells.cell1, Cells.cell2],
|
|
163
162
|
cellHandles: {
|
|
164
163
|
[Cells.cell1]: { current: mockEditorViews[0] },
|
|
165
164
|
[Cells.cell2]: { current: mockEditorViews[1] },
|
|
@@ -177,7 +176,7 @@ describe("getCodes", () => {
|
|
|
177
176
|
];
|
|
178
177
|
store.set(notebookAtom, {
|
|
179
178
|
...initialNotebookState(),
|
|
180
|
-
cellIds:
|
|
179
|
+
cellIds: [Cells.cell1, Cells.cell2],
|
|
181
180
|
cellHandles: {
|
|
182
181
|
[Cells.cell1]: { current: mockEditorViews[0] },
|
|
183
182
|
[Cells.cell2]: { current: mockEditorViews[1] },
|
|
@@ -196,7 +195,7 @@ describe("getCodes", () => {
|
|
|
196
195
|
];
|
|
197
196
|
store.set(notebookAtom, {
|
|
198
197
|
...initialNotebookState(),
|
|
199
|
-
cellIds:
|
|
198
|
+
cellIds: [Cells.cell1, Cells.cell2, Cells.cell3],
|
|
200
199
|
cellHandles: {
|
|
201
200
|
[Cells.cell1]: { current: mockEditorViews[0] },
|
|
202
201
|
[Cells.cell2]: { current: mockEditorViews[1] },
|
|
@@ -218,7 +217,7 @@ describe("getCodes", () => {
|
|
|
218
217
|
const otherCode = "print('Hello World')";
|
|
219
218
|
store.set(notebookAtom, {
|
|
220
219
|
...initialNotebookState(),
|
|
221
|
-
cellIds:
|
|
220
|
+
cellIds: [Cells.cell1, Cells.cell2],
|
|
222
221
|
cellData: {
|
|
223
222
|
[Cells.cell1]: createCell({ id: Cells.cell1, code: "import os" }),
|
|
224
223
|
[Cells.cell2]: createCell({ id: Cells.cell2, code: "x = 1" }),
|
|
@@ -232,7 +231,7 @@ describe("getCodes", () => {
|
|
|
232
231
|
const otherCode = "print('Hello World')";
|
|
233
232
|
store.set(notebookAtom, {
|
|
234
233
|
...initialNotebookState(),
|
|
235
|
-
cellIds:
|
|
234
|
+
cellIds: [Cells.cell1, Cells.cell2],
|
|
236
235
|
cellData: {
|
|
237
236
|
[Cells.cell1]: createCell({ id: Cells.cell1, code: "import os" }),
|
|
238
237
|
[Cells.cell2]: createCell({ id: Cells.cell2, code: "x = 1" }),
|
|
@@ -250,7 +249,7 @@ describe("topologicalCodesAtom", () => {
|
|
|
250
249
|
it("should include every cell when no editor is mounted", () => {
|
|
251
250
|
store.set(notebookAtom, {
|
|
252
251
|
...initialNotebookState(),
|
|
253
|
-
cellIds:
|
|
252
|
+
cellIds: [Cells.cell1, Cells.cell2, Cells.cell3],
|
|
254
253
|
cellData: {
|
|
255
254
|
[Cells.cell1]: createCell({ id: Cells.cell1, code: "import os" }),
|
|
256
255
|
[Cells.cell2]: createCell({ id: Cells.cell2, code: "x = 1" }),
|
|
@@ -12,7 +12,7 @@ import { getEditorCodeAsPython } from "../language/utils";
|
|
|
12
12
|
const notebookCellCodes = atom((get) => {
|
|
13
13
|
const notebook = get(notebookAtom);
|
|
14
14
|
const codes = Objects.fromEntries(
|
|
15
|
-
notebook.cellIds.
|
|
15
|
+
notebook.cellIds.map((id) => {
|
|
16
16
|
// A cell editor mounts progressively, so the notebook store is the only
|
|
17
17
|
// complete source of code until every editor is built.
|
|
18
18
|
const editorView = notebook.cellHandles[id]?.current?.editorViewOrNull;
|
|
@@ -54,7 +54,7 @@ export function getOtherCellsCode(otherCode: string) {
|
|
|
54
54
|
|
|
55
55
|
const inOrderCellIdsAtom = atom((get) => {
|
|
56
56
|
const notebook = get(notebookAtom);
|
|
57
|
-
return notebook.cellIds
|
|
57
|
+
return notebook.cellIds;
|
|
58
58
|
});
|
|
59
59
|
const topologicalCellIdsAtom = atom((get) => {
|
|
60
60
|
const cellIds = get(inOrderCellIdsAtom);
|
|
@@ -11,7 +11,6 @@ import type { CellId } from "@/core/cells/ids";
|
|
|
11
11
|
import { initialNotebookState, notebookAtom } from "@/core/cells/cells";
|
|
12
12
|
import { createCell } from "@/core/cells/types";
|
|
13
13
|
import { store } from "@/core/state/jotai";
|
|
14
|
-
import { MultiColumn } from "@/utils/id-tree";
|
|
15
14
|
import { topologicalCodesAtom } from "../../copilot/getCodes";
|
|
16
15
|
import { lspWorkspaceAtom } from "@/core/saving/file-state";
|
|
17
16
|
import { languageAdapterState } from "../../language/extension";
|
|
@@ -69,7 +68,7 @@ describe("merged document with unmounted editors", () => {
|
|
|
69
68
|
it("should include the code of cells whose editors are not mounted", () => {
|
|
70
69
|
store.set(notebookAtom, {
|
|
71
70
|
...initialNotebookState(),
|
|
72
|
-
cellIds:
|
|
71
|
+
cellIds: [Cells.cell1, Cells.cell2],
|
|
73
72
|
cellData: {
|
|
74
73
|
[Cells.cell1]: createCell({ id: Cells.cell1, code: "import math" }),
|
|
75
74
|
[Cells.cell2]: createCell({
|
|
@@ -13,7 +13,7 @@ export function isKnownCellDocumentUri(uri: string): boolean {
|
|
|
13
13
|
if (!CellDocumentUri.is(uri)) {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
|
-
return store.get(cellIdsAtom).
|
|
16
|
+
return store.get(cellIdsAtom).includes(CellDocumentUri.parse(uri));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function getLspRootUri() {
|
|
@@ -17,7 +17,7 @@ export async function requestOutputDocumentation(
|
|
|
17
17
|
qualifiedName: string,
|
|
18
18
|
): Promise<void> {
|
|
19
19
|
// We need any valid cell_id for the completion request.
|
|
20
|
-
const cellId = getCells().
|
|
20
|
+
const cellId = getCells().at(0);
|
|
21
21
|
if (!cellId) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
package/src/core/edit-app.tsx
CHANGED
|
@@ -27,11 +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 {
|
|
31
|
-
|
|
32
|
-
notebookIsRunningAtom,
|
|
33
|
-
numColumnsAtom,
|
|
34
|
-
} from "./cells/cells";
|
|
30
|
+
import { hasCellsAtom, notebookIsRunningAtom } from "./cells/cells";
|
|
31
|
+
import { numColumnsAtom } from "./cells/layout";
|
|
35
32
|
import { useCellActions } from "./cells/actions";
|
|
36
33
|
import type { AppConfig, UserConfig } from "./config/config-schema";
|
|
37
34
|
import { RuntimeState } from "./kernel/RuntimeState";
|
|
@@ -80,7 +80,7 @@ export function getCellErrorEntries(store: JotaiStore): CellErrorEntry[] {
|
|
|
80
80
|
const { cellIds, cellRuntime, cellData } = store.get(notebookAtom);
|
|
81
81
|
const entries: CellErrorEntry[] = [];
|
|
82
82
|
|
|
83
|
-
for (const [cellIndex, cellId] of cellIds.
|
|
83
|
+
for (const [cellIndex, cellId] of cellIds.entries()) {
|
|
84
84
|
const cell = cellRuntime[cellId];
|
|
85
85
|
const output = cell.output;
|
|
86
86
|
if (!output || !isErrorMime(output.mimetype)) {
|
|
@@ -103,15 +103,11 @@ describe("initializeIslands document", () => {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
const notebook = store.get(notebookAtom);
|
|
106
|
-
expect(notebook.cellIds
|
|
106
|
+
expect(notebook.cellIds).toEqual(["c1", "c3", "k7f2"]);
|
|
107
107
|
expect(notebook.cellData[cellId("c3")].code).toBe("x = 21");
|
|
108
108
|
expect(notebook.cellRuntime[cellId("c3")]).toBeDefined();
|
|
109
109
|
|
|
110
110
|
handlers?.message({ event: "reset", data: {} });
|
|
111
|
-
expect(store.get(notebookAtom).cellIds
|
|
112
|
-
"c1",
|
|
113
|
-
"c3",
|
|
114
|
-
"k7f2",
|
|
115
|
-
]);
|
|
111
|
+
expect(store.get(notebookAtom).cellIds).toEqual(["c1", "c3", "k7f2"]);
|
|
116
112
|
});
|
|
117
113
|
});
|
|
@@ -104,7 +104,7 @@ export class MarimoIslandElement extends HTMLElement {
|
|
|
104
104
|
*/
|
|
105
105
|
private getCellIdFromIndex(idx: number): CellId | undefined {
|
|
106
106
|
const { cellIds } = store.get(notebookAtom);
|
|
107
|
-
return cellIds.
|
|
107
|
+
return cellIds.at(idx);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/**
|
|
@@ -82,6 +82,14 @@ function languages(id: CellId) {
|
|
|
82
82
|
dropCellOverColumn: vi.fn(),
|
|
83
83
|
sendToTop: vi.fn(),
|
|
84
84
|
sendToBottom: vi.fn(),
|
|
85
|
+
addColumn: vi.fn(),
|
|
86
|
+
addColumnBreakpoint: vi.fn(),
|
|
87
|
+
deleteColumn: vi.fn(),
|
|
88
|
+
mergeAllColumns: vi.fn(),
|
|
89
|
+
compactColumns: vi.fn(),
|
|
90
|
+
moveColumn: vi.fn(),
|
|
91
|
+
splitCell: vi.fn(),
|
|
92
|
+
undoSplitCell: vi.fn(),
|
|
85
93
|
onRun: vi.fn(),
|
|
86
94
|
deleteCell: vi.fn(),
|
|
87
95
|
afterToggleMarkdown: vi.fn(),
|
|
@@ -272,7 +272,7 @@ describe("useNotebookSession document model", () => {
|
|
|
272
272
|
});
|
|
273
273
|
|
|
274
274
|
let notebook = store.get(notebookAtom);
|
|
275
|
-
expect(notebook.cellIds
|
|
275
|
+
expect(notebook.cellIds).toEqual(["c1", "c3", "k7f2"]);
|
|
276
276
|
expect(notebook.cellData[cellId("k7f2")]).toMatchObject({
|
|
277
277
|
code: "y = x * 2",
|
|
278
278
|
config: { hide_code: true },
|
|
@@ -15,7 +15,6 @@ import { requestClientAtom } from "@/core/network/requests";
|
|
|
15
15
|
import { resolveRequestClient } from "@/core/network/resolve";
|
|
16
16
|
import type { CellConfig } from "@/core/network/types";
|
|
17
17
|
import { ConnectionState } from "@/core/session/types";
|
|
18
|
-
import { MultiColumn } from "@/utils/id-tree";
|
|
19
18
|
import type { Milliseconds, Seconds } from "@/utils/time";
|
|
20
19
|
import { Cell as EditorCell } from "../components/editor/notebook-cell";
|
|
21
20
|
import { TooltipProvider } from "../components/ui/tooltip";
|
|
@@ -55,7 +54,7 @@ const Cell: React.FC<{
|
|
|
55
54
|
lastExecutionTime: null,
|
|
56
55
|
},
|
|
57
56
|
},
|
|
58
|
-
cellIds:
|
|
57
|
+
cellIds: [cid],
|
|
59
58
|
cellRuntime: {
|
|
60
59
|
[cid]: createCellRuntimeState({
|
|
61
60
|
output: overrides.output ?? null,
|
|
@@ -12,7 +12,6 @@ import { connectionAtom } from "@/core/network/connection";
|
|
|
12
12
|
import { requestClientAtom } from "@/core/network/requests";
|
|
13
13
|
import { resolveRequestClient } from "@/core/network/resolve";
|
|
14
14
|
import { ConnectionState } from "@/core/session/types";
|
|
15
|
-
import { MultiColumn } from "@/utils/id-tree";
|
|
16
15
|
import type { Milliseconds, Seconds } from "@/utils/time";
|
|
17
16
|
import { CellArray } from "../../../components/editor/renderers/cell-array";
|
|
18
17
|
import { CellsRenderer } from "../../../components/editor/renderers/cells-renderer";
|
|
@@ -52,7 +51,7 @@ LongReprA()`,
|
|
|
52
51
|
lastExecutionTime: null,
|
|
53
52
|
},
|
|
54
53
|
},
|
|
55
|
-
cellIds:
|
|
54
|
+
cellIds: [cellId],
|
|
56
55
|
cellRuntime: {
|
|
57
56
|
[cellId]: createCellRuntimeState({
|
|
58
57
|
output: {
|
|
@@ -16,7 +16,6 @@ import type { EnvironmentOperation } from "@/core/alerts/environment";
|
|
|
16
16
|
import { notebookAtom } from "@/core/cells/cells";
|
|
17
17
|
import { CellId } from "@/core/cells/ids";
|
|
18
18
|
import { createCell, createCellRuntimeState } from "@/core/cells/types";
|
|
19
|
-
import { MultiColumn } from "@/utils/id-tree";
|
|
20
19
|
import { userConfigAtom } from "@/core/config/config";
|
|
21
20
|
import {
|
|
22
21
|
type AppConfig,
|
|
@@ -111,7 +110,7 @@ function RuntimePreview({
|
|
|
111
110
|
{props.surface === "notebook" && (
|
|
112
111
|
<div className="flex-1 min-w-0 pt-12">
|
|
113
112
|
<ConnectionNotice appConfig={appConfig} onRetry={reconnect} />
|
|
114
|
-
{notebook.cellIds.
|
|
113
|
+
{notebook.cellIds.map((cellId) => (
|
|
115
114
|
<VerticalLayoutWrapper key={cellId} appConfig={appConfig}>
|
|
116
115
|
<Cell
|
|
117
116
|
cellId={cellId}
|
|
@@ -351,7 +350,7 @@ export function RuntimeStory(props: Props) {
|
|
|
351
350
|
const cellId = CellId.create();
|
|
352
351
|
state.set(notebookAtom, (value) => ({
|
|
353
352
|
...value,
|
|
354
|
-
cellIds:
|
|
353
|
+
cellIds: [cellId],
|
|
355
354
|
cellData: {
|
|
356
355
|
...value.cellData,
|
|
357
356
|
[cellId]: createCell({
|