diff --git a/packages/core/src/editor.js b/packages/core/src/editor.js index 236e459..28dbe9e 100644 --- a/packages/core/src/editor.js +++ b/packages/core/src/editor.js @@ -463,11 +463,13 @@ export class Editor { } shapesSorted() { - // highlighter lives under the ink, like on paper — highlights render - // first (in their own z order), everything else above + // images are the paper — beneath everything — then highlighters soak in + // above them, like marker over print, with the ink on top. Within each + // layer shapes order by z-index, ties broken by id. + const layer = (s) => (s.type === 'image' ? 0 : s.type === 'highlight' ? 1 : 2) return this.store.shapes().sort( (a, b) => - (a.type === 'highlight' ? 0 : 1) - (b.type === 'highlight' ? 0 : 1) || + layer(a) - layer(b) || a.z - b.z || (a.id < b.id ? -1 : 1) ) diff --git a/packages/core/test/editor.test.js b/packages/core/test/editor.test.js index 25280ff..38dca09 100644 --- a/packages/core/test/editor.test.js +++ b/packages/core/test/editor.test.js @@ -551,6 +551,25 @@ describe('export', () => { }) }) +describe('render order', () => { + it('paints images beneath highlighters beneath everything else, whatever the z-index', () => { + const shape = (id, type, z) => ({ id, typeName: 'shape', type, x: 0, y: 0, rot: 0, z, props: {} }) + editor.store.put(shape('geo-hi', 'geo', 99)) + editor.store.put(shape('hl-lo', 'highlight', 1)) + editor.store.put(shape('img-mid', 'image', 50)) + expect(editor.shapesSorted().map((s) => s.id)).toEqual(['img-mid', 'hl-lo', 'geo-hi']) + }) + + it('orders within each layer by z, ties by id', () => { + const shape = (id, type, z) => ({ id, typeName: 'shape', type, x: 0, y: 0, rot: 0, z, props: {} }) + editor.store.put(shape('b', 'geo', 2)) + editor.store.put(shape('a', 'geo', 1)) + editor.store.put(shape('d', 'image', 9)) + editor.store.put(shape('c', 'image', 3)) + expect(editor.shapesSorted().map((s) => s.id)).toEqual(['c', 'd', 'a', 'b']) + }) +}) + describe('events & lifecycle', () => { it('emits change/selection/tool events and unsubscribes cleanly', () => { const changes = vi.fn(), sel = vi.fn(), tool = vi.fn()