"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.BORDER_SUPPORT_KEY = void 0;
exports.BorderPanel = BorderPanel;
exports.default = exports.SHADOW_SUPPORT_KEY = void 0;
exports.getBorderClasses = getBorderClasses;
exports.getMultiOriginColor = void 0;
exports.hasBorderSupport = hasBorderSupport;
exports.hasShadowSupport = hasShadowSupport;
exports.removeBorderAttribute = removeBorderAttribute;
exports.useBorderPanelLabel = useBorderPanelLabel;
var _clsx = _interopRequireDefault(require("clsx"));
var _blocks = require("@wordpress/blocks");
var _components = require("@wordpress/components");
var _element = require("@wordpress/element");
var _hooks = require("@wordpress/hooks");
var _data = require("@wordpress/data");
var _colors = require("../components/colors");
var _inspectorControls = _interopRequireDefault(require("../components/inspector-controls"));
var _useMultipleOriginColorsAndGradients = _interopRequireDefault(require("../components/colors-gradients/use-multiple-origin-colors-and-gradients"));
var _utils = require("./utils");
var _globalStyles = require("../components/global-styles");
var _store = require("../store");
var _i18n = require("@wordpress/i18n");
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const BORDER_SUPPORT_KEY = exports.BORDER_SUPPORT_KEY = '__experimentalBorder';
const SHADOW_SUPPORT_KEY = exports.SHADOW_SUPPORT_KEY = 'shadow';
const getColorByProperty = (colors, property, value) => {
  let matchedColor;
  colors.some(origin => origin.colors.some(color => {
    if (color[property] === value) {
      matchedColor = color;
      return true;
    }
    return false;
  }));
  return matchedColor;
};
const getMultiOriginColor = ({
  colors,
  namedColor,
  customColor
}) => {
  // Search each origin (default, theme, or user) for matching color by name.
  if (namedColor) {
    const colorObject = getColorByProperty(colors, 'slug', namedColor);
    if (colorObject) {
      return colorObject;
    }
  }

  // Skip if no custom color or matching named color.
  if (!customColor) {
    return {
      color: undefined
    };
  }

  // Attempt to find color via custom color value or build new object.
  const colorObject = getColorByProperty(colors, 'color', customColor);
  return colorObject ? colorObject : {
    color: customColor
  };
};
exports.getMultiOriginColor = getMultiOriginColor;
function getColorSlugFromVariable(value) {
  const namedColor = /var:preset\|color\|(.+)/.exec(value);
  if (namedColor && namedColor[1]) {
    return namedColor[1];
  }
  return null;
}
function styleToAttributes(style) {
  if ((0, _components.__experimentalHasSplitBorders)(style?.border)) {
    return {
      style,
      borderColor: undefined
    };
  }
  const borderColorValue = style?.border?.color;
  const borderColorSlug = borderColorValue?.startsWith('var:preset|color|') ? borderColorValue.substring('var:preset|color|'.length) : undefined;
  const updatedStyle = {
    ...style
  };
  updatedStyle.border = {
    ...updatedStyle.border,
    color: borderColorSlug ? undefined : borderColorValue
  };
  return {
    style: (0, _utils.cleanEmptyObject)(updatedStyle),
    borderColor: borderColorSlug
  };
}
function attributesToStyle(attributes) {
  if ((0, _components.__experimentalHasSplitBorders)(attributes.style?.border)) {
    return attributes.style;
  }
  return {
    ...attributes.style,
    border: {
      ...attributes.style?.border,
      color: attributes.borderColor ? 'var:preset|color|' + attributes.borderColor : attributes.style?.border?.color
    }
  };
}
function BordersInspectorControl({
  label,
  children,
  resetAllFilter
}) {
  const attributesResetAllFilter = (0, _element.useCallback)(attributes => {
    const existingStyle = attributesToStyle(attributes);
    const updatedStyle = resetAllFilter(existingStyle);
    return {
      ...attributes,
      ...styleToAttributes(updatedStyle)
    };
  }, [resetAllFilter]);
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_inspectorControls.default, {
    group: "border",
    resetAllFilter: attributesResetAllFilter,
    label: label,
    children: children
  });
}
function BorderPanel({
  clientId,
  name,
  setAttributes,
  settings
}) {
  const isEnabled = (0, _globalStyles.useHasBorderPanel)(settings);
  function selector(select) {
    const {
      style,
      borderColor
    } = select(_store.store).getBlockAttributes(clientId) || {};
    return {
      style,
      borderColor
    };
  }
  const {
    style,
    borderColor
  } = (0, _data.useSelect)(selector, [clientId]);
  const value = (0, _element.useMemo)(() => {
    return attributesToStyle({
      style,
      borderColor
    });
  }, [style, borderColor]);
  const onChange = newStyle => {
    setAttributes(styleToAttributes(newStyle));
  };
  if (!isEnabled) {
    return null;
  }
  const defaultControls = {
    ...(0, _blocks.getBlockSupport)(name, [BORDER_SUPPORT_KEY, '__experimentalDefaultControls']),
    ...(0, _blocks.getBlockSupport)(name, [SHADOW_SUPPORT_KEY, '__experimentalDefaultControls'])
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_globalStyles.BorderPanel, {
    as: BordersInspectorControl,
    panelId: clientId,
    settings: settings,
    value: value,
    onChange: onChange,
    defaultControls: defaultControls
  });
}

/**
 * Determine whether there is block support for border properties.
 *
 * @param {string} blockName Block name.
 * @param {string} feature   Border feature to check support for.
 *
 * @return {boolean} Whether there is support.
 */
function hasBorderSupport(blockName, feature = 'any') {
  if (_element.Platform.OS !== 'web') {
    return false;
  }
  const support = (0, _blocks.getBlockSupport)(blockName, BORDER_SUPPORT_KEY);
  if (support === true) {
    return true;
  }
  if (feature === 'any') {
    return !!(support?.color || support?.radius || support?.width || support?.style);
  }
  return !!support?.[feature];
}

/**
 * Determine whether there is block support for shadow properties.
 *
 * @param {string} blockName Block name.
 *
 * @return {boolean} Whether there is support.
 */
function hasShadowSupport(blockName) {
  return (0, _blocks.hasBlockSupport)(blockName, SHADOW_SUPPORT_KEY);
}
function useBorderPanelLabel({
  blockName,
  hasBorderControl,
  hasShadowControl
} = {}) {
  const settings = (0, _utils.useBlockSettings)(blockName);
  const controls = (0, _globalStyles.useHasBorderPanelControls)(settings);
  if (!hasBorderControl && !hasShadowControl && blockName) {
    hasBorderControl = controls?.hasBorderColor || controls?.hasBorderStyle || controls?.hasBorderWidth || controls?.hasBorderRadius;
    hasShadowControl = controls?.hasShadow;
  }
  if (hasBorderControl && hasShadowControl) {
    return (0, _i18n.__)('Border & Shadow');
  }
  if (hasShadowControl) {
    return (0, _i18n.__)('Shadow');
  }
  return (0, _i18n.__)('Border');
}

/**
 * Returns a new style object where the specified border attribute has been
 * removed.
 *
 * @param {Object} style     Styles from block attributes.
 * @param {string} attribute The border style attribute to clear.
 *
 * @return {Object} Style object with the specified attribute removed.
 */
function removeBorderAttribute(style, attribute) {
  return (0, _utils.cleanEmptyObject)({
    ...style,
    border: {
      ...style?.border,
      [attribute]: undefined
    }
  });
}

/**
 * Filters registered block settings, extending attributes to include
 * `borderColor` if needed.
 *
 * @param {Object} settings Original block settings.
 *
 * @return {Object} Updated block settings.
 */
function addAttributes(settings) {
  if (!hasBorderSupport(settings, 'color')) {
    return settings;
  }

  // Allow blocks to specify default value if needed.
  if (settings.attributes.borderColor) {
    return settings;
  }

  // Add new borderColor attribute to block settings.
  return {
    ...settings,
    attributes: {
      ...settings.attributes,
      borderColor: {
        type: 'string'
      }
    }
  };
}

/**
 * Override props assigned to save component to inject border color.
 *
 * @param {Object}        props           Additional props applied to save element.
 * @param {Object|string} blockNameOrType Block type definition.
 * @param {Object}        attributes      Block's attributes.
 *
 * @return {Object} Filtered props to apply to save element.
 */
function addSaveProps(props, blockNameOrType, attributes) {
  if (!hasBorderSupport(blockNameOrType, 'color') || (0, _utils.shouldSkipSerialization)(blockNameOrType, BORDER_SUPPORT_KEY, 'color')) {
    return props;
  }
  const borderClasses = getBorderClasses(attributes);
  const newClassName = (0, _clsx.default)(props.className, borderClasses);

  // If we are clearing the last of the previous classes in `className`
  // set it to `undefined` to avoid rendering empty DOM attributes.
  props.className = newClassName ? newClassName : undefined;
  return props;
}

/**
 * Generates a CSS class name consisting of all the applicable border color
 * classes given the current block attributes.
 *
 * @param {Object} attributes Block's attributes.
 *
 * @return {string} CSS class name.
 */
function getBorderClasses(attributes) {
  const {
    borderColor,
    style
  } = attributes;
  const borderColorClass = (0, _colors.getColorClassName)('border-color', borderColor);
  return (0, _clsx.default)({
    'has-border-color': borderColor || style?.border?.color,
    [borderColorClass]: !!borderColorClass
  });
}
function useBlockProps({
  name,
  borderColor,
  style
}) {
  const {
    colors
  } = (0, _useMultipleOriginColorsAndGradients.default)();
  if (!hasBorderSupport(name, 'color') || (0, _utils.shouldSkipSerialization)(name, BORDER_SUPPORT_KEY, 'color')) {
    return {};
  }
  const {
    color: borderColorValue
  } = getMultiOriginColor({
    colors,
    namedColor: borderColor
  });
  const {
    color: borderTopColor
  } = getMultiOriginColor({
    colors,
    namedColor: getColorSlugFromVariable(style?.border?.top?.color)
  });
  const {
    color: borderRightColor
  } = getMultiOriginColor({
    colors,
    namedColor: getColorSlugFromVariable(style?.border?.right?.color)
  });
  const {
    color: borderBottomColor
  } = getMultiOriginColor({
    colors,
    namedColor: getColorSlugFromVariable(style?.border?.bottom?.color)
  });
  const {
    color: borderLeftColor
  } = getMultiOriginColor({
    colors,
    namedColor: getColorSlugFromVariable(style?.border?.left?.color)
  });
  const extraStyles = {
    borderTopColor: borderTopColor || borderColorValue,
    borderRightColor: borderRightColor || borderColorValue,
    borderBottomColor: borderBottomColor || borderColorValue,
    borderLeftColor: borderLeftColor || borderColorValue
  };
  return addSaveProps({
    style: (0, _utils.cleanEmptyObject)(extraStyles) || {}
  }, name, {
    borderColor,
    style
  });
}
var _default = exports.default = {
  useBlockProps,
  addSaveProps,
  attributeKeys: ['borderColor', 'style'],
  hasSupport(name) {
    return hasBorderSupport(name, 'color');
  }
};
(0, _hooks.addFilter)('blocks.registerBlockType', 'core/border/addAttributes', addAttributes);
//# sourceMappingURL=border.js.map