@marimo-team/islands 0.25.3-dev134 → 0.25.3-dev135

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-7ZbDdjfz.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
138
+ var I = (0, T.lazy)(() => import("./feedback-button-n0-eDhBU.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,
@@ -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-dev134", C = u(S), w = u(!0);
21
+ var S = x() || "0.25.3-dev135", C = u(S), w = u(!0);
22
22
  u(null);
23
23
  //#endregion
24
24
  //#region src/core/wasm/state.ts
@@ -12,7 +12,7 @@ import { t as ut } from "./check-SpOMoCLP.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-CkF_GBxO.js";
13
13
  import { $ as Mt, $t as Nt, A as Pt, At as Ft, B as It, Bt as Lt, Ct as Rt, D as zt, Dt as Bt, E as Vt, Et as Ht, F as Ut, Ft as Wt, G as Gt, Gt as Kt, H as qt, Ht as Jt, I as Yt, It as Xt, J as Zt, Jt as Qt, Kt as $t, L as en, Lt as tn, M as nn, Mt as rn, N as an, Nt as on, O as sn, Ot as cn, P as ln, Pt as un, Q as dn, Qt as fn, R as pn, Rt as mn, S as hn, St as gn, T as _n, Tt as vn, U as yn, Ut as bn, V as xn, Vt as Sn, W as Cn, Wt as wn, X as Tn, Xt as En, Y as Dn, Yt as On, Z as kn, Zt as An, _ as jn, _n as Mn, _t as Nn, a as Pn, an as Fn, at as In, b as Ln, bt as Rn, cn as zn, ct as Bn, d as Vn, dn as Hn, en as Un, et as Wn, f as Gn, fn as Kn, ft 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, nt as fr, o as pr, on as mr, ot as hr, pn as gr, pt as _r, qt as vr, rn as yr, rt as br, s as xr, st as Sr, t as Cr, tn as wr, tt as Tr, u as Er, ut as Dr, vn as Or, vt as kr, w as Ar, wt as jr, x as Mr, xt as Nr, y as Pr, yn as Fr, yt as Ir, z as Lr, zt as Rr } from "./dropdown-menu-CgL3fm8P.js";
14
14
  import { a as zr, c as Br, d as Vr, i as Hr, l as Ur, n as Wr, o as Gr, r as Kr, t as qr, v as Jr, x as Yr, y as Xr } from "./toDate-DGvRHwTk.js";
15
- import { n as Zr, t as Qr } from "./ErrorBoundary-CImYa86e.js";
15
+ import { n as Zr, t as Qr } from "./ErrorBoundary-C1PyX4Kv.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-D72zmCan.js";
5
+ import { a as o, i as s, n as c, r as l } from "./glide-data-editor-BQBctTSS.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-C1trdvVt.js";
6
6
  import { H as o, K as s, Lt as c, Ot as l, fn as u, h as d, i as f, n as p, q as m, zt as h } from "./error-entries-CmFDQ9CA.js";
7
7
  import { b as g } from "./select-CkF_GBxO.js";
8
- import { n as ee, t as te } from "./globals-DE2S2io9.js";
8
+ import { n as ee, t as te } from "./globals-C9s-sVIk.js";
9
9
  import { t as _ } from "./jsx-runtime-3BD1kT0s.js";
10
10
  import { C as v, _ as ne, i as y } from "./useTheme-Bq9pi_vz.js";
11
11
  import { a as re, i as ie, n as ae, r as oe } from "./dialog-DgeqyrEZ.js";
12
12
  import { t as se } from "./useAsyncData-BmVgnMP5.js";
13
- import { t as ce } from "./code-visibility-BZoWT5f1.js";
13
+ import { t as ce } from "./code-visibility-BS43kDO4.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-C1trdvVt.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-CkF_GBxO.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-CgL3fm8P.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-Dz_F4pAY.js";
9
- import { n as ne, t as re } from "./ErrorBoundary-CImYa86e.js";
9
+ import { n as ne, t as re } from "./ErrorBoundary-C1PyX4Kv.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-D9_-zSg-.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-CtOna148.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-Cxje4LxB.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-Br0lPnFE.js")), Us = {
9296
+ var Hs = K.lazy(async () => await import("./number-overlay-editor-Bp1CMtol.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-CJ4Rqasp.js";
2
2
  import { _ as t } from "./useTheme-Bq9pi_vz.js";
3
- import { r as n } from "./code-visibility-BZoWT5f1.js";
3
+ import { r as n } from "./code-visibility-BS43kDO4.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 { C as T, F as E, G as D, I as O, J as k, K as A, L as j, P as M, R as N,
7
7
  import { a as oe, d as se, i as ce, m as le, n as ue, o as de, p as fe, r as pe, t as me } from "./tooltip-CJ4Rqasp.js";
8
8
  import { $ as he, A as ge, At as _e, B as ve, Bt as ye, D as be, Dt as xe, G as Se, H as Ce, Ht as we, It as Te, J as Ee, Jt as De, Kt as Oe, M as ke, Mt as Ae, N as je, Nt as Me, O as Ne, Ot as Pe, P as Fe, Q as Ie, S as Le, Tt as Re, V as ze, Vt as Be, Wt as Ve, X as He, Xt as Ue, Y as We, Yt as Ge, _ as Ke, _n as qe, _t as Je, an as Ye, b as Xe, cn as Ze, ct as Qe, dn as $e, dt as et, en as tt, f as nt, ft as rt, g as it, gn as at, gt as ot, h as st, it as ct, jt as lt, k as ut, kt as dt, ln as ft, m as pt, mn as mt, nn as ht, o as gt, p as _t, pn as vt, pt as yt, qt as bt, rn as xt, rt as St, s as Ct, tn as wt, u as Tt, un as Et, v as Dt, xt as Ot, y as kt, z as At } from "./error-entries-CmFDQ9CA.js";
9
9
  import { D as jt, E as Mt, O as Nt, S as Pt, T as Ft, _ as It, a as Lt, c as Rt, d as zt, f as Bt, g as Vt, h as Ht, i as Ut, l as Wt, m as Gt, n as Kt, o as qt, p as Jt, r as Yt, s as Xt, t as Zt, u as Qt, v as $t, w as en, x as tn, y as nn } from "./spec-DiSh_qJC.js";
10
- import { $t as rn, A as an, At as on, B as sn, Bt as cn, C as ln, Ct as un, D as dn, Dt as fn, E as pn, Et as mn, F as hn, Ft as gn, G as _n, Gt as vn, H as yn, Ht as bn, I as xn, It as Sn, J as Cn, Jt as wn, K as Tn, Kt as En, L as Dn, Lt as On, M as kn, Mt as An, N as jn, Nt as Mn, O as Nn, Ot as Pn, P as Fn, Pt as In, Qt as Ln, R as Rn, Rt as zn, S as Bn, St as Vn, T as Hn, Tt as Un, U as Wn, Ut as Gn, V as Kn, Vt as qn, W as Jn, Wt as Yn, X as Xn, Xt as Zn, Y as Qn, Yt as $n, Zt as er, _ as tr, _t as nr, an as rr, at as ir, b as ar, c as or, cn as sr, ct as cr, d as lr, dn as ur, dt as dr, en as fr, et as pr, f as mr, fn as hr, ft as gr, g as _r, gt as vr, h as yr, hn as br, ht as xr, in as Sr, it as Cr, j as wr, jt as Tr, k as Er, kt as Dr, ln as Or, lt as kr, m as Ar, mn as jr, mt as Mr, nn as Nr, nt as Pr, ot as Fr, p as Ir, pn as Lr, pt as Rr, q as zr, qt as Br, r as Vr, rn as Hr, rt as Ur, sn as Wr, st as Gr, t as Kr, tn as qr, tt as Jr, u as Yr, un as Xr, ut as Zr, v as Qr, vt as $r, w as ei, wt as ti, x as ni, y as ri, yt as ii, z as ai, zt as oi } from "./common-CGmIoGK3.js";
10
+ import { $t as rn, A as an, At as on, B as sn, Bt as cn, C as ln, Ct as un, D as dn, Dt as fn, E as pn, Et as mn, F as hn, Ft as gn, G as _n, Gt as vn, H as yn, Ht as bn, I as xn, It as Sn, J as Cn, Jt as wn, K as Tn, Kt as En, L as Dn, Lt as On, M as kn, Mt as An, N as jn, Nt as Mn, O as Nn, Ot as Pn, P as Fn, Pt as In, Qt as Ln, R as Rn, Rt as zn, S as Bn, St as Vn, T as Hn, Tt as Un, U as Wn, Ut as Gn, V as Kn, Vt as qn, W as Jn, Wt as Yn, X as Xn, Xt as Zn, Y as Qn, Yt as $n, Zt as er, _ as tr, _t as nr, an as rr, at as ir, b as ar, c as or, cn as sr, ct as cr, d as lr, dn as ur, dt as dr, en as fr, et as pr, f as mr, fn as hr, ft as gr, g as _r, gt as vr, h as yr, hn as br, ht as xr, in as Sr, it as Cr, j as wr, jt as Tr, k as Er, kt as Dr, ln as Or, lt as kr, m as Ar, mn as jr, mt as Mr, nn as Nr, nt as Pr, ot as Fr, p as Ir, pn as Lr, pt as Rr, q as zr, qt as Br, r as Vr, rn as Hr, rt as Ur, sn as Wr, st as Gr, t as Kr, tn as qr, tt as Jr, u as Yr, un as Xr, ut as Zr, v as Qr, vt as $r, w as ei, wt as ti, x as ni, y as ri, yt as ii, z as ai, zt as oi } from "./common-Bi8KemMn.js";
11
11
  import { c as si, i as ci, n as li, o as ui, t as di } from "./useLifecycle-B5BX921H.js";
12
12
  import { t as fi } from "./check-SpOMoCLP.js";
13
13
  import { A as pi, C as mi, D as hi, E as gi, M as _i, O as vi, S as yi, T as bi, a as xi, b as Si, c as Ci, i 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-CkF_GBxO.js";
@@ -15,8 +15,8 @@ import { At as Ni, C as Pi, Dt as Fi, J as Ii, K as Li, R as Ri, S as zi, U as B
15
15
  import { C as da, _ as fa, a as pa, b as ma, c as ha, f as ga, h as _a, m as va, p as ya, s as ba, u as xa, x as Sa, y as Ca } from "./toDate-DGvRHwTk.js";
16
16
  import { a as wa, c as Ta, d as Ea, f as Da, i as Oa, l as ka, n as Aa, o as ja, r as Ma, s as Na, t as Pa } from "./process-output-B64ZYWuI.js";
17
17
  import { a as Fa, c as Ia, d as La, i as Ra, l as za, r as Ba, u as Va } from "./glide-utils-Dz_F4pAY.js";
18
- import { n as Ha, t as Ua } from "./ErrorBoundary-CImYa86e.js";
19
- import { n as Wa, t as Ga } from "./globals-DE2S2io9.js";
18
+ import { n as Ha, t as Ua } from "./ErrorBoundary-C1PyX4Kv.js";
19
+ import { n as Wa, t as Ga } from "./globals-C9s-sVIk.js";
20
20
  import { t as Ka } from "./react-dom-DUmH0GXv.js";
21
21
  import { t as qa } from "./jsx-runtime-3BD1kT0s.js";
22
22
  import { B as Ja, C as H, Ct as Ya, D as Xa, Dt as Za, E as Qa, Et as $a, F as U, G as eo, H as to, I as no, L as ro, M as W, N as io, O as ao, P as oo, Q as so, R as co, S as G, St as lo, Tt as uo, U as fo, W as po, Y as mo, Z as ho, _ as go, _t as _o, a as vo, b as yo, bt as bo, c as xo, d as So, f as Co, g as wo, h as To, i as Eo, j as K, k as Do, l as Oo, m as ko, n as Ao, o as jo, p as Mo, r as No, s as Po, u as Fo, ut as Io, v as Lo, w as Ro, wt as zo, x as Bo, xt as Vo, y as Ho, yt as Uo } from "./use-restore-focus-CmGwRNId.js";
@@ -39,7 +39,7 @@ import { t as Ns } from "./useAsyncData-BmVgnMP5.js";
39
39
  import { i as Ps, n as Fs, r as Is } from "./formats-CCxaLPNs.js";
40
40
  import { D as Ls, O as Rs } from "./vega-loader.browser-B9Pz0EGP.js";
41
41
  import { a as zs, n as Bs } from "./loader-DOVB0Syl.js";
42
- import { c as Vs, d as Hs, i as Us, l as Ws, o as Gs, s as Ks, t as qs, u as Js } from "./code-visibility-BZoWT5f1.js";
42
+ import { c as Vs, d as Hs, i as Us, l as Ws, o as Gs, s as Ks, t as qs, u as Js } from "./code-visibility-BS43kDO4.js";
43
43
  import { t as Ys } from "./useDeepCompareMemoize-Ch_AeGu6.js";
44
44
  import { t as Xs } from "./esm-D2gTsXEV.js";
45
45
  //#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
@@ -10635,7 +10635,7 @@ function UC(e, t) {
10635
10635
  }
10636
10636
  //#endregion
10637
10637
  //#region src/plugins/impl/DataEditorPlugin.tsx
10638
- var WC = J.lazy(() => import("./glide-data-editor-D72zmCan.js").then((e) => e.t)), GC = ES("marimo-data-editor", { cssStyles: [YS] }).withData(W({
10638
+ var WC = J.lazy(() => import("./glide-data-editor-BQBctTSS.js").then((e) => e.t)), GC = ES("marimo-data-editor", { cssStyles: [YS] }).withData(W({
10639
10639
  initialValue: W({ edits: G(W({
10640
10640
  rowIdx: K(),
10641
10641
  columnId: U(),
@@ -30414,7 +30414,7 @@ function UR(e) {
30414
30414
  }
30415
30415
  //#endregion
30416
30416
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
30417
- var WR = J.lazy(() => import("./reveal-component-DnbPU885.js")), GR = (e) => {
30417
+ var WR = J.lazy(() => import("./reveal-component-C2qjH1P6.js")), GR = (e) => {
30418
30418
  let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = rs(fa), s = a === "read" || o, c = rs(Ke) > 1, [l, u] = (0, J.useState)(null), d;
30419
30419
  t[0] !== i || t[1] !== n ? (d = VP(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
30420
30420
  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-D72zmCan.js";
3
+ import { a as n } from "./glide-data-editor-BQBctTSS.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-CJ4Rqasp.js";
6
6
  import { k as u } from "./error-entries-CmFDQ9CA.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-CGmIoGK3.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-Bi8KemMn.js";
8
8
  import { M as C } from "./select-CkF_GBxO.js";
9
9
  import { q as ee } from "./dropdown-menu-CgL3fm8P.js";
10
10
  import { _ as w } from "./toDate-DGvRHwTk.js";
11
11
  import { t as T } from "./jsx-runtime-3BD1kT0s.js";
12
12
  import { q as E } from "./use-restore-focus-CmGwRNId.js";
13
13
  import { A as D, C as O, b as k } from "./useTheme-Bq9pi_vz.js";
14
- import { a as A, n as te, t as ne } from "./code-visibility-BZoWT5f1.js";
14
+ import { a as A, n as te, t as ne } from "./code-visibility-BS43kDO4.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-dev134",
3
+ "version": "0.25.3-dev135",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -79,7 +79,9 @@ describe("DatasetColumnPreview fullyQualifiedTableName", () => {
79
79
  it("qualifies with database and schema for flat engines", () => {
80
80
  const client = renderPreview(ctx({ database: "db", schema: "public" }));
81
81
  expect(client.previewDatasetColumn).toHaveBeenCalledWith(
82
- expect.objectContaining({ fullyQualifiedTableName: "db.public.users" }),
82
+ expect.objectContaining({
83
+ fullyQualifiedTableName: '"db"."public"."users"',
84
+ }),
83
85
  );
84
86
  });
85
87
 
@@ -87,7 +89,7 @@ describe("DatasetColumnPreview fullyQualifiedTableName", () => {
87
89
  // Regression: previously produced "db..users".
88
90
  const client = renderPreview(ctx({ database: "db", schema: "" }));
89
91
  expect(client.previewDatasetColumn).toHaveBeenCalledWith(
90
- expect.objectContaining({ fullyQualifiedTableName: "db.users" }),
92
+ expect.objectContaining({ fullyQualifiedTableName: '"db"."users"' }),
91
93
  );
92
94
  });
93
95
 
@@ -98,7 +100,37 @@ describe("DatasetColumnPreview fullyQualifiedTableName", () => {
98
100
  );
99
101
  expect(client.previewDatasetColumn).toHaveBeenCalledWith(
100
102
  expect.objectContaining({
101
- fullyQualifiedTableName: "top.nested.deep.users",
103
+ fullyQualifiedTableName: '"top"."nested"."deep"."users"',
104
+ }),
105
+ );
106
+ });
107
+
108
+ it("quotes a literal dot as one schema segment", () => {
109
+ const client = renderPreview(
110
+ ctx({
111
+ database: "memory",
112
+ schema: "finance.reports",
113
+ schemaPath: ["finance.reports"],
114
+ }),
115
+ );
116
+ expect(client.previewDatasetColumn).toHaveBeenCalledWith(
117
+ expect.objectContaining({
118
+ fullyQualifiedTableName: '"memory"."finance.reports"."users"',
119
+ }),
120
+ );
121
+ });
122
+
123
+ it("escapes quotes inside schema identifiers", () => {
124
+ const client = renderPreview(
125
+ ctx({
126
+ database: "memory",
127
+ schema: 'fi"nance',
128
+ schemaPath: ['fi"nance', "reports"],
129
+ }),
130
+ );
131
+ expect(client.previewDatasetColumn).toHaveBeenCalledWith(
132
+ expect.objectContaining({
133
+ fullyQualifiedTableName: '"memory"."fi""nance"."reports"."users"',
102
134
  }),
103
135
  );
104
136
  });
@@ -0,0 +1,181 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import {
4
+ act,
5
+ fireEvent,
6
+ render,
7
+ screen,
8
+ waitFor,
9
+ } from "@testing-library/react";
10
+ import { createStore, Provider } from "jotai";
11
+ import { beforeAll, describe, expect, it, vi } from "vitest";
12
+ import { MockRequestClient } from "@/__mocks__/requests";
13
+ import { Command, CommandList } from "@/components/ui/command";
14
+ import { TooltipProvider } from "@/components/ui/tooltip";
15
+ import {
16
+ dataSourceConnectionsAtom,
17
+ type SQLTableContext,
18
+ } from "@/core/datasets/data-source-connections";
19
+ import { DUCKDB_ENGINE } from "@/core/datasets/engines";
20
+ import { datasetsAtom, exportedForTesting } from "@/core/datasets/state";
21
+ import type { DataTable } from "@/core/kernel/messages";
22
+ import { requestClientAtom } from "@/core/network/requests";
23
+ import {
24
+ DataSources,
25
+ hideEmptyDatasourcesAtom,
26
+ TableList,
27
+ } from "../datasources";
28
+
29
+ beforeAll(() => {
30
+ HTMLElement.prototype.scrollIntoView = vi.fn();
31
+ });
32
+
33
+ const table: DataTable = {
34
+ name: "reports",
35
+ columns: [
36
+ {
37
+ name: "amount",
38
+ type: "integer",
39
+ external_type: "INTEGER",
40
+ sample_values: [],
41
+ },
42
+ ],
43
+ source: "memory",
44
+ source_type: "duckdb",
45
+ type: "table",
46
+ engine: null,
47
+ indexes: null,
48
+ num_columns: 1,
49
+ num_rows: null,
50
+ variable_name: null,
51
+ primary_keys: null,
52
+ };
53
+
54
+ describe("Datasource column preview responses", () => {
55
+ it.each([
56
+ { path: ["main"], qualifiedName: '"memory"."main"."reports"' },
57
+ {
58
+ path: ["finance", "reports"],
59
+ qualifiedName: '"memory"."finance"."reports"."reports"',
60
+ },
61
+ {
62
+ path: ["finance.reports"],
63
+ qualifiedName: '"memory"."finance.reports"."reports"',
64
+ },
65
+ {
66
+ path: ['fi"nance', "reports"],
67
+ qualifiedName: '"memory"."fi""nance"."reports"."reports"',
68
+ },
69
+ ])(
70
+ "renders the returned preview for $path",
71
+ async ({ path, qualifiedName }) => {
72
+ const store = createStore();
73
+ const client = MockRequestClient.create();
74
+ store.set(requestClientAtom, client);
75
+ const context: SQLTableContext = {
76
+ engine: DUCKDB_ENGINE,
77
+ database: "memory",
78
+ schema: path.at(-1) ?? "",
79
+ schemaPath: path,
80
+ dialect: "duckdb",
81
+ };
82
+ render(
83
+ <Provider store={store}>
84
+ <TooltipProvider>
85
+ <Command shouldFilter={false}>
86
+ <CommandList>
87
+ <TableList tables={[table]} sqlTableContext={context} />
88
+ </CommandList>
89
+ </Command>
90
+ </TooltipProvider>
91
+ </Provider>,
92
+ );
93
+
94
+ fireEvent.click(await screen.findByText("reports"));
95
+ fireEvent.click(await screen.findByText("amount"));
96
+ await waitFor(() => {
97
+ expect(client.previewDatasetColumn).toHaveBeenCalledWith(
98
+ expect.objectContaining({ fullyQualifiedTableName: qualifiedName }),
99
+ );
100
+ });
101
+ expect(screen.getByText("Loading...")).toBeInTheDocument();
102
+
103
+ const actions = exportedForTesting.createActions((action) => {
104
+ store.set(datasetsAtom, (state) =>
105
+ exportedForTesting.reducer(state, action),
106
+ );
107
+ });
108
+ act(() => {
109
+ actions.addColumnPreview({
110
+ table_name: qualifiedName,
111
+ column_name: "amount",
112
+ stats: { min: 42 },
113
+ error: null,
114
+ missing_packages: null,
115
+ chart_spec: null,
116
+ chart_code: null,
117
+ });
118
+ });
119
+
120
+ expect(await screen.findByText("42")).toBeInTheDocument();
121
+ expect(screen.queryByText("Loading...")).not.toBeInTheDocument();
122
+ },
123
+ );
124
+ });
125
+
126
+ it("activates a schema and a table with the same path independently using the keyboard", async () => {
127
+ const store = createStore();
128
+ store.set(requestClientAtom, MockRequestClient.create());
129
+ store.set(hideEmptyDatasourcesAtom, false);
130
+ store.set(dataSourceConnectionsAtom, {
131
+ latestEngineSelected: DUCKDB_ENGINE,
132
+ connectionsMap: new Map([
133
+ [
134
+ DUCKDB_ENGINE,
135
+ {
136
+ name: DUCKDB_ENGINE,
137
+ dialect: "duckdb",
138
+ source: "duckdb",
139
+ display_name: "DuckDB (In-Memory)",
140
+ databases: [
141
+ {
142
+ name: "memory",
143
+ dialect: "duckdb",
144
+ schemas: [
145
+ {
146
+ name: "finance",
147
+ tables: [table],
148
+ child_schemas: [{ name: "reports", tables: [] }],
149
+ },
150
+ ],
151
+ },
152
+ ],
153
+ },
154
+ ],
155
+ ]),
156
+ });
157
+ render(
158
+ <Provider store={store}>
159
+ <TooltipProvider>
160
+ <DataSources />
161
+ </TooltipProvider>
162
+ </Provider>,
163
+ );
164
+ fireEvent.click(await screen.findByText("memory"));
165
+ fireEvent.click(await screen.findByText("finance"));
166
+ await waitFor(() => {
167
+ expect(screen.getAllByText("reports")).toHaveLength(2);
168
+ });
169
+
170
+ const input = screen.getByRole("combobox");
171
+ input.focus();
172
+ fireEvent.keyDown(input, { key: "ArrowDown" });
173
+ fireEvent.keyDown(input, { key: "Enter" });
174
+ expect(await screen.findByText("No tables found")).toBeInTheDocument();
175
+ expect(screen.queryByText("amount")).not.toBeInTheDocument();
176
+
177
+ fireEvent.keyDown(input, { key: "ArrowDown" });
178
+ fireEvent.keyDown(input, { key: "Enter" });
179
+ expect(await screen.findByText("amount")).toBeInTheDocument();
180
+ expect(screen.getByText("No tables found")).toBeInTheDocument();
181
+ });
@@ -34,6 +34,37 @@ describe("sqlCode", () => {
34
34
  name: "email" as const,
35
35
  } as DataTableColumn;
36
36
 
37
+ it.each([
38
+ {
39
+ path: ["finance", "reports"],
40
+ expected: '"memory"."finance"."reports"."users"',
41
+ },
42
+ { path: ["finance.reports"], expected: '"finance.reports"."users"' },
43
+ {
44
+ path: ['fi"nance', "reports"],
45
+ expected: '"memory"."fi""nance"."reports"."users"',
46
+ },
47
+ {
48
+ path: ["main", "reports"],
49
+ expected: '"memory"."main"."reports"."users"',
50
+ },
51
+ ])("preserves schema path $path in generated SQL", ({ path, expected }) => {
52
+ const result = sqlCode({
53
+ table: mockTable,
54
+ columnName: "*",
55
+ sqlTableContext: {
56
+ engine: DUCKDB_ENGINE,
57
+ dialect: "duckdb",
58
+ database: "memory",
59
+ defaultDatabase: "memory",
60
+ defaultSchema: "main",
61
+ schema: path.at(-1)!,
62
+ schemaPath: path,
63
+ },
64
+ });
65
+ expect(result).toContain(`FROM ${expected}`);
66
+ });
67
+
37
68
  describe("basic SQL generation", () => {
38
69
  it("should generate basic SQL without sqlTableContext", () => {
39
70
  const result = sqlCode({ table: mockTable, columnName: mockColumn.name });
@@ -484,7 +515,7 @@ describe("tableUniqueId", () => {
484
515
 
485
516
  it("uses database + schema for flat engines", () => {
486
517
  expect(tableUniqueId(ctx({ database: "db", schema: "public" }), "t")).toBe(
487
- "db.public.t",
518
+ '["db","public","t"]',
488
519
  );
489
520
  });
490
521
 
@@ -495,7 +526,7 @@ describe("tableUniqueId", () => {
495
526
  ctx({ database: "top", schema: "nested", schemaPath: ["nested"] }),
496
527
  "t",
497
528
  ),
498
- ).toBe("top.nested.t");
529
+ ).toBe('["top","nested","t"]');
499
530
  });
500
531
 
501
532
  it("includes the full schema path for deeply nested namespaces", () => {
@@ -508,7 +539,7 @@ describe("tableUniqueId", () => {
508
539
  }),
509
540
  "t",
510
541
  ),
511
- ).toBe("top.nested.deep.t");
542
+ ).toBe('["top","nested","deep","t"]');
512
543
  });
513
544
 
514
545
  it("falls back to the flat schema when schemaPath is empty", () => {
@@ -517,16 +548,36 @@ describe("tableUniqueId", () => {
517
548
  ctx({ database: "db", schema: "public", schemaPath: [] }),
518
549
  "t",
519
550
  ),
520
- ).toBe("db.public.t");
551
+ ).toBe('["db","public","t"]');
521
552
  });
522
553
 
523
554
  it("does not emit a double dot for schemaless tables", () => {
524
555
  expect(
525
556
  tableUniqueId(ctx({ database: "db", schema: "", schemaPath: [] }), "t"),
526
- ).toBe("db.t");
557
+ ).toBe('["db","t"]');
527
558
  expect(tableUniqueId(ctx({ database: "db", schema: "" }), "t")).toBe(
528
- "db.t",
559
+ '["db","t"]',
560
+ );
561
+ });
562
+
563
+ it("keeps literal-dot and nested schemas distinct", () => {
564
+ const nested = tableUniqueId(
565
+ ctx({
566
+ database: "memory",
567
+ schema: "reports",
568
+ schemaPath: ["finance", "reports"],
569
+ }),
570
+ "sales",
571
+ );
572
+ const literal = tableUniqueId(
573
+ ctx({
574
+ database: "memory",
575
+ schema: "finance.reports",
576
+ schemaPath: ["finance.reports"],
577
+ }),
578
+ "sales",
529
579
  );
580
+ expect(nested).not.toBe(literal);
530
581
  });
531
582
  });
532
583
 
@@ -29,7 +29,7 @@ import { Button } from "../ui/button";
29
29
  import { Tooltip } from "../ui/tooltip";
30
30
  import { ColumnPreviewContainer } from "./components";
31
31
  import { InstallPackageButton } from "./install-package-button";
32
- import { convertStatsName, sqlCode, tableUniqueId } from "./utils";
32
+ import { convertStatsName, fullyQualifiedTableName, sqlCode } from "./utils";
33
33
 
34
34
  export const DatasetColumnPreview: React.FC<{
35
35
  table: DataTable;
@@ -48,7 +48,10 @@ export const DatasetColumnPreview: React.FC<{
48
48
  tableName: table.name,
49
49
  columnName: column.name,
50
50
  sourceType: table.source_type,
51
- fullyQualifiedTableName: tableUniqueId(sqlTableContext, table.name),
51
+ fullyQualifiedTableName: fullyQualifiedTableName(
52
+ sqlTableContext,
53
+ table.name,
54
+ ),
52
55
  });
53
56
  };
54
57
 
@@ -78,6 +78,7 @@ import {
78
78
  areChildSchemasResolved,
79
79
  areSchemasResolved,
80
80
  areTablesResolved,
81
+ fullyQualifiedTableName,
81
82
  isSchemaless,
82
83
  schemaSubtreeMatchesSearch,
83
84
  shouldExpandDatabaseForSearch,
@@ -637,7 +638,7 @@ const SchemaNode: React.FC<SchemaNodeProps> = (props) => {
637
638
  const [prevSearchValue, setPrevSearchValue] = React.useState(searchValue);
638
639
  const [prevExpandForSearch, setPrevExpandForSearch] =
639
640
  React.useState(expandForSearch);
640
- const uniqueValue = `${databaseName}:${schemaPath.join(".")}`;
641
+ const uniqueValue = JSON.stringify(["schema", databaseName, ...schemaPath]);
641
642
  const childSchemas = schema.child_schemas ?? [];
642
643
 
643
644
  // Re-sync when the query changes or when newly resolved data turns this
@@ -1095,9 +1096,7 @@ const DatasetColumnItem: React.FC<{
1095
1096
  column={column}
1096
1097
  onAddColumnChart={handleAddColumn}
1097
1098
  preview={columnsPreviews.get(
1098
- sqlTableContext
1099
- ? `${sqlTableContext.database}.${sqlTableContext.schema}.${table.name}:${column.name}`
1100
- : `${table.name}:${column.name}`,
1099
+ `${fullyQualifiedTableName(sqlTableContext, table.name)}:${column.name}`,
1101
1100
  )}
1102
1101
  sqlTableContext={sqlTableContext}
1103
1102
  />
@@ -13,26 +13,29 @@ import type {
13
13
  import { logNever } from "@/utils/assertNever";
14
14
  import type { ColumnHeaderStatsKey } from "../data-table/types";
15
15
 
16
- /**
17
- * Stable id for a table node in the datasources tree.
18
- *
19
- * schemaPath already includes the leaf schema for nested namespaces, so use it
20
- * when present and fall back to the flat schema name otherwise (avoids
21
- * duplicating the leaf, e.g. `top.nested.nested.table`).
22
- */
16
+ function tablePath(context: SQLTableContext, tableName: string): string[] {
17
+ const segments = context.schemaPath?.length
18
+ ? context.schemaPath
19
+ : [context.schema];
20
+ return [context.database, ...segments.filter(Boolean), tableName];
21
+ }
22
+
23
23
  export function tableUniqueId(
24
- sqlTableContext: SQLTableContext | undefined,
24
+ context: SQLTableContext | undefined,
25
25
  tableName: string,
26
26
  ): string {
27
- if (!sqlTableContext) {
28
- return tableName;
29
- }
30
- const segments = (
31
- sqlTableContext.schemaPath?.length
32
- ? sqlTableContext.schemaPath
33
- : [sqlTableContext.schema]
34
- ).filter(Boolean);
35
- return [sqlTableContext.database, ...segments, tableName].join(".");
27
+ return context ? JSON.stringify(tablePath(context, tableName)) : tableName;
28
+ }
29
+
30
+ export function fullyQualifiedTableName(
31
+ context: SQLTableContext | undefined,
32
+ tableName: string,
33
+ ): string {
34
+ return context
35
+ ? getFormatter(context.dialect).formatTablePath(
36
+ tablePath(context, tableName),
37
+ )
38
+ : tableName;
36
39
  }
37
40
 
38
41
  // Some databases have no schemas, so we don't show it (eg. Clickhouse)
@@ -114,6 +117,10 @@ const defaultFormatter: SqlCodeFormatter = {
114
117
  `SELECT ${columnName} FROM ${tableName} LIMIT 100`,
115
118
  };
116
119
 
120
+ function quoteIdentifier(identifier: string): string {
121
+ return `"${identifier.replaceAll('"', '""')}"`;
122
+ }
123
+
117
124
  function getFormatter(dialect: string): SqlCodeFormatter {
118
125
  dialect = dialect.toLowerCase();
119
126
  if (!isKnownDialect(dialect)) {
@@ -146,9 +153,9 @@ function getFormatter(dialect: string): SqlCodeFormatter {
146
153
  // Quote column and table names to avoid raising errors on weird characters
147
154
  return {
148
155
  formatTablePath: (tablePath: string[]) =>
149
- tablePath.map((part) => `"${part}"`).join("."),
156
+ tablePath.map(quoteIdentifier).join("."),
150
157
  formatSelectClause: (columnName: string, tableName: string) =>
151
- `SELECT ${columnName === "*" ? "*" : `"${columnName}"`} FROM ${tableName} LIMIT 100`,
158
+ `SELECT ${columnName === "*" ? "*" : quoteIdentifier(columnName)} FROM ${tableName} LIMIT 100`,
152
159
  };
153
160
  case "db2":
154
161
  case "db2i":
@@ -194,6 +201,7 @@ export function sqlCode({
194
201
  engine,
195
202
  schema,
196
203
  defaultSchema,
204
+ schemaPath,
197
205
  defaultDatabase,
198
206
  database,
199
207
  dialect,
@@ -207,12 +215,13 @@ export function sqlCode({
207
215
  }
208
216
  } else {
209
217
  // Include schema if it's not the default schema
210
- if (schema !== defaultSchema) {
211
- tablePath.unshift(schema);
218
+ const path = schemaPath?.length ? schemaPath : [schema];
219
+ if (path.length > 1 || path[0] !== defaultSchema) {
220
+ tablePath.unshift(...path);
212
221
  }
213
222
 
214
- // Include database if it's not the default database
215
- if (database !== defaultDatabase) {
223
+ // Nested schema names can also be attached catalog names.
224
+ if (path.length > 1 || database !== defaultDatabase) {
216
225
  tablePath.unshift(database);
217
226
  }
218
227
  }