diff --git a/CHANGELOG.md b/CHANGELOG.md index dbb7c2c..fc7ecab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,21 @@ +1.2.9 / 2025-03-09 +================== + + * Fix dim safe for good + +1.2.8 / 2025-03-09 +================== + + * Add debug mode + +1.2.7 / 2024-07-21 +================== + + * Use board uid and getElementById + * Improve performances + * Fix bug if missing linked item + 1.2.6 / 2024-03-09 ================== diff --git a/package-lock.json b/package-lock.json index 9bfbfc7..07b2272 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-sync-board", - "version": "1.2.6", + "version": "1.2.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "react-sync-board", - "version": "1.2.6", + "version": "1.2.9", "license": "MIT", "dependencies": { "@react-hookz/web": "^22.0.0", diff --git a/package.json b/package.json index a6cc23f..ebae24e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-sync-board", - "version": "1.2.6", + "version": "1.2.9", "description": "React-sync-board is a board for react", "type": "module", "files": [ diff --git a/src/lib/board/Items/Item.jsx b/src/lib/board/Items/Item.jsx index 0d8ef1f..e14dadf 100644 --- a/src/lib/board/Items/Item.jsx +++ b/src/lib/board/Items/Item.jsx @@ -1,9 +1,11 @@ import React, { memo } from "react"; -import ResizeHandler from "./ResizeHandler"; import { css } from "goober"; import deepEqual from "fast-deep-equal"; +import ResizeHandler from "./ResizeHandler"; +import useMainStore from "../store/main"; + const itemClass = css` display: inline-block; transition: transform 150ms; @@ -184,6 +186,7 @@ const Item = ({ showResizeHandle = true, }) => { const itemWrapperRef = React.useRef(null); + const [uid] = useMainStore((state) => [state.config.uid]); const { component: Component = () => null, @@ -244,6 +247,7 @@ const Item = ({
{ + const [getSelection] = useMainStore((state) => [state.getSelection]); + return getSelection; +}; + +export default useGetSelectedItems; diff --git a/src/lib/board/Items/useItemActions.js b/src/lib/board/Items/useItemActions.js index 2fdf4cd..b52c573 100644 --- a/src/lib/board/Items/useItemActions.js +++ b/src/lib/board/Items/useItemActions.js @@ -123,10 +123,8 @@ const useItemActions = () => { getLinkedItems(getStoreItems(), getItemIds(), itemIds), posDelta ); - - updateItemExtent(); }, - [getItemIds, getStoreItems, moveStoreItems, updateItemExtent] + [getItemIds, getStoreItems, moveStoreItems] ); const putItemsOnTop = React.useCallback( @@ -144,12 +142,12 @@ const useItemActions = () => { const stickOnGrid = React.useCallback( (itemIds, { type: globalType, size: globalSize } = {}) => { - const { boardWrapper } = getConfiguration(); + const { uid } = getConfiguration(); batchUpdateItems( itemIds, (item) => { - const elem = getItemElem(boardWrapper, item.id); + const elem = getItemElem(uid, item.id); if (!elem) { return; @@ -292,10 +290,9 @@ const useItemActions = () => { }); insertItems(itemsWithPosition, beforeId); - - updateItemExtent(); + placeItems(itemsToInsert.map(({ id }) => id)); }, - [getCenter, insertItems, updateItemExtent] + [getCenter, insertItems, placeItems] ); const pushItem = React.useCallback( @@ -351,11 +348,11 @@ const useItemActions = () => { if (hasClass(target, "passthrough")) { // Get current value const itemList = getItemIds(); - const { boardWrapper } = getConfiguration(); + const { uid } = getConfiguration(); // Found element under the cursor const elements = itemList.reduce((prev, itemId) => { - const elem = getItemElem(boardWrapper, itemId); + const elem = getItemElem(uid, itemId); const itemRect = elem.getBoundingClientRect(); if (isPointInsideRect({ x: clientX, y: clientY }, itemRect)) { prev.unshift(elem); diff --git a/src/lib/board/Selection.jsx b/src/lib/board/Selection.jsx index ecdd7a1..8d6e914 100644 --- a/src/lib/board/Selection.jsx +++ b/src/lib/board/Selection.jsx @@ -45,14 +45,14 @@ const BoundingBox = () => { // Update selection bounding box const updateBox = React.useCallback(() => { const currentSelectedItems = getSelection(); - const { boardWrapperRect, boardWrapper } = getConfiguration(); + const { boardWrapperRect, uid } = getConfiguration(); if (currentSelectedItems.length === 0) { setSelectionBox(null); return; } - const boundingBox = getItemsBoundingBox(currentSelectedItems, boardWrapper); + const boundingBox = getItemsBoundingBox(currentSelectedItems, uid); if (!boundingBox) { setSelectionBox(null); diff --git a/src/lib/board/useDim.js b/src/lib/board/useDim.js index b134ecb..100d40d 100644 --- a/src/lib/board/useDim.js +++ b/src/lib/board/useDim.js @@ -15,6 +15,8 @@ const TOLERANCE = 100; const MIN_SIZE = 1000; const SCALE_TOLERANCE = 0.8; +let debug = false; + /** * Return new board positions fixed to fit inside the board and not too far from the * item extent. @@ -185,6 +187,8 @@ const useDim = () => { ...fn(prev), }; + if (debug) console.log("New expected values: ", translateX, translateY, scale, newRotate); + const newScale = clampScale(scale); let [newX, newY] = [translateX, translateY]; @@ -201,11 +205,13 @@ const useDim = () => { }); } + if (debug) console.log("New fixed values: ", newX, newY, newScale, newRotate); + updateBoardState({ - translateX: newX, - translateY: newY, - scale: newScale, - rotate: newRotate, + translateX: isNaN(newX)? 0: newX, + translateY: isNaN(newY)? 0: newY, + scale: isNaN(newScale)? clampScale(1): newScale, + rotate: isNaN(newRotate) ? 0 : newRotate, }); }, [clampScale, getBoardState, getConfiguration, updateBoardState] @@ -280,15 +286,18 @@ const useDim = () => { const { rotate } = getBoardState(); const { boardWrapperRect, boardSize } = getConfiguration(); - const scaleX = boardWrapperRect.width / (radius * 2); - const scaleY = boardWrapperRect.height / (radius * 2); + const [safeX, safeY, safeRadius] = [x || 0, y||0, radius || 2000] + + const scaleX = boardWrapperRect.width / (safeRadius * 2); + const scaleY = boardWrapperRect.height / (safeRadius * 2); // The scale that fits in all dimensions with a border around const scale = clampScale(Math.min(scaleX, scaleY) * SCALE_TOLERANCE); + // We apply the board transformations const [translateX, translateY] = transformTo( - [-boardSize / 2 - x, -boardSize / 2 - y], + [-boardSize / 2 - safeX, -boardSize / 2 - safeY], { translateX: boardWrapperRect.width / 2, translateY: boardWrapperRect.height / 2, @@ -323,11 +332,11 @@ const useDim = () => { const updateItemExtent = React.useCallback(() => { // Update item extent const items = getItemList(); - const { boardWrapper, boardSize } = getConfiguration(); + const { boardSize, uid } = getConfiguration(); const newRes = items.reduce( (boundingBox, item) => { - const elem = getItemElem(boardWrapper, item.id); + const elem = getItemElem(uid, item.id); if (elem) { boundingBox.left = Math.min(item.x, boundingBox.left); @@ -392,6 +401,15 @@ const useDim = () => { 200 ); + React.useEffect(() => { + window.debugUpdateExtent = () => updateItemExtent(); + window.debugDisplayExtent = () => + console.log(getConfiguration().itemExtent); + window.debugSetDebug = () => { + debug = true; + } + }, [getConfiguration, updateItemExtent]); + return { setDim: setDimSafe, rotateBoard, diff --git a/src/lib/index.js b/src/lib/index.js index 38d022c..d40c4f6 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -3,6 +3,7 @@ export { default as useWire } from "@/hooks/useWire"; export { default as useItems } from "@/board/Items/useItems"; export { default as useDebouncedItems } from "@/board/Items/useDebouncedItems"; export { default as useSelectedItems } from "@/board/Items/useSelectedItems"; +export { default as useGetSelectedItems } from "@/board/Items/useGetSelectedItems"; export { default as useItemActions } from "@/board/Items/useItemActions"; export { default as useItemInteraction } from "@/board/Items/useItemInteraction"; export { default as useAvailableActions } from "@/board/Items/useAvailableActions"; diff --git a/src/lib/utils.js b/src/lib/utils.js index d59fcde..1dc7215 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -122,18 +122,17 @@ export const isItemInsideElement = (itemElement, otherElem) => { return result; }; -export const getItemElem = (wrapper, itemId) => { +export const getItemElem = (uid, itemId) => { try { - const elems = wrapper.getElementsByClassName(`item ${itemId}`); - const elem = elems[0]; + const elem = document.getElementById(`${uid}__${itemId}`); if (!elem) { console.error(`Missing item ${itemId}`); } return elem; } catch (e) { console.error( - `Error while getting item with id ${itemId} with wrapper`, - wrapper + `Error while getting item with id ${itemId} inside wrapper`, + uid ); return undefined; } @@ -153,9 +152,9 @@ export const getIdFromElem = (elem) => { return value; }; -export const getItemsBoundingBox = (itemIds, wrapper = document) => { +export const getItemsBoundingBox = (itemIds, uid) => { const result = itemIds.reduce((prev, itemId) => { - const elem = getItemElem(wrapper, itemId); + const elem = getItemElem(uid, itemId); if (!elem) { if (!prev) { @@ -212,14 +211,19 @@ const getLinkedItemsRecursive = (itemMap, itemIds, alreadyMet = null) => { return []; } else { alreadyMet.add(itemId); - return [ - itemId, - ...getLinkedItemsRecursive( - itemMap, - itemMap[itemId].linkedItems, - alreadyMet - ), - ]; + if (itemMap[itemId]) { + // If the item has been removed but not from linked list + return [ + itemId, + ...getLinkedItemsRecursive( + itemMap, + itemMap[itemId].linkedItems, + alreadyMet + ), + ]; + } else { + return []; + } } }) .flat();