@wordpress/block-library
Version:
Block library for the WordPress editor.
170 lines (169 loc) • 5.62 kB
JavaScript
// 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