"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.BlockListItems = BlockListItems;
exports.IntersectionObserver = void 0;
exports.default = BlockList;
var _clsx = _interopRequireDefault(require("clsx"));
var _data = require("@wordpress/data");
var _compose = require("@wordpress/compose");
var _element = require("@wordpress/element");
var _block = _interopRequireDefault(require("./block"));
var _blockListAppender = _interopRequireDefault(require("../block-list-appender"));
var _useInBetweenInserter = require("./use-in-between-inserter");
var _store = require("../../store");
var _layout = require("./layout");
var _blockSelectionClearer = require("../block-selection-clearer");
var _innerBlocks = require("../inner-blocks");
var _context = require("../block-edit/context");
var _observeTyping = require("../observe-typing");
var _zoomOutSeparator = require("./zoom-out-separator");
var _lockUnlock = require("../../lock-unlock");
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const IntersectionObserver = exports.IntersectionObserver = (0, _element.createContext)();
const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap();
function Root({
  className,
  ...settings
}) {
  const isLargeViewport = (0, _compose.useViewportMatch)('medium');
  const {
    isOutlineMode,
    isFocusMode,
    editorMode,
    temporarilyEditingAsBlocks
  } = (0, _data.useSelect)(select => {
    const {
      getSettings,
      __unstableGetEditorMode,
      getTemporarilyEditingAsBlocks,
      isTyping
    } = (0, _lockUnlock.unlock)(select(_store.store));
    const {
      outlineMode,
      focusMode
    } = getSettings();
    return {
      isOutlineMode: outlineMode && !isTyping(),
      isFocusMode: focusMode,
      editorMode: __unstableGetEditorMode(),
      temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks()
    };
  }, []);
  const registry = (0, _data.useRegistry)();
  const {
    setBlockVisibility
  } = (0, _data.useDispatch)(_store.store);
  const delayedBlockVisibilityUpdates = (0, _compose.useDebounce)((0, _element.useCallback)(() => {
    const updates = {};
    pendingBlockVisibilityUpdatesPerRegistry.get(registry).forEach(([id, isIntersecting]) => {
      updates[id] = isIntersecting;
    });
    setBlockVisibility(updates);
  }, [registry]), 300, {
    trailing: true
  });
  const intersectionObserver = (0, _element.useMemo)(() => {
    const {
      IntersectionObserver: Observer
    } = window;
    if (!Observer) {
      return;
    }
    return new Observer(entries => {
      if (!pendingBlockVisibilityUpdatesPerRegistry.get(registry)) {
        pendingBlockVisibilityUpdatesPerRegistry.set(registry, []);
      }
      for (const entry of entries) {
        const clientId = entry.target.getAttribute('data-block');
        pendingBlockVisibilityUpdatesPerRegistry.get(registry).push([clientId, entry.isIntersecting]);
      }
      delayedBlockVisibilityUpdates();
    });
  }, []);
  const innerBlocksProps = (0, _innerBlocks.useInnerBlocksProps)({
    ref: (0, _compose.useMergeRefs)([(0, _blockSelectionClearer.useBlockSelectionClearer)(), (0, _useInBetweenInserter.useInBetweenInserter)(), (0, _observeTyping.useTypingObserver)()]),
    className: (0, _clsx.default)('is-root-container', className, {
      'is-outline-mode': isOutlineMode,
      'is-focus-mode': isFocusMode && isLargeViewport,
      'is-navigate-mode': editorMode === 'navigation'
    })
  }, settings);
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(IntersectionObserver.Provider, {
    value: intersectionObserver,
    children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      ...innerBlocksProps
    }), !!temporarilyEditingAsBlocks && /*#__PURE__*/(0, _jsxRuntime.jsx)(StopEditingAsBlocksOnOutsideSelect, {
      clientId: temporarilyEditingAsBlocks
    })]
  });
}
function StopEditingAsBlocksOnOutsideSelect({
  clientId
}) {
  const {
    stopEditingAsBlocks
  } = (0, _lockUnlock.unlock)((0, _data.useDispatch)(_store.store));
  const isBlockOrDescendantSelected = (0, _data.useSelect)(select => {
    const {
      isBlockSelected,
      hasSelectedInnerBlock
    } = select(_store.store);
    return isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true);
  }, [clientId]);
  (0, _element.useEffect)(() => {
    if (!isBlockOrDescendantSelected) {
      stopEditingAsBlocks(clientId);
    }
  }, [isBlockOrDescendantSelected, clientId, stopEditingAsBlocks]);
  return null;
}
function BlockList(settings) {
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_context.BlockEditContextProvider, {
    value: _context.DEFAULT_BLOCK_EDIT_CONTEXT,
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Root, {
      ...settings
    })
  });
}
const EMPTY_ARRAY = [];
const EMPTY_SET = new Set();
function Items({
  placeholder,
  rootClientId,
  renderAppender: CustomAppender,
  __experimentalAppenderTagName,
  layout = _layout.defaultLayout
}) {
  // Avoid passing CustomAppender to useSelect because it could be a new
  // function on every render.
  const hasAppender = CustomAppender !== false;
  const hasCustomAppender = !!CustomAppender;
  const {
    order,
    isZoomOut,
    selectedBlocks,
    visibleBlocks,
    shouldRenderAppender
  } = (0, _data.useSelect)(select => {
    const {
      getSettings,
      getBlockOrder,
      getSelectedBlockClientId,
      getSelectedBlockClientIds,
      __unstableGetVisibleBlocks,
      getTemplateLock,
      getBlockEditingMode,
      __unstableGetEditorMode
    } = select(_store.store);
    const _order = getBlockOrder(rootClientId);
    if (getSettings().__unstableIsPreviewMode) {
      return {
        order: _order,
        selectedBlocks: EMPTY_ARRAY,
        visibleBlocks: EMPTY_SET
      };
    }
    const selectedBlockClientId = getSelectedBlockClientId();
    return {
      order: _order,
      selectedBlocks: getSelectedBlockClientIds(),
      visibleBlocks: __unstableGetVisibleBlocks(),
      isZoomOut: __unstableGetEditorMode() === 'zoom-out',
      shouldRenderAppender: hasAppender && __unstableGetEditorMode() !== 'zoom-out' && (hasCustomAppender ? !getTemplateLock(rootClientId) && getBlockEditingMode(rootClientId) !== 'disabled' : rootClientId === selectedBlockClientId || !rootClientId && !selectedBlockClientId && !_order.length)
    };
  }, [rootClientId, hasAppender, hasCustomAppender]);
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_layout.LayoutProvider, {
    value: layout,
    children: [order.map(clientId => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_data.AsyncModeProvider, {
      value:
      // Only provide data asynchronously if the block is
      // not visible and not selected.
      !visibleBlocks.has(clientId) && !selectedBlocks.includes(clientId),
      children: [isZoomOut && /*#__PURE__*/(0, _jsxRuntime.jsx)(_zoomOutSeparator.ZoomOutSeparator, {
        clientId: clientId,
        rootClientId: rootClientId,
        position: "top"
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_block.default, {
        rootClientId: rootClientId,
        clientId: clientId
      }), isZoomOut && /*#__PURE__*/(0, _jsxRuntime.jsx)(_zoomOutSeparator.ZoomOutSeparator, {
        clientId: clientId,
        rootClientId: rootClientId,
        position: "bottom"
      })]
    }, clientId)), order.length < 1 && placeholder, shouldRenderAppender && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockListAppender.default, {
      tagName: __experimentalAppenderTagName,
      rootClientId: rootClientId,
      CustomAppender: CustomAppender
    })]
  });
}
function BlockListItems(props) {
  // This component needs to always be synchronous as it's the one changing
  // the async mode depending on the block selection.
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_data.AsyncModeProvider, {
    value: false,
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Items, {
      ...props
    })
  });
}
//# sourceMappingURL=index.js.map