/* wp:polyfill */
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
exports.useBlockHasGlobalStyles = useBlockHasGlobalStyles;
var _blocks = require("@wordpress/blocks");
var _i18n = require("@wordpress/i18n");
var _components = require("@wordpress/components");
var _data = require("@wordpress/data");
var _element = require("@wordpress/element");
var _blockEditor = require("@wordpress/block-editor");
var _compose = require("@wordpress/compose");
var _a11y = require("@wordpress/a11y");
var _variationsPanel = require("./variations/variations-panel");
var _header = _interopRequireDefault(require("./header"));
var _navigationButton = require("./navigation-button");
var _lockUnlock = require("../../lock-unlock");
var _jsxRuntime = require("react/jsx-runtime");
/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const {
  useHasDimensionsPanel,
  useHasTypographyPanel,
  useHasBorderPanel,
  useGlobalSetting,
  useSettingsForBlockElement,
  useHasColorPanel
} = (0, _lockUnlock.unlock)(_blockEditor.privateApis);
function useSortedBlockTypes() {
  const blockItems = (0, _data.useSelect)(select => select(_blocks.store).getBlockTypes(), []);
  // Ensure core blocks are prioritized in the returned results,
  // because third party blocks can be registered earlier than
  // the core blocks (usually by using the `init` action),
  // thus affecting the display order.
  // We don't sort reusable blocks as they are handled differently.
  const groupByType = (blocks, block) => {
    const {
      core,
      noncore
    } = blocks;
    const type = block.name.startsWith('core/') ? core : noncore;
    type.push(block);
    return blocks;
  };
  const {
    core: coreItems,
    noncore: nonCoreItems
  } = blockItems.reduce(groupByType, {
    core: [],
    noncore: []
  });
  return [...coreItems, ...nonCoreItems];
}
function useBlockHasGlobalStyles(blockName) {
  const [rawSettings] = useGlobalSetting('', blockName);
  const settings = useSettingsForBlockElement(rawSettings, blockName);
  const hasTypographyPanel = useHasTypographyPanel(settings);
  const hasColorPanel = useHasColorPanel(settings);
  const hasBorderPanel = useHasBorderPanel(settings);
  const hasDimensionsPanel = useHasDimensionsPanel(settings);
  const hasLayoutPanel = hasBorderPanel || hasDimensionsPanel;
  const hasVariationsPanel = !!(0, _variationsPanel.useBlockVariations)(blockName)?.length;
  const hasGlobalStyles = hasTypographyPanel || hasColorPanel || hasLayoutPanel || hasVariationsPanel;
  return hasGlobalStyles;
}
function BlockMenuItem({
  block
}) {
  const hasBlockMenuItem = useBlockHasGlobalStyles(block.name);
  if (!hasBlockMenuItem) {
    return null;
  }
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_navigationButton.NavigationButtonAsItem, {
    path: '/blocks/' + encodeURIComponent(block.name),
    children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
      justify: "flex-start",
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.BlockIcon, {
        icon: block.icon
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
        children: block.title
      })]
    })
  });
}
function BlockList({
  filterValue
}) {
  const sortedBlockTypes = useSortedBlockTypes();
  const debouncedSpeak = (0, _compose.useDebounce)(_a11y.speak, 500);
  const {
    isMatchingSearchTerm
  } = (0, _data.useSelect)(_blocks.store);
  const filteredBlockTypes = !filterValue ? sortedBlockTypes : sortedBlockTypes.filter(blockType => isMatchingSearchTerm(blockType, filterValue));
  const blockTypesListRef = (0, _element.useRef)();

  // Announce search results on change
  (0, _element.useEffect)(() => {
    if (!filterValue) {
      return;
    }
    // We extract the results from the wrapper div's `ref` because
    // filtered items can contain items that will eventually not
    // render and there is no reliable way to detect when a child
    // will return `null`.
    // TODO: We should find a better way of handling this as it's
    // fragile and depends on the number of rendered elements of `BlockMenuItem`,
    // which is now one.
    // @see https://github.com/WordPress/gutenberg/pull/39117#discussion_r816022116
    const count = blockTypesListRef.current.childElementCount;
    const resultsFoundMessage = (0, _i18n.sprintf)(/* translators: %d: number of results. */
    (0, _i18n._n)('%d result found.', '%d results found.', count), count);
    debouncedSpeak(resultsFoundMessage, count);
  }, [filterValue, debouncedSpeak]);
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    ref: blockTypesListRef,
    className: "edit-site-block-types-item-list",
    children: filteredBlockTypes.map(block => /*#__PURE__*/(0, _jsxRuntime.jsx)(BlockMenuItem, {
      block: block
    }, 'menu-itemblock-' + block.name))
  });
}
const MemoizedBlockList = (0, _element.memo)(BlockList);
function ScreenBlockList() {
  const [filterValue, setFilterValue] = (0, _element.useState)('');
  const deferredFilterValue = (0, _element.useDeferredValue)(filterValue);
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
    children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_header.default, {
      title: (0, _i18n.__)('Blocks'),
      description: (0, _i18n.__)('Customize the appearance of specific blocks and for the whole site.')
    }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.SearchControl, {
      __nextHasNoMarginBottom: true,
      className: "edit-site-block-types-search",
      onChange: setFilterValue,
      value: filterValue,
      label: (0, _i18n.__)('Search'),
      placeholder: (0, _i18n.__)('Search')
    }), /*#__PURE__*/(0, _jsxRuntime.jsx)(MemoizedBlockList, {
      filterValue: deferredFilterValue
    })]
  });
}
var _default = exports.default = ScreenBlockList;
//# sourceMappingURL=screen-block-list.js.map