@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
@@ -37,8 +37,10 @@ import { Label } from "@/components/ui/label";
37
37
  import { toast } from "@/components/ui/use-toast";
38
38
  import { aiCompletionCellAtom } from "@/core/ai/state";
39
39
  import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
40
- import { hasOnlyOneCellAtom, useCellActions } from "@/core/cells/cells";
40
+ import { hasOnlyOneCellAtom } from "@/core/cells/cells";
41
+ import { useCellActions } from "@/core/cells/actions";
41
42
  import { type CellId, SETUP_CELL_ID } from "@/core/cells/ids";
43
+ import { useNotebookDocumentEdit } from "@/core/notebook/document";
42
44
  import type { CellData } from "@/core/cells/types";
43
45
  import { formatEditorViews } from "@/core/codemirror/format";
44
46
  import {
@@ -53,7 +55,6 @@ import {
53
55
  autoInstantiateAtom,
54
56
  } from "@/core/config/config";
55
57
  import { kioskModeAtom } from "@/core/mode";
56
- import { useRequestClient } from "@/core/network/requests";
57
58
  import type { CellConfig, RuntimeState } from "@/core/network/types";
58
59
  import { canLinkToCell, createCellLink } from "@/utils/cell-urls";
59
60
  import { copyToClipboard } from "@/utils/copy";
@@ -83,16 +84,15 @@ interface Props {
83
84
 
84
85
  export function useCellActionButtons({ cell, closePopover }: Props) {
85
86
  const {
86
- createNewCell: createCell,
87
- updateCellConfig,
88
- updateCellName,
89
87
  moveCell,
90
88
  sendToTop,
91
89
  sendToBottom,
92
90
  addColumnBreakpoint,
93
91
  clearCellOutput,
94
92
  markUntouched,
93
+ createCell,
95
94
  } = useCellActions();
95
+ const edit = useNotebookDocumentEdit();
96
96
  const splitCell = useSplitCellCallback();
97
97
  const runCell = useRunCell(cell?.cellId);
98
98
  const hasOnlyOneCell = useAtomValue(hasOnlyOneCellAtom);
@@ -104,7 +104,6 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
104
104
  const autoInstantiate = useAtomValue(autoInstantiateAtom);
105
105
  const kioskMode = useAtomValue(kioskModeAtom);
106
106
  const appWidth = useAtomValue(appWidthAtom);
107
- const { saveCellConfig } = useRequestClient();
108
107
 
109
108
  if (!cell || kioskMode) {
110
109
  return [];
@@ -120,16 +119,13 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
120
119
  status,
121
120
  } = cell;
122
121
 
123
- const toggleDisabled = async () => {
124
- const newConfig = { disabled: !config.disabled };
125
- await saveCellConfig({ configs: { [cellId]: newConfig } });
126
- updateCellConfig({ cellId, config: newConfig });
122
+ const toggleDisabled = () => {
123
+ edit((tx) => tx.updateConfig(cellId, { disabled: !config.disabled }));
127
124
  };
128
125
 
129
- const toggleHideCode = async () => {
126
+ const toggleHideCode = () => {
130
127
  const newConfig: Partial<CellConfig> = { hide_code: !config.hide_code };
131
- await saveCellConfig({ configs: { [cellId]: newConfig } });
132
- updateCellConfig({ cellId, config: newConfig });
128
+ edit((tx) => tx.updateConfig(cellId, newConfig));
133
129
  const editorView = getEditorView();
134
130
  // If we're hiding the code, we should blur the editor
135
131
  // otherwise, we should focus it
@@ -221,20 +217,18 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
221
217
  if (!editorView) {
222
218
  return;
223
219
  }
224
- maybeAddMarimoImport({ autoInstantiate, createNewCell: createCell });
220
+ maybeAddMarimoImport({ autoInstantiate, createCell });
225
221
  switchLanguage(editorView, {
226
222
  language: "markdown",
227
223
  keepCodeAsIs: false,
228
224
  });
229
225
  // Code stays visible until the user blurs the cell
230
226
  if (!config.hide_code && MARKDOWN_INITIAL_HIDE_CODE) {
231
- await saveCellConfig({
232
- configs: { [cellId]: { hide_code: MARKDOWN_INITIAL_HIDE_CODE } },
233
- });
234
- updateCellConfig({
235
- cellId,
236
- config: { hide_code: MARKDOWN_INITIAL_HIDE_CODE },
237
- });
227
+ edit((tx) =>
228
+ tx.updateConfig(cellId, {
229
+ hide_code: MARKDOWN_INITIAL_HIDE_CODE,
230
+ }),
231
+ );
238
232
  markUntouched({ cellId });
239
233
  }
240
234
  },
@@ -266,7 +260,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
266
260
  }
267
261
  maybeAddMarimoImport({
268
262
  autoInstantiate,
269
- createNewCell: createCell,
263
+ createCell,
270
264
  });
271
265
  switchLanguage(editorView, {
272
266
  language: "sql",
@@ -288,7 +282,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
288
282
  ),
289
283
  label: "Create cell above",
290
284
  hotkey: "cell.createAbove",
291
- handle: () => createCell({ cellId, before: true }),
285
+ handle: () => createCell({ before: cellId }),
292
286
  hidden: isSetupCell,
293
287
  redundant: true,
294
288
  },
@@ -301,7 +295,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
301
295
  ),
302
296
  label: "Create cell below",
303
297
  hotkey: "cell.createBelow",
304
- handle: () => createCell({ cellId, before: false }),
298
+ handle: () => createCell({ after: cellId }),
305
299
  redundant: true,
306
300
  },
307
301
  {
@@ -406,7 +400,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
406
400
  }
407
401
  }}
408
402
  onChange={(newName) =>
409
- updateCellName({ cellId, name: newName })
403
+ edit((tx) => tx.setName(cellId, newName))
410
404
  }
411
405
  />
412
406
  </div>
@@ -417,7 +411,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
417
411
  <NameCellInput
418
412
  placeholder={"cell name"}
419
413
  value={name}
420
- onChange={(newName) => updateCellName({ cellId, name: newName })}
414
+ onChange={(newName) => edit((tx) => tx.setName(cellId, newName))}
421
415
  onEnterKey={() => closePopover?.()}
422
416
  />
423
417
  ),
@@ -62,8 +62,9 @@ import {
62
62
  getNotebook,
63
63
  hasDisabledCellsAtom,
64
64
  undoLabelAtom,
65
- useCellActions,
66
65
  } from "@/core/cells/cells";
66
+ import { useCellActions } from "@/core/cells/actions";
67
+ import { useNotebookDocumentEdit } from "@/core/notebook/document";
67
68
  import { disabledCellIds } from "@/core/cells/utils";
68
69
  import { capabilitiesAtom } from "@/core/config/capabilities";
69
70
  import { aiEnabledAtom, useResolvedMarimoConfig } from "@/core/config/config";
@@ -77,7 +78,6 @@ import { createShareableLink } from "@/core/wasm/share";
77
78
  import { isWasm } from "@/core/wasm/utils";
78
79
  import { useDetectedDataSources } from "@/hooks/useDataSourceDiscovery";
79
80
  import { copyToClipboard } from "@/utils/copy";
80
- import { Objects } from "@/utils/objects";
81
81
  import { Strings } from "@/utils/strings";
82
82
  import { newNotebookURL } from "@/utils/urls";
83
83
  import { useRunAllCells } from "../cell/useRunCells";
@@ -127,12 +127,11 @@ export function useNotebookActions({
127
127
  const aiEnabled = useAtomValue(aiEnabledAtom);
128
128
 
129
129
  const {
130
- updateCellConfig,
131
130
  undoDeleteCell,
132
131
  clearAllCellOutputs,
133
- addSetupCellIfDoesntExist,
134
132
  collapseAllCells,
135
133
  expandAllCells,
134
+ addSetupCell,
136
135
  } = useCellActions();
137
136
  const restartKernel = useRestartKernel();
138
137
  const runAllCells = useRunAllCells();
@@ -142,7 +141,8 @@ export function useNotebookActions({
142
141
  const { handleClick: openSettings } = useOpenSettingsToTab();
143
142
  const setKeyboardShortcutsOpen = useSetAtom(keyboardShortcutsAtom);
144
143
  const setExportOptions = useSetAtom(exportOptionsAtom);
145
- const { readCode, saveCellConfig } = useRequestClient();
144
+ const { readCode } = useRequestClient();
145
+ const edit = useNotebookDocumentEdit();
146
146
  const detectedDatabaseSources = useDetectedDataSources("database");
147
147
  const detectedStorageSources = useDetectedDataSources("storage");
148
148
  const addDetectedDataSource = useAddDetectedDataSource();
@@ -449,18 +449,13 @@ export function useNotebookActions({
449
449
  icon: <ZapIcon size={14} strokeWidth={1.5} />,
450
450
  label: "Enable all cells",
451
451
  hidden: !hasDisabledCells || kioskMode,
452
- handle: async () => {
453
- const notebook = getNotebook();
454
- const ids = disabledCellIds(notebook);
455
- const newConfigs = Objects.fromEntries(
456
- ids.map((cellId) => [cellId, { disabled: false }]),
457
- );
458
- // send to BE
459
- await saveCellConfig({ configs: newConfigs });
460
- // update on FE
461
- for (const cellId of ids) {
462
- updateCellConfig({ cellId, config: { disabled: false } });
463
- }
452
+ handle: () => {
453
+ const ids = disabledCellIds(getNotebook());
454
+ edit((tx) => {
455
+ for (const cellId of ids) {
456
+ tx.updateConfig(cellId, { disabled: false });
457
+ }
458
+ });
464
459
  },
465
460
  },
466
461
 
@@ -469,7 +464,7 @@ export function useNotebookActions({
469
464
  icon: <DiamondPlusIcon size={14} strokeWidth={1.5} />,
470
465
  label: "Add setup cell",
471
466
  handle: () => {
472
- addSetupCellIfDoesntExist({});
467
+ addSetupCell();
473
468
  },
474
469
  },
475
470
  {
@@ -1,10 +1,10 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { useCallback } from "react";
4
- import { getNotebook, useCellActions } from "@/core/cells/cells";
4
+ import { getNotebook } from "@/core/cells/cells";
5
5
  import type { CellId } from "@/core/cells/ids";
6
6
  import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
7
- import { useRequestClient } from "@/core/network/requests";
7
+ import { useNotebookDocumentEdit } from "@/core/notebook/document";
8
8
  import type { CellConfig } from "@/core/network/types";
9
9
  import { Objects } from "@/utils/objects";
10
10
 
@@ -21,11 +21,10 @@ const cellCodeKind = (code: string): CellCodeKind =>
21
21
  * cell of the given kind.
22
22
  */
23
23
  export const useSetCodeVisibility = () => {
24
- const { updateCellConfig } = useCellActions();
25
- const { saveCellConfig } = useRequestClient();
24
+ const edit = useNotebookDocumentEdit();
26
25
 
27
26
  return useCallback(
28
- async (hidden: boolean, kind: CellCodeKind) => {
27
+ (hidden: boolean, kind: CellCodeKind) => {
29
28
  const notebook = getNotebook();
30
29
 
31
30
  const newConfigs: Record<CellId, Partial<CellConfig>> = {};
@@ -46,12 +45,12 @@ export const useSetCodeVisibility = () => {
46
45
  return;
47
46
  }
48
47
 
49
- await saveCellConfig({ configs: newConfigs });
50
-
51
- for (const [cellId, config] of entries) {
52
- updateCellConfig({ cellId, config });
53
- }
48
+ edit((tx) => {
49
+ for (const [cellId, config] of entries) {
50
+ tx.updateConfig(cellId, config);
51
+ }
52
+ });
54
53
  },
55
- [updateCellConfig, saveCellConfig],
54
+ [edit],
56
55
  );
57
56
  };
@@ -1,14 +1,10 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { useCallback } from "react";
4
- import {
5
- getNotebook,
6
- type NotebookState,
7
- useCellActions,
8
- } from "@/core/cells/cells";
4
+ import { getNotebook, type NotebookState } from "@/core/cells/cells";
9
5
  import type { CellId } from "@/core/cells/ids";
10
6
  import { isOutputEmpty } from "@/core/cells/outputs";
11
- import { useRequestClient } from "@/core/network/requests";
7
+ import { useNotebookDocumentEdit } from "@/core/notebook/document";
12
8
  import type { CellConfig } from "@/core/network/types";
13
9
  import { Objects } from "@/utils/objects";
14
10
 
@@ -44,24 +40,23 @@ export function outputExpansionConfigs(
44
40
  * every output to a fixed height, by setting each cell's `expand_output` config.
45
41
  */
46
42
  export const useSetOutputsExpanded = () => {
47
- const { updateCellConfig } = useCellActions();
48
- const { saveCellConfig } = useRequestClient();
43
+ const edit = useNotebookDocumentEdit();
49
44
 
50
45
  return useCallback(
51
- async (expanded: boolean) => {
52
- const newConfigs = outputExpansionConfigs(getNotebook(), expanded);
53
-
54
- const entries = Objects.entries(newConfigs);
46
+ (expanded: boolean) => {
47
+ const entries = Objects.entries(
48
+ outputExpansionConfigs(getNotebook(), expanded),
49
+ );
55
50
  if (entries.length === 0) {
56
51
  return;
57
52
  }
58
53
 
59
- await saveCellConfig({ configs: newConfigs });
60
-
61
- for (const [cellId, config] of entries) {
62
- updateCellConfig({ cellId, config });
63
- }
54
+ edit((tx) => {
55
+ for (const [cellId, config] of entries) {
56
+ tx.updateConfig(cellId, config);
57
+ }
58
+ });
64
59
  },
65
- [updateCellConfig, saveCellConfig],
60
+ [edit],
66
61
  );
67
62
  };
@@ -10,7 +10,7 @@ import {
10
10
  DropdownMenuTrigger,
11
11
  } from "@/components/ui/dropdown-menu";
12
12
  import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
13
- import { useCellActions } from "@/core/cells/cells";
13
+ import { useCellActions } from "@/core/cells/actions";
14
14
  import { LanguageAdapters } from "@/core/codemirror/language/LanguageAdapters";
15
15
  import { MARKDOWN_INITIAL_HIDE_CODE } from "@/core/codemirror/language/languages/markdown";
16
16
  import {
@@ -33,7 +33,7 @@ export const CreateCellButton = ({
33
33
  onClick: ((opts: { code: string; hideCode?: boolean }) => void) | undefined;
34
34
  oneClickShortcut: "shift" | "mod";
35
35
  }) => {
36
- const { createNewCell, addSetupCellIfDoesntExist } = useCellActions();
36
+ const { createCell, addSetupCell } = useCellActions();
37
37
  const shortcut = `${oneClickShortcut}-Click`;
38
38
  const [open, setOpen] = useState(false);
39
39
  // Time the dropdown last opened, to ignore the click that opened it
@@ -62,7 +62,7 @@ export const CreateCellButton = ({
62
62
  // enabled; the user experience is confusing otherwise (how does the user
63
63
  // know they need to run import marimo as mo. first?).
64
64
  const addMarkdownCell = () => {
65
- maybeAddMarimoImport({ autoInstantiate: true, createNewCell });
65
+ maybeAddMarimoImport({ autoInstantiate: true, createCell });
66
66
  onClick?.({
67
67
  code: LanguageAdapters.markdown.defaultCode,
68
68
  hideCode: MARKDOWN_INITIAL_HIDE_CODE,
@@ -70,14 +70,10 @@ export const CreateCellButton = ({
70
70
  };
71
71
 
72
72
  const addSQLCell = () => {
73
- maybeAddMarimoImport({ autoInstantiate: true, createNewCell });
73
+ maybeAddMarimoImport({ autoInstantiate: true, createCell });
74
74
  onClick?.({ code: LanguageAdapters.sql.defaultCode });
75
75
  };
76
76
 
77
- const addSetupCell = () => {
78
- addSetupCellIfDoesntExist({});
79
- };
80
-
81
77
  const renderIcon = (icon: React.ReactNode) => {
82
78
  return <div className="mr-3 text-muted-foreground">{icon}</div>;
83
79
  };
@@ -170,7 +166,7 @@ export const CreateCellButton = ({
170
166
  {renderIcon(<DatabaseIcon size={13} strokeWidth={1.5} />)}
171
167
  SQL cell
172
168
  </DropdownMenuItem>
173
- <DropdownMenuItem onClick={addSetupCell}>
169
+ <DropdownMenuItem onClick={() => addSetupCell()}>
174
170
  {renderIcon(<DiamondPlusIcon size={13} strokeWidth={1.5} />)}
175
171
  Setup cell
176
172
  </DropdownMenuItem>
@@ -14,8 +14,10 @@ vi.mock("@/components/editor/cell/useDeleteCell", () => ({
14
14
 
15
15
  vi.mock("@/core/cells/cells", () => ({
16
16
  getCellEditorView: vi.fn(),
17
+ }));
18
+ vi.mock("@/core/cells/actions", () => ({
17
19
  useCellActions: () => ({
18
- createNewCell: vi.fn(),
20
+ createCell: vi.fn(),
19
21
  updateCellCode: vi.fn(),
20
22
  }),
21
23
  }));
@@ -10,7 +10,9 @@ import { Button } from "@/components/ui/button";
10
10
  import { DelayMount } from "@/components/utils/delay-mount";
11
11
  import { aiCompletionCellAtom } from "@/core/ai/state";
12
12
  import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
13
- import { getNotebook, useCellActions } from "@/core/cells/cells";
13
+ import { getNotebook } from "@/core/cells/cells";
14
+ import { useCellActions } from "@/core/cells/actions";
15
+ import { useNotebookDocumentEdit } from "@/core/notebook/document";
14
16
  import { SETUP_CELL_ID } from "@/core/cells/ids";
15
17
  import { usePendingDeleteService } from "@/core/cells/pending-delete-service";
16
18
  import type { CellData, CellRuntimeState } from "@/core/cells/types";
@@ -36,7 +38,6 @@ import { autoInstantiateAtom, isAiFeatureEnabled } from "@/core/config/config";
36
38
  import type { UserConfig } from "@/core/config/config-schema";
37
39
  import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
38
40
  import { connectionAtom } from "@/core/network/connection";
39
- import { useRequestClient } from "@/core/network/requests";
40
41
  import { canUseRtc, isRtcEnabled } from "@/core/rtc/state";
41
42
  import { useSaveNotebook } from "@/core/saving/save-component";
42
43
  import { isAppConnecting } from "@/core/session/connection-utils";
@@ -135,7 +136,7 @@ const CellEditorInternal = ({
135
136
  const deleteCell = useDeleteCellCallback();
136
137
  const { saveOrNameNotebook } = useSaveNotebook();
137
138
  const pendingDeleteService = usePendingDeleteService();
138
- const { saveCellConfig } = useRequestClient();
139
+ const edit = useNotebookDocumentEdit();
139
140
 
140
141
  const loading = status === "running" || status === "queued";
141
142
  const cellActions = useCellActions();
@@ -175,9 +176,7 @@ const CellEditorInternal = ({
175
176
  const toggleHideCode = useEvent(() => {
176
177
  // Use cellConfig.hide_code instead of hidden, since it may be temporarily shown
177
178
  const nextHidden = !cellConfig.hide_code;
178
- // Fire-and-forget save
179
- void saveCellConfig({ configs: { [cellId]: { hide_code: nextHidden } } });
180
- cellActions.updateCellConfig({ cellId, config: { hide_code: nextHidden } });
179
+ edit((tx) => tx.updateConfig(cellId, { hide_code: nextHidden }));
181
180
  return nextHidden;
182
181
  });
183
182
 
@@ -186,17 +185,13 @@ const CellEditorInternal = ({
186
185
  const afterToggleMarkdown = useEvent(() => {
187
186
  maybeAddMarimoImport({
188
187
  autoInstantiate,
189
- createNewCell: cellActions.createNewCell,
188
+ createCell: cellActions.createCell,
190
189
  });
191
190
  // Code stays visible until the user blurs the cell
192
191
  if (!cellConfig.hide_code && MARKDOWN_INITIAL_HIDE_CODE) {
193
- void saveCellConfig({
194
- configs: { [cellId]: { hide_code: MARKDOWN_INITIAL_HIDE_CODE } },
195
- });
196
- cellActions.updateCellConfig({
197
- cellId,
198
- config: { hide_code: MARKDOWN_INITIAL_HIDE_CODE },
199
- });
192
+ edit((tx) =>
193
+ tx.updateConfig(cellId, { hide_code: MARKDOWN_INITIAL_HIDE_CODE }),
194
+ );
200
195
  cellActions.markUntouched({ cellId });
201
196
  }
202
197
  });
@@ -204,7 +199,7 @@ const CellEditorInternal = ({
204
199
  const afterToggleSQL = useEvent(() => {
205
200
  maybeAddMarimoImport({
206
201
  autoInstantiate,
207
- createNewCell: cellActions.createNewCell,
202
+ createCell: cellActions.createCell,
208
203
  });
209
204
  });
210
205
 
@@ -224,11 +219,9 @@ const CellEditorInternal = ({
224
219
  saveNotebook: saveOrNameNotebook,
225
220
  createManyBelow: (cells) => {
226
221
  for (const code of cells.toReversed()) {
227
- cellActions.createNewCell({
222
+ cellActions.createCell({
223
+ after: cellId,
228
224
  code,
229
- before: false,
230
- cellId: cellId,
231
- // If the code already exists, skip creation
232
225
  skipIfCodeExists: true,
233
226
  });
234
227
  }
@@ -237,7 +230,7 @@ const CellEditorInternal = ({
237
230
  const notebook = getNotebook();
238
231
  // No setup cell yet: create one with this code at the top.
239
232
  if (!notebook.cellIds.setupCellExists()) {
240
- cellActions.addSetupCellIfDoesntExist({ code });
233
+ cellActions.addSetupCell({ code });
241
234
  return;
242
235
  }
243
236
  // Setup cell exists: append the pasted code to it. Prefer updating
@@ -2,28 +2,24 @@
2
2
 
3
3
  import { useAtomValue } from "jotai";
4
4
  import { maybeAddAltairImport } from "@/core/cells/add-missing-import";
5
- import { useCellActions } from "@/core/cells/cells";
5
+ import { useCellActions } from "@/core/cells/actions";
6
6
  import { useLastFocusedCellId } from "@/core/cells/focus";
7
7
  import { autoInstantiateAtom } from "@/core/config/config";
8
8
 
9
9
  export function useAddCodeToNewCell(): (code: string) => void {
10
10
  const autoInstantiate = useAtomValue(autoInstantiateAtom);
11
11
  const lastFocusedCellId = useLastFocusedCellId();
12
- const { createNewCell } = useCellActions();
12
+ const { createCell } = useCellActions();
13
13
 
14
14
  return (code: string) => {
15
15
  if (code.includes("alt")) {
16
16
  maybeAddAltairImport({
17
17
  autoInstantiate,
18
- createNewCell,
18
+ createCell,
19
19
  fromCellId: lastFocusedCellId,
20
20
  });
21
21
  }
22
22
 
23
- createNewCell({
24
- code: code,
25
- before: false,
26
- cellId: lastFocusedCellId ?? "__end__",
27
- });
23
+ createCell({ after: lastFocusedCellId, code });
28
24
  };
29
25
  }
@@ -3,35 +3,22 @@
3
3
  import useEvent from "react-use-event-hook";
4
4
  import { UndoButton } from "@/components/buttons/undo-button";
5
5
  import { toast } from "@/components/ui/use-toast";
6
- import {
7
- hasOnlyOneCellAtom,
8
- notebookAtom,
9
- useCellActions,
10
- } from "@/core/cells/cells";
6
+ import { useCellActions } from "@/core/cells/actions";
7
+ import { notebookAtom } from "@/core/cells/cells";
11
8
  import type { CellId } from "@/core/cells/ids";
12
- import { useRequestClient } from "@/core/network/requests";
13
9
  import { store } from "@/core/state/jotai";
14
10
 
15
11
  export function useDeleteCellCallback() {
16
- const { deleteCell, undoDeleteCell } = useCellActions();
17
- const { sendDeleteCell } = useRequestClient();
12
+ const { deleteCells, undoDeleteCell } = useCellActions();
18
13
 
19
14
  return useEvent((opts: { cellId: CellId }) => {
20
- // Can't delete the last cell
21
- if (store.get(hasOnlyOneCellAtom)) {
22
- return;
23
- }
24
-
25
15
  const { cellId } = opts;
26
16
  const notebook = store.get(notebookAtom);
27
17
  const isEmptyCell = (notebook.cellData[cellId]?.code ?? "").trim() === "";
28
18
 
29
- // Optimistic update
30
- deleteCell({ cellId });
31
- sendDeleteCell({ cellId: cellId }).catch(() => {
32
- // Fall back on failure
33
- undoDeleteCell();
34
- });
19
+ if (!deleteCells({ cellIds: [cellId] })) {
20
+ return;
21
+ }
35
22
 
36
23
  if (!isEmptyCell) {
37
24
  const { dismiss } = toast({
@@ -53,33 +40,20 @@ export function useDeleteCellCallback() {
53
40
  }
54
41
 
55
42
  export function useDeleteManyCellsCallback() {
56
- const { deleteCell, undoDeleteCell } = useCellActions();
57
- const { sendDeleteCell } = useRequestClient();
43
+ const { deleteCells, undoDeleteCell } = useCellActions();
58
44
 
59
- return useEvent(async (opts: { cellIds: CellId[] }) => {
60
- // Can't delete the last cell
61
- if (store.get(hasOnlyOneCellAtom)) {
45
+ return useEvent((opts: { cellIds: CellId[] }) => {
46
+ if (!deleteCells({ cellIds: opts.cellIds })) {
62
47
  return;
63
48
  }
64
49
 
65
- const { cellIds } = opts;
66
- for (const cellId of cellIds) {
67
- await sendDeleteCell({ cellId }).then(() => {
68
- deleteCell({ cellId });
69
- });
70
- }
71
-
72
50
  const { dismiss } = toast({
73
51
  title: "Cells deleted",
74
52
  action: (
75
53
  <UndoButton
76
54
  data-testid="undo-delete-button"
77
55
  onClick={() => {
78
- for (const _cellId of cellIds) {
79
- // This function does not take a cellId,
80
- // so we just undo the number of cells that were deleted
81
- undoDeleteCell();
82
- }
56
+ undoDeleteCell();
83
57
  dismiss();
84
58
  }}
85
59
  />
@@ -3,11 +3,8 @@
3
3
  import { closeCompletion } from "@codemirror/autocomplete";
4
4
  import { atom, useSetAtom } from "jotai";
5
5
  import useEvent from "react-use-event-hook";
6
- import {
7
- getNotebook,
8
- type NotebookState,
9
- useCellActions,
10
- } from "@/core/cells/cells";
6
+ import { getNotebook, type NotebookState } from "@/core/cells/cells";
7
+ import { useCellActions } from "@/core/cells/actions";
11
8
  import type { CellId } from "@/core/cells/ids";
12
9
  import { enabledCellIds, staleCellIds } from "@/core/cells/utils";
13
10
  import { getCurrentLanguageAdapter } from "@/core/codemirror/language/commands";
@@ -3,7 +3,8 @@
3
3
  import useEvent from "react-use-event-hook";
4
4
  import { UndoButton } from "@/components/buttons/undo-button";
5
5
  import { toast } from "@/components/ui/use-toast";
6
- import { getCellEditorView, useCellActions } from "@/core/cells/cells";
6
+ import { getCellEditorView } from "@/core/cells/cells";
7
+ import { useCellActions } from "@/core/cells/actions";
7
8
  import type { CellId } from "@/core/cells/ids";
8
9
  import { getEditorCodeAsPython } from "@/core/codemirror/language/utils";
9
10
 
@@ -3,7 +3,8 @@
3
3
  import { FileTextIcon } from "lucide-react";
4
4
  import React from "react";
5
5
  import { ClearButton } from "@/components/buttons/clear-button";
6
- import { useCellActions, useCellLogs } from "@/core/cells/cells";
6
+ import { useCellLogs } from "@/core/cells/cells";
7
+ import { useCellActions } from "@/core/cells/actions";
7
8
  import {
8
9
  type CellLog,
9
10
  formatLogTimestamp,
@@ -22,7 +22,7 @@ import { Suspense } from "react";
22
22
  import { Spinner } from "@/components/icons/spinner";
23
23
  import { Button } from "@/components/ui/button";
24
24
  import { Tooltip } from "@/components/ui/tooltip";
25
- import { useCellActions } from "@/core/cells/cells";
25
+ import { useCellActions } from "@/core/cells/actions";
26
26
  import { useLastFocusedCellId } from "@/core/cells/focus";
27
27
  import { useRequestClient } from "@/core/network/requests";
28
28
  import { LazyAnyLanguageCodeMirror } from "@/plugins/impl/code/LazyAnyLanguageCodeMirror";
@@ -125,18 +125,16 @@ const SnippetViewer: React.FC<{ snippet: Snippet; onClose: () => void }> = ({
125
125
  onClose,
126
126
  }) => {
127
127
  const { theme } = useTheme();
128
- const { createNewCell } = useCellActions();
128
+ const { createCell } = useCellActions();
129
129
  const lastFocusedCellId = useLastFocusedCellId();
130
130
 
131
131
  const handleInsertSnippet = () => {
132
132
  // Add below last focused cell in reverse order
133
133
  for (const section of snippet.sections.toReversed()) {
134
134
  if (section.code) {
135
- createNewCell({
135
+ createCell({
136
+ after: lastFocusedCellId,
136
137
  code: section.code,
137
- before: false,
138
- cellId: lastFocusedCellId ?? "__end__",
139
- // If the code already exists, skip creation
140
138
  skipIfCodeExists: true,
141
139
  });
142
140
  }
@@ -144,11 +142,7 @@ const SnippetViewer: React.FC<{ snippet: Snippet; onClose: () => void }> = ({
144
142
  };
145
143
 
146
144
  const handleInsertCode = (code: string) => {
147
- createNewCell({
148
- code,
149
- before: false,
150
- cellId: lastFocusedCellId ?? "__end__",
151
- });
145
+ createCell({ after: lastFocusedCellId, code });
152
146
  };
153
147
 
154
148
  return (