@marimo-team/islands 0.25.3-dev170 → 0.25.3-dev175

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.
Files changed (196) hide show
  1. package/dist/{ConnectedDataExplorerComponent-BbSXV-Xa.js → ConnectedDataExplorerComponent-Le_OBfmt.js} +9 -9
  2. package/dist/{ErrorBoundary-NE86qEWZ.js → ErrorBoundary-DNvcAIsP.js} +8 -8
  3. package/dist/{abnfDiagram-VCTEODGH-D7n07nXf.js → abnfDiagram-VCTEODGH-Tf1ghyQQ.js} +2 -2
  4. package/dist/{any-language-editor-3E24SnCV.js → any-language-editor-BVFHDDQ3.js} +4 -4
  5. package/dist/{architectureDiagram-5GKGNRK7-D6CjRib5.js → architectureDiagram-5GKGNRK7-xlnbTG0T.js} +1 -1
  6. package/dist/{chat-ui-CC7GekpG.js → chat-ui-X-cWrL9u.js} +1218 -1218
  7. package/dist/{check-SpOMoCLP.js → check-C9Mp9eCK.js} +1 -1
  8. package/dist/{chunk-IMKFNOWR-6dtPz7uS.js → chunk-IMKFNOWR-Cmd4a5jy.js} +1 -1
  9. package/dist/{chunk-SHT3W25Y-BwnFNKDA.js → chunk-SHT3W25Y-mSNp-WpO.js} +1 -1
  10. package/dist/{chunk-SVP7TREG-D2eV4vBJ.js → chunk-SVP7TREG-CWC49D8X.js} +1 -1
  11. package/dist/{chunk-TICWLB2K-BDs4-_-r.js → chunk-TICWLB2K-De9FINtG.js} +1 -1
  12. package/dist/{classDiagram-ZZMXUADV-DCJnf_8v.js → classDiagram-ZZMXUADV-DweTkYdp.js} +2 -2
  13. package/dist/{classDiagram-v2-VYDZK3BY-BOmSzPBD.js → classDiagram-v2-VYDZK3BY-A6MR2TiE.js} +2 -2
  14. package/dist/{code-visibility-Bzvc6ajl.js → code-visibility-CH1lmM1h.js} +5 -5
  15. package/dist/{common-Ciw4zkh2.js → common-DIrS1UR9.js} +1081 -1085
  16. package/dist/{copy-icon-C1trdvVt.js → copy-icon-De584pZ4.js} +2 -2
  17. package/dist/{cynefinDiagram-5FMLGOSQ-Bln_Soky.js → cynefinDiagram-5FMLGOSQ-BSvo5le-.js} +1 -1
  18. package/dist/{dagre-GXQ25YYZ-D-nf7WzW.js → dagre-GXQ25YYZ-tXRQslO6.js} +1 -1
  19. package/dist/{data-grid-overlay-editor-AQREmxI7.js → data-grid-overlay-editor-DFLZvFK0.js} +1 -1
  20. package/dist/{diagram-S7CK7UJ4-PsgSMkY2.js → diagram-S7CK7UJ4-r3t5VtwI.js} +1 -1
  21. package/dist/{diagram-UQ7AKVKN-DfwfUuSw.js → diagram-UQ7AKVKN-qgbC8YnT.js} +1 -1
  22. package/dist/{diagram-VX7I27RA-C9_e-oMc.js → diagram-VX7I27RA-CiHxEwtp.js} +1 -1
  23. package/dist/{diagram-Z3DM3KII-CWLa5tuY.js → diagram-Z3DM3KII-D95u15Ev.js} +1 -1
  24. package/dist/{dialog-DgeqyrEZ.js → dialog-DVRfQuhD.js} +24 -24
  25. package/dist/{dist-F8Ep36rk.js → dist-B1M0bGO3.js} +1 -1
  26. package/dist/{dist-D6d86eNJ.js → dist-BA13RJj5.js} +1 -1
  27. package/dist/{dist-Bvs24R_E.js → dist-BJtmSgcE.js} +48 -48
  28. package/dist/{dist-CN_BeG2I.js → dist-Ba2VIn1K.js} +53 -53
  29. package/dist/{dist-PXYI_yuP.js → dist-Bj4bmwUm.js} +12 -12
  30. package/dist/{dist-DoE4XJBC.js → dist-BmS-ZGjl.js} +8626 -8626
  31. package/dist/{dist-BorMD-uX.js → dist-Bzogh7CW.js} +87 -87
  32. package/dist/{dist-CN8zI-XC.js → dist-CThPVKaP.js} +1385 -1382
  33. package/dist/{dist-DiDibOYr.js → dist-CTi5FTiV.js} +87 -87
  34. package/dist/{dist-diIx5qJW.js → dist-Ck_C32ye.js} +2 -2
  35. package/dist/{dist-BLfKmR-l.js → dist-D1fnFp1J.js} +1 -1
  36. package/dist/{dist-OR1OnN-y.js → dist-D3x9__Fu.js} +46 -46
  37. package/dist/{dist-BMQf5zIS.js → dist-D7mrh5sO.js} +36 -36
  38. package/dist/{dist-CSJ0MDRw.js → dist-D9Q3xjiP.js} +1 -1
  39. package/dist/{dist-BuaRHxOc.js → dist-DP60Ubh8.js} +2 -2
  40. package/dist/{dist-CSbh1PNP.js → dist-DTv9KkpW.js} +12 -12
  41. package/dist/{dist-D-wwqlzJ.js → dist-DVVwOfrD.js} +109 -109
  42. package/dist/{dist-C8fAKSH1.js → dist-DYXM73-k.js} +36 -36
  43. package/dist/{dist-DBtSl3sf.js → dist-DjeybPOb.js} +1 -1
  44. package/dist/{dist-CrSP_H1M.js → dist-DtGn9N4h.js} +197 -197
  45. package/dist/{dist-CLdpGQVr.js → dist-KN80qWCP.js} +2 -2
  46. package/dist/{dist-Cg7gzw-a.js → dist-O0qFpEJh.js} +56 -56
  47. package/dist/{dist-CkTTIdBe.js → dist-OUle2RT7.js} +207 -207
  48. package/dist/{dist-BK4Oj99o.js → dist-T5rh6JvL.js} +1 -1
  49. package/dist/{dropdown-menu-B6ftyzOg.js → dropdown-menu-DCMbbQ35.js} +691 -691
  50. package/dist/{ebnfDiagram-PWID7BFC-B1QRM58v.js → ebnfDiagram-PWID7BFC-P7e4bryK.js} +2 -2
  51. package/dist/{erDiagram-RLTQ6QDP-DJK_FqvW.js → erDiagram-RLTQ6QDP-CUHZcmRj.js} +1 -1
  52. package/dist/{error-banner-D40pmfQQ.js → error-banner-DxJ3s8YO.js} +57 -57
  53. package/dist/{error-entries-DgK3wUJR.js → error-entries-mpoD5t79.js} +4985 -5006
  54. package/dist/{esm-D2gTsXEV.js → esm-Bbw_Njjx.js} +575 -575
  55. package/dist/{esm-AMFssoNp.js → esm-mDQNEFe_.js} +354 -354
  56. package/dist/{feedback-button-8a6SETmT.js → feedback-button-DL0DJ-LB.js} +30 -30
  57. package/dist/{flowDiagram-HODETNUW-Uxc25XSJ.js → flowDiagram-HODETNUW-BGZ95AzI.js} +2 -2
  58. package/dist/{formats-DQCyPd5Z.js → formats-DI7HEVv7.js} +1 -1
  59. package/dist/{glide-data-editor-B70oke_v.js → glide-data-editor-n4wnx19S.js} +10 -10
  60. package/dist/{glide-utils-Dz_F4pAY.js → glide-utils-D98laidb.js} +2 -2
  61. package/dist/{globals-Cxd5hNlI.js → globals-NCsYyjpB.js} +3 -3
  62. package/dist/{html-to-image-D4yG5Ru0.js → html-to-image-BoZthB4P.js} +467 -458
  63. package/dist/{infoDiagram-27XIBGKW-DmjxqwL0.js → infoDiagram-27XIBGKW-BF0YX70D.js} +1 -1
  64. package/dist/{ishikawaDiagram-5VMMS53U-NgCLHqQi.js → ishikawaDiagram-5VMMS53U-_itsAAn-.js} +1 -1
  65. package/dist/{kanban-definition-UXKFOSKX-CZaG-iam.js → kanban-definition-UXKFOSKX-VNW2Beqh.js} +1 -1
  66. package/dist/{label-D9_-zSg-.js → label-Qvw1E97W.js} +1 -1
  67. package/dist/main.js +8257 -6606
  68. package/dist/{mermaid-CSvw7c71.js → mermaid-CZ6FrClS.js} +35 -35
  69. package/dist/{mindmap-definition-YA3MSWOX-DJYQBDH_.js → mindmap-definition-YA3MSWOX-DR4ripvd.js} +1 -1
  70. package/dist/{number-overlay-editor-ChK-SKUk.js → number-overlay-editor-rlvo4mo3.js} +1 -1
  71. package/dist/{pegDiagram-XKGWAZYB-CHKO_dAe.js → pegDiagram-XKGWAZYB-CFr3XlGl.js} +2 -2
  72. package/dist/{pieDiagram-E7YTZNPT-DVevbMAo.js → pieDiagram-E7YTZNPT-j91XYSLY.js} +1 -1
  73. package/dist/{process-output-DxvBAeL3.js → process-output-DLS4Mqg_.js} +4 -4
  74. package/dist/{railroadDiagram-O6MQD6OU-Detj1kcB.js → railroadDiagram-O6MQD6OU-Cd47ZV9E.js} +2 -2
  75. package/dist/{requirementDiagram-BXWQKSXE-BLFD0T_Z.js → requirementDiagram-BXWQKSXE-eJH6gLtX.js} +1 -1
  76. package/dist/{reveal-component-CXMXeDZD.js → reveal-component-BJfmRUzb.js} +9 -9
  77. package/dist/{select-CkF_GBxO.js → select-2KOiReNY.js} +324 -324
  78. package/dist/{sequenceDiagram-WJ2MYXX4-BZBgatQV.js → sequenceDiagram-WJ2MYXX4-DdfFEIrm.js} +1 -1
  79. package/dist/{spec-Mnkn3XEr.js → spec-h69nC3SI.js} +4 -4
  80. package/dist/{stateDiagram-D77RDMKH-4BZW9-6_.js → stateDiagram-D77RDMKH-DkjDvip8.js} +2 -2
  81. package/dist/{stateDiagram-v2-MP3YSRHH-C4sKC8Iq.js → stateDiagram-v2-MP3YSRHH-DBHACnOo.js} +2 -2
  82. package/dist/{swimlanes-42K2YHIH-SL5yeGe2.js → swimlanes-42K2YHIH-ogImlOmp.js} +1 -1
  83. package/dist/{swimlanesDiagram-VR7AAH4N-DqPmAYUv.js → swimlanesDiagram-VR7AAH4N-D6x-zsci.js} +2 -2
  84. package/dist/{timeline-definition-24CTP7MA-BfXUMWkq.js → timeline-definition-24CTP7MA-DQpLtsHD.js} +1 -1
  85. package/dist/{toDate-TMubKIVL.js → toDate-CDzoofJo.js} +2 -2
  86. package/dist/{toast-Btbve3Lm.js → toast-B5t9o6s_.js} +47 -47
  87. package/dist/{tooltip-CJ4Rqasp.js → tooltip-s4zZxwKe.js} +67 -67
  88. package/dist/{use-restore-focus-CmGwRNId.js → use-restore-focus-BgDTd2tc.js} +1 -1
  89. package/dist/{useAsyncData-DjMGFzFy.js → useAsyncData-Bn8SxUqM.js} +1 -1
  90. package/dist/{useDateFormatter-eCL_SdeG.js → useDateFormatter-D3Tkfzej.js} +2 -2
  91. package/dist/{useDeepCompareMemoize-BQR5TJot.js → useDeepCompareMemoize-CC2tnPCk.js} +1 -1
  92. package/dist/{useLifecycle-C_GvKWbQ.js → useLifecycle-BJlxHqWa.js} +2 -2
  93. package/dist/{useTheme-Bns2gJZ6.js → useTheme-DMfQYmlG.js} +85 -85
  94. package/dist/{vega-component-BsVptuhz.js → vega-component-CovWHi60.js} +7 -7
  95. package/dist/{vennDiagram-4TSXK5OY-CH65znGa.js → vennDiagram-4TSXK5OY-BD-SL_vq.js} +1 -1
  96. package/dist/{wardleyDiagram-VM6X3IG4-z9pWKb2_.js → wardleyDiagram-VM6X3IG4-BDgJV4ah.js} +1 -1
  97. package/dist/{xychartDiagram-S5SC5T6Z-MxyaWjjq.js → xychartDiagram-S5SC5T6Z-1hIHN6Rl.js} +1 -1
  98. package/package.json +1 -1
  99. package/src/__mocks__/document.tsx +54 -0
  100. package/src/__mocks__/notebook.ts +2 -1
  101. package/src/__mocks__/requests.ts +0 -2
  102. package/src/components/chat/chat-panel.tsx +3 -3
  103. package/src/components/datasources/__tests__/column-preview.test.tsx +6 -8
  104. package/src/components/datasources/column-preview.tsx +4 -8
  105. package/src/components/datasources/datasources.tsx +4 -3
  106. package/src/components/dependency-graph/minimap-content.tsx +2 -6
  107. package/src/components/dependency-graph/panels.tsx +2 -1
  108. package/src/components/editor/__tests__/Output.test.tsx +50 -32
  109. package/src/components/editor/__tests__/data-attributes.test.tsx +22 -11
  110. package/src/components/editor/__tests__/output-persistence.test.tsx +6 -1
  111. package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
  112. package/src/components/editor/actions/name-cell-input.tsx +4 -3
  113. package/src/components/editor/actions/useCellActionButton.tsx +20 -26
  114. package/src/components/editor/actions/useNotebookActions.tsx +13 -18
  115. package/src/components/editor/actions/useSetCodeVisibility.ts +10 -11
  116. package/src/components/editor/actions/useSetOutputsExpanded.ts +13 -18
  117. package/src/components/editor/cell/CreateCellButton.tsx +5 -9
  118. package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +3 -1
  119. package/src/components/editor/cell/code/cell-editor.tsx +13 -20
  120. package/src/components/editor/cell/useAddCell.ts +4 -8
  121. package/src/components/editor/cell/useDeleteCell.tsx +10 -36
  122. package/src/components/editor/cell/useRunCells.ts +2 -5
  123. package/src/components/editor/cell/useSplitCell.tsx +2 -1
  124. package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
  125. package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -11
  126. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +3 -1
  127. package/src/components/editor/columns/sortable-column.tsx +1 -1
  128. package/src/components/editor/connections/components.tsx +4 -9
  129. package/src/components/editor/controls/Controls.tsx +1 -1
  130. package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +9 -3
  131. package/src/components/editor/documentation.css +34 -11
  132. package/src/components/editor/errors/auto-fix.tsx +4 -8
  133. package/src/components/editor/file-tree/file-explorer.tsx +3 -7
  134. package/src/components/editor/links/__tests__/cell-link.test.tsx +3 -1
  135. package/src/components/editor/links/cell-link.tsx +2 -1
  136. package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
  137. package/src/components/editor/navigation/__tests__/navigation.test.ts +73 -64
  138. package/src/components/editor/navigation/clipboard.ts +12 -11
  139. package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +11 -20
  140. package/src/components/editor/navigation/navigation.ts +20 -28
  141. package/src/components/editor/notebook-cell.tsx +7 -10
  142. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
  143. package/src/components/editor/renderers/cell-array.tsx +10 -17
  144. package/src/components/markdown/markdown-renderer.tsx +4 -8
  145. package/src/components/pages/edit-page.tsx +32 -17
  146. package/src/components/scratchpad/scratchpad.test.tsx +3 -1
  147. package/src/components/scratchpad/scratchpad.tsx +4 -7
  148. package/src/components/slides/__tests__/minimap-actions.test.tsx +9 -25
  149. package/src/components/slides/minimap.tsx +7 -3
  150. package/src/components/slides/slide-cell-view.tsx +3 -3
  151. package/src/components/sort/SortableCellsProvider.tsx +2 -1
  152. package/src/core/ai/__tests__/staged-cells.test.ts +18 -20
  153. package/src/core/ai/staged-cells.ts +8 -16
  154. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +2 -2
  155. package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +2 -2
  156. package/src/core/ai/tools/base.ts +2 -2
  157. package/src/core/ai/tools/edit-notebook-tool.ts +13 -21
  158. package/src/core/cells/__tests__/actions.test.ts +474 -34
  159. package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
  160. package/src/core/cells/__tests__/cells.test.ts +251 -861
  161. package/src/core/cells/__tests__/document.test.ts +42 -38
  162. package/src/core/cells/__tests__/notebook-outline.test.ts +7 -1
  163. package/src/core/cells/__tests__/outputs.test.tsx +71 -53
  164. package/src/core/cells/actions.ts +391 -3
  165. package/src/core/cells/add-missing-import.ts +46 -42
  166. package/src/core/cells/cells.ts +73 -444
  167. package/src/core/cells/document.ts +38 -6
  168. package/src/core/cells/outputs.ts +12 -28
  169. package/src/core/codemirror/cells/extensions.ts +6 -6
  170. package/src/core/codemirror/cells/state.ts +1 -1
  171. package/src/core/codemirror/keymaps/vim.ts +2 -2
  172. package/src/core/edit-app.tsx +20 -25
  173. package/src/core/islands/__tests__/bootstrap.test.ts +56 -0
  174. package/src/core/islands/__tests__/bridge.test.ts +42 -0
  175. package/src/core/islands/bootstrap.ts +24 -1
  176. package/src/core/islands/bridge.ts +46 -5
  177. package/src/core/kernel/__tests__/handlers.test.ts +7 -153
  178. package/src/core/kernel/handlers.ts +18 -59
  179. package/src/core/network/__tests__/requests-lazy.test.ts +1 -3
  180. package/src/core/network/requests-lazy.ts +0 -2
  181. package/src/core/network/requests-network.ts +0 -16
  182. package/src/core/network/requests-static.ts +0 -2
  183. package/src/core/network/requests-toasting.tsx +0 -2
  184. package/src/core/network/types.ts +0 -7
  185. package/src/core/notebook/document/__tests__/codemirror.test.ts +5 -0
  186. package/src/core/notebook/document/__tests__/draft.test.ts +41 -0
  187. package/src/core/notebook/document/__tests__/state.test.ts +21 -0
  188. package/src/core/notebook/document/draft.ts +35 -5
  189. package/src/core/notebook/document/index.ts +1 -0
  190. package/src/core/notebook/document/state.ts +6 -2
  191. package/src/core/run-app.tsx +1 -7
  192. package/src/core/session/__tests__/useNotebookSession.hook.test.tsx +0 -6
  193. package/src/core/session/useNotebookSession.tsx +28 -35
  194. package/src/core/wasm/bridge.ts +0 -16
  195. package/src/css/globals.css +56 -22
  196. package/src/stories/runtime-story.tsx +22 -15
@@ -11,11 +11,7 @@ import { Spinner } from "@/components/icons/spinner";
11
11
  import { buttonVariants } from "@/components/ui/button";
12
12
  import { cn } from "@/utils/cn";
13
13
  import { CellsRenderer } from "../components/editor/renderers/cells-renderer";
14
- import {
15
- hasCellsAtom,
16
- notebookIsRunningAtom,
17
- useCellActions,
18
- } from "./cells/cells";
14
+ import { hasCellsAtom, notebookIsRunningAtom } from "./cells/cells";
19
15
  import type { AppConfig } from "./config/config-schema";
20
16
  import { DocumentProvider } from "./notebook/document";
21
17
  import { RuntimeState } from "./kernel/RuntimeState";
@@ -41,7 +37,6 @@ const canPaintRunAppAtom = atom(
41
37
  );
42
38
 
43
39
  export const RunApp: React.FC<AppProps> = ({ appConfig, hideHeader }) => {
44
- const { setCells } = useCellActions();
45
40
  const { sendComponentValues } = useRequestClient();
46
41
 
47
42
  // Initialize RuntimeState event-listeners
@@ -54,7 +49,6 @@ export const RunApp: React.FC<AppProps> = ({ appConfig, hideHeader }) => {
54
49
 
55
50
  const { connection, reconnect, documentModel } = useNotebookSession({
56
51
  autoInstantiate: true,
57
- setCells: setCells,
58
52
  sessionId: getSessionId(),
59
53
  });
60
54
 
@@ -159,7 +159,6 @@ function renderConnectionHook(
159
159
  useNotebookSession({
160
160
  sessionId: SESSION_ID,
161
161
  autoInstantiate: false,
162
- setCells: vi.fn(),
163
162
  }),
164
163
  { wrapper, reactStrictMode },
165
164
  );
@@ -334,10 +333,6 @@ it.each(["kernel-ready", "reconnected"])(
334
333
  act(() =>
335
334
  conn.send({
336
335
  op,
337
- cell_ids: [],
338
- codes: [],
339
- names: [],
340
- configs: [],
341
336
  layout: null,
342
337
  resumed: true,
343
338
  ui_values: {},
@@ -367,7 +362,6 @@ describe("connection notice", () => {
367
362
  const { reconnect } = useNotebookSession({
368
363
  sessionId: SESSION_ID,
369
364
  autoInstantiate: false,
370
- setCells: vi.fn(),
371
365
  });
372
366
  return (
373
367
  <ConnectionNotice
@@ -5,7 +5,12 @@ import { useAtom, useAtomValue, useSetAtom, useStore } from "jotai";
5
5
  import { useEffect, useLayoutEffect, useMemo } from "react";
6
6
  import { useErrorBoundary } from "react-error-boundary";
7
7
  import { toast } from "@/components/ui/use-toast";
8
- import { getNotebook, useCellActions } from "@/core/cells/cells";
8
+ import {
9
+ getNotebook,
10
+ notebookAtom,
11
+ useReducerActions,
12
+ } from "@/core/cells/cells";
13
+ import { followDocument } from "@/core/cells/document";
9
14
  import { AUTOCOMPLETER } from "@/core/codemirror/completion/Autocompleter";
10
15
  import { createDocumentModel } from "@/core/notebook/document";
11
16
  import type { NotificationPayload } from "@/core/kernel/messages";
@@ -22,14 +27,13 @@ import { Logger } from "@/utils/Logger";
22
27
  import { reloadSafe } from "@/utils/reload-safe";
23
28
  import { useAlertActions } from "../alerts/state";
24
29
  import { cacheInfoAtom } from "../cache/requests";
25
- import { SCRATCH_CELL_ID } from "../cells/ids";
26
30
  import { useRunsActions } from "../cells/runs";
27
31
  import { focusAndScrollCellOutputIntoView } from "../cells/scrollCellIntoView";
28
32
  import {
29
33
  resyncBreakpoints,
30
34
  setActiveLine,
31
35
  } from "../codemirror/cells/debugger-state";
32
- import type { CellData } from "../cells/types";
36
+ import { notebookCells } from "../cells/utils";
33
37
  import { capabilitiesAtom } from "../config/capabilities";
34
38
  import { connectionTransportTypeAtom, useSetAppConfig } from "../config/config";
35
39
  import { useDataSourceActions } from "../datasets/data-source-connections";
@@ -75,30 +79,23 @@ import type { VariableName } from "../variables/types";
75
79
  import { activeDocumentModelAtom } from "./active-notebook";
76
80
  import { WebSocketClosedReason, ConnectionState } from "./types";
77
81
 
78
- const SUPPORTS_LAZY_KERNELS = true;
79
-
80
- function getExistingCells(): CellData[] | undefined {
81
- if (!SUPPORTS_LAZY_KERNELS) {
82
- return undefined;
83
- }
84
-
85
- // Remove scratch pad
86
- return Object.values(getNotebook().cellData).filter(
87
- (cell) => cell.id !== SCRATCH_CELL_ID,
88
- );
89
- }
90
-
91
82
  /** Coordinate session startup and apply notifications to the editor. */
92
83
  export function useNotebookSession(opts: {
93
84
  sessionId: SessionId;
94
85
  autoInstantiate: boolean;
95
- setCells: (cells: CellData[], layout: LayoutState) => void;
86
+ /** Called with the layout the kernel reported, after its cells are ready. */
87
+ onKernelReady?: (layout: LayoutState) => void;
96
88
  }) {
97
- const { autoInstantiate, sessionId, setCells } = opts;
89
+ const { autoInstantiate, sessionId, onKernelReady } = opts;
98
90
  const { showBoundary } = useErrorBoundary();
91
+ const store = useStore();
99
92
 
100
- const { handleCellMessage } = useCellActions();
101
- const { reconcileDocument } = useCellActions({ skipMiddleware: true });
93
+ const {
94
+ handleCellMessage,
95
+ reconcileDocument,
96
+ setLastRun,
97
+ resetCellRuntimes,
98
+ } = useReducerActions();
102
99
  const { addCellNotification } = useRunsActions();
103
100
  const setKernelState = useSetAtom(kernelStateAtom);
104
101
  const setInitialRunCompleted = useSetAtom(initialRunCompletedAtom);
@@ -153,18 +150,18 @@ export function useNotebookSession(opts: {
153
150
  setInitialRunCompleted(
154
151
  Boolean(msg.data.resumed || msg.data.auto_instantiated),
155
152
  );
156
- const existingCells = getExistingCells();
157
-
158
- handleKernelReady(msg.data, {
153
+ const layout = handleKernelReady(msg.data, {
159
154
  autoInstantiate,
160
- setCells,
155
+ cells: notebookCells(store.get(notebookAtom)),
156
+ setLastRun,
157
+ resetCellRuntimes,
161
158
  setLayoutData,
162
159
  setAppConfig,
163
160
  setCapabilities,
164
161
  setKernelState,
165
162
  onError: showBoundary,
166
- existingCells,
167
163
  });
164
+ onKernelReady?.(layout);
168
165
  if (!msg.data.resumed) {
169
166
  // A freshly started kernel may expose a different environment
170
167
  // (e.g. new env vars); re-run discovery instead of reusing stale
@@ -393,7 +390,6 @@ export function useNotebookSession(opts: {
393
390
  }
394
391
  };
395
392
 
396
- const store = useStore();
397
393
  const onMessageError = (error: unknown) => {
398
394
  toast({
399
395
  title: "Failed to handle message",
@@ -443,16 +439,13 @@ export function useNotebookSession(opts: {
443
439
  const controller = new AbortController();
444
440
  documentModel.start({ signal: controller.signal });
445
441
  store.set(activeDocumentModelAtom, documentModel);
446
- const follow = () => {
447
- const document = store.get(documentModel.documentAtom);
448
- if (document !== null) {
449
- reconcileDocument(document);
450
- }
451
- };
452
- const unsubscribe = store.sub(documentModel.documentAtom, follow);
453
- follow();
442
+ followDocument({
443
+ store,
444
+ model: documentModel,
445
+ reconcile: reconcileDocument,
446
+ signal: controller.signal,
447
+ });
454
448
  return () => {
455
- unsubscribe();
456
449
  controller.abort();
457
450
  if (store.get(activeDocumentModelAtom) === documentModel) {
458
451
  store.set(activeDocumentModelAtom, null);
@@ -345,14 +345,6 @@ export class PyodideBridge implements RunRequests, EditRequests {
345
345
  return response as FormatResponse;
346
346
  };
347
347
 
348
- public sendDeleteCell: EditRequests["sendDeleteCell"] = async (request) => {
349
- await this.putControlRequest({
350
- type: "delete-cell",
351
- ...request,
352
- });
353
- return null;
354
- };
355
-
356
348
  public sendInstallMissingPackages: EditRequests["sendInstallMissingPackages"] =
357
349
  async (request) => {
358
350
  this.putControlRequest({
@@ -403,14 +395,6 @@ export class PyodideBridge implements RunRequests, EditRequests {
403
395
  return null;
404
396
  };
405
397
 
406
- public saveCellConfig: EditRequests["saveCellConfig"] = async (request) => {
407
- await this.putControlRequest({
408
- type: "update-cell-config",
409
- ...request,
410
- });
411
- return null;
412
- };
413
-
414
398
  public sendRestart = async (): Promise<null> => {
415
399
  // Save first
416
400
  const code = await this.readCode();
@@ -55,21 +55,29 @@
55
55
  --background: light-dark(hsl(0deg 0% 100%), hsl(150deg 7.7% 10.2%));
56
56
  --foreground: light-dark(hsl(222.2deg 47.4% 11.2%), hsl(155deg 7% 93%));
57
57
  --muted: light-dark(hsl(210deg 40% 96.1%), hsl(180deg 14% 1%));
58
- --muted-foreground: light-dark(hsl(215.4deg 16.3% 46.9%),
59
- hsl(155deg 5% 68.3%));
58
+ --muted-foreground: light-dark(
59
+ hsl(215.4deg 16.3% 46.9%),
60
+ hsl(155deg 5% 68.3%)
61
+ );
60
62
  --popover: light-dark(hsl(0deg 0% 100%), hsl(151deg 5.5% 15.2%));
61
- --popover-foreground: light-dark(hsl(222.2deg 47.4% 11.2%),
62
- hsl(155deg 5% 68.3%));
63
+ --popover-foreground: light-dark(
64
+ hsl(222.2deg 47.4% 11.2%),
65
+ hsl(155deg 5% 68.3%)
66
+ );
63
67
  --card: light-dark(hsl(0deg 0% 100%), hsl(151deg 5.5% 15.2%));
64
- --card-foreground: light-dark(hsl(222.2deg 47.4% 11.2%),
65
- hsl(155deg 5% 76.3%));
68
+ --card-foreground: light-dark(
69
+ hsl(222.2deg 47.4% 11.2%),
70
+ hsl(155deg 5% 76.3%)
71
+ );
66
72
  --border: light-dark(hsl(214.3deg 31.8% 91.4%), hsl(153deg 3.7% 24.2%));
67
73
  --input: light-dark(hsl(0deg 0% 64%), hsl(154deg 3.3% 28.7%));
68
74
  --primary: light-dark(hsl(208deg 93.5% 47.4%), hsl(192deg 59.8% 39%));
69
75
  --primary-foreground: light-dark(hsl(210deg 40% 98%), hsl(190deg 80% 84%));
70
76
  --secondary: light-dark(hsl(210deg 40% 96.1%), hsl(155deg 7% 93%));
71
- --secondary-foreground: light-dark(hsl(222.2deg 47.4% 11.2%),
72
- hsl(151deg 5.5% 15.2%));
77
+ --secondary-foreground: light-dark(
78
+ hsl(222.2deg 47.4% 11.2%),
79
+ hsl(151deg 5.5% 15.2%)
80
+ );
73
81
  --accent: light-dark(hsl(209deg 100% 96.5%), hsl(192deg 56.6% 26.5%));
74
82
  --accent-foreground: light-dark(hsl(211deg 90% 42%), hsl(190deg 80% 84%));
75
83
  --ring: hsl(215deg 20.2% 65.1%);
@@ -101,8 +109,10 @@
101
109
 
102
110
  /* Base shadows. */
103
111
  --base-shadow: light-dark(hsl(0deg 0% 85% / 40%), hsla(0deg 0% 36% / 60%));
104
- --base-shadow-darker: light-dark(hsl(0deg 0% 50% / 40%),
105
- hsl(0deg 0% 50% / 60%));
112
+ --base-shadow-darker: light-dark(
113
+ hsl(0deg 0% 50% / 40%),
114
+ hsl(0deg 0% 50% / 60%)
115
+ );
106
116
  --base-shadow-opacity: 5%;
107
117
 
108
118
  /* Codemirror editor */
@@ -219,40 +229,64 @@
219
229
  --shadow-xxs: 0px 0px 2px 0px var(--base-shadow-darker);
220
230
 
221
231
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
222
- --shadow-xs: 1px 1px 2px 0px var(--base-shadow), 0px 0px 2px 0px hsl(0deg 0% 25% / var(--base-shadow-opacity));
232
+ --shadow-xs:
233
+ 1px 1px 2px 0px var(--base-shadow),
234
+ 0px 0px 2px 0px hsl(0deg 0% 25% / var(--base-shadow-opacity));
223
235
 
224
236
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
225
- --shadow-sm: 2px 2px 2px 0px var(--base-shadow), 0px 0px 2px 0px hsl(0deg 0% 25% / var(--base-shadow-opacity));
237
+ --shadow-sm:
238
+ 2px 2px 2px 0px var(--base-shadow),
239
+ 0px 0px 2px 0px hsl(0deg 0% 25% / var(--base-shadow-opacity));
226
240
 
227
241
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
228
- --shadow-md: 4px 4px 4px 0px var(--base-shadow), 0 0px 4px 0px hsl(0deg 0% 60% / var(--base-shadow-opacity));
242
+ --shadow-md:
243
+ 4px 4px 4px 0px var(--base-shadow),
244
+ 0 0px 4px 0px hsl(0deg 0% 60% / var(--base-shadow-opacity));
229
245
 
230
246
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
231
- --shadow-lg: 5px 6px 4px 0px var(--base-shadow), 0 0px 4px 0px hsl(0deg 0% 75% / var(--base-shadow-opacity));
247
+ --shadow-lg:
248
+ 5px 6px 4px 0px var(--base-shadow),
249
+ 0 0px 4px 0px hsl(0deg 0% 75% / var(--base-shadow-opacity));
232
250
 
233
251
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
234
- --shadow-xl: 8px 9px 4px 0px var(--base-shadow), 0 0px 6px 0px hsl(0deg 0% 85% / var(--base-shadow-opacity));
252
+ --shadow-xl:
253
+ 8px 9px 4px 0px var(--base-shadow),
254
+ 0 0px 6px 0px hsl(0deg 0% 85% / var(--base-shadow-opacity));
235
255
 
236
256
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
237
- --shadow-2xl: 10px 12px 10px 0px var(--base-shadow), 0 0px 8px 0px hsl(0deg 0% 90% / var(--base-shadow-opacity));
257
+ --shadow-2xl:
258
+ 10px 12px 10px 0px var(--base-shadow),
259
+ 0 0px 8px 0px hsl(0deg 0% 90% / var(--base-shadow-opacity));
238
260
 
239
261
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
240
- --shadow-xs-solid: 1px 1px 0px 0px var(--base-shadow-darker), 0px 0px 2px 0px hsl(0deg 0% 50% / 20%);
262
+ --shadow-xs-solid:
263
+ 1px 1px 0px 0px var(--base-shadow-darker),
264
+ 0px 0px 2px 0px hsl(0deg 0% 50% / 20%);
241
265
 
242
266
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
243
- --shadow-sm-solid: 2px 2px 0px 0px var(--base-shadow-darker), 0px 0px 2px 0px hsl(0deg 0% 50% / 20%);
267
+ --shadow-sm-solid:
268
+ 2px 2px 0px 0px var(--base-shadow-darker),
269
+ 0px 0px 2px 0px hsl(0deg 0% 50% / 20%);
244
270
 
245
271
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
246
- --shadow-md-solid: 4px 4px 0px 0px var(--base-shadow-darker), 0 0px 2px 0px hsl(0deg 0% 60% / 50%);
272
+ --shadow-md-solid:
273
+ 4px 4px 0px 0px var(--base-shadow-darker),
274
+ 0 0px 2px 0px hsl(0deg 0% 60% / 50%);
247
275
 
248
276
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
249
- --shadow-lg-solid: 5px 6px 0px 0px var(--base-shadow-darker), 0 0px 4px 0px hsl(0deg 0% 75% / 50%);
277
+ --shadow-lg-solid:
278
+ 5px 6px 0px 0px var(--base-shadow-darker),
279
+ 0 0px 4px 0px hsl(0deg 0% 75% / 50%);
250
280
 
251
281
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
252
- --shadow-xl-solid: 7px 8px 0px 0px var(--base-shadow-darker), 0 0px 4px 0px hsl(0deg 0% 85% / 50%);
282
+ --shadow-xl-solid:
283
+ 7px 8px 0px 0px var(--base-shadow-darker),
284
+ 0 0px 4px 0px hsl(0deg 0% 85% / 50%);
253
285
 
254
286
  /* oxfmt-ignore: definition needs to be oneline or breaks variants */
255
- --shadow-2xl-solid: 10px 12px 0px 0px var(--base-shadow-darker), 0 0px 8px 0px hsl(0deg 0% 90% / 50%);
287
+ --shadow-2xl-solid:
288
+ 10px 12px 0px 0px var(--base-shadow-darker),
289
+ 0 0px 8px 0px hsl(0deg 0% 90% / 50%);
256
290
 
257
291
  /* Solid shadows with lighter shade color */
258
292
 
@@ -1,7 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import type { Meta } from "@storybook/react-vite";
3
3
  import { createStore, Provider, useAtomValue, useStore } from "jotai";
4
- import { useEffect, useRef, useState } from "react";
4
+ import { createRef, useEffect, useRef, useState } from "react";
5
5
  import { Button } from "@/components/ui/button";
6
6
  import { ConnectionNotice } from "@/components/editor/alerts/connection-notice";
7
7
  import PackagesPanel from "@/components/editor/chrome/panels/packages-panel";
@@ -13,11 +13,10 @@ import { Cell } from "@/components/editor/notebook-cell";
13
13
  import { VerticalLayoutWrapper } from "@/components/editor/renderers/vertical-layout/vertical-layout-wrapper";
14
14
  import { alertAtom } from "@/core/alerts/state";
15
15
  import type { EnvironmentOperation } from "@/core/alerts/environment";
16
- import {
17
- createNotebookActions,
18
- notebookAtom,
19
- notebookReducer,
20
- } from "@/core/cells/cells";
16
+ import { notebookAtom } from "@/core/cells/cells";
17
+ import { CellId } from "@/core/cells/ids";
18
+ import { createCell, createCellRuntimeState } from "@/core/cells/types";
19
+ import { MultiColumn } from "@/utils/id-tree";
21
20
  import { userConfigAtom } from "@/core/config/config";
22
21
  import {
23
22
  type AppConfig,
@@ -349,15 +348,23 @@ export function RuntimeStory(props: Props) {
349
348
  log_mode: "replace",
350
349
  });
351
350
  if (props.existingCells) {
352
- const actions = createNotebookActions((action) =>
353
- state.set(notebookAtom, (value) => notebookReducer(value, action)),
354
- );
355
- actions.createNewCell({
356
- cellId: "__end__",
357
- before: false,
358
- code: 'import polars as pl\n\ntrips = pl.read_csv("bike_trips.csv")\ntrips.head()',
359
- autoFocus: false,
360
- });
351
+ const cellId = CellId.create();
352
+ state.set(notebookAtom, (value) => ({
353
+ ...value,
354
+ cellIds: MultiColumn.from([[cellId]]),
355
+ cellData: {
356
+ ...value.cellData,
357
+ [cellId]: createCell({
358
+ id: cellId,
359
+ code: 'import polars as pl\n\ntrips = pl.read_csv("bike_trips.csv")\ntrips.head()',
360
+ }),
361
+ },
362
+ cellRuntime: {
363
+ ...value.cellRuntime,
364
+ [cellId]: createCellRuntimeState(),
365
+ },
366
+ cellHandles: { ...value.cellHandles, [cellId]: createRef() },
367
+ }));
361
368
  }
362
369
  state.set(requestClientAtom, {
363
370
  ...createStaticRequests(),