import { E as G, _ as X, u as Y, aK as I, aL as Z, m as L, aM as q, aN as ee, aO as M, aP as H, aQ as te, aR as ne, n as _, aS as W, w as $, aT as se, aU as re, aV as ae, I as oe, a3 as ie, as as ce, aW as le, j as x, aX as ue, aY as fe, aZ as de } from "./index-CsBCemCF.js";
import * as v from "react";
import { useMemo as J, useCallback as A, useRef as D, useEffect as R, memo as me, useState as P, useLayoutEffect as he } from "react";
import { w as pe, E as ge } from "./withFullScreenWrapper-B2V0S41O.js";
import { a as U, S as k, T as Se } from "./Toolbar-BPTl0_g8.js";
import { R as ye } from "./ReadOnlyGrid-BgtwS-Z3.js";
import { u as we } from "./FormClearHelper-7XVCWEDh.js";
var K = /* @__PURE__ */ v.forwardRef(function(n, t) {
  var r = {
    fill: "currentColor",
    xmlns: "http://www.w3.org/2000/svg"
  };
  return /* @__PURE__ */ v.createElement(G, X({
    iconAttrs: r,
    iconVerticalAlign: "middle",
    iconViewBox: "0 0 24 24"
  }, n, {
    ref: t
  }), /* @__PURE__ */ v.createElement("path", {
    fill: "none",
    d: "M0 0h24v24H0V0z"
  }), /* @__PURE__ */ v.createElement("path", {
    d: "M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 10h2v7H7zm4-3h2v10h-2zm4 6h2v4h-2z"
  }));
});
K.displayName = "InsertChart";
var Q = /* @__PURE__ */ v.forwardRef(function(n, t) {
  var r = {
    fill: "currentColor",
    xmlns: "http://www.w3.org/2000/svg"
  };
  return /* @__PURE__ */ v.createElement(G, X({
    iconAttrs: r,
    iconVerticalAlign: "middle",
    iconViewBox: "0 0 24 24"
  }, n, {
    ref: t
  }), /* @__PURE__ */ v.createElement("path", {
    fill: "none",
    d: "M0 0h24v24H0V0z"
  }), /* @__PURE__ */ v.createElement("path", {
    d: "M20 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 2v3H5V5h15zm-5 14h-5v-9h5v9zM5 10h3v9H5v-9zm12 9v-9h3v9h-3z"
  }));
});
Q.displayName = "TableChart";
const be = 20;
function Ce(n) {
  "params" in n && "encoding" in n && n.params.forEach((t) => {
    "select" in t && (["interval", "point"].includes(t.select) && (t.select = {
      type: t.select
    }), "type" in t.select && t.select.type === "point" && !("encodings" in t.select) && L(t.select.encodings) && (t.select.encodings = Object.keys(n.encoding)));
  });
}
const Ee = (n, t, r, s, l, i, c, h) => {
  const e = JSON.parse(n);
  if (s === "streamlit" ? e.config = I(e.config, i) : e.usermeta?.embedOptions?.theme === "streamlit" ? (e.config = I(e.config, i), e.usermeta.embedOptions.theme = void 0) : e.config = Z(e.config, i), e.title && (typeof e.title == "string" && (e.title = {
    text: e.title
  }), e.title.limit = // Preserve existing limit if it exists,
  e.title.limit ?? // Otherwise, calculate the width - 40px to give some padding, especially
  // for the ... menu button. If the width is less than 40px, we set it to
  // 0 to avoid negative values.
  Math.max(c - 40, 0)), r && (e.height = h), t && (e.width = c, "vconcat" in e && e.vconcat.forEach((f) => {
    f.width = c;
  })), e.padding || (e.padding = {}), L(e.padding.bottom) && (e.padding.bottom = be), e.datasets)
    throw new Error("Datasets should not be passed as part of the spec");
  return l.length > 0 && Ce(e), e;
}, Ve = (n, t, r, s, l) => {
  const i = Y(), {
    id: c,
    formId: h,
    spec: e,
    data: f,
    datasets: a,
    vegaLiteTheme: u,
    selectionMode: o
  } = n, p = J(() => o, [JSON.stringify(o)]), y = J(() => Ee(e, s, l, u, p, i, t, r), [e, s, l, u, p, i, t, r]);
  return {
    id: c,
    formId: h,
    vegaLiteTheme: u,
    spec: y,
    selectionMode: p,
    data: f,
    datasets: a,
    useContainerWidth: s
  };
}, ve = {
  DATAFRAME_INDEX: "(index)"
};
function Ne(n) {
  return !n || n.dimensions.numDataRows === 0 ? null : z(n);
}
function Te(n) {
  const t = F(n);
  if (L(t))
    return null;
  const r = {};
  for (const [s, l] of Object.entries(t))
    r[s] = z(l);
  return r;
}
function F(n) {
  if (n?.length === 0)
    return null;
  const t = {};
  return n.forEach((r) => {
    if (!r)
      return;
    const s = r.hasName ? r.name : null;
    t[s] = r.data;
  }), t;
}
function z(n, t = 0) {
  if (n.dimensions.numDataRows === 0)
    return [];
  const r = [], {
    numDataRows: s,
    numDataColumns: l,
    numIndexColumns: i
  } = n.dimensions, c = n.columnTypes[0] ?? void 0, h = c && c.type === q.INDEX && (ee(c) || M(c) || H(c));
  for (let e = t; e < s; e++) {
    const f = {};
    if (h) {
      const {
        content: a
      } = n.getCell(e, 0);
      f[ve.DATAFRAME_INDEX] = typeof a == "bigint" ? Number(a) : a;
    }
    for (let a = 0; a < l; a++) {
      const u = a + i, {
        content: o,
        contentType: p
      } = n.getCell(e, u);
      if ((o instanceof Date || typeof o == "number" && Number.isFinite(o)) && (M(p) || H(p)) && // Only convert dates without timezone information
      // to utc timezone
      !te(p)) {
        const y = new Date(o).getTimezoneOffset() * 60 * 1e3;
        f[n.columnNames[0][u]] = o.valueOf() + y;
      } else
        f[n.columnNames[0][u]] = typeof o == "bigint" ? Number(o) : o;
    }
    r.push(f);
  }
  return r;
}
const xe = 150, Oe = $.getLogger("useVegaLiteSelections"), Ae = (n, t, r) => {
  const {
    id: s,
    formId: l,
    selectionMode: i
  } = n, c = A((e) => {
    i.forEach((a) => {
      e.addSignalListener(a, ne(xe, (u, o) => {
        const p = e.getState({
          // There are also `signals` data, but I believe its
          // not relevant for restoring the selection state.
          data: (g, S) => i.some((C) => `${C}_store` === g),
          // Don't include subcontext data since it will lead to exceptions
          // when loading the state.
          recurse: !1
        });
        _(p) && t.setElementState(s, "viewState", p);
        let y = o;
        "vlPoint" in o && "or" in o.vlPoint && (y = o.vlPoint.or);
        const O = {
          id: s,
          formId: l
        }, m = JSON.parse(t.getStringValue(O) || "{}"), d = {
          selection: {
            ...m?.selection || {},
            [u]: y || {}
          }
        };
        W(m, d) || t.setStringValue(O, JSON.stringify(d), {
          fromUi: !0
        }, r);
      }));
    });
    const f = t.getElementState(s, "viewState");
    if (_(f))
      try {
        return e.setState(f);
      } catch (a) {
        Oe.warn("Failed to restore view state", a);
      }
    return e;
  }, [s, i, t, l, r]), h = A(() => {
    const e = {
      selection: {}
    };
    i.forEach((o) => {
      e.selection[o] = {};
    });
    const f = {
      id: s,
      formId: l
    }, a = t.getStringValue(f), u = a ? JSON.parse(a) : (
      // If there wasn't any selection yet, the selection state
      // is assumed to be empty.
      e
    );
    W(u, e) || t.setStringValue(f, JSON.stringify(e), {
      fromUi: !0
    }, r);
  }, [s, l, r, i, t]);
  return {
    maybeConfigureSelections: c,
    onFormCleared: h
  };
}, B = "source", De = $.getLogger("useVegaEmbed");
function ze(n, t, r) {
  const s = D(null), l = D(null), i = D(B), c = D(null), h = D([]), {
    maybeConfigureSelections: e,
    onFormCleared: f
  } = Ae(n, t, r);
  we({
    widgetMgr: t,
    element: n,
    onFormCleared: f
  });
  const {
    data: a,
    datasets: u
  } = n;
  R(() => {
    s.current === null && (c.current = a, h.current = u);
  }, [a, u]);
  const o = A(() => {
    l.current && l.current(), l.current = null, s.current = null;
  }, []), p = A(async (m, d) => {
    if (m.current === null)
      throw new Error("Element missing.");
    o();
    const g = {
      // Adds interpreter support for Vega expressions that is compliant with CSP
      ast: !0,
      expr: re,
      // Disable default styles so that vega doesn't inject <style> tags in the
      // DOM. We set these styles manually for finer control over them and to
      // avoid inlining styles.
      tooltip: {
        disableDefaultStyle: !0
      },
      defaultStyle: !1,
      forceActionsMenu: !0
    }, {
      vgSpec: S,
      view: C,
      finalize: N
    } = await se(m.current, d, g);
    s.current = e(C), l.current = N;
    const w = Te(h.current), E = w ? Object.keys(w) : [];
    if (E.length === 1) {
      const [b] = E;
      i.current = b;
    } else E.length === 0 && S.data && (i.current = B);
    const V = Ne(c.current);
    if (V && s.current.insert(i.current, V), w)
      for (const [b, T] of Object.entries(w))
        s.current.insert(b, T);
    return await s.current.runAsync(), await s.current.resize().runAsync(), s.current;
  }, [o, e]), y = A((m, d, g, S) => {
    if (!S || S.dimensions.numDataRows === 0) {
      try {
        m.remove(d, ae);
      } finally {
      }
      return;
    }
    if (!g || g.dimensions.numDataRows === 0) {
      m.insert(d, z(S));
      return;
    }
    S.hash !== g.hash && (m.data(d, z(S)), De.info(`Had to clear the ${d} dataset before inserting data through Vega view.`));
  }, []), O = A(async (m, d) => {
    if (s.current === null)
      return null;
    const g = c.current, S = h.current;
    (g || m) && y(s.current, i.current, g, m);
    const C = F(S) ?? {}, N = F(d) ?? {};
    for (const [w, E] of Object.entries(N)) {
      const V = w || i.current, b = C[V];
      y(s.current, V, b, E);
    }
    for (const w of Object.keys(C))
      !Object.hasOwn(N, w) && w !== i.current && y(s.current, w, null, null);
    return await s.current?.resize().runAsync(), c.current = m, h.current = d, s.current;
  }, [y]);
  return {
    createView: p,
    updateView: O,
    finalizeView: o
  };
}
function Re(n) {
  try {
    const t = typeof n == "string" ? JSON.parse(n) : n;
    return !!(t.facet || // TODO (lawilby): do some tests for row/column
    // shorthand facet charts to confirm they work with
    // sizing in the same way.
    t.encoding?.row || t.encoding?.column || t.encoding?.facet);
  } catch {
    return !1;
  }
}
const Fe = ({
  disableFullscreenMode: n,
  element: t,
  fragmentId: r,
  widgetMgr: s,
  widthConfig: l,
  heightConfig: i
}) => {
  const [c, h] = P(!1), [e, f] = P(!1), {
    expanded: a,
    height: u,
    width: o,
    expand: p,
    collapse: y
  } = oe(ge), {
    width: O,
    height: m,
    elementRef: d
  } = ie(
    // We need to update whenever the showData state changes because
    // the underlying element ref that needs to be observed is updated.
    [c],
    // Use 0 as fallback instead of -1 because Vega-Lite cannot handle negative dimensions
    0
  ), g = ce(l) || t.useContainerWidth, S = le(i), C = Re(t.spec), N = Ve(
    t,
    // Facet charts enter a loop when using the width/height from the StyledVegaLiteChartContainer.
    C ? o ?? 0 : O,
    (a ? u : m) ?? 0,
    a ? !0 : g,
    a ? !0 : S
  ), {
    createView: w,
    updateView: E,
    finalizeView: V
  } = ze(N, s, r), {
    data: b,
    datasets: T,
    spec: j
  } = N;
  return he(() => (d.current !== null && w(d, j), V), [w, V, j, o, u, c, d]), R(() => {
    E(b, T);
  }, [b, T, E]), R(() => {
    b || T?.[0]?.data ? f(!0) : f(!1);
  }, [b, T]), c ? /* @__PURE__ */ x.jsx(ye, { data: b ?? T[0]?.data, height: u ?? m ?? void 0, customToolbarActions: [/* @__PURE__ */ x.jsx(U, { label: "Show chart", icon: K, onClick: () => {
    h(!1);
  } }, "show-chart")] }) : /* @__PURE__ */ x.jsxs(k, { height: S ? a ? u : "100%" : u, useContainerWidth: a ? !0 : g, children: [
    /* @__PURE__ */ x.jsx(Se, { target: k, isFullScreen: a, onExpand: p, onCollapse: y, disableFullscreenMode: n, children: e && /* @__PURE__ */ x.jsx(U, { label: "Show data", icon: Q, onClick: () => {
      h(!0);
    } }) }),
    /* @__PURE__ */ x.jsx(ue, { styles: fe }),
    /* @__PURE__ */ x.jsx(de, { "data-testid": "stVegaLiteChart", className: "stVegaLiteChart", useContainerWidth: g, useContainerHeight: S, ref: d })
  ] });
}, Le = pe(Fe), Je = me(Le);
export {
  fe as StyledVegaLiteChartTooltips,
  I as applyStreamlitTheme,
  Je as default
};
//# sourceMappingURL=index-BqjVvYwm.js.map
