import { describe, expect, it } from 'vitest'; import { findNodePageContext, pageRectFromSize, resolveAnchorPresetTransform, resolveChildrenTransformsForParentRect, resolvePageRect, resolveReparentTransform, } from '../src/features/ui-editor/nodeTransformGeometry'; import type { Node } from '../src/features/ui-editor/types/Node'; import type { Transform } from '../src/features/ui-editor/types/Transform'; const ROOT_TRANSFORM: Transform = { anchor_min: [0, 0], anchor_max: [1, 1], offset_min: [0, 0], offset_max: [0, 0], }; function node(id: string, transform: Transform, children: Node[] = []): Node { return { id, layout: { transform } as Node['layout'], metadata: {} as Node['metadata'], components: [], children_display_mode: 'Stack', children, }; } describe('nodeTransformGeometry', () => { it('resolves nested context and inverts page offsets at the same seam', () => { const childTransform: Transform = { anchor_min: [0.5, 0.5], anchor_max: [0.5, 0.5], offset_min: [-10, -15], offset_max: [30, 25], }; const root = node('root', ROOT_TRANSFORM, [ node( 'parent', { anchor_min: [0, 0], anchor_max: [0, 0], offset_min: [20, 30], offset_max: [220, 130], }, [node('child', childTransform)], ), ]); const context = findNodePageContext( root, 'child', pageRectFromSize([400, 300]), ); expect(context).toMatchObject({ parentRect: { min: [20, 30], max: [220, 130] }, rect: { min: [110, 65], max: [150, 105] }, }); expect( resolveReparentTransform( childTransform, context!.rect, context!.parentRect, ), ).toEqual(childTransform); }); it('preserves direct child page rectangles when a parent changes', () => { const child = node('child', { anchor_min: [0.25, 0], anchor_max: [0.75, 1], offset_min: [5, 10], offset_max: [-10, -15], }); const oldParentRect = { min: [20, 30] as [number, number], max: [220, 130] as [number, number], }; const newParentRect = { min: [40, 50] as [number, number], max: [340, 250] as [number, number], }; const oldChildRect = resolvePageRect(child.layout.transform, oldParentRect); const [{ transform }] = resolveChildrenTransformsForParentRect( [child], oldParentRect, newParentRect, ); expect(resolvePageRect(transform, newParentRect)).toEqual(oldChildRect); }); it('keeps the page rectangle stable when inspector anchors change', () => { const transform: Transform = { anchor_min: [0.5, 0.5], anchor_max: [0.5, 0.5], offset_min: [-60, -20], offset_max: [40, 30], }; const parentSize = { width: 300, height: 200 }; const pageRect = pageRectFromSize([parentSize.width, parentSize.height]); const next = resolveAnchorPresetTransform( transform, [0, 0], [1, 1], parentSize, ); expect(resolvePageRect(next, pageRect)).toEqual( resolvePageRect(transform, pageRect), ); }); });