var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};
var __accessCheck = (obj, member, msg) => {
  if (!member.has(obj))
    throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
  __accessCheck(obj, member, "read from private field");
  return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
  if (member.has(obj))
    throw TypeError("Cannot add the same private member more than once");
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
  __accessCheck(obj, member, "write to private field");
  setter ? setter.call(obj, value) : member.set(obj, value);
  return value;
};
var __privateMethod = (obj, member, method) => {
  __accessCheck(obj, member, "access private method");
  return method;
};
var _loadRequested, _hasLoaded, _iframe, _playerState, _currentTime, _muted, _volume, _paused, _seeking, _readyState, _config, _onMessage, _sendCommand, sendCommand_fn, _upgradeProperty, upgradeProperty_fn;
import { J as React } from "./index-B1wc0Lcg.js";
const EMBED_BASE = "https://player.twitch.tv";
const MATCH_VIDEO = /(?:www\.|go\.)?twitch\.tv\/(?:videos?\/|\?video=)(\d+)($|\?)/;
const MATCH_CHANNEL = /(?:www\.|go\.)?twitch\.tv\/([a-zA-Z0-9_]+)($|\?)/;
const PlaybackState = {
  IDLE: "Idle",
  ENDED: "Ended"
};
const PlayerCommands = {
  PAUSE: 2,
  PLAY: 3,
  SEEK: 4,
  SET_MUTED: 10,
  SET_VOLUME: 11
};
function getTemplateHTML(attrs, props = {}) {
  const iframeAttrs = {
    src: serializeIframeUrl(attrs, props),
    frameborder: "0",
    width: "100%",
    height: "100%",
    allow: "accelerometer; fullscreen; autoplay; encrypted-media; picture-in-picture;",
    sandbox: "allow-modals allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",
    scrolling: "no"
  };
  if (props.config) {
    iframeAttrs["data-config"] = JSON.stringify(props.config);
  }
  return (
    /*html*/
    `
    <style>
      :host {
        display: inline-block;
        min-width: 300px;
        min-height: 150px;
        position: relative;
      }
      iframe {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
      }
      :host(:not([controls])) {
        pointer-events: none;
      }
    </style>
    <iframe${serializeAttributes(iframeAttrs)}></iframe>
  `
  );
}
function serializeIframeUrl(attrs, props) {
  var _a;
  if (!attrs.src)
    return;
  const videoMatch = attrs.src.match(MATCH_VIDEO);
  const channelMatch = attrs.src.match(MATCH_CHANNEL);
  const params = {
    parent: (_a = globalThis.location) == null ? void 0 : _a.hostname,
    // ?controls=true is enabled by default in the iframe
    controls: attrs.controls === "" ? null : false,
    autoplay: attrs.autoplay === "" ? null : false,
    muted: attrs.muted,
    preload: attrs.preload,
    ...props.config
  };
  if (videoMatch) {
    const videoId = videoMatch[1];
    return `${EMBED_BASE}/?video=v${videoId}&${serialize(params)}`;
  } else if (channelMatch) {
    const channel = channelMatch[1];
    return `${EMBED_BASE}/?channel=${channel}&${serialize(params)}`;
  }
  return "";
}
class TwitchVideoElement extends (globalThis.HTMLElement ?? class {
}) {
  constructor() {
    super();
    __privateAdd(this, _sendCommand);
    // This is a pattern to update property values that are set before
    // the custom element is upgraded.
    // https://web.dev/custom-elements-best-practices/#make-properties-lazy
    __privateAdd(this, _upgradeProperty);
    __publicField(this, "loadComplete", new PublicPromise());
    __privateAdd(this, _loadRequested, void 0);
    __privateAdd(this, _hasLoaded, void 0);
    __privateAdd(this, _iframe, void 0);
    __privateAdd(this, _playerState, {});
    __privateAdd(this, _currentTime, 0);
    __privateAdd(this, _muted, false);
    __privateAdd(this, _volume, 1);
    __privateAdd(this, _paused, !this.autoplay);
    __privateAdd(this, _seeking, false);
    __privateAdd(this, _readyState, 0);
    __privateAdd(this, _config, null);
    __privateAdd(this, _onMessage, async (event) => {
      var _a, _b, _c, _d;
      if (!__privateGet(this, _iframe).contentWindow)
        return;
      const { data, source } = event;
      const isFromEmbedWindow = source === __privateGet(this, _iframe).contentWindow;
      if (!isFromEmbedWindow)
        return;
      if (data.namespace === "twitch-embed") {
        await new Promise((resolve) => setTimeout(resolve, 10));
        if (data.eventName === "ready") {
          this.dispatchEvent(new Event("loadcomplete"));
          this.loadComplete.resolve();
          __privateSet(this, _readyState, 1);
          this.dispatchEvent(new Event("loadedmetadata"));
        } else if (data.eventName === "seek") {
          __privateSet(this, _seeking, true);
          this.dispatchEvent(new Event("seeking"));
        } else if (data.eventName === "playing") {
          if (__privateGet(this, _seeking)) {
            __privateSet(this, _seeking, false);
            this.dispatchEvent(new Event("seeked"));
          }
          __privateSet(this, _readyState, 3);
          this.dispatchEvent(new Event("playing"));
        } else {
          this.dispatchEvent(new Event(data.eventName));
        }
      } else if (data.namespace === "twitch-embed-player-proxy" && data.eventName === "UPDATE_STATE") {
        const oldDuration = __privateGet(this, _playerState).duration;
        const oldCurrentTime = __privateGet(this, _playerState).currentTime;
        const oldVolume = __privateGet(this, _playerState).volume;
        const oldMuted = __privateGet(this, _playerState).muted;
        const oldBuffered = (_b = (_a = __privateGet(this, _playerState).stats) == null ? void 0 : _a.videoStats) == null ? void 0 : _b.bufferSize;
        __privateSet(this, _playerState, { ...__privateGet(this, _playerState), ...data.params });
        if (oldDuration !== __privateGet(this, _playerState).duration) {
          this.dispatchEvent(new Event("durationchange"));
        }
        if (oldCurrentTime !== __privateGet(this, _playerState).currentTime) {
          this.dispatchEvent(new Event("timeupdate"));
        }
        if (oldVolume !== __privateGet(this, _playerState).volume || oldMuted !== __privateGet(this, _playerState).muted) {
          this.dispatchEvent(new Event("volumechange"));
        }
        if (oldBuffered !== ((_d = (_c = __privateGet(this, _playerState).stats) == null ? void 0 : _c.videoStats) == null ? void 0 : _d.bufferSize)) {
          this.dispatchEvent(new Event("progress"));
        }
      }
    });
    __privateMethod(this, _upgradeProperty, upgradeProperty_fn).call(this, "config");
  }
  get config() {
    return __privateGet(this, _config);
  }
  set config(value) {
    __privateSet(this, _config, value);
  }
  async load() {
    if (__privateGet(this, _loadRequested))
      return;
    if (!this.shadowRoot) {
      this.attachShadow({ mode: "open" });
    }
    const isFirstLoad = !__privateGet(this, _hasLoaded);
    if (__privateGet(this, _hasLoaded)) {
      this.loadComplete = new PublicPromise();
    }
    __privateSet(this, _hasLoaded, true);
    await __privateSet(this, _loadRequested, Promise.resolve());
    __privateSet(this, _loadRequested, null);
    __privateSet(this, _readyState, 0);
    this.dispatchEvent(new Event("emptied"));
    if (!this.src) {
      this.shadowRoot.innerHTML = "";
      globalThis.removeEventListener("message", __privateGet(this, _onMessage));
      return;
    }
    this.dispatchEvent(new Event("loadstart"));
    let iframe = this.shadowRoot.querySelector("iframe");
    const attrs = namedNodeMapToObject(this.attributes);
    if (isFirstLoad && iframe) {
      __privateSet(this, _config, JSON.parse(iframe.getAttribute("data-config") || "{}"));
    }
    if (!(iframe == null ? void 0 : iframe.src) || iframe.src !== serializeIframeUrl(attrs, this)) {
      this.shadowRoot.innerHTML = getTemplateHTML(attrs, this);
      iframe = this.shadowRoot.querySelector("iframe");
    }
    __privateSet(this, _iframe, iframe);
    globalThis.addEventListener("message", __privateGet(this, _onMessage));
  }
  attributeChangedCallback(attrName, oldValue, newValue) {
    if (oldValue === newValue)
      return;
    switch (attrName) {
      case "src":
      case "controls": {
        this.load();
        break;
      }
    }
  }
  get src() {
    return this.getAttribute("src");
  }
  set src(value) {
    this.setAttribute("src", value);
  }
  get readyState() {
    return __privateGet(this, _readyState);
  }
  get seeking() {
    return __privateGet(this, _seeking);
  }
  get buffered() {
    var _a, _b;
    return createTimeRanges(0, ((_b = (_a = __privateGet(this, _playerState).stats) == null ? void 0 : _a.videoStats) == null ? void 0 : _b.bufferSize) ?? 0);
  }
  get paused() {
    if (!__privateGet(this, _playerState).playback)
      return __privateGet(this, _paused);
    return __privateGet(this, _playerState).playback === PlaybackState.IDLE;
  }
  get ended() {
    if (!__privateGet(this, _playerState).playback)
      return false;
    return __privateGet(this, _playerState).playback === PlaybackState.ENDED;
  }
  get duration() {
    return __privateGet(this, _playerState).duration ?? NaN;
  }
  get autoplay() {
    return this.hasAttribute("autoplay");
  }
  set autoplay(val) {
    if (this.autoplay == val)
      return;
    this.toggleAttribute("autoplay", Boolean(val));
  }
  get controls() {
    return this.hasAttribute("controls");
  }
  set controls(val) {
    if (this.controls == val)
      return;
    this.toggleAttribute("controls", Boolean(val));
  }
  get currentTime() {
    if (!__privateGet(this, _playerState).currentTime)
      return __privateGet(this, _currentTime);
    return __privateGet(this, _playerState).currentTime;
  }
  set currentTime(val) {
    __privateSet(this, _currentTime, val);
    this.loadComplete.then(() => {
      __privateMethod(this, _sendCommand, sendCommand_fn).call(this, PlayerCommands.SEEK, val);
    });
  }
  get defaultMuted() {
    return this.hasAttribute("muted");
  }
  set defaultMuted(val) {
    this.toggleAttribute("muted", Boolean(val));
  }
  get loop() {
    return this.hasAttribute("loop");
  }
  set loop(val) {
    this.toggleAttribute("loop", Boolean(val));
  }
  get muted() {
    return __privateGet(this, _muted);
  }
  set muted(val) {
    __privateSet(this, _muted, val);
    this.loadComplete.then(() => {
      __privateMethod(this, _sendCommand, sendCommand_fn).call(this, PlayerCommands.SET_MUTED, val);
    });
  }
  get volume() {
    return __privateGet(this, _volume);
  }
  set volume(val) {
    __privateSet(this, _volume, val);
    this.loadComplete.then(() => {
      __privateMethod(this, _sendCommand, sendCommand_fn).call(this, PlayerCommands.SET_VOLUME, val);
    });
  }
  get playsInline() {
    return this.hasAttribute("playsinline");
  }
  set playsInline(val) {
    this.toggleAttribute("playsinline", Boolean(val));
  }
  play() {
    __privateSet(this, _paused, false);
    __privateMethod(this, _sendCommand, sendCommand_fn).call(this, PlayerCommands.PLAY);
  }
  pause() {
    __privateSet(this, _paused, true);
    __privateMethod(this, _sendCommand, sendCommand_fn).call(this, PlayerCommands.PAUSE);
  }
}
_loadRequested = new WeakMap();
_hasLoaded = new WeakMap();
_iframe = new WeakMap();
_playerState = new WeakMap();
_currentTime = new WeakMap();
_muted = new WeakMap();
_volume = new WeakMap();
_paused = new WeakMap();
_seeking = new WeakMap();
_readyState = new WeakMap();
_config = new WeakMap();
_onMessage = new WeakMap();
_sendCommand = new WeakSet();
sendCommand_fn = function(command, params) {
  if (!__privateGet(this, _iframe).contentWindow)
    return;
  const message = {
    eventName: command,
    params,
    namespace: "twitch-embed-player-proxy"
  };
  __privateGet(this, _iframe).contentWindow.postMessage(message, EMBED_BASE);
};
_upgradeProperty = new WeakSet();
upgradeProperty_fn = function(prop) {
  if (Object.prototype.hasOwnProperty.call(this, prop)) {
    const value = this[prop];
    delete this[prop];
    this[prop] = value;
  }
};
__publicField(TwitchVideoElement, "getTemplateHTML", getTemplateHTML);
__publicField(TwitchVideoElement, "shadowRootOptions", { mode: "open" });
__publicField(TwitchVideoElement, "observedAttributes", ["autoplay", "controls", "loop", "muted", "playsinline", "preload", "src"]);
function namedNodeMapToObject(namedNodeMap) {
  let obj = {};
  for (let attr of namedNodeMap) {
    obj[attr.name] = attr.value;
  }
  return obj;
}
function serializeAttributes(attrs) {
  let html = "";
  for (const key in attrs) {
    const value = attrs[key];
    if (value === "")
      html += ` ${escapeHtml(key)}`;
    else
      html += ` ${escapeHtml(key)}="${escapeHtml(`${value}`)}"`;
  }
  return html;
}
function escapeHtml(str) {
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/`/g, "&#x60;");
}
function serialize(props) {
  return String(new URLSearchParams(filterParams(props)));
}
function filterParams(props) {
  let p = {};
  for (let key in props) {
    let val = props[key];
    if (val === true || val === "")
      p[key] = true;
    else if (val === false)
      p[key] = false;
    else if (val != null)
      p[key] = val;
  }
  return p;
}
class PublicPromise extends Promise {
  constructor(executor = () => {
  }) {
    let res, rej;
    super((resolve, reject) => {
      executor(resolve, reject);
      res = resolve;
      rej = reject;
    });
    this.resolve = res;
    this.reject = rej;
  }
}
function createTimeRanges(start, end) {
  if (Array.isArray(start)) {
    return createTimeRangesObj(start);
  } else if (end == null || end === 0) {
    return createTimeRangesObj([[0, 0]]);
  }
  return createTimeRangesObj([[start, end]]);
}
function createTimeRangesObj(ranges) {
  Object.defineProperties(ranges, {
    start: {
      value: (i) => ranges[i][0]
    },
    end: {
      value: (i) => ranges[i][1]
    }
  });
  return ranges;
}
if (globalThis.customElements && !globalThis.customElements.get("twitch-video")) {
  globalThis.customElements.define("twitch-video", TwitchVideoElement);
}
var twitch_video_element_default = TwitchVideoElement;
var reservedReactProps = /* @__PURE__ */ new Set([
  "style",
  "children",
  "ref",
  "key",
  "suppressContentEditableWarning",
  "suppressHydrationWarning",
  "dangerouslySetInnerHTML"
]);
var reactPropToAttrNameMap = {
  className: "class",
  htmlFor: "for"
};
function defaultToAttributeName(propName) {
  return propName.toLowerCase();
}
function defaultToAttributeValue(propValue) {
  if (typeof propValue === "boolean")
    return propValue ? "" : void 0;
  if (typeof propValue === "function")
    return void 0;
  if (typeof propValue === "object" && propValue !== null)
    return void 0;
  return propValue;
}
function createComponent({
  react: React2,
  tagName,
  elementClass,
  events,
  displayName,
  defaultProps,
  toAttributeName = defaultToAttributeName,
  toAttributeValue = defaultToAttributeValue
}) {
  const IS_REACT_19_OR_NEWER = Number.parseInt(React2.version) >= 19;
  const ReactComponent = React2.forwardRef((props, ref) => {
    var _a, _b;
    const elementRef = React2.useRef(null);
    const prevElemPropsRef = React2.useRef(/* @__PURE__ */ new Map());
    const eventProps = {};
    const attrs = {};
    const reactProps = {};
    const elementProps = {};
    for (const [k, v] of Object.entries(props)) {
      if (reservedReactProps.has(k)) {
        reactProps[k] = v;
        continue;
      }
      const attrName = toAttributeName(reactPropToAttrNameMap[k] ?? k);
      if (k in elementClass.prototype && !(k in (((_a = globalThis.HTMLElement) == null ? void 0 : _a.prototype) ?? {})) && !((_b = elementClass.observedAttributes) == null ? void 0 : _b.some((attr) => attr === attrName))) {
        elementProps[k] = v;
        continue;
      }
      if (k.startsWith("on")) {
        eventProps[k] = v;
        continue;
      }
      const attrValue = toAttributeValue(v);
      if (attrName && attrValue != null) {
        attrs[attrName] = String(attrValue);
        if (!IS_REACT_19_OR_NEWER) {
          reactProps[attrName] = attrValue;
        }
      }
      if (attrName && IS_REACT_19_OR_NEWER) {
        const attrValueFromDefault = defaultToAttributeValue(v);
        if (attrValue !== attrValueFromDefault) {
          reactProps[attrName] = attrValue;
        } else {
          reactProps[attrName] = v;
        }
      }
    }
    if (typeof window !== "undefined") {
      for (const propName in eventProps) {
        const callback = eventProps[propName];
        const useCapture = propName.endsWith("Capture");
        const eventName = ((events == null ? void 0 : events[propName]) ?? propName.slice(2).toLowerCase()).slice(
          0,
          useCapture ? -7 : void 0
        );
        React2.useLayoutEffect(() => {
          const eventTarget = elementRef == null ? void 0 : elementRef.current;
          if (!eventTarget || typeof callback !== "function")
            return;
          eventTarget.addEventListener(eventName, callback, useCapture);
          return () => {
            eventTarget.removeEventListener(eventName, callback, useCapture);
          };
        }, [elementRef == null ? void 0 : elementRef.current, callback]);
      }
      React2.useLayoutEffect(() => {
        if (elementRef.current === null)
          return;
        const newElemProps = /* @__PURE__ */ new Map();
        for (const key in elementProps) {
          setProperty(elementRef.current, key, elementProps[key]);
          prevElemPropsRef.current.delete(key);
          newElemProps.set(key, elementProps[key]);
        }
        for (const [key, _value] of prevElemPropsRef.current) {
          setProperty(elementRef.current, key, void 0);
        }
        prevElemPropsRef.current = newElemProps;
      });
    }
    if (typeof window === "undefined" && (elementClass == null ? void 0 : elementClass.getTemplateHTML) && (elementClass == null ? void 0 : elementClass.shadowRootOptions)) {
      const { mode, delegatesFocus } = elementClass.shadowRootOptions;
      const templateShadowRoot = React2.createElement("template", {
        shadowrootmode: mode,
        shadowrootdelegatesfocus: delegatesFocus,
        dangerouslySetInnerHTML: {
          __html: elementClass.getTemplateHTML(attrs, props)
        }
      });
      reactProps.children = [templateShadowRoot, reactProps.children];
    }
    return React2.createElement(tagName, {
      ...defaultProps,
      ...reactProps,
      ref: React2.useCallback(
        (node) => {
          elementRef.current = node;
          if (typeof ref === "function") {
            ref(node);
          } else if (ref !== null) {
            ref.current = node;
          }
        },
        [ref]
      )
    });
  });
  ReactComponent.displayName = displayName ?? elementClass.name;
  return ReactComponent;
}
function setProperty(node, name, value) {
  var _a;
  node[name] = value;
  if (value == null && name in (((_a = globalThis.HTMLElement) == null ? void 0 : _a.prototype) ?? {})) {
    node.removeAttribute(name);
  }
}
var react_default = createComponent({
  react: React,
  tagName: "twitch-video",
  elementClass: twitch_video_element_default,
  toAttributeName(propName) {
    if (propName === "muted")
      return "";
    if (propName === "defaultMuted")
      return "muted";
    return defaultToAttributeName(propName);
  }
});
/*! Bundled license information:

ce-la-react/dist/ce-la-react.js:
  (**
   * @license
   * Copyright 2018 Google LLC
   * SPDX-License-Identifier: BSD-3-Clause
   *
   * Modified version of `@lit/react` for vanilla custom elements with support for SSR.
   *)
*/
export {
  react_default as default
};
