@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
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
/** Notebook operations that move cells
|
|
3
|
+
/** Notebook operations that move cells and arrange columns. */
|
|
4
4
|
|
|
5
5
|
import { dequal as isEqual } from "dequal";
|
|
6
6
|
import { atom, type Getter, type Setter } from "jotai";
|
|
7
|
-
import
|
|
7
|
+
import { reorderColumnSizes } from "@/components/editor/columns/storage";
|
|
8
|
+
import type {
|
|
9
|
+
DocumentEditor,
|
|
10
|
+
EditableDocument,
|
|
11
|
+
} from "@/core/notebook/document";
|
|
8
12
|
import { arrayMove } from "@/utils/arrays";
|
|
9
13
|
import { notebookAtom, type UndoMoveEntry } from "./cells";
|
|
10
14
|
import { documentOf, focusWhenMounted, modelOf } from "./edit";
|
|
11
|
-
import
|
|
15
|
+
import { CellId } from "./ids";
|
|
12
16
|
import {
|
|
17
|
+
type CellColumnId,
|
|
18
|
+
columnIdsAtom,
|
|
13
19
|
columnOf,
|
|
20
|
+
emptyColumnIdsAtom,
|
|
14
21
|
findColumn,
|
|
15
22
|
type Layout,
|
|
16
23
|
type LayoutColumn,
|
|
17
24
|
layoutAtom,
|
|
25
|
+
newColumnId,
|
|
18
26
|
} from "./layout";
|
|
19
27
|
|
|
20
28
|
/** A placement to restore a cell to: its column and its index there. */
|
|
21
29
|
export interface Placement {
|
|
22
30
|
columnId: CellColumnId;
|
|
23
|
-
index:
|
|
31
|
+
index: number;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
/** A cell with the cells its fold hides, which move with it. */
|
|
@@ -66,12 +74,11 @@ function columnConfigs(
|
|
|
66
74
|
return fixes;
|
|
67
75
|
}
|
|
68
76
|
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const document = documentOf(get);
|
|
77
|
+
/** The steps that make the document's cells fall into `columns`, or null when they do. */
|
|
78
|
+
function arrangement(
|
|
79
|
+
document: EditableDocument,
|
|
80
|
+
columns: readonly (readonly CellId[])[],
|
|
81
|
+
): ((tx: DocumentEditor) => void) | null {
|
|
75
82
|
const order = columns.flat();
|
|
76
83
|
const fixes = columnConfigs(
|
|
77
84
|
columns,
|
|
@@ -79,16 +86,61 @@ export function arrange(get: Getter, set: Setter, columns: CellId[][]): void {
|
|
|
79
86
|
);
|
|
80
87
|
const reordered = !isEqual(order, document.order);
|
|
81
88
|
if (!reordered && fixes.length === 0) {
|
|
82
|
-
return;
|
|
89
|
+
return null;
|
|
83
90
|
}
|
|
84
|
-
|
|
91
|
+
return (tx) => {
|
|
85
92
|
if (reordered) {
|
|
86
93
|
tx.setOrder(order);
|
|
87
94
|
}
|
|
88
95
|
for (const [id, column] of fixes) {
|
|
89
96
|
tx.updateConfig(id, { column });
|
|
90
97
|
}
|
|
91
|
-
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* How many of `columns` the document holds: all but the trailing empty
|
|
103
|
+
* ones, which the page alone keeps.
|
|
104
|
+
*/
|
|
105
|
+
function heldByDocument(columns: readonly (readonly CellId[])[]): number {
|
|
106
|
+
let count = columns.length;
|
|
107
|
+
while (count > 1 && columns[count - 1].length === 0) {
|
|
108
|
+
count -= 1;
|
|
109
|
+
}
|
|
110
|
+
return count;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Name the page's columns: `count` of `ids` for the document's, the rest kept empty. */
|
|
114
|
+
function nameColumns(
|
|
115
|
+
set: Setter,
|
|
116
|
+
ids: readonly CellColumnId[],
|
|
117
|
+
count: number,
|
|
118
|
+
): void {
|
|
119
|
+
set(columnIdsAtom, ids.slice(0, count));
|
|
120
|
+
set(emptyColumnIdsAtom, ids.slice(count));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Make the document's cells fall into `columns`, in that order, as one
|
|
125
|
+
* edit, and name the columns `ids`, by default as they stand. Nothing is
|
|
126
|
+
* written when the cells already fall that way. Trailing columns left
|
|
127
|
+
* empty stay on the page, as the document cannot hold them, until a drop
|
|
128
|
+
* compacts them.
|
|
129
|
+
*/
|
|
130
|
+
export function arrange(
|
|
131
|
+
get: Getter,
|
|
132
|
+
set: Setter,
|
|
133
|
+
columns: CellId[][],
|
|
134
|
+
ids: readonly CellColumnId[] = get(layoutAtom).columns.map(
|
|
135
|
+
(column) => column.id,
|
|
136
|
+
),
|
|
137
|
+
): void {
|
|
138
|
+
const count = heldByDocument(columns);
|
|
139
|
+
nameColumns(set, ids, count);
|
|
140
|
+
const edit = arrangement(documentOf(get), columns.slice(0, count));
|
|
141
|
+
if (edit !== null) {
|
|
142
|
+
set(modelOf(get).editAtom, edit);
|
|
143
|
+
}
|
|
92
144
|
}
|
|
93
145
|
|
|
94
146
|
/**
|
|
@@ -339,3 +391,144 @@ export function placeCells(
|
|
|
339
391
|
}
|
|
340
392
|
arrange(get, set, cleaned);
|
|
341
393
|
}
|
|
394
|
+
|
|
395
|
+
// Columns --------------------------------------------------------------------
|
|
396
|
+
|
|
397
|
+
/** Add a column after another, with one new cell to start it, and focus the cell. */
|
|
398
|
+
export const addColumnAtom = atom(
|
|
399
|
+
null,
|
|
400
|
+
(get, set, { columnId }: { columnId: CellColumnId }): void => {
|
|
401
|
+
const layout = get(layoutAtom);
|
|
402
|
+
const at = layout.columns.findIndex((column) => column.id === columnId);
|
|
403
|
+
if (at === -1) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const id = CellId.create();
|
|
407
|
+
const columns = columnsOf(layout);
|
|
408
|
+
columns.splice(at + 1, 0, [id]);
|
|
409
|
+
const ids = layout.columns.map((column) => column.id);
|
|
410
|
+
ids.splice(at + 1, 0, newColumnId());
|
|
411
|
+
const document = documentOf(get);
|
|
412
|
+
const previous = layout.columns[at].ids.at(-1);
|
|
413
|
+
const count = heldByDocument(columns);
|
|
414
|
+
nameColumns(set, ids, count);
|
|
415
|
+
set(modelOf(get).editAtom, (tx) => {
|
|
416
|
+
tx.createCell(
|
|
417
|
+
{ id, code: "", config: { column: at + 1 } },
|
|
418
|
+
previous === undefined ? {} : { after: previous },
|
|
419
|
+
);
|
|
420
|
+
arrangement(document, columns.slice(0, count))?.(tx);
|
|
421
|
+
});
|
|
422
|
+
focusWhenMounted(set, id);
|
|
423
|
+
},
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
/** Start a new column at a cell, unless it already starts the first column. */
|
|
427
|
+
export const addColumnBreakpointAtom = atom(
|
|
428
|
+
null,
|
|
429
|
+
(get, set, { cellId }: { cellId: CellId }): void => {
|
|
430
|
+
const layout = get(layoutAtom);
|
|
431
|
+
const column = columnOf(layout, cellId);
|
|
432
|
+
const at = layout.columns.indexOf(column);
|
|
433
|
+
const index = column.ids.indexOf(cellId);
|
|
434
|
+
if (at === 0 && index === 0) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const columns = columnsOf(layout);
|
|
438
|
+
columns.splice(at, 1, column.ids.slice(0, index), column.ids.slice(index));
|
|
439
|
+
const ids = layout.columns.map((column) => column.id);
|
|
440
|
+
// The id stays with the cells, so the half without any is the new one.
|
|
441
|
+
ids.splice(index === 0 ? at : at + 1, 0, newColumnId());
|
|
442
|
+
arrange(get, set, columns, ids);
|
|
443
|
+
},
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
/** Remove a column, moving its cells to the column before it, or after it for the first. */
|
|
447
|
+
export const deleteColumnAtom = atom(
|
|
448
|
+
null,
|
|
449
|
+
(get, set, { columnId }: { columnId: CellColumnId }): void => {
|
|
450
|
+
const layout = get(layoutAtom);
|
|
451
|
+
const at = layout.columns.findIndex((column) => column.id === columnId);
|
|
452
|
+
if (at === -1 || layout.columns.length <= 1) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const columns = columnsOf(layout);
|
|
456
|
+
const target = at === 0 ? 1 : at - 1;
|
|
457
|
+
columns[target] =
|
|
458
|
+
at === 0
|
|
459
|
+
? [...columns[at], ...columns[target]]
|
|
460
|
+
: [...columns[target], ...columns[at]];
|
|
461
|
+
columns.splice(at, 1);
|
|
462
|
+
const ids = layout.columns.map((column) => column.id);
|
|
463
|
+
ids.splice(at, 1);
|
|
464
|
+
arrange(get, set, columns, ids);
|
|
465
|
+
},
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
/** Bring every cell into the first column. */
|
|
469
|
+
export const mergeAllColumnsAtom = atom(null, (get, set): void => {
|
|
470
|
+
const layout = get(layoutAtom);
|
|
471
|
+
if (layout.columns.length <= 1) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
arrange(
|
|
475
|
+
get,
|
|
476
|
+
set,
|
|
477
|
+
[layout.columns.flatMap((column) => [...column.ids])],
|
|
478
|
+
[layout.columns[0].id],
|
|
479
|
+
);
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
/** Drop the columns a drag left empty. */
|
|
483
|
+
export const compactColumnsAtom = atom(null, (get, set): void => {
|
|
484
|
+
const layout = get(layoutAtom);
|
|
485
|
+
const kept = layout.columns.filter((column) => column.ids.length > 0);
|
|
486
|
+
if (kept.length === layout.columns.length || layout.columns.length <= 1) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
arrange(
|
|
490
|
+
get,
|
|
491
|
+
set,
|
|
492
|
+
kept.map((column) => [...column.ids]),
|
|
493
|
+
kept.map((column) => column.id),
|
|
494
|
+
);
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
/** Move a column where another is, or one step left or right, with its saved width. */
|
|
498
|
+
export const moveColumnAtom = atom(
|
|
499
|
+
null,
|
|
500
|
+
(
|
|
501
|
+
get,
|
|
502
|
+
set,
|
|
503
|
+
{
|
|
504
|
+
column,
|
|
505
|
+
overColumn,
|
|
506
|
+
}: {
|
|
507
|
+
column: CellColumnId;
|
|
508
|
+
overColumn: CellColumnId | "_left_" | "_right_";
|
|
509
|
+
},
|
|
510
|
+
): void => {
|
|
511
|
+
if (column === overColumn) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
const layout = get(layoutAtom);
|
|
515
|
+
const ids = layout.columns.map((column) => column.id);
|
|
516
|
+
const from = ids.indexOf(column);
|
|
517
|
+
const to =
|
|
518
|
+
overColumn === "_left_"
|
|
519
|
+
? from - 1
|
|
520
|
+
: overColumn === "_right_"
|
|
521
|
+
? from + 1
|
|
522
|
+
: ids.indexOf(overColumn);
|
|
523
|
+
if (from === -1 || to < 0 || to >= ids.length) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
arrange(
|
|
527
|
+
get,
|
|
528
|
+
set,
|
|
529
|
+
arrayMove(columnsOf(layout), from, to),
|
|
530
|
+
arrayMove(ids, from, to),
|
|
531
|
+
);
|
|
532
|
+
reorderColumnSizes(from, to);
|
|
533
|
+
},
|
|
534
|
+
);
|
package/src/core/cells/cells.ts
CHANGED
|
@@ -6,11 +6,7 @@ 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
|
-
type CellColumnId,
|
|
11
|
-
type CellIndex,
|
|
12
|
-
MultiColumn,
|
|
13
|
-
} from "@/utils/id-tree";
|
|
9
|
+
import type { CellColumnId } from "./layout";
|
|
14
10
|
import { invariant } from "@/utils/invariant";
|
|
15
11
|
import { Logger } from "@/utils/Logger";
|
|
16
12
|
import { Objects } from "@/utils/objects";
|
|
@@ -18,8 +14,6 @@ import { extractAllTracebackInfo, type TracebackInfo } from "@/utils/traceback";
|
|
|
18
14
|
import { createReducerAndAtoms } from "../../utils/createReducer";
|
|
19
15
|
import { foldAllBulk, unfoldAllBulk } from "../codemirror/editing/commands";
|
|
20
16
|
import { editorMountScheduler } from "../codemirror/editor-mount-scheduler";
|
|
21
|
-
import { prepareCellCodeUpdate } from "../codemirror/language/cell-code";
|
|
22
|
-
import { splitEditor } from "../codemirror/language/utils";
|
|
23
17
|
import type { SerializedEditorState } from "../codemirror/types";
|
|
24
18
|
import { mergeOutlines } from "../dom/outline";
|
|
25
19
|
import type { CellMessage } from "../kernel/messages";
|
|
@@ -30,7 +24,7 @@ import { isWasm } from "../wasm/utils";
|
|
|
30
24
|
import { prepareCellForExecution, transitionCell } from "./cell";
|
|
31
25
|
import { applyDocument, documentEditMiddleware } from "./document";
|
|
32
26
|
import { isCodeHidden, shownHiddenCodeAtom } from "./editor";
|
|
33
|
-
import { CellId, SCRATCH_CELL_ID } from "./ids";
|
|
27
|
+
import { type CellId, SCRATCH_CELL_ID } from "./ids";
|
|
34
28
|
import { type CellLog, getCellLogsForMessage } from "./logs";
|
|
35
29
|
import type { Outline } from "./outline";
|
|
36
30
|
import { focusAndScrollCellIntoView } from "./scrollCellIntoView";
|
|
@@ -74,7 +68,7 @@ export interface UndoDeleteEntry {
|
|
|
74
68
|
export interface UndoMoveEntry {
|
|
75
69
|
type: "move";
|
|
76
70
|
cellIds: CellId[];
|
|
77
|
-
placements: Array<{ columnId: CellColumnId; index:
|
|
71
|
+
placements: Array<{ columnId: CellColumnId; index: number }>;
|
|
78
72
|
}
|
|
79
73
|
|
|
80
74
|
export type HistoryEntry = UndoDeleteEntry | UndoMoveEntry;
|
|
@@ -86,7 +80,8 @@ export interface NotebookState {
|
|
|
86
80
|
/**
|
|
87
81
|
* Order of cells on the page.
|
|
88
82
|
*/
|
|
89
|
-
|
|
83
|
+
/** The cells in document order. */
|
|
84
|
+
cellIds: CellId[];
|
|
90
85
|
/**
|
|
91
86
|
* Map of cells to their view state
|
|
92
87
|
*/
|
|
@@ -144,7 +139,7 @@ function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
|
144
139
|
*/
|
|
145
140
|
export function initialNotebookState(): NotebookState {
|
|
146
141
|
return withScratchCell({
|
|
147
|
-
cellIds:
|
|
142
|
+
cellIds: [],
|
|
148
143
|
cellData: {},
|
|
149
144
|
cellRuntime: {},
|
|
150
145
|
cellHandles: {},
|
|
@@ -164,74 +159,6 @@ const {
|
|
|
164
159
|
useActions,
|
|
165
160
|
valueAtom: notebookAtom,
|
|
166
161
|
} = createReducerAndAtoms(initialNotebookState, {
|
|
167
|
-
moveColumn: (
|
|
168
|
-
state,
|
|
169
|
-
action: {
|
|
170
|
-
column: CellColumnId;
|
|
171
|
-
overColumn: CellColumnId | "_left_" | "_right_";
|
|
172
|
-
},
|
|
173
|
-
) => {
|
|
174
|
-
if (action.column === action.overColumn) {
|
|
175
|
-
return state;
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
...state,
|
|
179
|
-
cellIds: state.cellIds.moveColumn(action.column, action.overColumn),
|
|
180
|
-
};
|
|
181
|
-
},
|
|
182
|
-
addColumn: (state, action: { columnId: CellColumnId }) => {
|
|
183
|
-
// Add column and new cell
|
|
184
|
-
const newCellId = CellId.create();
|
|
185
|
-
return {
|
|
186
|
-
...state,
|
|
187
|
-
cellIds: state.cellIds.addColumn(action.columnId, [newCellId]),
|
|
188
|
-
cellData: {
|
|
189
|
-
...state.cellData,
|
|
190
|
-
[newCellId]: createCell({
|
|
191
|
-
id: newCellId,
|
|
192
|
-
}),
|
|
193
|
-
},
|
|
194
|
-
cellRuntime: {
|
|
195
|
-
...state.cellRuntime,
|
|
196
|
-
[newCellId]: createCellRuntimeState(),
|
|
197
|
-
},
|
|
198
|
-
cellHandles: {
|
|
199
|
-
...state.cellHandles,
|
|
200
|
-
[newCellId]: createRef(),
|
|
201
|
-
},
|
|
202
|
-
scrollKey: newCellId,
|
|
203
|
-
};
|
|
204
|
-
},
|
|
205
|
-
addColumnBreakpoint: (state, action: { cellId: CellId }) => {
|
|
206
|
-
const { cellId } = action;
|
|
207
|
-
if (state.cellIds.getColumns()[0].inOrderIds[0] === cellId) {
|
|
208
|
-
return state;
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
...state,
|
|
212
|
-
cellIds: state.cellIds.insertBreakpoint(cellId),
|
|
213
|
-
};
|
|
214
|
-
},
|
|
215
|
-
deleteColumn: (state, action: { columnId: CellColumnId }) => {
|
|
216
|
-
// Move all cells in the column to the previous column
|
|
217
|
-
const { columnId } = action;
|
|
218
|
-
return {
|
|
219
|
-
...state,
|
|
220
|
-
cellIds: state.cellIds.delete(columnId),
|
|
221
|
-
};
|
|
222
|
-
},
|
|
223
|
-
mergeAllColumns: (state) => {
|
|
224
|
-
return {
|
|
225
|
-
...state,
|
|
226
|
-
cellIds: state.cellIds.mergeAllColumns(),
|
|
227
|
-
};
|
|
228
|
-
},
|
|
229
|
-
compactColumns: (state) => {
|
|
230
|
-
return {
|
|
231
|
-
...state,
|
|
232
|
-
cellIds: state.cellIds.compact(),
|
|
233
|
-
};
|
|
234
|
-
},
|
|
235
162
|
/**
|
|
236
163
|
* Put moved cells back where they were.
|
|
237
164
|
*
|
|
@@ -332,7 +259,7 @@ const {
|
|
|
332
259
|
/** Follow the host document's cells and order. */
|
|
333
260
|
reconcileDocument: (state, document: EditableDocument) => {
|
|
334
261
|
const nextState = applyDocument(state, document);
|
|
335
|
-
for (const cellId of state.cellIds
|
|
262
|
+
for (const cellId of state.cellIds) {
|
|
336
263
|
if (!(cellId in nextState.cellData)) {
|
|
337
264
|
releaseCellAtoms(cellId);
|
|
338
265
|
}
|
|
@@ -382,7 +309,7 @@ const {
|
|
|
382
309
|
},
|
|
383
310
|
) => {
|
|
384
311
|
const cellData = { ...state.cellData };
|
|
385
|
-
for (const cellId of state.cellIds
|
|
312
|
+
for (const cellId of state.cellIds) {
|
|
386
313
|
const cell = state.cellData[cellId];
|
|
387
314
|
const lastCodeRun = action.lastCodeRun[cellId] ?? null;
|
|
388
315
|
cellData[cellId] = {
|
|
@@ -402,7 +329,7 @@ const {
|
|
|
402
329
|
resetCellRuntimes: (state) => {
|
|
403
330
|
const preserveSnapshot = isWasm();
|
|
404
331
|
const cellRuntime = { ...state.cellRuntime };
|
|
405
|
-
for (const cellId of [...state.cellIds
|
|
332
|
+
for (const cellId of [...state.cellIds, SCRATCH_CELL_ID]) {
|
|
406
333
|
const previous = state.cellRuntime[cellId];
|
|
407
334
|
const hasSnapshot =
|
|
408
335
|
preserveSnapshot &&
|
|
@@ -419,12 +346,7 @@ const {
|
|
|
419
346
|
return state;
|
|
420
347
|
}
|
|
421
348
|
|
|
422
|
-
const
|
|
423
|
-
const index = column.indexOfOrThrow(scrollKey);
|
|
424
|
-
|
|
425
|
-
const cellId =
|
|
426
|
-
index === column.length - 1 ? column.last() : column.atOrThrow(index);
|
|
427
|
-
|
|
349
|
+
const cellId = scrollKey;
|
|
428
350
|
focusAndScrollCellIntoView({
|
|
429
351
|
cellId: cellId,
|
|
430
352
|
cell: state.cellHandles[cellId],
|
|
@@ -462,110 +384,6 @@ const {
|
|
|
462
384
|
cellLogs: [],
|
|
463
385
|
};
|
|
464
386
|
},
|
|
465
|
-
splitCell: (state, action: { cellId: CellId }) => {
|
|
466
|
-
const { cellId } = action;
|
|
467
|
-
const column = state.cellIds.findWithId(cellId);
|
|
468
|
-
const index = column.indexOfOrThrow(cellId);
|
|
469
|
-
const cell = state.cellData[cellId];
|
|
470
|
-
const cellHandle = state.cellHandles[cellId].current;
|
|
471
|
-
|
|
472
|
-
if (cellHandle?.editorView == null) {
|
|
473
|
-
return state;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const { beforeCursorCode, afterCursorCode } = splitEditor(
|
|
477
|
-
cellHandle.editorView,
|
|
478
|
-
);
|
|
479
|
-
|
|
480
|
-
const update = prepareCellCodeUpdate(
|
|
481
|
-
cellHandle.editorView.state,
|
|
482
|
-
beforeCursorCode,
|
|
483
|
-
);
|
|
484
|
-
|
|
485
|
-
if (update) {
|
|
486
|
-
cellHandle.editorView.dispatch(update);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const newCellId = CellId.create();
|
|
490
|
-
|
|
491
|
-
return {
|
|
492
|
-
...state,
|
|
493
|
-
cellIds: state.cellIds.insertId(newCellId, column.id, index + 1),
|
|
494
|
-
cellData: {
|
|
495
|
-
...state.cellData,
|
|
496
|
-
[cellId]: {
|
|
497
|
-
...cell,
|
|
498
|
-
code: beforeCursorCode,
|
|
499
|
-
edited:
|
|
500
|
-
Boolean(beforeCursorCode) &&
|
|
501
|
-
beforeCursorCode.trim() !== cell.lastCodeRun?.trim(),
|
|
502
|
-
},
|
|
503
|
-
[newCellId]: createCell({
|
|
504
|
-
id: newCellId,
|
|
505
|
-
code: afterCursorCode,
|
|
506
|
-
edited: Boolean(afterCursorCode),
|
|
507
|
-
}),
|
|
508
|
-
},
|
|
509
|
-
cellRuntime: {
|
|
510
|
-
...state.cellRuntime,
|
|
511
|
-
[cellId]: {
|
|
512
|
-
...state.cellRuntime[cellId],
|
|
513
|
-
output: null,
|
|
514
|
-
consoleOutputs: [],
|
|
515
|
-
},
|
|
516
|
-
[newCellId]: createCellRuntimeState(),
|
|
517
|
-
},
|
|
518
|
-
cellHandles: {
|
|
519
|
-
...state.cellHandles,
|
|
520
|
-
[newCellId]: createRef(),
|
|
521
|
-
},
|
|
522
|
-
scrollKey: newCellId,
|
|
523
|
-
};
|
|
524
|
-
},
|
|
525
|
-
undoSplitCell: (state, action: { cellId: CellId; snapshot: string }) => {
|
|
526
|
-
const { cellId, snapshot } = action;
|
|
527
|
-
|
|
528
|
-
const cell = state.cellData[cellId];
|
|
529
|
-
const cellHandle = state.cellHandles[cellId].current;
|
|
530
|
-
|
|
531
|
-
if (cellHandle?.editorView == null) {
|
|
532
|
-
return state;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const update = prepareCellCodeUpdate(cellHandle.editorView.state, snapshot);
|
|
536
|
-
|
|
537
|
-
if (update) {
|
|
538
|
-
cellHandle.editorView.dispatch(update);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
return {
|
|
542
|
-
...state,
|
|
543
|
-
cellIds: state.cellIds.transformWithCellId(cellId, (column) => {
|
|
544
|
-
const newCellIndex = column.indexOfOrThrow(cellId) + 1;
|
|
545
|
-
return column.deleteAtIndex(newCellIndex);
|
|
546
|
-
}),
|
|
547
|
-
cellData: {
|
|
548
|
-
...state.cellData,
|
|
549
|
-
[cellId]: {
|
|
550
|
-
...cell,
|
|
551
|
-
code: snapshot,
|
|
552
|
-
edited:
|
|
553
|
-
Boolean(snapshot) && snapshot?.trim() !== cell.lastCodeRun?.trim(),
|
|
554
|
-
},
|
|
555
|
-
},
|
|
556
|
-
cellRuntime: {
|
|
557
|
-
...state.cellRuntime,
|
|
558
|
-
[cellId]: {
|
|
559
|
-
...state.cellRuntime[cellId],
|
|
560
|
-
output: null,
|
|
561
|
-
consoleOutputs: [],
|
|
562
|
-
},
|
|
563
|
-
},
|
|
564
|
-
cellHandles: {
|
|
565
|
-
...state.cellHandles,
|
|
566
|
-
},
|
|
567
|
-
};
|
|
568
|
-
},
|
|
569
387
|
clearCellOutput: (state, action: { cellId: CellId }) => {
|
|
570
388
|
const { cellId } = action;
|
|
571
389
|
return updateCellRuntimeState({
|
|
@@ -594,7 +412,7 @@ const {
|
|
|
594
412
|
},
|
|
595
413
|
clearAllCellOutputs: (state) => {
|
|
596
414
|
const newCellRuntime = { ...state.cellRuntime };
|
|
597
|
-
for (const cellId of state.cellIds
|
|
415
|
+
for (const cellId of state.cellIds) {
|
|
598
416
|
newCellRuntime[cellId] = {
|
|
599
417
|
...newCellRuntime[cellId],
|
|
600
418
|
output: null,
|
|
@@ -660,43 +478,12 @@ function updateCellData({
|
|
|
660
478
|
};
|
|
661
479
|
}
|
|
662
480
|
|
|
481
|
+
/** Each cell's config in order. The document's `column` configs are canonical. */
|
|
663
482
|
export function getCellConfigs(state: NotebookState): CellConfig[] {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
// Handle the case where there's only one column
|
|
670
|
-
// We don't want to set the column config
|
|
671
|
-
const hasMultipleColumns = state.cellIds.getColumns().length > 1;
|
|
672
|
-
if (!hasMultipleColumns) {
|
|
673
|
-
return state.cellIds.getColumns().flatMap((column) => {
|
|
674
|
-
return column.inOrderIds.map((cellId) => {
|
|
675
|
-
return {
|
|
676
|
-
...cells[cellId].config,
|
|
677
|
-
...defaultCellConfig,
|
|
678
|
-
};
|
|
679
|
-
});
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
return state.cellIds.getColumns().flatMap((column, columnIndex) => {
|
|
684
|
-
return column.inOrderIds.map((cellId, cellIndex) => {
|
|
685
|
-
const config: Partial<CellConfig> = { ...defaultCellConfig };
|
|
686
|
-
|
|
687
|
-
// Only set the column index for the first cell in the column
|
|
688
|
-
if (cellIndex === 0) {
|
|
689
|
-
config.column = columnIndex;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
const newConfig = {
|
|
693
|
-
...cells[cellId].config,
|
|
694
|
-
...config,
|
|
695
|
-
};
|
|
696
|
-
|
|
697
|
-
return newConfig;
|
|
698
|
-
});
|
|
699
|
-
});
|
|
483
|
+
return state.cellIds.map((cellId) => ({
|
|
484
|
+
...state.cellData[cellId].config,
|
|
485
|
+
column: state.cellData[cellId].config.column ?? null,
|
|
486
|
+
}));
|
|
700
487
|
}
|
|
701
488
|
|
|
702
489
|
export {
|
|
@@ -716,9 +503,7 @@ export const addLogs = imperativeActions.addLogs;
|
|
|
716
503
|
|
|
717
504
|
export const cellIdsAtom = atom((get) => get(notebookAtom).cellIds);
|
|
718
505
|
|
|
719
|
-
export const hasOnlyOneCellAtom = atom((get) =>
|
|
720
|
-
get(cellIdsAtom).hasOnlyOneId(),
|
|
721
|
-
);
|
|
506
|
+
export const hasOnlyOneCellAtom = atom((get) => get(cellIdsAtom).length === 1);
|
|
722
507
|
|
|
723
508
|
export const hasDisabledCellsAtom = atom(
|
|
724
509
|
(get) => disabledCellIds(get(notebookAtom)).length > 0,
|
|
@@ -736,7 +521,7 @@ export const needsRunAtom = atom((get) => notebookNeedsRun(get(notebookAtom)));
|
|
|
736
521
|
|
|
737
522
|
export const cellErrorsAtom = atom((get) => {
|
|
738
523
|
const { cellIds, cellRuntime, cellData } = get(notebookAtom);
|
|
739
|
-
const errors = cellIds
|
|
524
|
+
const errors = cellIds
|
|
740
525
|
.map((cellId) => {
|
|
741
526
|
const cell = cellRuntime[cellId];
|
|
742
527
|
const { name } = cellData[cellId];
|
|
@@ -785,9 +570,7 @@ export const cellOutlinesAtom = createDeepEqualAtom(
|
|
|
785
570
|
export const notebookOutline = atom((get) => {
|
|
786
571
|
const cellIds = get(cellIdsAtom);
|
|
787
572
|
const cellRuntime = get(cellsRuntimeAtom);
|
|
788
|
-
const outlines = cellIds.
|
|
789
|
-
(cellId) => cellRuntime[cellId].outline,
|
|
790
|
-
);
|
|
573
|
+
const outlines = cellIds.map((cellId) => cellRuntime[cellId].outline);
|
|
791
574
|
return mergeOutlines(outlines);
|
|
792
575
|
});
|
|
793
576
|
|
|
@@ -797,7 +580,7 @@ export const cellIdToNamesMap = createDeepEqualAtom(
|
|
|
797
580
|
atom((get) => {
|
|
798
581
|
const { cellIds, cellData } = get(notebookAtom);
|
|
799
582
|
const names: Record<CellId, string | undefined> = Objects.fromEntries(
|
|
800
|
-
cellIds.
|
|
583
|
+
cellIds.map((cellId) => [cellId, cellData[cellId]?.name]),
|
|
801
584
|
);
|
|
802
585
|
return names;
|
|
803
586
|
}),
|
|
@@ -854,12 +637,12 @@ export const getCells = () => store.get(notebookAtom).cellIds;
|
|
|
854
637
|
*/
|
|
855
638
|
export const getCellNames = () => {
|
|
856
639
|
const { cellIds, cellData } = store.get(notebookAtom);
|
|
857
|
-
return cellIds.
|
|
640
|
+
return cellIds.map((id) => cellData[id]?.name).filter(Boolean);
|
|
858
641
|
};
|
|
859
642
|
|
|
860
643
|
const cellDataAtoms = splitAtom(
|
|
861
644
|
selectAtom(notebookAtom, (cells) =>
|
|
862
|
-
cells.cellIds.
|
|
645
|
+
cells.cellIds.map((id) => cells.cellData[id]),
|
|
863
646
|
),
|
|
864
647
|
);
|
|
865
648
|
export const useCellDataAtoms = () => useAtom(cellDataAtoms);
|
|
@@ -879,16 +662,7 @@ export const notebookQueuedOrRunningCountAtom = atom((get) =>
|
|
|
879
662
|
notebookQueueOrRunningCount(get(notebookAtom)),
|
|
880
663
|
);
|
|
881
664
|
|
|
882
|
-
export const
|
|
883
|
-
(get) => get(notebookAtom).cellIds.colLength,
|
|
884
|
-
);
|
|
885
|
-
export const hasCellsAtom = atom(
|
|
886
|
-
(get) => get(notebookAtom).cellIds.idLength > 0,
|
|
887
|
-
);
|
|
888
|
-
export const columnIdsAtom = atom((get) =>
|
|
889
|
-
get(notebookAtom).cellIds.getColumnIds(),
|
|
890
|
-
);
|
|
891
|
-
|
|
665
|
+
export const hasCellsAtom = atom((get) => get(notebookAtom).cellIds.length > 0);
|
|
892
666
|
export const cellDataAtom = atomFamily((cellId: CellId) =>
|
|
893
667
|
atom((get) => get(notebookAtom).cellData[cellId]),
|
|
894
668
|
);
|
|
@@ -929,7 +703,7 @@ export const useCellHandle = (cellId: CellId) =>
|
|
|
929
703
|
*/
|
|
930
704
|
export const getAllEditorViews = () => {
|
|
931
705
|
const { cellIds, cellHandles } = store.get(notebookAtom);
|
|
932
|
-
return cellIds
|
|
706
|
+
return cellIds
|
|
933
707
|
.map((cellId) => cellHandles[cellId]?.current?.editorViewOrNull)
|
|
934
708
|
.filter(Boolean);
|
|
935
709
|
};
|
|
@@ -953,12 +727,10 @@ export function flattenTopLevelNotebookCells(
|
|
|
953
727
|
state: NotebookState,
|
|
954
728
|
): (CellData & CellRuntimeState)[] {
|
|
955
729
|
const { cellIds, cellData, cellRuntime } = state;
|
|
956
|
-
return cellIds.
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
})),
|
|
961
|
-
);
|
|
730
|
+
return cellIds.map((cellId) => ({
|
|
731
|
+
...cellData[cellId],
|
|
732
|
+
...cellRuntime[cellId],
|
|
733
|
+
}));
|
|
962
734
|
}
|
|
963
735
|
|
|
964
736
|
export function createTracebackInfoAtom(
|