UNPKG

@wordpress/block-editor

Version:
444 lines (443 loc) 14.4 kB
// packages/block-editor/src/store/private-selectors.js import { createSelector, createRegistrySelector } from "@wordpress/data"; import { hasBlockSupport, privateApis as blocksPrivateApis } from "@wordpress/blocks"; import { getBlockOrder, getBlockParents, getBlockEditingMode, getSettings, canInsertBlockType, getBlockName, getTemplateLock, getClientIdsWithDescendants, getBlockRootClientId, getBlockAttributes } from "./selectors"; import { checkAllowListRecursive, getAllPatternsDependants, getInsertBlockTypeDependants, getGrammar, mapUserPattern } from "./utils"; import { STORE_NAME } from "./constants"; import { unlock } from "../lock-unlock"; import { selectBlockPatternsKey, reusableBlocksSelectKey, sectionRootClientIdKey, isIsolatedEditorKey } from "./private-keys"; import { getBlockSettings } from "./get-block-settings"; var { isContentBlock } = unlock(blocksPrivateApis); function isBlockInterfaceHidden(state) { return state.isBlockInterfaceHidden; } function getLastInsertedBlocksClientIds(state) { return state?.lastBlockInserted?.clientIds; } function getBlockWithoutAttributes(state, clientId) { return state.blocks.byClientId.get(clientId); } var isBlockSubtreeDisabled = (state, clientId) => { const isChildSubtreeDisabled = (childClientId) => { return getBlockEditingMode(state, childClientId) === "disabled" && getBlockOrder(state, childClientId).every( isChildSubtreeDisabled ); }; return getBlockOrder(state, clientId).every(isChildSubtreeDisabled); }; function isContainerInsertableToInContentOnlyMode(state, blockName, rootClientId) { const isBlockContentBlock = isContentBlock(blockName); const rootBlockName = getBlockName(state, rootClientId); const isContainerContentBlock = isContentBlock(rootBlockName); const isRootBlockMain = getSectionRootClientId(state) === rootClientId; return isRootBlockMain || isContainerContentBlock && isBlockContentBlock; } function getEnabledClientIdsTreeUnmemoized(state, rootClientId) { const blockOrder = getBlockOrder(state, rootClientId); const result = []; for (const clientId of blockOrder) { const innerBlocks = getEnabledClientIdsTreeUnmemoized( state, clientId ); if (getBlockEditingMode(state, clientId) !== "disabled") { result.push({ clientId, innerBlocks }); } else { result.push(...innerBlocks); } } return result; } var getEnabledClientIdsTree = createRegistrySelector( () => createSelector(getEnabledClientIdsTreeUnmemoized, (state) => [ state.blocks.order, state.derivedBlockEditingModes, state.blockEditingModes ]) ); var getEnabledBlockParents = createSelector( (state, clientId, ascending = false) => { return getBlockParents(state, clientId, ascending).filter( (parent) => getBlockEditingMode(state, parent) !== "disabled" ); }, (state) => [ state.blocks.parents, state.blockEditingModes, state.settings.templateLock, state.blockListSettings ] ); function getRemovalPromptData(state) { return state.removalPromptData; } function getBlockRemovalRules(state) { return state.blockRemovalRules; } function getOpenedBlockSettingsMenu(state) { return state.openedBlockSettingsMenu; } var getStyleOverrides = createSelector( (state) => { const clientIds = getClientIdsWithDescendants(state); const clientIdMap = clientIds.reduce((acc, clientId, index) => { acc[clientId] = index; return acc; }, {}); return [...state.styleOverrides].sort((overrideA, overrideB) => { const [, { clientId: clientIdA }] = overrideA; const [, { clientId: clientIdB }] = overrideB; const aIndex = clientIdMap[clientIdA] ?? -1; const bIndex = clientIdMap[clientIdB] ?? -1; return aIndex - bIndex; }); }, (state) => [state.blocks.order, state.styleOverrides] ); function getRegisteredInserterMediaCategories(state) { return state.registeredInserterMediaCategories; } var getInserterMediaCategories = createSelector( (state) => { const { settings: { inserterMediaCategories, allowedMimeTypes, enableOpenverseMediaCategory }, registeredInserterMediaCategories } = state; if (!inserterMediaCategories && !registeredInserterMediaCategories.length || !allowedMimeTypes) { return; } const coreInserterMediaCategoriesNames = inserterMediaCategories?.map(({ name }) => name) || []; const mergedCategories = [ ...inserterMediaCategories || [], ...(registeredInserterMediaCategories || []).filter( ({ name }) => !coreInserterMediaCategoriesNames.includes(name) ) ]; return mergedCategories.filter((category) => { if (!enableOpenverseMediaCategory && category.name === "openverse") { return false; } return Object.values(allowedMimeTypes).some( (mimeType) => mimeType.startsWith(`${category.mediaType}/`) ); }); }, (state) => [ state.settings.inserterMediaCategories, state.settings.allowedMimeTypes, state.settings.enableOpenverseMediaCategory, state.registeredInserterMediaCategories ] ); var hasAllowedPatterns = createRegistrySelector( (select) => createSelector( (state, rootClientId = null) => { const { getAllPatterns: getAllPatterns2 } = unlock(select(STORE_NAME)); const patterns = getAllPatterns2(); const { allowedBlockTypes } = getSettings(state); return patterns.some((pattern) => { const { inserter = true } = pattern; if (!inserter) { return false; } const grammar = getGrammar(pattern); return checkAllowListRecursive(grammar, allowedBlockTypes) && grammar.every( ({ name: blockName }) => canInsertBlockType(state, blockName, rootClientId) ); }); }, (state, rootClientId) => [ ...getAllPatternsDependants(select)(state), ...getInsertBlockTypeDependants(select)(state, rootClientId) ] ) ); var getPatternBySlug = createRegistrySelector( (select) => createSelector( (state, patternName) => { if (patternName?.startsWith("core/block/")) { const _id = parseInt( patternName.slice("core/block/".length), 10 ); const block = unlock(select(STORE_NAME)).getReusableBlocks().find(({ id }) => id === _id); if (!block) { return null; } return mapUserPattern( block, state.settings.__experimentalUserPatternCategories ); } return [ // This setting is left for back compat. ...state.settings.__experimentalBlockPatterns ?? [], ...state.settings[selectBlockPatternsKey]?.(select) ?? [] ].find(({ name }) => name === patternName); }, (state, patternName) => patternName?.startsWith("core/block/") ? [ unlock(select(STORE_NAME)).getReusableBlocks(), state.settings.__experimentalReusableBlocks ] : [ state.settings.__experimentalBlockPatterns, state.settings[selectBlockPatternsKey]?.(select) ] ) ); var getAllPatterns = createRegistrySelector( (select) => createSelector((state) => { return [ ...unlock(select(STORE_NAME)).getReusableBlocks().map( (userPattern) => mapUserPattern( userPattern, state.settings.__experimentalUserPatternCategories ) ), // This setting is left for back compat. ...state.settings.__experimentalBlockPatterns ?? [], ...state.settings[selectBlockPatternsKey]?.(select) ?? [] ].filter( (x, index, arr) => index === arr.findIndex((y) => x.name === y.name) ); }, getAllPatternsDependants(select)) ); var EMPTY_ARRAY = []; var getReusableBlocks = createRegistrySelector( (select) => (state) => { const reusableBlocksSelect = state.settings[reusableBlocksSelectKey]; return (reusableBlocksSelect ? reusableBlocksSelect(select) : state.settings.__experimentalReusableBlocks) ?? EMPTY_ARRAY; } ); function getLastFocus(state) { return state.lastFocus; } function isDragging(state) { return state.isDragging; } function getExpandedBlock(state) { return state.expandedBlock; } var getContentLockingParent = (state, clientId) => { let current = clientId; let result; while (!result && (current = state.blocks.parents.get(current))) { if (getTemplateLock(state, current) === "contentOnly") { result = current; } } return result; }; var getParentSectionBlock = (state, clientId) => { let current = clientId; let result; while (current = state.blocks.parents.get(current)) { if (isSectionBlock(state, current)) { result = current; } } return result; }; function isSectionBlock(state, clientId) { if (clientId === state.editedContentOnlySection) { return false; } const blockName = getBlockName(state, clientId); if (blockName === "core/block") { return true; } const attributes = getBlockAttributes(state, clientId); const isTemplatePart = blockName === "core/template-part"; const isIsolatedEditor = state.settings?.[isIsolatedEditorKey]; if ((attributes?.metadata?.patternName || isTemplatePart) && !!window?.__experimentalContentOnlyPatternInsertion && !isIsolatedEditor) { return true; } const hasContentOnlyTempateLock = getTemplateLock(state, clientId) === "contentOnly"; const rootClientId = getBlockRootClientId(state, clientId); const hasRootContentOnlyTemplateLock = getTemplateLock(state, rootClientId) === "contentOnly"; if (hasContentOnlyTempateLock && !hasRootContentOnlyTemplateLock) { return true; } return false; } function getEditedContentOnlySection(state) { return state.editedContentOnlySection; } function isWithinEditedContentOnlySection(state, clientId) { if (!state.editedContentOnlySection) { return false; } if (state.editedContentOnlySection === clientId) { return true; } let current = clientId; while (current = state.blocks.parents.get(current)) { if (state.editedContentOnlySection === current) { return true; } } return false; } var getBlockStyles = createSelector( (state, clientIds) => clientIds.reduce((styles, clientId) => { styles[clientId] = state.blocks.attributes.get(clientId)?.style; return styles; }, {}), (state, clientIds) => [ ...clientIds.map( (clientId) => state.blocks.attributes.get(clientId)?.style ) ] ); function getSectionRootClientId(state) { return state.settings?.[sectionRootClientIdKey]; } function isZoomOut(state) { return state.zoomLevel === "auto-scaled" || state.zoomLevel < 100; } function getZoomLevel(state) { return state.zoomLevel; } function getClosestAllowedInsertionPoint(state, name, clientId = "") { const blockNames = Array.isArray(name) ? name : [name]; const areBlockNamesAllowedInClientId = (id) => blockNames.every( (currentName) => canInsertBlockType(state, currentName, id) ); if (!clientId) { if (areBlockNamesAllowedInClientId(clientId)) { return clientId; } const sectionRootClientId = getSectionRootClientId(state); if (sectionRootClientId && areBlockNamesAllowedInClientId(sectionRootClientId)) { return sectionRootClientId; } return null; } let current = clientId; while (current !== null && !areBlockNamesAllowedInClientId(current)) { const parentClientId = getBlockRootClientId(state, current); current = parentClientId; } return current; } function getClosestAllowedInsertionPointForPattern(state, pattern, clientId) { const { allowedBlockTypes } = getSettings(state); const isAllowed = checkAllowListRecursive( getGrammar(pattern), allowedBlockTypes ); if (!isAllowed) { return null; } const names = getGrammar(pattern).map(({ blockName: name }) => name); return getClosestAllowedInsertionPoint(state, names, clientId); } function getInsertionPoint(state) { return state.insertionPoint; } var isBlockHidden = (state, clientId) => { const blockName = getBlockName(state, clientId); if (!hasBlockSupport(state, blockName, "visibility", true)) { return false; } const attributes = state.blocks.attributes.get(clientId); return attributes?.metadata?.blockVisibility === false; }; function hasBlockSpotlight(state) { return !!state.hasBlockSpotlight || !!state.editedContentOnlySection; } function isEditLockedBlock(state, clientId) { const attributes = getBlockAttributes(state, clientId); return !!attributes?.lock?.edit; } function isMoveLockedBlock(state, clientId) { const attributes = getBlockAttributes(state, clientId); if (attributes?.lock?.move !== void 0) { return !!attributes?.lock?.move; } const rootClientId = getBlockRootClientId(state, clientId); const templateLock = getTemplateLock(state, rootClientId); return templateLock === "all"; } function isRemoveLockedBlock(state, clientId) { const attributes = getBlockAttributes(state, clientId); if (attributes?.lock?.remove !== void 0) { return !!attributes?.lock?.remove; } const rootClientId = getBlockRootClientId(state, clientId); const templateLock = getTemplateLock(state, rootClientId); return templateLock === "all" || templateLock === "insert"; } function isLockedBlock(state, clientId) { return isEditLockedBlock(state, clientId) || isMoveLockedBlock(state, clientId) || isRemoveLockedBlock(state, clientId); } export { getAllPatterns, getBlockRemovalRules, getBlockSettings, getBlockStyles, getBlockWithoutAttributes, getClosestAllowedInsertionPoint, getClosestAllowedInsertionPointForPattern, getContentLockingParent, getEditedContentOnlySection, getEnabledBlockParents, getEnabledClientIdsTree, getExpandedBlock, getInserterMediaCategories, getInsertionPoint, getLastFocus, getLastInsertedBlocksClientIds, getOpenedBlockSettingsMenu, getParentSectionBlock, getPatternBySlug, getRegisteredInserterMediaCategories, getRemovalPromptData, getReusableBlocks, getSectionRootClientId, getStyleOverrides, getZoomLevel, hasAllowedPatterns, hasBlockSpotlight, isBlockHidden, isBlockInterfaceHidden, isBlockSubtreeDisabled, isContainerInsertableToInContentOnlyMode, isDragging, isEditLockedBlock, isLockedBlock, isMoveLockedBlock, isRemoveLockedBlock, isSectionBlock, isWithinEditedContentOnlySection, isZoomOut }; //# sourceMappingURL=private-selectors.js.map