// packages/block-editor/src/components/background-image-control/index.js
import clsx from "clsx";
import {
  ToggleControl,
  __experimentalToggleGroupControl as ToggleGroupControl,
  __experimentalToggleGroupControlOption as ToggleGroupControlOption,
  __experimentalUnitControl as UnitControl,
  __experimentalVStack as VStack,
  DropZone,
  FlexItem,
  FocalPointPicker,
  MenuItem,
  VisuallyHidden,
  __experimentalHStack as HStack,
  __experimentalTruncate as Truncate,
  Dropdown,
  Placeholder,
  Spinner,
  __experimentalDropdownContentWrapper as DropdownContentWrapper,
  Button
} from "@wordpress/components";
import { reset as resetIcon } from "@wordpress/icons";
import { __, _x, sprintf } from "@wordpress/i18n";
import { store as noticesStore } from "@wordpress/notices";
import { getFilename } from "@wordpress/url";
import { useRef, useState, useEffect, useMemo } from "@wordpress/element";
import { useDispatch, useSelect } from "@wordpress/data";
import { focus } from "@wordpress/dom";
import { isBlobURL } from "@wordpress/blob";
import { getResolvedValue } from "@wordpress/global-styles-engine";
import { hasBackgroundImageValue } from "../global-styles/background-panel";
import { setImmutably } from "../../utils/object";
import MediaReplaceFlow from "../media-replace-flow";
import { store as blockEditorStore } from "../../store";
import {
  globalStylesDataKey,
  globalStylesLinksDataKey
} from "../../store/private-keys";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var IMAGE_BACKGROUND_TYPE = "image";
var BACKGROUND_POPOVER_PROPS = {
  placement: "left-start",
  offset: 36,
  shift: true,
  className: "block-editor-global-styles-background-panel__popover"
};
var noop = () => {
};
var focusToggleButton = (containerRef) => {
  window.requestAnimationFrame(() => {
    const [toggleButton] = focus.tabbable.find(containerRef?.current);
    if (!toggleButton) {
      return;
    }
    toggleButton.focus();
  });
};
function backgroundSizeHelpText(value) {
  if (value === "cover" || value === void 0) {
    return __("Image covers the space evenly.");
  }
  if (value === "contain") {
    return __("Image is contained without distortion.");
  }
  return __("Image has a fixed width.");
}
var coordsToBackgroundPosition = (value) => {
  if (!value || isNaN(value.x) && isNaN(value.y)) {
    return void 0;
  }
  const x = isNaN(value.x) ? 0.5 : value.x;
  const y = isNaN(value.y) ? 0.5 : value.y;
  return `${x * 100}% ${y * 100}%`;
};
var backgroundPositionToCoords = (value) => {
  if (!value) {
    return { x: void 0, y: void 0 };
  }
  let [x, y] = value.split(" ").map((v) => parseFloat(v) / 100);
  x = isNaN(x) ? void 0 : x;
  y = isNaN(y) ? x : y;
  return { x, y };
};
function InspectorImagePreviewItem({
  as = "span",
  imgUrl,
  toggleProps = {},
  filename,
  label,
  onToggleCallback = noop
}) {
  const { isOpen, ...restToggleProps } = toggleProps;
  useEffect(() => {
    if (typeof isOpen !== "undefined") {
      onToggleCallback(isOpen);
    }
  }, [isOpen, onToggleCallback]);
  const renderPreviewContent = () => {
    return /* @__PURE__ */ jsxs(
      HStack,
      {
        justify: "flex-start",
        as: "span",
        className: "block-editor-global-styles-background-panel__inspector-preview-inner",
        children: [
          imgUrl && /* @__PURE__ */ jsx(
            "span",
            {
              className: "block-editor-global-styles-background-panel__inspector-image-indicator-wrapper",
              "aria-hidden": true,
              children: /* @__PURE__ */ jsx(
                "span",
                {
                  className: "block-editor-global-styles-background-panel__inspector-image-indicator",
                  style: {
                    backgroundImage: `url(${imgUrl})`
                  }
                }
              )
            }
          ),
          /* @__PURE__ */ jsxs(FlexItem, { as: "span", style: imgUrl ? {} : { flexGrow: 1 }, children: [
            /* @__PURE__ */ jsx(
              Truncate,
              {
                numberOfLines: 1,
                className: "block-editor-global-styles-background-panel__inspector-media-replace-title",
                children: label
              }
            ),
            /* @__PURE__ */ jsx(VisuallyHidden, { as: "span", children: imgUrl ? sprintf(
              /* translators: %s: file name */
              __("Background image: %s"),
              filename || label
            ) : __("No background image selected") })
          ] })
        ]
      }
    );
  };
  return as === "button" ? /* @__PURE__ */ jsx(Button, { __next40pxDefaultSize: true, ...restToggleProps, children: renderPreviewContent() }) : renderPreviewContent();
}
function BackgroundControlsPanel({
  label,
  filename,
  url: imgUrl,
  children,
  onToggle: onToggleCallback = noop,
  hasImageValue,
  onReset,
  containerRef
}) {
  if (!hasImageValue) {
    return;
  }
  const imgLabel = label || getFilename(imgUrl) || __("Add background image");
  return /* @__PURE__ */ jsx(
    Dropdown,
    {
      popoverProps: BACKGROUND_POPOVER_PROPS,
      renderToggle: ({ onToggle, isOpen }) => {
        const toggleProps = {
          onClick: onToggle,
          className: "block-editor-global-styles-background-panel__dropdown-toggle",
          "aria-expanded": isOpen,
          "aria-label": __(
            "Background size, position and repeat options."
          ),
          isOpen
        };
        return /* @__PURE__ */ jsxs(Fragment, { children: [
          /* @__PURE__ */ jsx(
            InspectorImagePreviewItem,
            {
              imgUrl,
              filename,
              label: imgLabel,
              toggleProps,
              as: "button",
              onToggleCallback
            }
          ),
          onReset && /* @__PURE__ */ jsx(
            Button,
            {
              __next40pxDefaultSize: true,
              label: __("Reset"),
              className: "block-editor-global-styles-background-panel__reset",
              size: "small",
              icon: resetIcon,
              onClick: () => {
                onReset();
                if (isOpen) {
                  onToggle();
                }
                focusToggleButton(containerRef);
              }
            }
          )
        ] });
      },
      renderContent: () => /* @__PURE__ */ jsx(
        DropdownContentWrapper,
        {
          className: "block-editor-global-styles-background-panel__dropdown-content-wrapper",
          paddingSize: "medium",
          children
        }
      )
    }
  );
}
function LoadingSpinner() {
  return /* @__PURE__ */ jsx(Placeholder, { className: "block-editor-global-styles-background-panel__loading", children: /* @__PURE__ */ jsx(Spinner, {}) });
}
function BackgroundImageControls({
  onChange,
  style,
  inheritedValue,
  onRemoveImage = noop,
  onResetImage = noop,
  displayInPanel,
  defaultValues,
  containerRef
}) {
  const [isUploading, setIsUploading] = useState(false);
  const { getSettings } = useSelect(blockEditorStore);
  const { id, title, url } = style?.background?.backgroundImage || {
    ...inheritedValue?.background?.backgroundImage
  };
  const { createErrorNotice } = useDispatch(noticesStore);
  const onUploadError = (message) => {
    createErrorNotice(message, { type: "snackbar" });
    setIsUploading(false);
  };
  const resetBackgroundImage = () => onChange(
    setImmutably(
      style,
      ["background", "backgroundImage"],
      void 0
    )
  );
  const onSelectMedia = (media) => {
    if (!media || !media.url) {
      resetBackgroundImage();
      setIsUploading(false);
      return;
    }
    if (isBlobURL(media.url)) {
      setIsUploading(true);
      return;
    }
    if (media.media_type && media.media_type !== IMAGE_BACKGROUND_TYPE || !media.media_type && media.type && media.type !== IMAGE_BACKGROUND_TYPE) {
      onUploadError(
        __("Only images can be used as a background image.")
      );
      return;
    }
    const sizeValue = style?.background?.backgroundSize || defaultValues?.backgroundSize;
    const positionValue = style?.background?.backgroundPosition;
    onChange(
      setImmutably(style, ["background"], {
        ...style?.background,
        backgroundImage: {
          url: media.url,
          id: media.id,
          source: "file",
          title: media.title || void 0
        },
        backgroundPosition: (
          /*
           * A background image uploaded and set in the editor receives a default background position of '50% 0',
           * when the background image size is the equivalent of "Tile".
           * This is to increase the chance that the image's focus point is visible.
           * This is in-editor only to assist with the user experience.
           */
          !positionValue && ("auto" === sizeValue || !sizeValue) ? "50% 0" : positionValue
        ),
        backgroundSize: sizeValue
      })
    );
    setIsUploading(false);
    focusToggleButton(containerRef);
  };
  const onFilesDrop = (filesList) => {
    getSettings().mediaUpload({
      allowedTypes: [IMAGE_BACKGROUND_TYPE],
      filesList,
      onFileChange([image]) {
        onSelectMedia(image);
      },
      onError: onUploadError,
      multiple: false
    });
  };
  const hasValue = hasBackgroundImageValue(style);
  const onRemove = () => onChange(
    setImmutably(style, ["background"], {
      backgroundImage: "none"
    })
  );
  const canRemove = !hasValue && hasBackgroundImageValue(inheritedValue);
  const imgLabel = title || getFilename(url) || __("Add background image");
  return /* @__PURE__ */ jsxs("div", { className: "block-editor-global-styles-background-panel__image-tools-panel-item", children: [
    isUploading && /* @__PURE__ */ jsx(LoadingSpinner, {}),
    /* @__PURE__ */ jsx(
      MediaReplaceFlow,
      {
        mediaId: id,
        mediaURL: url,
        allowedTypes: [IMAGE_BACKGROUND_TYPE],
        accept: "image/*",
        onSelect: onSelectMedia,
        popoverProps: {
          className: clsx({
            "block-editor-global-styles-background-panel__media-replace-popover": displayInPanel
          })
        },
        name: /* @__PURE__ */ jsx(
          InspectorImagePreviewItem,
          {
            imgUrl: url,
            filename: title,
            label: imgLabel
          }
        ),
        renderToggle: (props) => /* @__PURE__ */ jsx(Button, { ...props, __next40pxDefaultSize: true }),
        onError: onUploadError,
        onReset: () => {
          focusToggleButton(containerRef);
          onResetImage();
        },
        children: canRemove && /* @__PURE__ */ jsx(
          MenuItem,
          {
            onClick: () => {
              focusToggleButton(containerRef);
              onRemove();
              onRemoveImage();
            },
            children: __("Remove")
          }
        )
      }
    ),
    /* @__PURE__ */ jsx(
      DropZone,
      {
        onFilesDrop,
        label: __("Drop to upload")
      }
    )
  ] });
}
function BackgroundSizeControls({
  onChange,
  style,
  inheritedValue,
  defaultValues
}) {
  const sizeValue = style?.background?.backgroundSize || inheritedValue?.background?.backgroundSize;
  const repeatValue = style?.background?.backgroundRepeat || inheritedValue?.background?.backgroundRepeat;
  const imageValue = style?.background?.backgroundImage?.url || inheritedValue?.background?.backgroundImage?.url;
  const isUploadedImage = style?.background?.backgroundImage?.id;
  const positionValue = style?.background?.backgroundPosition || inheritedValue?.background?.backgroundPosition;
  const attachmentValue = style?.background?.backgroundAttachment || inheritedValue?.background?.backgroundAttachment;
  let currentValueForToggle = !sizeValue && isUploadedImage ? defaultValues?.backgroundSize : sizeValue || "auto";
  currentValueForToggle = !["cover", "contain", "auto"].includes(
    currentValueForToggle
  ) ? "auto" : currentValueForToggle;
  const repeatCheckedValue = !(repeatValue === "no-repeat" || currentValueForToggle === "cover" && repeatValue === void 0);
  const updateBackgroundSize = (next) => {
    let nextRepeat = repeatValue;
    let nextPosition = positionValue;
    if (next === "contain") {
      nextRepeat = "no-repeat";
      nextPosition = void 0;
    }
    if (next === "cover") {
      nextRepeat = void 0;
      nextPosition = void 0;
    }
    if ((currentValueForToggle === "cover" || currentValueForToggle === "contain") && next === "auto") {
      nextRepeat = void 0;
      if (!!style?.background?.backgroundImage?.id) {
        nextPosition = "50% 0";
      }
    }
    if (!next && currentValueForToggle === "auto") {
      next = "auto";
    }
    onChange(
      setImmutably(style, ["background"], {
        ...style?.background,
        backgroundPosition: nextPosition,
        backgroundRepeat: nextRepeat,
        backgroundSize: next
      })
    );
  };
  const updateBackgroundPosition = (next) => {
    onChange(
      setImmutably(
        style,
        ["background", "backgroundPosition"],
        coordsToBackgroundPosition(next)
      )
    );
  };
  const toggleIsRepeated = () => onChange(
    setImmutably(
      style,
      ["background", "backgroundRepeat"],
      repeatCheckedValue === true ? "no-repeat" : "repeat"
    )
  );
  const toggleScrollWithPage = () => onChange(
    setImmutably(
      style,
      ["background", "backgroundAttachment"],
      attachmentValue === "fixed" ? "scroll" : "fixed"
    )
  );
  const backgroundPositionValue = !positionValue && isUploadedImage && "contain" === sizeValue ? defaultValues?.backgroundPosition : positionValue;
  return /* @__PURE__ */ jsxs(VStack, { spacing: 3, className: "single-column", children: [
    /* @__PURE__ */ jsx(
      FocalPointPicker,
      {
        __nextHasNoMarginBottom: true,
        label: __("Focal point"),
        url: imageValue,
        value: backgroundPositionToCoords(backgroundPositionValue),
        onChange: updateBackgroundPosition
      }
    ),
    /* @__PURE__ */ jsx(
      ToggleControl,
      {
        __nextHasNoMarginBottom: true,
        label: __("Fixed background"),
        checked: attachmentValue === "fixed",
        onChange: toggleScrollWithPage
      }
    ),
    /* @__PURE__ */ jsxs(
      ToggleGroupControl,
      {
        __nextHasNoMarginBottom: true,
        size: "__unstable-large",
        label: __("Size"),
        value: currentValueForToggle,
        onChange: updateBackgroundSize,
        isBlock: true,
        help: backgroundSizeHelpText(
          sizeValue || defaultValues?.backgroundSize
        ),
        children: [
          /* @__PURE__ */ jsx(
            ToggleGroupControlOption,
            {
              value: "cover",
              label: _x(
                "Cover",
                "Size option for background image control"
              )
            },
            "cover"
          ),
          /* @__PURE__ */ jsx(
            ToggleGroupControlOption,
            {
              value: "contain",
              label: _x(
                "Contain",
                "Size option for background image control"
              )
            },
            "contain"
          ),
          /* @__PURE__ */ jsx(
            ToggleGroupControlOption,
            {
              value: "auto",
              label: _x(
                "Tile",
                "Size option for background image control"
              )
            },
            "tile"
          )
        ]
      }
    ),
    /* @__PURE__ */ jsxs(HStack, { justify: "flex-start", spacing: 2, as: "span", children: [
      /* @__PURE__ */ jsx(
        UnitControl,
        {
          "aria-label": __("Background image width"),
          onChange: updateBackgroundSize,
          value: sizeValue,
          size: "__unstable-large",
          __unstableInputWidth: "100px",
          min: 0,
          placeholder: __("Auto"),
          disabled: currentValueForToggle !== "auto" || currentValueForToggle === void 0
        }
      ),
      /* @__PURE__ */ jsx(
        ToggleControl,
        {
          __nextHasNoMarginBottom: true,
          label: __("Repeat"),
          checked: repeatCheckedValue,
          onChange: toggleIsRepeated,
          disabled: currentValueForToggle === "cover"
        }
      )
    ] })
  ] });
}
function BackgroundImagePanel({
  value,
  onChange,
  inheritedValue = value,
  settings,
  defaultValues = {}
}) {
  const { globalStyles, _links } = useSelect((select) => {
    const { getSettings } = select(blockEditorStore);
    const _settings = getSettings();
    return {
      globalStyles: _settings[globalStylesDataKey],
      _links: _settings[globalStylesLinksDataKey]
    };
  }, []);
  const resolvedInheritedValue = useMemo(() => {
    const resolvedValues = {
      background: {}
    };
    if (!inheritedValue?.background) {
      return inheritedValue;
    }
    Object.entries(inheritedValue?.background).forEach(
      ([key, backgroundValue]) => {
        resolvedValues.background[key] = getResolvedValue(
          backgroundValue,
          {
            styles: globalStyles,
            _links
          }
        );
      }
    );
    return resolvedValues;
  }, [globalStyles, _links, inheritedValue]);
  const resetBackground = () => onChange(setImmutably(value, ["background"], {}));
  const { title, url } = value?.background?.backgroundImage || {
    ...resolvedInheritedValue?.background?.backgroundImage
  };
  const hasImageValue = hasBackgroundImageValue(value) || hasBackgroundImageValue(resolvedInheritedValue);
  const imageValue = value?.background?.backgroundImage || inheritedValue?.background?.backgroundImage;
  const shouldShowBackgroundImageControls = hasImageValue && "none" !== imageValue && (settings?.background?.backgroundSize || settings?.background?.backgroundPosition || settings?.background?.backgroundRepeat);
  const [isDropDownOpen, setIsDropDownOpen] = useState(false);
  const containerRef = useRef();
  return /* @__PURE__ */ jsx(
    "div",
    {
      ref: containerRef,
      className: clsx(
        "block-editor-global-styles-background-panel__inspector-media-replace-container",
        {
          "is-open": isDropDownOpen
        }
      ),
      children: shouldShowBackgroundImageControls ? /* @__PURE__ */ jsx(
        BackgroundControlsPanel,
        {
          label: title,
          filename: title,
          url,
          onToggle: setIsDropDownOpen,
          hasImageValue,
          onReset: resetBackground,
          containerRef,
          children: /* @__PURE__ */ jsxs(VStack, { spacing: 3, className: "single-column", children: [
            /* @__PURE__ */ jsx(
              BackgroundImageControls,
              {
                onChange,
                style: value,
                inheritedValue: resolvedInheritedValue,
                displayInPanel: true,
                onResetImage: () => {
                  setIsDropDownOpen(false);
                  resetBackground();
                },
                onRemoveImage: () => setIsDropDownOpen(false),
                defaultValues,
                containerRef
              }
            ),
            /* @__PURE__ */ jsx(
              BackgroundSizeControls,
              {
                onChange,
                style: value,
                defaultValues,
                inheritedValue: resolvedInheritedValue
              }
            )
          ] })
        }
      ) : /* @__PURE__ */ jsx(
        BackgroundImageControls,
        {
          onChange,
          style: value,
          inheritedValue: resolvedInheritedValue,
          defaultValues,
          onResetImage: () => {
            setIsDropDownOpen(false);
            resetBackground();
          },
          onRemoveImage: () => setIsDropDownOpen(false),
          containerRef
        }
      )
    }
  );
}
export {
  backgroundPositionToCoords,
  coordsToBackgroundPosition,
  BackgroundImagePanel as default
};
//# sourceMappingURL=index.js.map
