// packages/block-editor/src/store/reducer.js
import fastDeepEqual from "fast-deep-equal/es6/index.js";
import { pipe } from "@wordpress/compose";
import { combineReducers, select } from "@wordpress/data";
import deprecated from "@wordpress/deprecated";
import {
  store as blocksStore,
  privateApis as blocksPrivateApis
} from "@wordpress/blocks";
import { PREFERENCES_DEFAULTS, SETTINGS_DEFAULTS } from "./defaults.mjs";
import { insertAt, moveTo } from "./array.mjs";
import { sectionRootClientIdKey, isIsolatedEditorKey } from "./private-keys.mjs";
import { unlock } from "../lock-unlock.mjs";
var { isContentBlock } = unlock(blocksPrivateApis);
var identity = (x) => x;
function mapBlockOrder(blocks2, rootClientId = "") {
  const result = /* @__PURE__ */ new Map();
  const current = [];
  result.set(rootClientId, current);
  blocks2.forEach((block) => {
    const { clientId, innerBlocks } = block;
    current.push(clientId);
    mapBlockOrder(innerBlocks, clientId).forEach(
      (order, subClientId) => {
        result.set(subClientId, order);
      }
    );
  });
  return result;
}
function mapBlockParents(blocks2, rootClientId = "") {
  const result = [];
  const stack = [[rootClientId, blocks2]];
  while (stack.length) {
    const [parent, currentBlocks] = stack.shift();
    currentBlocks.forEach(({ innerBlocks, ...block }) => {
      result.push([block.clientId, parent]);
      if (innerBlocks?.length) {
        stack.push([block.clientId, innerBlocks]);
      }
    });
  }
  return result;
}
function flattenBlocks(blocks2, transform = identity) {
  const result = [];
  const stack = [...blocks2];
  while (stack.length) {
    const { innerBlocks, ...block } = stack.shift();
    stack.push(...innerBlocks);
    result.push([block.clientId, transform(block)]);
  }
  return result;
}
function getFlattenedClientIds(blocks2) {
  const result = {};
  const stack = [...blocks2];
  while (stack.length) {
    const { innerBlocks, ...block } = stack.shift();
    stack.push(...innerBlocks);
    result[block.clientId] = true;
  }
  return result;
}
function getFlattenedBlocksWithoutAttributes(blocks2) {
  return flattenBlocks(blocks2, (block) => {
    const { attributes, ...restBlock } = block;
    return restBlock;
  });
}
function getFlattenedBlockAttributes(blocks2) {
  return flattenBlocks(blocks2, (block) => block.attributes);
}
function hasSameKeys(a, b) {
  return fastDeepEqual(Object.keys(a), Object.keys(b));
}
function isUpdatingSameBlockAttribute(action, lastAction) {
  return action.type === "UPDATE_BLOCK_ATTRIBUTES" && lastAction !== void 0 && lastAction.type === "UPDATE_BLOCK_ATTRIBUTES" && fastDeepEqual(action.clientIds, lastAction.clientIds) && hasSameKeys(action.attributes, lastAction.attributes);
}
function updateBlockTreeForBlocks(state, blocks2) {
  const treeToUpdate = state.tree;
  const stack = [...blocks2];
  const flattenedBlocks = [...blocks2];
  while (stack.length) {
    const block = stack.shift();
    stack.push(...block.innerBlocks);
    flattenedBlocks.push(...block.innerBlocks);
  }
  for (const block of flattenedBlocks) {
    treeToUpdate.set(block.clientId, {});
  }
  for (const block of flattenedBlocks) {
    treeToUpdate.set(
      block.clientId,
      Object.assign(treeToUpdate.get(block.clientId), {
        ...state.byClientId.get(block.clientId),
        attributes: state.attributes.get(block.clientId),
        innerBlocks: block.innerBlocks.map(
          (subBlock) => treeToUpdate.get(subBlock.clientId)
        )
      })
    );
  }
}
function updateParentInnerBlocksInTree(state, updatedClientIds, updateChildrenOfUpdatedClientIds = false) {
  const treeToUpdate = state.tree;
  const uncontrolledParents = /* @__PURE__ */ new Set([]);
  const controlledParents = /* @__PURE__ */ new Set();
  for (const clientId of updatedClientIds) {
    let current = updateChildrenOfUpdatedClientIds ? clientId : state.parents.get(clientId);
    do {
      if (state.controlledInnerBlocks.has(current)) {
        controlledParents.add(current);
        break;
      } else {
        uncontrolledParents.add(current);
        current = state.parents.get(current);
      }
    } while (current !== void 0);
  }
  for (const clientId of uncontrolledParents) {
    treeToUpdate.set(clientId, { ...treeToUpdate.get(clientId) });
  }
  for (const clientId of uncontrolledParents) {
    treeToUpdate.get(clientId).innerBlocks = (state.order.get(clientId) || []).map((subClientId) => treeToUpdate.get(subClientId));
  }
  for (const clientId of controlledParents) {
    treeToUpdate.set("controlled||" + clientId, {
      innerBlocks: (state.order.get(clientId) || []).map(
        (subClientId) => treeToUpdate.get(subClientId)
      )
    });
  }
}
var withBlockTree = (reducer) => (state = {}, action) => {
  const newState = reducer(state, action);
  if (newState === state) {
    return state;
  }
  newState.tree = state.tree ? state.tree : /* @__PURE__ */ new Map();
  switch (action.type) {
    case "RECEIVE_BLOCKS":
    case "INSERT_BLOCKS": {
      newState.tree = new Map(newState.tree);
      updateBlockTreeForBlocks(newState, action.blocks);
      updateParentInnerBlocksInTree(
        newState,
        action.rootClientId ? [action.rootClientId] : [""],
        true
      );
      break;
    }
    case "UPDATE_BLOCK":
      newState.tree = new Map(newState.tree);
      newState.tree.set(action.clientId, {
        ...newState.tree.get(action.clientId),
        ...newState.byClientId.get(action.clientId),
        attributes: newState.attributes.get(action.clientId)
      });
      updateParentInnerBlocksInTree(
        newState,
        [action.clientId],
        false
      );
      break;
    case "UPDATE_BLOCK_ATTRIBUTES": {
      newState.tree = new Map(newState.tree);
      action.clientIds.forEach((clientId) => {
        newState.tree.set(clientId, {
          ...newState.tree.get(clientId),
          attributes: newState.attributes.get(clientId)
        });
      });
      updateParentInnerBlocksInTree(
        newState,
        action.clientIds,
        false
      );
      break;
    }
    case "REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
      const inserterClientIds = getFlattenedClientIds(
        action.blocks
      );
      newState.tree = new Map(newState.tree);
      action.replacedClientIds.forEach((clientId) => {
        newState.tree.delete(clientId);
        if (!inserterClientIds[clientId]) {
          newState.tree.delete("controlled||" + clientId);
        }
      });
      updateBlockTreeForBlocks(newState, action.blocks);
      updateParentInnerBlocksInTree(
        newState,
        action.blocks.map((b) => b.clientId),
        false
      );
      const parentsOfRemovedBlocks2 = [];
      for (const clientId of action.clientIds) {
        const parentId = state.parents.get(clientId);
        if (parentId !== void 0 && (parentId === "" || newState.byClientId.get(parentId))) {
          parentsOfRemovedBlocks2.push(parentId);
        }
      }
      updateParentInnerBlocksInTree(
        newState,
        parentsOfRemovedBlocks2,
        true
      );
      break;
    }
    case "REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN":
      const parentsOfRemovedBlocks = [];
      for (const clientId of action.clientIds) {
        const parentId = state.parents.get(clientId);
        if (parentId !== void 0 && (parentId === "" || newState.byClientId.get(parentId))) {
          parentsOfRemovedBlocks.push(parentId);
        }
      }
      newState.tree = new Map(newState.tree);
      action.removedClientIds.forEach((clientId) => {
        newState.tree.delete(clientId);
        newState.tree.delete("controlled||" + clientId);
      });
      updateParentInnerBlocksInTree(
        newState,
        parentsOfRemovedBlocks,
        true
      );
      break;
    case "MOVE_BLOCKS_TO_POSITION": {
      const updatedBlockUids = [];
      if (action.fromRootClientId) {
        updatedBlockUids.push(action.fromRootClientId);
      } else {
        updatedBlockUids.push("");
      }
      if (action.toRootClientId) {
        updatedBlockUids.push(action.toRootClientId);
      }
      newState.tree = new Map(newState.tree);
      updateParentInnerBlocksInTree(
        newState,
        updatedBlockUids,
        true
      );
      break;
    }
    case "MOVE_BLOCKS_UP":
    case "MOVE_BLOCKS_DOWN": {
      const updatedBlockUids = [
        action.rootClientId ? action.rootClientId : ""
      ];
      newState.tree = new Map(newState.tree);
      updateParentInnerBlocksInTree(
        newState,
        updatedBlockUids,
        true
      );
      break;
    }
  }
  return newState;
};
function withPersistentBlockChange(reducer) {
  let lastAction;
  let markNextChangeAsNotPersistent = false;
  return (state, action) => {
    const nextState = reducer(state, action);
    const wasMarkedAsNotPersistent = markNextChangeAsNotPersistent;
    markNextChangeAsNotPersistent = action.type === "MARK_NEXT_CHANGE_AS_NOT_PERSISTENT";
    const isExplicitPersistentChange = action.type === "MARK_LAST_CHANGE_AS_PERSISTENT" || wasMarkedAsNotPersistent;
    if (state === nextState && !isExplicitPersistentChange) {
      if (state.isPersistentChange !== void 0) {
        return state;
      }
      return { ...nextState, isPersistentChange: true };
    }
    const isPersistentChange = isExplicitPersistentChange ? !wasMarkedAsNotPersistent : !isUpdatingSameBlockAttribute(action, lastAction);
    lastAction = action;
    return { ...nextState, isPersistentChange };
  };
}
function withIgnoredBlockChange(reducer) {
  const IGNORED_ACTION_TYPES = /* @__PURE__ */ new Set(["RECEIVE_BLOCKS"]);
  return (state, action) => {
    const nextState = reducer(state, action);
    if (nextState !== state) {
      nextState.isIgnoredChange = IGNORED_ACTION_TYPES.has(action.type);
    }
    return nextState;
  };
}
var withInnerBlocksRemoveCascade = (reducer) => (state, action) => {
  const getAllChildren = (clientIds) => {
    let result = clientIds;
    for (let i = 0; i < result.length; i++) {
      if (!state.order.get(result[i]) || action.keepControlledInnerBlocks && action.keepControlledInnerBlocks[result[i]]) {
        continue;
      }
      if (result === clientIds) {
        result = [...result];
      }
      result.push(...state.order.get(result[i]));
    }
    return result;
  };
  if (state) {
    switch (action.type) {
      case "REMOVE_BLOCKS":
        action = {
          ...action,
          type: "REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN",
          removedClientIds: getAllChildren(action.clientIds)
        };
        break;
      case "REPLACE_BLOCKS":
        action = {
          ...action,
          type: "REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN",
          replacedClientIds: getAllChildren(action.clientIds)
        };
        break;
    }
  }
  return reducer(state, action);
};
var withBlockReset = (reducer) => (state, action) => {
  if (action.type === "RESET_BLOCKS") {
    const newState = reducer(void 0, {
      type: "INSERT_BLOCKS",
      rootClientId: "",
      blocks: action.blocks
    });
    const preservedControlledInnerBlocks = state?.controlledInnerBlocks ?? /* @__PURE__ */ new Set();
    if (state?.order) {
      for (const clientId of preservedControlledInnerBlocks) {
        if (!newState.byClientId.has(clientId)) {
          continue;
        }
        newState.controlledInnerBlocks.add(clientId);
        const oldOrder = state.order.get(clientId);
        if (!oldOrder?.length) {
          continue;
        }
        newState.order.set(clientId, oldOrder);
        const preserveBlock = (blockId, parentId) => {
          const blockData = state.byClientId.get(blockId);
          if (!blockData) {
            return;
          }
          newState.byClientId.set(blockId, blockData);
          newState.attributes.set(
            blockId,
            state.attributes.get(blockId)
          );
          newState.parents.set(blockId, parentId);
          const childOrder = state.order.get(blockId) || [];
          newState.order.set(blockId, childOrder);
          childOrder.forEach(
            (childId) => preserveBlock(childId, blockId)
          );
        };
        oldOrder.forEach((id) => preserveBlock(id, clientId));
      }
    }
    for (const clientId of newState.controlledInnerBlocks) {
      const controlledOrder = newState.order.get(clientId);
      if (!controlledOrder?.length) {
        continue;
      }
      const innerBlocks = controlledOrder.map(
        (id) => state.tree.get(id)
      );
      const existingEntry = newState.tree.get(clientId);
      if (existingEntry) {
        existingEntry.innerBlocks = innerBlocks;
      }
      newState.tree.set("controlled||" + clientId, { innerBlocks });
      const preserveTreeEntry = (blockId) => {
        const treeEntry = state.tree.get(blockId);
        if (!treeEntry) {
          return;
        }
        newState.tree.set(blockId, treeEntry);
        const childOrder = newState.order.get(blockId) || [];
        childOrder.forEach(preserveTreeEntry);
      };
      controlledOrder.forEach(preserveTreeEntry);
    }
    const preservedBlockEditingModes = state?.blockEditingModes ?? /* @__PURE__ */ new Map();
    for (const [clientId, mode] of preservedBlockEditingModes) {
      if (!newState.tree.has(clientId)) {
        continue;
      }
      newState.blockEditingModes.set(clientId, mode);
    }
    return newState;
  }
  return reducer(state, action);
};
var withReplaceInnerBlocks = (reducer) => (state, action) => {
  if (action.type !== "REPLACE_INNER_BLOCKS") {
    return reducer(state, action);
  }
  const nestedControllers = {};
  if (state.controlledInnerBlocks.size) {
    const stack = [...action.blocks];
    while (stack.length) {
      const { innerBlocks, ...block } = stack.shift();
      stack.push(...innerBlocks);
      if (state.controlledInnerBlocks.has(block.clientId)) {
        nestedControllers[block.clientId] = true;
      }
    }
  }
  let stateAfterBlocksRemoval = state;
  if (state.order.get(action.rootClientId)) {
    stateAfterBlocksRemoval = reducer(stateAfterBlocksRemoval, {
      type: "REMOVE_BLOCKS",
      keepControlledInnerBlocks: nestedControllers,
      clientIds: state.order.get(action.rootClientId)
    });
  }
  let stateAfterInsert = stateAfterBlocksRemoval;
  if (action.blocks.length) {
    stateAfterInsert = reducer(stateAfterInsert, {
      ...action,
      type: "INSERT_BLOCKS",
      index: 0
    });
    const stateAfterInsertOrder = new Map(stateAfterInsert.order);
    Object.keys(nestedControllers).forEach((key) => {
      if (state.order.get(key)) {
        stateAfterInsertOrder.set(key, state.order.get(key));
      }
    });
    stateAfterInsert.order = stateAfterInsertOrder;
    stateAfterInsert.tree = new Map(stateAfterInsert.tree);
    Object.keys(nestedControllers).forEach((_key) => {
      const key = `controlled||${_key}`;
      if (state.tree.has(key)) {
        stateAfterInsert.tree.set(key, state.tree.get(key));
      }
    });
  }
  return stateAfterInsert;
};
var withResetControlledBlocks = (reducer) => (state, action) => {
  if (action.type === "SET_HAS_CONTROLLED_INNER_BLOCKS") {
    const innerBlockOrder = state.order.get(action.clientId);
    if (innerBlockOrder?.length) {
      const tempState = reducer(state, {
        type: "REPLACE_INNER_BLOCKS",
        rootClientId: action.clientId,
        blocks: []
      });
      return reducer(tempState, action);
    }
    return reducer(state, action);
  }
  return reducer(state, action);
};
var blocks = pipe(
  combineReducers,
  withBlockTree,
  // Needs to be before withInnerBlocksRemoveCascade.
  withInnerBlocksRemoveCascade,
  withReplaceInnerBlocks,
  // Needs to be after withInnerBlocksRemoveCascade.
  withBlockReset,
  withPersistentBlockChange,
  withIgnoredBlockChange,
  withResetControlledBlocks
)({
  // The state is using a Map instead of a plain object for performance reasons.
  // You can run the "./test/performance.js" unit test to check the impact
  // code changes can have on this reducer.
  byClientId(state = /* @__PURE__ */ new Map(), action) {
    switch (action.type) {
      case "RECEIVE_BLOCKS":
      case "INSERT_BLOCKS": {
        const newState = new Map(state);
        getFlattenedBlocksWithoutAttributes(action.blocks).forEach(
          ([key, value]) => {
            newState.set(key, value);
          }
        );
        return newState;
      }
      case "UPDATE_BLOCK": {
        if (!state.has(action.clientId)) {
          return state;
        }
        const { attributes, ...changes } = action.updates;
        if (Object.values(changes).length === 0) {
          return state;
        }
        const newState = new Map(state);
        newState.set(action.clientId, {
          ...state.get(action.clientId),
          ...changes
        });
        return newState;
      }
      case "REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        if (!action.blocks) {
          return state;
        }
        const newState = new Map(state);
        action.replacedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        getFlattenedBlocksWithoutAttributes(action.blocks).forEach(
          ([key, value]) => {
            newState.set(key, value);
          }
        );
        return newState;
      }
      case "REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        const newState = new Map(state);
        action.removedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        return newState;
      }
    }
    return state;
  },
  // The state is using a Map instead of a plain object for performance reasons.
  // You can run the "./test/performance.js" unit test to check the impact
  // code changes can have on this reducer.
  attributes(state = /* @__PURE__ */ new Map(), action) {
    switch (action.type) {
      case "RECEIVE_BLOCKS":
      case "INSERT_BLOCKS": {
        const newState = new Map(state);
        getFlattenedBlockAttributes(action.blocks).forEach(
          ([key, value]) => {
            newState.set(key, value);
          }
        );
        return newState;
      }
      case "UPDATE_BLOCK": {
        if (!state.get(action.clientId) || !action.updates.attributes) {
          return state;
        }
        const newState = new Map(state);
        newState.set(action.clientId, {
          ...state.get(action.clientId),
          ...action.updates.attributes
        });
        return newState;
      }
      case "UPDATE_BLOCK_ATTRIBUTES": {
        if (action.clientIds.every((id) => !state.get(id))) {
          return state;
        }
        let hasChange = false;
        const newState = new Map(state);
        for (const clientId of action.clientIds) {
          const updatedAttributeEntries = Object.entries(
            !!action.options?.uniqueByBlock ? action.attributes[clientId] : action.attributes ?? {}
          );
          if (updatedAttributeEntries.length === 0) {
            continue;
          }
          let hasUpdatedAttributes = false;
          const existingAttributes = state.get(clientId);
          const newAttributes = {};
          updatedAttributeEntries.forEach(([key, value]) => {
            if (existingAttributes[key] !== value) {
              hasUpdatedAttributes = true;
              newAttributes[key] = value;
            }
          });
          hasChange = hasChange || hasUpdatedAttributes;
          if (hasUpdatedAttributes) {
            newState.set(clientId, {
              ...existingAttributes,
              ...newAttributes
            });
          }
        }
        return hasChange ? newState : state;
      }
      case "REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        if (!action.blocks) {
          return state;
        }
        const newState = new Map(state);
        action.replacedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        getFlattenedBlockAttributes(action.blocks).forEach(
          ([key, value]) => {
            newState.set(key, value);
          }
        );
        return newState;
      }
      case "REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        const newState = new Map(state);
        action.removedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        return newState;
      }
    }
    return state;
  },
  // The state is using a Map instead of a plain object for performance reasons.
  // You can run the "./test/performance.js" unit test to check the impact
  // code changes can have on this reducer.
  order(state = /* @__PURE__ */ new Map(), action) {
    switch (action.type) {
      case "RECEIVE_BLOCKS": {
        const blockOrder = mapBlockOrder(action.blocks);
        const newState = new Map(state);
        blockOrder.forEach((order, clientId) => {
          if (clientId !== "") {
            newState.set(clientId, order);
          }
        });
        newState.set(
          "",
          (state.get("") ?? []).concat(blockOrder[""])
        );
        return newState;
      }
      case "INSERT_BLOCKS": {
        const { rootClientId = "" } = action;
        const subState = state.get(rootClientId) || [];
        const mappedBlocks = mapBlockOrder(
          action.blocks,
          rootClientId
        );
        const { index = subState.length } = action;
        const newState = new Map(state);
        mappedBlocks.forEach((order, clientId) => {
          newState.set(clientId, order);
        });
        newState.set(
          rootClientId,
          insertAt(
            subState,
            mappedBlocks.get(rootClientId),
            index
          )
        );
        return newState;
      }
      case "MOVE_BLOCKS_TO_POSITION": {
        const {
          fromRootClientId = "",
          toRootClientId = "",
          clientIds
        } = action;
        const { index = state.get(toRootClientId).length } = action;
        if (fromRootClientId === toRootClientId) {
          const subState = state.get(toRootClientId);
          const fromIndex = subState.indexOf(clientIds[0]);
          if (fromIndex === -1) {
            return state;
          }
          const newState2 = new Map(state);
          newState2.set(
            toRootClientId,
            moveTo(
              state.get(toRootClientId),
              fromIndex,
              index,
              clientIds.length
            )
          );
          return newState2;
        }
        const newState = new Map(state);
        newState.set(
          fromRootClientId,
          state.get(fromRootClientId)?.filter((id) => !clientIds.includes(id)) ?? []
        );
        newState.set(
          toRootClientId,
          insertAt(state.get(toRootClientId), clientIds, index)
        );
        return newState;
      }
      case "MOVE_BLOCKS_UP": {
        const { clientIds, rootClientId = "" } = action;
        const firstClientId = clientIds[0];
        const subState = state.get(rootClientId);
        if (!subState.length || firstClientId === subState[0]) {
          return state;
        }
        const firstIndex = subState.indexOf(firstClientId);
        const newState = new Map(state);
        newState.set(
          rootClientId,
          moveTo(
            subState,
            firstIndex,
            firstIndex - 1,
            clientIds.length
          )
        );
        return newState;
      }
      case "MOVE_BLOCKS_DOWN": {
        const { clientIds, rootClientId = "" } = action;
        const firstClientId = clientIds[0];
        const lastClientId = clientIds[clientIds.length - 1];
        const subState = state.get(rootClientId);
        if (!subState.length || lastClientId === subState[subState.length - 1]) {
          return state;
        }
        const firstIndex = subState.indexOf(firstClientId);
        const newState = new Map(state);
        newState.set(
          rootClientId,
          moveTo(
            subState,
            firstIndex,
            firstIndex + 1,
            clientIds.length
          )
        );
        return newState;
      }
      case "REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        const { clientIds } = action;
        if (!action.blocks) {
          return state;
        }
        const mappedBlocks = mapBlockOrder(action.blocks);
        const newState = new Map(state);
        action.replacedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        mappedBlocks.forEach((order, clientId) => {
          if (clientId !== "") {
            newState.set(clientId, order);
          }
        });
        newState.forEach((order, clientId) => {
          const newSubOrder = Object.values(order).reduce(
            (result, subClientId) => {
              if (subClientId === clientIds[0]) {
                return [...result, ...mappedBlocks.get("")];
              }
              if (clientIds.indexOf(subClientId) === -1) {
                result.push(subClientId);
              }
              return result;
            },
            []
          );
          newState.set(clientId, newSubOrder);
        });
        return newState;
      }
      case "REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        const newState = new Map(state);
        action.removedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        newState.forEach((order, clientId) => {
          const newSubOrder = order?.filter(
            (id) => !action.removedClientIds.includes(id)
          ) ?? [];
          if (newSubOrder.length !== order.length) {
            newState.set(clientId, newSubOrder);
          }
        });
        return newState;
      }
    }
    return state;
  },
  // While technically redundant data as the inverse of `order`, it serves as
  // an optimization for the selectors which derive the ancestry of a block.
  parents(state = /* @__PURE__ */ new Map(), action) {
    switch (action.type) {
      case "RECEIVE_BLOCKS": {
        const newState = new Map(state);
        mapBlockParents(action.blocks).forEach(
          ([key, value]) => {
            newState.set(key, value);
          }
        );
        return newState;
      }
      case "INSERT_BLOCKS": {
        const newState = new Map(state);
        mapBlockParents(
          action.blocks,
          action.rootClientId || ""
        ).forEach(([key, value]) => {
          newState.set(key, value);
        });
        return newState;
      }
      case "MOVE_BLOCKS_TO_POSITION": {
        const newState = new Map(state);
        action.clientIds.forEach((id) => {
          newState.set(id, action.toRootClientId || "");
        });
        return newState;
      }
      case "REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        const newState = new Map(state);
        action.replacedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        mapBlockParents(
          action.blocks,
          state.get(action.clientIds[0])
        ).forEach(([key, value]) => {
          newState.set(key, value);
        });
        return newState;
      }
      case "REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN": {
        const newState = new Map(state);
        action.removedClientIds.forEach((clientId) => {
          newState.delete(clientId);
        });
        return newState;
      }
    }
    return state;
  },
  controlledInnerBlocks(state = /* @__PURE__ */ new Set(), { type, clientId, hasControlledInnerBlocks }) {
    if (type === "SET_HAS_CONTROLLED_INNER_BLOCKS") {
      if (hasControlledInnerBlocks) {
        if (state.has(clientId)) {
          return state;
        }
        return new Set(state).add(clientId);
      }
      if (!state.has(clientId)) {
        return state;
      }
      const newState = new Set(state);
      newState.delete(clientId);
      return newState;
    }
    return state;
  },
  blockEditingModes(state = /* @__PURE__ */ new Map(), action) {
    switch (action.type) {
      case "SET_BLOCK_EDITING_MODE":
        if (state.get(action.clientId) === action.mode) {
          return state;
        }
        return new Map(state).set(action.clientId, action.mode);
      case "UNSET_BLOCK_EDITING_MODE": {
        if (!state.has(action.clientId)) {
          return state;
        }
        const newState = new Map(state);
        newState.delete(action.clientId);
        return newState;
      }
    }
    return state;
  }
});
function isBlockInterfaceHidden(state = false, action) {
  switch (action.type) {
    case "HIDE_BLOCK_INTERFACE":
      return true;
    case "SHOW_BLOCK_INTERFACE":
      return false;
  }
  return state;
}
function isTyping(state = false, action) {
  switch (action.type) {
    case "START_TYPING":
      return true;
    case "STOP_TYPING":
      return false;
  }
  return state;
}
function isDragging(state = false, action) {
  switch (action.type) {
    case "START_DRAGGING":
      return true;
    case "STOP_DRAGGING":
      return false;
  }
  return state;
}
function draggedBlocks(state = [], action) {
  switch (action.type) {
    case "START_DRAGGING_BLOCKS":
      return action.clientIds;
    case "STOP_DRAGGING_BLOCKS":
      return [];
  }
  return state;
}
function blockVisibility(state = {}, action) {
  if (action.type === "SET_BLOCK_VISIBILITY") {
    return {
      ...state,
      ...action.updates
    };
  }
  return state;
}
function selectionHelper(state = {}, action) {
  switch (action.type) {
    case "CLEAR_SELECTED_BLOCK": {
      if (state.clientId) {
        return {};
      }
      return state;
    }
    case "SELECT_BLOCK":
      if (action.clientId === state.clientId) {
        return state;
      }
      return { clientId: action.clientId };
    case "REPLACE_INNER_BLOCKS":
    case "INSERT_BLOCKS": {
      if (!action.updateSelection || !action.blocks.length) {
        return state;
      }
      return { clientId: action.blocks[0].clientId };
    }
    case "REMOVE_BLOCKS":
      if (!action.clientIds || !action.clientIds.length || action.clientIds.indexOf(state.clientId) === -1) {
        return state;
      }
      return {};
    case "REPLACE_BLOCKS": {
      if (action.clientIds.indexOf(state.clientId) === -1) {
        return state;
      }
      const blockToSelect = action.blocks[action.indexToSelect] || action.blocks[action.blocks.length - 1];
      if (!blockToSelect) {
        return {};
      }
      if (blockToSelect.clientId === state.clientId) {
        return state;
      }
      return { clientId: blockToSelect.clientId };
    }
  }
  return state;
}
function selection(state = {}, action) {
  switch (action.type) {
    case "SELECTION_CHANGE":
      if (action.clientId) {
        return {
          selectionStart: {
            clientId: action.clientId,
            attributeKey: action.attributeKey,
            offset: action.startOffset
          },
          selectionEnd: {
            clientId: action.clientId,
            attributeKey: action.attributeKey,
            offset: action.endOffset
          }
        };
      }
      return {
        selectionStart: action.start || state.selectionStart,
        selectionEnd: action.end || state.selectionEnd
      };
    case "RESET_SELECTION":
      const { selectionStart: selectionStart2, selectionEnd: selectionEnd2 } = action;
      return {
        selectionStart: selectionStart2,
        selectionEnd: selectionEnd2
      };
    case "MULTI_SELECT":
      const { start, end } = action;
      if (start === state.selectionStart?.clientId && end === state.selectionEnd?.clientId) {
        return state;
      }
      return {
        selectionStart: { clientId: start },
        selectionEnd: { clientId: end }
      };
    case "RESET_BLOCKS":
      const startClientId = state?.selectionStart?.clientId;
      const endClientId = state?.selectionEnd?.clientId;
      if (!startClientId && !endClientId) {
        return state;
      }
      if (!action.blocks.some(
        (block) => block.clientId === startClientId
      )) {
        return {
          selectionStart: {},
          selectionEnd: {}
        };
      }
      if (!action.blocks.some(
        (block) => block.clientId === endClientId
      )) {
        return {
          ...state,
          selectionEnd: state.selectionStart
        };
      }
  }
  const selectionStart = selectionHelper(state.selectionStart, action);
  const selectionEnd = selectionHelper(state.selectionEnd, action);
  if (selectionStart === state.selectionStart && selectionEnd === state.selectionEnd) {
    return state;
  }
  return {
    selectionStart,
    selectionEnd
  };
}
function isMultiSelecting(state = false, action) {
  switch (action.type) {
    case "START_MULTI_SELECT":
      return true;
    case "STOP_MULTI_SELECT":
      return false;
  }
  return state;
}
function isSelectionEnabled(state = true, action) {
  switch (action.type) {
    case "TOGGLE_SELECTION":
      return action.isSelectionEnabled;
  }
  return state;
}
function viewportModalClientIds(state = null, action) {
  switch (action.type) {
    case "SHOW_VIEWPORT_MODAL":
      return action.clientIds;
    case "HIDE_VIEWPORT_MODAL":
      return null;
  }
  return state;
}
function removalPromptData(state = false, action) {
  switch (action.type) {
    case "DISPLAY_BLOCK_REMOVAL_PROMPT":
      const { clientIds, selectPrevious, message } = action;
      return {
        clientIds,
        selectPrevious,
        message
      };
    case "CLEAR_BLOCK_REMOVAL_PROMPT":
      return false;
  }
  return state;
}
function blockRemovalRules(state = false, action) {
  switch (action.type) {
    case "SET_BLOCK_REMOVAL_RULES":
      return action.rules;
  }
  return state;
}
function initialPosition(state = null, action) {
  if (action.type === "REPLACE_BLOCKS" && action.initialPosition !== void 0) {
    return action.initialPosition;
  } else if ([
    "MULTI_SELECT",
    "SELECT_BLOCK",
    "RESET_SELECTION",
    "INSERT_BLOCKS",
    "REPLACE_INNER_BLOCKS"
  ].includes(action.type)) {
    return action.initialPosition;
  }
  return state;
}
function blocksMode(state = {}, action) {
  if (action.type === "TOGGLE_BLOCK_MODE") {
    const { clientId } = action;
    return {
      ...state,
      [clientId]: state[clientId] && state[clientId] === "html" ? "visual" : "html"
    };
  }
  return state;
}
function insertionCue(state = null, action) {
  switch (action.type) {
    case "SHOW_INSERTION_POINT": {
      const {
        rootClientId,
        index,
        __unstableWithInserter,
        operation,
        nearestSide
      } = action;
      const nextState = {
        rootClientId,
        index,
        __unstableWithInserter,
        operation,
        nearestSide
      };
      return fastDeepEqual(state, nextState) ? state : nextState;
    }
    case "HIDE_INSERTION_POINT":
      return null;
  }
  return state;
}
function template(state = { isValid: true }, action) {
  switch (action.type) {
    case "SET_TEMPLATE_VALIDITY":
      return {
        ...state,
        isValid: action.isValid
      };
  }
  return state;
}
function settings(state = SETTINGS_DEFAULTS, action) {
  switch (action.type) {
    case "UPDATE_SETTINGS": {
      const updatedSettings = action.reset ? {
        ...SETTINGS_DEFAULTS,
        ...action.settings
      } : {
        ...state,
        ...action.settings
      };
      Object.defineProperty(updatedSettings, "__unstableIsPreviewMode", {
        get() {
          deprecated("__unstableIsPreviewMode", {
            since: "6.8",
            alternative: "isPreviewMode"
          });
          return this.isPreviewMode;
        }
      });
      return updatedSettings;
    }
  }
  return state;
}
function preferences(state = PREFERENCES_DEFAULTS, action) {
  switch (action.type) {
    case "INSERT_BLOCKS":
    case "REPLACE_BLOCKS": {
      const nextInsertUsage = action.blocks.reduce(
        (prevUsage, block) => {
          const { attributes, name: blockName } = block;
          let id = blockName;
          const match = select(blocksStore).getActiveBlockVariation(
            blockName,
            attributes
          );
          if (match?.name) {
            id += "/" + match.name;
          }
          if (blockName === "core/block") {
            id += "/" + attributes.ref;
          }
          return {
            ...prevUsage,
            [id]: {
              time: action.time,
              count: prevUsage[id] ? prevUsage[id].count + 1 : 1
            }
          };
        },
        state.insertUsage
      );
      return {
        ...state,
        insertUsage: nextInsertUsage
      };
    }
  }
  return state;
}
var blockListSettings = (state = /* @__PURE__ */ new Map(), action) => {
  switch (action.type) {
    case "REPLACE_BLOCKS": {
      const replacementIds = /* @__PURE__ */ new Set();
      const stack = [...action.blocks];
      while (stack.length) {
        const block = stack.shift();
        replacementIds.add(block.clientId);
        stack.push(...block.innerBlocks);
      }
      const newState = new Map(state);
      for (const clientId of action.clientIds) {
        if (!replacementIds.has(clientId)) {
          newState.delete(clientId);
        }
      }
      return newState;
    }
    case "REMOVE_BLOCKS": {
      const newState = new Map(state);
      for (const clientId of action.clientIds) {
        newState.delete(clientId);
      }
      return newState;
    }
    case "UPDATE_BLOCK_LIST_SETTINGS": {
      const updates = typeof action.clientId === "string" ? [[action.clientId, action.settings]] : Object.entries(action.clientId);
      const relevantUpdates = updates.filter(
        ([clientId, nextSettings]) => !nextSettings ? state.has(clientId) : !fastDeepEqual(state.get(clientId), nextSettings)
      );
      if (!relevantUpdates.length) {
        return state;
      }
      const newState = new Map(state);
      for (const [clientId, nextSettings] of relevantUpdates) {
        if (!nextSettings) {
          newState.delete(clientId);
        } else {
          newState.set(clientId, nextSettings);
        }
      }
      return newState;
    }
  }
  return state;
};
function lastBlockAttributesChange(state = null, action) {
  switch (action.type) {
    case "UPDATE_BLOCK":
      if (!action.updates.attributes) {
        break;
      }
      return { [action.clientId]: action.updates.attributes };
    case "UPDATE_BLOCK_ATTRIBUTES":
      return action.clientIds.reduce(
        (accumulator, id) => ({
          ...accumulator,
          [id]: !!action.options?.uniqueByBlock ? action.attributes[id] : action.attributes
        }),
        {}
      );
  }
  return state;
}
function highlightedBlock(state, action) {
  switch (action.type) {
    case "TOGGLE_BLOCK_HIGHLIGHT":
      const { clientId, isHighlighted } = action;
      if (isHighlighted) {
        return clientId;
      } else if (state === clientId) {
        return null;
      }
      return state;
    case "SELECT_BLOCK":
      if (action.clientId !== state) {
        return null;
      }
  }
  return state;
}
function hasBlockSpotlight(state, action) {
  switch (action.type) {
    case "TOGGLE_BLOCK_SPOTLIGHT":
      const { clientId, hasBlockSpotlight: _hasBlockSpotlight } = action;
      if (_hasBlockSpotlight) {
        return clientId;
      } else if (state === clientId) {
        return null;
      }
      return state;
    case "SELECT_BLOCK":
      if (action.clientId !== state) {
        return null;
      }
      return state;
    case "SELECTION_CHANGE":
      if (action.start?.clientId !== state || action.end?.clientId !== state) {
        return null;
      }
      return state;
    case "CLEAR_SELECTED_BLOCK":
      return null;
  }
  return state;
}
function expandedBlock(state = null, action) {
  switch (action.type) {
    case "SET_BLOCK_EXPANDED_IN_LIST_VIEW":
      return action.clientId;
    case "SELECT_BLOCK":
      if (action.clientId !== state) {
        return null;
      }
  }
  return state;
}
function lastBlockInserted(state = {}, action) {
  switch (action.type) {
    case "INSERT_BLOCKS":
    case "REPLACE_BLOCKS":
      if (!action.blocks.length) {
        return state;
      }
      const clientIds = action.blocks.map((block) => {
        return block.clientId;
      });
      const source = action.meta?.source;
      return { clientIds, source };
    case "RESET_BLOCKS":
      return {};
  }
  return state;
}
function editedContentOnlySection(state, action) {
  if (action.type === "EDIT_CONTENT_ONLY_SECTION") {
    return action.clientId;
  }
  if (!state) {
    return state;
  }
  switch (action.type) {
    case "REMOVE_BLOCKS":
    case "REPLACE_BLOCKS":
      if (action.clientIds.includes(state)) {
        return void 0;
      }
      break;
    case "RESET_BLOCKS":
      if (!getFlattenedClientIds(action.blocks)[state]) {
        return void 0;
      }
      break;
  }
  return state;
}
function styleOverrides(state = /* @__PURE__ */ new Map(), action) {
  switch (action.type) {
    case "SET_STYLE_OVERRIDE":
      return new Map(state).set(action.id, action.style);
    case "DELETE_STYLE_OVERRIDE": {
      const newState = new Map(state);
      newState.delete(action.id);
      return newState;
    }
  }
  return state;
}
function registeredInserterMediaCategories(state = [], action) {
  switch (action.type) {
    case "REGISTER_INSERTER_MEDIA_CATEGORY":
      return [...state, action.category];
  }
  return state;
}
function lastFocus(state = false, action) {
  switch (action.type) {
    case "LAST_FOCUS":
      return action.lastFocus;
  }
  return state;
}
function zoomLevel(state = 100, action) {
  switch (action.type) {
    case "SET_ZOOM_LEVEL":
      return action.zoom;
    case "RESET_ZOOM_LEVEL":
      return 100;
  }
  return state;
}
function insertionPoint(state = null, action) {
  switch (action.type) {
    case "SET_INSERTION_POINT":
      return action.value;
    case "SELECT_BLOCK":
      return null;
  }
  return state;
}
function openedListViewPanels(state = { allOpen: false, panels: {} }, action) {
  switch (action.type) {
    case "SET_OPEN_LIST_VIEW_PANEL":
      return {
        allOpen: false,
        panels: action.clientId ? { [action.clientId]: true } : {}
      };
    case "SET_ALL_LIST_VIEW_PANELS_OPEN":
      return { allOpen: true, panels: {} };
    case "TOGGLE_LIST_VIEW_PANEL":
      return {
        allOpen: false,
        panels: {
          ...state.panels,
          [action.clientId]: action.isOpen
        }
      };
    case "REPLACE_BLOCKS":
    case "REMOVE_BLOCKS": {
      if (!action.clientIds || action.clientIds.length === 0) {
        return state;
      }
      const newPanels = { ...state.panels };
      let hasChanges = false;
      action.clientIds.forEach((clientId) => {
        if (clientId in newPanels) {
          delete newPanels[clientId];
          hasChanges = true;
        }
      });
      return hasChanges ? { ...state, panels: newPanels } : state;
    }
  }
  return state;
}
function listViewExpandRevision(state = 0, action) {
  switch (action.type) {
    case "INCREMENT_LIST_VIEW_EXPAND_REVISION":
      return state + 1;
  }
  return state;
}
function listViewContentPanelOpen(state = false, action) {
  switch (action.type) {
    case "OPEN_LIST_VIEW_CONTENT_PANEL":
      return true;
    case "CLOSE_LIST_VIEW_CONTENT_PANEL":
      return false;
    // Close when selection is cleared
    case "CLEAR_SELECTED_BLOCK":
      return false;
  }
  return state;
}
function requestedInspectorTab(state = null, action) {
  switch (action.type) {
    case "REQUEST_INSPECTOR_TAB":
      return {
        tabName: action.tabName,
        options: action.options
      };
    case "CLEAR_REQUESTED_INSPECTOR_TAB":
      return null;
  }
  return state;
}
var combinedReducers = combineReducers({
  blocks,
  isDragging,
  isTyping,
  isBlockInterfaceHidden,
  draggedBlocks,
  selection,
  isMultiSelecting,
  isSelectionEnabled,
  initialPosition,
  blocksMode,
  blockListSettings,
  insertionPoint,
  insertionCue,
  template,
  settings,
  preferences,
  lastBlockAttributesChange,
  lastFocus,
  expandedBlock,
  highlightedBlock,
  lastBlockInserted,
  editedContentOnlySection,
  blockVisibility,
  viewportModalClientIds,
  styleOverrides,
  removalPromptData,
  blockRemovalRules,
  registeredInserterMediaCategories,
  zoomLevel,
  hasBlockSpotlight,
  openedListViewPanels,
  listViewExpandRevision,
  listViewContentPanelOpen,
  requestedInspectorTab
});
function getBlockTreeBlock(state, clientId) {
  if (clientId === "") {
    const rootBlock = state.blocks.tree.get(clientId);
    if (!rootBlock) {
      return;
    }
    return {
      clientId: "",
      ...rootBlock
    };
  }
  if (!state.blocks.controlledInnerBlocks.has(clientId)) {
    return state.blocks.tree.get(clientId);
  }
  const controlledTree = state.blocks.tree.get(`controlled||${clientId}`);
  const regularTree = state.blocks.tree.get(clientId);
  return {
    ...regularTree,
    innerBlocks: controlledTree?.innerBlocks
  };
}
function traverseBlockTree(state, clientId, callback) {
  const tree = getBlockTreeBlock(state, clientId);
  if (!tree) {
    return;
  }
  callback(tree);
  if (!tree?.innerBlocks?.length) {
    return;
  }
  for (const innerBlock of tree?.innerBlocks) {
    traverseBlockTree(state, innerBlock.clientId, callback);
  }
}
function findParentInClientIdsList(state, clientId, clientIds) {
  if (!clientIds.length) {
    return;
  }
  let parent = state.blocks.parents.get(clientId);
  while (parent !== void 0) {
    if (clientIds.includes(parent)) {
      return parent;
    }
    parent = state.blocks.parents.get(parent);
  }
}
function hasBindings(block) {
  return block?.attributes?.metadata?.bindings && Object.keys(block?.attributes?.metadata?.bindings).length;
}
function getDerivedBlockEditingModesForTree(state, treeClientId = "") {
  const isZoomedOut = state?.zoomLevel < 100 || state?.zoomLevel === "auto-scaled";
  const derivedBlockEditingModes = /* @__PURE__ */ new Map();
  const sectionRootClientId = state.settings?.[sectionRootClientIdKey];
  const sectionClientIds = state.blocks.order.get(sectionRootClientId);
  const hasDisabledBlocks = Array.from(state.blocks.blockEditingModes).some(
    ([, mode]) => mode === "disabled"
  );
  const templatePartClientIds = [];
  const syncedPatternClientIds = [];
  state.blocks.controlledInnerBlocks.forEach((clientId) => {
    const block = state.blocks.byClientId?.get(clientId);
    if (block?.name === "core/template-part") {
      templatePartClientIds.push(clientId);
    }
    if (block?.name === "core/block") {
      syncedPatternClientIds.push(clientId);
    }
  });
  const contentOnlyTemplateLockedClientIds = Array.from(
    state.blockListSettings
  ).flatMap(
    ([clientId, listSettings]) => listSettings?.templateLock === "contentOnly" ? [clientId] : []
  );
  const isIsolatedEditor = state.settings?.[isIsolatedEditorKey];
  const disableContentOnlyForUnsyncedPatterns = state.settings?.disableContentOnlyForUnsyncedPatterns;
  const unsyncedPatternClientIds = isIsolatedEditor || disableContentOnlyForUnsyncedPatterns ? [] : Array.from(state.blocks.attributes.keys()).filter(
    (clientId) => state.blocks.attributes.get(clientId)?.metadata?.patternName
  );
  const disableContentOnlyForTemplateParts = state.settings?.disableContentOnlyForTemplateParts;
  const contentOnlyParents = [
    ...contentOnlyTemplateLockedClientIds,
    ...unsyncedPatternClientIds,
    ...isIsolatedEditor || disableContentOnlyForTemplateParts ? [] : templatePartClientIds
  ];
  traverseBlockTree(state, treeClientId, (block) => {
    const { clientId, name: blockName } = block;
    const hasEditedContentOnlySection = !!state.editedContentOnlySection;
    let isWithinEditedContentOnlySection = false;
    if (hasEditedContentOnlySection) {
      isWithinEditedContentOnlySection = clientId === state.editedContentOnlySection || !!findParentInClientIdsList(state, clientId, [
        state.editedContentOnlySection
      ]);
      if (!isWithinEditedContentOnlySection) {
        derivedBlockEditingModes.set(clientId, "disabled");
        return;
      }
    }
    if (state.blocks.blockEditingModes.has(clientId)) {
      return;
    }
    if (hasDisabledBlocks) {
      let ancestorBlockEditingMode;
      let parent = state.blocks.parents.get(clientId);
      while (parent !== void 0) {
        if (state.blocks.blockEditingModes.has(parent)) {
          ancestorBlockEditingMode = state.blocks.blockEditingModes.get(parent);
        }
        if (ancestorBlockEditingMode) {
          break;
        }
        parent = state.blocks.parents.get(parent);
      }
      if (ancestorBlockEditingMode === "disabled") {
        derivedBlockEditingModes.set(clientId, "disabled");
        return;
      }
    }
    if (isZoomedOut) {
      if (clientId === sectionRootClientId) {
        derivedBlockEditingModes.set(clientId, "contentOnly");
        return;
      }
      if (!sectionClientIds?.length) {
        derivedBlockEditingModes.set(clientId, "disabled");
        return;
      }
      if (sectionClientIds.includes(clientId)) {
        derivedBlockEditingModes.set(clientId, "contentOnly");
        return;
      }
      derivedBlockEditingModes.set(clientId, "disabled");
      return;
    }
    if (syncedPatternClientIds.length) {
      if (syncedPatternClientIds.includes(clientId)) {
        if (findParentInClientIdsList(
          state,
          clientId,
          syncedPatternClientIds
        )) {
          derivedBlockEditingModes.set(clientId, "disabled");
          return;
        }
        return;
      }
      const parentSyncedPatternClientId = findParentInClientIdsList(
        state,
        clientId,
        syncedPatternClientIds
      );
      if (parentSyncedPatternClientId) {
        if (findParentInClientIdsList(
          state,
          parentSyncedPatternClientId,
          syncedPatternClientIds
        )) {
          derivedBlockEditingModes.set(clientId, "disabled");
          return;
        }
        if (hasBindings(block)) {
          derivedBlockEditingModes.set(clientId, "contentOnly");
          return;
        }
        derivedBlockEditingModes.set(clientId, "disabled");
        return;
      }
    }
    if (hasEditedContentOnlySection && isWithinEditedContentOnlySection) {
      derivedBlockEditingModes.set(clientId, "default");
      return;
    }
    if (contentOnlyParents.length) {
      const hasContentOnlyParent = !!findParentInClientIdsList(
        state,
        clientId,
        contentOnlyParents
      );
      if (hasContentOnlyParent) {
        if (isContentBlock(blockName)) {
          derivedBlockEditingModes.set(clientId, "contentOnly");
        } else {
          derivedBlockEditingModes.set(clientId, "disabled");
        }
      }
    }
  });
  return derivedBlockEditingModes;
}
function getDerivedBlockEditingModesUpdates({
  prevState,
  nextState,
  addedBlocks,
  removedClientIds
}) {
  const prevDerivedBlockEditingModes = prevState.derivedBlockEditingModes;
  let nextDerivedBlockEditingModes;
  removedClientIds?.forEach((clientId) => {
    traverseBlockTree(prevState, clientId, (block) => {
      if (prevDerivedBlockEditingModes.has(block.clientId)) {
        if (!nextDerivedBlockEditingModes) {
          nextDerivedBlockEditingModes = new Map(
            prevDerivedBlockEditingModes
          );
        }
        nextDerivedBlockEditingModes.delete(block.clientId);
      }
    });
  });
  addedBlocks?.forEach((addedBlock) => {
    const updates = getDerivedBlockEditingModesForTree(
      nextState,
      addedBlock.clientId
    );
    if (updates.size) {
      if (!nextDerivedBlockEditingModes) {
        nextDerivedBlockEditingModes = new Map([
          ...prevDerivedBlockEditingModes?.size ? prevDerivedBlockEditingModes : [],
          ...updates
        ]);
      } else {
        nextDerivedBlockEditingModes = new Map([
          ...nextDerivedBlockEditingModes?.size ? nextDerivedBlockEditingModes : [],
          ...updates
        ]);
      }
    }
  });
  return nextDerivedBlockEditingModes;
}
function withDerivedBlockEditingModes(reducer) {
  return (state, action) => {
    const nextState = reducer(state, action);
    if (action.type !== "SET_EDITOR_MODE" && nextState === state) {
      return state;
    }
    switch (action.type) {
      case "REMOVE_BLOCKS": {
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          removedClientIds: action.clientIds
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "RECEIVE_BLOCKS":
      case "INSERT_BLOCKS": {
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          addedBlocks: action.blocks
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "UPDATE_BLOCK_ATTRIBUTES": {
        const disableContentOnlyForUnsyncedPatterns = nextState.settings?.disableContentOnlyForUnsyncedPatterns;
        if (disableContentOnlyForUnsyncedPatterns) {
          break;
        }
        const addedBlocks = [];
        const removedClientIds = [];
        for (const clientId of action?.clientIds) {
          const attributes = action.options?.uniqueByBlock ? action.attributes[clientId] : action.attributes;
          if (!attributes) {
            break;
          }
          if (
            // patternName is switching from falsy to truthy, indicating
            // this block is becoming an unsynced pattern.
            attributes.metadata?.patternName && !state.blocks.attributes.get(clientId)?.metadata?.patternName
          ) {
            addedBlocks.push(
              nextState.blocks.tree.get(clientId)
            );
          } else if (
            // patternName is switching from truthy to falsy, this block is becoming
            // a regular block but was an unsynced pattern.
            // Check that `metadata` is part of the included attributes, as
            // `updateBlockAttributes` merges attributes, if it isn't present
            // the previous `metadata` would be retained.
            attributes.metadata && !attributes.metadata?.patternName && state.blocks.attributes.get(clientId)?.metadata?.patternName
          ) {
            removedClientIds.push(clientId);
          }
        }
        if (!addedBlocks?.length && !removedClientIds?.length) {
          break;
        }
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          addedBlocks,
          removedClientIds
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "UPDATE_BLOCK_LIST_SETTINGS": {
        const addedBlocks = [];
        const removedClientIds = [];
        const updates = typeof action.clientId === "string" ? { [action.clientId]: action.settings } : action.clientId;
        for (const clientId in updates) {
          const isNewContentOnlyBlock = state.blockListSettings.get(clientId)?.templateLock !== "contentOnly" && nextState.blockListSettings.get(clientId)?.templateLock === "contentOnly";
          const wasContentOnlyBlock = state.blockListSettings.get(clientId)?.templateLock === "contentOnly" && nextState.blockListSettings.get(clientId)?.templateLock !== "contentOnly";
          if (isNewContentOnlyBlock) {
            addedBlocks.push(
              nextState.blocks.tree.get(clientId)
            );
          } else if (wasContentOnlyBlock) {
            removedClientIds.push(clientId);
          }
        }
        if (!addedBlocks.length && !removedClientIds.length) {
          break;
        }
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          addedBlocks,
          removedClientIds
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "SET_BLOCK_EDITING_MODE":
      case "UNSET_BLOCK_EDITING_MODE":
      case "SET_HAS_CONTROLLED_INNER_BLOCKS": {
        const updatedBlock = getBlockTreeBlock(
          nextState,
          action.clientId
        );
        if (!updatedBlock) {
          break;
        }
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          removedClientIds: [action.clientId],
          addedBlocks: [updatedBlock]
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "REPLACE_BLOCKS": {
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          addedBlocks: action.blocks,
          removedClientIds: action.clientIds
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "REPLACE_INNER_BLOCKS": {
        const removedClientIds = state.blocks.order.get(
          action.rootClientId
        );
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          addedBlocks: action.blocks,
          removedClientIds
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "MOVE_BLOCKS_TO_POSITION": {
        const addedBlocks = action.clientIds.map((clientId) => {
          return nextState.blocks.byClientId.get(clientId);
        });
        const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
          prevState: state,
          nextState,
          addedBlocks,
          removedClientIds: action.clientIds
        });
        if (nextDerivedBlockEditingModes) {
          return {
            ...nextState,
            derivedBlockEditingModes: nextDerivedBlockEditingModes ?? state.derivedBlockEditingModes
          };
        }
        break;
      }
      case "UPDATE_SETTINGS": {
        if (state?.settings?.[sectionRootClientIdKey] !== nextState?.settings?.[sectionRootClientIdKey] || !!state?.settings?.disableContentOnlyForUnsyncedPatterns !== !!nextState?.settings?.disableContentOnlyForUnsyncedPatterns || !!state?.settings?.[isIsolatedEditorKey] !== !!nextState?.settings?.[isIsolatedEditorKey] || !!state?.settings?.disableContentOnlyForTemplateParts !== !!nextState?.settings?.disableContentOnlyForTemplateParts) {
          return {
            ...nextState,
            derivedBlockEditingModes: getDerivedBlockEditingModesForTree(nextState)
          };
        }
        break;
      }
      case "RESET_BLOCKS":
      case "EDIT_CONTENT_ONLY_SECTION":
      case "SET_EDITOR_MODE":
      case "RESET_ZOOM_LEVEL":
      case "SET_ZOOM_LEVEL": {
        return {
          ...nextState,
          derivedBlockEditingModes: getDerivedBlockEditingModesForTree(nextState)
        };
      }
    }
    nextState.derivedBlockEditingModes = state?.derivedBlockEditingModes ?? /* @__PURE__ */ new Map();
    return nextState;
  };
}
function withAutomaticChangeReset(reducer) {
  return (state, action) => {
    const nextState = reducer(state, action);
    if (!state) {
      return nextState;
    }
    nextState.automaticChangeStatus = state.automaticChangeStatus;
    if (action.type === "MARK_AUTOMATIC_CHANGE") {
      return {
        ...nextState,
        automaticChangeStatus: "pending"
      };
    }
    if (action.type === "MARK_AUTOMATIC_CHANGE_FINAL" && state.automaticChangeStatus === "pending") {
      return {
        ...nextState,
        automaticChangeStatus: "final"
      };
    }
    if (nextState.blocks === state.blocks && nextState.selection === state.selection) {
      return nextState;
    }
    if (nextState.automaticChangeStatus !== "final" && nextState.selection !== state.selection) {
      return nextState;
    }
    return {
      ...nextState,
      automaticChangeStatus: void 0
    };
  };
}
var reducer_default = pipe(
  withDerivedBlockEditingModes,
  withAutomaticChangeReset
)(combinedReducers);
export {
  blockListSettings,
  blockVisibility,
  blocks,
  blocksMode,
  reducer_default as default,
  draggedBlocks,
  editedContentOnlySection,
  expandedBlock,
  hasBlockSpotlight,
  hasSameKeys,
  highlightedBlock,
  initialPosition,
  insertionCue,
  insertionPoint,
  isBlockInterfaceHidden,
  isDragging,
  isMultiSelecting,
  isSelectionEnabled,
  isTyping,
  isUpdatingSameBlockAttribute,
  lastBlockAttributesChange,
  lastBlockInserted,
  lastFocus,
  listViewContentPanelOpen,
  preferences,
  registeredInserterMediaCategories,
  requestedInspectorTab,
  selection,
  settings,
  styleOverrides,
  template,
  viewportModalClientIds,
  withDerivedBlockEditingModes,
  zoomLevel
};
//# sourceMappingURL=reducer.mjs.map
