From 4273ea7b39c26760ffc71503eb0b14803e491d37 Mon Sep 17 00:00:00 2001 From: Jeremie Pardou <571533+jrmi@users.noreply.github.com> Date: Mon, 15 Jan 2024 14:56:18 +0100 Subject: [PATCH] Get linked item is now recursive --- src/lib/board/Items/ItemList.jsx | 1 + src/lib/board/Items/useItemActions.js | 31 ++++++++++------------ src/lib/board/Items/useItemInteraction.js | 4 +-- src/lib/board/store/main.jsx | 4 +-- src/lib/utils.js | 32 +++++++++++++++++++++++ 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/lib/board/Items/ItemList.jsx b/src/lib/board/Items/ItemList.jsx index 8b2d7c5..217c901 100644 --- a/src/lib/board/Items/ItemList.jsx +++ b/src/lib/board/Items/ItemList.jsx @@ -29,6 +29,7 @@ const ItemList = () => { top: `${boardSize / 2}px`, left: `${boardSize / 2}px`, display: "inline-block", + lineHeight: 0, }); return itemList.map((itemId) => ( diff --git a/src/lib/board/Items/useItemActions.js b/src/lib/board/Items/useItemActions.js index 7fa812d..75c68dd 100644 --- a/src/lib/board/Items/useItemActions.js +++ b/src/lib/board/Items/useItemActions.js @@ -9,6 +9,7 @@ import { insideClass, hasClass, snapToGrid, + getLinkedItems, } from "@/utils"; import useItemInteraction from "./useItemInteraction"; @@ -105,18 +106,14 @@ const useItemActions = () => { const moveItems = React.useCallback( (itemIds, posDelta) => { - const prevMap = getStoreItems(); - - const itemIdsWithLinkedItems = itemIds - .map((itemId) => { - return [itemId, ...(prevMap[itemId].linkedItems || [])]; - }) - .flat(); + moveStoreItems( + getLinkedItems(getStoreItems(), getItemIds(), itemIds), + posDelta + ); - moveStoreItems(itemIdsWithLinkedItems, posDelta); updateItemExtent(); }, - [getStoreItems, moveStoreItems, updateItemExtent] + [getItemIds, getStoreItems, moveStoreItems, updateItemExtent] ); const putItemsOnTop = React.useCallback( @@ -168,16 +165,15 @@ const useItemActions = () => { const placeItems = React.useCallback( (itemIds, gridConfig) => { - const prevMap = getStoreItems(); - - // Put moved items on top - const itemIdsWithLinkedItems = itemIds - .map((itemId) => { - return [itemId, ...(prevMap[itemId].linkedItems || [])]; - }) - .flat(); + // Put all moved items on top + const itemIdsWithLinkedItems = getLinkedItems( + getStoreItems(), + getItemIds(), + itemIds + ); putItemsOnTop(itemIdsWithLinkedItems); + // Remove moving state batchUpdateItems(itemIdsWithLinkedItems, (item) => { const newItem = { ...item }; @@ -192,6 +188,7 @@ const useItemActions = () => { [ batchUpdateItems, callPlaceInteractions, + getItemIds, getStoreItems, putItemsOnTop, stickOnGrid, diff --git a/src/lib/board/Items/useItemInteraction.js b/src/lib/board/Items/useItemInteraction.js index 0a7ab83..385ee6e 100644 --- a/src/lib/board/Items/useItemInteraction.js +++ b/src/lib/board/Items/useItemInteraction.js @@ -21,8 +21,8 @@ const useItemInteraction = (interaction) => { ); const call = React.useCallback( - (items) => { - callInteractions(interaction, items); + (itemIds) => { + callInteractions(interaction, itemIds); }, [callInteractions, interaction] ); diff --git a/src/lib/board/store/main.jsx b/src/lib/board/store/main.jsx index 3149d38..2ae4b46 100644 --- a/src/lib/board/store/main.jsx +++ b/src/lib/board/store/main.jsx @@ -56,10 +56,10 @@ const itemInteractions = (set, get) => ({ interactions: { ...state.interactions, [interaction]: nextInteraction }, }; }), - callInteractions: (interaction, items) => { + callInteractions: (interaction, itemIds) => { if (!get().interactions[interaction]) return; get().interactions[interaction].forEach((callback) => { - callback(items); + callback(itemIds); }); }, }); diff --git a/src/lib/utils.js b/src/lib/utils.js index 264c4f5..f562a7c 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -190,6 +190,38 @@ export const getItemsBoundingBox = (itemIds, wrapper = document) => { return result; }; +const getLinkedItemsRecursive = (itemMap, itemIds, alreadyMet = null) => { + if (alreadyMet === null) { + alreadyMet = new Set(); + } + + if (!itemIds || itemIds.length === 0) { + return []; + } + return itemIds + .map((itemId) => { + if (alreadyMet.has(itemId)) { + return []; + } else { + alreadyMet.add(itemId); + return [ + itemId, + ...getLinkedItemsRecursive( + itemMap, + itemMap[itemId].linkedItems, + alreadyMet + ), + ]; + } + }) + .flat(); +}; + +export const getLinkedItems = (itemMap, orderedItemIds, itemIds) => { + const linkedItems = new Set(getLinkedItemsRecursive(itemMap, itemIds)); + return orderedItemIds.filter((itemId) => linkedItems.has(itemId)); +}; + export const snapToGrid = ( { x, y, width, height }, { type = "grid", size = 1, offset = { x: 0, y: 0 } }