@wordpress/block-editor
Version:
8 lines (7 loc) • 6.11 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../src/components/inner-blocks/use-inner-block-template-sync.js"],
"sourcesContent": ["/**\n * External dependencies\n */\nimport fastDeepEqual from 'fast-deep-equal/es6/index.js';\n\n/**\n * WordPress dependencies\n */\nimport { useRef, useLayoutEffect } from '@wordpress/element';\nimport { useRegistry } from '@wordpress/data';\nimport { synchronizeBlocksWithTemplate } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\n\n/**\n * This hook makes sure that a block's inner blocks stay in sync with the given\n * block \"template\". The template is a block hierarchy to which inner blocks must\n * conform. If the blocks get \"out of sync\" with the template and the template\n * is meant to be locked (e.g. templateLock = \"all\" or templateLock = \"contentOnly\"),\n * then we replace the inner blocks with the correct value after synchronizing it with the template.\n *\n * @param {string} clientId The block client ID.\n * @param {Object} template The template to match.\n * @param {string} templateLock The template lock state for the inner blocks. For\n * example, if the template lock is set to \"all\",\n * then the inner blocks will stay in sync with the\n * template. If not defined or set to false, then\n * the inner blocks will not be synchronized with\n * the given template.\n * @param {boolean} templateInsertUpdatesSelection Whether or not to update the\n * block-editor selection state when inner blocks\n * are replaced after template synchronization.\n */\nexport default function useInnerBlockTemplateSync(\n\tclientId,\n\ttemplate,\n\ttemplateLock,\n\ttemplateInsertUpdatesSelection\n) {\n\t// Instead of adding a useSelect mapping here, please add to the useSelect\n\t// mapping in InnerBlocks! Every subscription impacts performance.\n\tconst registry = useRegistry();\n\n\t// Maintain a reference to the previous value so we can do a deep equality check.\n\tconst existingTemplateRef = useRef( null );\n\n\tuseLayoutEffect( () => {\n\t\tlet isCancelled = false;\n\n\t\tconst {\n\t\t\tgetBlocks,\n\t\t\tgetSelectedBlocksInitialCaretPosition,\n\t\t\tisBlockSelected,\n\t\t} = registry.select( blockEditorStore );\n\t\tconst { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } =\n\t\t\tregistry.dispatch( blockEditorStore );\n\n\t\t// There's an implicit dependency between useInnerBlockTemplateSync and useNestedSettingsUpdate\n\t\t// The former needs to happen after the latter and since the latter is using microtasks to batch updates (performance optimization),\n\t\t// we need to schedule this one in a microtask as well.\n\t\t// Example: If you remove queueMicrotask here, ctrl + click to insert quote block won't close the inserter.\n\t\twindow.queueMicrotask( () => {\n\t\t\tif ( isCancelled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only synchronize innerBlocks with template if innerBlocks are empty\n\t\t\t// or a locking \"all\" or \"contentOnly\" exists directly on the block.\n\t\t\tconst currentInnerBlocks = getBlocks( clientId );\n\t\t\tconst shouldApplyTemplate =\n\t\t\t\tcurrentInnerBlocks.length === 0 ||\n\t\t\t\ttemplateLock === 'all' ||\n\t\t\t\ttemplateLock === 'contentOnly';\n\n\t\t\tconst hasTemplateChanged = ! fastDeepEqual(\n\t\t\t\ttemplate,\n\t\t\t\texistingTemplateRef.current\n\t\t\t);\n\n\t\t\tif ( ! shouldApplyTemplate || ! hasTemplateChanged ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\texistingTemplateRef.current = template;\n\t\t\tconst nextBlocks = synchronizeBlocksWithTemplate(\n\t\t\t\tcurrentInnerBlocks,\n\t\t\t\ttemplate\n\t\t\t);\n\n\t\t\tif ( ! fastDeepEqual( nextBlocks, currentInnerBlocks ) ) {\n\t\t\t\t__unstableMarkNextChangeAsNotPersistent();\n\t\t\t\treplaceInnerBlocks(\n\t\t\t\t\tclientId,\n\t\t\t\t\tnextBlocks,\n\t\t\t\t\tcurrentInnerBlocks.length === 0 &&\n\t\t\t\t\t\ttemplateInsertUpdatesSelection &&\n\t\t\t\t\t\tnextBlocks.length !== 0 &&\n\t\t\t\t\t\tisBlockSelected( clientId ),\n\t\t\t\t\t// This ensures the \"initialPosition\" doesn't change when applying the template\n\t\t\t\t\t// If we're supposed to focus the block, we'll focus the first inner block\n\t\t\t\t\t// otherwise, we won't apply any auto-focus.\n\t\t\t\t\t// This ensures for instance that the focus stays in the inserter when inserting the \"buttons\" block.\n\t\t\t\t\tgetSelectedBlocksInitialCaretPosition()\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t\treturn () => {\n\t\t\tisCancelled = true;\n\t\t};\n\t}, [\n\t\ttemplate,\n\t\ttemplateLock,\n\t\tclientId,\n\t\tregistry,\n\t\ttemplateInsertUpdatesSelection,\n\t] );\n}\n"],
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAA0B;AAK1B,qBAAwC;AACxC,kBAA4B;AAC5B,oBAA8C;AAK9C,mBAA0C;AAqB3B,SAAR,0BACN,UACA,UACA,cACA,gCACC;AAGD,QAAM,eAAW,yBAAY;AAG7B,QAAM,0BAAsB,uBAAQ,IAAK;AAEzC,sCAAiB,MAAM;AACtB,QAAI,cAAc;AAElB,UAAM;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACD,IAAI,SAAS,OAAQ,aAAAA,KAAiB;AACtC,UAAM,EAAE,oBAAoB,wCAAwC,IACnE,SAAS,SAAU,aAAAA,KAAiB;AAMrC,WAAO,eAAgB,MAAM;AAC5B,UAAK,aAAc;AAClB;AAAA,MACD;AAIA,YAAM,qBAAqB,UAAW,QAAS;AAC/C,YAAM,sBACL,mBAAmB,WAAW,KAC9B,iBAAiB,SACjB,iBAAiB;AAElB,YAAM,qBAAqB,KAAE,WAAAC;AAAA,QAC5B;AAAA,QACA,oBAAoB;AAAA,MACrB;AAEA,UAAK,CAAE,uBAAuB,CAAE,oBAAqB;AACpD;AAAA,MACD;AAEA,0BAAoB,UAAU;AAC9B,YAAM,iBAAa;AAAA,QAClB;AAAA,QACA;AAAA,MACD;AAEA,UAAK,KAAE,WAAAA,SAAe,YAAY,kBAAmB,GAAI;AACxD,gDAAwC;AACxC;AAAA,UACC;AAAA,UACA;AAAA,UACA,mBAAmB,WAAW,KAC7B,kCACA,WAAW,WAAW,KACtB,gBAAiB,QAAS;AAAA;AAAA;AAAA;AAAA;AAAA,UAK3B,sCAAsC;AAAA,QACvC;AAAA,MACD;AAAA,IACD,CAAE;AAEF,WAAO,MAAM;AACZ,oBAAc;AAAA,IACf;AAAA,EACD,GAAG;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAE;AACH;",
"names": ["blockEditorStore", "fastDeepEqual"]
}