"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// packages/block-editor/src/components/list-view/block.js
var block_exports = {};
__export(block_exports, {
  default: () => block_default
});
module.exports = __toCommonJS(block_exports);
var import_clsx = __toESM(require("clsx"));
var import_blocks = require("@wordpress/blocks");
var import_components = require("@wordpress/components");
var import_compose = require("@wordpress/compose");
var import_icons = require("@wordpress/icons");
var import_element = require("@wordpress/element");
var import_data = require("@wordpress/data");
var import_i18n = require("@wordpress/i18n");
var import_keycodes = require("@wordpress/keycodes");
var import_is_shallow_equal = __toESM(require("@wordpress/is-shallow-equal"));
var import_keyboard_shortcuts = require("@wordpress/keyboard-shortcuts");
var import_a11y = require("@wordpress/a11y");
var import_leaf = __toESM(require("./leaf"));
var import_use_list_view_scroll_into_view = __toESM(require("./use-list-view-scroll-into-view"));
var import_button = require("../block-mover/button");
var import_block_contents = __toESM(require("./block-contents"));
var import_context = require("./context");
var import_utils = require("./utils");
var import_store = require("../../store");
var import_use_block_display_information = __toESM(require("../use-block-display-information"));
var import_block_lock = require("../block-lock");
var import_aria_referenced_text = __toESM(require("./aria-referenced-text"));
var import_lock_unlock = require("../../lock-unlock");
var import_use_paste_styles = __toESM(require("../use-paste-styles"));
var import_utils2 = require("../../hooks/utils");
var import_jsx_runtime = require("react/jsx-runtime");
function ListViewBlock({
  block: { clientId },
  displacement,
  isAfterDraggedBlocks,
  isDragged,
  isNesting,
  isSelected,
  isBranchSelected,
  selectBlock,
  position,
  level,
  rowCount,
  siblingBlockCount,
  showBlockMovers,
  path,
  isExpanded,
  selectedClientIds,
  isSyncedBranch
}) {
  const cellRef = (0, import_element.useRef)(null);
  const rowRef = (0, import_element.useRef)(null);
  const settingsRef = (0, import_element.useRef)(null);
  const [isHovered, setIsHovered] = (0, import_element.useState)(false);
  const [settingsAnchorRect, setSettingsAnchorRect] = (0, import_element.useState)();
  const { isLocked } = (0, import_block_lock.useBlockLock)(clientId);
  const isFirstSelectedBlock = isSelected && selectedClientIds[0] === clientId;
  const isLastSelectedBlock = isSelected && selectedClientIds[selectedClientIds.length - 1] === clientId;
  const {
    toggleBlockHighlight,
    duplicateBlocks,
    multiSelect,
    replaceBlocks,
    removeBlocks,
    insertAfterBlock,
    insertBeforeBlock,
    setOpenedBlockSettingsMenu,
    updateBlockAttributes
  } = (0, import_lock_unlock.unlock)((0, import_data.useDispatch)(import_store.store));
  const debouncedToggleBlockHighlight = (0, import_compose.useDebounce)(
    toggleBlockHighlight,
    50
  );
  const {
    canInsertBlockType,
    getSelectedBlockClientIds,
    getPreviousBlockClientId,
    getBlockRootClientId,
    getBlockOrder,
    getBlockParents,
    getBlocksByClientId,
    canEditBlock,
    canMoveBlock,
    canRemoveBlocks,
    isGroupable
  } = (0, import_data.useSelect)(import_store.store);
  const { getGroupingBlockName } = (0, import_data.useSelect)(import_blocks.store);
  const blockInformation = (0, import_use_block_display_information.default)(clientId);
  const pasteStyles = (0, import_use_paste_styles.default)();
  const { block, blockName, allowRightClickOverrides, isBlockHidden } = (0, import_data.useSelect)(
    (select) => {
      const { getBlock, getBlockName, getSettings } = select(import_store.store);
      const { isBlockHidden: _isBlockHidden } = (0, import_lock_unlock.unlock)(
        select(import_store.store)
      );
      return {
        block: getBlock(clientId),
        blockName: getBlockName(clientId),
        allowRightClickOverrides: getSettings().allowRightClickOverrides,
        isBlockHidden: _isBlockHidden(clientId)
      };
    },
    [clientId]
  );
  const showBlockActions = (
    // When a block hides its toolbar it also hides the block settings menu,
    // since that menu is part of the toolbar in the editor canvas.
    // List View respects this by also hiding the block settings menu.
    (0, import_blocks.hasBlockSupport)(blockName, "__experimentalToolbar", true)
  );
  const instanceId = (0, import_compose.useInstanceId)(ListViewBlock);
  const descriptionId = `list-view-block-select-button__description-${instanceId}`;
  const {
    expand,
    collapse,
    collapseAll,
    BlockSettingsMenu,
    listViewInstanceId,
    expandedState,
    setInsertedBlock,
    treeGridElementRef,
    rootClientId
  } = (0, import_context.useListViewContext)();
  const isMatch = (0, import_keyboard_shortcuts.__unstableUseShortcutEventMatch)();
  function getBlocksToUpdate() {
    const selectedBlockClientIds = getSelectedBlockClientIds();
    const isUpdatingSelectedBlocks = selectedBlockClientIds.includes(clientId);
    const firstBlockClientId = isUpdatingSelectedBlocks ? selectedBlockClientIds[0] : clientId;
    const firstBlockRootClientId = getBlockRootClientId(firstBlockClientId);
    const blocksToUpdate = isUpdatingSelectedBlocks ? selectedBlockClientIds : [clientId];
    return {
      blocksToUpdate,
      firstBlockClientId,
      firstBlockRootClientId,
      selectedBlockClientIds
    };
  }
  async function onKeyDown(event) {
    if (event.defaultPrevented) {
      return;
    }
    if (event.target.closest("[role=dialog]")) {
      return;
    }
    const isDeleteKey = [import_keycodes.BACKSPACE, import_keycodes.DELETE].includes(event.keyCode);
    if (isMatch("core/block-editor/unselect", event) && selectedClientIds.length > 0) {
      event.stopPropagation();
      event.preventDefault();
      selectBlock(event, void 0);
    } else if (isDeleteKey || isMatch("core/block-editor/remove", event)) {
      const {
        blocksToUpdate: blocksToDelete,
        firstBlockClientId,
        firstBlockRootClientId,
        selectedBlockClientIds
      } = getBlocksToUpdate();
      if (!canRemoveBlocks(blocksToDelete)) {
        return;
      }
      let blockToFocus = getPreviousBlockClientId(firstBlockClientId) ?? // If the previous block is not found (when the first block is deleted),
      // fallback to focus the parent block.
      firstBlockRootClientId;
      removeBlocks(blocksToDelete, false);
      const shouldUpdateSelection = selectedBlockClientIds.length > 0 && getSelectedBlockClientIds().length === 0;
      if (!blockToFocus) {
        blockToFocus = getBlockOrder()[0];
      }
      updateFocusAndSelection(blockToFocus, shouldUpdateSelection);
    } else if (isMatch("core/block-editor/paste-styles", event)) {
      event.preventDefault();
      const { blocksToUpdate } = getBlocksToUpdate();
      const blocks = getBlocksByClientId(blocksToUpdate);
      pasteStyles(blocks);
    } else if (isMatch("core/block-editor/duplicate", event)) {
      event.preventDefault();
      const { blocksToUpdate, firstBlockRootClientId } = getBlocksToUpdate();
      const canDuplicate = getBlocksByClientId(blocksToUpdate).every(
        (blockToUpdate) => {
          return !!blockToUpdate && (0, import_blocks.hasBlockSupport)(
            blockToUpdate.name,
            "multiple",
            true
          ) && canInsertBlockType(
            blockToUpdate.name,
            firstBlockRootClientId
          );
        }
      );
      if (canDuplicate) {
        const updatedBlocks = await duplicateBlocks(
          blocksToUpdate,
          false
        );
        if (updatedBlocks?.length) {
          updateFocusAndSelection(updatedBlocks[0], false);
        }
      }
    } else if (isMatch("core/block-editor/insert-before", event)) {
      event.preventDefault();
      const { blocksToUpdate } = getBlocksToUpdate();
      await insertBeforeBlock(blocksToUpdate[0]);
      const newlySelectedBlocks = getSelectedBlockClientIds();
      setOpenedBlockSettingsMenu(void 0);
      updateFocusAndSelection(newlySelectedBlocks[0], false);
    } else if (isMatch("core/block-editor/insert-after", event)) {
      event.preventDefault();
      const { blocksToUpdate } = getBlocksToUpdate();
      await insertAfterBlock(blocksToUpdate.at(-1));
      const newlySelectedBlocks = getSelectedBlockClientIds();
      setOpenedBlockSettingsMenu(void 0);
      updateFocusAndSelection(newlySelectedBlocks[0], false);
    } else if (isMatch("core/block-editor/select-all", event)) {
      event.preventDefault();
      const { firstBlockRootClientId, selectedBlockClientIds } = getBlocksToUpdate();
      const blockClientIds = getBlockOrder(firstBlockRootClientId);
      if (!blockClientIds.length) {
        return;
      }
      if ((0, import_is_shallow_equal.default)(selectedBlockClientIds, blockClientIds)) {
        if (firstBlockRootClientId && firstBlockRootClientId !== rootClientId) {
          updateFocusAndSelection(firstBlockRootClientId, true);
          return;
        }
      }
      multiSelect(
        blockClientIds[0],
        blockClientIds[blockClientIds.length - 1],
        null
      );
    } else if (isMatch("core/block-editor/collapse-list-view", event)) {
      event.preventDefault();
      const { firstBlockClientId } = getBlocksToUpdate();
      const blockParents = getBlockParents(firstBlockClientId, false);
      collapseAll();
      expand(blockParents);
    } else if (isMatch("core/block-editor/group", event)) {
      const { blocksToUpdate } = getBlocksToUpdate();
      if (blocksToUpdate.length > 1 && isGroupable(blocksToUpdate)) {
        event.preventDefault();
        const blocks = getBlocksByClientId(blocksToUpdate);
        const groupingBlockName = getGroupingBlockName();
        const newBlocks = (0, import_blocks.switchToBlockType)(
          blocks,
          groupingBlockName
        );
        replaceBlocks(blocksToUpdate, newBlocks);
        (0, import_a11y.speak)((0, import_i18n.__)("Selected blocks are grouped."));
        const newlySelectedBlocks = getSelectedBlockClientIds();
        setOpenedBlockSettingsMenu(void 0);
        updateFocusAndSelection(newlySelectedBlocks[0], false);
      }
    } else if (isMatch("core/block-editor/toggle-block-visibility", event)) {
      event.preventDefault();
      const { blocksToUpdate } = getBlocksToUpdate();
      const blocks = getBlocksByClientId(blocksToUpdate);
      const canToggleVisibility = blocks.every(
        (blockToUpdate) => (0, import_blocks.hasBlockSupport)(blockToUpdate.name, "visibility", true)
      );
      if (!canToggleVisibility) {
        return;
      }
      const hasHiddenBlock = blocks.some(
        (blockToUpdate) => blockToUpdate.attributes.metadata?.blockVisibility === false
      );
      const attributesByClientId = Object.fromEntries(
        blocks.map(({ clientId: mapClientId, attributes }) => [
          mapClientId,
          {
            metadata: (0, import_utils2.cleanEmptyObject)({
              ...attributes?.metadata,
              blockVisibility: hasHiddenBlock ? void 0 : false
            })
          }
        ])
      );
      updateBlockAttributes(blocksToUpdate, attributesByClientId, {
        uniqueByBlock: true
      });
    }
  }
  const onMouseEnter = (0, import_element.useCallback)(() => {
    setIsHovered(true);
    debouncedToggleBlockHighlight(clientId, true);
  }, [clientId, setIsHovered, debouncedToggleBlockHighlight]);
  const onMouseLeave = (0, import_element.useCallback)(() => {
    setIsHovered(false);
    debouncedToggleBlockHighlight(clientId, false);
  }, [clientId, setIsHovered, debouncedToggleBlockHighlight]);
  const selectEditorBlock = (0, import_element.useCallback)(
    (event) => {
      selectBlock(event, clientId);
      event.preventDefault();
    },
    [clientId, selectBlock]
  );
  const updateFocusAndSelection = (0, import_element.useCallback)(
    (focusClientId, shouldSelectBlock) => {
      if (shouldSelectBlock) {
        selectBlock(void 0, focusClientId, null, null);
      }
      (0, import_utils.focusListItem)(focusClientId, treeGridElementRef?.current);
    },
    [selectBlock, treeGridElementRef]
  );
  const toggleExpanded = (0, import_element.useCallback)(
    (event) => {
      event.preventDefault();
      event.stopPropagation();
      if (isExpanded === true) {
        collapse(clientId);
      } else if (isExpanded === false) {
        expand(clientId);
      }
    },
    [clientId, expand, collapse, isExpanded]
  );
  const onContextMenu = (0, import_element.useCallback)(
    (event) => {
      if (showBlockActions && allowRightClickOverrides) {
        settingsRef.current?.click();
        setSettingsAnchorRect(
          new window.DOMRect(event.clientX, event.clientY, 0, 0)
        );
        event.preventDefault();
      }
    },
    [allowRightClickOverrides, settingsRef, showBlockActions]
  );
  const onMouseDown = (0, import_element.useCallback)(
    (event) => {
      if (allowRightClickOverrides && event.button === 2) {
        event.preventDefault();
      }
    },
    [allowRightClickOverrides]
  );
  const settingsPopoverAnchor = (0, import_element.useMemo)(() => {
    const { ownerDocument } = rowRef?.current || {};
    if (!settingsAnchorRect || !ownerDocument) {
      return void 0;
    }
    return {
      ownerDocument,
      getBoundingClientRect() {
        return settingsAnchorRect;
      }
    };
  }, [settingsAnchorRect]);
  const clearSettingsAnchorRect = (0, import_element.useCallback)(() => {
    setSettingsAnchorRect(void 0);
  }, [setSettingsAnchorRect]);
  (0, import_use_list_view_scroll_into_view.default)({
    isSelected,
    rowItemRef: rowRef,
    selectedClientIds
  });
  if (!block) {
    return null;
  }
  const blockPositionDescription = (0, import_utils.getBlockPositionDescription)(
    position,
    siblingBlockCount,
    level
  );
  const blockPropertiesDescription = (0, import_utils.getBlockPropertiesDescription)(
    blockInformation,
    isLocked
  );
  const blockVisibilityDescription = isBlockHidden ? (0, import_i18n.__)("Block is hidden.") : null;
  const hasSiblings = siblingBlockCount > 0;
  const hasRenderedMovers = showBlockMovers && hasSiblings;
  const moverCellClassName = (0, import_clsx.default)(
    "block-editor-list-view-block__mover-cell",
    { "is-visible": isHovered || isSelected }
  );
  const listViewBlockSettingsClassName = (0, import_clsx.default)(
    "block-editor-list-view-block__menu-cell",
    { "is-visible": isHovered || isFirstSelectedBlock }
  );
  let colSpan;
  if (hasRenderedMovers) {
    colSpan = 2;
  } else if (!showBlockActions) {
    colSpan = 3;
  }
  const classes = (0, import_clsx.default)({
    "is-selected": isSelected,
    "is-first-selected": isFirstSelectedBlock,
    "is-last-selected": isLastSelectedBlock,
    "is-branch-selected": isBranchSelected,
    "is-synced-branch": isSyncedBranch,
    "is-dragging": isDragged,
    "has-single-cell": !showBlockActions,
    "is-synced": blockInformation?.isSynced,
    "is-draggable": canMoveBlock,
    "is-displacement-normal": displacement === "normal",
    "is-displacement-up": displacement === "up",
    "is-displacement-down": displacement === "down",
    "is-after-dragged-blocks": isAfterDraggedBlocks,
    "is-nesting": isNesting
  });
  const dropdownClientIds = selectedClientIds.includes(clientId) ? selectedClientIds : [clientId];
  const currentlyEditingBlockInCanvas = isSelected && selectedClientIds.length === 1;
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
    import_leaf.default,
    {
      className: classes,
      isDragged,
      onKeyDown,
      onMouseEnter,
      onMouseLeave,
      onFocus: onMouseEnter,
      onBlur: onMouseLeave,
      level,
      position,
      rowCount,
      path,
      id: `list-view-${listViewInstanceId}-block-${clientId}`,
      "data-block": clientId,
      "data-expanded": canEditBlock ? isExpanded : void 0,
      ref: rowRef,
      children: [
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
          import_components.__experimentalTreeGridCell,
          {
            className: "block-editor-list-view-block__contents-cell",
            colSpan,
            ref: cellRef,
            "aria-selected": !!isSelected,
            children: ({ ref, tabIndex, onFocus }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "block-editor-list-view-block__contents-container", children: [
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
                import_block_contents.default,
                {
                  block,
                  onClick: selectEditorBlock,
                  onContextMenu,
                  onMouseDown,
                  onToggleExpanded: toggleExpanded,
                  isSelected,
                  position,
                  siblingBlockCount,
                  level,
                  ref,
                  tabIndex: currentlyEditingBlockInCanvas ? 0 : tabIndex,
                  onFocus,
                  isExpanded: canEditBlock ? isExpanded : void 0,
                  selectedClientIds,
                  ariaDescribedBy: descriptionId
                }
              ),
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_aria_referenced_text.default, { id: descriptionId, children: [
                blockPositionDescription,
                blockPropertiesDescription,
                blockVisibilityDescription
              ].filter(Boolean).join(" ") })
            ] })
          }
        ),
        hasRenderedMovers && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
          import_components.__experimentalTreeGridCell,
          {
            className: moverCellClassName,
            withoutGridItem: true,
            children: [
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalTreeGridItem, { children: ({ ref, tabIndex, onFocus }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
                import_button.BlockMoverUpButton,
                {
                  orientation: "vertical",
                  clientIds: [clientId],
                  ref,
                  tabIndex,
                  onFocus
                }
              ) }),
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalTreeGridItem, { children: ({ ref, tabIndex, onFocus }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
                import_button.BlockMoverDownButton,
                {
                  orientation: "vertical",
                  clientIds: [clientId],
                  ref,
                  tabIndex,
                  onFocus
                }
              ) })
            ]
          }
        ) }),
        showBlockActions && BlockSettingsMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
          import_components.__experimentalTreeGridCell,
          {
            className: listViewBlockSettingsClassName,
            "aria-selected": !!isSelected,
            ref: settingsRef,
            children: ({ ref, tabIndex, onFocus }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
              BlockSettingsMenu,
              {
                clientIds: dropdownClientIds,
                block,
                icon: import_icons.moreVertical,
                label: (0, import_i18n.__)("Options"),
                popoverProps: {
                  anchor: settingsPopoverAnchor
                  // Used to position the settings at the cursor on right-click.
                },
                toggleProps: {
                  ref,
                  className: "block-editor-list-view-block__menu",
                  tabIndex,
                  onClick: clearSettingsAnchorRect,
                  onFocus,
                  size: "small"
                },
                disableOpenOnArrowDown: true,
                expand,
                expandedState,
                setInsertedBlock,
                __experimentalSelectBlock: updateFocusAndSelection
              }
            )
          }
        )
      ]
    }
  );
}
var block_default = (0, import_element.memo)(ListViewBlock);
//# sourceMappingURL=block.js.map
