@wordpress/block-editor
Version:
227 lines (223 loc) • 8.15 kB
JavaScript
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
;