"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getAllBlockBindingsSources = getAllBlockBindingsSources;
exports.getBlockBindingsSource = getBlockBindingsSource;
exports.getBootstrappedBlockType = getBootstrappedBlockType;
exports.getSupportedStyles = void 0;
exports.getUnprocessedBlockTypes = getUnprocessedBlockTypes;
exports.hasContentRoleAttribute = void 0;
var _data = require("@wordpress/data");
var _deprecated = _interopRequireDefault(require("@wordpress/deprecated"));
var _selectors = require("./selectors");
var _utils = require("./utils");
var _constants = require("../api/constants");
/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const ROOT_BLOCK_SUPPORTS = ['background', 'backgroundColor', 'color', 'linkColor', 'captionColor', 'buttonColor', 'headingColor', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'lineHeight', 'padding', 'contentSize', 'wideSize', 'blockGap', 'textDecoration', 'textTransform', 'letterSpacing'];

/**
 * Filters the list of supported styles for a given element.
 *
 * @param {string[]}         blockSupports list of supported styles.
 * @param {string|undefined} name          block name.
 * @param {string|undefined} element       element name.
 *
 * @return {string[]} filtered list of supported styles.
 */
function filterElementBlockSupports(blockSupports, name, element) {
  return blockSupports.filter(support => {
    if (support === 'fontSize' && element === 'heading') {
      return false;
    }

    // This is only available for links
    if (support === 'textDecoration' && !name && element !== 'link') {
      return false;
    }

    // This is only available for heading, button, caption and text
    if (support === 'textTransform' && !name && !(['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element) || element === 'button' || element === 'caption' || element === 'text')) {
      return false;
    }

    // This is only available for heading, button, caption and text
    if (support === 'letterSpacing' && !name && !(['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element) || element === 'button' || element === 'caption' || element === 'text')) {
      return false;
    }

    // Text columns is only available for blocks.
    if (support === 'textColumns' && !name) {
      return false;
    }
    return true;
  });
}

/**
 * Returns the list of supported styles for a given block name and element.
 */
const getSupportedStyles = exports.getSupportedStyles = (0, _data.createSelector)((state, name, element) => {
  if (!name) {
    return filterElementBlockSupports(ROOT_BLOCK_SUPPORTS, name, element);
  }
  const blockType = (0, _selectors.getBlockType)(state, name);
  if (!blockType) {
    return [];
  }
  const supportKeys = [];

  // Check for blockGap support.
  // Block spacing support doesn't map directly to a single style property, so needs to be handled separately.
  if (blockType?.supports?.spacing?.blockGap) {
    supportKeys.push('blockGap');
  }

  // check for shadow support
  if (blockType?.supports?.shadow) {
    supportKeys.push('shadow');
  }
  Object.keys(_constants.__EXPERIMENTAL_STYLE_PROPERTY).forEach(styleName => {
    if (!_constants.__EXPERIMENTAL_STYLE_PROPERTY[styleName].support) {
      return;
    }

    // Opting out means that, for certain support keys like background color,
    // blocks have to explicitly set the support value false. If the key is
    // unset, we still enable it.
    if (_constants.__EXPERIMENTAL_STYLE_PROPERTY[styleName].requiresOptOut) {
      if (_constants.__EXPERIMENTAL_STYLE_PROPERTY[styleName].support[0] in blockType.supports && (0, _utils.getValueFromObjectPath)(blockType.supports, _constants.__EXPERIMENTAL_STYLE_PROPERTY[styleName].support) !== false) {
        supportKeys.push(styleName);
        return;
      }
    }
    if ((0, _utils.getValueFromObjectPath)(blockType.supports, _constants.__EXPERIMENTAL_STYLE_PROPERTY[styleName].support, false)) {
      supportKeys.push(styleName);
    }
  });
  return filterElementBlockSupports(supportKeys, name, element);
}, (state, name) => [state.blockTypes[name]]);

/**
 * Returns the bootstrapped block type metadata for a give block name.
 *
 * @param {Object} state Data state.
 * @param {string} name  Block name.
 *
 * @return {Object} Bootstrapped block type metadata for a block.
 */
function getBootstrappedBlockType(state, name) {
  return state.bootstrappedBlockTypes[name];
}

/**
 * Returns all the unprocessed (before applying the `registerBlockType` filter)
 * block type settings as passed during block registration.
 *
 * @param {Object} state Data state.
 *
 * @return {Array} Unprocessed block type settings for all blocks.
 */
function getUnprocessedBlockTypes(state) {
  return state.unprocessedBlockTypes;
}

/**
 * Returns all the block bindings sources registered.
 *
 * @param {Object} state Data state.
 *
 * @return {Object} All the registered sources and their properties.
 */
function getAllBlockBindingsSources(state) {
  return state.blockBindingsSources;
}

/**
 * Returns a specific block bindings source.
 *
 * @param {Object} state      Data state.
 * @param {string} sourceName Name of the source to get.
 *
 * @return {Object} The specific block binding source and its properties.
 */
function getBlockBindingsSource(state, sourceName) {
  return state.blockBindingsSources[sourceName];
}

/**
 * Determines if any of the block type's attributes have
 * the content role attribute.
 *
 * @param {Object} state         Data state.
 * @param {string} blockTypeName Block type name.
 * @return {boolean} Whether block type has content role attribute.
 */
const hasContentRoleAttribute = (state, blockTypeName) => {
  const blockType = (0, _selectors.getBlockType)(state, blockTypeName);
  if (!blockType) {
    return false;
  }
  return Object.values(blockType.attributes).some(({
    role,
    __experimentalRole
  }) => {
    if (role === 'content') {
      return true;
    }
    if (__experimentalRole === 'content') {
      (0, _deprecated.default)('__experimentalRole attribute', {
        since: '6.7',
        version: '6.8',
        alternative: 'role attribute',
        hint: `Check the block.json of the ${blockTypeName} block.`
      });
      return true;
    }
    return false;
  });
};
exports.hasContentRoleAttribute = hasContentRoleAttribute;
//# sourceMappingURL=private-selectors.js.map