@marimo-team/islands 0.25.3-dev29 → 0.25.3-dev30

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.
@@ -135,7 +135,7 @@ function F(e) {
135
135
  }
136
136
  //#endregion
137
137
  //#region src/components/editor/boundary/ErrorBoundary.tsx
138
- var I = (0, T.lazy)(() => import("./feedback-button-CykZqHY-.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
138
+ var I = (0, T.lazy)(() => import("./feedback-button-DlBBr16w.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
139
139
  let t = (0, w.c)(2), n;
140
140
  return t[0] === e.children ? n = t[1] : (n = /* @__PURE__ */ (0, j.jsx)(O, {
141
141
  FallbackComponent: R,
@@ -3,13 +3,13 @@ import { c as n, g as r, h as i, t as a } from "./button-CvjkwdSk.js";
3
3
  import { t as o } from "./react-sHtZdjeP.js";
4
4
  import { t as s } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { i as c, t as l } from "./copy-icon-BgUO8jsi.js";
6
- import { F as u, H as d, U as f, V as p, X as m, Y as h, Z as g, _, a as v, c as y, d as b, f as x, g as S, h as C, l as w, m as T, n as E, p as D, r as O, t as k, v as A, x as ee, y as te, z as ne } from "./html-to-image--r0l9wUy.js";
6
+ import { F as u, H as d, U as f, V as p, X as m, Y as h, Z as g, _, a as v, c as y, d as b, f as x, g as S, h as C, l as w, m as T, n as E, p as D, r as O, t as k, v as A, x as ee, y as te, z as ne } from "./html-to-image-BsG_zyNW.js";
7
7
  import { h as j, t as re } from "./tooltip-CtBZ5q8p.js";
8
- import { Ct as ie, Et as ae, Ht as oe, L as se, Lt as ce, Nt as le, St as ue, X as de, cn as fe, ct as pe, dn as me, en as he, et as ge, h as _e, i as ve, ln as ye, mn as be, mt as xe, r as Se, rt as Ce, st as we, t as Te, w as Ee, xt as De } from "./error-entries-DgtRTNaG.js";
8
+ import { Ct as ie, Et as ae, Ht as oe, L as se, Lt as ce, Nt as le, St as ue, X as de, cn as fe, ct as pe, dn as me, en as he, et as ge, h as _e, i as ve, ln as ye, mn as be, mt as xe, r as Se, rt as Ce, st as we, t as Te, w as Ee, xt as De } from "./error-entries-CnqKxhU9.js";
9
9
  import { A as Oe, C as ke, M as Ae, b as je } from "./select-DemoKT4G.js";
10
10
  import { _ as Me, f as Ne, h as Pe, i as Fe, n as Ie, t as Le } from "./dropdown-menu-BuE2b8Yb.js";
11
11
  import { C as Re, d as ze } from "./toDate-gyi35XS2.js";
12
- import { d as Be, f as Ve, i as He, n as Ue, t as We, u as Ge } from "./process-output-CuIlhYwn.js";
12
+ import { d as Be, f as Ve, i as He, n as Ue, t as We, u as Ge } from "./process-output-DgQrilBD.js";
13
13
  import { t as Ke } from "./jsx-runtime-3BD1kT0s.js";
14
14
  import { A as qe, B as Je, C as Ye, E as Xe, I as Ze, L as Qe, M as $e, N as et, O as tt, P as nt, S as rt, T as it, U as at, V as ot, b as st, k as ct, w as lt, x as ut, y as dt, z as ft } from "./use-restore-focus-CKjfFjLM.js";
15
15
  import { n as pt } from "./error-banner-CFPHFw4h.js";
@@ -1,6 +1,6 @@
1
1
  import { g as e } from "./button-CvjkwdSk.js";
2
2
  import { t } from "./compiler-runtime-CldRdSsv.js";
3
- import { G as n, K as r } from "./error-entries-DgtRTNaG.js";
3
+ import { G as n, K as r } from "./error-entries-CnqKxhU9.js";
4
4
  import { C as i } from "./select-DemoKT4G.js";
5
5
  import { _ as a, c as o, x as s, y as c } from "./toDate-gyi35XS2.js";
6
6
  import { C as l, E as u, a as d, b as f } from "./useTheme-Bu5bBgrh.js";
@@ -18,7 +18,7 @@ function x() {
18
18
  return e.warn("Failed to get version from mount config"), null;
19
19
  }
20
20
  }
21
- var S = x() || "0.25.3-dev29", C = u(S), w = u(!0);
21
+ var S = x() || "0.25.3-dev30", C = u(S), w = u(!0);
22
22
  u(null);
23
23
  //#endregion
24
24
  //#region src/core/wasm/state.ts
@@ -3,16 +3,16 @@ import { _ as t, c as n, f as r, g as i, h as a, m as o, n as s, p as c, r as l,
3
3
  import { t as d } from "./react-sHtZdjeP.js";
4
4
  import { t as f } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { i as p, n as m, r as h, t as g } from "./copy-icon-BgUO8jsi.js";
6
- import { $ as _, A as v, B as y, D as b, E as x, F as S, H as C, M as w, N as T, Q as E, S as D, T as O, V as k, W as A, X as j, Y as M, Z as N, _ as P, g as F, n as I, r as L, s as R, t as z, u as B, v as ee, w as V, y as te, z as ne } from "./html-to-image--r0l9wUy.js";
6
+ import { $ as _, A as v, B as y, D as b, E as x, F as S, H as C, M as w, N as T, Q as E, S as D, T as O, V as k, W as A, X as j, Y as M, Z as N, _ as P, g as F, n as I, r as L, s as R, t as z, u as B, v as ee, w as V, y as te, z as ne } from "./html-to-image-BsG_zyNW.js";
7
7
  import { a as re, d as ie, h as H, n as ae, o as oe, r as se, t as U } from "./tooltip-CtBZ5q8p.js";
8
- import { $ as ce, A as le, D as ue, Et as de, F as fe, G as pe, Ht as me, I as he, J as ge, K as _e, L as ve, Ot as ye, Rt as be, T as xe, Ut as Se, V as Ce, Xt as we, Yt as Te, Zt as Ee, _t as De, an as Oe, at as ke, b as Ae, c as je, cn as Me, dn as Ne, en as Pe, gn as Fe, gt as Ie, h as Le, hn as Re, l as ze, ln as Be, lt as Ve, mn as He, mt as Ue, on as We, ot as Ge, rn as Ke, st as qe, t as Je, un as Ye, vt as Xe, w as Ze, x as Qe, y as $e } from "./error-entries-DgtRTNaG.js";
8
+ import { $ as ce, A as le, D as ue, Et as de, F as fe, G as pe, Ht as me, I as he, J as ge, K as _e, L as ve, Ot as ye, Rt as be, T as xe, Ut as Se, V as Ce, Xt as we, Yt as Te, Zt as Ee, _t as De, an as Oe, at as ke, b as Ae, c as je, cn as Me, dn as Ne, en as Pe, gn as Fe, gt as Ie, h as Le, hn as Re, l as ze, ln as Be, lt as Ve, mn as He, mt as Ue, on as We, ot as Ge, rn as Ke, st as qe, t as Je, un as Ye, vt as Xe, w as Ze, x as Qe, y as $e } from "./error-entries-CnqKxhU9.js";
9
9
  import { c as et, i as tt, r as nt } from "./useLifecycle-Dfq8UD-b.js";
10
10
  import { a as rt, i as it, n as at, o as ot, r as st, t as ct } from "./useDateFormatter-DkajGwwd.js";
11
11
  import { t as lt } from "./check-BMKBBrdc.js";
12
12
  import { A as ut, C as dt, M as ft, O as pt, S as mt, _ as ht, b as gt, c as _t, d as vt, g as yt, h as bt, i as xt, l as St, m as Ct, n as wt, p as Tt, s as Et, t as Dt, u as Ot, v as kt, y as At } from "./select-DemoKT4G.js";
13
13
  import { $ as jt, $t as Mt, A as Nt, At as Pt, B as Ft, Bt as It, Ct as Lt, D as Rt, Dt as zt, E as Bt, Et as Vt, F as Ht, Ft as Ut, G as Wt, Gt, H as Kt, Ht as qt, I as Jt, It as Yt, J as Xt, Jt as Zt, Kt as Qt, L as $t, Lt as en, M as tn, Mt as nn, N as rn, Nt as an, O as on, Ot as sn, P as cn, Pt as ln, Q as un, Qt as dn, R as fn, Rt as pn, S as mn, St as hn, T as gn, Tt as _n, U as vn, Ut as yn, V as bn, Vt as xn, W as Sn, Wt as Cn, X as wn, Xt as Tn, Y as En, Yt as Dn, Z as On, Zt as kn, _ as An, _n as jn, _t as Mn, a as Nn, at as Pn, b as Fn, bt as In, cn as Ln, ct as Rn, d as zn, dn as Bn, dt as Vn, et as Hn, f as Un, fn as Wn, ft as Gn, gn as Kn, gt as qn, h as Jn, hn as Yn, ht as Xn, i as Zn, in as Qn, it as $n, j as er, jt as tr, k as nr, kt as rr, l as ir, lt as ar, mn as or, mt as sr, n as cr, nn as lr, nt as ur, o as dr, on as fr, ot as pr, pn as mr, pt as hr, qt as gr, rn as _r, rt as vr, s as yr, sn as br, st as xr, t as Sr, tn as Cr, tt as wr, u as Tr, un as Er, vn as Dr, vt as Or, w as kr, wt as Ar, x as jr, xt as Mr, y as Nr, yt as Pr, z as Fr, zt as Ir } from "./dropdown-menu-BuE2b8Yb.js";
14
14
  import { a as Lr, c as Rr, d as zr, i as Br, l as Vr, n as Hr, o as Ur, r as Wr, t as Gr, v as Kr, x as qr, y as Jr } from "./toDate-gyi35XS2.js";
15
- import { n as Yr, t as Xr } from "./ErrorBoundary-ysC54Xwn.js";
15
+ import { n as Yr, t as Xr } from "./ErrorBoundary-2Tp_7IgE.js";
16
16
  import { t as Zr } from "./clsx-CoeGtWvn.js";
17
17
  import { t as Qr } from "./react-dom-DUmH0GXv.js";
18
18
  import { t as $r } from "./jsx-runtime-3BD1kT0s.js";
@@ -2,7 +2,7 @@ import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
3
  import { t as n } from "./react-dom-DUmH0GXv.js";
4
4
  import { c as r, l as i, u as a } from "./data-grid-types-0PJ-9N5n.js";
5
- import { a as o, i as s, n as c, r as l } from "./glide-data-editor-DLHbRbsj.js";
5
+ import { a as o, i as s, n as c, r as l } from "./glide-data-editor-ugYWecYd.js";
6
6
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/data-grid-overlay-editor-style.js
7
7
  var u = /* @__PURE__ */ e(t(), 1), d = /* @__PURE__ */ e(n(), 1), f = /*#__PURE__*/ o("div")({
8
8
  name: "DataGridOverlayEditorStyle",
@@ -26077,7 +26077,7 @@ function Gv(e, t) {
26077
26077
  //#endregion
26078
26078
  //#region src/components/editor/connections/components.tsx
26079
26079
  function Kv() {
26080
- let e = (0, Tr.c)(4), { createNewCell: t } = Fx(), n = Wv(), r = Me(Fe), i;
26080
+ let e = (0, Tr.c)(4), { createNewCell: t } = Ix(), n = Wv(), r = Me(Fe), i;
26081
26081
  return e[0] !== r || e[1] !== t || e[2] !== n ? (i = (e) => {
26082
26082
  /\bmo\./.test(e) && Iv({
26083
26083
  autoInstantiate: r,
@@ -28223,7 +28223,7 @@ var { reducer: ux, addMiddleware: dx, createActions: fx, useActions: px, valueAt
28223
28223
  let i = r.indexOfOrThrow(n), o = i === 0 ? 1 : i - 1, s = null;
28224
28224
  r.length > 1 && (s = r.atOrThrow(o));
28225
28225
  let c = (e.cellHandles[n].current?.editorView)?.state.toJSON({ history: Tt });
28226
- c && (c.doc = e.cellData[n].code), Mx(n);
28226
+ c && (c.doc = e.cellData[n].code), Nx(n);
28227
28227
  let l = e.cellData[n];
28228
28228
  return {
28229
28229
  ...e,
@@ -28807,7 +28807,7 @@ var bx = A((e) => {
28807
28807
  return null;
28808
28808
  }).filter(Boolean);
28809
28809
  }), xx = A((e) => {
28810
- let { cellIds: t, cellRuntime: n } = e($);
28810
+ let t = e(vx), n = e(Ox);
28811
28811
  return Ky(t.inOrderIds.map((e) => n[e].outline));
28812
28812
  });
28813
28813
  A((e) => e(bx).length);
@@ -28820,27 +28820,29 @@ var Cx = () => Me(vx), wx = () => Me(Sx), Tx = () => j.get($), Ex = () => j.get(
28820
28820
  let { cellIds: e, cellData: t } = j.get($);
28821
28821
  return e.inOrderIds.map((e) => t[e]?.name).filter(Boolean);
28822
28822
  };
28823
- br(pr($, (e) => e.cellIds.inOrderIds.map((t) => e.cellData[t]))), A((e) => e($).cellRuntime), A((e) => Hc(e($))), A((e) => {
28823
+ br(pr($, (e) => e.cellIds.inOrderIds.map((t) => e.cellData[t])));
28824
+ var Ox = A((e) => e($).cellRuntime);
28825
+ A((e) => Hc(e($))), A((e) => {
28824
28826
  let { cellRuntime: t } = e($);
28825
28827
  return Object.entries(t).every(([e, t]) => t.status !== "running" || e === "__scratch__");
28826
28828
  }), A((e) => Uc(e($)));
28827
- var Ox = A((e) => e($).cellIds.colLength);
28829
+ var kx = A((e) => e($).cellIds.colLength);
28828
28830
  A((e) => e($).cellIds.idLength > 0), A((e) => e($).cellIds.getColumnIds());
28829
- var kx = lr((e) => A((t) => t($).cellData[e])), Ax = lr((e) => A((t) => t($).cellRuntime[e])), jx = lr((e) => A((t) => t($).cellHandles[e]));
28830
- function Mx(e) {
28831
- kx.remove(e), Ax.remove(e), jx.remove(e);
28831
+ var Ax = lr((e) => A((t) => t($).cellData[e])), jx = lr((e) => A((t) => t($).cellRuntime[e])), Mx = lr((e) => A((t) => t($).cellHandles[e]));
28832
+ function Nx(e) {
28833
+ Ax.remove(e), jx.remove(e), Mx.remove(e);
28832
28834
  }
28833
- var Nx = (e) => {
28835
+ var Px = (e) => {
28834
28836
  let { cellHandles: t } = j.get($);
28835
28837
  return t[e].current?.editorView;
28836
- }, Px = (e) => (Ei.promote(e), Nx(e));
28837
- function Fx(e) {
28838
+ }, Fx = (e) => (Ei.promote(e), Px(e));
28839
+ function Ix(e) {
28838
28840
  let t = (0, Tr.c)(2), n;
28839
28841
  return t[0] === e ? n = t[1] : (n = e === void 0 ? {} : e, t[0] = e, t[1] = n), px(n);
28840
28842
  }
28841
28843
  //#endregion
28842
28844
  //#region src/core/errors/error-entries.ts
28843
- function Ix(e) {
28845
+ function Lx(e) {
28844
28846
  if (zc(e.mimetype)) {
28845
28847
  if (!Array.isArray(e.data)) return null;
28846
28848
  let t = e.data.filter((e) => !e.type.includes("ancestor"));
@@ -28851,23 +28853,23 @@ function Ix(e) {
28851
28853
  tracebackHtml: e.data
28852
28854
  } : null;
28853
28855
  }
28854
- function Lx(e) {
28856
+ function Rx(e) {
28855
28857
  return e.some((e) => "traceback" in e && e.traceback);
28856
28858
  }
28857
- function Rx(e) {
28859
+ function zx(e) {
28858
28860
  let t = e?.find((e) => Bc(e.mimetype));
28859
28861
  if (!(!t || typeof t.data != "string" || t.data.length === 0)) return t.data;
28860
28862
  }
28861
- function zx(e, t) {
28863
+ function Bx(e, t) {
28862
28864
  if (e.tracebackHtml) return e.tracebackHtml;
28863
- if (!Lx(e.errorData)) return Rx(t);
28865
+ if (!Rx(e.errorData)) return zx(t);
28864
28866
  }
28865
- function Bx(e) {
28867
+ function Vx(e) {
28866
28868
  let { cellIds: t, cellRuntime: n, cellData: r } = e.get($), i = [];
28867
28869
  for (let [e, a] of t.inOrderIds.entries()) {
28868
28870
  let t = n[a], o = t.output;
28869
28871
  if (!o || !Vc(o.mimetype)) continue;
28870
- let s = Ix(o);
28872
+ let s = Lx(o);
28871
28873
  if (!s) continue;
28872
28874
  let c = hv(r[a].name, e), l = r[a].lastCodeRun ?? r[a].code;
28873
28875
  i.push({
@@ -28875,21 +28877,21 @@ function Bx(e) {
28875
28877
  cellName: c,
28876
28878
  cellCode: l,
28877
28879
  errorData: s.errorData,
28878
- tracebackHtml: zx(s, t.consoleOutputs)
28880
+ tracebackHtml: Bx(s, t.consoleOutputs)
28879
28881
  });
28880
28882
  }
28881
28883
  return i;
28882
28884
  }
28883
- function Vx(e) {
28885
+ function Hx(e) {
28884
28886
  return e.type === "setup-refs" ? "The setup cell cannot have references" : e.type === "cycle" ? "This cell is in a cycle" : e.type === "multiple-defs" ? `The variable '${e.name}' was defined by another cell` : e.type === "import-star" || e.type === "ancestor-stopped" || e.type === "ancestor-prevented" || e.type === "exception" || e.type === "strict-exception" ? e.msg : e.type === "interruption" ? "This cell was interrupted and needs to be re-run" : e.type === "syntax" || e.type === "unknown" || e.type === "sql-error" ? e.msg : e.type === "internal" ? e.msg || "An internal error occurred" : (T(e), "Unknown error");
28885
28887
  }
28886
- function Hx(e) {
28887
- let t = Vx(e);
28888
+ function Ux(e) {
28889
+ let t = Hx(e);
28888
28890
  return "traceback" in e && e.traceback && (t += `\n\nTraceback:\n${Gb(e.traceback)}`), t;
28889
28891
  }
28890
- function Ux(e) {
28892
+ function Wx(e) {
28891
28893
  let t = [e.cellName];
28892
- return e.tracebackHtml && t.push(Gb(e.tracebackHtml)), e.errorData.length > 0 && t.push(e.errorData.map(Hx).join("\n\n")), t.join("\n\n");
28894
+ return e.tracebackHtml && t.push(Gb(e.tracebackHtml)), e.errorData.length > 0 && t.push(e.errorData.map(Ux).join("\n\n")), t.join("\n\n");
28893
28895
  }
28894
28896
  //#endregion
28895
- export { bf as $, cr as $t, By as A, Gc as At, pv as B, ei as Bt, Kb as C, Fl as Ct, lb as D, el as Dt, jb as E, nl as Et, bv as F, ui as Ft, wm as G, Xr as Gt, uv as H, Zr as Ht, xv as I, ci as It, Np as J, Vr as Jt, Cm as K, Yr as Kt, hv as L, li as Lt, Wv as M, $c as Mt, Lv as N, Mc as Nt, ub as O, tl as Ot, Iv as P, hi as Pt, Vf as Q, Er as Qt, mv as R, ri as Rt, ax as S, Al as St, Rb as T, hl as Tt, U_ as U, Jr as Ut, dv as V, ti as Vt, Vm as W, Gr as Wt, np as X, Ir as Xt, yp as Y, Fr as Yt, Hf as Z, Nr as Zt, Ox as _, Kl as _t, kx as a, Nn as an, zd as at, Cx as b, Bl as bt, Px as c, En as cn, Cd as ct, Ex as d, Sn as dn, dd as dt, wr as en, sf as et, Tx as f, xn as fn, cd as ft, xx as g, pn as gn, Wl as gt, $ as h, hn, Jl as ht, Bx as i, Pn as in, Hd as it, Hv as j, Qc as jt, Gy as k, Zc as kt, Nx as l, wn as ln, vd as lt, lx as m, gn as mn, ql as mt, Ux as n, Bn as nn, Xd as nt, vx as o, jn as on, Td as ot, yx as p, yn as pn, hu as pt, Pp as q, Br as qt, Hx as r, Ln as rn, Jd as rt, fx as s, kn as sn, Ed as st, Vx as t, pr as tn, Qd as tt, Dx as u, Cn as un, gd as ut, ux as v, Gl as vt, Gb as w, _l as wt, wx as x, Pl as xt, Fx as y, Hl as yt, gv as z, $r as zt };
28897
+ export { bf as $, cr as $t, By as A, Gc as At, pv as B, ei as Bt, Kb as C, Fl as Ct, lb as D, el as Dt, jb as E, nl as Et, bv as F, ui as Ft, wm as G, Xr as Gt, uv as H, Zr as Ht, xv as I, ci as It, Np as J, Vr as Jt, Cm as K, Yr as Kt, hv as L, li as Lt, Wv as M, $c as Mt, Lv as N, Mc as Nt, ub as O, tl as Ot, Iv as P, hi as Pt, Vf as Q, Er as Qt, mv as R, ri as Rt, ax as S, Al as St, Rb as T, hl as Tt, U_ as U, Jr as Ut, dv as V, ti as Vt, Vm as W, Gr as Wt, np as X, Ir as Xt, yp as Y, Fr as Yt, Hf as Z, Nr as Zt, kx as _, Kl as _t, Ax as a, Nn as an, zd as at, Cx as b, Bl as bt, Fx as c, En as cn, Cd as ct, Ex as d, Sn as dn, dd as dt, wr as en, sf as et, Tx as f, xn as fn, cd as ft, xx as g, pn as gn, Wl as gt, $ as h, hn, Jl as ht, Vx as i, Pn as in, Hd as it, Hv as j, Qc as jt, Gy as k, Zc as kt, Px as l, wn as ln, vd as lt, lx as m, gn as mn, ql as mt, Wx as n, Bn as nn, Xd as nt, vx as o, jn as on, Td as ot, yx as p, yn as pn, hu as pt, Pp as q, Br as qt, Ux as r, Ln as rn, Jd as rt, fx as s, kn as sn, Ed as st, Hx as t, pr as tn, Qd as tt, Dx as u, Cn as un, gd as ut, ux as v, Gl as vt, Gb as w, _l as wt, wx as x, Pl as xt, Ix as y, Hl as yt, gv as z, $r as zt };
@@ -3,14 +3,14 @@ import { h as t, t as n } from "./button-CvjkwdSk.js";
3
3
  import { t as r } from "./react-sHtZdjeP.js";
4
4
  import { t as i } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { t as a } from "./copy-icon-BgUO8jsi.js";
6
- import { Dt as o, G as s, It as c, K as l, Rt as u, V as d, dn as f, h as p, i as m, n as h } from "./error-entries-DgtRTNaG.js";
6
+ import { Dt as o, G as s, It as c, K as l, Rt as u, V as d, dn as f, h as p, i as m, n as h } from "./error-entries-CnqKxhU9.js";
7
7
  import { b as g } from "./select-DemoKT4G.js";
8
- import { n as ee, t as te } from "./globals-D2g1BHQ0.js";
8
+ import { n as ee, t as te } from "./globals-BdBjL67a.js";
9
9
  import { t as _ } from "./jsx-runtime-3BD1kT0s.js";
10
10
  import { C as v, _ as ne, i as y } from "./useTheme-Bu5bBgrh.js";
11
11
  import { a as re, i as ie, n as ae, r as oe } from "./dialog-Cc479ZEH.js";
12
12
  import { t as se } from "./useAsyncData-BneN349z.js";
13
- import { t as ce } from "./code-visibility-CZmyRTO8.js";
13
+ import { t as ce } from "./code-visibility-891-xGjh.js";
14
14
  //#region src/components/ui/skeleton.tsx
15
15
  var b = /* @__PURE__ */ e(r(), 1), x = i(), S = _(), le = (e) => {
16
16
  let n = (0, x.c)(8), r, i;
@@ -6,7 +6,7 @@ import { i as s, n as c, r as l } from "./copy-icon-BgUO8jsi.js";
6
6
  import { C as u, c as d, i as f, n as p, s as m, t as h, x as g } from "./select-DemoKT4G.js";
7
7
  import { d as _, h as v, i as y, l as b, n as x, o as S, s as C, t as w, u as T } from "./dropdown-menu-BuE2b8Yb.js";
8
8
  import { c as E, d as D, l as O, n as k, o as A, s as ee, t as j, u as te } from "./glide-utils-pisbYVjH.js";
9
- import { n as ne, t as re } from "./ErrorBoundary-ysC54Xwn.js";
9
+ import { n as ne, t as re } from "./ErrorBoundary-2Tp_7IgE.js";
10
10
  import { t as M } from "./react-dom-DUmH0GXv.js";
11
11
  import { t as N } from "./jsx-runtime-3BD1kT0s.js";
12
12
  import { t as ie } from "./label-DoysmLMW.js";
@@ -7062,7 +7062,7 @@ function rs(e, t, n, r, i) {
7062
7062
  }
7063
7063
  //#endregion
7064
7064
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/data-editor/data-editor.js
7065
- var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-B141KnZO.js")), ss = 0;
7065
+ var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-TVf1Kaxm.js")), ss = 0;
7066
7066
  function cs(e) {
7067
7067
  return (0, is.default)((0, as.default)((0, as.default)(e).filter((e) => e.span !== void 0).map((e) => (0, Za.default)((e.span?.[0] ?? 0) + 1, (e.span?.[1] ?? 0) + 1))));
7068
7068
  }
@@ -9293,7 +9293,7 @@ function Vs(e, t, n, r, i) {
9293
9293
  }
9294
9294
  //#endregion
9295
9295
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/cells/number-cell.js
9296
- var Hs = K.lazy(async () => await import("./number-overlay-editor-DHqP6YVn.js")), Us = {
9296
+ var Hs = K.lazy(async () => await import("./number-overlay-editor-I4AHjcHG.js")), Us = {
9297
9297
  getAccessibilityString: (e) => e.data?.toString() ?? "",
9298
9298
  kind: W.Number,
9299
9299
  needsHover: (e) => e.hoverEffect === !0,
@@ -1,6 +1,6 @@
1
1
  import { h as e } from "./tooltip-CtBZ5q8p.js";
2
2
  import { _ as t } from "./useTheme-Bu5bBgrh.js";
3
- import { r as n } from "./code-visibility-CZmyRTO8.js";
3
+ import { r as n } from "./code-visibility-891-xGjh.js";
4
4
  var r = e("triangle-alert", [
5
5
  ["path", {
6
6
  d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
@@ -5,7 +5,7 @@ import { t as l } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { n as u, t as d } from "./copy-icon-BgUO8jsi.js";
6
6
  import { a as f, c as p, l as m, s as h, t as g } from "./chunk-YOKDWASO-DKplTrBY.js";
7
7
  import { c as _, h as v, l as y, s as b, t as x, u as ee } from "./tooltip-CtBZ5q8p.js";
8
- import { A as te, Ct as ne, Et as re, H as ie, M as ae, P as oe, Pt as se, Qt as ce, St as le, Tt as ue, U as de, Y as fe, a as pe, bt as me, d as he, it as ge, pt as _e, tn as ve, tt as ye, xt as be, y as xe, yt as Se } from "./error-entries-DgtRTNaG.js";
8
+ import { A as te, Ct as ne, Et as re, H as ie, M as ae, P as oe, Pt as se, Qt as ce, St as le, Tt as ue, U as de, Y as fe, a as pe, bt as me, d as he, it as ge, pt as _e, tn as ve, tt as ye, xt as be, y as xe, yt as Se } from "./error-entries-CnqKxhU9.js";
9
9
  import { M as Ce, O as we, k as Te } from "./select-DemoKT4G.js";
10
10
  import { dt as Ee, q as De } from "./dropdown-menu-BuE2b8Yb.js";
11
11
  import { m as Oe, y as ke } from "./toDate-gyi35XS2.js";
package/dist/main.js CHANGED
@@ -3,20 +3,20 @@ import { _ as a, c as o, g as s, h as c, i as l, l as u, m as d, n as f, o as p,
3
3
  import { t as v } from "./react-sHtZdjeP.js";
4
4
  import { t as y } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { i as b, n as x, r as S, t as C } from "./copy-icon-BgUO8jsi.js";
6
- import { C as w, F as T, G as E, I as D, J as O, K as k, L as A, P as j, R as M, X as N, Z as P, _ as F, a as I, b as L, g as R, i as z, j as B, k as ee, n as te, o as ne, q as re, v as ie, y as ae } from "./html-to-image--r0l9wUy.js";
6
+ import { C as w, F as T, G as E, I as D, J as O, K as k, L as A, P as j, R as M, X as N, Z as P, _ as F, a as I, b as L, g as R, i as z, j as B, k as ee, n as te, o as ne, q as re, v as ie, y as ae } from "./html-to-image-BsG_zyNW.js";
7
7
  import { a as oe, d as se, f as ce, h as V, i as le, n as ue, o as de, r as fe, t as pe } from "./tooltip-CtBZ5q8p.js";
8
- import { $t as me, At as he, B as ge, Bt as _e, D as ve, Dt as ye, E as be, Et as xe, Ft as Se, Gt as Ce, J as we, Jt as Te, Kt as Ee, M as De, Mt as Oe, N as ke, O as Ae, Ot as je, Q as Me, R as Ne, S as Pe, Ut as Fe, V as Ie, Vt as Le, W as Re, Y as ze, Yt as Be, Z as Ve, _ as He, b as Ue, bt as We, cn as Ge, dt as Ke, en as qe, f as Je, fn as Ye, ft as Xe, g as Ze, gn as Qe, gt as $e, h as et, hn as tt, ht as nt, in as rt, j as it, jt as at, k as ot, kt as st, ln as ct, m as lt, nn as ut, nt as dt, o as ft, p as pt, pn as mt, q as ht, qt as gt, rt as _t, s as vt, sn as yt, st as bt, tn as xt, u as St, un as Ct, ut as wt, v as Tt, wt as Et, y as Dt, z as Ot, zt as kt } from "./error-entries-DgtRTNaG.js";
8
+ import { $t as me, At as he, B as ge, Bt as _e, D as ve, Dt as ye, E as be, Et as xe, Ft as Se, Gt as Ce, J as we, Jt as Te, Kt as Ee, M as De, Mt as Oe, N as ke, O as Ae, Ot as je, Q as Me, R as Ne, S as Pe, Ut as Fe, V as Ie, Vt as Le, W as Re, Y as ze, Yt as Be, Z as Ve, _ as He, b as Ue, bt as We, cn as Ge, dt as Ke, en as qe, f as Je, fn as Ye, ft as Xe, g as Ze, gn as Qe, gt as $e, h as et, hn as tt, ht as nt, in as rt, j as it, jt as at, k as ot, kt as st, ln as ct, m as lt, nn as ut, nt as dt, o as ft, p as pt, pn as mt, q as ht, qt as gt, rt as _t, s as vt, sn as yt, st as bt, tn as xt, u as St, un as Ct, ut as wt, v as Tt, wt as Et, y as Dt, z as Ot, zt as kt } from "./error-entries-CnqKxhU9.js";
9
9
  import { D as At, E as jt, O as Mt, S as Nt, T as Pt, _ as Ft, a as It, c as Lt, d as Rt, f as zt, g as Bt, h as Vt, i as Ht, l as Ut, m as Wt, n as Gt, o as Kt, p as qt, r as Jt, s as Yt, t as Xt, u as Zt, v as Qt, w as $t, x as en, y as tn } from "./spec-D_u2ipzF.js";
10
- import { $t as nn, A as rn, At as an, B as on, Bt as sn, C as cn, Ct as ln, D as un, Dt as dn, E as fn, Et as pn, F as mn, Ft as hn, G as gn, Gt as _n, H as vn, Ht as yn, I as bn, It as xn, J as Sn, Jt as Cn, K as wn, Kt as Tn, L as En, Lt as Dn, M as On, Mt as kn, N as An, Nt as jn, O as Mn, Ot as Nn, P as Pn, Pt as Fn, Qt as In, R as Ln, Rt as Rn, S as zn, St as Bn, T as Vn, Tt as Hn, U as Un, Ut as Wn, V as Gn, Vt as Kn, W as qn, Wt as Jn, X as Yn, Xt as Xn, Y as Zn, Yt as Qn, Zt as $n, _ as er, _t as tr, an as nr, at as rr, b as ir, c as ar, cn as or, ct as sr, d as cr, dn as lr, dt as ur, en as dr, et as fr, f as pr, fn as mr, ft as hr, g as gr, gt as _r, h as vr, hn as yr, ht as br, in as xr, it as Sr, j as Cr, jt as wr, k as Tr, kt as Er, ln as Dr, lt as Or, m as kr, mn as Ar, mt as jr, nn as Mr, nt as Nr, ot as Pr, p as Fr, pn as Ir, pt as Lr, q as Rr, qt as zr, r as Br, rn as Vr, rt as Hr, sn as Ur, st as Wr, t as Gr, tn as Kr, tt as qr, u as Jr, un as Yr, ut as Xr, v as Zr, vt as Qr, w as $r, wt as ei, x as ti, y as ni, yt as ri, z as ii, zt as ai } from "./common-CCrzSQnL.js";
10
+ import { $t as nn, A as rn, At as an, B as on, Bt as sn, C as cn, Ct as ln, D as un, Dt as dn, E as fn, Et as pn, F as mn, Ft as hn, G as gn, Gt as _n, H as vn, Ht as yn, I as bn, It as xn, J as Sn, Jt as Cn, K as wn, Kt as Tn, L as En, Lt as Dn, M as On, Mt as kn, N as An, Nt as jn, O as Mn, Ot as Nn, P as Pn, Pt as Fn, Qt as In, R as Ln, Rt as Rn, S as zn, St as Bn, T as Vn, Tt as Hn, U as Un, Ut as Wn, V as Gn, Vt as Kn, W as qn, Wt as Jn, X as Yn, Xt as Xn, Y as Zn, Yt as Qn, Zt as $n, _ as er, _t as tr, an as nr, at as rr, b as ir, c as ar, cn as or, ct as sr, d as cr, dn as lr, dt as ur, en as dr, et as fr, f as pr, fn as mr, ft as hr, g as gr, gt as _r, h as vr, hn as yr, ht as br, in as xr, it as Sr, j as Cr, jt as wr, k as Tr, kt as Er, ln as Dr, lt as Or, m as kr, mn as Ar, mt as jr, nn as Mr, nt as Nr, ot as Pr, p as Fr, pn as Ir, pt as Lr, q as Rr, qt as zr, r as Br, rn as Vr, rt as Hr, sn as Ur, st as Wr, t as Gr, tn as Kr, tt as qr, u as Jr, un as Yr, ut as Xr, v as Zr, vt as Qr, w as $r, wt as ei, x as ti, y as ni, yt as ri, z as ii, zt as ai } from "./common-_IunO2z-.js";
11
11
  import { c as oi, i as si, n as ci, o as li, t as ui } from "./useLifecycle-Dfq8UD-b.js";
12
12
  import { t as di } from "./check-BMKBBrdc.js";
13
13
  import { A as fi, C as pi, D as mi, E as hi, M as gi, O as _i, S as vi, T as yi, a as bi, b as xi, c as Si, i as Ci, k as wi, l as Ti, n as Ei, o as Di, r as Oi, s as ki, t as Ai, w as ji, x as Mi } from "./select-DemoKT4G.js";
14
14
  import { $ as Ni, C as Pi, Et as Fi, J as Ii, K as Li, R as Ri, S as zi, U as Bi, Y as Vi, _ as Hi, _n as Ui, a as Wi, c as Gi, f as Ki, g as qi, h as Ji, i as Yi, kt as Xi, m as Zi, mt as Qi, n as $i, p as ea, q as ta, r as na, s as ra, t as ia, ut as aa, v as oa, vn as sa, x as ca, z as la } from "./dropdown-menu-BuE2b8Yb.js";
15
15
  import { C as ua, _ as da, a as fa, b as pa, c as ma, f as ha, h as ga, m as _a, p as va, s as ya, u as ba, x as xa, y as Sa } from "./toDate-gyi35XS2.js";
16
- import { a as Ca, c as wa, d as Ta, f as Ea, i as Da, l as Oa, n as ka, o as Aa, r as ja, s as Ma, t as Na } from "./process-output-CuIlhYwn.js";
16
+ import { a as Ca, c as wa, d as Ta, f as Ea, i as Da, l as Oa, n as ka, o as Aa, r as ja, s as Ma, t as Na } from "./process-output-DgQrilBD.js";
17
17
  import { a as Pa, c as Fa, d as Ia, i as La, l as Ra, r as za, u as Ba } from "./glide-utils-pisbYVjH.js";
18
- import { n as Va, t as Ha } from "./ErrorBoundary-ysC54Xwn.js";
19
- import { n as Ua, t as Wa } from "./globals-D2g1BHQ0.js";
18
+ import { n as Va, t as Ha } from "./ErrorBoundary-2Tp_7IgE.js";
19
+ import { n as Ua, t as Wa } from "./globals-BdBjL67a.js";
20
20
  import { t as Ga } from "./react-dom-DUmH0GXv.js";
21
21
  import { t as Ka } from "./jsx-runtime-3BD1kT0s.js";
22
22
  import { A as qa, B as Ja, C as H, Ct as Ya, Dt as Xa, Et as Za, F as Qa, G as $a, H as eo, I as to, J as no, K as ro, L as U, N as W, O as io, Ot as ao, P as G, Q as oo, R as so, S as co, St as lo, T as uo, Tt as fo, W as po, _ as mo, a as ho, b as go, bt as _o, c as vo, d as yo, et as bo, f as xo, g as So, h as Co, i as wo, j as To, k as Eo, m as Do, n as Oo, o as ko, p as Ao, pt as jo, r as Mo, s as No, tt as Po, u as Fo, v as Io, vt as Lo, w as K, wt as Ro, x as zo, xt as Bo, y as Vo, z as Ho } from "./use-restore-focus-CKjfFjLM.js";
@@ -39,7 +39,7 @@ import { t as Ms } from "./useAsyncData-BneN349z.js";
39
39
  import { i as Ns, n as Ps, r as Fs } from "./formats-DRHUWwSK.js";
40
40
  import { D as Is, O as Ls } from "./vega-loader.browser-CpbZAXub.js";
41
41
  import { a as Rs, n as zs } from "./loader-BPdQhmlq.js";
42
- import { c as Bs, d as Vs, i as Hs, l as Us, o as Ws, s as Gs, t as Ks, u as qs } from "./code-visibility-CZmyRTO8.js";
42
+ import { c as Bs, d as Vs, i as Hs, l as Us, o as Ws, s as Gs, t as Ks, u as qs } from "./code-visibility-891-xGjh.js";
43
43
  import { t as Js } from "./useDeepCompareMemoize-Z_7R8wTt.js";
44
44
  import { t as Ys } from "./esm-D2gTsXEV.js";
45
45
  //#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
@@ -10067,7 +10067,7 @@ var LS = (e) => {
10067
10067
  output: t
10068
10068
  };
10069
10069
  } };
10070
- } }, US = J.lazy(() => import("./chat-ui-0udY4hpv.js").then((e) => ({ default: e.Chatbot }))), WS = H(G({
10070
+ } }, US = J.lazy(() => import("./chat-ui-BeKQyQQI.js").then((e) => ({ default: e.Chatbot }))), WS = H(G({
10071
10071
  id: U(),
10072
10072
  role: Vo([
10073
10073
  "system",
@@ -10533,7 +10533,7 @@ function VC(e, t) {
10533
10533
  }
10534
10534
  //#endregion
10535
10535
  //#region src/plugins/impl/DataEditorPlugin.tsx
10536
- var HC = J.lazy(() => import("./glide-data-editor-DLHbRbsj.js").then((e) => e.t)), UC = wS("marimo-data-editor", { cssStyles: [qS] }).withData(G({
10536
+ var HC = J.lazy(() => import("./glide-data-editor-ugYWecYd.js").then((e) => e.t)), UC = wS("marimo-data-editor", { cssStyles: [qS] }).withData(G({
10537
10537
  initialValue: G({ edits: H(G({
10538
10538
  rowIdx: W(),
10539
10539
  columnId: U(),
@@ -30107,7 +30107,7 @@ function OR(e) {
30107
30107
  }
30108
30108
  //#endregion
30109
30109
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
30110
- var kR = J.lazy(() => import("./reveal-component-DYHhtPqq.js")), AR = (e) => {
30110
+ var kR = J.lazy(() => import("./reveal-component-Bb5vzlMs.js")), AR = (e) => {
30111
30111
  let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = ns(da), s = a === "read" || o, c = ns(He) > 1, [l, u] = (0, J.useState)(null), d;
30112
30112
  t[0] !== i || t[1] !== n ? (d = EP(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
30113
30113
  let { slideCells: f, skippedIds: p, noOutputIds: m, slideTypes: h, startCellIndex: g } = d, _;
@@ -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 { a as n } from "./glide-data-editor-DLHbRbsj.js";
3
+ import { a as n } from "./glide-data-editor-ugYWecYd.js";
4
4
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/private/number-overlay-editor-style.js
5
5
  var r = /* @__PURE__ */ e(t()), i = /*#__PURE__*/ n("div")({
6
6
  name: "NumberOverlayEditorStyle",
@@ -1,6 +1,6 @@
1
- import { O as e } from "./html-to-image--r0l9wUy.js";
1
+ import { O as e } from "./html-to-image-BsG_zyNW.js";
2
2
  import { h as t } from "./tooltip-CtBZ5q8p.js";
3
- import { C as n, w as r } from "./error-entries-DgtRTNaG.js";
3
+ import { C as n, w as r } from "./error-entries-CnqKxhU9.js";
4
4
  import { b as i } from "./select-DemoKT4G.js";
5
5
  import { n as a } from "./semaphore-89jsoHtS.js";
6
6
  var o = t("file", [["path", {
@@ -3,15 +3,15 @@ import { c as t, g as n, h as r, m as i, t as a } from "./button-CvjkwdSk.js";
3
3
  import { t as o } from "./react-sHtZdjeP.js";
4
4
  import { t as s } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { h as c, t as l } from "./tooltip-CtBZ5q8p.js";
6
- import { O as u } from "./error-entries-DgtRTNaG.js";
7
- import { $ as d, Q as f, Z as p, an as m, i as h, l as g, ln as _, n as v, on as y, r as b, t as x, u as S } from "./common-CCrzSQnL.js";
6
+ import { O as u } from "./error-entries-CnqKxhU9.js";
7
+ import { $ as d, Q as f, Z as p, an as m, i as h, l as g, ln as _, n as v, on as y, r as b, t as x, u as S } from "./common-_IunO2z-.js";
8
8
  import { M as C } from "./select-DemoKT4G.js";
9
9
  import { q as ee } from "./dropdown-menu-BuE2b8Yb.js";
10
10
  import { _ as w } from "./toDate-gyi35XS2.js";
11
11
  import { t as T } from "./jsx-runtime-3BD1kT0s.js";
12
12
  import { X as E } from "./use-restore-focus-CKjfFjLM.js";
13
13
  import { A as D, C as O, b as k } from "./useTheme-Bu5bBgrh.js";
14
- import { a as A, n as te, t as ne } from "./code-visibility-CZmyRTO8.js";
14
+ import { a as A, n as te, t as ne } from "./code-visibility-891-xGjh.js";
15
15
  /* empty css */
16
16
  var j = c("sticky-note", [["path", {
17
17
  d: "M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev29",
3
+ "version": "0.25.3-dev30",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -1,17 +1,41 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { render, waitFor } from "@testing-library/react";
3
+ import {
4
+ act,
5
+ render as renderComponent,
6
+ waitFor,
7
+ } from "@testing-library/react";
4
8
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
- import { useCellErrors } from "@/core/cells/cells";
9
+ import { Provider, createStore } from "jotai";
10
+ import type { ReactNode } from "react";
11
+ import { MockNotebook } from "@/__mocks__/notebook";
12
+ import { cellId } from "@/__tests__/branded";
13
+ import { notebookAtom } from "@/core/cells/cells";
6
14
  import { DynamicFavicon } from "../dynamic-favicon";
7
15
 
8
- // Mock useCellErrors hook
9
- vi.mock("@/core/cells/cells", () => ({
10
- useCellErrors: vi.fn(),
11
- }));
12
-
13
16
  describe("DynamicFavicon", () => {
14
17
  let favicon: HTMLLinkElement;
18
+ let store: ReturnType<typeof createStore>;
19
+ const id = cellId("cell");
20
+
21
+ function render(ui: ReactNode) {
22
+ return renderComponent(ui, {
23
+ wrapper: ({ children }) => <Provider store={store}>{children}</Provider>,
24
+ });
25
+ }
26
+
27
+ function setErrors() {
28
+ store.set(
29
+ notebookAtom,
30
+ MockNotebook.notebookStateWithErrors([
31
+ {
32
+ cellId: id,
33
+ cellName: "cell",
34
+ errorData: [MockNotebook.errors.syntax("Invalid syntax")],
35
+ },
36
+ ]),
37
+ );
38
+ }
15
39
 
16
40
  beforeEach(() => {
17
41
  document
@@ -27,15 +51,20 @@ describe("DynamicFavicon", () => {
27
51
  // Mock document.hasFocus
28
52
  vi.spyOn(document, "hasFocus").mockReturnValue(true);
29
53
 
30
- // Mock useCellErrors to return no errors by default
31
- (useCellErrors as ReturnType<typeof vi.fn>).mockReturnValue([]);
54
+ store = createStore();
55
+ store.set(
56
+ notebookAtom,
57
+ MockNotebook.notebookState({
58
+ cellData: { [id]: { code: "x = 1" } },
59
+ }),
60
+ );
32
61
  });
33
62
 
34
63
  afterEach(() => {
35
64
  document
36
65
  .querySelectorAll("link[rel~='icon']")
37
66
  .forEach((element) => element.remove());
38
- vi.clearAllMocks();
67
+ vi.restoreAllMocks();
39
68
  vi.useRealTimers();
40
69
  });
41
70
 
@@ -67,9 +96,7 @@ describe("DynamicFavicon", () => {
67
96
  });
68
97
 
69
98
  it("should show error favicon when run completes with errors", async () => {
70
- (useCellErrors as ReturnType<typeof vi.fn>).mockReturnValue([
71
- { error: "mock error" },
72
- ]);
99
+ setErrors();
73
100
 
74
101
  const { rerender } = render(<DynamicFavicon isRunning={true} />);
75
102
 
@@ -147,6 +174,72 @@ describe("DynamicFavicon", () => {
147
174
  });
148
175
  });
149
176
 
177
+ it("does not look up or rewrite the favicon when code changes", async () => {
178
+ const { rerender } = render(<DynamicFavicon isRunning={true} />);
179
+ await waitFor(() => expect(favicon.href).toContain("circle-play.ico"));
180
+ rerender(<DynamicFavicon isRunning={false} />);
181
+ await waitFor(() => expect(favicon.href).toContain("circle-check.ico"));
182
+ const lookup = vi.spyOn(document, "querySelector");
183
+ const write = vi.spyOn(favicon, "href", "set");
184
+
185
+ await act(async () => {
186
+ store.set(notebookAtom, (state) => ({
187
+ ...state,
188
+ cellData: {
189
+ ...state.cellData,
190
+ [id]: { ...state.cellData[id], code: "x = 2" },
191
+ },
192
+ }));
193
+ });
194
+
195
+ expect(
196
+ lookup.mock.calls.filter(
197
+ ([selector]) => selector === "link[rel~='icon']",
198
+ ),
199
+ ).toEqual([]);
200
+ expect(write).not.toHaveBeenCalled();
201
+ lookup.mockRestore();
202
+ write.mockRestore();
203
+ });
204
+
205
+ it("updates the favicon when the error count changes", async () => {
206
+ const { rerender } = render(<DynamicFavicon isRunning={true} />);
207
+ await waitFor(() => expect(favicon.href).toContain("circle-play.ico"));
208
+ rerender(<DynamicFavicon isRunning={false} />);
209
+ await waitFor(() => expect(favicon.href).toContain("circle-check.ico"));
210
+
211
+ act(() => setErrors());
212
+ await waitFor(() => expect(favicon.href).toContain("circle-x.ico"));
213
+
214
+ act(() =>
215
+ store.set(
216
+ notebookAtom,
217
+ MockNotebook.notebookState({ cellData: { [id]: {} } }),
218
+ ),
219
+ );
220
+ await waitFor(() => expect(favicon.href).toContain("circle-check.ico"));
221
+ });
222
+
223
+ it("keeps the completion icon until its own reset timer expires", async () => {
224
+ vi.useFakeTimers();
225
+ const { rerender } = render(<DynamicFavicon isRunning={true} />);
226
+ await act(() => vi.advanceTimersByTimeAsync(1000));
227
+ rerender(<DynamicFavicon isRunning={false} />);
228
+ await act(() => vi.advanceTimersByTimeAsync(2000));
229
+ expect(favicon.href).toContain("circle-check.ico");
230
+ await act(() => vi.advanceTimersByTimeAsync(1000));
231
+ expect(favicon.href).toContain("favicon.ico");
232
+ });
233
+
234
+ it("cancels the reset timer when unmounted", async () => {
235
+ vi.useFakeTimers();
236
+ const { unmount } = render(<DynamicFavicon isRunning={true} />);
237
+ await act(() => vi.advanceTimersByTimeAsync(0));
238
+ expect(vi.getTimerCount()).toBe(1);
239
+ unmount();
240
+ expect(vi.getTimerCount()).toBe(0);
241
+ });
242
+
150
243
  describe("notifications", () => {
151
244
  beforeEach(() => {
152
245
  vi.spyOn(document, "visibilityState", "get").mockReturnValue("hidden");
@@ -156,7 +249,7 @@ describe("DynamicFavicon", () => {
156
249
  global.Notification.permission = "granted";
157
250
  });
158
251
 
159
- it("should send success notification when run completes without errors", () => {
252
+ it("should send success notification when run completes without errors", async () => {
160
253
  // @ts-expect-error ok in tests
161
254
  global.Notification = vi
162
255
  .fn()
@@ -172,12 +265,11 @@ describe("DynamicFavicon", () => {
172
265
 
173
266
  const { rerender } = render(<DynamicFavicon isRunning={true} />);
174
267
  rerender(<DynamicFavicon isRunning={false} />);
268
+ await waitFor(() => expect(Notification).toHaveBeenCalledOnce());
175
269
  });
176
270
 
177
- it("should send error notification when run completes with errors", () => {
178
- (useCellErrors as ReturnType<typeof vi.fn>).mockReturnValue([
179
- { error: "mock error" },
180
- ]);
271
+ it("should send error notification when run completes with errors", async () => {
272
+ setErrors();
181
273
 
182
274
  // @ts-expect-error ok in tests
183
275
  global.Notification = vi
@@ -194,6 +286,7 @@ describe("DynamicFavicon", () => {
194
286
 
195
287
  const { rerender } = render(<DynamicFavicon isRunning={true} />);
196
288
  rerender(<DynamicFavicon isRunning={false} />);
289
+ await waitFor(() => expect(Notification).toHaveBeenCalledOnce());
197
290
  });
198
291
 
199
292
  it("should not send notification when document is visible", () => {
@@ -0,0 +1,53 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
4
+ import { createStore, Provider } from "jotai";
5
+ import { expect, it, vi } from "vitest";
6
+ import { useNotebookActions } from "../../actions/useNotebookActions";
7
+ import CommandPalette from "../command-palette";
8
+
9
+ vi.mock("../../actions/useNotebookActions", () => ({
10
+ useNotebookActions: vi.fn(),
11
+ }));
12
+ vi.mock("../../actions/useCellActionButton", () => ({
13
+ useCellActionButtons: () => [],
14
+ }));
15
+ vi.mock("../../actions/useConfigActions", () => ({
16
+ useConfigActions: () => [],
17
+ }));
18
+
19
+ it("builds current actions only while open and keeps the opening shortcut active", async () => {
20
+ HTMLElement.prototype.scrollIntoView = vi.fn();
21
+ const firstAction = vi.fn();
22
+ const nextAction = vi.fn();
23
+ vi.mocked(useNotebookActions).mockReturnValue([
24
+ { label: "First action", handle: firstAction },
25
+ ]);
26
+ render(
27
+ <Provider store={createStore()}>
28
+ <CommandPalette />
29
+ </Provider>,
30
+ );
31
+ expect(useNotebookActions).not.toHaveBeenCalled();
32
+
33
+ fireEvent.keyDown(document, { key: "k", ctrlKey: true });
34
+ await screen.findByPlaceholderText("Type to search...");
35
+ fireEvent.click(screen.getByText("First action"));
36
+ await waitFor(() => expect(firstAction).toHaveBeenCalledOnce());
37
+ await waitFor(() =>
38
+ expect(screen.queryByPlaceholderText("Type to search...")).toBeNull(),
39
+ );
40
+
41
+ vi.mocked(useNotebookActions)
42
+ .mockClear()
43
+ .mockReturnValue([{ label: "Updated action", handle: nextAction }]);
44
+ fireEvent.keyDown(document, { key: "x" });
45
+ expect(useNotebookActions).not.toHaveBeenCalled();
46
+
47
+ fireEvent.keyDown(document, { key: "k", ctrlKey: true });
48
+ await screen.findByPlaceholderText("Type to search...");
49
+ expect(screen.queryByText("First action")).toBeNull();
50
+ fireEvent.click(screen.getByText("Updated action"));
51
+ await waitFor(() => expect(nextAction).toHaveBeenCalledOnce());
52
+ expect(firstAction).toHaveBeenCalledOnce();
53
+ });
@@ -1,6 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { useAtom, useAtomValue } from "jotai";
3
+ import { useAtom, useAtomValue, useSetAtom } from "jotai";
4
4
  import {
5
5
  CommandDialog,
6
6
  CommandEmpty,
@@ -32,6 +32,25 @@ import { commandPaletteAtom } from "./state";
32
32
 
33
33
  const CommandPalette = () => {
34
34
  const [open, setOpen] = useAtom(commandPaletteAtom);
35
+ const hotkeys = useAtomValue(hotkeysAtom);
36
+
37
+ useEventListener(document, "keydown", (e) => {
38
+ if (parseShortcut(hotkeys.getHotkey("global.commandPalette").key)(e)) {
39
+ e.preventDefault();
40
+ setOpen((open) => !open);
41
+ }
42
+ });
43
+
44
+ return (
45
+ <CommandDialog open={open} onOpenChange={setOpen}>
46
+ <CommandPaletteContent />
47
+ </CommandDialog>
48
+ );
49
+ };
50
+
51
+ // The dialog mounts these subscriptions only while its content is present.
52
+ const CommandPaletteContent = () => {
53
+ const setOpen = useSetAtom(commandPaletteAtom);
35
54
  const registeredActions = useRegisteredActions();
36
55
  const lastFocusedCell = useAtomValue(lastFocusedCellAtom);
37
56
  const hotkeys = useAtomValue(hotkeysAtom);
@@ -55,13 +74,6 @@ const CommandPalette = () => {
55
74
  const { recentCommands, addRecentCommand } = useRecentCommands();
56
75
  const recentCommandsSet = new Set(recentCommands);
57
76
 
58
- useEventListener(document, "keydown", (e) => {
59
- if (parseShortcut(hotkeys.getHotkey("global.commandPalette").key)(e)) {
60
- e.preventDefault();
61
- setOpen((open) => !open);
62
- }
63
- });
64
-
65
77
  const renderShortcutCommandItem = (
66
78
  shortcut: HotkeyAction,
67
79
  props: {
@@ -142,7 +154,7 @@ const CommandPalette = () => {
142
154
  };
143
155
 
144
156
  return (
145
- <CommandDialog open={open} onOpenChange={setOpen}>
157
+ <>
146
158
  <CommandInput placeholder="Type to search..." />
147
159
  <CommandList>
148
160
  <CommandEmpty>No results found.</CommandEmpty>
@@ -211,7 +223,7 @@ const CommandPalette = () => {
211
223
  })}
212
224
  </CommandGroup>
213
225
  </CommandList>
214
- </CommandDialog>
226
+ </>
215
227
  );
216
228
  };
217
229
 
@@ -1,8 +1,9 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { usePrevious } from "@dnd-kit/utilities";
4
+ import { useAtomValue } from "jotai";
4
5
  import { useEffect } from "react";
5
- import { useCellErrors } from "@/core/cells/cells";
6
+ import { cellErrorCount } from "@/core/cells/cells";
6
7
  import { useEventListener } from "@/hooks/useEventListener";
7
8
  import successFaviconUrl from "../../assets/circle-check.ico";
8
9
  import runningFaviconUrl from "../../assets/circle-play.ico";
@@ -15,13 +16,6 @@ const FAVICON_PATHS = {
15
16
  error: errorFaviconUrl,
16
17
  } as const;
17
18
 
18
- // Cache favicon object URLs lazily
19
- type FaviconKey = keyof typeof FAVICON_PATHS;
20
-
21
- async function getFaviconUrl(key: FaviconKey): Promise<string> {
22
- return FAVICON_PATHS[key];
23
- }
24
-
25
19
  function getOrCreateFavicon(): HTMLLinkElement {
26
20
  const existingFavicon =
27
21
  document.querySelector<HTMLLinkElement>("link[rel~='icon']");
@@ -44,16 +38,16 @@ function maybeSendNotification(numErrors: number) {
44
38
  return;
45
39
  }
46
40
 
47
- const sendNotification = async () => {
41
+ const sendNotification = () => {
48
42
  if (numErrors === 0) {
49
43
  new Notification("Execution completed", {
50
44
  body: "Your notebook run completed successfully.",
51
- icon: await getFaviconUrl("success"),
45
+ icon: FAVICON_PATHS.success,
52
46
  });
53
47
  } else {
54
48
  new Notification("Execution failed", {
55
49
  body: `Your notebook run encountered ${numErrors} error(s).`,
56
- icon: await getFaviconUrl("error"),
50
+ icon: FAVICON_PATHS.error,
57
51
  });
58
52
  }
59
53
  };
@@ -75,7 +69,7 @@ function maybeSendNotification(numErrors: number) {
75
69
 
76
70
  export const DynamicFavicon = (props: Props) => {
77
71
  const { isRunning } = props;
78
- const errors = useCellErrors();
72
+ const numErrors = useAtomValue(cellErrorCount);
79
73
 
80
74
  useEffect(() => {
81
75
  const favicon = getOrCreateFavicon();
@@ -86,46 +80,33 @@ export const DynamicFavicon = (props: Props) => {
86
80
  return;
87
81
  }
88
82
 
89
- const updateFavicon = async () => {
90
- let key: FaviconKey;
91
- // When notebook is running, display running favicon
92
- if (isRunning) {
93
- key = "running";
94
- } else {
95
- // When run is complete, display success or error favicon
96
- key = errors.length === 0 ? "success" : "error";
97
- }
98
- favicon.href = await getFaviconUrl(key);
83
+ const key = isRunning ? "running" : numErrors === 0 ? "success" : "error";
84
+ favicon.href = FAVICON_PATHS[key];
99
85
 
100
- // If notebook is in focus, reset favicon after 3 seconds
101
- // If not in focus, the focus event listener handles it
102
- if (!document.hasFocus()) {
103
- return;
104
- }
105
-
106
- const timeoutId = setTimeout(async () => {
107
- favicon.href = await getFaviconUrl("idle");
108
- }, 3000);
109
-
110
- return () => clearTimeout(timeoutId);
111
- };
86
+ if (!document.hasFocus()) {
87
+ // The focus listener resets the favicon when the user returns.
88
+ return;
89
+ }
112
90
 
113
- updateFavicon();
114
- }, [isRunning, errors]);
91
+ const timeoutId = setTimeout(() => {
92
+ favicon.href = FAVICON_PATHS.idle;
93
+ }, 3000);
94
+ return () => clearTimeout(timeoutId);
95
+ }, [isRunning, numErrors]);
115
96
 
116
97
  // Send user notification when run has completed
117
98
  const prevRunning = usePrevious(isRunning) ?? isRunning;
118
99
  useEffect(() => {
119
100
  if (prevRunning && !isRunning) {
120
- maybeSendNotification(errors.length);
101
+ maybeSendNotification(numErrors);
121
102
  }
122
- }, [errors, prevRunning, isRunning]);
103
+ }, [numErrors, prevRunning, isRunning]);
123
104
 
124
105
  // When notebook comes back in focus, reset favicon
125
- useEventListener(window, "focus", async (_) => {
106
+ useEventListener(window, "focus", () => {
126
107
  if (!isRunning) {
127
108
  const favicon = getOrCreateFavicon();
128
- favicon.href = await getFaviconUrl("idle");
109
+ favicon.href = FAVICON_PATHS.idle;
129
110
  }
130
111
  });
131
112
 
@@ -0,0 +1,113 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { createStore } from "jotai";
4
+ import { afterEach, describe, expect, it, vi } from "vitest";
5
+ import { MockNotebook } from "@/__mocks__/notebook";
6
+ import { cellId } from "@/__tests__/branded";
7
+ import {
8
+ createNotebookActions,
9
+ notebookAtom,
10
+ notebookOutline,
11
+ notebookReducer,
12
+ } from "../cells";
13
+ import { exportedForTesting } from "../document-changes";
14
+ import type { Outline } from "../outline";
15
+
16
+ const first = cellId("first");
17
+ const second = cellId("second");
18
+ const firstOutline: Outline = {
19
+ items: [{ name: "First", level: 1, by: { id: "first" } }],
20
+ };
21
+ const secondOutline: Outline = {
22
+ items: [{ name: "Second", level: 2, by: { id: "second" } }],
23
+ };
24
+
25
+ function setup() {
26
+ const store = createStore();
27
+ store.set(
28
+ notebookAtom,
29
+ MockNotebook.notebookState({
30
+ cellData: { [first]: { code: "x = 1" }, [second]: {} },
31
+ cellRuntime: {
32
+ [first]: { outline: firstOutline },
33
+ [second]: { outline: secondOutline },
34
+ },
35
+ }),
36
+ );
37
+ const actions = createNotebookActions((action) =>
38
+ store.set(notebookAtom, (state) => notebookReducer(state, action)),
39
+ );
40
+ return { store, actions };
41
+ }
42
+
43
+ afterEach(() => {
44
+ exportedForTesting.cancelPendingChanges();
45
+ });
46
+
47
+ describe("notebookOutline", () => {
48
+ it("does not notify outline subscribers when cell code changes", () => {
49
+ const { store, actions } = setup();
50
+ const initial = store.get(notebookOutline);
51
+ const listener = vi.fn();
52
+ const unsubscribe = store.sub(notebookOutline, listener);
53
+
54
+ actions.updateCellCode({
55
+ cellId: first,
56
+ code: "x = 2",
57
+ formattingChange: false,
58
+ });
59
+
60
+ expect(store.get(notebookOutline)).toBe(initial);
61
+ expect(listener).not.toHaveBeenCalled();
62
+ unsubscribe();
63
+ });
64
+
65
+ it("updates headings when runtime outlines change or are removed", () => {
66
+ const { store } = setup();
67
+ const updated: Outline = {
68
+ items: [{ name: "Updated", level: 1, by: { id: "updated" } }],
69
+ };
70
+
71
+ for (const outline of [updated, null]) {
72
+ store.set(notebookAtom, (state) => ({
73
+ ...state,
74
+ cellRuntime: {
75
+ ...state.cellRuntime,
76
+ [first]: { ...state.cellRuntime[first], outline },
77
+ },
78
+ }));
79
+ expect(store.get(notebookOutline)).toEqual({
80
+ items: [...(outline?.items ?? []), ...secondOutline.items],
81
+ });
82
+ }
83
+ });
84
+
85
+ it("keeps headings in cell order after moving and deleting cells", () => {
86
+ const { store, actions } = setup();
87
+ actions.moveCell({ cellId: second, before: true });
88
+ expect(store.get(notebookOutline)).toEqual({
89
+ items: [...secondOutline.items, ...firstOutline.items],
90
+ });
91
+
92
+ actions.deleteCell({ cellId: second });
93
+ expect(store.get(notebookOutline)).toEqual(firstOutline);
94
+ });
95
+
96
+ it("notifies subscribers when output is replaced with the same headings", () => {
97
+ const { store } = setup();
98
+ const listener = vi.fn();
99
+ const unsubscribe = store.sub(notebookOutline, listener);
100
+
101
+ store.set(notebookAtom, (state) => ({
102
+ ...state,
103
+ cellRuntime: {
104
+ ...state.cellRuntime,
105
+ [first]: { ...state.cellRuntime[first], outline: { ...firstOutline } },
106
+ },
107
+ }));
108
+
109
+ // Consumers must reconnect to replacement heading elements in the DOM.
110
+ expect(listener).toHaveBeenCalledOnce();
111
+ unsubscribe();
112
+ });
113
+ });
@@ -1761,7 +1761,8 @@ export const cellErrorsAtom = atom((get) => {
1761
1761
  });
1762
1762
 
1763
1763
  export const notebookOutline = atom((get) => {
1764
- const { cellIds, cellRuntime } = get(notebookAtom);
1764
+ const cellIds = get(cellIdsAtom);
1765
+ const cellRuntime = get(cellsRuntimeAtom);
1765
1766
  const outlines = cellIds.inOrderIds.map(
1766
1767
  (cellId) => cellRuntime[cellId].outline,
1767
1768
  );