UNPKG

@wordpress/block-editor

Version:
227 lines (223 loc) 8.15 kB
"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 _blocks = require("@wordpress/blocks"); 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 { isOutlineMode, isFocusMode, temporarilyEditingAsBlocks } = (0, _data.useSelect)(select => { const { getSettings, getTemporarilyEditingAsBlocks, isTyping } = (0, _lockUnlock.unlock)(select(_store.store)); const { outlineMode, focusMode } = getSettings(); return { isOutlineMode: outlineMode && !isTyping(), isFocusMode: focusMode, 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 }) }, 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, getSelectedBlockClientIds, __unstableGetVisibleBlocks, getTemplateLock, getBlockEditingMode, isSectionBlock, isZoomOut: _isZoomOut, canInsertBlockType } = (0, _lockUnlock.unlock)(select(_store.store)); const _order = getBlockOrder(rootClientId); if (getSettings().isPreviewMode) { return { order: _order, selectedBlocks: EMPTY_ARRAY, visibleBlocks: EMPTY_SET }; } const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[0]; const showRootAppender = !rootClientId && !selectedBlockClientId && (!_order.length || !canInsertBlockType((0, _blocks.getDefaultBlockName)(), rootClientId)); const hasSelectedRoot = !!(rootClientId && selectedBlockClientId && rootClientId === selectedBlockClientId); return { order: _order, selectedBlocks: selectedBlockClientIds, visibleBlocks: __unstableGetVisibleBlocks(), isZoomOut: _isZoomOut(), shouldRenderAppender: !isSectionBlock(rootClientId) && getBlockEditingMode(rootClientId) !== 'disabled' && !getTemplateLock(rootClientId) && hasAppender && !_isZoomOut() && (hasCustomAppender || hasSelectedRoot || showRootAppender) }; }, [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