class LayerNode {
constructor(data) {
this.data = data;
// { id, name, imageData, opacity, visible, blendMode }
this.prev = null;
this.next = null;
}
}
class LayerList {
constructor() {
this.head = null; // Top layer (rendered last)
this.tail = null; // Bottom layer (rendered first)
this.size = 0;
}
addLayer(data) {
const node = new LayerNode(data);
if (!this.head) {
this.head = this.tail = node;
} else {
node.next = this.head;
this.head.prev = node;
this.head = node;
}
this.size++;
return node;
}
removeLayer(node) {
if (node.prev) node.prev.next = node.next;
else this.head = node.next;
if (node.next) node.next.prev = node.prev;
else this.tail = node.prev;
this.size--;
}
toArray() {
const result = [];
let current = this.head;
while (current) {
result.push(current.data);
current = current.next;
}
return result;
}
}
moveUp(node) {
if (!node.prev) return; // Already at top
const prev = node.prev;
// Swap positions in the list
if (prev.prev) prev.prev.next = node;
else this.head = node;
if (node.next) node.next.prev = prev;
else this.tail = prev;
node.prev = prev.prev;
prev.next = node.next;
prev.prev = node;
node.next = prev;
}
function LayerPanel({ layers, onReorder,
onToggleVisibility, onOpacityChange, onDelete }) {
return (
<div className="flex flex-col gap-1 p-2
bg-slate-900">
<h3 className="text-xs font-bold
text-slate-400 uppercase">Layers</h3>
{layers.map((layer, index) => (
<LayerItem
key={layer.id}
layer={layer}
onMoveUp={() => onReorder(layer.id, 'up')}
onMoveDown={() => onReorder(layer.id, 'down')}
onToggle={() => onToggleVisibility(layer.id)}
onOpacity={(val) =>
onOpacityChange(layer.id, val)}
onDelete={() => onDelete(layer.id)}
/>
))}
<button onClick={onAddLayer}
className="...">+ New Layer</button>
</div>
);
}
Traverse the list bottom-to-top (tail → head). Composite each visible layer onto the canvas with its opacity. Bottom layer first = background, top layer last = foreground.
Add 5 layers, reorder them, toggle visibility, adjust opacity, merge two layers. Verify rendering order matches the layer panel display at every step.
git switch -c feature/PIXELCRAFT-034-layers
git add src/
git commit -m "Add layer system with doubly linked list (PIXELCRAFT-034)"
git push origin feature/PIXELCRAFT-034-layers
# PR → Review → Merge → Close ticket ✅
Data structure selection depends on your access patterns.
There is no "best" data structure — only the right one for your specific operations.