"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _clsx = _interopRequireDefault(require("clsx"));
var _components = require("@wordpress/components");
var _i18n = require("@wordpress/i18n");
var _blocks = require("@wordpress/blocks");
var _blockEditor = require("@wordpress/block-editor");
var _editor = require("@wordpress/editor");
var _data = require("@wordpress/data");
var _compose = require("@wordpress/compose");
var _element = require("@wordpress/element");
var _keycodes = require("@wordpress/keycodes");
var _lockUnlock = require("../../lock-unlock");
var _editorCanvasContainer = _interopRequireDefault(require("../editor-canvas-container"));
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const {
  ExperimentalBlockEditorProvider,
  useGlobalStyle,
  GlobalStylesContext,
  useGlobalStylesOutputWithConfig
} = (0, _lockUnlock.unlock)(_blockEditor.privateApis);
const {
  mergeBaseAndUserConfigs
} = (0, _lockUnlock.unlock)(_editor.privateApis);
const {
  Tabs
} = (0, _lockUnlock.unlock)(_components.privateApis);

// The content area of the Style Book is rendered within an iframe so that global styles
// are applied to elements within the entire content area. To support elements that are
// not part of the block previews, such as headings and layout for the block previews,
// additional CSS rules need to be passed into the iframe. These are hard-coded below.
// Note that button styles are unset, and then focus rules from the `Button` component are
// applied to the `button` element, targeted via `.edit-site-style-book__example`.
// This is to ensure that browser default styles for buttons are not applied to the previews.
const STYLE_BOOK_IFRAME_STYLES = `
	.edit-site-style-book__examples {
		max-width: 900px;
		margin: 0 auto;
	}

	.edit-site-style-book__example {
		border-radius: 2px;
		cursor: pointer;
		display: flex;
		flex-direction: column;
		gap: 40px;
		margin-bottom: 40px;
		padding: 16px;
		width: 100%;
		box-sizing: border-box;
		scroll-margin-top: 32px;
		scroll-margin-bottom: 32px;
	}

	.edit-site-style-book__example.is-selected {
		box-shadow: 0 0 0 1px var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba));
	}

	.edit-site-style-book__example:focus:not(:disabled) {
		box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba));
		outline: 3px solid transparent;
	}

	.edit-site-style-book__examples.is-wide .edit-site-style-book__example {
		flex-direction: row;
	}

	.edit-site-style-book__example-title {
		font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
		font-size: 11px;
		font-weight: 500;
		line-height: normal;
		margin: 0;
		text-align: left;
		text-transform: uppercase;
	}

	.edit-site-style-book__examples.is-wide .edit-site-style-book__example-title {
		text-align: right;
		width: 120px;
	}

	.edit-site-style-book__example-preview {
		width: 100%;
	}

	.edit-site-style-book__example-preview .block-editor-block-list__insertion-point,
	.edit-site-style-book__example-preview .block-list-appender {
		display: none;
	}

	.edit-site-style-book__example-preview .is-root-container > .wp-block:first-child {
		margin-top: 0;
	}
	.edit-site-style-book__example-preview .is-root-container > .wp-block:last-child {
		margin-bottom: 0;
	}
`;
function isObjectEmpty(object) {
  return !object || Object.keys(object).length === 0;
}
function getExamples() {
  const nonHeadingBlockExamples = (0, _blocks.getBlockTypes)().filter(blockType => {
    const {
      name,
      example,
      supports
    } = blockType;
    return name !== 'core/heading' && !!example && supports.inserter !== false;
  }).map(blockType => ({
    name: blockType.name,
    title: blockType.title,
    category: blockType.category,
    blocks: (0, _blocks.getBlockFromExample)(blockType.name, blockType.example)
  }));
  const isHeadingBlockRegistered = !!(0, _blocks.getBlockType)('core/heading');
  if (!isHeadingBlockRegistered) {
    return nonHeadingBlockExamples;
  }

  // Use our own example for the Heading block so that we can show multiple
  // heading levels.
  const headingsExample = {
    name: 'core/heading',
    title: (0, _i18n.__)('Headings'),
    category: 'text',
    blocks: [1, 2, 3, 4, 5, 6].map(level => {
      return (0, _blocks.createBlock)('core/heading', {
        content: (0, _i18n.sprintf)(
        // translators: %d: heading level e.g: "1", "2", "3"
        (0, _i18n.__)('Heading %d'), level),
        level
      });
    })
  };
  return [headingsExample, ...nonHeadingBlockExamples];
}
function StyleBook({
  enableResizing = true,
  isSelected,
  onClick,
  onSelect,
  showCloseButton = true,
  onClose,
  showTabs = true,
  userConfig = {}
}) {
  const [resizeObserver, sizes] = (0, _compose.useResizeObserver)();
  const [textColor] = useGlobalStyle('color.text');
  const [backgroundColor] = useGlobalStyle('color.background');
  const [examples] = (0, _element.useState)(getExamples);
  const tabs = (0, _element.useMemo)(() => (0, _blocks.getCategories)().filter(category => examples.some(example => example.category === category.slug)).map(category => ({
    name: category.slug,
    title: category.title,
    icon: category.icon
  })), [examples]);
  const {
    base: baseConfig
  } = (0, _element.useContext)(GlobalStylesContext);
  const mergedConfig = (0, _element.useMemo)(() => {
    if (!isObjectEmpty(userConfig) && !isObjectEmpty(baseConfig)) {
      return mergeBaseAndUserConfigs(baseConfig, userConfig);
    }
    return {};
  }, [baseConfig, userConfig]);

  // Copied from packages/edit-site/src/components/revisions/index.js
  // could we create a shared hook?
  const originalSettings = (0, _data.useSelect)(select => select(_blockEditor.store).getSettings(), []);
  const settings = (0, _element.useMemo)(() => ({
    ...originalSettings,
    __unstableIsPreviewMode: true
  }), [originalSettings]);
  const [globalStyles] = useGlobalStylesOutputWithConfig(mergedConfig);
  settings.styles = !isObjectEmpty(globalStyles) && !isObjectEmpty(userConfig) ? globalStyles : settings.styles;
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_editorCanvasContainer.default, {
    onClose: onClose,
    enableResizing: enableResizing,
    closeButtonLabel: showCloseButton ? (0, _i18n.__)('Close') : null,
    children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
      className: (0, _clsx.default)('edit-site-style-book', {
        'is-wide': sizes.width > 600,
        'is-button': !!onClick
      }),
      style: {
        color: textColor,
        background: backgroundColor
      },
      children: [resizeObserver, showTabs ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        className: "edit-site-style-book__tabs",
        children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Tabs, {
          children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Tabs.TabList, {
            children: tabs.map(tab => /*#__PURE__*/(0, _jsxRuntime.jsx)(Tabs.Tab, {
              tabId: tab.name,
              children: tab.title
            }, tab.name))
          }), tabs.map(tab => /*#__PURE__*/(0, _jsxRuntime.jsx)(Tabs.TabPanel, {
            tabId: tab.name,
            focusable: false,
            children: /*#__PURE__*/(0, _jsxRuntime.jsx)(StyleBookBody, {
              category: tab.name,
              examples: examples,
              isSelected: isSelected,
              onSelect: onSelect,
              settings: settings,
              sizes: sizes,
              title: tab.title
            })
          }, tab.name))]
        })
      }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(StyleBookBody, {
        examples: examples,
        isSelected: isSelected,
        onClick: onClick,
        onSelect: onSelect,
        settings: settings,
        sizes: sizes
      })]
    })
  });
}
const StyleBookBody = ({
  category,
  examples,
  isSelected,
  onClick,
  onSelect,
  settings,
  sizes,
  title
}) => {
  const [isFocused, setIsFocused] = (0, _element.useState)(false);

  // The presence of an `onClick` prop indicates that the Style Book is being used as a button.
  // In this case, add additional props to the iframe to make it behave like a button.
  const buttonModeProps = {
    role: 'button',
    onFocus: () => setIsFocused(true),
    onBlur: () => setIsFocused(false),
    onKeyDown: event => {
      if (event.defaultPrevented) {
        return;
      }
      const {
        keyCode
      } = event;
      if (onClick && (keyCode === _keycodes.ENTER || keyCode === _keycodes.SPACE)) {
        event.preventDefault();
        onClick(event);
      }
    },
    onClick: event => {
      if (event.defaultPrevented) {
        return;
      }
      if (onClick) {
        event.preventDefault();
        onClick(event);
      }
    },
    readonly: true
  };
  const buttonModeStyles = onClick ? 'body { cursor: pointer; } body * { pointer-events: none; }' : '';
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_blockEditor.__unstableIframe, {
    className: (0, _clsx.default)('edit-site-style-book__iframe', {
      'is-focused': isFocused && !!onClick,
      'is-button': !!onClick
    }),
    name: "style-book-canvas",
    tabIndex: 0,
    ...(onClick ? buttonModeProps : {}),
    children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.__unstableEditorStyles, {
      styles: settings.styles
    }), /*#__PURE__*/(0, _jsxRuntime.jsx)("style", {
      children:
      // Forming a "block formatting context" to prevent margin collapsing.
      // @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
      `.is-root-container { display: flow-root; }
						body { position: relative; padding: 32px !important; }` + STYLE_BOOK_IFRAME_STYLES + buttonModeStyles
    }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Examples, {
      className: (0, _clsx.default)('edit-site-style-book__examples', {
        'is-wide': sizes.width > 600
      }),
      examples: examples,
      category: category,
      label: title ? (0, _i18n.sprintf)(
      // translators: %s: Category of blocks, e.g. Text.
      (0, _i18n.__)('Examples of blocks in the %s category'), title) : (0, _i18n.__)('Examples of blocks'),
      isSelected: isSelected,
      onSelect: onSelect
    }, category)]
  });
};
const Examples = (0, _element.memo)(({
  className,
  examples,
  category,
  label,
  isSelected,
  onSelect
}) => {
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Composite, {
    orientation: "vertical",
    className: className,
    "aria-label": label,
    role: "grid",
    children: examples.filter(example => category ? example.category === category : true).map(example => /*#__PURE__*/(0, _jsxRuntime.jsx)(Example, {
      id: `example-${example.name}`,
      title: example.title,
      blocks: example.blocks,
      isSelected: isSelected(example.name),
      onClick: () => {
        onSelect?.(example.name);
      }
    }, example.name))
  });
});
const Example = ({
  id,
  title,
  blocks,
  isSelected,
  onClick
}) => {
  const originalSettings = (0, _data.useSelect)(select => select(_blockEditor.store).getSettings(), []);
  const settings = (0, _element.useMemo)(() => ({
    ...originalSettings,
    focusMode: false,
    // Disable "Spotlight mode".
    __unstableIsPreviewMode: true
  }), [originalSettings]);

  // Cache the list of blocks to avoid additional processing when the component is re-rendered.
  const renderedBlocks = (0, _element.useMemo)(() => Array.isArray(blocks) ? blocks : [blocks], [blocks]);
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    role: "row",
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      role: "gridcell",
      children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Composite.Item, {
        className: (0, _clsx.default)('edit-site-style-book__example', {
          'is-selected': isSelected
        }),
        id: id,
        "aria-label": (0, _i18n.sprintf)(
        // translators: %s: Title of a block, e.g. Heading.
        (0, _i18n.__)('Open %s styles in Styles panel'), title),
        render: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {}),
        role: "button",
        onClick: onClick,
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
          className: "edit-site-style-book__example-title",
          children: title
        }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
          className: "edit-site-style-book__example-preview",
          "aria-hidden": true,
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Disabled, {
            className: "edit-site-style-book__example-preview__content",
            children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ExperimentalBlockEditorProvider, {
              value: renderedBlocks,
              settings: settings,
              children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.BlockList, {
                renderAppender: false
              })
            })
          })
        })]
      })
    })
  });
};
var _default = exports.default = StyleBook;
//# sourceMappingURL=index.js.map