// packages/block-editor/src/hooks/block-style-variation.js
import { getBlockTypes, store as blocksStore } from "@wordpress/blocks";
import { useSelect } from "@wordpress/data";
import { useMemo } from "@wordpress/element";
import { toStyles, getBlockSelectors } from "@wordpress/global-styles-engine";
import { usePrivateStyleOverride } from "./utils";
import { getValueFromObjectPath } from "../utils/object";
import { store as blockEditorStore } from "../store";
import { globalStylesDataKey } from "../store/private-keys";
import { unlock } from "../lock-unlock";
import { Fragment, jsx } from "react/jsx-runtime";
var VARIATION_PREFIX = "is-style-";
function getVariationMatches(className) {
  if (!className) {
    return [];
  }
  return className.split(/\s+/).reduce((matches, name) => {
    if (name.startsWith(VARIATION_PREFIX)) {
      const match = name.slice(VARIATION_PREFIX.length);
      if (match !== "default") {
        matches.push(match);
      }
    }
    return matches;
  }, []);
}
function getVariationNameFromClass(className, registeredStyles = []) {
  const matches = getVariationMatches(className);
  if (!matches) {
    return null;
  }
  for (const variation of matches) {
    if (registeredStyles.some((style) => style.name === variation)) {
      return variation;
    }
  }
  return null;
}
function OverrideStyles({ override }) {
  usePrivateStyleOverride(override);
}
function __unstableBlockStyleVariationOverridesWithConfig({ config }) {
  const { getBlockStyles, overrides } = useSelect(
    (select) => ({
      getBlockStyles: select(blocksStore).getBlockStyles,
      overrides: unlock(select(blockEditorStore)).getStyleOverrides()
    }),
    []
  );
  const { getBlockName } = useSelect(blockEditorStore);
  const overridesWithConfig = useMemo(() => {
    if (!overrides?.length) {
      return;
    }
    const newOverrides = [];
    const overriddenClientIds = [];
    for (const [, override] of overrides) {
      if (override?.variation && override?.clientId && /*
       * Because this component overwrites existing style overrides,
       * filter out any overrides that are already present in the store.
       */
      !overriddenClientIds.includes(override.clientId)) {
        const blockName = getBlockName(override.clientId);
        const configStyles = config?.styles?.blocks?.[blockName]?.variations?.[override.variation];
        if (configStyles) {
          const variationConfig = {
            settings: config?.settings,
            // The variation style data is all that is needed to generate
            // the styles for the current application to a block. The variation
            // name is updated to match the instance specific class name.
            styles: {
              blocks: {
                [blockName]: {
                  variations: {
                    [`${override.variation}-${override.clientId}`]: configStyles
                  }
                }
              }
            }
          };
          const blockSelectors = getBlockSelectors(
            getBlockTypes(),
            override.clientId
          );
          const hasBlockGapSupport = false;
          const hasFallbackGapSupport = true;
          const disableLayoutStyles = true;
          const disableRootPadding = true;
          const variationStyles = toStyles(
            variationConfig,
            blockSelectors,
            hasBlockGapSupport,
            hasFallbackGapSupport,
            disableLayoutStyles,
            disableRootPadding,
            {
              blockGap: false,
              blockStyles: true,
              layoutStyles: false,
              marginReset: false,
              presets: false,
              rootPadding: false,
              variationStyles: true
            }
          );
          newOverrides.push({
            id: `${override.variation}-${override.clientId}`,
            css: variationStyles,
            __unstableType: "variation",
            variation: override.variation,
            // The clientId will be stored with the override and used to ensure
            // the order of overrides matches the order of blocks so that the
            // correct CSS cascade is maintained.
            clientId: override.clientId
          });
          overriddenClientIds.push(override.clientId);
        }
      }
    }
    return newOverrides;
  }, [config, overrides, getBlockStyles, getBlockName]);
  if (!overridesWithConfig || !overridesWithConfig.length) {
    return;
  }
  return /* @__PURE__ */ jsx(Fragment, { children: overridesWithConfig.map((override) => /* @__PURE__ */ jsx(OverrideStyles, { override }, override.id)) });
}
function getVariationStylesWithRefValues(globalStyles, name, variation) {
  if (!globalStyles?.styles?.blocks?.[name]?.variations?.[variation]) {
    return;
  }
  const replaceRefs = (variationStyles) => {
    Object.keys(variationStyles).forEach((key) => {
      const value = variationStyles[key];
      if (typeof value === "object" && value !== null) {
        if (value.ref !== void 0) {
          if (typeof value.ref !== "string" || value.ref.trim() === "") {
            delete variationStyles[key];
          } else {
            const refValue = getValueFromObjectPath(
              globalStyles,
              value.ref
            );
            if (refValue) {
              variationStyles[key] = refValue;
            } else {
              delete variationStyles[key];
            }
          }
        } else {
          replaceRefs(value);
          if (Object.keys(value).length === 0) {
            delete variationStyles[key];
          }
        }
      }
    });
  };
  const styles = JSON.parse(
    JSON.stringify(
      globalStyles.styles.blocks[name].variations[variation]
    )
  );
  replaceRefs(styles);
  return styles;
}
function useBlockStyleVariation(name, variation, clientId) {
  const { globalSettings, globalStyles } = useSelect((select) => {
    const settings = select(blockEditorStore).getSettings();
    return {
      globalSettings: settings.__experimentalFeatures,
      globalStyles: settings[globalStylesDataKey]
    };
  }, []);
  return useMemo(() => {
    const variationStyles = getVariationStylesWithRefValues(
      {
        settings: globalSettings,
        styles: globalStyles
      },
      name,
      variation
    );
    return {
      settings: globalSettings,
      // The variation style data is all that is needed to generate
      // the styles for the current application to a block. The variation
      // name is updated to match the instance specific class name.
      styles: {
        blocks: {
          [name]: {
            variations: {
              [`${variation}-${clientId}`]: variationStyles
            }
          }
        }
      }
    };
  }, [globalSettings, globalStyles, variation, clientId, name]);
}
function useBlockProps({ name, className, clientId }) {
  const { getBlockStyles } = useSelect(blocksStore);
  const registeredStyles = getBlockStyles(name);
  const variation = getVariationNameFromClass(className, registeredStyles);
  const variationClass = `${VARIATION_PREFIX}${variation}-${clientId}`;
  const { settings, styles } = useBlockStyleVariation(
    name,
    variation,
    clientId
  );
  const variationStyles = useMemo(() => {
    if (!variation) {
      return;
    }
    const variationConfig = { settings, styles };
    const blockSelectors = getBlockSelectors(getBlockTypes(), clientId);
    const hasBlockGapSupport = false;
    const hasFallbackGapSupport = true;
    const disableLayoutStyles = true;
    const disableRootPadding = true;
    return toStyles(
      variationConfig,
      blockSelectors,
      hasBlockGapSupport,
      hasFallbackGapSupport,
      disableLayoutStyles,
      disableRootPadding,
      {
        blockGap: false,
        blockStyles: true,
        layoutStyles: false,
        marginReset: false,
        presets: false,
        rootPadding: false,
        variationStyles: true
      }
    );
  }, [variation, settings, styles, clientId]);
  usePrivateStyleOverride({
    id: `variation-${clientId}`,
    css: variationStyles,
    __unstableType: "variation",
    variation,
    // The clientId will be stored with the override and used to ensure
    // the order of overrides matches the order of blocks so that the
    // correct CSS cascade is maintained.
    clientId
  });
  return variation ? { className: variationClass } : {};
}
var block_style_variation_default = {
  hasSupport: () => true,
  attributeKeys: ["className"],
  isMatch: ({ className }) => getVariationMatches(className).length > 0,
  useBlockProps
};
export {
  __unstableBlockStyleVariationOverridesWithConfig,
  block_style_variation_default as default,
  getVariationStylesWithRefValues
};
//# sourceMappingURL=block-style-variation.js.map
