// packages/editor/src/components/visual-editor/index.js
import clsx from "clsx";
import {
  BlockList,
  store as blockEditorStore,
  __unstableUseTypewriter as useTypewriter,
  __unstableUseTypingObserver as useTypingObserver,
  useSettings,
  RecursionProvider,
  privateApis as blockEditorPrivateApis,
  __experimentalUseResizeCanvas as useResizeCanvas
} from "@wordpress/block-editor";
import { useEffect, useRef, useMemo } from "@wordpress/element";
import { useSelect } from "@wordpress/data";
import { parse } from "@wordpress/blocks";
import { store as coreStore } from "@wordpress/core-data";
import { useMergeRefs, useViewportMatch } from "@wordpress/compose";
import PostTitle from "../post-title/index.js";
import { store as editorStore } from "../../store/index.js";
import { unlock } from "../../lock-unlock.js";
import EditTemplateBlocksNotification from "./edit-template-blocks-notification.js";
import ResizableEditor from "../resizable-editor/index.js";
import useSelectNearestEditableBlock from "./use-select-nearest-editable-block.js";
import {
  NAVIGATION_POST_TYPE,
  PATTERN_POST_TYPE,
  TEMPLATE_PART_POST_TYPE,
  TEMPLATE_POST_TYPE,
  DESIGN_POST_TYPES
} from "../../store/constants.js";
import { useZoomOutModeExit } from "./use-zoom-out-mode-exit.js";
import { usePaddingAppender } from "./use-padding-appender.js";
import { useEditContentOnlySectionExit } from "./use-edit-content-only-section-exit.js";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var {
  LayoutStyle,
  useLayoutClasses,
  useLayoutStyles,
  ExperimentalBlockCanvas: BlockCanvas,
  useFlashEditableBlocks
} = unlock(blockEditorPrivateApis);
function getPostContentAttributes(blocks) {
  for (let i = 0; i < blocks.length; i++) {
    if (blocks[i].name === "core/post-content") {
      return blocks[i].attributes;
    }
    if (blocks[i].innerBlocks.length) {
      const nestedPostContent = getPostContentAttributes(
        blocks[i].innerBlocks
      );
      if (nestedPostContent) {
        return nestedPostContent;
      }
    }
  }
}
function checkForPostContentAtRootLevel(blocks) {
  for (let i = 0; i < blocks.length; i++) {
    if (blocks[i].name === "core/post-content") {
      return true;
    }
  }
  return false;
}
function VisualEditor({
  // Ideally as we unify post and site editors, we won't need these props.
  autoFocus,
  disableIframe = false,
  iframeProps,
  contentRef,
  className
}) {
  const isMobileViewport = useViewportMatch("small", "<");
  const {
    renderingMode,
    postContentAttributes,
    editedPostTemplate = {},
    wrapperBlockName,
    wrapperUniqueId,
    deviceType,
    isFocusedEntity,
    isDesignPostType,
    postType,
    isPreview,
    styles,
    canvasMinHeight
  } = useSelect((select) => {
    const {
      getCurrentPostId,
      getCurrentPostType,
      getCurrentTemplateId,
      getEditorSettings,
      getRenderingMode,
      getDeviceType,
      getCanvasMinHeight
    } = unlock(select(editorStore));
    const { getPostType, getEditedEntityRecord } = select(coreStore);
    const postTypeSlug = getCurrentPostType();
    const _renderingMode = getRenderingMode();
    let _wrapperBlockName;
    if (postTypeSlug === PATTERN_POST_TYPE) {
      _wrapperBlockName = "core/block";
    } else if (_renderingMode === "post-only") {
      _wrapperBlockName = "core/post-content";
    }
    const editorSettings = getEditorSettings();
    const supportsTemplateMode = editorSettings.supportsTemplateMode;
    const postTypeObject = getPostType(postTypeSlug);
    const currentTemplateId = getCurrentTemplateId();
    const template = currentTemplateId ? getEditedEntityRecord(
      "postType",
      TEMPLATE_POST_TYPE,
      currentTemplateId
    ) : void 0;
    return {
      renderingMode: _renderingMode,
      postContentAttributes: editorSettings.postContentAttributes,
      isDesignPostType: DESIGN_POST_TYPES.includes(postTypeSlug),
      // Post template fetch returns a 404 on classic themes, which
      // messes with e2e tests, so check it's a block theme first.
      editedPostTemplate: postTypeObject?.viewable && supportsTemplateMode ? template : void 0,
      wrapperBlockName: _wrapperBlockName,
      wrapperUniqueId: getCurrentPostId(),
      deviceType: getDeviceType(),
      isFocusedEntity: !!editorSettings.onNavigateToPreviousEntityRecord,
      postType: postTypeSlug,
      isPreview: editorSettings.isPreviewMode,
      styles: editorSettings.styles,
      canvasMinHeight: getCanvasMinHeight()
    };
  }, []);
  const { isCleanNewPost } = useSelect(editorStore);
  const {
    hasRootPaddingAwareAlignments,
    themeHasDisabledLayoutStyles,
    themeSupportsLayout,
    isZoomedOut
  } = useSelect((select) => {
    const { getSettings, isZoomOut: _isZoomOut } = unlock(
      select(blockEditorStore)
    );
    const _settings = getSettings();
    return {
      themeHasDisabledLayoutStyles: _settings.disableLayoutStyles,
      themeSupportsLayout: _settings.supportsLayout,
      hasRootPaddingAwareAlignments: _settings.__experimentalFeatures?.useRootPaddingAwareAlignments,
      isZoomedOut: _isZoomOut()
    };
  }, []);
  const localRef = useRef();
  const deviceStyles = useResizeCanvas(deviceType);
  const [globalLayoutSettings] = useSettings("layout");
  const fallbackLayout = useMemo(() => {
    if (renderingMode !== "post-only" || isDesignPostType) {
      return { type: "default" };
    }
    if (themeSupportsLayout) {
      return { ...globalLayoutSettings, type: "constrained" };
    }
    return { type: "default" };
  }, [
    renderingMode,
    themeSupportsLayout,
    globalLayoutSettings,
    isDesignPostType
  ]);
  const newestPostContentAttributes = useMemo(() => {
    if (!editedPostTemplate?.content && !editedPostTemplate?.blocks && postContentAttributes) {
      return postContentAttributes;
    }
    if (editedPostTemplate?.blocks) {
      return getPostContentAttributes(editedPostTemplate?.blocks);
    }
    const parseableContent = typeof editedPostTemplate?.content === "string" ? editedPostTemplate?.content : "";
    return getPostContentAttributes(parse(parseableContent)) || {};
  }, [
    editedPostTemplate?.content,
    editedPostTemplate?.blocks,
    postContentAttributes
  ]);
  const hasPostContentAtRootLevel = useMemo(() => {
    if (!editedPostTemplate?.content && !editedPostTemplate?.blocks) {
      return false;
    }
    if (editedPostTemplate?.blocks) {
      return checkForPostContentAtRootLevel(editedPostTemplate?.blocks);
    }
    const parseableContent = typeof editedPostTemplate?.content === "string" ? editedPostTemplate?.content : "";
    return checkForPostContentAtRootLevel(parse(parseableContent)) || false;
  }, [editedPostTemplate?.content, editedPostTemplate?.blocks]);
  const { layout = {}, align = "" } = newestPostContentAttributes || {};
  const postContentLayoutClasses = useLayoutClasses(
    newestPostContentAttributes,
    "core/post-content"
  );
  const blockListLayoutClass = clsx(
    {
      "is-layout-flow": !themeSupportsLayout
    },
    themeSupportsLayout && postContentLayoutClasses,
    align && `align${align}`
  );
  const postContentLayoutStyles = useLayoutStyles(
    newestPostContentAttributes,
    "core/post-content",
    ".block-editor-block-list__layout.is-root-container"
  );
  const postContentLayout = useMemo(() => {
    return layout && (layout?.type === "constrained" || layout?.inherit || layout?.contentSize || layout?.wideSize) ? { ...globalLayoutSettings, ...layout, type: "constrained" } : { ...globalLayoutSettings, ...layout, type: "default" };
  }, [
    layout?.type,
    layout?.inherit,
    layout?.contentSize,
    layout?.wideSize,
    globalLayoutSettings
  ]);
  const blockListLayout = postContentAttributes ? postContentLayout : fallbackLayout;
  const postEditorLayout = blockListLayout?.type === "default" && !hasPostContentAtRootLevel ? fallbackLayout : blockListLayout;
  const observeTypingRef = useTypingObserver();
  const titleRef = useRef();
  useEffect(() => {
    if (!autoFocus || !isCleanNewPost()) {
      return;
    }
    titleRef?.current?.focus();
  }, [autoFocus, isCleanNewPost]);
  const alignCSS = `.is-root-container.alignwide { max-width: var(--wp--style--global--wide-size); margin-left: auto; margin-right: auto;}
		.is-root-container.alignwide:where(.is-layout-flow) > :not(.alignleft):not(.alignright) { max-width: var(--wp--style--global--wide-size);}
		.is-root-container.alignfull { max-width: none; margin-left: auto; margin-right: auto;}
		.is-root-container.alignfull:where(.is-layout-flow) > :not(.alignleft):not(.alignright) { max-width: none;}`;
  const enableResizing = [
    NAVIGATION_POST_TYPE,
    TEMPLATE_PART_POST_TYPE,
    PATTERN_POST_TYPE
  ].includes(postType) && // Disable in previews / view mode.
  !isPreview && // Disable resizing in mobile viewport.
  !isMobileViewport && // Disable resizing in zoomed-out mode.
  !isZoomedOut;
  const calculatedMinHeight = useMemo(() => {
    if (!localRef.current) {
      return canvasMinHeight;
    }
    const { ownerDocument } = localRef.current;
    const scrollTop = ownerDocument.documentElement.scrollTop || ownerDocument.body.scrollTop;
    return canvasMinHeight + scrollTop;
  }, [canvasMinHeight]);
  const [paddingAppenderRef, paddingStyle] = usePaddingAppender(
    !isPreview && renderingMode === "post-only" && !isDesignPostType
  );
  const iframeStyles = useMemo(() => {
    return [
      ...styles ?? [],
      {
        // Ensures margins of children are contained so that the body background paints behind them.
        // Otherwise, the background of html (when zoomed out) would show there and appear broken. It's
        // important mostly for post-only views yet conceivably an issue in templated views too.
        css: `:where(.block-editor-iframe__body){display:flow-root;${calculatedMinHeight ? `min-height:${calculatedMinHeight}px;` : ""}}.is-root-container{display:flow-root;${// Some themes will have `min-height: 100vh` for the root container,
        // which isn't a requirement in auto resize mode.
        enableResizing ? "min-height:0!important;" : ""}}
				${paddingStyle ? paddingStyle : ""}
				${enableResizing ? `.block-editor-iframe__html{background:var(--wp-editor-canvas-background);display:flex;align-items:center;justify-content:center;min-height:100vh;}.block-editor-iframe__body{width:100%;}` : ""}`
        // The CSS above centers the body content vertically when resizing is enabled and applies a background
        // color to the iframe HTML element to match the background color of the editor canvas.
      }
    ];
  }, [styles, enableResizing, calculatedMinHeight, paddingStyle]);
  const typewriterRef = useTypewriter();
  contentRef = useMergeRefs([
    localRef,
    contentRef,
    renderingMode === "post-only" ? typewriterRef : null,
    useFlashEditableBlocks({
      isEnabled: renderingMode === "template-locked"
    }),
    useSelectNearestEditableBlock({
      isEnabled: renderingMode === "template-locked"
    }),
    useZoomOutModeExit(),
    paddingAppenderRef,
    useEditContentOnlySectionExit()
  ]);
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: clsx(
        "editor-visual-editor",
        // this class is here for backward compatibility reasons.
        "edit-post-visual-editor",
        className,
        {
          "has-padding": isFocusedEntity || enableResizing,
          "is-resizable": enableResizing,
          "is-iframed": !disableIframe
        }
      ),
      children: /* @__PURE__ */ jsx(ResizableEditor, { enableResizing, height: "100%", children: /* @__PURE__ */ jsxs(
        BlockCanvas,
        {
          shouldIframe: !disableIframe,
          contentRef,
          styles: iframeStyles,
          height: "100%",
          iframeProps: {
            ...iframeProps,
            style: {
              ...iframeProps?.style,
              ...deviceStyles
            }
          },
          children: [
            themeSupportsLayout && !themeHasDisabledLayoutStyles && renderingMode === "post-only" && !isDesignPostType && /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx(
                LayoutStyle,
                {
                  selector: ".editor-visual-editor__post-title-wrapper",
                  layout: fallbackLayout
                }
              ),
              /* @__PURE__ */ jsx(
                LayoutStyle,
                {
                  selector: ".block-editor-block-list__layout.is-root-container",
                  layout: postEditorLayout
                }
              ),
              align && /* @__PURE__ */ jsx(LayoutStyle, { css: alignCSS }),
              postContentLayoutStyles && /* @__PURE__ */ jsx(
                LayoutStyle,
                {
                  layout: postContentLayout,
                  css: postContentLayoutStyles
                }
              )
            ] }),
            renderingMode === "post-only" && !isDesignPostType && /* @__PURE__ */ jsx(
              "div",
              {
                className: clsx(
                  "editor-visual-editor__post-title-wrapper",
                  // The following class is only here for backward compatibility
                  // some themes might be using it to style the post title.
                  "edit-post-visual-editor__post-title-wrapper",
                  {
                    "has-global-padding": hasRootPaddingAwareAlignments
                  }
                ),
                contentEditable: false,
                ref: observeTypingRef,
                style: {
                  // This is using inline styles
                  // so it's applied for both iframed and non iframed editors.
                  marginTop: "4rem"
                },
                children: /* @__PURE__ */ jsx(PostTitle, { ref: titleRef })
              }
            ),
            /* @__PURE__ */ jsxs(
              RecursionProvider,
              {
                blockName: wrapperBlockName,
                uniqueId: wrapperUniqueId,
                children: [
                  /* @__PURE__ */ jsx(
                    BlockList,
                    {
                      className: clsx(
                        "is-" + deviceType.toLowerCase() + "-preview",
                        renderingMode !== "post-only" || isDesignPostType ? "wp-site-blocks" : `${blockListLayoutClass} wp-block-post-content`,
                        // Ensure root level blocks receive default/flow blockGap styling rules.
                        {
                          "has-global-padding": renderingMode === "post-only" && !isDesignPostType && hasRootPaddingAwareAlignments
                        }
                      ),
                      layout: blockListLayout,
                      dropZoneElement: (
                        // When iframed, pass in the html element of the iframe to
                        // ensure the drop zone extends to the edges of the iframe.
                        disableIframe ? localRef.current : localRef.current?.parentNode
                      ),
                      __unstableDisableDropZone: (
                        // In template preview mode, disable drop zones at the root of the template.
                        renderingMode === "template-locked" ? true : false
                      )
                    }
                  ),
                  renderingMode === "template-locked" && /* @__PURE__ */ jsx(
                    EditTemplateBlocksNotification,
                    {
                      contentRef: localRef
                    }
                  )
                ]
              }
            )
          ]
        }
      ) })
    }
  );
}
var visual_editor_default = VisualEditor;
export {
  visual_editor_default as default
};
//# sourceMappingURL=index.js.map
