Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/core/src/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
Expand Down
19 changes: 19 additions & 0 deletions packages/core/test/editor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down