@marimo-team/islands 0.25.3-dev203 → 0.25.3-dev205

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-BYqWGSOj.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
138
+ var I = (0, T.lazy)(() => import("./feedback-button-DOT-sr6d.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,
@@ -17,7 +17,7 @@ function b() {
17
17
  return e.warn("Failed to get version from mount config"), null;
18
18
  }
19
19
  }
20
- var x = b() || "0.25.3-dev203", S = c(x), C = c(!0);
20
+ var x = b() || "0.25.3-dev205", S = c(x), C = c(!0);
21
21
  c(null);
22
22
  //#endregion
23
23
  //#region src/core/wasm/state.ts
@@ -12,7 +12,7 @@ import { t as ut } from "./check-C9Mp9eCK.js";
12
12
  import { A as dt, C as ft, D as pt, M as mt, S as ht, _ as gt, b as _t, c as vt, d as yt, g as bt, h as xt, i as St, l as Ct, m as wt, n as Tt, p as Et, s as Dt, t as Ot, u as kt, v as At, y as jt } from "./select-2KOiReNY.js";
13
13
  import { $ as Mt, $t as Nt, A as Pt, At as Ft, B as It, Bt as Lt, C as Rt, Ct as zt, D as Bt, Dt as Vt, E as Ht, Et as Ut, F as Wt, Ft as Gt, G as Kt, Gt as qt, H as Jt, Ht as Yt, I as Xt, It as Zt, Jt as Qt, K as $t, Kt as en, L as tn, Lt as nn, M as rn, Mt as an, N as on, Nt as sn, O as cn, Ot as ln, P as un, Pt as dn, Q as fn, Qt as pn, R as mn, Rt as hn, S as gn, St as _n, T as vn, Tt as yn, U as bn, Ut as xn, V as Sn, Vt as Cn, W as wn, Wt as Tn, X as En, Xt as Dn, Y as On, Yt as kn, Z as An, Zt as jn, _ as Mn, _n as Nn, _t as Pn, a as Fn, an as In, at as Ln, b as Rn, bn as zn, bt as Bn, ct as Vn, d as Hn, dt as Un, en as Wn, et as Gn, f as Kn, fn as qn, gn as Jn, gt as Yn, h as Xn, hn as Zn, ht as Qn, i as $n, in as er, it as tr, j as nr, jt as rr, k as ir, kt as ar, l as or, ln as sr, lt as cr, mn as lr, mt as ur, n as dr, nn as fr, nt as pr, o as mr, on as hr, ot as gr, pn as _r, pt as vr, qt as yr, rt as br, s as xr, sn as Sr, st as Cr, t as wr, tn as Tr, tt as Er, u as Dr, un as Or, ut as kr, vn as Ar, vt as jr, wt as Mr, x as Nr, xt as Pr, yn as Fr, yt as Ir, z as Lr, zt as Rr } from "./dropdown-menu-BFQYzWmC.js";
14
14
  import { S as zr, a as Br, c as Vr, d as Hr, i as Ur, l as Wr, n as Gr, o as Kr, r as qr, t as Jr, v as Yr, y as Xr } from "./toDate-B0-Y0SEW.js";
15
- import { n as Zr, t as Qr } from "./ErrorBoundary-CYw4nBEN.js";
15
+ import { n as Zr, t as Qr } from "./ErrorBoundary-OPdycBFt.js";
16
16
  import { t as $r } from "./clsx-CoeGtWvn.js";
17
17
  import { t as ei } from "./react-dom-DUmH0GXv.js";
18
18
  import { t as ti } 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-odIdinCX.js";
5
+ import { a as o, i as s, n as c, r as l } from "./glide-data-editor-wPaUwYJ-.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",
@@ -5,12 +5,12 @@ import { t as i } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { t as a } from "./copy-icon-De584pZ4.js";
6
6
  import { H as o, Ht as s, R as c, W as l, at as u, i as d, ln as f, n as p, st as m } from "./error-entries-B0bcEwXm.js";
7
7
  import { b as h } from "./select-2KOiReNY.js";
8
- import { n as ee, t as te } from "./globals-Pb4d_RfL.js";
8
+ import { n as ee, t as te } from "./globals-iMXhFlx_.js";
9
9
  import { t as g } from "./jsx-runtime-3BD1kT0s.js";
10
10
  import { M as ne, b as re, i as _ } from "./useTheme-DbBkeP6Z.js";
11
11
  import { a as ie, i as ae, n as oe, r as se } from "./dialog-DVRfQuhD.js";
12
12
  import { t as ce } from "./useAsyncData-Phxf6GCd.js";
13
- import { t as le } from "./code-visibility-WinzKDYd.js";
13
+ import { t as le } from "./code-visibility-DBpgJeRK.js";
14
14
  //#region src/components/ui/skeleton.tsx
15
15
  var v = /* @__PURE__ */ e(r(), 1), y = i(), b = g(), x = (e) => {
16
16
  let n = (0, y.c)(8), r, i;
@@ -6,7 +6,7 @@ import { i as s, n as c, r as l } from "./copy-icon-De584pZ4.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-2KOiReNY.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-BFQYzWmC.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-D98laidb.js";
9
- import { n as ne, t as re } from "./ErrorBoundary-CYw4nBEN.js";
9
+ import { n as ne, t as re } from "./ErrorBoundary-OPdycBFt.js";
10
10
  import { t as ie } from "./react-dom-DUmH0GXv.js";
11
11
  import { t as M } from "./jsx-runtime-3BD1kT0s.js";
12
12
  import { t as N } from "./label-Qvw1E97W.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-Ct_7pOS8.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-aBSCgI7f.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-CaCxGSux.js")), Us = {
9296
+ var Hs = K.lazy(async () => await import("./number-overlay-editor-CmrlqczC.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 { m as e } from "./tooltip-s4zZxwKe.js";
2
2
  import { b as t } from "./useTheme-DbBkeP6Z.js";
3
- import { r as n } from "./code-visibility-WinzKDYd.js";
3
+ import { r as n } from "./code-visibility-DBpgJeRK.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",
package/dist/main.js CHANGED
@@ -7,7 +7,7 @@ import { A as T, F as E, I as D, J as O, K as k, L as A, M as j, Q as M, R as N,
7
7
  import { a as ce, d as le, i as ue, m as de, n as fe, o as pe, p as me, r as he, t as ge } from "./tooltip-s4zZxwKe.js";
8
8
  import { A as _e, At as ve, C as ye, Ct as be, D as xe, Dt as Se, E as Ce, Et as we, F as Te, Ft as Ee, G as De, Gt as Oe, Ht as ke, I as Ae, K as je, Kt as Me, L as Ne, O as Pe, Qt as Fe, R as Ie, S as Le, St as Re, T as ze, Tt as Be, U as Ve, Ut as He, V as Ue, Vt as We, W as Ge, Wt as Ke, X as qe, Xt as Je, Y as Ye, Yt as Xe, Zt as Ze, an as Qe, bt as $e, cn as et, ct as tt, dn as nt, dt as rt, en as it, et as at, f as ot, g as st, h as ct, ht as lt, it as ut, jt as dt, lt as ft, m as pt, mn as mt, nn as ht, o as gt, on as _t, p as vt, pn as yt, q as bt, qt as xt, s as St, sn as Ct, tt as wt, u as Tt, un as Et, ut as Dt, vt as Ot, w as kt, wt as At, zt as jt } from "./error-entries-B0bcEwXm.js";
9
9
  import { D as Mt, E as Nt, O as Pt, S as Ft, T as It, _ as Lt, a as Rt, c as zt, d as Bt, f as Vt, g as Ht, h as Ut, i as Wt, l as Gt, m as Kt, n as qt, o as Jt, p as Yt, r as Xt, s as Zt, t as Qt, u as $t, v as en, w as tn, x as nn, y as rn } from "./spec-Alkla7dB.js";
10
- import { $t as an, A as on, At as sn, B as cn, Bt as ln, C as un, Ct as dn, D as fn, Dt as pn, E as mn, Et as hn, F as gn, Ft as _n, G as vn, Gt as yn, H as bn, Ht as xn, I as Sn, It as Cn, J as wn, Jt as Tn, K as En, Kt as Dn, L as On, Lt as kn, M as An, Mt as jn, N as Mn, Nt as Nn, O as Pn, Ot as Fn, P as In, Pt as Ln, Qt as Rn, R as zn, Rt as Bn, S as Vn, St as Hn, T as Un, Tt as Wn, U as Gn, Ut as Kn, V as qn, Vt as Jn, W as Yn, Wt as Xn, X as Zn, Xt as Qn, Y as $n, Yt as er, Zt as tr, _ as nr, _t as rr, an as ir, at as ar, b as or, c as sr, cn as cr, ct as lr, d as ur, dn as dr, dt as fr, en as pr, et as mr, f as hr, fn as gr, ft as _r, g as vr, gt as yr, h as br, hn as xr, ht as Sr, in as Cr, it as wr, j as Tr, jt as Er, k as Dr, kt as Or, ln as kr, lt as Ar, m as jr, mn as Mr, mt as Nr, nn as Pr, nt as Fr, ot as Ir, p as Lr, pn as Rr, pt as zr, q as Br, qt as Vr, r as Hr, rn as Ur, rt as Wr, sn as Gr, st as Kr, t as qr, tn as Jr, tt as Yr, u as Xr, un as Zr, ut as Qr, v as $r, vt as ei, w as ti, wt as ni, x as ri, y as ii, yt as ai, z as oi, zt as si } from "./common-D1st4ghC.js";
10
+ import { $t as an, A as on, At as sn, B as cn, Bt as ln, C as un, Ct as dn, D as fn, Dt as pn, E as mn, Et as hn, F as gn, Ft as _n, G as vn, Gt as yn, H as bn, Ht as xn, I as Sn, It as Cn, J as wn, Jt as Tn, K as En, Kt as Dn, L as On, Lt as kn, M as An, Mt as jn, N as Mn, Nt as Nn, O as Pn, Ot as Fn, P as In, Pt as Ln, Qt as Rn, R as zn, Rt as Bn, S as Vn, St as Hn, T as Un, Tt as Wn, U as Gn, Ut as Kn, V as qn, Vt as Jn, W as Yn, Wt as Xn, X as Zn, Xt as Qn, Y as $n, Yt as er, Zt as tr, _ as nr, _t as rr, an as ir, at as ar, b as or, c as sr, cn as cr, ct as lr, d as ur, dn as dr, dt as fr, en as pr, et as mr, f as hr, fn as gr, ft as _r, g as vr, gt as yr, h as br, hn as xr, ht as Sr, in as Cr, it as wr, j as Tr, jt as Er, k as Dr, kt as Or, ln as kr, lt as Ar, m as jr, mn as Mr, mt as Nr, nn as Pr, nt as Fr, ot as Ir, p as Lr, pn as Rr, pt as zr, q as Br, qt as Vr, r as Hr, rn as Ur, rt as Wr, sn as Gr, st as Kr, t as qr, tn as Jr, tt as Yr, u as Xr, un as Zr, ut as Qr, v as $r, vt as ei, w as ti, wt as ni, x as ri, y as ii, yt as ai, z as oi, zt as si } from "./common-DZdZhBUN.js";
11
11
  import { c as ci, i as li, n as ui, o as di, t as fi } from "./useLifecycle-DDDsO4O2.js";
12
12
  import { t as pi } from "./check-C9Mp9eCK.js";
13
13
  import { A as mi, C as hi, D as gi, E as _i, M as vi, O as yi, S as bi, T as xi, a as Si, b as Ci, c as wi, i as Ti, l as Ei, n as Di, o as Oi, r as ki, s as Ai, t as ji, w as Mi, x as Ni } from "./select-2KOiReNY.js";
@@ -15,8 +15,8 @@ import { B as Pi, C as Fi, J as Ii, Ot as Li, S as Ri, W as zi, X as Bi, Y as Vi
15
15
  import { C as pa, S as ma, _ as ha, a as ga, b as _a, c as va, f as ya, h as ba, m as xa, p as Sa, s as Ca, u as wa, y as Ta } from "./toDate-B0-Y0SEW.js";
16
16
  import { a as Ea, c as Da, d as Oa, f as ka, i as Aa, l as ja, n as Ma, o as Na, r as Pa, s as Fa, t as Ia } from "./process-output-8BbxxGrz.js";
17
17
  import { a as La, c as Ra, d as za, i as Ba, l as Va, r as Ha, u as Ua } from "./glide-utils-D98laidb.js";
18
- import { n as Wa, t as Ga } from "./ErrorBoundary-CYw4nBEN.js";
19
- import { n as Ka, t as qa } from "./globals-Pb4d_RfL.js";
18
+ import { n as Wa, t as Ga } from "./ErrorBoundary-OPdycBFt.js";
19
+ import { n as Ka, t as qa } from "./globals-iMXhFlx_.js";
20
20
  import { t as Ja } from "./react-dom-DUmH0GXv.js";
21
21
  import { t as Ya } from "./jsx-runtime-3BD1kT0s.js";
22
22
  import { A as Xa, At as Za, B as Qa, C as V, Ct as $a, D as eo, Dt as to, Et as no, F as ro, G as io, H as ao, I as oo, J as so, K as co, L as H, N as U, O as lo, Ot as uo, P as W, Q as fo, R as po, S as mo, St as ho, T as go, Tt as _o, W as vo, _ as yo, a as bo, b as xo, bt as So, c as Co, d as wo, et as To, f as Eo, g as Do, h as Oo, i as ko, j as Ao, k as jo, kt as Mo, l as No, m as Po, n as Fo, o as Io, p as Lo, pt as Ro, q as zo, r as Bo, s as Vo, tt as Ho, u as Uo, v as Wo, w as G, wt as Go, x as Ko, y as K, z as qo } from "./use-restore-focus-BgDTd2tc.js";
@@ -40,7 +40,7 @@ import { i as zs, n as Bs, r as Vs } from "./formats-DyYnckF5.js";
40
40
  import { t as Hs } from "./semaphore-89jsoHtS.js";
41
41
  import { D as Us, O as Ws } from "./vega-loader.browser-B9Pz0EGP.js";
42
42
  import { a as Gs, n as Ks } from "./loader-DOVB0Syl.js";
43
- import { c as qs, d as Js, i as Ys, l as Xs, o as Zs, s as Qs, t as $s, u as ec } from "./code-visibility-WinzKDYd.js";
43
+ import { c as qs, d as Js, i as Ys, l as Xs, o as Zs, s as Qs, t as $s, u as ec } from "./code-visibility-DBpgJeRK.js";
44
44
  import { t as tc } from "./useDeepCompareMemoize-BXv7DUcU.js";
45
45
  import { t as nc } from "./esm-Bbw_Njjx.js";
46
46
  //#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
@@ -12254,7 +12254,7 @@ function tD(e, t) {
12254
12254
  }
12255
12255
  //#endregion
12256
12256
  //#region src/plugins/impl/DataEditorPlugin.tsx
12257
- var nD = J.lazy(() => import("./glide-data-editor-odIdinCX.js").then((e) => e.t)), rD = RT("marimo-data-editor", { cssStyles: [sE] }).withData(W({
12257
+ var nD = J.lazy(() => import("./glide-data-editor-wPaUwYJ-.js").then((e) => e.t)), rD = RT("marimo-data-editor", { cssStyles: [sE] }).withData(W({
12258
12258
  initialValue: W({ edits: V(W({
12259
12259
  rowIdx: U(),
12260
12260
  columnId: H(),
@@ -32045,7 +32045,7 @@ function nH(e) {
32045
32045
  }
32046
32046
  //#endregion
32047
32047
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
32048
- var rH = J.lazy(() => import("./reveal-component-Dlt6nj0h.js")), iH = (e) => {
32048
+ var rH = J.lazy(() => import("./reveal-component-W-rBMqdU.js")), iH = (e) => {
32049
32049
  let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = us(ha), s = a === "read" || o, c = us(xe) > 1, [l, u] = (0, J.useState)(null), d;
32050
32050
  t[0] !== i || t[1] !== n ? (d = eR(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
32051
32051
  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-odIdinCX.js";
3
+ import { a as n } from "./glide-data-editor-wPaUwYJ-.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",
@@ -4,14 +4,14 @@ import { t as o } from "./react-sHtZdjeP.js";
4
4
  import { t as s } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { m as c, t as l } from "./tooltip-s4zZxwKe.js";
6
6
  import { Zt as u } from "./error-entries-B0bcEwXm.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-D1st4ghC.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-DZdZhBUN.js";
8
8
  import { M as C } from "./select-2KOiReNY.js";
9
9
  import { J as ee } from "./dropdown-menu-BFQYzWmC.js";
10
10
  import { _ as w } from "./toDate-B0-Y0SEW.js";
11
11
  import { t as T } from "./jsx-runtime-3BD1kT0s.js";
12
12
  import { X as te } from "./use-restore-focus-BgDTd2tc.js";
13
13
  import { M as E, R as D, o as O } from "./useTheme-DbBkeP6Z.js";
14
- import { a as k, n as ne, t as re } from "./code-visibility-WinzKDYd.js";
14
+ import { a as k, n as ne, t as re } from "./code-visibility-DBpgJeRK.js";
15
15
  /* empty css */
16
16
  var A = 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-dev203",
3
+ "version": "0.25.3-dev205",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,97 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { renderHook } from "@testing-library/react";
4
+ import { createStore, Provider } from "jotai";
5
+ import type { ReactNode } from "react";
6
+ import { beforeEach, describe, expect, it, vi } from "vitest";
7
+ import { MockRequestClient } from "@/__mocks__/requests";
8
+ import { ModalProvider } from "@/components/modal/ImperativeModal";
9
+ import { toast } from "@/components/ui/use-toast";
10
+ import { CellId } from "@/core/cells/ids";
11
+ import { requestClientAtom } from "@/core/network/requests";
12
+ import { copyToClipboard } from "@/utils/copy";
13
+ import type { ActionButton } from "../types";
14
+ import { useCellActionButtons } from "../useCellActionButton";
15
+
16
+ vi.mock("@/utils/copy", () => ({ copyToClipboard: vi.fn() }));
17
+ vi.mock("@/components/ui/use-toast", () => ({ toast: vi.fn() }));
18
+
19
+ function renderActions(cellId: CellId, name: string) {
20
+ const store = createStore();
21
+ store.set(requestClientAtom, MockRequestClient.create());
22
+ const wrapper = ({ children }: { children: ReactNode }) => (
23
+ <Provider store={store}>
24
+ <ModalProvider>{children}</ModalProvider>
25
+ </Provider>
26
+ );
27
+ const { result } = renderHook(
28
+ () =>
29
+ useCellActionButtons({
30
+ cell: {
31
+ cellId,
32
+ name,
33
+ config: { disabled: false, hide_code: false, column: null },
34
+ status: "idle",
35
+ hasOutput: false,
36
+ hasConsoleOutput: false,
37
+ getEditorView: () => null,
38
+ },
39
+ }),
40
+ { wrapper },
41
+ );
42
+ return result.current;
43
+ }
44
+
45
+ function getAction(groups: ActionButton[][], label: string): ActionButton {
46
+ const action = groups.flat().find((a) => a.label === label);
47
+ if (!action) {
48
+ throw new Error(`Action "${label}" not found`);
49
+ }
50
+ return action;
51
+ }
52
+
53
+ describe("useCellActionButtons", () => {
54
+ beforeEach(() => {
55
+ vi.clearAllMocks();
56
+ });
57
+
58
+ it("places Copy cell ID right after Copy link to cell", () => {
59
+ const groups = renderActions(CellId.create(), "_");
60
+ const linkGroup = groups.find((group) =>
61
+ group.some((a) => a.label === "Copy link to cell"),
62
+ );
63
+ expect(linkGroup?.map((a) => a.label)).toEqual([
64
+ "Name",
65
+ "Copy link to cell",
66
+ "Copy cell ID",
67
+ ]);
68
+ });
69
+
70
+ it("copies the cell ID of an unnamed cell", async () => {
71
+ const cellId = CellId.create();
72
+ const groups = renderActions(cellId, "_");
73
+
74
+ await getAction(groups, "Copy cell ID").handle();
75
+
76
+ expect(copyToClipboard).toHaveBeenCalledWith(cellId);
77
+ expect(toast).toHaveBeenCalledWith({
78
+ description: "Cell ID copied to clipboard",
79
+ });
80
+ });
81
+
82
+ it("copies the cell ID, not the name, of a named cell", async () => {
83
+ const cellId = CellId.create();
84
+ const groups = renderActions(cellId, "my_cell");
85
+
86
+ await getAction(groups, "Copy cell ID").handle();
87
+
88
+ expect(copyToClipboard).toHaveBeenCalledWith(cellId);
89
+ });
90
+
91
+ it("keeps Copy link to cell disabled for unnamed cells", () => {
92
+ const groups = renderActions(CellId.create(), "_");
93
+
94
+ expect(getAction(groups, "Copy link to cell").disabled).toBe(true);
95
+ expect(getAction(groups, "Copy cell ID").disabled).toBeUndefined();
96
+ });
97
+ });
@@ -14,6 +14,7 @@ import {
14
14
  DatabaseIcon,
15
15
  EyeIcon,
16
16
  EyeOffIcon,
17
+ HashIcon,
17
18
  ImageIcon,
18
19
  LinkIcon,
19
20
  PlayIcon,
@@ -430,6 +431,15 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
430
431
  toast({ description: "Link copied to clipboard" });
431
432
  },
432
433
  },
434
+ {
435
+ icon: <HashIcon size={13} strokeWidth={1.5} />,
436
+ label: "Copy cell ID",
437
+ additionalKeywords: ["cell_id", "identifier"],
438
+ handle: async () => {
439
+ await copyToClipboard(cellId);
440
+ toast({ description: "Cell ID copied to clipboard" });
441
+ },
442
+ },
433
443
  ],
434
444
 
435
445
  // Delete