import { extentOf, RoughRectangle, useResolvedVibe, RoughText, RoughLine, SeriesVisibilityProvider, VibeProvider } from './chunk-2FBXYIJM.js';
export { SeriesVisibilityProvider, defaultSeriesVisibility, useSeriesVisibility } from './chunk-2FBXYIJM.js';
import './chunk-3TD64277.js';
import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext, cloneElement } from 'react';
import { jsx, jsxs } from 'react/jsx-runtime';

// src/interactive/readMark.ts
function readMark(el) {
  const host = el.closest("[data-gc-mark]");
  if (!host) return null;
  const get = (n) => host.getAttribute(n);
  const raw = get("data-gc-value");
  const value = raw == null ? 0 : raw.startsWith("{") ? JSON.parse(raw) : Number(raw);
  const series = get("data-gc-series");
  const label = get("data-gc-label");
  return {
    kind: get("data-gc-mark"),
    index: Number(get("data-gc-index")),
    value,
    cx: Number(get("data-gc-cx")),
    cy: Number(get("data-gc-cy")),
    ...series != null ? { series } : {},
    ...label != null ? { label } : {}
  };
}

// src/core/zoom.ts
function zoomDomain([lo, hi], focus, factor) {
  const anchor = lo + (hi - lo) * focus;
  return [anchor - (anchor - lo) * factor, anchor + (hi - anchor) * factor];
}
function panDomain([lo, hi], deltaData) {
  return [lo + deltaData, hi + deltaData];
}
function clampDomain([lo, hi], [bLo, bHi], minSpan) {
  const span = Math.max(minSpan, Math.min(hi - lo, bHi - bLo));
  const nLo = Math.max(bLo, Math.min(lo, bHi - span));
  return [nLo, nLo + span];
}
function wheelFactor(deltaY) {
  return deltaY < 0 ? 0.8 : 1.25;
}
function wheelZoom(domain, focus, deltaY, bounds, minSpan) {
  return clampDomain(zoomDomain(domain, focus, wheelFactor(deltaY)), bounds, minSpan);
}
function focusFraction(clientPos, edgeStart, length) {
  if (length <= 0) return 0;
  return Math.max(0, Math.min(1, (clientPos - edgeStart) / length));
}

// src/interactive/useZoomPan.ts
function chartXExtent(props) {
  const series = props.series;
  if (Array.isArray(series)) {
    const xs = series.flatMap((s) => (s.points ?? []).map((p) => p.x));
    return xs.length ? extentOf(xs, false) : null;
  }
  const data = props.data;
  if (Array.isArray(data) && data.length > 0 && data.every((d) => typeof d?.x === "number")) {
    return extentOf(data.map((d) => d.x), false);
  }
  return null;
}
function useZoomPan(bounds, opts = {}) {
  const minSpan = opts.minSpan ?? (bounds ? (bounds[1] - bounds[0]) / 1e3 || 1 : 1);
  const [domain, setDomain] = useState(null);
  const drag = useRef(null);
  const onWheel = useCallback(
    (e) => {
      if (!bounds) return;
      e.preventDefault();
      const rect = e.currentTarget.getBoundingClientRect();
      const focus = focusFraction(e.clientX, rect.left, rect.width);
      setDomain((d) => wheelZoom(d ?? bounds, focus, e.deltaY, bounds, minSpan));
    },
    [bounds, minSpan]
  );
  const onPointerDown = useCallback(
    (e) => {
      if (!bounds || !opts.pan) return;
      drag.current = { x: e.clientX, domain: domain ?? bounds };
    },
    [bounds, opts.pan, domain]
  );
  const onPointerMove = useCallback(
    (e) => {
      const d = drag.current;
      if (!d || !bounds) return;
      const rect = e.currentTarget.getBoundingClientRect();
      const span = d.domain[1] - d.domain[0];
      const deltaData = -((e.clientX - d.x) / rect.width) * span;
      setDomain(clampDomain(panDomain(d.domain, deltaData), bounds, minSpan));
    },
    [bounds, minSpan]
  );
  const onPointerUp = useCallback(() => {
    drag.current = null;
  }, []);
  const reset = useCallback(() => setDomain(null), []);
  return { domain, onWheel, onPointerDown, onPointerMove, onPointerUp, reset };
}
function Brush({ start, length, height }) {
  if (length <= 0 || height <= 0) return null;
  return /* @__PURE__ */ jsx(RoughRectangle, { x: start, y: 0, width: length, height, style: { opacity: 0.25 } });
}

// src/core/brush.ts
function pixelToValue(px, [p0, p1], [v0, v1]) {
  if (p1 === p0) return v0;
  return v0 + (px - p0) / (p1 - p0) * (v1 - v0);
}
function clientToViewBox(client, rectStart, rectLength, vbStart, vbLength) {
  if (rectLength <= 0) return vbStart;
  return vbStart + (client - rectStart) / rectLength * vbLength;
}
function brushRect(a, b) {
  return { start: Math.min(a, b), length: Math.abs(b - a) };
}
function marksInPixelRange(marks, range, axis) {
  const lo = Math.min(range[0], range[1]);
  const hi = Math.max(range[0], range[1]);
  return marks.filter((m) => {
    const v = axis === "x" ? m.cx : m.cy;
    return v >= lo && v <= hi;
  });
}

// src/core/transition.ts
function lerp(a, b, t) {
  return a + (b - a) * t;
}
function interpolateNumberMap(from, to, t) {
  const out = {};
  for (const k of Object.keys(to)) {
    out[k] = k in from ? lerp(from[k], to[k], t) : to[k];
  }
  return out;
}
function easeInOutCubic(t) {
  return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
var isDatumArray = (v) => Array.isArray(v) && v.every((d) => d && typeof d.label === "string" && typeof d.value === "number");
var isSeriesArray = (v) => Array.isArray(v) && v.every((s) => s && typeof s.id === "string" && Array.isArray(s.points));
function interpolateChartData(from, to, t) {
  if (isDatumArray(from) && isDatumArray(to)) {
    const prev = new Map(from.map((d) => [d.label, d.value]));
    return to.map((d) => ({ ...d, value: lerp(prev.get(d.label) ?? d.value, d.value, t) }));
  }
  if (isSeriesArray(from) && isSeriesArray(to)) {
    const prev = new Map(from.map((s) => [s.id, s.points]));
    return to.map((s) => {
      const pp = prev.get(s.id);
      return { ...s, points: s.points.map((p, i) => ({ x: p.x, y: pp && pp[i] ? lerp(pp[i].y, p.y, t) : p.y })) };
    });
  }
  return to;
}

// src/interactive/useDataTransition.ts
function prefersReducedMotion() {
  return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;
}
function useDataTransition(data, durationMs = 500, enabled = true) {
  const [frame, setFrame] = useState(data);
  const prev = useRef(data);
  useEffect(() => {
    if (!enabled || prefersReducedMotion() || prev.current === data) {
      setFrame(data);
      prev.current = data;
      return;
    }
    const from = prev.current;
    const start = performance.now();
    let raf = 0;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / durationMs);
      setFrame(interpolateChartData(from, data, easeInOutCubic(t)));
      if (t < 1) raf = requestAnimationFrame(tick);
      else prev.current = data;
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [data, durationMs, enabled]);
  return frame;
}

// src/core/linkSelection.ts
function emptyLink() {
  return { bySource: {} };
}
function setFilter(state, source, keys) {
  if (keys.length === 0) return clearFilter(state, source);
  return { bySource: { ...state.bySource, [source]: keys } };
}
function clearFilter(state, source) {
  if (!(source in state.bySource)) return state;
  const next = { ...state.bySource };
  delete next[source];
  return { bySource: next };
}
function activeFilter(state) {
  const all = /* @__PURE__ */ new Set();
  for (const keys of Object.values(state.bySource)) for (const k of keys) all.add(k);
  return [...all].sort();
}
var LinkContext = createContext(null);
function LinkedCharts({ children }) {
  const [state, setState] = useState(emptyLink);
  const publish = useCallback((source, keys) => {
    setState((s) => setFilter(s, source, keys));
  }, []);
  const value = useMemo(() => ({ filter: activeFilter(state), publish }), [state, publish]);
  return /* @__PURE__ */ jsx(LinkContext.Provider, { value, children });
}
function useLinkGroup() {
  return useContext(LinkContext);
}

// src/core/seriesVisibility.ts
function markKey(mark) {
  return `${mark.series ?? ""}:${mark.index}`;
}
function toggleSelection(current, key, multi) {
  if (!multi) return current.has(key) && current.size === 1 ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([key]);
  const next = new Set(current);
  if (next.has(key)) next.delete(key);
  else next.add(key);
  return next;
}

// src/interactive/placeTooltip.ts
function placeTooltip(anchor, size, bounds, gap = 8) {
  let x = anchor.x + gap;
  let y = anchor.y + gap;
  if (x + size.width > bounds.width) x = anchor.x - gap - size.width;
  if (y + size.height > bounds.height) y = anchor.y - gap - size.height;
  return { x: Math.max(0, x), y: Math.max(0, y) };
}

// src/interactive/defaultTooltipFormat.ts
function defaultTooltipFormat(mark) {
  const title = mark.label ?? mark.series;
  const rows = typeof mark.value === "number" ? [["value", String(mark.value)]] : Object.entries(mark.value).map(([k, v]) => [k, String(v)]);
  return title !== void 0 ? { title, rows } : { rows };
}
function markAriaLabel(mark) {
  const { title, rows } = defaultTooltipFormat(mark);
  return [...title ? [title] : [], ...rows.map(([k, v]) => `${k} ${v}`)].join(", ");
}
var PAD = 7;
var LINE = 15;
var CHAR_W = 7;
function Tooltip({ mark, anchor, bounds, format = defaultTooltipFormat }) {
  const resolved = useResolvedVibe();
  const { title, rows } = format(mark);
  const lines = [...title ? [title] : [], ...rows.map(([k, v]) => `${k}: ${v}`)];
  const width = PAD * 2 + Math.max(0, ...lines.map((l) => l.length)) * CHAR_W;
  const height = PAD * 2 + lines.length * LINE;
  const { x, y } = placeTooltip(anchor, { width, height }, bounds);
  const bg = resolved.background ?? "#ffffff";
  return /* @__PURE__ */ jsxs("g", { transform: `translate(${x}, ${y})`, pointerEvents: "none", "aria-hidden": "true", children: [
    /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width, height, rx: 4, fill: bg, opacity: 0.92 }),
    /* @__PURE__ */ jsx(RoughRectangle, { x: 0, y: 0, width, height, fill: null }),
    lines.map((line, i) => /* @__PURE__ */ jsx(RoughText, { x: PAD, y: PAD + LINE * (i + 0.7), anchor: "start", baseline: "middle", haloColor: bg, children: line }, i))
  ] });
}
function nearestMark(marks, x, y) {
  let best = null;
  let bestD = Infinity;
  for (const m of marks) {
    const d = (m.cx - x) ** 2 + (m.cy - y) ** 2;
    if (d < bestD) {
      bestD = d;
      best = m;
    }
  }
  return best;
}
function Crosshair({ x, height }) {
  return /* @__PURE__ */ jsx(RoughLine, { x1: x, y1: 0, x2: x, y2: height });
}

// src/interactive/hoverStyle.ts
var HOVER_ATTR = "data-gc-hover";
var CURRENT_ATTR = "data-gc-current";
function hoverCss(dimOpacity = 0.35) {
  return `[${HOVER_ATTR}] [data-gc-mark]:not([${CURRENT_ATTR}]){opacity:${dimOpacity}}@media (prefers-reduced-motion: no-preference){[data-gc-mark]{transition:opacity 120ms ease}}`;
}

// src/interactive/selectStyle.ts
var SELECTED_ATTR = "data-gc-selected";
var CHOSEN_ATTR = "data-gc-chosen";
function selectCss(dimOpacity = 0.5) {
  return `[data-gc-mark][${CHOSEN_ATTR}]{opacity:1}[${SELECTED_ATTR}] [data-gc-mark]:not([${CHOSEN_ATTR}]){opacity:${dimOpacity}}`;
}
function markFromEvent(_svg, target, _clientX, _clientY) {
  const mark = readMark(target);
  if (!mark) return null;
  return { mark, x: mark.cx, y: mark.cy };
}
function enhanceMarks(svg) {
  svg.querySelectorAll("[data-gc-mark]").forEach((el) => {
    const mark = readMark(el);
    if (!mark) return;
    el.setAttribute("tabindex", "0");
    el.setAttribute("role", "img");
    el.setAttribute("aria-label", markAriaLabel(mark));
  });
}
function toSet(v) {
  return new Set(v == null ? [] : Array.isArray(v) ? v : [v]);
}
function InteractiveChart({
  children,
  tooltip = true,
  highlight = true,
  onHover,
  selectable = false,
  selected,
  defaultSelected,
  multiSelect = false,
  onSelect,
  legendToggle = true,
  crosshair = false,
  zoom = false,
  pan = false,
  brush = false,
  onBrush,
  transition = false,
  linkGroup,
  vibe
}) {
  const link = useLinkGroup();
  const svgRef = useRef(null);
  const currentRef = useRef(null);
  const lastKeyRef = useRef(null);
  const [hover, setHover] = useState(null);
  const [viewBox, setViewBox] = useState(void 0);
  const [internalSel, setInternalSel] = useState(() => toSet(defaultSelected));
  const selectedKeys = selected !== void 0 ? toSet(selected) : internalSel;
  const selSig = [...selectedKeys].sort().join("|");
  const [hidden, setHidden] = useState(/* @__PURE__ */ new Set());
  const toggle = useCallback((series) => {
    setHidden((prev) => {
      const next = new Set(prev);
      if (next.has(series)) next.delete(series);
      else next.add(series);
      return next;
    });
  }, []);
  const visibility = useMemo(
    () => ({ hidden, toggle, interactive: legendToggle }),
    [hidden, toggle, legendToggle]
  );
  const zoomBounds = useMemo(
    () => zoom ? chartXExtent(children.props) : null,
    [zoom, children]
  );
  const zp = useZoomPan(zoomBounds, { pan: pan && !brush });
  const childProps = children.props;
  const dataKey = Array.isArray(childProps.series) ? "series" : Array.isArray(childProps.data) ? "data" : null;
  const transitionOn = !!transition && dataKey != null;
  const durationMs = typeof transition === "object" ? transition.durationMs ?? 500 : 500;
  const animatedData = useDataTransition(dataKey ? childProps[dataKey] : void 0, durationMs, transitionOn);
  const overrides = {};
  if (zp.domain) overrides.xAxis = { ...childProps.xAxis ?? {}, domain: zp.domain };
  if (transitionOn && dataKey) overrides[dataKey] = animatedData;
  const content = Object.keys(overrides).length ? cloneElement(children, overrides) : children;
  const [brushPx, setBrushPx] = useState(null);
  const brushing = useRef(false);
  const clear = useCallback(() => {
    const svg = svgRef.current;
    if (svg) {
      svg.removeAttribute(HOVER_ATTR);
      currentRef.current?.removeAttribute(CURRENT_ATTR);
      currentRef.current = null;
    }
    lastKeyRef.current = null;
    setHover(null);
    onHover?.(null);
  }, [onHover]);
  const onMove = useCallback(
    (e) => {
      const svg = svgRef.current;
      const target = e.target;
      if (!svg || !target) return;
      const next = markFromEvent(svg, target);
      if (!next) {
        clear();
        return;
      }
      const key = markKey(next.mark);
      if (key === lastKeyRef.current) return;
      lastKeyRef.current = key;
      if (highlight) {
        svg.setAttribute(HOVER_ATTR, "");
        const group = target.closest("[data-gc-mark]");
        if (group !== currentRef.current) {
          currentRef.current?.removeAttribute(CURRENT_ATTR);
          group?.setAttribute(CURRENT_ATTR, "");
          currentRef.current = group;
        }
      }
      setHover(next);
      onHover?.(next.mark);
    },
    [highlight, onHover, clear]
  );
  const activate = useCallback(
    (target) => {
      if (!selectable || !target) return;
      const mark = readMark(target);
      if (!mark) return;
      const next = toggleSelection(selectedKeys, markKey(mark), multiSelect);
      if (selected === void 0) setInternalSel(next);
      onSelect?.(mark, [...next]);
      if (linkGroup) link?.publish(linkGroup, [...next]);
    },
    [selectable, multiSelect, selected, onSelect, selSig, linkGroup, link]
    // selSig: stable signature of selectedKeys
  );
  const onClick = useCallback((e) => activate(e.target), [activate]);
  const onKey = useCallback(
    (e) => {
      const ke = e;
      if (ke.key !== "Enter" && ke.key !== " ") return;
      ke.preventDefault?.();
      activate(e.target);
    },
    [activate]
  );
  const attach = useCallback((node) => {
    const svg = node?.querySelector("svg") ?? null;
    svgRef.current = svg;
    setViewBox(svg?.getAttribute("viewBox") ?? void 0);
    if (svg) enhanceMarks(svg);
  }, []);
  const linkSig = linkGroup && link ? link.filter.join("|") : "";
  useEffect(() => {
    const svg = svgRef.current;
    if (!svg) return;
    const emphasized = /* @__PURE__ */ new Set([...selectedKeys, ...linkGroup && link ? link.filter : []]);
    if (emphasized.size > 0) svg.setAttribute(SELECTED_ATTR, "");
    else svg.removeAttribute(SELECTED_ATTR);
    svg.querySelectorAll("[data-gc-mark]").forEach((el) => {
      const m = readMark(el);
      if (m && emphasized.has(markKey(m))) el.setAttribute(CHOSEN_ATTR, "");
      else el.removeAttribute(CHOSEN_ATTR);
    });
  }, [selSig, linkSig]);
  useEffect(() => {
    const svg = svgRef.current;
    if (!svg || !(zoom || pan)) return;
    const wheel = (e) => zp.onWheel(e);
    const down = (e) => zp.onPointerDown(e);
    const move = (e) => zp.onPointerMove(e);
    const up = () => zp.onPointerUp();
    svg.addEventListener("wheel", wheel, { passive: false });
    if (pan && !brush) {
      svg.addEventListener("pointerdown", down);
      svg.addEventListener("pointermove", move);
      svg.addEventListener("pointerup", up);
      svg.addEventListener("pointerleave", up);
    }
    return () => {
      svg.removeEventListener("wheel", wheel);
      svg.removeEventListener("pointerdown", down);
      svg.removeEventListener("pointermove", move);
      svg.removeEventListener("pointerup", up);
      svg.removeEventListener("pointerleave", up);
    };
  }, [zoom, pan, brush, zp.onWheel, zp.onPointerDown, zp.onPointerMove, zp.onPointerUp]);
  useEffect(() => {
    const svg = svgRef.current;
    if (!svg || !brush) return;
    const vb = (viewBox ?? "0 0 0 0").split(/[\s,]+/).map(Number);
    const toVb = (clientX) => {
      const r = svg.getBoundingClientRect();
      return clientToViewBox(clientX, r.left, r.width, vb[0] ?? 0, vb[2] ?? 0);
    };
    const down = (e) => {
      brushing.current = true;
      const x = toVb(e.clientX);
      setBrushPx({ a: x, b: x });
    };
    const move = (e) => {
      if (!brushing.current) return;
      const x = toVb(e.clientX);
      setBrushPx((p) => p ? { a: p.a, b: x } : null);
    };
    const up = () => {
      if (!brushing.current) return;
      brushing.current = false;
      setBrushPx((p) => {
        if (p && svgRef.current) {
          const tagged = [];
          svgRef.current.querySelectorAll("[data-gc-mark]").forEach((el) => {
            const m = readMark(el);
            if (m) tagged.push({ meta: m, key: markKey(m), cx: m.cx, cy: m.cy });
          });
          const hit = marksInPixelRange(tagged, [p.a, p.b], "x").map((t) => t.meta);
          onBrush?.(hit);
          if (linkGroup) link?.publish(linkGroup, hit.map(markKey));
        }
        return null;
      });
    };
    svg.addEventListener("pointerdown", down);
    svg.addEventListener("pointermove", move);
    svg.addEventListener("pointerup", up);
    svg.addEventListener("pointerleave", up);
    return () => {
      svg.removeEventListener("pointerdown", down);
      svg.removeEventListener("pointermove", move);
      svg.removeEventListener("pointerup", up);
      svg.removeEventListener("pointerleave", up);
    };
  }, [brush, viewBox, onBrush, linkGroup, link]);
  useEffect(() => {
    const svg = svgRef.current;
    if (!svg) return;
    svg.addEventListener("pointermove", onMove);
    svg.addEventListener("pointerleave", clear);
    svg.addEventListener("focusin", onMove);
    svg.addEventListener("focusout", clear);
    svg.addEventListener("click", onClick);
    svg.addEventListener("keydown", onKey);
    return () => {
      svg.removeEventListener("pointermove", onMove);
      svg.removeEventListener("pointerleave", clear);
      svg.removeEventListener("focusin", onMove);
      svg.removeEventListener("focusout", clear);
      svg.removeEventListener("click", onClick);
      svg.removeEventListener("keydown", onKey);
    };
  }, [onMove, clear, onClick, onKey]);
  const renderTooltip = typeof tooltip === "function" ? tooltip : void 0;
  const vbParts = viewBox ? viewBox.split(/[\s,]+/).map(Number) : void 0;
  const vbWidth = vbParts?.[2];
  const vbHeight = vbParts?.[3];
  const cursor = brush ? "crosshair" : pan ? "grab" : zoom ? "zoom-in" : void 0;
  const zoomed = (zoom || pan) && zp.domain != null;
  return /* @__PURE__ */ jsxs(
    "div",
    {
      ref: attach,
      style: { position: "relative", display: "inline-block", overflow: zoom || pan ? "hidden" : void 0, cursor },
      children: [
        /* @__PURE__ */ jsx(SeriesVisibilityProvider, { value: visibility, children: content }),
        highlight ? /* @__PURE__ */ jsx("style", { children: hoverCss() }) : null,
        selectable || linkGroup ? /* @__PURE__ */ jsx("style", { children: selectCss() }) : null,
        selectable ? /* @__PURE__ */ jsx("style", { children: `[${HOVER_ATTR}] [data-gc-mark],[data-gc-mark]{cursor:pointer}` }) : null,
        zoomed ? /* @__PURE__ */ jsx(
          "button",
          {
            type: "button",
            onClick: () => zp.reset(),
            style: {
              position: "absolute",
              top: 6,
              right: 6,
              font: "11px system-ui, sans-serif",
              padding: "2px 8px",
              borderRadius: 4,
              border: "1px solid rgba(0,0,0,0.25)",
              background: "rgba(255,255,255,0.85)",
              cursor: "pointer"
            },
            children: "Reset view"
          }
        ) : null,
        brush && brushPx && vbHeight !== void 0 ? /* @__PURE__ */ jsx(
          "svg",
          {
            viewBox,
            style: { position: "absolute", inset: 0, pointerEvents: "none", width: "100%", height: "100%" },
            children: /* @__PURE__ */ jsx(VibeProvider, { vibe, children: /* @__PURE__ */ jsx(Brush, { start: brushRect(brushPx.a, brushPx.b).start, length: brushRect(brushPx.a, brushPx.b).length, height: vbHeight }) })
          }
        ) : null,
        hover && (tooltip || crosshair) ? /* @__PURE__ */ jsx(
          "svg",
          {
            viewBox,
            style: { position: "absolute", inset: 0, pointerEvents: "none", width: "100%", height: "100%" },
            children: /* @__PURE__ */ jsxs(VibeProvider, { vibe, children: [
              crosshair && vbHeight !== void 0 ? /* @__PURE__ */ jsx(Crosshair, { x: hover.x, height: vbHeight }) : null,
              tooltip ? renderTooltip ? /* @__PURE__ */ jsx("g", { transform: `translate(${hover.x}, ${hover.y})`, children: renderTooltip(hover.mark) }) : vbWidth !== void 0 && vbHeight !== void 0 ? /* @__PURE__ */ jsx(Tooltip, { mark: hover.mark, anchor: { x: hover.x, y: hover.y }, bounds: { width: vbWidth, height: vbHeight } }) : null : null
            ] })
          }
        ) : null
      ]
    }
  );
}

// src/interactive/embed.ts
function escapeHtml(s) {
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}
var TIP_CSS = "#gc-tip{position:fixed;display:none;pointer-events:none;background:#111;color:#fff;font:12px/1.4 system-ui,sans-serif;padding:4px 8px;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.3);z-index:10}";
var HYDRATOR = "(function(){var tip=document.getElementById('gc-tip');var root=document.querySelector('svg[data-gc]')||document.querySelector('svg');if(!root||!tip)return;root.addEventListener('pointermove',function(e){var g=e.target.closest&&e.target.closest('[data-gc-mark]');if(!g){tip.style.display='none';return;}var label=g.getAttribute('data-gc-label')||'';var value=g.getAttribute('data-gc-value')||'';tip.textContent=label?(label+': '+value):value;tip.style.display='block';tip.style.left=(e.clientX+12)+'px';tip.style.top=(e.clientY+12)+'px';});root.addEventListener('pointerleave',function(){tip.style.display='none';});})();";
function interactiveEmbed(svg, opts = {}) {
  const tooltip = opts.tooltip !== false;
  const title = escapeHtml(opts.title ?? "GoldenChart");
  const head = '<!doctype html>\n<html>\n<head>\n<meta charset="utf-8">\n<title>' + title + "</title>\n" + (tooltip ? "<style>" + TIP_CSS + "</style>\n" : "") + "</head>\n<body>\n";
  const body = svg + "\n" + (tooltip ? '<div id="gc-tip"></div>\n<script>' + HYDRATOR + "</script>\n" : "");
  return head + body + "</body>\n</html>\n";
}

export { Brush, CHOSEN_ATTR, CURRENT_ATTR, Crosshair, HOVER_ATTR, InteractiveChart, LinkedCharts, SELECTED_ATTR, Tooltip, activeFilter, brushRect, chartXExtent, clampDomain, clearFilter, clientToViewBox, defaultTooltipFormat, easeInOutCubic, emptyLink, enhanceMarks, focusFraction, hoverCss, interactiveEmbed, interpolateChartData, interpolateNumberMap, lerp, markAriaLabel, markFromEvent, markKey, marksInPixelRange, nearestMark, panDomain, pixelToValue, placeTooltip, prefersReducedMotion, readMark, selectCss, setFilter, toggleSelection, useDataTransition, useLinkGroup, useZoomPan, wheelFactor, wheelZoom, zoomDomain };
//# sourceMappingURL=interactive.js.map
//# sourceMappingURL=interactive.js.map