"use client";
import {
  Box
} from "./chunk-7GWX2ZS4.js";
import {
  logger
} from "./chunk-UUHGOBKZ.js";

// src/components/AsyncImage/useAsyncImage.ts
import { useEffect, useReducer } from "react";
var cachedUrls = /* @__PURE__ */ new Map();
var cachedRequestPromises = /* @__PURE__ */ new Map();
async function loadAsyncImage(asyncImage) {
  const cachedRequestPromise = cachedRequestPromises.get(asyncImage);
  if (cachedRequestPromise) {
    return cachedRequestPromise;
  }
  const load = async () => asyncImage().then(async (url) => {
    cachedUrls.set(asyncImage, url);
    return url;
  });
  const requestPromise = load().catch(async () => {
    return load().catch(() => {
      cachedRequestPromises.delete(asyncImage);
      return void 0;
    });
  });
  cachedRequestPromises.set(asyncImage, requestPromise);
  return requestPromise;
}
function useForceUpdate() {
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
  return forceUpdate;
}
function useAsyncImage(url) {
  const cachedUrl = typeof url === "function" ? cachedUrls.get(url) : void 0;
  const forceUpdate = useForceUpdate();
  useEffect(() => {
    if (typeof url === "function" && !cachedUrl) {
      loadAsyncImage(url).then(forceUpdate);
    }
  }, [url, cachedUrl, forceUpdate]);
  return typeof url === "function" ? cachedUrl : url;
}
var REMOTE_IMG_CACHE = /* @__PURE__ */ new Set();
function preloadRemoteImages(...imageUrls) {
  for (const imageUrl of imageUrls) {
    try {
      const { protocol } = new URL(imageUrl);
      if (protocol !== "https:" && protocol !== "http:") {
        logger.warn("preloadRemoteImages:invalidUrl", {
          message: "Invalid protocol",
          imageUrl
        });
        continue;
      }
      if (!REMOTE_IMG_CACHE.has(imageUrl)) {
        REMOTE_IMG_CACHE.add(imageUrl);
        const preloadImage = new Image();
        preloadImage.src = imageUrl;
      }
    } catch (error) {
      logger.warn("preloadRemoteImages:error", {
        message: "Unable to preload image",
        imageUrl,
        error
      });
    }
  }
}

// src/components/AsyncImage/AsyncImage.tsx
import React, { useMemo, useReducer as useReducer2, useState } from "react";

// src/utils/sanitizeUrl.ts
var SAFE_URL_PROTOCOLS = /* @__PURE__ */ new Set(["https:", "http:"]);
function sanitizeUrl(url) {
  if (!url) {
    return void 0;
  }
  try {
    const parsed = new URL(url);
    if (SAFE_URL_PROTOCOLS.has(parsed.protocol)) {
      return parsed.href;
    }
    return void 0;
  } catch {
    return void 0;
  }
}
function sanitizeCssUrl(url) {
  const safeUrl = sanitizeUrl(url);
  if (!safeUrl) {
    return void 0;
  }
  return safeUrl.replace(/['()\\]/g, (char) => {
    return `%${char.charCodeAt(0).toString(16).padStart(2, "0")}`;
  });
}

// src/components/AsyncImage/AsyncImage.tsx
function useTriggeredOnce() {
  return useReducer2(() => true, false);
}
function AsyncImage({
  alt,
  background,
  borderColor,
  borderRadius,
  boxShadow,
  height,
  useAsImage,
  src: srcProp,
  fallbackSrc,
  fallbackElement,
  width,
  testId
}) {
  const src = useAsyncImage(srcProp || fallbackSrc);
  const isRemoteImage = src !== void 0 && /^(https?|data):/.test(src);
  const [isRemoteImageLoaded, setRemoteImageLoaded] = useTriggeredOnce();
  const [hasError, setHasError] = useState(
    srcProp === void 0 && fallbackSrc === void 0
  );
  const { asyncStyle, imgProps } = useMemo(() => {
    const asyncStyle2 = !useAsImage ? getRemoteImageStyles(isRemoteImage, isRemoteImageLoaded, src) : {};
    if (useAsImage || isRemoteImage) {
      const imgProps2 = {
        as: "img",
        src,
        "aria-hidden": true,
        onError: ({
          currentTarget
        }) => {
          currentTarget.onerror = null;
          if (fallbackSrc !== void 0) {
            currentTarget.src = fallbackSrc;
          } else {
            setHasError(true);
          }
        },
        onLoad: isRemoteImage ? setRemoteImageLoaded : void 0
      };
      return { imgProps: imgProps2, asyncStyle: asyncStyle2 };
    }
    return {
      imgProps: {
        backgroundSize: "cover"
      },
      asyncStyle: {
        ...asyncStyle2,
        // has to be added as a inline style because vanilla-extract doesn't recognize this as a valid style
        backgroundPosition: "center"
      }
    };
  }, [
    fallbackSrc,
    isRemoteImage,
    isRemoteImageLoaded,
    src,
    useAsImage,
    setRemoteImageLoaded
  ]);
  const mainElement = hasError && fallbackElement || /* @__PURE__ */ React.createElement(
    Box,
    {
      ...imgProps,
      height: "full",
      position: "absolute",
      style: {
        WebkitTouchCallout: "none",
        transition: "opacity .15s linear",
        userSelect: "none",
        ...asyncStyle
      },
      width: "full"
    }
  );
  return /* @__PURE__ */ React.createElement(
    Box,
    {
      "aria-label": alt,
      borderRadius,
      boxShadow,
      height: typeof height === "string" ? height : void 0,
      overflow: "hidden",
      position: "relative",
      role: "img",
      style: {
        background,
        height: typeof height === "number" ? height : void 0,
        width: typeof width === "number" ? width : void 0
      },
      width: typeof width === "string" ? width : void 0,
      testId
    },
    mainElement,
    borderColor ? /* @__PURE__ */ React.createElement(
      Box,
      {
        ...typeof borderColor === "object" && "custom" in borderColor ? { style: { borderColor: borderColor.custom } } : { borderColor },
        borderRadius,
        borderStyle: "solid",
        borderWidth: "1",
        height: "full",
        position: "relative",
        width: "full"
      }
    ) : null
  );
}
var getRemoteImageStyles = (isRemoteImage, isRemoteImageLoaded, src) => {
  if (isRemoteImage) {
    return {
      opacity: isRemoteImageLoaded ? 1 : 0
    };
  }
  const safeSrc = sanitizeCssUrl(src);
  return {
    // note the url must have quotation, see https://github.com/evanw/esbuild/issues/1843#issuecomment-1370108070
    backgroundImage: safeSrc ? `url('${safeSrc}')` : void 0,
    backgroundRepeat: "no-repeat",
    opacity: src ? 1 : 0
  };
};

export {
  preloadRemoteImages,
  AsyncImage
};
