JavaScript: A drawing program in OOP
Question responses

if there is a better to approach the OO design here?

It seems okay. As was pointed out in answers to your other recent questions there currently is no use of OO features like inheritance.

Did I do a good job at separating the concerns here?

The separation seems okay.
Suggestions
Simplify move method
The Rectangle method move is currently implemented as this:

move(dx, dy) {
    for (const position of this.positions) {
      const nx = position[0] + dx
      const ny = position[1] + dy
      position[0] = nx
      position[1] = ny
    }
  }


Variables nx and ny are only used once. The method could greatly be simplified:
position[0] += dx;
position[1] += dy;

functional approach to print
In the Canvas method print two for loops are used. A functional approach, similar to how the canvas is created in the constructor, would allow fewer lines and the variable rows could be assigned in one statement, which would allow const to be used, though this would not be wise to change if performance is a major concern.
print(palette) {
    const rows = this.canvas.map(column =&gt; column.map(cell =&gt; {
      if (cell === null || !cell.length) {
        return '*';
      }
      return palette[cell[cell.length - 1]];
    }).join('') + &quot;\n&quot; ).join('');

check parameter types
Since JavaScript is loosely typed, there isn’t much support for ensuring a method is called with parameters of certain types. However, if a method expects to be called with certain types of arguments (e.g. Canvas::draw() and ::remove() expect a Rectangle instance) then the type of those arguments can be checked - e.g. using the typeof keyword. If an argument doesn’t match an expected type then perhaps an Error should be thrown.