Files
Endoleap/src/lib/canvas-core/gesture-placement.ts
T

31 lines
2.0 KiB
TypeScript

import type {Document,Geometry,Id,Registry} from './types.ts';
import {fault} from './values.ts';
import {unitScale} from './units.ts';
type PlacementStep={canvasId:Id;parentCanvasId:Id;entryId:Id;incarnation:number;componentId:string;dataVersion:number;geometry:Geometry;contentScale:number;unitScale:number};
/** A short-lived reader of the visible owner chain relative to one view, not the project root.
* Cache by owner only during this admission/publication, so multi-selection shares ancestry work. */
export function createGesturePlacementReader(document:Document,viewCanvasId:Id,registry:Registry){
const values=new Map<Id,readonly PlacementStep[]>();
return(ownerCanvasId:Id):readonly PlacementStep[]=>{
const cached=values.get(ownerCanvasId);if(cached)return cached;
if(!document.canvases.has(viewCanvasId))throw fault('canvas_missing',[viewCanvasId]);
const chain:PlacementStep[]=[],seen=new Set<Id>();let id=ownerCanvasId;
while(id!==viewCanvasId){
if(seen.has(id))throw fault('canvas_cycle',[id]);seen.add(id);
const parent=document.canvases.get(id)?.parent;
if(!parent)throw fault('target_outside_view',[ownerCanvasId]);
const entry=document.elements.get(parent.entryElementId);
// A future/unknown entry is a collapsed placeholder; never interpret its payload.
if(!entry||entry.structure!=='node'||registry.resolve(entry)!=='known')throw fault('target_hidden',[ownerCanvasId]);
const raw=entry.data.presentation,presentation=raw&&typeof raw==='object'&&!Array.isArray(raw)?raw:{};
if(presentation.collapsed===true)throw fault('target_hidden',[ownerCanvasId]);
const contentScale=typeof presentation.contentScale==='number'&&presentation.contentScale>0?presentation.contentScale:1;
chain.push({canvasId:id,parentCanvasId:parent.canvasId,entryId:entry.id,incarnation:entry.incarnation,componentId:entry.componentId,dataVersion:entry.dataVersion,geometry:entry.geometry,contentScale,unitScale:unitScale(raw)});
id=parent.canvasId;
}
values.set(ownerCanvasId,chain);return chain;
};
}