"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.InsertionPointOpenRef = void 0;
exports.default = InsertionPoint;
var _clsx = _interopRequireDefault(require("clsx"));
var _data = require("@wordpress/data");
var _element = require("@wordpress/element");
var _components = require("@wordpress/components");
var _compose = require("@wordpress/compose");
var _inserter = _interopRequireDefault(require("../inserter"));
var _store = require("../../store");
var _inbetween = _interopRequireDefault(require("../block-popover/inbetween"));
var _dropZone = _interopRequireDefault(require("../block-popover/drop-zone"));
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const InsertionPointOpenRef = exports.InsertionPointOpenRef = (0, _element.createContext)();
function InbetweenInsertionPointPopover({
  __unstablePopoverSlot,
  __unstableContentRef,
  operation = 'insert',
  nearestSide = 'right'
}) {
  const {
    selectBlock,
    hideInsertionPoint
  } = (0, _data.useDispatch)(_store.store);
  const openRef = (0, _element.useContext)(InsertionPointOpenRef);
  const ref = (0, _element.useRef)();
  const {
    orientation,
    previousClientId,
    nextClientId,
    rootClientId,
    isInserterShown,
    isDistractionFree,
    isNavigationMode,
    isZoomOutMode
  } = (0, _data.useSelect)(select => {
    const {
      getBlockOrder,
      getBlockListSettings,
      getBlockInsertionPoint,
      isBlockBeingDragged,
      getPreviousBlockClientId,
      getNextBlockClientId,
      getSettings,
      isNavigationMode: _isNavigationMode,
      __unstableGetEditorMode
    } = select(_store.store);
    const insertionPoint = getBlockInsertionPoint();
    const order = getBlockOrder(insertionPoint.rootClientId);
    if (!order.length) {
      return {};
    }
    let _previousClientId = order[insertionPoint.index - 1];
    let _nextClientId = order[insertionPoint.index];
    while (isBlockBeingDragged(_previousClientId)) {
      _previousClientId = getPreviousBlockClientId(_previousClientId);
    }
    while (isBlockBeingDragged(_nextClientId)) {
      _nextClientId = getNextBlockClientId(_nextClientId);
    }
    const settings = getSettings();
    return {
      previousClientId: _previousClientId,
      nextClientId: _nextClientId,
      orientation: getBlockListSettings(insertionPoint.rootClientId)?.orientation || 'vertical',
      rootClientId: insertionPoint.rootClientId,
      isNavigationMode: _isNavigationMode(),
      isDistractionFree: settings.isDistractionFree,
      isInserterShown: insertionPoint?.__unstableWithInserter,
      isZoomOutMode: __unstableGetEditorMode() === 'zoom-out'
    };
  }, []);
  const {
    getBlockEditingMode
  } = (0, _data.useSelect)(_store.store);
  const disableMotion = (0, _compose.useReducedMotion)();
  function onClick(event) {
    if (event.target === ref.current && nextClientId && getBlockEditingMode(nextClientId) !== 'disabled') {
      selectBlock(nextClientId, -1);
    }
  }
  function maybeHideInserterPoint(event) {
    // Only hide the inserter if it's triggered on the wrapper,
    // and the inserter is not open.
    if (event.target === ref.current && !openRef.current) {
      hideInsertionPoint();
    }
  }
  function onFocus(event) {
    // Only handle click on the wrapper specifically, and not an event
    // bubbled from the inserter itself.
    if (event.target !== ref.current) {
      openRef.current = true;
    }
  }
  const lineVariants = {
    // Initial position starts from the center and invisible.
    start: {
      opacity: 0,
      scale: 0
    },
    // The line expands to fill the container. If the inserter is visible it
    // is delayed so it appears orchestrated.
    rest: {
      opacity: 1,
      scale: 1,
      transition: {
        delay: isInserterShown ? 0.5 : 0,
        type: 'tween'
      }
    },
    hover: {
      opacity: 1,
      scale: 1,
      transition: {
        delay: 0.5,
        type: 'tween'
      }
    }
  };
  const inserterVariants = {
    start: {
      scale: disableMotion ? 1 : 0
    },
    rest: {
      scale: 1,
      transition: {
        delay: 0.4,
        type: 'tween'
      }
    }
  };
  if (isDistractionFree && !isNavigationMode) {
    return null;
  }

  // Zoom out mode should only show the insertion point for the insert operation.
  // Other operations such as "group" are when the editor tries to create a row
  // block by grouping the block being dragged with the block it's being dropped
  // onto.
  if (isZoomOutMode && operation !== 'insert') {
    return null;
  }
  const orientationClassname = orientation === 'horizontal' || operation === 'group' ? 'is-horizontal' : 'is-vertical';
  const className = (0, _clsx.default)('block-editor-block-list__insertion-point', orientationClassname);
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_inbetween.default, {
    previousClientId: previousClientId,
    nextClientId: nextClientId,
    __unstablePopoverSlot: __unstablePopoverSlot,
    __unstableContentRef: __unstableContentRef,
    operation: operation,
    nearestSide: nearestSide,
    children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__unstableMotion.div, {
      layout: !disableMotion,
      initial: disableMotion ? 'rest' : 'start',
      animate: "rest",
      whileHover: "hover",
      whileTap: "pressed",
      exit: "start",
      ref: ref,
      tabIndex: -1,
      onClick: onClick,
      onFocus: onFocus,
      className: (0, _clsx.default)(className, {
        'is-with-inserter': isInserterShown
      }),
      onHoverEnd: maybeHideInserterPoint,
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__unstableMotion.div, {
        variants: lineVariants,
        className: "block-editor-block-list__insertion-point-indicator",
        "data-testid": "block-list-insertion-point-indicator"
      }), isInserterShown && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__unstableMotion.div, {
        variants: inserterVariants,
        className: (0, _clsx.default)('block-editor-block-list__insertion-point-inserter'),
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_inserter.default, {
          position: "bottom center",
          clientId: nextClientId,
          rootClientId: rootClientId,
          __experimentalIsQuick: true,
          onToggle: isOpen => {
            openRef.current = isOpen;
          },
          onSelectOrClose: () => {
            openRef.current = false;
          }
        })
      })]
    })
  });
}
function InsertionPoint(props) {
  const {
    insertionPoint,
    isVisible,
    isBlockListEmpty
  } = (0, _data.useSelect)(select => {
    const {
      getBlockInsertionPoint,
      isBlockInsertionPointVisible,
      getBlockCount
    } = select(_store.store);
    const blockInsertionPoint = getBlockInsertionPoint();
    return {
      insertionPoint: blockInsertionPoint,
      isVisible: isBlockInsertionPointVisible(),
      isBlockListEmpty: getBlockCount(blockInsertionPoint?.rootClientId) === 0
    };
  }, []);
  if (!isVisible ||
  // Don't render the insertion point if the block list is empty.
  // The insertion point will be represented by the appender instead.
  isBlockListEmpty) {
    return null;
  }

  /**
   * Render a popover that overlays the block when the desired operation is to replace it.
   * Otherwise, render a popover in between blocks for the indication of inserting between them.
   */
  return insertionPoint.operation === 'replace' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_dropZone.default
  // Force remount to trigger the animation.
  , {
    ...props
  }, `${insertionPoint.rootClientId}-${insertionPoint.index}`) : /*#__PURE__*/(0, _jsxRuntime.jsx)(InbetweenInsertionPointPopover, {
    operation: insertionPoint.operation,
    nearestSide: insertionPoint.nearestSide,
    ...props
  });
}
//# sourceMappingURL=insertion-point.js.map