UNPKG

@wordpress/block-library

Version:
170 lines (169 loc) 5.62 kB
// packages/block-library/src/tabs/use-tab-list-sync.js import { createBlock } from "@wordpress/blocks"; import { store as blockEditorStore } from "@wordpress/block-editor"; import { useDispatch } from "@wordpress/data"; import { useEffect, useRef } from "@wordpress/element"; function useTabListSync({ tabPanels, tabs, tabPanelsClientId, tabsListClientId }) { const { removeBlock, insertBlocks, replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = useDispatch(blockEditorStore); const prevSyncStateRef = useRef(null); useEffect(() => { if (prevSyncStateRef.current === null) { prevSyncStateRef.current = { tabPanels: [...tabPanels], tabs: [...tabs] }; return; } const { tabPanels: prevTabPanels, tabs: prevTabs } = prevSyncStateRef.current; const tabPanelCountChange = tabPanels.length - prevTabPanels.length; const tabCountChange = tabs.length - prevTabs.length; const tabPanelsInserted = tabPanelCountChange > 0; const tabsInserted = tabCountChange > 0; if (tabPanelCountChange === tabCountChange) { if (tabPanelCountChange === 0 && tabPanelsClientId && tabs.some((m, i) => m.clientId !== prevTabs[i]?.clientId)) { const reorderedTabPanels = tabs.map((tab) => { const oldIndex = prevTabs.findIndex( (pm) => pm.clientId === tab.clientId ); return oldIndex !== -1 ? tabPanels[oldIndex] : null; }).filter(Boolean); if (reorderedTabPanels.length === tabPanels.length) { __unstableMarkNextChangeAsNotPersistent(); replaceInnerBlocks( tabPanelsClientId, reorderedTabPanels, false ); } } prevSyncStateRef.current = { tabPanels: [...tabPanels], tabs: [...tabs] }; return; } if (tabPanelCountChange > 0 && tabCountChange > 0 || tabPanelCountChange < 0 && tabCountChange < 0) { prevSyncStateRef.current = { tabPanels: [...tabPanels], tabs: [...tabs] }; return; } if (tabPanelsInserted && !tabsListClientId) { return; } if (tabsInserted && !tabPanelsClientId) { return; } prevSyncStateRef.current = { tabPanels: [...tabPanels], tabs: [...tabs] }; const currentTabPanelIds = new Set( tabPanels.map((t) => t.clientId) ); const currentTabIds = new Set(tabs.map((m) => m.clientId)); if (tabPanelCountChange < 0) { const removedIndices = prevTabPanels.map( (t, i) => !currentTabPanelIds.has(t.clientId) ? i : -1 ).filter((i) => i !== -1); const removedSet = new Set(removedIndices); removedIndices.forEach((removedIndex) => { if (tabs[removedIndex]) { __unstableMarkNextChangeAsNotPersistent(); removeBlock(tabs[removedIndex].clientId, false); } }); prevSyncStateRef.current.tabs = prevSyncStateRef.current.tabs.filter( (_, i) => !removedSet.has(i) ); } else if (tabCountChange < 0) { const removedIndices = prevTabs.map( (m, i) => !currentTabIds.has(m.clientId) ? i : -1 ).filter((i) => i !== -1); const removedSet = new Set(removedIndices); removedIndices.forEach((removedIndex) => { if (tabPanels[removedIndex]) { __unstableMarkNextChangeAsNotPersistent(); removeBlock(tabPanels[removedIndex].clientId, false); } }); prevSyncStateRef.current.tabPanels = prevSyncStateRef.current.tabPanels.filter( (_, i) => !removedSet.has(i) ); } else if (tabPanelsInserted) { const prevTabPanelIds = new Set( prevTabPanels.map((t) => t.clientId) ); const newTabs = tabPanels.map( (tabPanel, tabPanelIndex) => !prevTabPanelIds.has(tabPanel.clientId) ? { tabPanelIndex, block: createBlock("core/tab", {}) } : null ).filter(Boolean); if (newTabs.length > 0) { __unstableMarkNextChangeAsNotPersistent(); insertBlocks( newTabs.map(({ block }) => block), newTabs[0].tabPanelIndex, tabsListClientId, false ); newTabs.forEach(({ tabPanelIndex, block }) => { prevSyncStateRef.current.tabs.splice(tabPanelIndex, 0, { clientId: block.clientId }); }); } } else if (tabsInserted) { const prevTabIds = new Set(prevTabs.map((m) => m.clientId)); const newTabPanels = tabs.map((tab, tabIndex) => { if (prevTabIds.has(tab.clientId)) { return null; } const label = tabPanels[tabIndex - 1]?.attributes?.label ?? tabPanels[tabIndex]?.attributes?.label ?? ""; return { tabIndex, block: createBlock("core/tab-panel", { label }) }; }).filter(Boolean); if (newTabPanels.length > 0) { __unstableMarkNextChangeAsNotPersistent(); insertBlocks( newTabPanels.map(({ block }) => block), newTabPanels[0].tabIndex, tabPanelsClientId, false ); newTabPanels.forEach(({ tabIndex, block }) => { prevSyncStateRef.current.tabPanels.splice(tabIndex, 0, { clientId: block.clientId }); }); } } }, [ tabPanels, tabs, removeBlock, insertBlocks, replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent, tabsListClientId, tabPanelsClientId ]); } export { useTabListSync as default }; //# sourceMappingURL=use-tab-list-sync.mjs.map