@marimo-team/islands 0.25.1-dev17 → 0.25.1-dev18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/{ConnectedDataExplorerComponent-KVhjDMSe.js → ConnectedDataExplorerComponent-CwMXfDQR.js} +3 -3
  2. package/dist/{ErrorBoundary-B4i0ev18.js → ErrorBoundary-BCANhTrt.js} +1 -1
  3. package/dist/{code-visibility-CRc1C5g4.js → code-visibility-DIUkT8x-.js} +1 -1
  4. package/dist/{common-DQS4JILK.js → common-BfERj74g.js} +5 -5
  5. package/dist/{data-grid-overlay-editor-D0-p5694.js → data-grid-overlay-editor-ByNOrM5s.js} +1 -1
  6. package/dist/{feedback-button-DD68Ij-B.js → feedback-button-C6WatdDY.js} +2 -2
  7. package/dist/{formats-C8rLgZT9.js → formats-Cl_67ghI.js} +1 -1
  8. package/dist/{glide-data-editor-DqTwUsOq.js → glide-data-editor-BaQLny21.js} +3 -3
  9. package/dist/{globals-RG69U5-c.js → globals-DDOIQV3b.js} +1 -1
  10. package/dist/{loader-D2W4oM-3.js → loader-DEZSzvma.js} +253 -248
  11. package/dist/main.js +46 -39
  12. package/dist/{number-overlay-editor-DB4g1nLo.js → number-overlay-editor-pI5HWUmx.js} +1 -1
  13. package/dist/{react-vega-5AcMW8gG.js → react-vega-ewj7q_U5.js} +1 -1
  14. package/dist/{reveal-component-QBu-zZNO.js → reveal-component-BeyJErFp.js} +2 -2
  15. package/dist/{vega-component-CNf5gcrm.js → vega-component-tFOzgarw.js} +4 -4
  16. package/dist/{vega-embed-container-CbnTccZi.js → vega-embed-container-sSR5hAsy.js} +2 -2
  17. package/dist/{vega-loader.browser-D95WfUcj.js → vega-loader.browser-DNST6uVf.js} +2 -2
  18. package/package.json +1 -1
  19. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +286 -0
  20. package/src/components/data-table/charts/charts.tsx +26 -13
  21. package/src/plugins/impl/vega/__tests__/utils.test.ts +16 -1
  22. package/src/plugins/impl/vega/__tests__/vega.test.ts +37 -0
  23. package/src/plugins/impl/vega/loader.ts +23 -1
  24. package/src/plugins/impl/vega/utils.ts +5 -4
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 se, f as ce, g as V, i as le, n as ue, o as de, p as fe, r as pe, t as me } from "./tooltip-qB8NlSqV.js";
8
8
  import { $ as he, $t as ge, B as _e, Bt as ve, C as ye, Ct as be, D as xe, Dt as Se, Et as Ce, F as we, G as Te, Gt as Ee, Ht as De, I as Oe, J as ke, Jt as Ae, Kt as je, L as Me, O as Ne, Ot as Pe, P as Fe, Pt as Ie, Q as Le, Qt as Re, Rt as ze, S as Be, St as Ve, T as He, Tt as Ue, U as We, W as Ge, Wt as Ke, bt as qe, c as Je, cn as Ye, ct as Xe, d as Ze, dn as Qe, dt as $e, en as et, f as tt, fn as nt, ft as rt, g as it, gt as at, h as ot, hn as st, k as ct, l as lt, ln as ut, m as dt, mn as ft, n as pt, o as mt, on as ht, ot as gt, p as _t, q as vt, qt as yt, r as bt, rn as xt, rt as St, sn as Ct, st as wt, tn as Tt, u as Et, v as Dt, w as Ot, wt as kt, zt as At } from "./cells-Cksce8br.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-CAYwFeV6.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-DQS4JILK.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-BfERj74g.js";
11
11
  import { c as si, i as ci, n as li, o as ui, t as di } from "./useLifecycle-DPgiiwwU.js";
12
12
  import { t as fi } from "./check-B7cIK6gb.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, k 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-C6plhmZr.js";
@@ -15,8 +15,8 @@ import { B as Pi, C as Fi, J as Ii, Mt as Li, Nt as Ri, S as zi, Vt as Bi, W as
15
15
  import { C as da, S as fa, T as pa, _ as ma, c as ha, d as ga, f as _a, g as va, h as ya, m as ba, u as xa, x as Sa, y as Ca } from "./toDate-C67bxMWn.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-DevJrL3v.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-B3rUT5PI.js";
18
- import { n as Ha, t as Ua } from "./ErrorBoundary-B4i0ev18.js";
19
- import { n as Wa, t as Ga } from "./globals-RG69U5-c.js";
18
+ import { n as Ha, t as Ua } from "./ErrorBoundary-BCANhTrt.js";
19
+ import { n as Wa, t as Ga } from "./globals-DDOIQV3b.js";
20
20
  import { t as Ka } from "./react-dom-BUgJ-ab_.js";
21
21
  import { t as qa } from "./jsx-runtime-DgDPJV9S.js";
22
22
  import { B as Ja, C as H, Ct as Ya, D as Xa, E as Za, Et as Qa, F as U, G as $a, H as eo, I as to, L as no, M as W, N as ro, O as io, P as ao, Q as oo, R as so, S as G, St as co, Tt as lo, U as uo, W as fo, Y as po, Z as mo, _ as ho, a as go, b as _o, bt as vo, c as yo, d as bo, dt as xo, f as So, g as Co, gt 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, v as Io, vt as Lo, w as Ro, wt as zo, x as Bo, xt as Vo, y as Ho, yt as Uo } from "./use-restore-focus-D5D9xEjZ.js";
@@ -37,10 +37,10 @@ import { n as ks } from "./dist-BRxfaJgs.js";
37
37
  import { i as As } from "./dist-C2KzV-vf.js";
38
38
  import { n as js, t as Ms } from "./esm-h8f7-1CJ.js";
39
39
  import { t as Ns } from "./useAsyncData-BD6AStMt.js";
40
- import { i as Ps, n as Fs, r as Is } from "./formats-C8rLgZT9.js";
41
- import { M as Ls, N as Rs } from "./vega-loader.browser-D95WfUcj.js";
42
- import { a as zs, n as Bs } from "./loader-D2W4oM-3.js";
43
- 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-CRc1C5g4.js";
40
+ import { i as Ps, n as Fs, r as Is } from "./formats-Cl_67ghI.js";
41
+ import { M as Ls, N as Rs } from "./vega-loader.browser-DNST6uVf.js";
42
+ import { a as zs, n as Bs } from "./loader-DEZSzvma.js";
43
+ 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-DIUkT8x-.js";
44
44
  import { t as Ys } from "./useDeepCompareMemoize-D_HNdyvI.js";
45
45
  import { t as Xs } from "./esm-BElI3qKH.js";
46
46
  //#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
@@ -10458,7 +10458,7 @@ function RC(e, t) {
10458
10458
  }
10459
10459
  //#endregion
10460
10460
  //#region src/plugins/impl/DataEditorPlugin.tsx
10461
- var zC = J.lazy(() => import("./glide-data-editor-DqTwUsOq.js").then((e) => e.t)), BC = xS("marimo-data-editor", { cssStyles: [WS] }).withData(W({
10461
+ var zC = J.lazy(() => import("./glide-data-editor-BaQLny21.js").then((e) => e.t)), BC = xS("marimo-data-editor", { cssStyles: [WS] }).withData(W({
10462
10462
  initialValue: W({ edits: G(W({
10463
10463
  rowIdx: K(),
10464
10464
  columnId: U(),
@@ -13668,26 +13668,33 @@ var ZT = ({ cellId: e, data: t, dataTable: n, totalRows: r, columns: i, getDataU
13668
13668
  S(e.tabName, t);
13669
13669
  },
13670
13670
  getDataUrl: a,
13671
+ hasSchema: !!o?.length,
13671
13672
  fieldTypes: XT(o ?? Zr(n.props.data), s),
13672
13673
  isLargeDataset: C
13673
13674
  })
13674
13675
  }, r))
13675
13676
  ]
13676
13677
  });
13677
- }, QT = "X and Y columns are not set", $T = ({ tableData: e, chartConfig: t, chartType: n, saveChart: r, saveChartType: i, getDataUrl: a, fieldTypes: o, isLargeDataset: s }) => {
13678
- let { theme: c } = fs(), l = Qm({
13678
+ }, QT = "X and Y columns are not set", $T = ({ tableData: e, chartConfig: t, chartType: n, saveChart: r, saveChartType: i, getDataUrl: a, fieldTypes: o, hasSchema: s = !!o?.length, isLargeDataset: c }) => {
13679
+ let { theme: l } = fs(), u = Qm({
13679
13680
  defaultValues: t ?? FT(),
13680
13681
  resolver: ch(PT)
13681
- }), [u, d] = (0, J.useState)(n), [f, p] = (0, J.useState)(!1), [m, h] = (0, J.useState)(!s), { ref: g } = WC(), { data: v, isPending: y, error: b } = Ns(async () => {
13682
- if (!a || e.length === 0 || !m) return [];
13682
+ }), [d, f] = (0, J.useState)(n), [p, m] = (0, J.useState)(!1), [h, g] = (0, J.useState)(!c), { ref: v } = WC(), y = Ys(s ? o : null), { data: b, isPending: x, error: S } = Ns(async () => {
13683
+ if (!a || e.length === 0 || !h) return [];
13683
13684
  let t = await a({});
13684
- return Array.isArray(t.data_url) ? t.data_url : await Bs(t.data_url, t.format === "arrow" ? { type: "arrow" } : t.format === "json" ? { type: "json" } : {
13685
+ if (Array.isArray(t.data_url)) return t.data_url;
13686
+ let n;
13687
+ return n = t.format === "arrow" ? { type: "arrow" } : t.format === "json" ? { type: "json" } : {
13685
13688
  type: "csv",
13686
- parse: "auto"
13687
- }, { replacePeriod: !0 });
13688
- }, [e, m]), x = l.watch(), S = (0, J.useMemo)(() => structuredClone(x), [x]), C = Kt(u, S, c, "container", qT), w = (0, J.useMemo)(() => y ? /* @__PURE__ */ (0, Y.jsx)(Sn, {}) : b ? /* @__PURE__ */ (0, Y.jsx)(In, { error: b }) : m ? /* @__PURE__ */ (0, Y.jsx)(DT, {
13689
- baseSpec: C,
13690
- data: v,
13689
+ parse: Rs(y && Object.fromEntries(y.map(([e, [t]]) => [e, t])), { parseDates: !0 })
13690
+ }, Bs(t.data_url, n);
13691
+ }, [
13692
+ e,
13693
+ h,
13694
+ y
13695
+ ]), C = u.watch(), w = (0, J.useMemo)(() => structuredClone(C), [C]), T = Kt(d, w, l, "container", qT), E = (0, J.useMemo)(() => x ? /* @__PURE__ */ (0, Y.jsx)(Sn, {}) : S ? /* @__PURE__ */ (0, Y.jsx)(In, { error: S }) : h ? /* @__PURE__ */ (0, Y.jsx)(DT, {
13696
+ baseSpec: T,
13697
+ data: b,
13691
13698
  height: qT
13692
13699
  }) : /* @__PURE__ */ (0, Y.jsxs)(Fs, {
13693
13700
  variant: "warning",
@@ -13696,45 +13703,45 @@ var ZT = ({ cellId: e, data: t, dataTable: n, totalRows: r, columns: i, getDataU
13696
13703
  className: "flex flex-row justify-between items-center w-full",
13697
13704
  children: [/* @__PURE__ */ (0, Y.jsx)("span", { children: "Rendering large datasets is not well supported and may crash the browser" }), /* @__PURE__ */ (0, Y.jsx)(_, {
13698
13705
  variant: "warn",
13699
- onClick: () => h(!0),
13706
+ onClick: () => g(!0),
13700
13707
  className: "h-8",
13701
13708
  children: "Proceed"
13702
13709
  })]
13703
13710
  })]
13704
13711
  }), [
13705
- y,
13706
- b,
13707
- m,
13708
- C,
13709
- v
13712
+ x,
13713
+ S,
13714
+ h,
13715
+ T,
13716
+ b
13710
13717
  ]);
13711
13718
  return /* @__PURE__ */ (0, Y.jsxs)("div", {
13712
13719
  className: "flex flex-row gap-2 h-full rounded-md border-t pr-2",
13713
13720
  children: [/* @__PURE__ */ (0, Y.jsxs)("div", {
13714
- className: `relative flex flex-col gap-2 overflow-auto px-2 py-3 scrollbar-thin transition-width duration-200 ${f ? "w-8" : "w-[300px]"}`,
13715
- children: [!f && /* @__PURE__ */ (0, Y.jsxs)(Y.Fragment, { children: [/* @__PURE__ */ (0, Y.jsx)(pT, {
13716
- value: u,
13721
+ className: `relative flex flex-col gap-2 overflow-auto px-2 py-3 scrollbar-thin transition-width duration-200 ${p ? "w-8" : "w-[300px]"}`,
13722
+ children: [!p && /* @__PURE__ */ (0, Y.jsxs)(Y.Fragment, { children: [/* @__PURE__ */ (0, Y.jsx)(pT, {
13723
+ value: d,
13717
13724
  onValueChange: (e) => {
13718
- d(e), i(e);
13725
+ f(e), i(e);
13719
13726
  }
13720
13727
  }), /* @__PURE__ */ (0, Y.jsx)(eE, {
13721
- form: l,
13728
+ form: u,
13722
13729
  saveChart: r,
13723
13730
  fieldTypes: o,
13724
- chartType: u
13731
+ chartType: d
13725
13732
  })] }), /* @__PURE__ */ (0, Y.jsx)(_, {
13726
13733
  variant: "outline",
13727
13734
  size: "icon",
13728
13735
  className: "border-border ml-auto",
13729
- onClick: () => p((e) => !e),
13730
- title: f ? "Expand sidebar" : "Collapse sidebar",
13731
- children: f ? /* @__PURE__ */ (0, Y.jsx)(na, { className: "w-4 h-5" }) : /* @__PURE__ */ (0, Y.jsx)(jr, { className: "w-4 h-5" })
13736
+ onClick: () => m((e) => !e),
13737
+ title: p ? "Expand sidebar" : "Collapse sidebar",
13738
+ children: p ? /* @__PURE__ */ (0, Y.jsx)(na, { className: "w-4 h-5" }) : /* @__PURE__ */ (0, Y.jsx)(jr, { className: "w-4 h-5" })
13732
13739
  })]
13733
13740
  }), /* @__PURE__ */ (0, Y.jsx)("div", {
13734
13741
  className: "flex-1 overflow-auto h-full w-full mt-3",
13735
13742
  children: (() => {
13736
13743
  let e = QT;
13737
- return typeof C != "string" && (e = rw(C, "_df", "_chart")), /* @__PURE__ */ (0, Y.jsxs)(on, {
13744
+ return typeof T != "string" && (e = rw(T, "_df", "_chart")), /* @__PURE__ */ (0, Y.jsxs)(on, {
13738
13745
  defaultValue: "chart",
13739
13746
  children: [
13740
13747
  /* @__PURE__ */ (0, Y.jsx)("div", {
@@ -13755,8 +13762,8 @@ var ZT = ({ cellId: e, data: t, dataTable: n, totalRows: r, columns: i, getDataU
13755
13762
  }),
13756
13763
  /* @__PURE__ */ (0, Y.jsx)(Tr, {
13757
13764
  value: "chart",
13758
- ref: g,
13759
- children: w
13765
+ ref: v,
13766
+ children: E
13760
13767
  }),
13761
13768
  /* @__PURE__ */ (0, Y.jsx)(Tr, {
13762
13769
  value: "code",
@@ -15396,7 +15403,7 @@ var $E = class {
15396
15403
  fullWidth: s,
15397
15404
  children: _
15398
15405
  }), t[20] = s, t[21] = u, t[22] = n, t[23] = _, t[24] = v) : v = t[24], v;
15399
- }, nD = J.lazy(() => import("./ConnectedDataExplorerComponent-KVhjDMSe.js")), rD = xS("marimo-data-explorer").withData(W({
15406
+ }, nD = J.lazy(() => import("./ConnectedDataExplorerComponent-CwMXfDQR.js")), rD = xS("marimo-data-explorer").withData(W({
15400
15407
  label: U().nullish(),
15401
15408
  data: U()
15402
15409
  })).renderer((e) => /* @__PURE__ */ (0, Y.jsx)(nD, {
@@ -21653,7 +21660,7 @@ function Gj(e, t) {
21653
21660
  }
21654
21661
  //#endregion
21655
21662
  //#region src/plugins/impl/vega/VegaPlugin.tsx
21656
- var Kj = J.lazy(() => import("./vega-component-CNf5gcrm.js")), qj = class {
21663
+ var Kj = J.lazy(() => import("./vega-component-tFOzgarw.js")), qj = class {
21657
21664
  tagName = "marimo-vega";
21658
21665
  validator = W({
21659
21666
  spec: W({}).passthrough().transform((e) => e),
@@ -29927,7 +29934,7 @@ function bR(e) {
29927
29934
  }
29928
29935
  //#endregion
29929
29936
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
29930
- var xR = J.lazy(() => import("./reveal-component-QBu-zZNO.js")), SR = (e) => {
29937
+ var xR = J.lazy(() => import("./reveal-component-BeyJErFp.js")), SR = (e) => {
29931
29938
  let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = rs(Ca), s = a === "read" || o, c = rs(_t) > 1, [l, u] = (0, J.useState)(null), d;
29932
29939
  t[0] !== i || t[1] !== n ? (d = vP(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
29933
29940
  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-ofJbxM4x.js";
3
- import { a as n } from "./glide-data-editor-DqTwUsOq.js";
3
+ import { a as n } from "./glide-data-editor-BaQLny21.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.2.8_b9e6aec46d952f631ce71b0585d2a8e5/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,7 +1,7 @@
1
1
  import { a as e, r as t } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t as n } from "./react-ofJbxM4x.js";
3
3
  import { t as r } from "./jsx-runtime-DgDPJV9S.js";
4
- import { $ as i, A as a, B as o, C as s, D as c, E as l, F as u, G as d, H as f, I as p, J as m, K as h, L as g, O as _, P as v, Q as y, R as b, S as x, T as S, U as C, V as w, W as T, X as E, Y as D, Z as O, _ as k, a as A, at as ee, b as te, c as ne, ct as re, d as ie, dt as ae, et as oe, f as se, ft as ce, g as le, gt as ue, h as de, ht as fe, i as pe, it as me, j as he, k as ge, l as _e, lt as ve, m as ye, mt as be, n as xe, nt as j, o as Se, ot as Ce, p as we, pt as M, q as Te, r as Ee, rt as N, s as De, st as Oe, t as ke, tt as Ae, u as je, ut as Me, v as eee, w as Ne, x as Pe, y as Fe, z as Ie } from "./vega-loader.browser-D95WfUcj.js";
4
+ import { $ as i, A as a, B as o, C as s, D as c, E as l, F as u, G as d, H as f, I as p, J as m, K as h, L as g, O as _, P as v, Q as y, R as b, S as x, T as S, U as C, V as w, W as T, X as E, Y as D, Z as O, _ as k, a as A, at as ee, b as te, c as ne, ct as re, d as ie, dt as ae, et as oe, f as se, ft as ce, g as le, gt as ue, h as de, ht as fe, i as pe, it as me, j as he, k as ge, l as _e, lt as ve, m as ye, mt as be, n as xe, nt as j, o as Se, ot as Ce, p as we, pt as M, q as Te, r as Ee, rt as N, s as De, st as Oe, t as ke, tt as Ae, u as je, ut as Me, v as eee, w as Ne, x as Pe, y as Fe, z as Ie } from "./vega-loader.browser-DNST6uVf.js";
5
5
  import { a as Le, c as Re, o as ze, s as Be } from "./precisionRound-DMIVQrt2.js";
6
6
  import { _ as tee, a as Ve, c as He, d as nee, f as Ue, g as We, h as Ge, l as Ke, m as qe, n as Je, o as Ye, p as ree, r as Xe, s as Ze, t as Qe, u as $e, v as et } from "./linear-Cnaq3Tfb.js";
7
7
  import { n as tt, r as nt, t as rt } from "./ordinal-c7efuCSS.js";
@@ -4,14 +4,14 @@ import { t as o } from "./react-ofJbxM4x.js";
4
4
  import { t as s } from "./compiler-runtime-Cj8ZWiNS.js";
5
5
  import { g as c, t as l } from "./tooltip-qB8NlSqV.js";
6
6
  import { w as u } from "./cells-Cksce8br.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-DQS4JILK.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-BfERj74g.js";
8
8
  import { M as C } from "./select-C6plhmZr.js";
9
9
  import { J as ee } from "./dropdown-menu-CZgjYSAh.js";
10
10
  import { y as w } from "./toDate-C67bxMWn.js";
11
11
  import { t as T } from "./jsx-runtime-DgDPJV9S.js";
12
12
  import { q as te } from "./use-restore-focus-D5D9xEjZ.js";
13
13
  import { A as E, C as D, b as O } from "./useTheme-DzXmYZ5V.js";
14
- import { a as k, n as ne, t as re } from "./code-visibility-CRc1C5g4.js";
14
+ import { a as k, n as ne, t as re } from "./code-visibility-DIUkT8x-.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",
@@ -11,10 +11,10 @@ import { A as p, n as ee } from "./useTheme-DzXmYZ5V.js";
11
11
  import { c as m } from "./arrays-CN1djC4k.js";
12
12
  import { t as te } from "./objects-CzUgoMIF.js";
13
13
  import { t as h } from "./useAsyncData-BD6AStMt.js";
14
- import { a as ne, i as re, n as ie, t as g } from "./formats-C8rLgZT9.js";
15
- import { M as ae, n as oe } from "./vega-loader.browser-D95WfUcj.js";
16
- import { t as se } from "./react-vega-5AcMW8gG.js";
17
- import { a as ce, n as _ } from "./loader-D2W4oM-3.js";
14
+ import { a as ne, i as re, n as ie, t as g } from "./formats-Cl_67ghI.js";
15
+ import { M as ae, n as oe } from "./vega-loader.browser-DNST6uVf.js";
16
+ import { t as se } from "./react-vega-ewj7q_U5.js";
17
+ import { a as ce, n as _ } from "./loader-DEZSzvma.js";
18
18
  import { t as le } from "./useDeepCompareMemoize-D_HNdyvI.js";
19
19
  import { t as ue } from "./semaphore-89jsoHtS.js";
20
20
  import { t as de } from "./use-vega-container-remeasure-4DwJbPWu.js";
@@ -2,8 +2,8 @@ import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-ofJbxM4x.js";
3
3
  import { t as n } from "./compiler-runtime-Cj8ZWiNS.js";
4
4
  import { t as r } from "./jsx-runtime-DgDPJV9S.js";
5
- import { M as i } from "./vega-loader.browser-D95WfUcj.js";
6
- import { n as a } from "./react-vega-5AcMW8gG.js";
5
+ import { M as i } from "./vega-loader.browser-DNST6uVf.js";
6
+ import { n as a } from "./react-vega-ewj7q_U5.js";
7
7
  import { t as o } from "./use-vega-container-remeasure-4DwJbPWu.js";
8
8
  //#region src/components/charts/vega-embed-container.tsx
9
9
  var s = n(), c = /* @__PURE__ */ e(t(), 1), l = r();
@@ -237,8 +237,8 @@ function Ye(e) {
237
237
  if ("spec" in e) return Ye(e.spec);
238
238
  }
239
239
  }
240
- function Xe(t) {
241
- return !t || Object.keys(t).length === 0 ? "auto" : e.mapValues(t, (e) => e === "geometry" || e === "date" || e === "time" ? "string" : e === "datetime" ? "date" : e);
240
+ function Xe(t, { parseDates: n = !1 } = {}) {
241
+ return !t || Object.keys(t).length === 0 ? "auto" : e.mapValues(t, (e) => e === "geometry" ? "string" : e === "date" ? n ? "date" : "string" : e === "time" ? "string" : e === "datetime" ? "date" : e);
242
242
  }
243
243
  //#endregion
244
244
  //#region ../node_modules/.pnpm/d3-dsv@3.0.1/node_modules/d3-dsv/src/dsv.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.1-dev17",
3
+ "version": "0.25.1-dev18",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,286 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { fireEvent, render, waitFor } from "@testing-library/react";
4
+ import { createStore, Provider } from "jotai";
5
+ import { Tooltip } from "radix-ui";
6
+ import type { ComponentProps } from "react";
7
+ import { beforeAll, describe, expect, it, vi } from "vitest";
8
+ import { SetupMocks } from "@/__mocks__/common";
9
+ import { cellId } from "@/__tests__/branded";
10
+ import { LazyVegaEmbed } from "@/components/charts/lazy";
11
+ import { vegaLoader } from "@/plugins/impl/vega/loader";
12
+ import { ChartPanel, TablePanel, type TablePanelProps } from "../charts";
13
+ import { getChartTabName, tabsStorageAtom } from "../storage";
14
+ import { ChartType, NONE_VALUE } from "../types";
15
+
16
+ vi.mock("@/components/charts/lazy", () => ({
17
+ LazyVegaEmbed: vi.fn(() => null),
18
+ }));
19
+
20
+ beforeAll(() => {
21
+ SetupMocks.resizeObserver();
22
+ });
23
+
24
+ describe("ChartPanel", () => {
25
+ it.each([undefined, null, []] as const)(
26
+ "infers the full CSV through TablePanel without backend metadata (%s)",
27
+ async (fieldTypes) => {
28
+ vi.spyOn(vegaLoader, "load").mockResolvedValue(
29
+ "value,index\n,0\n2.5,1\n",
30
+ );
31
+ const store = createStore();
32
+ const id = cellId("csv-inference");
33
+ const tabName = getChartTabName(0, ChartType.BAR);
34
+ store.set(
35
+ tabsStorageAtom,
36
+ new Map([
37
+ [
38
+ id,
39
+ [
40
+ {
41
+ tabName,
42
+ chartType: ChartType.BAR,
43
+ config: {
44
+ general: {
45
+ xColumn: { field: "value", type: "number" },
46
+ yColumn: {
47
+ field: "index",
48
+ type: "integer",
49
+ aggregate: NONE_VALUE,
50
+ },
51
+ },
52
+ },
53
+ },
54
+ ],
55
+ ],
56
+ ]),
57
+ );
58
+ const sample = [{ value: null }];
59
+ const SampleTable = (_props: { data: typeof sample }) => null;
60
+ const props: TablePanelProps = {
61
+ cellId: id,
62
+ data: sample,
63
+ dataTable: <SampleTable data={sample} />,
64
+ totalRows: 2,
65
+ columns: 1,
66
+ displayHeader: true,
67
+ fieldTypes: fieldTypes == null ? fieldTypes : [...fieldTypes],
68
+ rowHeaders: [["index", ["integer", "int64"]]],
69
+ getDataUrl: vi
70
+ .fn()
71
+ .mockResolvedValue({ data_url: "chart.csv", format: "csv" }),
72
+ };
73
+ const { getByRole } = render(
74
+ <Provider store={store}>
75
+ <Tooltip.Provider>
76
+ <TablePanel {...props} />
77
+ </Tooltip.Provider>
78
+ </Provider>,
79
+ );
80
+ fireEvent.click(getByRole("tab", { name: tabName }));
81
+ await waitFor(() => {
82
+ expect(vi.mocked(LazyVegaEmbed).mock.lastCall?.[0].spec).toEqual(
83
+ expect.objectContaining({
84
+ data: {
85
+ values: [
86
+ { value: null, index: 0 },
87
+ { value: 2.5, index: 1 },
88
+ ],
89
+ },
90
+ }),
91
+ );
92
+ });
93
+ },
94
+ );
95
+
96
+ it("reloads CSV only when column types change, not their array identity", async () => {
97
+ vi.spyOn(vegaLoader, "load").mockResolvedValue("value\n001\n");
98
+ const getDataUrl = vi.fn().mockResolvedValue({
99
+ data_url: "chart.csv",
100
+ format: "csv",
101
+ });
102
+ const props: ComponentProps<typeof ChartPanel> = {
103
+ tableData: [{ value: "001" }],
104
+ chartConfig: {
105
+ general: {
106
+ xColumn: { field: "value", type: "string" },
107
+ yColumn: { field: "value", type: "integer", aggregate: NONE_VALUE },
108
+ },
109
+ },
110
+ chartType: ChartType.BAR,
111
+ saveChart: vi.fn(),
112
+ saveChartType: vi.fn(),
113
+ getDataUrl,
114
+ isLargeDataset: false,
115
+ };
116
+ const panel = (
117
+ fieldTypes: ComponentProps<typeof ChartPanel>["fieldTypes"],
118
+ ) => (
119
+ <Tooltip.Provider>
120
+ <ChartPanel {...props} fieldTypes={fieldTypes} />
121
+ </Tooltip.Provider>
122
+ );
123
+ const expectValues = async (value: string | number) => {
124
+ await waitFor(() => {
125
+ expect(vi.mocked(LazyVegaEmbed).mock.lastCall?.[0].spec).toEqual(
126
+ expect.objectContaining({ data: { values: [{ value }] } }),
127
+ );
128
+ });
129
+ };
130
+
131
+ const { rerender } = render(panel([["value", ["string", "object"]]]));
132
+ await expectValues("001");
133
+ expect(getDataUrl).toHaveBeenCalledTimes(1);
134
+
135
+ rerender(panel([["value", ["string", "object"]]]));
136
+ await expectValues("001");
137
+ expect(getDataUrl).toHaveBeenCalledTimes(1);
138
+
139
+ rerender(panel([["value", ["integer", "int64"]]]));
140
+ await expectValues(1);
141
+ expect(getDataUrl).toHaveBeenCalledTimes(2);
142
+ });
143
+
144
+ it("uses column types to parse numeric CSV values without coercing text", async () => {
145
+ vi.spyOn(vegaLoader, "load").mockResolvedValue(
146
+ "a.b,n,label,day,timestamp,active,duration\ninf,1,inf,2024-01-01,2024-01-01T12:00:00Z,True,1 days\n-inf,2,001,2024-01-02,2024-01-02T12:00:00Z,False,2 days\n2.5,3,2024-01-03,2024-01-03,2024-01-03T12:00:00Z,True,3 days\n,4,,,,,\n",
147
+ );
148
+
149
+ render(
150
+ <Tooltip.Provider>
151
+ <ChartPanel
152
+ tableData={[{ "a.b": 1, n: 1 }]}
153
+ chartConfig={{
154
+ general: {
155
+ xColumn: { field: "a.b", type: "number" },
156
+ yColumn: { field: "n", type: "integer", aggregate: NONE_VALUE },
157
+ },
158
+ }}
159
+ chartType={ChartType.BAR}
160
+ saveChart={vi.fn()}
161
+ saveChartType={vi.fn()}
162
+ getDataUrl={vi.fn().mockResolvedValue({
163
+ data_url: "chart.csv",
164
+ format: "csv",
165
+ })}
166
+ fieldTypes={[
167
+ ["a.b", ["number", "float64"]],
168
+ ["n", ["integer", "int64"]],
169
+ ["label", ["string", "object"]],
170
+ ["day", ["date", "date"]],
171
+ ["timestamp", ["datetime", "datetime64[ns]"]],
172
+ ["active", ["boolean", "bool"]],
173
+ ["duration", ["unknown", "timedelta64[ns]"]],
174
+ ]}
175
+ isLargeDataset={false}
176
+ />
177
+ </Tooltip.Provider>,
178
+ );
179
+
180
+ await waitFor(() => {
181
+ expect(vi.mocked(LazyVegaEmbed).mock.lastCall?.[0].spec).toEqual(
182
+ expect.objectContaining({
183
+ data: {
184
+ values: [
185
+ {
186
+ "a.b": Infinity,
187
+ n: 1,
188
+ label: "inf",
189
+ day: new Date("2024-01-01"),
190
+ timestamp: new Date("2024-01-01T12:00:00Z"),
191
+ active: true,
192
+ duration: "1 days",
193
+ },
194
+ {
195
+ "a.b": -Infinity,
196
+ n: 2,
197
+ label: "001",
198
+ day: new Date("2024-01-02"),
199
+ timestamp: new Date("2024-01-02T12:00:00Z"),
200
+ active: false,
201
+ duration: "2 days",
202
+ },
203
+ {
204
+ "a.b": 2.5,
205
+ n: 3,
206
+ label: "2024-01-03",
207
+ day: new Date("2024-01-03"),
208
+ timestamp: new Date("2024-01-03T12:00:00Z"),
209
+ active: true,
210
+ duration: "3 days",
211
+ },
212
+ {
213
+ "a.b": null,
214
+ n: 4,
215
+ label: null,
216
+ day: "",
217
+ timestamp: "",
218
+ active: null,
219
+ duration: "",
220
+ },
221
+ ],
222
+ },
223
+ }),
224
+ );
225
+ });
226
+ });
227
+
228
+ it.each([true, false])(
229
+ "keeps dotted CSV columns aligned with the chart encodings (schema: %s)",
230
+ async (hasSchema) => {
231
+ vi.spyOn(vegaLoader, "load").mockResolvedValue("a.b,n\n1,1\n2,2\n3,3\n");
232
+
233
+ render(
234
+ <Tooltip.Provider>
235
+ <ChartPanel
236
+ tableData={[{ "a.b": 1, n: 1 }]}
237
+ chartConfig={{
238
+ general: {
239
+ xColumn: { field: "a.b", type: "number" },
240
+ yColumn: {
241
+ field: "n",
242
+ type: "number",
243
+ aggregate: NONE_VALUE,
244
+ },
245
+ },
246
+ }}
247
+ chartType={ChartType.BAR}
248
+ saveChart={vi.fn()}
249
+ saveChartType={vi.fn()}
250
+ getDataUrl={vi.fn().mockResolvedValue({
251
+ data_url: "chart.csv",
252
+ format: "csv",
253
+ })}
254
+ fieldTypes={
255
+ hasSchema
256
+ ? [
257
+ ["a.b", ["number", "float64"]],
258
+ ["n", ["integer", "int64"]],
259
+ ]
260
+ : undefined
261
+ }
262
+ isLargeDataset={false}
263
+ />
264
+ </Tooltip.Provider>,
265
+ );
266
+
267
+ await waitFor(() => {
268
+ expect(vi.mocked(LazyVegaEmbed).mock.lastCall?.[0].spec).toEqual(
269
+ expect.objectContaining({
270
+ data: {
271
+ values: [
272
+ { "a.b": 1, n: 1 },
273
+ { "a.b": 2, n: 2 },
274
+ { "a.b": 3, n: 3 },
275
+ ],
276
+ },
277
+ encoding: expect.objectContaining({
278
+ x: expect.objectContaining({ field: "a\\.b" }),
279
+ y: expect.objectContaining({ field: "n" }),
280
+ }),
281
+ }),
282
+ );
283
+ });
284
+ },
285
+ );
286
+ });
@@ -23,9 +23,11 @@ import { Form } from "@/components/ui/form";
23
23
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
24
24
  import type { CellId } from "@/core/cells/ids";
25
25
  import { useAsyncData } from "@/hooks/useAsyncData";
26
+ import { useDeepCompareMemoize } from "@/hooks/useDeepCompareMemoize";
26
27
  import { useDebouncedCallback } from "@/hooks/useDebounce";
27
28
  import type { GetDataUrl } from "@/plugins/impl/DataTablePlugin";
28
29
  import { vegaLoadData } from "@/plugins/impl/vega/loader";
30
+ import { getVegaFieldTypes } from "@/plugins/impl/vega/utils";
29
31
  import { useTheme } from "@/theme/useTheme";
30
32
  import { uniqueBy } from "@/utils/arrays";
31
33
  import { inferFieldTypes } from "../columns";
@@ -284,6 +286,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
284
286
  saveChart={saveChart}
285
287
  saveChartType={saveChartType}
286
288
  getDataUrl={getDataUrl}
289
+ hasSchema={Boolean(fieldTypes?.length)}
287
290
  fieldTypes={mergeIndexFields(
288
291
  fieldTypes ?? inferFieldTypes(dataTable.props.data),
289
292
  rowHeaders,
@@ -307,6 +310,7 @@ export const ChartPanel: React.FC<{
307
310
  saveChartType: (chartType: ChartType) => void;
308
311
  getDataUrl?: GetDataUrl;
309
312
  fieldTypes?: FieldTypesWithExternalType | null;
313
+ hasSchema?: boolean;
310
314
  isLargeDataset: boolean;
311
315
  }> = ({
312
316
  tableData,
@@ -316,6 +320,7 @@ export const ChartPanel: React.FC<{
316
320
  saveChartType,
317
321
  getDataUrl,
318
322
  fieldTypes,
323
+ hasSchema = Boolean(fieldTypes?.length),
319
324
  isLargeDataset,
320
325
  }) => {
321
326
  const { theme } = useTheme();
@@ -331,6 +336,8 @@ export const ChartPanel: React.FC<{
331
336
  const [renderLargeCharts, setRenderLargeCharts] = useState(!isLargeDataset);
332
337
 
333
338
  const { ref: chartContainerRef } = useResizeObserver();
339
+ // Sample-inferred types are useful for controls, but not full CSV parsing.
340
+ const csvFieldTypes = useDeepCompareMemoize(hasSchema ? fieldTypes : null);
334
341
 
335
342
  const { data, isPending, error } = useAsyncData(async () => {
336
343
  if (!getDataUrl || tableData.length === 0 || !renderLargeCharts) {
@@ -342,20 +349,26 @@ export const ChartPanel: React.FC<{
342
349
  return response.data_url;
343
350
  }
344
351
 
345
- const chartData = await vegaLoadData(
346
- response.data_url,
347
- response.format === "arrow"
348
- ? { type: "arrow" }
349
- : response.format === "json"
350
- ? { type: "json" }
351
- : { type: "csv", parse: "auto" },
352
- {
353
- replacePeriod: true,
354
- },
355
- );
356
- return chartData;
352
+ let format: Parameters<typeof vegaLoadData>[1];
353
+ if (response.format === "arrow") {
354
+ format = { type: "arrow" };
355
+ } else if (response.format === "json") {
356
+ format = { type: "json" };
357
+ } else {
358
+ format = {
359
+ type: "csv",
360
+ parse: getVegaFieldTypes(
361
+ csvFieldTypes &&
362
+ Object.fromEntries(
363
+ csvFieldTypes.map(([name, [type]]) => [name, type]),
364
+ ),
365
+ { parseDates: true },
366
+ ),
367
+ };
368
+ }
369
+ return vegaLoadData(response.data_url, format);
357
370
  // Re-run when the data table changes
358
- }, [tableData, renderLargeCharts]);
371
+ }, [tableData, renderLargeCharts, csvFieldTypes]);
359
372
 
360
373
  const formValues = form.watch();
361
374