({ toolSelector })
| 39 | }; |
| 40 | |
| 41 | export default function ShapeMagic({ toolSelector }) { |
| 42 | const isMobile = useBreakpointValue({ base: true, lg: false }); |
| 43 | const [mobileControlsOpen, setMobileControlsOpen] = useState(false); |
| 44 | const canvasRef = useRef(null); |
| 45 | |
| 46 | const initialState = useMemo(() => createInitialState(), []); |
| 47 | const { current: state, push: pushState, undo, redo } = useHistory(initialState); |
| 48 | |
| 49 | const [shapes, setShapes] = useState(state.shapes); |
| 50 | const [selectedIds, setSelectedIds] = useState([]); |
| 51 | const [style, setStyle] = useState(state.style); |
| 52 | const [globalRadius, setGlobalRadius] = useState(state.globalRadius); |
| 53 | const [smoothing, setSmoothing] = useState(state.smoothing); |
| 54 | const [showBridgeDebug, setShowBridgeDebug] = useState(false); |
| 55 | const [showGrid, setShowGrid] = useState(true); |
| 56 | const [snapToGrid, setSnapToGrid] = useState(true); |
| 57 | const [gridSize, setGridSize] = useState(10); |
| 58 | |
| 59 | const justPushedRef = useRef(false); |
| 60 | |
| 61 | const tolerance = 1; |
| 62 | |
| 63 | useEffect(() => { |
| 64 | if (justPushedRef.current) { |
| 65 | justPushedRef.current = false; |
| 66 | return; |
| 67 | } |
| 68 | setShapes(state.shapes); |
| 69 | setStyle(state.style); |
| 70 | setGlobalRadius(state.globalRadius); |
| 71 | setSmoothing(state.smoothing); |
| 72 | }, [state]); |
| 73 | |
| 74 | const bridges = useMemo(() => { |
| 75 | return computeBridges(shapes, globalRadius, tolerance); |
| 76 | }, [shapes, globalRadius, tolerance]); |
| 77 | |
| 78 | const cornerRadii = useMemo(() => { |
| 79 | return computeCornerRadii(shapes, globalRadius, tolerance); |
| 80 | }, [shapes, globalRadius, tolerance]); |
| 81 | |
| 82 | const saveToHistory = useCallback( |
| 83 | (newShapes, newStyle, newRadius, newSmoothing) => { |
| 84 | justPushedRef.current = true; |
| 85 | pushState({ |
| 86 | shapes: newShapes ?? shapes, |
| 87 | style: newStyle ?? style, |
| 88 | globalRadius: newRadius ?? globalRadius, |
| 89 | smoothing: newSmoothing ?? smoothing |
| 90 | }); |
| 91 | }, |
| 92 | [pushState, shapes, style, globalRadius, smoothing] |
| 93 | ); |
| 94 | |
| 95 | const handleApplyPreset = useCallback( |
| 96 | presetId => { |
| 97 | const preset = PRESETS.find(p => p.id === presetId); |
| 98 | if (!preset) return; |
nothing calls this directly
no test coverage detected