@marimo-team/islands 0.25.3-dev273 → 0.25.3-dev279

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 (143) hide show
  1. package/dist/{ConnectedDataExplorerComponent-eLHPh6uu.js → ConnectedDataExplorerComponent-CErm132k.js} +25 -26
  2. package/dist/{ErrorBoundary-DBh-wUT9.js → ErrorBoundary-DmTMuDPR.js} +43 -44
  3. package/dist/{abnfDiagram-VCTEODGH-hqd0IBtX.js → abnfDiagram-VCTEODGH-d-Qn2fwb.js} +2 -2
  4. package/dist/{any-language-editor-DnG26QXh.js → any-language-editor-6k6F12Z3.js} +3 -3
  5. package/dist/{architectureDiagram-5GKGNRK7-BzLAFcc0.js → architectureDiagram-5GKGNRK7-DxragHYv.js} +1 -1
  6. package/dist/{assertNever-DIU3JJbt.js → assertNever-B-YzWzbL.js} +14 -14
  7. package/dist/{button-0-RqY1DW.js → button-DZuNnIZO.js} +220 -223
  8. package/dist/{capabilities-B6yy_CBN.js → capabilities-D9FskwsK.js} +1 -1
  9. package/dist/{chat-ui-BWIkve2R.js → chat-ui-v1Fdh0NA.js} +332 -333
  10. package/dist/{check-gUSZbRsl.js → check-XFzZeH-y.js} +1 -1
  11. package/dist/{chunk-IMKFNOWR-DOeVvuyE.js → chunk-IMKFNOWR-C0x0feFg.js} +1 -1
  12. package/dist/{chunk-SHT3W25Y-DZoFI8wR.js → chunk-SHT3W25Y-D0ZdASqB.js} +1 -1
  13. package/dist/{chunk-SVP7TREG-CWu86PSW.js → chunk-SVP7TREG-BHjL96zx.js} +1 -1
  14. package/dist/{chunk-TICWLB2K-BrM0GoP3.js → chunk-TICWLB2K-CzcrwGfp.js} +1 -1
  15. package/dist/{classDiagram-ZZMXUADV-DYi4V2bB.js → classDiagram-ZZMXUADV-BTqFAZTP.js} +2 -2
  16. package/dist/{classDiagram-v2-VYDZK3BY-tN7FIk-m.js → classDiagram-v2-VYDZK3BY-EPXb0Elt.js} +2 -2
  17. package/dist/{code-visibility-M_dXDGp6.js → code-visibility-Dw4-TXN0.js} +20 -20
  18. package/dist/{common-DV0fvw_I.js → common-BXMFi4lr.js} +5399 -5397
  19. package/dist/{config-BsPruWMR.js → config-C8MFHQ2E.js} +23 -22
  20. package/dist/{copy-icon-C2I8sw4h.js → copy-icon-CtllOdmg.js} +3 -3
  21. package/dist/{createReducer-DdtT_7ji.js → createReducer-DRqwmaTc.js} +2 -2
  22. package/dist/{cynefinDiagram-5FMLGOSQ-D5nCnDc-.js → cynefinDiagram-5FMLGOSQ-CBSD344q.js} +1 -1
  23. package/dist/{dagre-GXQ25YYZ-BHkd7f_i.js → dagre-GXQ25YYZ-JItjh3Ge.js} +1 -1
  24. package/dist/{data-grid-overlay-editor-Cd1zGKBt.js → data-grid-overlay-editor-hZzwX7Ia.js} +1 -1
  25. package/dist/{diagram-S7CK7UJ4-D1ALppT2.js → diagram-S7CK7UJ4-CTD9xTVb.js} +1 -1
  26. package/dist/{diagram-UQ7AKVKN-DLv0b83L.js → diagram-UQ7AKVKN-DTfnFai8.js} +1 -1
  27. package/dist/{diagram-VX7I27RA-7XJ7J6qg.js → diagram-VX7I27RA-BcSnucV-.js} +1 -1
  28. package/dist/{diagram-Z3DM3KII-7M7zbHp_.js → diagram-Z3DM3KII-C2ATIE8A.js} +1 -1
  29. package/dist/{dialog-DzCj1qQv.js → dialog-CaYm5imE.js} +33 -33
  30. package/dist/{dropdown-menu-CdXE15an.js → dropdown-menu-Bb0bFOIk.js} +149 -149
  31. package/dist/{ebnfDiagram-PWID7BFC-DHH1qlmV.js → ebnfDiagram-PWID7BFC-B7B9JPxc.js} +2 -2
  32. package/dist/{erDiagram-RLTQ6QDP-fI_0dGef.js → erDiagram-RLTQ6QDP-v6hDno1O.js} +1 -1
  33. package/dist/{error-banner-DPc9eIw5.js → error-banner-CHCdHVFB.js} +44 -45
  34. package/dist/{error-entries-CxN-Nq3V.js → error-entries-C1S-Rmyt.js} +563 -554
  35. package/dist/{feedback-button-CE2gPi4-.js → feedback-button-6Ui2TDLR.js} +12 -12
  36. package/dist/{flowDiagram-HODETNUW-Brg9MA6i.js → flowDiagram-HODETNUW-aIFlAtOy.js} +2 -2
  37. package/dist/{formats-DbSvAPY-.js → formats-PzBQMUnr.js} +3 -3
  38. package/dist/{glide-data-editor-BycATbgF.js → glide-data-editor-PZNlrSDI.js} +14 -16
  39. package/dist/{glide-utils-BSw3SSHF.js → glide-utils-BSQr4d90.js} +51 -59
  40. package/dist/{globals-CW6OvnI5.js → globals-DX6FPZYq.js} +3 -3
  41. package/dist/{html-to-image-Bc2AvXHG.js → html-to-image-CqGUd58T.js} +14529 -14531
  42. package/dist/{infoDiagram-27XIBGKW-E9e403YT.js → infoDiagram-27XIBGKW-D6YHLeCP.js} +1 -1
  43. package/dist/{ishikawaDiagram-5VMMS53U-C-RlYDRo.js → ishikawaDiagram-5VMMS53U-D1ZvprOX.js} +1 -1
  44. package/dist/{kanban-definition-UXKFOSKX-CLFl_uqK.js → kanban-definition-UXKFOSKX-Bna_3BMr.js} +1 -1
  45. package/dist/{loader-BVEtQ4F3.js → loader-DZvtzQoD.js} +1 -1
  46. package/dist/main.js +7357 -7361
  47. package/dist/{mermaid-rd09e1JL.js → mermaid-A36unKXJ.js} +50 -50
  48. package/dist/{mindmap-definition-YA3MSWOX-BQ8TWtyB.js → mindmap-definition-YA3MSWOX-CyVCs__G.js} +1 -1
  49. package/dist/{number-overlay-editor-B_rR-LdM.js → number-overlay-editor-D0CsL3_R.js} +1 -1
  50. package/dist/{pegDiagram-XKGWAZYB-CN8UHFPi.js → pegDiagram-XKGWAZYB-9hNBD2wZ.js} +2 -2
  51. package/dist/{pencil-DcT8AE0h.js → pencil-DYUlSKxZ.js} +1 -1
  52. package/dist/{pieDiagram-E7YTZNPT-DGuJ0EBd.js → pieDiagram-E7YTZNPT-8tr-NYo7.js} +1 -1
  53. package/dist/{process-output-qecD7Dk8.js → process-output-DskX9jLa.js} +4 -4
  54. package/dist/{railroadDiagram-O6MQD6OU-BPDA8wy8.js → railroadDiagram-O6MQD6OU-Dzg1dyyp.js} +2 -2
  55. package/dist/{requirementDiagram-BXWQKSXE-ChzLGbGW.js → requirementDiagram-BXWQKSXE-B7sNqwGG.js} +1 -1
  56. package/dist/{reveal-component-CngVwOSy.js → reveal-component-D7xeI1QR.js} +1003 -1003
  57. package/dist/{select-OxgozOC8.js → select-DsoP1qe8.js} +290 -290
  58. package/dist/{sequenceDiagram-WJ2MYXX4-DFX-bE6O.js → sequenceDiagram-WJ2MYXX4-oP9shbaG.js} +1 -1
  59. package/dist/{spec-oJn0RhpQ.js → spec-BZMDxAu7.js} +4 -4
  60. package/dist/{stateDiagram-D77RDMKH-BR7cI3wK.js → stateDiagram-D77RDMKH-CjCv4ogv.js} +2 -2
  61. package/dist/{stateDiagram-v2-MP3YSRHH-oGqB5UDI.js → stateDiagram-v2-MP3YSRHH-BW9X162a.js} +2 -2
  62. package/dist/{static-state-CuV6Pc3a.js → static-state-D-Q-Ajaa.js} +8 -8
  63. package/dist/style.css +1 -1
  64. package/dist/{swimlanes-42K2YHIH-DwSZl1yC.js → swimlanes-42K2YHIH-Ckfs9Wrn.js} +1 -1
  65. package/dist/{swimlanesDiagram-VR7AAH4N-BHlcd-Ri.js → swimlanesDiagram-VR7AAH4N-DpTNG9YP.js} +2 -2
  66. package/dist/{swiper-component-Dvj-goaD.js → swiper-component-DQbK_ZWm.js} +7 -7
  67. package/dist/{timeline-definition-24CTP7MA-DMmP-G2O.js → timeline-definition-24CTP7MA-BXaBlV6U.js} +1 -1
  68. package/dist/{toast-DbBHmxmB.js → toast-BhjIy3Tq.js} +158 -158
  69. package/dist/{tooltip-BfcDQd2j.js → tooltip-DMMiOn2f.js} +64 -64
  70. package/dist/use-restore-focus-CosX7-gx.js +7568 -0
  71. package/dist/{useAsyncData-BYIAoMqn.js → useAsyncData-Ci4AvJff.js} +4 -4
  72. package/dist/{useDateFormatter-ButWkdcK.js → useDateFormatter-CPlava52.js} +2 -2
  73. package/dist/{useDeepCompareMemoize-Bz0c5GN6.js → useDeepCompareMemoize-NaaWoFlX.js} +1 -1
  74. package/dist/useEvent-BRH-aCqi.js +19 -0
  75. package/dist/{useIframeCapabilities-BIolGsF1.js → useIframeCapabilities-BXhDDoCG.js} +1 -1
  76. package/dist/{useLifecycle-JjxCC7Vu.js → useLifecycle-SniivYmC.js} +2 -2
  77. package/dist/{vega-component-rxIxAAh9.js → vega-component-DIxaDQNs.js} +40 -40
  78. package/dist/{vennDiagram-4TSXK5OY-Db8GtH1G.js → vennDiagram-4TSXK5OY-C-hQ4iNJ.js} +1 -1
  79. package/dist/{wardleyDiagram-VM6X3IG4-DmIiC3FU.js → wardleyDiagram-VM6X3IG4-C2MQ_Umv.js} +1 -1
  80. package/dist/{xychartDiagram-S5SC5T6Z-DS9OPrNq.js → xychartDiagram-S5SC5T6Z-BtTTBn7Q.js} +1 -1
  81. package/package.json +1 -1
  82. package/src/__mocks__/executions.ts +4 -2
  83. package/src/__mocks__/notebook.ts +0 -2
  84. package/src/__tests__/CellStatus.test.tsx +6 -6
  85. package/src/components/editor/__tests__/data-attributes.test.tsx +0 -2
  86. package/src/components/editor/__tests__/output-persistence.test.tsx +20 -5
  87. package/src/components/editor/cell/CellStatus.tsx +6 -5
  88. package/src/components/editor/cell/__tests__/useRunCells.test.tsx +169 -0
  89. package/src/components/editor/cell/collapse.tsx +3 -4
  90. package/src/components/editor/cell/useRunCells.ts +32 -3
  91. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +2 -3
  92. package/src/components/editor/notebook-cell.tsx +23 -37
  93. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +4 -10
  94. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -2
  95. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +8 -5
  96. package/src/components/slides/minimap.tsx +3 -2
  97. package/src/components/slides/reveal-component.tsx +3 -2
  98. package/src/components/slides/slide-cell-view.tsx +8 -8
  99. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -101
  100. package/src/core/cells/__tests__/actions.test.ts +0 -1
  101. package/src/core/cells/__tests__/cell.test.ts +81 -17
  102. package/src/core/cells/__tests__/cells.test.ts +0 -100
  103. package/src/core/cells/__tests__/document.test.ts +2 -8
  104. package/src/core/cells/__tests__/utils.test.ts +93 -24
  105. package/src/core/cells/actions.ts +0 -1
  106. package/src/core/cells/cell.ts +37 -14
  107. package/src/core/cells/cells.ts +10 -99
  108. package/src/core/cells/document.ts +2 -13
  109. package/src/core/cells/types.ts +0 -23
  110. package/src/core/cells/utils.ts +44 -17
  111. package/src/core/codemirror/cells/extensions.ts +0 -14
  112. package/src/core/errors/__tests__/error-entries.test.ts +40 -1
  113. package/src/core/errors/error-entries.ts +2 -3
  114. package/src/core/executions/__tests__/freshness.test.ts +420 -0
  115. package/src/core/executions/__tests__/hooks.test.tsx +106 -0
  116. package/src/core/executions/atoms.ts +22 -0
  117. package/src/core/executions/freshness.ts +164 -0
  118. package/src/core/executions/hooks.ts +17 -1
  119. package/src/core/executions/index.ts +3 -1
  120. package/src/core/islands/bootstrap.ts +0 -1
  121. package/src/core/islands/components/__tests__/web-components.test.tsx +63 -0
  122. package/src/core/islands/components/web-components.tsx +11 -0
  123. package/src/core/kernel/handlers.ts +0 -4
  124. package/src/core/session/useNotebookSession.tsx +2 -7
  125. package/src/css/globals.css +6 -2
  126. package/src/plugins/impl/DataEditorPlugin.tsx +0 -4
  127. package/src/plugins/impl/data-editor/__tests__/column-types.test.ts +5 -0
  128. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +9 -5
  129. package/src/plugins/impl/data-editor/column-types.ts +3 -0
  130. package/src/plugins/impl/data-editor/glide-data-editor.tsx +6 -5
  131. package/src/plugins/impl/data-editor/glide-utils.ts +10 -32
  132. package/src/plugins/impl/data-editor/types.ts +0 -2
  133. package/src/stories/cell-status.stories.tsx +12 -14
  134. package/src/stories/cell.stories.tsx +44 -10
  135. package/src/stories/layout/vertical/one-column.stories.tsx +0 -10
  136. package/src/theme/__tests__/islands-theme.test.tsx +276 -0
  137. package/src/theme/namespace.tsx +4 -3
  138. package/src/theme/useTheme.ts +71 -41
  139. package/dist/schemas-CdscWNy_.js +0 -4747
  140. package/dist/use-restore-focus-CmflVLWJ.js +0 -1672
  141. package/dist/useTheme-DPLobSFs.js +0 -339
  142. package/dist/utils-EBklsC5R.js +0 -813
  143. package/src/components/editor/cell/__tests__/useRunCells.test.ts +0 -45
@@ -1,8 +1,8 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
3
  import { t as n } from "./compiler-runtime-CldRdSsv.js";
4
- import { D as r } from "./utils-EBklsC5R.js";
5
- import { t as i } from "./invariant-DLmrl-hA.js";
4
+ import { t as r } from "./invariant-DLmrl-hA.js";
5
+ import { t as i } from "./useEvent-BRH-aCqi.js";
6
6
  //#region src/hooks/useAsyncData.ts
7
7
  var a = n(), o = /* @__PURE__ */ e(t(), 1), s = {
8
8
  error(e, t) {
@@ -45,7 +45,7 @@ var a = n(), o = /* @__PURE__ */ e(t(), 1), s = {
45
45
  function c(e, t) {
46
46
  let n = (0, a.c)(16), [c, d] = (0, o.useState)(0), [f, p] = (0, o.useState)(u), m;
47
47
  n[0] === e ? m = n[1] : (m = typeof e == "function" ? { fetch: e } : e, n[0] = e, n[1] = m);
48
- let h = r(m.fetch), g;
48
+ let h = i(m.fetch), g;
49
49
  n[2] === h ? g = n[3] : (g = () => {
50
50
  let e = new AbortController(), t = !1;
51
51
  return p(l), h({ previous: () => {
@@ -67,7 +67,7 @@ function c(e, t) {
67
67
  let v;
68
68
  n[8] === f ? v = n[9] : (v = (e) => {
69
69
  let t;
70
- typeof e == "function" ? (i(f.status === "success" || f.status === "loading", "No previous state value."), t = e(f.data)) : t = e, p(s.success(t));
70
+ typeof e == "function" ? (r(f.status === "success" || f.status === "loading", "No previous state value."), t = e(f.data)) : t = e, p(s.success(t));
71
71
  }, n[8] = f, n[9] = v);
72
72
  let y;
73
73
  n[10] === c ? y = n[11] : (y = () => d(c + 1), n[10] = c, n[11] = y);
@@ -1,7 +1,7 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
- import { h as n } from "./tooltip-BfcDQd2j.js";
4
- import { C as r } from "./select-OxgozOC8.js";
3
+ import { h as n } from "./tooltip-DMMiOn2f.js";
4
+ import { C as r } from "./select-DsoP1qe8.js";
5
5
  var i = n("chart-pie", [["path", {
6
6
  d: "M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z",
7
7
  key: "pzmjnu"
@@ -1,6 +1,6 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
- import { l as n } from "./utils-EBklsC5R.js";
3
+ import { Mt as n } from "./use-restore-focus-CosX7-gx.js";
4
4
  //#region src/hooks/useDeepCompareMemoize.ts
5
5
  var r = /* @__PURE__ */ e(t(), 1);
6
6
  function i(e) {
@@ -0,0 +1,19 @@
1
+ import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
+ import { t } from "./react-sHtZdjeP.js";
3
+ //#region ../node_modules/.pnpm/react-use-event-hook@0.9.6_react@19.3.0/node_modules/react-use-event-hook/dist/esm/useEvent.js
4
+ var n = /* @__PURE__ */ e(t()), r = typeof window < "u" ? n.useInsertionEffect || n.useLayoutEffect : () => {};
5
+ function i(e) {
6
+ let t = n.useRef(a);
7
+ r(() => {
8
+ t.current = e;
9
+ }, [e]);
10
+ let i = n.useRef(null);
11
+ return i.current ||= function() {
12
+ return t.current.apply(this, arguments);
13
+ }, i.current;
14
+ }
15
+ function a() {
16
+ throw Error("INVALID_USEEVENT_INVOCATION: the callback from useEvent cannot be invoked before the component has mounted.");
17
+ }
18
+ //#endregion
19
+ export { i as t };
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./compiler-runtime-CldRdSsv.js";
2
- import { t } from "./capabilities-B6yy_CBN.js";
2
+ import { t } from "./capabilities-D9FskwsK.js";
3
3
  //#region src/hooks/useIframeCapabilities.ts
4
4
  var n = e();
5
5
  function r() {
@@ -1,8 +1,8 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
- import { h as t, s as n } from "./button-0-RqY1DW.js";
2
+ import { h as t, r as n } from "./button-DZuNnIZO.js";
3
3
  import { t as r } from "./react-sHtZdjeP.js";
4
4
  import { t as i } from "./compiler-runtime-CldRdSsv.js";
5
- import { h as a } from "./tooltip-BfcDQd2j.js";
5
+ import { h as a } from "./tooltip-DMMiOn2f.js";
6
6
  import { t as o } from "./jsx-runtime-3BD1kT0s.js";
7
7
  var s = a("calendar", [
8
8
  ["path", {
@@ -1,23 +1,23 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
- import { a as t, g as n, h as r, m as i } from "./button-0-RqY1DW.js";
2
+ import { g as t, h as n, m as r, s as i } from "./button-DZuNnIZO.js";
3
3
  import { t as a } from "./react-sHtZdjeP.js";
4
4
  import { t as o } from "./compiler-runtime-CldRdSsv.js";
5
- import { t as s } from "./tooltip-BfcDQd2j.js";
6
- import { l as c, t as l } from "./config-BsPruWMR.js";
5
+ import { t as s } from "./tooltip-DMMiOn2f.js";
6
+ import { l as c, t as l } from "./config-C8MFHQ2E.js";
7
7
  import { t as u } from "./jsx-runtime-3BD1kT0s.js";
8
- import { n as d } from "./error-banner-DPc9eIw5.js";
9
- import { t as f } from "./debounce-DrhhziJv.js";
10
- import { n as p } from "./useTheme-DPLobSFs.js";
11
- import { D as ee } from "./utils-EBklsC5R.js";
12
- import { t as te } from "./objects-DCmMvZtn.js";
13
- import { a as ne, i as re, n as ie, t as m } from "./formats-DbSvAPY-.js";
8
+ import { u as d } from "./use-restore-focus-CosX7-gx.js";
9
+ import { n as f } from "./error-banner-CHCdHVFB.js";
10
+ import { t as p } from "./debounce-DrhhziJv.js";
11
+ import { t as ee } from "./objects-DCmMvZtn.js";
12
+ import { t as te } from "./useEvent-BRH-aCqi.js";
13
+ import { a as ne, i as re, n as ie, t as m } from "./formats-PzBQMUnr.js";
14
14
  import { a as h, t as g } from "./arrays-DoQ-AILx.js";
15
- import { t as ae } from "./useAsyncData-BYIAoMqn.js";
15
+ import { t as ae } from "./useAsyncData-Ci4AvJff.js";
16
16
  import { t as _ } from "./semaphore-89jsoHtS.js";
17
17
  import { D as oe, n as se } from "./vega-loader.browser-B9Pz0EGP.js";
18
18
  import { t as ce } from "./react-vega-C4T9Rb_w.js";
19
- import { a as le, n as v } from "./loader-BVEtQ4F3.js";
20
- import { t as ue } from "./useDeepCompareMemoize-Bz0c5GN6.js";
19
+ import { a as le, n as v } from "./loader-DZvtzQoD.js";
20
+ import { t as ue } from "./useDeepCompareMemoize-NaaWoFlX.js";
21
21
  import { t as de } from "./use-vega-container-remeasure-Bz4PZMtt.js";
22
22
  //#region src/plugins/impl/vega/fix-relative-url.ts
23
23
  var fe = /* @__PURE__ */ e(a(), 1), pe = o();
@@ -103,7 +103,7 @@ var y = {
103
103
  }
104
104
  };
105
105
  function C() {
106
- return t() ? "metaKey" : "ctrlKey";
106
+ return i() ? "metaKey" : "ctrlKey";
107
107
  }
108
108
  var w = {
109
109
  highlight() {
@@ -515,10 +515,10 @@ se("arrow", m);
515
515
  var K = (e) => {
516
516
  let t = (0, pe.c)(12), { value: n, setValue: r, chartSelection: i, fieldSelection: a, spec: o, embedOptions: s } = e, c, l;
517
517
  t[0] === o ? (c = t[1], l = t[2]) : (c = async () => W(o), l = [o], t[0] = o, t[1] = c, t[2] = l);
518
- let { data: u, error: f } = ae(c, l);
519
- if (f) {
518
+ let { data: u, error: d } = ae(c, l);
519
+ if (d) {
520
520
  let e;
521
- return t[3] === f ? e = t[4] : (e = /* @__PURE__ */ (0, G.jsx)(d, { error: f }), t[3] = f, t[4] = e), e;
521
+ return t[3] === d ? e = t[4] : (e = /* @__PURE__ */ (0, G.jsx)(f, { error: d }), t[3] = d, t[4] = e), e;
522
522
  }
523
523
  if (!u) return null;
524
524
  let p;
@@ -531,7 +531,7 @@ var K = (e) => {
531
531
  embedOptions: s
532
532
  }), t[5] = i, t[6] = s, t[7] = a, t[8] = u, t[9] = r, t[10] = n, t[11] = p) : p = t[11], p;
533
533
  }, q = (e) => {
534
- let a = (0, pe.c)(50), { value: o, setValue: l, chartSelection: u, fieldSelection: d, spec: ne, embedOptions: m } = e, { theme: h } = p(), g = (0, fe.useRef)(null), ae = (0, fe.useRef)(void 0), [_, se] = (0, fe.useState)(), v;
534
+ let a = (0, pe.c)(50), { value: o, setValue: l, chartSelection: u, fieldSelection: f, spec: ne, embedOptions: m } = e, { theme: h } = d(), g = (0, fe.useRef)(null), ae = (0, fe.useRef)(void 0), [_, se] = (0, fe.useState)(), v;
535
535
  bb0: {
536
536
  if (m && "actions" in m) {
537
537
  v = m.actions;
@@ -544,10 +544,10 @@ var K = (e) => {
544
544
  }, a[0] = e) : e = a[0], v = e;
545
545
  }
546
546
  let y = v, b = ue(ne), x;
547
- a[1] !== u || a[2] !== d || a[3] !== b ? (x = he(me(b), {
547
+ a[1] !== u || a[2] !== f || a[3] !== b ? (x = he(me(b), {
548
548
  chartSelection: u,
549
- fieldSelection: d
550
- }), a[1] = u, a[2] = d, a[3] = b, a[4] = x) : x = a[4];
549
+ fieldSelection: f
550
+ }), a[1] = u, a[2] = f, a[3] = b, a[4] = x) : x = a[4];
551
551
  let C = x, w;
552
552
  a[5] === C ? w = a[6] : (w = E(C), a[5] = C, a[6] = w);
553
553
  let T = w, D;
@@ -557,11 +557,11 @@ var K = (e) => {
557
557
  ...e
558
558
  });
559
559
  }, a[7] = l, a[8] = o, a[9] = D) : D = a[9];
560
- let O = ee(D), k;
561
- a[10] === O ? k = a[11] : (k = f((e, t) => {
562
- n.debug("[Vega signal]", e, t);
563
- let r = te.mapValues(t, _e);
564
- r = te.mapValues(r, ge), O({ [e]: r });
560
+ let O = te(D), k;
561
+ a[10] === O ? k = a[11] : (k = p((e, n) => {
562
+ t.debug("[Vega signal]", e, n);
563
+ let r = ee.mapValues(n, _e);
564
+ r = ee.mapValues(r, ge), O({ [e]: r });
565
565
  }, 100), a[10] = O, a[11] = k);
566
566
  let A = k, j = ue(T), M;
567
567
  if (a[12] !== A || a[13] !== j) {
@@ -573,18 +573,18 @@ var K = (e) => {
573
573
  } else M = a[14];
574
574
  let N = M, P;
575
575
  a[17] === C ? P = a[18] : (P = (e) => {
576
- n.error(e), n.debug(C), se(e);
576
+ t.error(e), t.debug(C), se(e);
577
577
  }, a[17] = C, a[18] = P);
578
- let F = ee(P), I;
578
+ let F = te(P), I;
579
579
  a[19] === Symbol.for("react.memo_cache_sentinel") ? (I = (e) => {
580
- n.debug("[Vega view] created", e), ae.current = e, se(void 0);
580
+ t.debug("[Vega view] created", e), ae.current = e, se(void 0);
581
581
  }, a[19] = I) : I = a[19];
582
- let L = ee(I), R;
582
+ let L = te(I), R;
583
583
  a[20] === T ? R = a[21] : (R = () => {
584
584
  let e = [];
585
585
  if (S.hasPoint(T) && e.push(["Point selection", "click to select a point; hold shift for multi-select"]), S.hasInterval(T) && e.push(["Interval selection", "click and drag to select an interval"]), S.hasLegend(T) && e.push(["Legend selection", "click to select a legend item; hold shift for multi-select"]), S.hasPanZoom(T)) {
586
- let n = t() ? "⌘" : "ctrl";
587
- e.push(["Pan", `hold the ${n} key and drag`], ["Zoom", `hold the ${n} key and scroll`]);
586
+ let t = i() ? "⌘" : "ctrl";
587
+ e.push(["Pan", `hold the ${t} key and drag`], ["Zoom", `hold the ${t} key and scroll`]);
588
588
  }
589
589
  return e.length === 0 ? null : /* @__PURE__ */ (0, G.jsx)(s, {
590
590
  delayDuration: 300,
@@ -618,21 +618,21 @@ var K = (e) => {
618
618
  de(g, K === "container");
619
619
  let q, J;
620
620
  a[32] !== U || a[33] !== N ? (q = () => (N.forEach((e) => {
621
- let { signalName: t, handler: r } = e;
621
+ let { signalName: n, handler: r } = e;
622
622
  try {
623
- U?.view.addSignalListener(t, r);
623
+ U?.view.addSignalListener(n, r);
624
624
  } catch (e) {
625
- let t = e;
626
- n.error(t);
625
+ let n = e;
626
+ t.error(n);
627
627
  }
628
628
  }), () => {
629
629
  N.forEach((e) => {
630
- let { signalName: t, handler: r } = e;
630
+ let { signalName: n, handler: r } = e;
631
631
  try {
632
- U?.view.removeSignalListener(t, r);
632
+ U?.view.removeSignalListener(n, r);
633
633
  } catch (e) {
634
- let t = e;
635
- n.error(t);
634
+ let n = e;
635
+ t.error(n);
636
636
  }
637
637
  });
638
638
  }), J = [U, N], a[32] = U, a[33] = N, a[34] = q, a[35] = J) : (q = a[34], J = a[35]), (0, fe.useEffect)(q, J);
@@ -645,7 +645,7 @@ var K = (e) => {
645
645
  })]
646
646
  }), a[36] = _, a[37] = Y);
647
647
  let X, ye;
648
- a[38] === Symbol.for("react.memo_cache_sentinel") ? (X = r("relative"), ye = i.stopPropagation(), a[38] = X, a[39] = ye) : (X = a[38], ye = a[39]);
648
+ a[38] === Symbol.for("react.memo_cache_sentinel") ? (X = n("relative"), ye = r.stopPropagation(), a[38] = X, a[39] = ye) : (X = a[38], ye = a[39]);
649
649
  let Z;
650
650
  a[40] === K ? Z = a[41] : (Z = /* @__PURE__ */ (0, G.jsx)("div", {
651
651
  ref: g,
@@ -3,7 +3,7 @@ import { t } from "./src-CA_m4ONl.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { $ as r, H as i, K as a, U as o, a as s, b as c, c as l, et as u, f as d, nt as f, tt as p, v as m, w as h, y as g } from "./chunk-DU6HZSFF-BwiyaNpg.js";
5
5
  import { t as _ } from "./rough.esm-CtV9AnV1.js";
6
- import { p as v } from "./mermaid-rd09e1JL.js";
6
+ import { p as v } from "./mermaid-A36unKXJ.js";
7
7
  //#region ../node_modules/.pnpm/khroma@2.1.0/node_modules/khroma/dist/methods/transparentize.js
8
8
  var y = (e, t) => p(e, "a", -t), b = 1e-10;
9
9
  function x(e, t) {
@@ -2,7 +2,7 @@ import { i as e } from "./chunk-75Z2AOVW-D7gxIs2Q.js";
2
2
  import { n as t } from "./src-CA_m4ONl.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { D as r, H as i, K as a, U as o, a as s, b as c, c as l, v as u, w as d, x as f, y as p } from "./chunk-DU6HZSFF-BwiyaNpg.js";
5
- import { p as m } from "./mermaid-rd09e1JL.js";
5
+ import { p as m } from "./mermaid-A36unKXJ.js";
6
6
  import { n as h } from "./mermaid-parser.core-DxuSfYwJ.js";
7
7
  import { t as g } from "./chunk-JWPE2WC7-DJvv1t8U.js";
8
8
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/wardleyDiagram-VM6X3IG4.mjs
@@ -9,7 +9,7 @@ import { n as s } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
9
9
  import { D as c, H as l, K as u, U as d, a as f, b as p, c as m, f as h, v as g, w as _, y as v, z as y } from "./chunk-DU6HZSFF-BwiyaNpg.js";
10
10
  import "./chunk-PWAF6VOD-CQw5qATZ.js";
11
11
  import { t as b } from "./chunk-GMAD6QVW-BhaJx0X3.js";
12
- import { p as x } from "./mermaid-rd09e1JL.js";
12
+ import { p as x } from "./mermaid-A36unKXJ.js";
13
13
  //#region ../node_modules/.pnpm/d3-scale@4.0.2/node_modules/d3-scale/src/band.js
14
14
  function S() {
15
15
  var e = t().unknown(void 0), r = e.domain, i = e.range, o = 0, s = 1, c, l, u = !1, d = 0, f = 0, p = .5;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev273",
3
+ "version": "0.25.3-dev279",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -8,6 +8,7 @@ import type { CellExecutionInputs } from "@/core/executions";
8
8
  import {
9
9
  ConnectionState,
10
10
  type ConnectionStatus,
11
+ type Document,
11
12
  type Execution,
12
13
  type Executions,
13
14
  type NotebookReplica,
@@ -162,16 +163,16 @@ export const MockExecutions = {
162
163
  };
163
164
  },
164
165
 
165
- /** Make the store's active replica report `records` and `runtime`. */
166
+ /** Make the store's active replica report `records`, `runtime`, and `document`. */
166
167
  seed(
167
168
  store: Store,
168
169
  records: Protocol.Execution[],
169
170
  runtime: Protocol.Runtime | null = null,
171
+ document: Document | null = null,
170
172
  ) {
171
173
  const current = store.get(activeNotebookReplicaAtom);
172
174
  const replica = {
173
175
  connectionAtom: atom<ConnectionStatus>({ state: ConnectionState.OPEN }),
174
- documentAtom: atom(null),
175
176
  backendAtom: atom(null),
176
177
  attachmentsAtom: atom([]),
177
178
  connect: () => () => undefined,
@@ -185,6 +186,7 @@ export const MockExecutions = {
185
186
  operations: [],
186
187
  updated_at: null,
187
188
  }),
189
+ documentAtom: atom<Document | null>(document),
188
190
  runtimeAtom: atom(runtime),
189
191
  executionsAtom: atom(mirror(records)),
190
192
  resultsAtom: atom(results(records)),
@@ -39,8 +39,6 @@ export const MockNotebook = {
39
39
  expand_output: false,
40
40
  ...data.config,
41
41
  },
42
- edited: false,
43
- lastCodeRun: null,
44
42
  serializedEditorState: null,
45
43
  ...data,
46
44
  })),
@@ -3,6 +3,7 @@
3
3
  import { render } from "@testing-library/react";
4
4
  import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
5
5
  import { TooltipProvider } from "@/components/ui/tooltip";
6
+ import type { CellFreshness } from "@/core/executions";
6
7
  import { formatElapsedTime, type Milliseconds } from "@/utils/time";
7
8
  import {
8
9
  CellStatusComponent,
@@ -70,9 +71,8 @@ describe("CellStatusComponent", () => {
70
71
  // Base props that will be modified for different test cases
71
72
  const baseProps = {
72
73
  editing: true,
73
- edited: false,
74
74
  disabled: false,
75
- staleInputs: false,
75
+ freshness: { sourceChanged: false, inputsChanged: false } as CellFreshness,
76
76
  status: "idle" as const,
77
77
  interrupted: false,
78
78
  elapsedTime: null,
@@ -94,7 +94,7 @@ describe("CellStatusComponent", () => {
94
94
  const props = {
95
95
  ...baseProps,
96
96
  disabled: true,
97
- staleInputs: true,
97
+ freshness: { sourceChanged: false, inputsChanged: true } as CellFreshness,
98
98
  startedAt: 1_704_096_000_000 as Milliseconds, // Jan 1, 2024 12:00:00
99
99
  };
100
100
 
@@ -140,7 +140,7 @@ describe("CellStatusComponent", () => {
140
140
  const props = {
141
141
  ...baseProps,
142
142
  blocked: true,
143
- staleInputs: true,
143
+ freshness: { sourceChanged: false, inputsChanged: true } as CellFreshness,
144
144
  startedAt: 1_704_096_000_000 as Milliseconds,
145
145
  };
146
146
 
@@ -215,7 +215,7 @@ describe("CellStatusComponent", () => {
215
215
  test("renders edited state", () => {
216
216
  const props = {
217
217
  ...baseProps,
218
- edited: true,
218
+ freshness: { sourceChanged: true, inputsChanged: false } as CellFreshness,
219
219
  elapsedTime: 1500 as Milliseconds,
220
220
  startedAt: 1_704_096_000_000 as Milliseconds,
221
221
  };
@@ -231,7 +231,7 @@ describe("CellStatusComponent", () => {
231
231
  test("renders stale inputs state", () => {
232
232
  const props = {
233
233
  ...baseProps,
234
- staleInputs: true,
234
+ freshness: { sourceChanged: false, inputsChanged: true } as CellFreshness,
235
235
  elapsedTime: 1500 as Milliseconds,
236
236
  startedAt: 1_704_096_000_000 as Milliseconds,
237
237
  };
@@ -93,7 +93,6 @@ describe("Cell data attributes", () => {
93
93
  [cid]: {
94
94
  code: "",
95
95
  name: cellName,
96
- edited: false,
97
96
  config: {
98
97
  disabled: false,
99
98
  hide_code: false,
@@ -106,7 +105,6 @@ describe("Cell data attributes", () => {
106
105
  notebook.cellRuntime[cid] = createCellRuntimeState({
107
106
  output: null,
108
107
  consoleOutputs: [],
109
- staleInputs: false,
110
108
  debuggerActive: false,
111
109
  outline: null,
112
110
  });
@@ -11,6 +11,11 @@ import { cellId } from "@/__tests__/branded";
11
11
  import { TooltipProvider } from "@/components/ui/tooltip";
12
12
  import { notebookAtom } from "@/core/cells/cells";
13
13
  import { DocumentProvider } from "@/core/notebook/document";
14
+ import {
15
+ cell,
16
+ document as documentOf,
17
+ withCells,
18
+ } from "@/core/notebook/document/__tests__/fixtures";
14
19
  import type { CellRuntimeState } from "@/core/cells/types";
15
20
  import { createCellRuntimeState } from "@/core/cells/types";
16
21
  import { defaultUserConfig } from "@/core/config/config-schema";
@@ -41,7 +46,6 @@ function seedNotebook(
41
46
  [cid]: {
42
47
  code: "1 + 1",
43
48
  name: "test_cell",
44
- edited: false,
45
49
  config: {
46
50
  disabled: false,
47
51
  hide_code: false,
@@ -188,11 +192,22 @@ describe("output persistence across mode changes", () => {
188
192
 
189
193
  it("does not dim edited-but-not-run outputs as stale while presenting", () => {
190
194
  const { store, wrapper } = createTestWrapper();
195
+ // The host holds newer source than the cell last ran with
196
+ MockExecutions.seed(
197
+ store,
198
+ [MockExecutions.completed(cid, { code_fingerprint: "ran" })],
199
+ null,
200
+ withCells(
201
+ documentOf(),
202
+ {
203
+ c1: null,
204
+ c2: null,
205
+ [cid]: cell(cid, "1 + 1", { code_fingerprint: "edited" }),
206
+ },
207
+ [cid],
208
+ ),
209
+ );
191
210
  seedNotebook(store);
192
- // Mark the cell as edited without re-running it
193
- const notebook = store.get(notebookAtom);
194
- notebook.cellData[cid] = { ...notebook.cellData[cid], edited: true };
195
- store.set(notebookAtom, { ...notebook });
196
211
 
197
212
  const { container, rerender } = render(renderCell("edit"), { wrapper });
198
213
  expect(container.querySelector(".marimo-output-stale")).toBeTruthy();
@@ -7,7 +7,7 @@ import {
7
7
  } from "lucide-react";
8
8
  import { useDateFormatter } from "react-aria";
9
9
  import { MultiIcon } from "@/components/icons/multi-icon";
10
- import type { CellRunStatus } from "@/core/executions";
10
+ import type { CellFreshness, CellRunStatus } from "@/core/executions";
11
11
  import { Logger } from "@/utils/Logger";
12
12
  import { useElapsedTime } from "../../../hooks/useElapsedTime";
13
13
  import { Tooltip } from "../../ui/tooltip";
@@ -18,11 +18,11 @@ import { formatElapsedTime, type Milliseconds, Time } from "@/utils/time";
18
18
 
19
19
  export interface CellStatusComponentProps {
20
20
  editing: boolean;
21
- edited: boolean;
22
21
  disabled: boolean;
23
22
  /** Whether a cell it depends on is disabled. */
24
23
  blocked: boolean;
25
- staleInputs: boolean;
24
+ /** Whether the cell's result is current. */
25
+ freshness: CellFreshness;
26
26
  status: CellRunStatus;
27
27
  /** Whether the cell's last run was interrupted. */
28
28
  interrupted: boolean;
@@ -38,8 +38,7 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
38
38
  status,
39
39
  disabled,
40
40
  blocked,
41
- staleInputs,
42
- edited,
41
+ freshness,
43
42
  interrupted,
44
43
  elapsedTime,
45
44
  startedAt,
@@ -48,6 +47,8 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
48
47
  if (!editing) {
49
48
  return null;
50
49
  }
50
+ const edited = freshness.sourceChanged;
51
+ const staleInputs = freshness.inputsChanged;
51
52
 
52
53
  const lastRanTime = startedAt ? (
53
54
  <LastRanTime lastRanTime={startedAt} />
@@ -0,0 +1,169 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { act, renderHook } from "@testing-library/react";
4
+ import { Provider } from "jotai";
5
+ import type { ReactNode } from "react";
6
+ import { afterEach, describe, expect, it, vi } from "vitest";
7
+ import { MockExecutions } from "@/__mocks__/executions";
8
+ import { MockNotebook } from "@/__mocks__/notebook";
9
+ import { MockRequestClient } from "@/__mocks__/requests";
10
+ import { cellId } from "@/__tests__/branded";
11
+ import { notebookAtom } from "@/core/cells/cells";
12
+ import {
13
+ cellExecutionInputsAtom,
14
+ cellExecutionView,
15
+ notebookQueuedOrRunningCountAtom,
16
+ } from "@/core/executions";
17
+ import { requestClientAtom } from "@/core/network/requests";
18
+ import type { DocumentModel } from "@/core/notebook/document";
19
+ import {
20
+ cell,
21
+ document as documentOf,
22
+ withCells,
23
+ } from "@/core/notebook/document/__tests__/fixtures";
24
+ import { activeDocumentModelAtom } from "@/core/session/active-notebook";
25
+ import { store } from "@/core/state/jotai";
26
+ import { runCells, useRunStaleCells } from "../useRunCells";
27
+
28
+ const ENABLED = cellId("enabled");
29
+ const DISABLED = cellId("disabled");
30
+
31
+ describe("runCells", () => {
32
+ it("sends a disabled cell to the kernel without reading it as queued", async () => {
33
+ MockExecutions.seed(store, []);
34
+ const notebook = MockNotebook.notebookState({
35
+ cellData: {
36
+ [ENABLED]: { code: "x = 1" },
37
+ [DISABLED]: { code: "y = 2", config: { disabled: true } },
38
+ },
39
+ });
40
+ const sendRun = vi.fn(async () => null);
41
+
42
+ await runCells({
43
+ cellIds: [ENABLED, DISABLED],
44
+ sendRun,
45
+ prepareForRun: vi.fn(),
46
+ notebook,
47
+ });
48
+
49
+ expect(sendRun).toHaveBeenCalledWith({
50
+ cellIds: [ENABLED, DISABLED],
51
+ codes: ["x = 1", "y = 2"],
52
+ });
53
+ const inputs = store.get(cellExecutionInputsAtom);
54
+ expect(cellExecutionView(inputs, ENABLED).status).toBe("queued");
55
+ expect(cellExecutionView(inputs, DISABLED).status).toBe("idle");
56
+ expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(1);
57
+ });
58
+ });
59
+
60
+ describe("useRunStaleCells", () => {
61
+ const C1 = cellId("c1");
62
+ const C2 = cellId("c2");
63
+
64
+ afterEach(() => {
65
+ store.set(activeDocumentModelAtom, null);
66
+ });
67
+
68
+ it("flushes pending edits before choosing the stale cells", async () => {
69
+ const document = documentOf();
70
+ const replica = MockExecutions.seed(
71
+ store,
72
+ [
73
+ MockExecutions.completed(C1, { code_fingerprint: "c1-hash" }),
74
+ MockExecutions.completed(C2, { code_fingerprint: "c2-hash" }),
75
+ ],
76
+ null,
77
+ document,
78
+ );
79
+ store.set(
80
+ notebookAtom,
81
+ MockNotebook.notebookState({
82
+ cellData: { [C1]: { code: "x = 2" }, [C2]: { code: "y = 2" } },
83
+ }),
84
+ );
85
+ const client = MockRequestClient.create();
86
+ store.set(requestClientAtom, client);
87
+ // The edit to c1 is still in flight: the host confirms it on flush.
88
+ const flush = vi.fn(async () => {
89
+ await new Promise((resolve) => setTimeout(resolve, 0));
90
+ store.set(
91
+ replica.documentAtom,
92
+ withCells(document, {
93
+ [C1]: cell(C1, "x = 2", { code_fingerprint: "c1-hash-2" }),
94
+ }),
95
+ );
96
+ });
97
+ store.set(activeDocumentModelAtom, { flush } as unknown as DocumentModel);
98
+ const wrapper = ({ children }: { children: ReactNode }) => (
99
+ <Provider store={store}>{children}</Provider>
100
+ );
101
+ const { result } = renderHook(useRunStaleCells, { wrapper });
102
+
103
+ await act(() => result.current());
104
+
105
+ expect(flush).toHaveBeenCalledOnce();
106
+ expect(client.sendRun).toHaveBeenCalledWith({
107
+ cellIds: [C1],
108
+ codes: ["x = 2"],
109
+ });
110
+ });
111
+
112
+ it("does nothing when the notebook changed while the flush was pending", async () => {
113
+ MockExecutions.seed(
114
+ store,
115
+ [MockExecutions.completed(C1, { code_fingerprint: "stale" })],
116
+ null,
117
+ documentOf(),
118
+ );
119
+ store.set(
120
+ notebookAtom,
121
+ MockNotebook.notebookState({ cellData: { [C1]: { code: "x = 1" } } }),
122
+ );
123
+ const client = MockRequestClient.create();
124
+ store.set(requestClientAtom, client);
125
+ const flush = vi.fn(async () => {
126
+ store.set(activeDocumentModelAtom, null);
127
+ throw new Error("aborted");
128
+ });
129
+ store.set(activeDocumentModelAtom, { flush } as unknown as DocumentModel);
130
+ const wrapper = ({ children }: { children: ReactNode }) => (
131
+ <Provider store={store}>{children}</Provider>
132
+ );
133
+ const { result } = renderHook(useRunStaleCells, { wrapper });
134
+
135
+ await act(() => result.current());
136
+
137
+ expect(client.sendRun).not.toHaveBeenCalled();
138
+ });
139
+
140
+ it("still runs what is stale when the flush fails", async () => {
141
+ MockExecutions.seed(
142
+ store,
143
+ [MockExecutions.completed(C1, { code_fingerprint: "stale" })],
144
+ null,
145
+ documentOf(),
146
+ );
147
+ store.set(
148
+ notebookAtom,
149
+ MockNotebook.notebookState({ cellData: { [C1]: { code: "x = 1" } } }),
150
+ );
151
+ const client = MockRequestClient.create();
152
+ store.set(requestClientAtom, client);
153
+ const flush = vi.fn(async () => {
154
+ throw new Error("offline");
155
+ });
156
+ store.set(activeDocumentModelAtom, { flush } as unknown as DocumentModel);
157
+ const wrapper = ({ children }: { children: ReactNode }) => (
158
+ <Provider store={store}>{children}</Provider>
159
+ );
160
+ const { result } = renderHook(useRunStaleCells, { wrapper });
161
+
162
+ await act(() => result.current());
163
+
164
+ expect(client.sendRun).toHaveBeenCalledWith({
165
+ cellIds: [C1],
166
+ codes: ["x = 1"],
167
+ });
168
+ });
169
+ });