Bind rendered editing callbacks to captured element lifetimes
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
import {createContext,useContext,useMemo} from 'react';
|
||||
import type {XYPosition} from '@xyflow/react';
|
||||
import type {NodeDirection} from '@/lib/canvas';
|
||||
import type {TextStyle} from '@/lib/canvas-elements';
|
||||
import type {NodeTransform} from '@/lib/canvas-geometry';
|
||||
import type {EditingLease} from './editing-lease';
|
||||
import type {RenderedTarget} from '@/lib/canvas-bindings/compat-types';
|
||||
import {CanvasOverlays} from './canvas-overlays';
|
||||
const defaultEditing = {
|
||||
beginTransform: undefined as undefined | ((id: string) => boolean | void | EditingLease<NodeTransform>), finishTransform: undefined as undefined | (() => void), cancelTransform: undefined as undefined | (() => void),
|
||||
endEditing: undefined as undefined | ((id: string) => void),
|
||||
workspace: "", schema: 1 as 1 | 2,
|
||||
begin: (_id?: string) => {}, select: (_id: string) => {}, edit: (_id: string, _text: string) => {},
|
||||
branch: (_id: string, _direction: NodeDirection, _point: XYPosition) => {},
|
||||
transform: (_id: string, _transform: NodeTransform) => {},
|
||||
style: (_id: string, _style: TextStyle, _fontSize?: number) => {},
|
||||
rename: (_id: string, _title: string) => {},
|
||||
frame: (_id: string, _patch: { title?: string; labelMode?: import("@/lib/canvas-elements").FrameLabelMode; presentation?: import("@/lib/canvas-v2").FramePresentation }) => {},
|
||||
rotating: null as string | null, rotate: (_id: string | null) => {},
|
||||
resizing: null as string | null, resize: (_id: string | null) => {},
|
||||
};
|
||||
type GestureHooks = 'beginTransform' | 'finishTransform' | 'cancelTransform' | 'endEditing';
|
||||
export const NodeEditing = createContext<Omit<typeof defaultEditing, GestureHooks> & Partial<Pick<typeof defaultEditing, GestureHooks>>>(defaultEditing);
|
||||
|
||||
/** Bind legacy renderer actions to the lifetime and placement that rendered them. */
|
||||
export function useScopedNodeEditing(id:string,rendered?:RenderedTarget){
|
||||
const editing=useContext(NodeEditing),scope=useContext(CanvasOverlays),incarnation=rendered?.id===id?rendered.incarnation:undefined,owner=rendered?.ownerCanvasId,canvas=rendered?.canvasId;
|
||||
return useMemo(()=>{if(!scope)return editing;
|
||||
const current=(candidate:string|null|undefined=id)=>{const durability=scope.engine.getDurability(),view=scope.engine.sessions.getSnapshot().views.get(scope.index.viewId),record=scope.engine.getSnapshot().document.elements.get(id);return !durability.closing&&!durability.closed&&!!view&&view.canvasId===canvas&&incarnation!==undefined&&record?.incarnation===incarnation&&record.ownerCanvasId===owner&&(candidate===undefined||candidate===null||candidate===id);};
|
||||
const ownGesture=()=>scope.engine.sessions.getSnapshot().gesture?.viewId===scope.index.viewId&&scope.engine.sessions.getSnapshot().gesture?.targets.some(target=>target.id===id&&target.incarnation===incarnation);
|
||||
const scoped:typeof editing={...editing,
|
||||
begin:candidate=>{if(current(candidate))editing.begin(candidate??id);},select:candidate=>{if(current(candidate))editing.select(candidate);},
|
||||
edit:(candidate,text)=>{if(current(candidate))editing.edit(candidate,text);},rename:(candidate,title)=>{if(current(candidate))editing.rename(candidate,title);},
|
||||
style:(candidate,style,size)=>{if(current(candidate))editing.style(candidate,style,size);},frame:(candidate,patch)=>{if(current(candidate))editing.frame(candidate,patch);},
|
||||
transform:(candidate,change)=>{if(current(candidate))editing.transform(candidate,change);},branch:(candidate,direction,point)=>{if(current(candidate))editing.branch(candidate,direction,point);},
|
||||
rotate:candidate=>{if(current(candidate)&&(candidate!==null||scope.engine.sessions.getSnapshot().views.get(scope.index.viewId)?.modes.get(id)==='rotate'))editing.rotate(candidate);},resize:candidate=>{if(current(candidate)&&(candidate!==null||scope.engine.sessions.getSnapshot().views.get(scope.index.viewId)?.modes.get(id)==='resize'))editing.resize(candidate);},
|
||||
};
|
||||
if(editing.beginTransform)scoped.beginTransform=candidate=>current(candidate)?editing.beginTransform!(candidate):false;
|
||||
if(editing.endEditing)scoped.endEditing=candidate=>{if(current(candidate))editing.endEditing!(candidate);};
|
||||
if(editing.finishTransform)scoped.finishTransform=()=>{if(current()&&ownGesture())editing.finishTransform!();};
|
||||
if(editing.cancelTransform)scoped.cancelTransform=()=>{if(current()&&ownGesture())editing.cancelTransform!();};
|
||||
return scoped;
|
||||
},[editing,scope,id,incarnation,owner,canvas]);
|
||||
}
|
||||
Reference in New Issue
Block a user