@marimo-team/islands 0.25.1-dev16 → 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 (41) hide show
  1. package/dist/{ConnectedDataExplorerComponent-KVhjDMSe.js → ConnectedDataExplorerComponent-CwMXfDQR.js} +3 -3
  2. package/dist/{ErrorBoundary-Dw6ePT6V.js → ErrorBoundary-BCANhTrt.js} +1 -1
  3. package/dist/{cells-B5-y5EY3.js → cells-Cksce8br.js} +2 -2
  4. package/dist/{chat-ui-HJZsTl7o.js → chat-ui-4lXygZ8L.js} +4 -4
  5. package/dist/{code-visibility-nEXuRCpZ.js → code-visibility-DIUkT8x-.js} +2 -2
  6. package/dist/{common-CKVUP-3T.js → common-BfERj74g.js} +13 -13
  7. package/dist/{data-grid-overlay-editor-Dl4u0MM_.js → data-grid-overlay-editor-ByNOrM5s.js} +1 -1
  8. package/dist/{error-entries-Bkbpx0T0.js → error-entries-CvCFdpY2.js} +1 -1
  9. package/dist/{feedback-button-7UQpHERA.js → feedback-button-C6WatdDY.js} +4 -4
  10. package/dist/{formats-C8rLgZT9.js → formats-Cl_67ghI.js} +1 -1
  11. package/dist/{glide-data-editor-Cau1B1SH.js → glide-data-editor-BaQLny21.js} +3 -3
  12. package/dist/{globals-BQb7ei48.js → globals-DDOIQV3b.js} +1 -1
  13. package/dist/{html-to-image-BAgJOlSW.js → html-to-image-jTwYSWRc.js} +1 -1
  14. package/dist/{loader-D2W4oM-3.js → loader-DEZSzvma.js} +253 -248
  15. package/dist/main.js +53 -51
  16. package/dist/{number-overlay-editor-CmsthUKy.js → number-overlay-editor-pI5HWUmx.js} +1 -1
  17. package/dist/{process-output-zDX4jbhd.js → process-output-DevJrL3v.js} +2 -2
  18. package/dist/{react-vega-5AcMW8gG.js → react-vega-ewj7q_U5.js} +1 -1
  19. package/dist/{reveal-component-IMWiBhGb.js → reveal-component-BeyJErFp.js} +3 -3
  20. package/dist/{vega-component-CNf5gcrm.js → vega-component-tFOzgarw.js} +4 -4
  21. package/dist/{vega-embed-container-CbnTccZi.js → vega-embed-container-sSR5hAsy.js} +2 -2
  22. package/dist/{vega-loader.browser-D95WfUcj.js → vega-loader.browser-DNST6uVf.js} +2 -2
  23. package/package.json +1 -1
  24. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +286 -0
  25. package/src/components/data-table/charts/charts.tsx +26 -13
  26. package/src/components/editor/chrome/components/contribute-snippet-button.tsx +6 -1
  27. package/src/components/editor/notebook-cell.tsx +2 -2
  28. package/src/components/editor/output/MarimoTracebackOutput.tsx +1 -1
  29. package/src/components/editor/output/VideoOutput.tsx +1 -1
  30. package/src/components/editor/output/ansi-reduce.ts +8 -4
  31. package/src/components/editor/output/console/text-rendering.tsx +3 -1
  32. package/src/components/home/components.tsx +1 -0
  33. package/src/components/pages/run-page.tsx +1 -0
  34. package/src/components/static-html/share-modal.tsx +2 -1
  35. package/src/components/static-html/static-banner.tsx +2 -1
  36. package/src/components/ui/links.tsx +6 -1
  37. package/src/plugins/impl/vega/__tests__/utils.test.ts +16 -1
  38. package/src/plugins/impl/vega/__tests__/vega.test.ts +37 -0
  39. package/src/plugins/impl/vega/loader.ts +23 -1
  40. package/src/plugins/impl/vega/utils.ts +5 -4
  41. package/src/plugins/layout/RoutesPlugin.tsx +4 -6
package/dist/main.js CHANGED
@@ -3,20 +3,20 @@ import { _ as a, c as o, f as s, g as c, h as l, i as u, l as d, m as f, n as p,
3
3
  import { t as y } from "./react-ofJbxM4x.js";
4
4
  import { t as b } from "./compiler-runtime-Cj8ZWiNS.js";
5
5
  import { i as x, n as S, r as C, t as w } from "./copy-icon-CLdENY__.js";
6
- 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, X as P, Z as F, _ as I, a as L, b as R, g as ee, i as z, j as te, k as B, n as ne, o as re, q as ie, v as ae, y as oe } from "./html-to-image-BAgJOlSW.js";
6
+ 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, X as P, Z as F, _ as I, a as L, b as R, g as ee, i as z, j as te, k as B, n as ne, o as re, q as ie, v as ae, y as oe } from "./html-to-image-jTwYSWRc.js";
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
- 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-B5-y5EY3.js";
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-CKVUP-3T.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";
14
14
  import { B as Pi, C as Fi, J as Ii, Mt as Li, Nt as Ri, S as zi, Vt as Bi, W as Vi, _ as Hi, a as Ui, at as Wi, c as Gi, dt as Ki, f as qi, fn as Ji, g as Yi, h as Xi, i as Zi, it as Qi, m as $i, n as ea, p as ta, pn as na, q as ra, r as ia, s as aa, t as oa, v as sa, vt as ca, x as la, z as ua } from "./dropdown-menu-CZgjYSAh.js";
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
- 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-zDX4jbhd.js";
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-Dw6ePT6V.js";
19
- import { n as Wa, t as Ga } from "./globals-BQb7ei48.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-nEXuRCpZ.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
@@ -9992,7 +9992,7 @@ var PS = (e) => {
9992
9992
  output: t
9993
9993
  };
9994
9994
  } };
9995
- } }, BS = J.lazy(() => import("./chat-ui-HJZsTl7o.js").then((e) => ({ default: e.Chatbot }))), VS = G(W({
9995
+ } }, BS = J.lazy(() => import("./chat-ui-4lXygZ8L.js").then((e) => ({ default: e.Chatbot }))), VS = G(W({
9996
9996
  id: U(),
9997
9997
  role: Io([
9998
9998
  "system",
@@ -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-Cau1B1SH.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),
@@ -23133,7 +23140,7 @@ var FM = (/* @__PURE__ */ i(((e) => {
23133
23140
  });
23134
23141
  }
23135
23142
  }, RM = (e) => {
23136
- let t = (0, X.c)(14), { routes: n, children: r } = e, i = J.Children.count(r);
23143
+ let t = (0, X.c)(11), { routes: n, children: r } = e, i = J.Children.count(r);
23137
23144
  if (i !== n.length) throw Error(`Expected ${n.length} children, but got ${i}`);
23138
23145
  let a;
23139
23146
  t[0] === n ? a = t[1] : (a = new IM(n), t[0] = n, t[1] = a);
@@ -23155,14 +23162,9 @@ var FM = (/* @__PURE__ */ i(((e) => {
23155
23162
  return window.addEventListener("hashchange", e), window.addEventListener("popstate", e), () => {
23156
23163
  window.removeEventListener("hashchange", e), window.removeEventListener("popstate", e);
23157
23164
  };
23158
- }, p = [d], t[6] = d, t[7] = f, t[8] = p), (0, J.useEffect)(f, p), !c) {
23159
- let e;
23160
- return t[9] === Symbol.for("react.memo_cache_sentinel") ? (e = /* @__PURE__ */ (0, Y.jsx)(Y.Fragment, {}), t[9] = e) : e = t[9], e;
23161
- }
23165
+ }, p = [d], t[6] = d, t[7] = f, t[8] = p), (0, J.useEffect)(f, p), !c) return null;
23162
23166
  let m = n.indexOf(c), h;
23163
- t[10] === r ? h = t[11] : (h = J.Children.toArray(r), t[10] = r, t[11] = h);
23164
- let g = h[m], _;
23165
- return t[12] === g ? _ = t[13] : (_ = /* @__PURE__ */ (0, Y.jsx)(Y.Fragment, { children: g }), t[12] = g, t[13] = _), _;
23167
+ return t[9] === r ? h = t[10] : (h = J.Children.toArray(r), t[9] = r, t[10] = h), h[m];
23166
23168
  }, zM = class {
23167
23169
  tagName = "marimo-stat";
23168
23170
  validator = W({
@@ -29932,7 +29934,7 @@ function bR(e) {
29932
29934
  }
29933
29935
  //#endregion
29934
29936
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
29935
- var xR = J.lazy(() => import("./reveal-component-IMWiBhGb.js")), SR = (e) => {
29937
+ var xR = J.lazy(() => import("./reveal-component-BeyJErFp.js")), SR = (e) => {
29936
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;
29937
29939
  t[0] !== i || t[1] !== n ? (d = vP(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
29938
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-Cau1B1SH.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,6 +1,6 @@
1
- import { O as e } from "./html-to-image-BAgJOlSW.js";
1
+ import { O as e } from "./html-to-image-jTwYSWRc.js";
2
2
  import { g as t } from "./tooltip-qB8NlSqV.js";
3
- import { b as n, y as r } from "./cells-B5-y5EY3.js";
3
+ import { b as n, y as r } from "./cells-Cksce8br.js";
4
4
  import { b as i } from "./select-C6plhmZr.js";
5
5
  import { n as a } from "./semaphore-89jsoHtS.js";
6
6
  var o = t("file", [["path", {
@@ -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";
@@ -3,15 +3,15 @@ import { c as t, g as n, h as r, m as i, t as a } from "./button-DdXAm8iz.js";
3
3
  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
- import { w as u } from "./cells-B5-y5EY3.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-CKVUP-3T.js";
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-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-nEXuRCpZ.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-dev16",
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
+ });