import {
  a as y,
  b as v,
  c as E,
  d as C
} from "../_browser-chunks/chunk-HT4E25ZO.js";
import {
  a as p
} from "../_browser-chunks/chunk-KCQXA5WV.js";
import "../_browser-chunks/chunk-JCASV5LV.js";
import {
  a as i
} from "../_browser-chunks/chunk-IO47FP3U.js";

// src/channels/index.ts
import { global as J } from "@storybook/global";

// src/channels/main.ts
var V = /* @__PURE__ */ i((c) => c.transports !== void 0, "isMulti"), U = /* @__PURE__ */ i(() => Math.random().toString(16).slice(2), "generateRandomId"), b = class b {
  constructor(e = {}) {
    this.sender = U();
    this.events = {};
    this.data = {};
    this.transports = [];
    this.isAsync = e.async || !1, V(e) ? (this.transports = e.transports || [], this.transports.forEach((t) => {
      t.setHandler((n) => this.handleEvent(n));
    })) : this.transports = e.transport ? [e.transport] : [], this.transports.forEach((t) => {
      t.setHandler((n) => this.handleEvent(n));
    });
  }
  get hasTransport() {
    return this.transports.length > 0;
  }
  addListener(e, t) {
    this.events[e] = this.events[e] || [], this.events[e].push(t);
  }
  emit(e, ...t) {
    let n = { type: e, args: t, from: this.sender }, r = {};
    t.length >= 1 && t[0] && t[0].options && (r = t[0].options);
    let s = /* @__PURE__ */ i(() => {
      this.transports.forEach((a) => {
        a.send(n, r);
      }), this.handleEvent(n);
    }, "handler");
    this.isAsync ? setImmediate(s) : s();
  }
  last(e) {
    return this.data[e];
  }
  eventNames() {
    return Object.keys(this.events);
  }
  listenerCount(e) {
    let t = this.listeners(e);
    return t ? t.length : 0;
  }
  listeners(e) {
    return this.events[e] || void 0;
  }
  once(e, t) {
    let n = this.onceListener(e, t);
    this.addListener(e, n);
  }
  removeAllListeners(e) {
    e ? this.events[e] && delete this.events[e] : this.events = {};
  }
  removeListener(e, t) {
    let n = this.listeners(e);
    n && (this.events[e] = n.filter((r) => r !== t));
  }
  on(e, t) {
    this.addListener(e, t);
  }
  off(e, t) {
    this.removeListener(e, t);
  }
  handleEvent(e) {
    let t = this.listeners(e.type);
    t && t.length && t.forEach((n) => {
      n.apply(e, e.args);
    }), this.data[e.type] = e.args;
  }
  onceListener(e, t) {
    let n = /* @__PURE__ */ i((...r) => (this.removeListener(e, n), t(...r)), "onceListener");
    return n;
  }
};
i(b, "Channel");
var f = b;

// src/channels/postmessage/index.ts
import { logger as H, pretty as N } from "storybook/internal/client-logger";
import * as j from "storybook/internal/core-events";
import { global as o } from "@storybook/global";

// src/channels/postmessage/getEventSourceUrl.ts
import { logger as B } from "storybook/internal/client-logger";
var k = /* @__PURE__ */ i((c) => {
  let e = Array.from(
    document.querySelectorAll("iframe[data-is-storybook]")
  ), [t, ...n] = e.filter((s) => {
    try {
      return s.contentWindow?.location.origin === c.source.location.origin && s.contentWindow?.location.pathname === c.source.location.pathname;
    } catch {
    }
    try {
      return s.contentWindow === c.source;
    } catch {
    }
    let a = s.getAttribute("src"), l;
    try {
      if (!a)
        return !1;
      ({ origin: l } = new URL(a, document.location.toString()));
    } catch {
      return !1;
    }
    return l === c.origin;
  }), r = t?.getAttribute("src");
  if (r && n.length === 0) {
    let { protocol: s, host: a, pathname: l } = new URL(r, document.location.toString());
    return `${s}//${a}${l}`;
  }
  return n.length > 0 && B.error("found multiple candidates for event source"), null;
}, "getEventSourceUrl");

// src/channels/postmessage/index.ts
var { document: T, location: A } = o, O = "storybook-channel", q = { maxDepth: 25 }, L = class L {
  constructor(e) {
    this.config = e;
    this.connected = !1;
    if (this.buffer = [], typeof o?.addEventListener == "function" && o.addEventListener("message", this.handleEvent.bind(this), !1), e.page !== "manager" && e.page !== "preview")
      throw new Error(`postmsg-channel: "config.page" cannot be "${e.page}"`);
  }
  setHandler(e) {
    this.handler = (...t) => {
      e.apply(this, t), !this.connected && this.getLocalFrame().length && (this.flush(), this.connected = !0);
    };
  }
  /**
   * Sends `event` to the associated window. If the window does not yet exist the event will be
   * stored in a buffer and sent when the window exists.
   *
   * @param event
   */
  send(e, t) {
    let {
      target: n,
      // telejson options
      allowRegExp: r,
      allowSymbol: s,
      allowDate: a,
      allowError: l,
      allowUndefined: h,
      maxDepth: R,
      space: $
    } = t || {}, F = Object.fromEntries(
      Object.entries({
        allowRegExp: r,
        allowSymbol: s,
        allowDate: a,
        allowError: l,
        allowUndefined: h,
        maxDepth: R,
        space: $
      }).filter(([g, m]) => typeof m < "u")
    ), P = {
      ...q,
      ...o.CHANNEL_OPTIONS || {},
      ...F
    }, S = this.getFrames(n), _ = new URLSearchParams(A?.search || ""), D = E(
      {
        key: O,
        event: e,
        refId: _.get("refId")
      },
      P
    );
    return S.length ? (this.buffer.length && this.flush(), S.forEach((g) => {
      try {
        g.postMessage(D, "*");
      } catch {
        H.error("sending over postmessage fail");
      }
    }), Promise.resolve(null)) : new Promise((g, m) => {
      this.buffer.push({ event: e, resolve: g, reject: m });
    });
  }
  flush() {
    let { buffer: e } = this;
    this.buffer = [], e.forEach((t) => {
      this.send(t.event).then(t.resolve).catch(t.reject);
    });
  }
  getFrames(e) {
    if (this.config.page === "manager") {
      let n = Array.from(
        T.querySelectorAll("iframe[data-is-storybook][data-is-loaded]")
      ).flatMap((r) => {
        try {
          return r.contentWindow && r.dataset.isStorybook !== void 0 && r.id === e ? [r.contentWindow] : [];
        } catch {
          return [];
        }
      });
      return n?.length ? n : this.getCurrentFrames();
    }
    return o && o.parent && o.parent !== o.self ? [o.parent] : [];
  }
  getCurrentFrames() {
    return this.config.page === "manager" ? Array.from(
      T.querySelectorAll('[data-is-storybook="true"]')
    ).flatMap((t) => t.contentWindow ? [t.contentWindow] : []) : o && o.parent ? [o.parent] : [];
  }
  getLocalFrame() {
    return this.config.page === "manager" ? Array.from(
      T.querySelectorAll("#storybook-preview-iframe")
    ).flatMap((t) => t.contentWindow ? [t.contentWindow] : []) : o && o.parent ? [o.parent] : [];
  }
  handleEvent(e) {
    try {
      let { data: t } = e, { key: n, event: r, refId: s } = typeof t == "string" && v(t) ? C(t, o.CHANNEL_OPTIONS || {}) : t;
      if (n === O) {
        let a = this.config.page === "manager" ? '<span style="color: #37D5D3; background: black"> manager </span>' : '<span style="color: #1EA7FD; background: black"> preview </span>', l = Object.values(j).includes(r.type) ? `<span style="color: #FF4785">${r.type}</span>` : `<span style="color: #FFAE00">${r.type}</span>`;
        if (s && (r.refId = s), r.source = this.config.page === "preview" ? e.origin : k(e), !r.source) {
          N.error(
            `${a} received ${l} but was unable to determine the source of the event`
          );
          return;
        }
        let h = `${a} received ${l} (${t.length})`;
        N.debug(
          A.origin !== r.source ? h : `${h} <span style="color: gray">(on ${A.origin} from ${r.source})</span>`,
          ...r.args
        ), p(this.handler, "ChannelHandler should be set"), this.handler(r);
      }
    } catch (t) {
      H.error(t);
    }
  }
};
i(L, "PostMessageTransport");
var d = L;

// src/channels/websocket/index.ts
import * as W from "storybook/internal/core-events";
import { global as x } from "@storybook/global";
var { WebSocket: Y } = x, M = 15e3, I = 5e3, w = class w {
  constructor({ url: e, onError: t, page: n }) {
    this.buffer = [];
    this.isReady = !1;
    this.isClosed = !1;
    this.pingTimeout = 0;
    this.socket = new Y(e), this.socket.onopen = () => {
      this.isReady = !0, this.heartbeat(), this.flush();
    }, this.socket.onmessage = ({ data: r }) => {
      let s = typeof r == "string" && v(r) ? C(r) : r;
      p(this.handler, "WebsocketTransport handler should be set"), this.handler(s), s.type === "ping" && (this.heartbeat(), this.send({ type: "pong" }));
    }, this.socket.onerror = (r) => {
      t && t(r);
    }, this.socket.onclose = (r) => {
      p(this.handler, "WebsocketTransport handler should be set"), this.handler({
        type: W.CHANNEL_WS_DISCONNECT,
        args: [{ reason: r.reason, code: r.code }],
        from: n || "preview"
      }), this.isClosed = !0, clearTimeout(this.pingTimeout);
    };
  }
  heartbeat() {
    clearTimeout(this.pingTimeout), this.pingTimeout = setTimeout(() => {
      this.socket.close(3008, "timeout");
    }, M + I);
  }
  setHandler(e) {
    this.handler = e;
  }
  send(e) {
    this.isClosed || (this.isReady ? this.sendNow(e) : this.sendLater(e));
  }
  sendLater(e) {
    this.buffer.push(e);
  }
  sendNow(e) {
    let t = E(e, {
      maxDepth: 15,
      ...x.CHANNEL_OPTIONS
    });
    this.socket.send(t);
  }
  flush() {
    let { buffer: e } = this;
    this.buffer = [], e.forEach((t) => this.send(t));
  }
};
i(w, "WebsocketTransport");
var u = w;

// src/channels/index.ts
var { CONFIG_TYPE: K } = J, ye = f;
function ve({ page: c, extraTransports: e = [] }) {
  let t = [new d({ page: c }), ...e];
  if (K === "DEVELOPMENT") {
    let r = window.location.protocol === "http:" ? "ws" : "wss", { hostname: s, port: a } = window.location, l = `${r}://${s}:${a}/storybook-server-channel`;
    t.push(new u({ url: l, onError: /* @__PURE__ */ i(() => {
    }, "onError"), page: c }));
  }
  let n = new f({ transports: t });
  return y.__prepare(
    n,
    c === "manager" ? y.Environment.MANAGER : y.Environment.PREVIEW
  ), n;
}
i(ve, "createBrowserChannel");
export {
  f as Channel,
  M as HEARTBEAT_INTERVAL,
  I as HEARTBEAT_MAX_LATENCY,
  d as PostMessageTransport,
  u as WebsocketTransport,
  ve as createBrowserChannel,
  ye as default
};
