import { s as __toESM } from "./chunk-BNovOVIE.js";
import { _ as Logger, c as Objects, g as cn, h as Events } from "./button-Dj4BTre0.js";
import { t as require_react } from "./react-DA-nE2FX.js";
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
import { c as asRemoteURL, v as CircleQuestionMark } from "./toDate-CIpC_34u.js";
import "./react-dom-BWRJ_g_k.js";
import { t as require_jsx_runtime } from "./jsx-runtime-COBk7ree.js";
import "./zod-BWkcDORu.js";
import { n as ErrorBanner } from "./error-banner-CVkfBUT3.js";
import { t as Tooltip } from "./tooltip-DRaMBu06.js";
import { i as debounce_default } from "./constants-D0gkYoE2.js";
import { n as useTheme, w as useEvent_default } from "./useTheme-DykuNHR2.js";
import { s as uniq } from "./arrays-CldYf7p7.js";
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-Dsy9kkZu.js";
import { n as formats } from "./vega-loader.browser-3_z8GoFC.js";
import { a as getContainerWidth, n as vegaLoadData, s as tooltipHandler } from "./loader-Dr8Qem8p.js";
import { t as useAsyncData } from "./useAsyncData-C56Khv_R.js";
import { t as j } from "./react-vega-Dh6-UKKe.js";
import "./defaultLocale-BpsHxBd7.js";
import "./defaultLocale-DoeErsX2.js";
import { t as useDeepCompareMemoize } from "./useDeepCompareMemoize-Dt98v2ua.js";
import { t as Semaphore } from "./semaphore-CNDGTzkX.js";
var import_compiler_runtime = require_compiler_runtime(), import_react = /* @__PURE__ */ __toESM(require_react(), 1);
function fixRelativeUrl(e) {
  return e.data && "url" in e.data && (e.data.url = asRemoteURL(e.data.url).href), e;
}
const Mark = {
  arc: "arc",
  area: "area",
  bar: "bar",
  image: "image",
  line: "line",
  point: "point",
  rect: "rect",
  rule: "rule",
  text: "text",
  tick: "tick",
  trail: "trail",
  circle: "circle",
  square: "square",
  geoshape: "geoshape"
};
var NON_INTERACTIVE_MARKS = /* @__PURE__ */ new Set([
  "boxplot",
  "errorband",
  "errorbar"
]);
const Marks = {
  getMarkType(e) {
    let C = typeof e == "string" ? e : e.type;
    if (NON_INTERACTIVE_MARKS.has(C)) throw Error("Not supported");
    return C;
  },
  isInteractive(e) {
    let C = typeof e == "string" ? e : e.type;
    return !NON_INTERACTIVE_MARKS.has(C);
  },
  makeClickable(e) {
    let C = typeof e == "string" ? e : e.type;
    return C in Mark ? typeof e == "string" ? {
      type: e,
      cursor: "pointer",
      tooltip: true
    } : {
      ...e,
      type: C,
      cursor: "pointer",
      tooltip: true
    } : e;
  },
  getOpacity(e) {
    return typeof e == "string" ? null : "opacity" in e && typeof e.opacity == "number" ? e.opacity : null;
  }
}, ParamNames = {
  point(e) {
    return e == null ? "select_point" : `select_point_${e}`;
  },
  interval(e) {
    return e == null ? "select_interval" : `select_interval_${e}`;
  },
  legendSelection(e) {
    return `legend_selection_${e}`;
  },
  binColoring(e) {
    return e == null ? "bin_coloring" : `bin_coloring_${e}`;
  },
  HIGHLIGHT: "highlight",
  PAN_ZOOM: "pan_zoom",
  hasPoint(e) {
    return e.some((e2) => e2.startsWith("select_point"));
  },
  hasInterval(e) {
    return e.some((e2) => e2.startsWith("select_interval"));
  },
  hasLegend(e) {
    return e.some((e2) => e2.startsWith("legend_selection"));
  },
  hasPanZoom(e) {
    return e.some((e2) => e2.startsWith("pan_zoom"));
  },
  isBinColoring(e) {
    return e.startsWith("bin_coloring");
  }
}, Params = {
  highlight() {
    return {
      name: ParamNames.HIGHLIGHT,
      select: {
        type: "point",
        on: "mouseover"
      }
    };
  },
  interval(e, C) {
    return {
      name: ParamNames.interval(C),
      select: {
        type: "interval",
        encodings: getEncodingAxisForMark(e),
        mark: {
          fill: "#669EFF",
          fillOpacity: 0.07,
          stroke: "#669EFF",
          strokeOpacity: 0.4
        },
        on: "[mousedown[!event.metaKey], mouseup] > mousemove[!event.metaKey]",
        translate: "[mousedown[!event.metaKey], mouseup] > mousemove[!event.metaKey]"
      }
    };
  },
  point(e, C) {
    return {
      name: ParamNames.point(C),
      select: {
        type: "point",
        encodings: getEncodingAxisForMark(e),
        on: "click[!event.metaKey]"
      }
    };
  },
  binColoring(e) {
    return {
      name: ParamNames.binColoring(e),
      select: {
        type: "point",
        on: "click[!event.metaKey]"
      }
    };
  },
  legend(e) {
    return {
      name: ParamNames.legendSelection(e),
      select: {
        type: "point",
        fields: [e]
      },
      bind: "legend"
    };
  },
  panZoom() {
    return {
      name: ParamNames.PAN_ZOOM,
      bind: "scales",
      select: {
        type: "interval",
        on: "[mousedown[event.metaKey], window:mouseup] > window:mousemove!",
        translate: "[mousedown[event.metaKey], window:mouseup] > window:mousemove!",
        zoom: "wheel![event.metaKey]"
      }
    };
  }
};
function getEncodingAxisForMark(e) {
  switch (Marks.getMarkType(e.mark)) {
    case Mark.image:
    case Mark.trail:
      return;
    case Mark.area:
    case Mark.arc:
      return ["color"];
    case Mark.bar: {
      let C = getDirectionOfBar(e);
      return C === "horizontal" ? ["y"] : C === "vertical" ? ["x"] : void 0;
    }
    case Mark.circle:
    case Mark.geoshape:
    case Mark.line:
    case Mark.point:
    case Mark.rect:
    case Mark.rule:
    case Mark.square:
    case Mark.text:
    case Mark.tick:
      return ["x", "y"];
  }
}
function getSelectionParamNames(e) {
  return "params" in e && e.params && e.params.length > 0 ? uniq(e.params.filter((e2) => e2 == null ? false : "select" in e2 && e2.select !== void 0).map((e2) => e2.name)) : "layer" in e ? uniq(e.layer.flatMap(getSelectionParamNames)) : "vconcat" in e ? uniq(e.vconcat.flatMap(getSelectionParamNames)) : "hconcat" in e ? uniq(e.hconcat.flatMap(getSelectionParamNames)) : [];
}
function getDirectionOfBar(e) {
  var _a, _b;
  if (!e || !("mark" in e)) return;
  let C = (_a = e.encoding) == null ? void 0 : _a.x, w = (_b = e.encoding) == null ? void 0 : _b.y;
  if (C && "type" in C && C.type === "nominal") return "vertical";
  if (w && "type" in w && w.type === "nominal" || C && "aggregate" in C) return "horizontal";
  if (w && "aggregate" in w) return "vertical";
}
function getBinnedFields(e) {
  if (!e.encoding) return [];
  let C = [];
  for (let w of Object.values(e.encoding)) w && typeof w == "object" && "bin" in w && w.bin && "field" in w && typeof w.field == "string" && C.push(w.field);
  return C;
}
function findEncodedFields(e) {
  if (!e || !("encoding" in e)) return [];
  let { encoding: C } = e;
  return C ? Object.entries(C).flatMap((e2) => {
    let [C2, w] = e2;
    return !w || !ALLOWED_ENCODING_TYPES.has(C2) ? [] : "field" in w && typeof w.field == "string" ? [w.field] : "condition" in w && w.condition && typeof w.condition == "object" && "field" in w.condition && w.condition.field && typeof w.condition.field == "string" ? [w.condition.field] : [];
  }) : [];
}
var ALLOWED_ENCODING_TYPES = /* @__PURE__ */ new Set([
  "color",
  "fill",
  "fillOpacity",
  "opacity",
  "shape",
  "size"
]);
function makeEncodingInteractive(e, C, w, T) {
  let E = w.filter((e2) => ParamNames.isBinColoring(e2)), D = { and: (E.length > 0 ? E : w).map((e2) => ({ param: e2 })) };
  switch (e) {
    case "opacity": {
      let e2 = Marks.getOpacity(T) || 1;
      return {
        ...C,
        opacity: {
          condition: {
            test: D,
            value: e2
          },
          value: e2 / 5
        }
      };
    }
    default:
      return C;
  }
}
function getParamSignature(e) {
  if (!("select" in e) || !e.select) return JSON.stringify(e);
  let C = e.select;
  if (typeof C == "string") return JSON.stringify({
    type: C,
    bind: e.bind
  });
  let w = {
    type: C.type,
    encodings: "encodings" in C && C.encodings ? [...C.encodings].toSorted() : void 0,
    fields: "fields" in C && C.fields ? [...C.fields].toSorted() : void 0,
    bind: e.bind
  };
  return JSON.stringify(w);
}
function hoistParamsAndApplyOpacity(e) {
  let C = collectAllUnitSpecParams(e);
  if (C.length === 0) return e;
  let w = findCommonParams(C);
  return w.length === 0 ? e : {
    ...applyOpacityToNestedSpecs(removeSpecificParamsFromNestedSpecs(e, new Set(w.map((e2) => e2.name))), w.map((e2) => e2.name)),
    params: [...e.params || [], ...w]
  };
}
function collectAllUnitSpecParams(e) {
  let C = [];
  if ("vconcat" in e && Array.isArray(e.vconcat)) for (let w of e.vconcat) C.push(...collectAllUnitSpecParams(w));
  else if ("hconcat" in e && Array.isArray(e.hconcat)) for (let w of e.hconcat) C.push(...collectAllUnitSpecParams(w));
  else if ("layer" in e) return [];
  else "mark" in e && "params" in e && e.params && e.params.length > 0 && C.push({ params: e.params });
  return C;
}
function findCommonParams(e) {
  if (e.length === 0) return [];
  let C = /* @__PURE__ */ new Map(), w = e.length;
  for (let { params: w2 } of e) {
    let e2 = /* @__PURE__ */ new Set();
    for (let T2 of w2) {
      let w3 = getParamSignature(T2);
      e2.has(w3) || (e2.add(w3), C.has(w3) || C.set(w3, {
        count: 0,
        param: T2
      }), C.get(w3).count++);
    }
  }
  let T = [];
  for (let [, { count: e2, param: E }] of C) e2 === w && T.push(E);
  return T;
}
function removeSpecificParamsFromNestedSpecs(e, C) {
  if ("vconcat" in e && Array.isArray(e.vconcat)) return {
    ...e,
    vconcat: e.vconcat.map((e2) => removeSpecificParamsFromNestedSpecs(e2, C))
  };
  if ("hconcat" in e && Array.isArray(e.hconcat)) return {
    ...e,
    hconcat: e.hconcat.map((e2) => removeSpecificParamsFromNestedSpecs(e2, C))
  };
  if ("mark" in e && "params" in e && e.params) {
    let w = e.params, T = [];
    for (let e2 of w) {
      if (!e2 || typeof e2 != "object" || !("name" in e2)) {
        T.push(e2);
        continue;
      }
      C.has(e2.name) || T.push(e2);
    }
    if (T.length === 0) {
      let { params: C2, ...w2 } = e;
      return w2;
    }
    return {
      ...e,
      params: T
    };
  }
  return e;
}
function applyOpacityToNestedSpecs(e, C) {
  return "vconcat" in e && Array.isArray(e.vconcat) ? {
    ...e,
    vconcat: e.vconcat.map((e2) => applyOpacityToNestedSpecs(e2, C))
  } : "hconcat" in e && Array.isArray(e.hconcat) ? {
    ...e,
    hconcat: e.hconcat.map((e2) => applyOpacityToNestedSpecs(e2, C))
  } : "layer" in e ? e : "mark" in e && Marks.isInteractive(e.mark) ? {
    ...e,
    mark: Marks.makeClickable(e.mark),
    encoding: makeEncodingInteractive("opacity", e.encoding || {}, C, e.mark)
  } : e;
}
function makeSelectable(e, C) {
  var _a, _b;
  let { chartSelection: w = true, fieldSelection: T = true } = C;
  if (!w && !T) return e;
  ((_a = e.params) == null ? void 0 : _a.some((e2) => e2.bind === "legend")) && (T = false);
  let E = (_b = e.params) == null ? void 0 : _b.some((e2) => !e2.bind);
  E && (w = false);
  let D = "vconcat" in e || "hconcat" in e;
  if (E && D) return e;
  if ("vconcat" in e) {
    let C2 = e.vconcat.map((e2) => "mark" in e2 ? makeSelectable(e2, {
      chartSelection: w,
      fieldSelection: T
    }) : e2);
    return hoistParamsAndApplyOpacity({
      ...e,
      vconcat: C2
    });
  }
  if ("hconcat" in e) {
    let C2 = e.hconcat.map((e2) => "mark" in e2 ? makeSelectable(e2, {
      chartSelection: w,
      fieldSelection: T
    }) : e2);
    return hoistParamsAndApplyOpacity({
      ...e,
      hconcat: C2
    });
  }
  if ("layer" in e) {
    let C2 = e.params && e.params.length > 0, E2 = T !== false && !C2, D2 = [];
    if (E2) {
      let C3 = e.layer.flatMap((e2) => "mark" in e2 ? findEncodedFields(e2) : []);
      D2 = [...new Set(C3)], Array.isArray(T) && (D2 = D2.filter((e2) => T.includes(e2)));
    }
    let O2 = e.layer.map((e2, C3) => {
      if (!("mark" in e2)) return e2;
      let T2 = e2;
      if (C3 === 0 && D2.length > 0) {
        let e3 = D2.map((e4) => Params.legend(e4));
        T2 = {
          ...T2,
          params: [...T2.params || [], ...e3]
        };
      }
      return T2 = makeChartSelectable(T2, w, C3), T2 = makeChartInteractive(T2), C3 === 0 && (T2 = makeChartPanZoom(T2)), T2;
    });
    return {
      ...e,
      layer: O2
    };
  }
  if (!("mark" in e) || !Marks.isInteractive(e.mark)) return e;
  let O = e;
  return O = makeLegendSelectable(O, T), O = makeChartSelectable(O, w, void 0), O = makeChartInteractive(O), O = makeChartPanZoom(O), O;
}
function makeLegendSelectable(e, C) {
  if (C === false) return e;
  let w = findEncodedFields(e);
  Array.isArray(C) && (w = w.filter((e2) => C.includes(e2)));
  let T = w.map((e2) => Params.legend(e2)), E = [...e.params || [], ...T];
  return {
    ...e,
    params: E
  };
}
function makeChartSelectable(e, C, w) {
  if (C === false) return e;
  let T;
  try {
    T = Marks.getMarkType(e.mark);
  } catch {
    return e;
  }
  if (T === "geoshape") return e;
  let E = getBinnedFields(e), D = C === true ? E.length > 0 ? ["point"] : getBestSelectionForMark(T) : [C];
  if (!D || D.length === 0) return e;
  let O = D.map((C2) => C2 === "interval" ? Params.interval(e, w) : Params.point(e, w)), k = [...e.params || [], ...O];
  return E.length > 0 && D.includes("point") && k.push(Params.binColoring(w)), {
    ...e,
    params: k
  };
}
function makeChartPanZoom(e) {
  let C;
  try {
    C = Marks.getMarkType(e.mark);
  } catch {
  }
  if (C === "geoshape") return e;
  let w = e.params || [];
  return w.some((e2) => e2.bind === "scales") ? e : {
    ...e,
    params: [...w, Params.panZoom()]
  };
}
function makeChartInteractive(e) {
  let C = "encoding" in e ? e.encoding : void 0, w = e.params || [], T = w.map((e2) => e2.name);
  return w.length === 0 || !Marks.isInteractive(e.mark) ? e : {
    ...e,
    mark: Marks.makeClickable(e.mark),
    encoding: makeEncodingInteractive("opacity", C || {}, T, e.mark)
  };
}
function getBestSelectionForMark(e) {
  switch (e) {
    case "arc":
    case "area":
      return ["point"];
    case "text":
    case "bar":
      return ["point", "interval"];
    case "line":
      return;
    default:
      return ["point", "interval"];
  }
}
var VEGA_DATA_FETCH_CONCURRENCY = 5;
async function resolveVegaSpecData(e) {
  if (!e) return e;
  let C = "datasets" in e ? { ...e.datasets } : {}, w = new Semaphore(VEGA_DATA_FETCH_CONCURRENCY), T = async (e2) => {
    if (!e2) return e2;
    if ("layer" in e2) {
      let C2 = await Promise.all(e2.layer.map(T));
      e2 = {
        ...e2,
        layer: C2
      };
    }
    if ("hconcat" in e2) {
      let C2 = await Promise.all(e2.hconcat.map(T));
      e2 = {
        ...e2,
        hconcat: C2
      };
    }
    if ("vconcat" in e2) {
      let C2 = await Promise.all(e2.vconcat.map(T));
      e2 = {
        ...e2,
        vconcat: C2
      };
    }
    if ("spec" in e2 && (e2 = {
      ...e2,
      spec: await T(e2.spec)
    }), !e2.data || !("url" in e2.data)) return e2;
    let E2;
    try {
      E2 = asRemoteURL(e2.data.url);
    } catch {
      return e2;
    }
    let D = e2.data.format, O = await w.run(() => vegaLoadData(E2.href, D));
    return C[E2.pathname] = O, {
      ...e2,
      data: { name: E2.pathname }
    };
  }, E = await T(e);
  return Object.keys(C).length === 0 ? E : {
    ...E,
    datasets: C
  };
}
var import_jsx_runtime = /* @__PURE__ */ __toESM(require_jsx_runtime(), 1);
formats("arrow", arrow);
var VegaComponent = (e) => {
  let C = (0, import_compiler_runtime.c)(12), { value: w, setValue: T, chartSelection: E, fieldSelection: D, spec: O, embedOptions: k } = e, A, M;
  C[0] === O ? (A = C[1], M = C[2]) : (A = async () => resolveVegaSpecData(O), M = [O], C[0] = O, C[1] = A, C[2] = M);
  let { data: P, error: F } = useAsyncData(A, M);
  if (F) {
    let e2;
    return C[3] === F ? e2 = C[4] : (e2 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorBanner, { error: F }), C[3] = F, C[4] = e2), e2;
  }
  if (!P) return null;
  let I;
  return C[5] !== E || C[6] !== k || C[7] !== D || C[8] !== P || C[9] !== T || C[10] !== w ? (I = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadedVegaComponent, {
    value: w,
    setValue: T,
    chartSelection: E,
    fieldSelection: D,
    spec: P,
    embedOptions: k
  }), C[5] = E, C[6] = k, C[7] = D, C[8] = P, C[9] = T, C[10] = w, C[11] = I) : I = C[11], I;
}, LoadedVegaComponent = ({ value: e, setValue: D, chartSelection: O, fieldSelection: k, spec: M, embedOptions: N }) => {
  let { theme: L } = useTheme(), R = (0, import_react.useRef)(null), z = (0, import_react.useRef)(void 0), [B, V] = (0, import_react.useState)(), H = (0, import_react.useMemo)(() => N && "actions" in N ? N.actions : {
    source: false,
    compiled: false
  }, [N]), U = useDeepCompareMemoize(M), W = (0, import_react.useMemo)(() => makeSelectable(fixRelativeUrl(U), {
    chartSelection: O,
    fieldSelection: k
  }), [
    U,
    O,
    k
  ]), G = (0, import_react.useMemo)(() => getSelectionParamNames(W), [W]), K = useEvent_default((C) => {
    D({
      ...e,
      ...C
    });
  }), q = (0, import_react.useMemo)(() => debounce_default((e2, T) => {
    Logger.debug("[Vega signal]", e2, T);
    let E = Objects.mapValues(T, convertDatetimeToEpochMilliseconds);
    E = Objects.mapValues(E, convertSetToList), K({ [e2]: E });
  }, 100), [K]), J = useDeepCompareMemoize(G), Y = (0, import_react.useMemo)(() => J.reduce((e2, C) => (ParamNames.PAN_ZOOM === C || ParamNames.isBinColoring(C) || e2.push({
    signalName: C,
    handler: (e3, C2) => q(e3, C2)
  }), e2), []), [J, q]), X = useEvent_default((e2) => {
    Logger.error(e2), Logger.debug(W), V(e2);
  }), Z = useEvent_default((e2) => {
    Logger.debug("[Vega view] created", e2), z.current = e2, V(void 0);
  }), Q = () => {
    let e2 = [];
    return ParamNames.hasPoint(G) && e2.push(["Point selection", "click to select a point; hold shift for multi-select"]), ParamNames.hasInterval(G) && e2.push(["Interval selection", "click and drag to select an interval"]), ParamNames.hasLegend(G) && e2.push(["Legend selection", "click to select a legend item; hold shift for multi-select"]), ParamNames.hasPanZoom(G) && e2.push(["Pan", "hold the meta key and drag"], ["Zoom", "hold the meta key and scroll"]), e2.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
      delayDuration: 300,
      side: "left",
      content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
        className: "text-xs flex flex-col",
        children: e2.map((e3, C) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
          /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
            className: "font-bold tracking-wide",
            children: [e3[0], ":"]
          }),
          " ",
          e3[1]
        ] }, C))
      }),
      children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleQuestionMark, { className: "absolute bottom-1 right-0 m-2 h-4 w-4 cursor-help text-muted-foreground hover:text-foreground" })
    });
  }, $ = j({
    ref: R,
    spec: W,
    options: {
      theme: L === "dark" ? "dark" : void 0,
      actions: H,
      mode: "vega-lite",
      tooltip: tooltipHandler.call,
      renderer: "canvas"
    },
    onError: X,
    onEmbed: Z
  });
  return (0, import_react.useEffect)(() => (Y.forEach(({ signalName: e2, handler: w }) => {
    try {
      $ == null ? void 0 : $.view.addSignalListener(e2, w);
    } catch (e3) {
      Logger.error(e3);
    }
  }), () => {
    Y.forEach(({ signalName: e2, handler: w }) => {
      try {
        $ == null ? void 0 : $.view.removeSignalListener(e2, w);
      } catch (e3) {
        Logger.error(e3);
      }
    });
  }), [$, Y]), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [B && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, {
    variant: "destructive",
    children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertTitle, { children: B.message }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
      className: "text-md",
      children: B.stack
    })]
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
    className: cn("relative"),
    onPointerDown: Events.stopPropagation(),
    children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
      ref: R,
      "data-container-width": getContainerWidth(W)
    }), Q()]
  })] });
};
function convertSetToList(e) {
  return e instanceof Set ? [...e] : e;
}
function convertDatetimeToEpochMilliseconds(e) {
  return Array.isArray(e) ? e.map((e2) => e2 instanceof Date && isValid(e2) ? new Date(e2).getTime() : e2) : e;
}
var vega_component_default = VegaComponent;
export {
  vega_component_default as default
};
