JSFiddle - React, Tailwind, and code Playground

HTML

<input type='button' id='btn_init' value='Init'>
<input type='button' id='btn_next' value='Next Step'>
<input type='button' id='btn_all' value='Pack All'>
<br>
<br>
<canvas id='placementCanvas' height='400' width='400' style='border: solid 3px black'></canvas>
<div id='remaining'></div>

JavaScript

// A relatively simple "packing" algorithm
// The goal is to pack all the sprite in a mostly square
// image of yet unkown size.

// The sprites we must pack, all rectangular shaped
var boxes=[{x:0,y:0,w:16,h:43},
           {x:0,y:0,w:46,h:88},
           {x:0,y:0,w:76,h:40},
           {x:0,y:0,w:19,h:88},
           {x:0,y:0,w:76,h:79},
           {x:0,y:0,w:22,h:82},
           {x:0,y:0,w:37,h:34},
           {x:0,y:0,w:16,h:97},
           {x:0,y:0,w:10,h:76},
           {x:0,y:0,w:13,h:76},
           {x:0,y:0,w:16,h:70},
           {x:0,y:0,w:31,h:97},
           {x:0,y:0,w:67,h:79},
           {x:0,y:0,w:31,h:88},
           {x:0,y:0,w:85,h:73}
          ];

// The minimal space between the boxes
var packingSpace=4;

//------------------------------------------
// Runtime variables
//------------------------------------------
// Virtual size
var maxX = 0;
var maxY = 0;

// Next placement
var nextY = 0;
var nextX = 0;

// Boxes to handle
var todo=[];

// Update the screen. Boxes are drawn in red while
// the size of the sprite sheet is in green
function drawBoxes()
{
  var ctx=document.getElementById('placementCanvas').getContext('2d');
  ctx.clearRect(0,0,1000,1000);

  ctx.strokeStyle='#008000'
  ctx.lineWidth=1;
  ctx.strokeRect(0.5,0.5,maxX,maxY);

  ctx.strokeStyle='#FF0000'
  ctx.lineWidth=2;
  for(var i=0;i < boxes.length;i++)
    ctx.strokeRect(boxes[i].x + 0.5,boxes[i].y + 0.5,boxes[i].w,boxes[i].h);

}

// Move all boxes on a negative value to not collide while packing them
function moveBoxOutside()
{
  for(var i=0;i < boxes.length;i++)
  {
    boxes[i].x=-100-boxes[i].w;
    boxes[i].y=-100-boxes[i].h;
  }
}

// Check if the current box is colliding with any other
function boxCollide(box, x, y)
{
  for (var i = 0; i < boxes.length; i++)
  {
    var s2 = boxes[i];
    if (s2 == box)
      continue;
    if (!(s2.x + s2.w + packingSpace < x || s2.x > x + box.w + packingSpace || s2.y + s2.h + packingSpace < y || s2.y > y + box.h + packingSpace))
   ...