tanuki-ui
Version:
HTML-first React component library with semantic elements, multi-OS themes, and production-ready visual node editor
1 lines • 147 kB
JavaScript
"use strict";var yn=Object.defineProperty;var xn=(e,t,n)=>t in e?yn(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var ie=(e,t,n)=>xn(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),vn=require("react"),Y=require("../vendor/classNames-BlNBsLzi.js");function bn(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const o=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,o.get?o:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const l=bn(vn),Ze=e=>{const t=[];return e.ctrl&&t.push("ctrl"),e.shift&&t.push("shift"),e.alt&&t.push("alt"),e.meta&&t.push("meta"),t.push(e.key.toLowerCase()),t.join("+")},Nn=(e,t)=>e.key.toLowerCase()===t.key.toLowerCase()&&!!e.ctrlKey==!!t.ctrl&&!!e.shiftKey==!!t.shift&&!!e.altKey==!!t.alt&&!!e.metaKey==!!t.meta,Cn=(e,t)=>{switch(t.type){case"REGISTER_SHORTCUT":{const n=Ze(t.payload.shortcut),o=new Map(e.shortcuts);return o.set(n,t.payload.handler),{...e,shortcuts:o}}case"UNREGISTER_SHORTCUT":{const n=Ze(t.payload.shortcut),o=new Map(e.shortcuts);return o.delete(n),{...e,shortcuts:o}}case"ENABLE_SHORTCUTS":return{...e,isEnabled:!0};case"DISABLE_SHORTCUTS":return{...e,isEnabled:!1};default:return e}},Sn={shortcuts:new Map,isEnabled:!0},Oe={registerShortcut:(e,t)=>({type:"REGISTER_SHORTCUT",payload:{shortcut:e,handler:t}}),unregisterShortcut:e=>({type:"UNREGISTER_SHORTCUT",payload:{shortcut:e}}),enableShortcuts:()=>({type:"ENABLE_SHORTCUTS"}),disableShortcuts:()=>({type:"DISABLE_SHORTCUTS"})},st=l.createContext(null),it=({children:e,initialState:t})=>{const[n,o]=l.useReducer(Cn,{...Sn,...t});l.useEffect(()=>{const c=d=>{if(!n.isEnabled)return;const h=d.target;if(!(h.tagName==="INPUT"||h.tagName==="TEXTAREA"||h.isContentEditable))for(const[u,p]of n.shortcuts){const m=u.split("+"),y=m[m.length-1],N=m.slice(0,-1),f={key:y,ctrl:N.includes("ctrl"),shift:N.includes("shift"),alt:N.includes("alt"),meta:N.includes("meta")};if(Nn(d,f)){d.preventDefault(),d.stopPropagation(),p(d);break}}};return document.addEventListener("keydown",c),()=>document.removeEventListener("keydown",c)},[n.shortcuts,n.isEnabled]);const i=l.useCallback((c,d)=>{o(Oe.registerShortcut(c,d))},[o]),s=l.useCallback(c=>{o(Oe.unregisterShortcut(c))},[o]),r={state:n,dispatch:o,actions:Oe,registerShortcut:i,unregisterShortcut:s};return a.jsx(st.Provider,{value:r,children:e})},wn=()=>{const e=l.useContext(st);if(!e)throw new Error("useKeyboardShortcut must be used within a KeyboardShortcutProvider");return e},se=(e,t,n=[])=>{const{registerShortcut:o,unregisterShortcut:i}=wn();l.useEffect(()=>(o(e,t),()=>i(e)),[o,i,...n])},En=(e,t)=>{switch(t.type){case"ADD_NODE":{const n=Se(),o={...t.payload.node,id:n};return o.ports&&(o.ports=o.ports.map(i=>({...i,nodeId:n}))),{...e,nodes:{...e.nodes,[n]:o}}}case"UPDATE_NODE":{const{nodeId:n,updates:o}=t.payload,i=e.nodes[n];return i?{...e,nodes:{...e.nodes,[n]:{...i,...o}}}:e}case"DELETE_NODE":{const{nodeId:n}=t.payload,{[n]:o,...i}=e.nodes,s=Object.entries(e.connections).reduce((r,[c,d])=>(d.fromNodeId!==n&&d.toNodeId!==n&&(r[c]=d),r),{});return{...e,nodes:i,connections:s}}case"MOVE_NODE":{const{nodeId:n,position:o}=t.payload,i=e.nodes[n];return i?{...e,nodes:{...e.nodes,[n]:{...i,position:o}}}:e}case"MOVE_NODES":{const{updates:n}=t.payload,o={...e.nodes};return Object.entries(n).forEach(([i,s])=>{const r=o[i];r&&(o[i]={...r,position:s})}),{...e,nodes:o}}case"ADD_CONNECTION":{const{connection:n}=t.payload,o=Se(),i=Object.entries(e.connections).filter(([r,c])=>c.toNodeId===n.toNodeId&&c.toPortId===n.toPortId),s={...e.connections};return i.forEach(([r])=>{delete s[r]}),{...e,connections:{...s,[o]:{...n,id:o}}}}case"DELETE_CONNECTION":{const{connectionId:n}=t.payload,{[n]:o,...i}=e.connections;return{...e,connections:i}}case"SET_NODE_DATA":return t.payload.data;case"RESTORE_STATE":return t.payload.data;case"DUPLICATE_NODES":{const{nodeIds:n}=t.payload;if(n.length===0)return e;const o={...e.nodes},i=[];return n.forEach(s=>{var h;const r=e.nodes[s];if(!r)return;const c=Se();i.push(c);const d={...r,id:c,position:{x:r.position.x+50,y:r.position.y+50},data:{...r.data,title:r.data.title?`${r.data.title} Copy`:"Node Copy",createdAt:Date.now()},ports:((h=r.ports)==null?void 0:h.map(u=>({...u,id:`${u.id}-copy-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,nodeId:c})))||[]};d.type==="group"&&(d.children=[]),o[c]=d}),{...e,nodes:o,lastDuplicatedNodeIds:i}}case"GROUP_NODES":{const{nodeIds:n,groupId:o=Se()}=t.payload;if(n.length===0)return e;let i=1/0,s=1/0,r=-1/0,c=-1/0;n.forEach(h=>{var p,m;const u=e.nodes[h];u&&(i=Math.min(i,u.position.x),s=Math.min(s,u.position.y),r=Math.max(r,u.position.x+(((p=u.size)==null?void 0:p.width)||100)),c=Math.max(c,u.position.y+(((m=u.size)==null?void 0:m.height)||50)))});const d={id:o,type:"group",position:{x:i-20,y:s-40},size:{width:r-i+40,height:c-s+60},data:{title:"Group"},children:n,expanded:!0};return{...e,nodes:{...e.nodes,[o]:d}}}case"UNGROUP_NODE":{const{groupId:n}=t.payload,o=e.nodes[n];if(!o||o.type!=="group")return e;const{[n]:i,...s}=e.nodes;return{...e,nodes:s}}case"UPDATE_GROUP_MEMBERSHIP":{const{updates:n}=t.payload,o={...e.nodes};return Object.entries(n).forEach(([i,s])=>{const r=o[i];r&&(o[i]={...r,...s})}),{...e,nodes:o}}case"MOVE_GROUP_WITH_CHILDREN":{const{groupId:n,delta:o}=t.payload,i={...e.nodes},s=i[n];return s&&(i[n]={...s,position:{x:s.position.x+o.x,y:s.position.y+o.y}},Object.values(i).forEach(r=>{r.parentId===n&&(i[r.id]={...r,position:{x:r.position.x+o.x,y:r.position.y+o.y}})})),{...e,nodes:i}}case"AUTO_LAYOUT":{const{layoutType:n,selectedOnly:o=!1}=t.payload;return o&&(Object.fromEntries(Object.entries(e.nodes).filter(([i,s])=>!0)),e.connections),e}default:return e}};function Se(){return Math.random().toString(36).slice(2,10)}const qe={nodes:{},connections:{}},In={addNode:e=>({type:"ADD_NODE",payload:{node:e}}),updateNode:(e,t)=>({type:"UPDATE_NODE",payload:{nodeId:e,updates:t}}),deleteNode:e=>({type:"DELETE_NODE",payload:{nodeId:e}}),moveNode:(e,t)=>({type:"MOVE_NODE",payload:{nodeId:e,position:t}}),moveNodes:e=>({type:"MOVE_NODES",payload:{updates:e}}),addConnection:e=>({type:"ADD_CONNECTION",payload:{connection:e}}),deleteConnection:e=>({type:"DELETE_CONNECTION",payload:{connectionId:e}}),setNodeData:e=>({type:"SET_NODE_DATA",payload:{data:e}}),restoreState:e=>({type:"RESTORE_STATE",payload:{data:e}}),duplicateNodes:e=>({type:"DUPLICATE_NODES",payload:{nodeIds:e}}),groupNodes:(e,t)=>({type:"GROUP_NODES",payload:{nodeIds:e,groupId:t}}),ungroupNode:e=>({type:"UNGROUP_NODE",payload:{groupId:e}}),updateGroupMembership:e=>({type:"UPDATE_GROUP_MEMBERSHIP",payload:{updates:e}}),moveGroupWithChildren:(e,t)=>({type:"MOVE_GROUP_WITH_CHILDREN",payload:{groupId:e,delta:t}}),autoLayout:(e,t)=>({type:"AUTO_LAYOUT",payload:{layoutType:e,selectedOnly:t}})},at=l.createContext(null),rt=({children:e,initialState:t})=>{const n=l.useMemo(()=>({nodes:(t==null?void 0:t.nodes)||qe.nodes,connections:(t==null?void 0:t.connections)||qe.connections}),[t]),[o,i]=l.useReducer(En,n),s={state:o,dispatch:i,actions:In};return a.jsx(at.Provider,{value:s,children:e})},K=()=>{const e=l.useContext(at);if(!e)throw new Error("useNodeEditor must be used within a NodeEditorProvider");return e},Dn=(e,t)=>{switch(t.type){case"SELECT_NODE":{const{nodeId:n,multiple:o}=t.payload;if(o){const i=e.selectedNodeIds.includes(n);return{...e,selectedNodeIds:i?e.selectedNodeIds.filter(s=>s!==n):[...e.selectedNodeIds,n]}}return{...e,selectedNodeIds:[n],selectedConnectionIds:[]}}case"SELECT_CONNECTION":{const{connectionId:n,multiple:o}=t.payload;if(o){const i=e.selectedConnectionIds.includes(n);return{...e,selectedConnectionIds:i?e.selectedConnectionIds.filter(s=>s!==n):[...e.selectedConnectionIds,n]}}return{...e,selectedConnectionIds:[n],selectedNodeIds:[]}}case"CLEAR_SELECTION":return{...e,selectedNodeIds:[],selectedConnectionIds:[],selectionBox:null};case"SELECT_ALL_NODES":return{...e,selectedNodeIds:t.payload.nodeIds,selectedConnectionIds:[]};case"SET_SELECTION_BOX":return{...e,selectionBox:t.payload.box};case"START_NODE_DRAG":{const{nodeIds:n,startPosition:o,initialPositions:i,affectedChildNodes:s}=t.payload;return{...e,dragState:{nodeIds:n,startPosition:o,offset:{x:0,y:0},initialPositions:i,affectedChildNodes:s}}}case"UPDATE_NODE_DRAG":return e.dragState?{...e,dragState:{...e.dragState,offset:t.payload.offset}}:e;case"END_NODE_DRAG":return{...e,dragState:null};case"SET_HOVERED_NODE":return{...e,hoveredNodeId:t.payload.nodeId};case"SET_HOVERED_CONNECTION":return{...e,hoveredConnectionId:t.payload.connectionId};case"START_CONNECTION_DRAG":return{...e,connectionDragState:{fromPort:t.payload.fromPort,toPosition:{x:0,y:0},validTarget:null,candidatePort:null}};case"UPDATE_CONNECTION_DRAG":return e.connectionDragState?{...e,connectionDragState:{...e.connectionDragState,toPosition:t.payload.toPosition,candidatePort:t.payload.candidatePort}}:e;case"END_CONNECTION_DRAG":return{...e,connectionDragState:null};case"START_CONNECTION_DISCONNECT":return{...e,connectionDisconnectState:{connectionId:t.payload.originalConnection.id,fixedPort:t.payload.fixedPort,draggingEnd:t.payload.disconnectedEnd,draggingPosition:t.payload.draggingPosition,originalConnection:t.payload.originalConnection,disconnectedEnd:t.payload.disconnectedEnd,candidatePort:null}};case"UPDATE_CONNECTION_DISCONNECT":return e.connectionDisconnectState?{...e,connectionDisconnectState:{...e.connectionDisconnectState,draggingPosition:t.payload.draggingPosition,candidatePort:t.payload.candidatePort}}:e;case"END_CONNECTION_DISCONNECT":return{...e,connectionDisconnectState:null};case"SET_HOVERED_PORT":return{...e,hoveredPort:t.payload.port};case"UPDATE_CONNECTED_PORTS":return{...e,connectedPorts:t.payload.connectedPorts};case"START_NODE_RESIZE":{const{nodeId:n,startPosition:o,startSize:i,handle:s}=t.payload;return{...e,resizeState:{nodeId:n,startPosition:o,startSize:i,currentSize:i,currentPosition:o,handle:s}}}case"UPDATE_NODE_RESIZE":return e.resizeState?{...e,resizeState:{...e.resizeState,currentSize:t.payload.currentSize}}:e;case"END_NODE_RESIZE":return{...e,resizeState:null};case"SHOW_CONTEXT_MENU":return{...e,contextMenu:{visible:!0,position:t.payload.position,canvasPosition:t.payload.canvasPosition,nodeId:t.payload.nodeId}};case"HIDE_CONTEXT_MENU":return{...e,contextMenu:{visible:!1,position:{x:0,y:0},canvasPosition:void 0,nodeId:void 0}};default:return e}},jn={selectedNodeIds:[],selectedConnectionIds:[],selectionBox:null,dragState:null,resizeState:null,hoveredNodeId:null,hoveredConnectionId:null,connectionDragState:null,connectionDisconnectState:null,hoveredPort:null,connectedPorts:new Set,contextMenu:{visible:!1,position:{x:0,y:0},canvasPosition:void 0,nodeId:void 0}},kn={selectNode:(e,t=!1)=>({type:"SELECT_NODE",payload:{nodeId:e,multiple:t}}),selectConnection:(e,t=!1)=>({type:"SELECT_CONNECTION",payload:{connectionId:e,multiple:t}}),clearSelection:()=>({type:"CLEAR_SELECTION"}),selectAllNodes:e=>({type:"SELECT_ALL_NODES",payload:{nodeIds:e}}),setSelectionBox:e=>({type:"SET_SELECTION_BOX",payload:{box:e}}),startNodeDrag:(e,t,n,o)=>({type:"START_NODE_DRAG",payload:{nodeIds:e,startPosition:t,initialPositions:n,affectedChildNodes:o}}),updateNodeDrag:e=>({type:"UPDATE_NODE_DRAG",payload:{offset:e}}),endNodeDrag:()=>({type:"END_NODE_DRAG"}),setHoveredNode:e=>({type:"SET_HOVERED_NODE",payload:{nodeId:e}}),setHoveredConnection:e=>({type:"SET_HOVERED_CONNECTION",payload:{connectionId:e}}),startConnectionDrag:e=>({type:"START_CONNECTION_DRAG",payload:{fromPort:e}}),updateConnectionDrag:(e,t)=>({type:"UPDATE_CONNECTION_DRAG",payload:{toPosition:e,candidatePort:t}}),endConnectionDrag:()=>({type:"END_CONNECTION_DRAG"}),setHoveredPort:e=>({type:"SET_HOVERED_PORT",payload:{port:e}}),updateConnectedPorts:e=>({type:"UPDATE_CONNECTED_PORTS",payload:{connectedPorts:e}}),startConnectionDisconnect:(e,t,n,o)=>({type:"START_CONNECTION_DISCONNECT",payload:{originalConnection:e,disconnectedEnd:t,fixedPort:n,draggingPosition:o}}),updateConnectionDisconnect:(e,t)=>({type:"UPDATE_CONNECTION_DISCONNECT",payload:{draggingPosition:e,candidatePort:t}}),endConnectionDisconnect:()=>({type:"END_CONNECTION_DISCONNECT"}),startNodeResize:(e,t,n,o)=>({type:"START_NODE_RESIZE",payload:{nodeId:e,startPosition:t,startSize:n,handle:o}}),updateNodeResize:e=>({type:"UPDATE_NODE_RESIZE",payload:{currentSize:e}}),endNodeResize:()=>({type:"END_NODE_RESIZE"}),showContextMenu:(e,t,n)=>({type:"SHOW_CONTEXT_MENU",payload:{position:e,nodeId:t,canvasPosition:n}}),hideContextMenu:()=>({type:"HIDE_CONTEXT_MENU"})},ct=l.createContext(null),lt=({children:e,initialState:t})=>{const[n,o]=l.useReducer(Dn,{...jn,...t}),i={state:n,dispatch:o,actions:kn};return a.jsx(ct.Provider,{value:i,children:e})},W=()=>{const e=l.useContext(ct);if(!e)throw new Error("useEditorActionState must be used within an EditorActionStateProvider");return e},Pn=(e,t)=>{switch(t.type){case"PUSH_ENTRY":{if(!e.isRecording)return e;const{action:n,data:o}=t.payload,i={id:`${Date.now()}-${Math.random().toString(36).substr(2,9)}`,timestamp:Date.now(),action:n,data:JSON.parse(JSON.stringify(o))},c=[...e.entries.slice(0,e.currentIndex+1),i].slice(-e.maxEntries);return{...e,entries:c,currentIndex:c.length-1}}case"UNDO":return e.currentIndex<=0?e:{...e,currentIndex:e.currentIndex-1};case"REDO":return e.currentIndex>=e.entries.length-1?e:{...e,currentIndex:e.currentIndex+1};case"CLEAR_HISTORY":return{...e,entries:[],currentIndex:-1};case"SET_RECORDING":return{...e,isRecording:t.payload.isRecording};case"SET_MAX_ENTRIES":{const{maxEntries:n}=t.payload,o=e.entries.slice(-n);return{...e,maxEntries:n,entries:o,currentIndex:Math.min(e.currentIndex,o.length-1)}}default:return e}},Tn={entries:[],currentIndex:-1,maxEntries:50,isRecording:!0},we={pushEntry:(e,t)=>({type:"PUSH_ENTRY",payload:{action:e,data:t}}),undo:()=>({type:"UNDO"}),redo:()=>({type:"REDO"}),clearHistory:()=>({type:"CLEAR_HISTORY"}),setRecording:e=>({type:"SET_RECORDING",payload:{isRecording:e}}),setMaxEntries:e=>({type:"SET_MAX_ENTRIES",payload:{maxEntries:e}})},dt=l.createContext(null),ut=({children:e,initialState:t})=>{const[n,o]=l.useReducer(Pn,{...Tn,...t}),i=n.currentIndex>0,s=n.currentIndex<n.entries.length-1,r=n.currentIndex>=0?n.entries[n.currentIndex]:null,c=l.useCallback((p,m)=>{o(we.pushEntry(p,m))},[o]),d=l.useCallback(()=>i?(o(we.undo()),n.entries[n.currentIndex-1]||null):null,[i,n.entries,n.currentIndex,o]),h=l.useCallback(()=>s?(o(we.redo()),n.entries[n.currentIndex+1]||null):null,[s,n.entries,n.currentIndex,o]),u={state:n,dispatch:o,actions:we,canUndo:i,canRedo:s,currentEntry:r,pushEntry:c,undo:d,redo:h};return a.jsx(dt.Provider,{value:u,children:e})},Mn=()=>{const e=l.useContext(dt);if(!e)throw new Error("useHistory must be used within a HistoryProvider");return e},On=()=>{const{state:e,dispatch:t,actions:n}=K(),{pushEntry:o,undo:i,redo:s,canUndo:r,canRedo:c}=Mn(),d=l.useRef(e),h=l.useRef(null);l.useEffect(()=>{const y=e,N=d.current;if(N===y||JSON.stringify(N)===JSON.stringify(y))return;const f=h.current||"Unknown Action";o(f,N),d.current=y,h.current=null},[e,o]);const u=l.useCallback(y=>{y&&typeof y=="object"&&y.type&&(h.current=y.type),t(y)},[t]),p=l.useCallback(()=>{if(!r)return!1;const y=i();return y?(h.current=null,d.current=y.data,t(n.restoreState(y.data)),!0):!1},[r,i,t,n]),m=l.useCallback(()=>{if(!c)return!1;const y=s();return y?(h.current=null,d.current=y.data,t(n.restoreState(y.data)),!0):!1},[c,s,t,n]);return{dispatchWithHistory:u,performUndo:p,performRedo:m,canUndo:r,canRedo:c}},zn={iterations:100,springLength:150,springStrength:.3,repulsionStrength:1e3,dampening:.9,maxForce:50,padding:100};function An(e,t={}){const n={...zn,...t},o=Object.values(e.nodes),i=Object.values(e.connections);if(o.length===0)return{nodePositions:{},iterations:0};if(o.length===1)return{nodePositions:{[o[0].id]:{x:0,y:0}},iterations:0};const s={},r={};o.forEach((u,p)=>{if(u.position)s[u.id]={...u.position};else{const m=p/o.length*2*Math.PI,y=Math.sqrt(o.length)*50;s[u.id]={x:Math.cos(m)*y,y:Math.sin(m)*y}}r[u.id]={x:0,y:0}});const c={};o.forEach(u=>{c[u.id]=new Set}),i.forEach(u=>{c[u.fromNodeId]&&c[u.toNodeId]&&(c[u.fromNodeId].add(u.toNodeId),c[u.toNodeId].add(u.fromNodeId))});let d=0;for(let u=0;u<n.iterations;u++){d++;const p={};o.forEach(N=>{p[N.id]={x:0,y:0}});for(let N=0;N<o.length;N++)for(let f=N+1;f<o.length;f++){const v=o[N],x=o[f],I=s[v.id],j=s[x.id],b=j.x-I.x,C=j.y-I.y,g=Math.sqrt(b*b+C*C);if(g<.01)continue;const w=n.repulsionStrength/(g*g),E=b/g*w,k=C/g*w;p[v.id].x-=E,p[v.id].y-=k,p[x.id].x+=E,p[x.id].y+=k}i.forEach(N=>{const f=s[N.fromNodeId],v=s[N.toNodeId];if(!f||!v)return;const x=v.x-f.x,I=v.y-f.y,j=Math.sqrt(x*x+I*I);if(j<.01)return;const b=n.springStrength*(j-n.springLength),C=x/j*b,g=I/j*b;p[N.fromNodeId].x+=C,p[N.fromNodeId].y+=g,p[N.toNodeId].x-=C,p[N.toNodeId].y-=g});let m=0;if(o.forEach(N=>{const f=p[N.id],v=Math.sqrt(f.x*f.x+f.y*f.y);v>n.maxForce&&(f.x=f.x/v*n.maxForce,f.y=f.y/v*n.maxForce),r[N.id].x=r[N.id].x*n.dampening+f.x,r[N.id].y=r[N.id].y*n.dampening+f.y;const x={...s[N.id]};s[N.id].x+=r[N.id].x,s[N.id].y+=r[N.id].y;const I=Math.sqrt(Math.pow(s[N.id].x-x.x,2)+Math.pow(s[N.id].y-x.y,2));m+=I}),m/o.length<.1)break}const h=Object.keys(s);if(h.length>0){let u=1/0,p=-1/0,m=1/0,y=-1/0;h.forEach(v=>{const x=s[v];u=Math.min(u,x.x),p=Math.max(p,x.x),m=Math.min(m,x.y),y=Math.max(y,x.y)});const N=(u+p)/2,f=(m+y)/2;h.forEach(v=>{s[v].x=s[v].x-N+n.padding,s[v].y=s[v].y-f+n.padding})}return{nodePositions:s,iterations:d}}function Rn(e,t={}){const{spacing:n=200,layerHeight:o=150}=t,i=Object.values(e.nodes),s=Object.values(e.connections);if(i.length===0)return{nodePositions:{},iterations:0};const r={},c={};i.forEach(f=>{r[f.id]=new Set,c[f.id]=new Set}),s.forEach(f=>{r[f.fromNodeId]&&c[f.toNodeId]&&(r[f.fromNodeId].add(f.toNodeId),c[f.toNodeId].add(f.fromNodeId))});const d=i.filter(f=>c[f.id].size===0);if(d.length===0){const f=Math.min(...i.map(v=>c[v.id].size));d.push(...i.filter(v=>c[v.id].size===f))}const h=[],u={},p=new Set;h[0]=d.map(f=>f.id),d.forEach(f=>{u[f.id]=0,p.add(f.id)});let m=0;for(;h[m]&&h[m].length>0;){const f=[];if(h[m].forEach(v=>{r[v].forEach(x=>{p.has(x)||(f.push(x),u[x]=m+1,p.add(x))})}),f.length>0)h[m+1]=f,m++;else break}const y=i.filter(f=>!p.has(f.id));y.length>0&&(h[m+1]||(h[m+1]=[]),h[m+1].push(...y.map(f=>f.id)),y.forEach(f=>{u[f.id]=m+1}));const N={};return h.forEach((f,v)=>{const x=v*o,j=-((f.length-1)*n)/2;f.forEach((b,C)=>{N[b]={x:j+C*n,y:x}})}),{nodePositions:N,iterations:h.length}}function Vn(e,t={}){const{spacing:n=200,columns:o}=t,i=Object.values(e.nodes);if(i.length===0)return{nodePositions:{},iterations:0};const s=o||Math.ceil(Math.sqrt(i.length)),r=Math.ceil(i.length/s),c={};return i.forEach((d,h)=>{const u=Math.floor(h/s),p=h%s,m=(s-1)*n,y=(r-1)*n;c[d.id]={x:p*n-m/2,y:u*n-y/2}}),{nodePositions:c,iterations:0}}const Ln=()=>{const{state:e,dispatch:t,actions:n}=K(),{state:o}=W(),i=l.useCallback((d=!1)=>{console.log("Applying force-directed layout");const u={nodes:d?Object.fromEntries(Object.entries(e.nodes).filter(([m])=>o.selectedNodeIds.includes(m))):e.nodes,connections:e.connections},p=An(u,{iterations:150,springLength:200,springStrength:.4,repulsionStrength:2e3,dampening:.85});Object.keys(p.nodePositions).length>0&&t(n.moveNodes(p.nodePositions))},[e,o.selectedNodeIds,t,n]),s=l.useCallback((d=!1)=>{console.log("Applying hierarchical layout");const u={nodes:d?Object.fromEntries(Object.entries(e.nodes).filter(([m])=>o.selectedNodeIds.includes(m))):e.nodes,connections:e.connections},p=Rn(u,{spacing:250,layerHeight:200});Object.keys(p.nodePositions).length>0&&t(n.moveNodes(p.nodePositions))},[e,o.selectedNodeIds,t,n]),r=l.useCallback((d=!1)=>{console.log("Applying grid layout");const h=d?Object.fromEntries(Object.entries(e.nodes).filter(([m])=>o.selectedNodeIds.includes(m))):e.nodes,u={nodes:h,connections:e.connections},p=Vn(u,{spacing:250,columns:Math.ceil(Math.sqrt(Object.keys(h).length))});Object.keys(p.nodePositions).length>0&&t(n.moveNodes(p.nodePositions))},[e,o.selectedNodeIds,t,n]);return{applyLayout:l.useCallback((d,h=!1)=>{switch(d){case"force":i(h);break;case"hierarchical":s(h);break;case"grid":r(h);break;default:console.warn(`Unknown layout type: ${d}`)}},[i,s,r]),applyForceLayout:i,applyHierarchicalLayout:s,applyGridLayout:r}},_n=()=>{const{state:e,dispatch:t,actions:n}=K(),{state:o,dispatch:i,actions:s}=W(),{performUndo:r,performRedo:c,canUndo:d,canRedo:h}=On(),{applyLayout:u}=Ln();se({key:"Delete"},l.useCallback(()=>{console.log("Delete shortcut triggered"),o.selectedNodeIds.length>0?(o.selectedNodeIds.forEach(p=>{t(n.deleteNode(p))}),i(s.clearSelection())):o.selectedConnectionIds.length>0&&(o.selectedConnectionIds.forEach(p=>{t(n.deleteConnection(p))}),i(s.clearSelection()))},[o.selectedNodeIds,o.selectedConnectionIds,t,n,i,s])),se({key:"Backspace"},l.useCallback(()=>{console.log("Backspace shortcut triggered"),o.selectedNodeIds.length>0?(o.selectedNodeIds.forEach(p=>{t(n.deleteNode(p))}),i(s.clearSelection())):o.selectedConnectionIds.length>0&&(o.selectedConnectionIds.forEach(p=>{t(n.deleteConnection(p))}),i(s.clearSelection()))},[o.selectedNodeIds,o.selectedConnectionIds,t,n,i,s])),se({key:"a",ctrl:!0},l.useCallback(()=>{console.log("Select All shortcut triggered");const p=Object.keys(e.nodes);i(s.selectAllNodes(p))},[e.nodes,i,s])),se({key:"Escape"},l.useCallback(()=>{console.log("Escape shortcut triggered"),i(s.clearSelection())},[i,s])),se({key:"n",ctrl:!0},l.useCallback(()=>{console.log("Add Node shortcut triggered");const p=`node-${Date.now()}`,m={title:"New Node",type:"default",position:{x:100,y:100},data:{title:"New Node"},ports:[{id:`port-input-${Date.now()}`,type:"input",label:"Input",position:"left",nodeId:p},{id:`port-output-${Date.now()}`,type:"output",label:"Output",position:"right",nodeId:p}]};t(n.addNode(m))},[t,n])),se({key:"d",ctrl:!0},l.useCallback(()=>{console.log("Duplicate shortcut triggered"),o.selectedNodeIds.length>0&&t(n.duplicateNodes(o.selectedNodeIds))},[o.selectedNodeIds,t,n])),l.useEffect(()=>{e.lastDuplicatedNodeIds&&e.lastDuplicatedNodeIds.length>0&&(i(s.selectAllNodes(e.lastDuplicatedNodeIds)),t(n.setNodeData({...e,lastDuplicatedNodeIds:void 0})))},[e.lastDuplicatedNodeIds,i,s,t,n,e]),se({key:"s",ctrl:!0},l.useCallback(p=>{console.log("Save shortcut triggered"),console.log("Save not yet implemented")},[])),se({key:"l",ctrl:!0},l.useCallback(()=>{console.log("Auto Layout shortcut triggered");const p=o.selectedNodeIds.length>0;u("force",p)},[o.selectedNodeIds,u])),se({key:"z",ctrl:!0},l.useCallback(()=>{console.log("Undo shortcut triggered"),d&&r()},[d,r])),se({key:"z",ctrl:!0,shift:!0},l.useCallback(()=>{console.log("Redo shortcut triggered"),h&&c()},[h,c])),se({key:"y",ctrl:!0},l.useCallback(()=>{console.log("Redo (Ctrl+Y) shortcut triggered"),h&&c()},[h,c]))},Hn="enenodedibas",Bn="enecnt",Gn="enecanvas",$n="enepanning",Xn="enespapan",Un="enenodes",Yn="enenode",Fn="enelocked",Kn="enesel",Wn="enedrg",Zn="enenodehdr",qn="eneintdra",Jn="enenod",Qn="enelockico",eo="enenodectn",to="enegrpNode",no="enecold",oo="enegrpcold",so="enegrpexped",io="enenodeinf",ao="enenodesuc",ro="enenodewrn",co="enenodeerr",lo="enenodedis",uo="enetbr",po="enetoolbtn",ho="eneconmen",go="eneconmenrax",mo="enegrid",fo="eneins",yo="eneinscIz",xo="eneinszAn",vo="eneinssec",bo="eneinsrow",No="eneediwitins",Co="eneedimai",So="eneextdat",wo="enedragui",Eo="enedraguiVp7",Io="enedraguiPHl",Do="enedragui-eW",jo="enesnatar",ko="enedis",Po="enedislin",To="enestabar",Mo="enestasec",Oo="enesta",zo="enestaval",Ao="enestamod",Ro="enenodePort",Vo="eneportinp",Lo="eneporout",_o="eneporinn",Ho="eneportlbl",Bo="eneportLeft",Go="eneporrig",$o="eneportTop",Xo="eneporbot",Uo="enecon",Yo="eneinstab",Fo="eneinstab5EW",Ko="eneact",Wo="eneinsfie",Zo="eneinsj42",qo="eneinskYN",Jo="eneinspos",Qo="eneinsnum",es="eneinsreaonlfie",ts="eneinssta",ns="enecan",os="eneboxsel",ss="enegridSvg",is="eneedi",as="eneediA9y",rs="eneediPTx",cs="eneedi-tX",ls="enetoptbr",ds="enenodlay",us="enenodeView",ps="enenodtit",hs="enenodtitpsF",gs="enegrpaccdro",ms="enegrpPulse",fs="enegrphaschi",ys="enenodpor",xs="eneport",vs="eneporhov",bs="eneporcon",Ns="enepulse",Cs="eneporcon7Fy",Ss="eneporlef",ws="eneporrigtpL",Es="eneportop",Is="eneporbotsMk",Ds="eneconlay",js="eneconhUO",ks="enecongay",Ps="eneconhov",Ts="eneconDHx",Ms="enedracon",Os="enedasani",zs="eneselbox",As="eneseldzq",Rs="eneldgovr",Vs="eneldgind",Ls="enecusnod",_s="eneres",Hs="eneresVnb",Bs="enenodseamen",Gs="enemenfadin",$s="enesea",Xs="eneseaEM8",Us="eneseahin",Ys="eneseares",Fs="enecatlis",Ks="enecat",Ws="enecatoHZ",Zs="eneselcat",qs="enecatnam",Js="enenodcou",Qs="enenodeList",ei="enenodeitm",ti="eneselNode",ni="enenodeico",oi="enenodeName",si="enenoddes",ii="enenodeType",ai="enenores",ri="enenoresgSZ",ci="eneseaqFY",li="eneselWi_",di="enemin",ui="eneminimap",pi="enemintit",hi="eneminont",gi="eneminvie",mi="eneminnod",fi="enedarthe",yi="enesmoani",xi="enestasav",vi="eneuiovrcnt",S={nodeEditorBase:Hn,container:Bn,canvas:Gn,panning:$n,spacePanning:Xn,nodes:Un,node:Yn,locked:Fn,selected:Kn,dragging:Wn,nodeHeader:Zn,interactiveDragHandle:qn,nodeHeaderInput:Jn,lockIcon:Qn,nodeContent:eo,groupNode:to,collapsed:no,groupCollapsed:oo,groupExpanded:so,nodeInfo:io,nodeSuccess:ao,nodeWarning:ro,nodeError:co,nodeDisabled:lo,toolbar:uo,toolButton:po,contextMenu:ho,contextMenuItem:go,grid:mo,inspectorPanel:fo,inspectorHeader:yo,inspectorContent:xo,inspectorSection:vo,inspectorRow:bo,editorWithInspector:No,editorMain:Co,externalDataInfo:So,dragGuides:wo,dragGuide:Eo,dragGuideVertical:Io,dragGuideHorizontal:Do,snapTarget:jo,distanceIndicator:ko,distanceLine:Po,statusBar:To,statusSection:Mo,statusLabel:Oo,statusValue:zo,statusMode:Ao,nodePort:Ro,portInput:Vo,portOutput:Lo,portInner:_o,portLabel:Ho,portLeft:Bo,portRight:Go,portTop:$o,portBottom:Xo,connections:Uo,inspectorTabs:Yo,inspectorTab:Fo,active:Ko,inspectorField:Wo,inspectorInput:Zo,inspectorTextarea:qo,inspectorPositionInputs:Jo,inspectorNumberInput:Qo,inspectorReadOnlyField:es,inspectorEmptyState:ts,canvasContainer:ns,boxSelecting:os,gridSvg:ss,editorLayout:is,editorToolbar:as,editorContent:rs,editorSidebar:cs,topToolbar:ls,nodeLayer:ds,nodeView:us,nodeTitle:ps,nodeTitleInput:hs,groupAcceptingDrop:gs,groupPulse:ms,groupHasChildren:fs,nodePorts:ys,port:xs,portHovered:vs,portConnecting:bs,pulse:Ns,portConnected:Cs,portLabelLeft:Ss,portLabelRight:ws,portLabelTop:Es,portLabelBottom:Is,connectionLayer:Ds,connectionGroup:js,connectionSelected:ks,connectionHovered:Ps,connectionDragging:Ts,dragConnection:Ms,dashAnimation:Os,selectionBoxOverlay:zs,selectionOverlay:As,loadingOverlay:Rs,loadingIndicator:Vs,customNodeContent:Ls,resizeHandle:_s,resizeHandleActive:Hs,nodeSearchMenu:Bs,menuFadeIn:Gs,searchHeader:$s,searchInput:Xs,searchHint:Us,searchResults:Ys,categoryList:Fs,categoryGroup:Ks,categoryHeader:Ws,selectedCategory:Zs,categoryName:qs,nodeCount:Js,nodeList:Qs,nodeItem:ei,selectedNode:ti,nodeIcon:ni,nodeName:oi,nodeDescription:si,nodeType:ii,noResults:ai,noResultsIcon:ri,searchFooter:ci,selectionInfo:li,minimapContainer:di,minimap:ui,minimapTitle:pi,minimapContent:hi,minimapViewport:gi,minimapNodes:mi,darkTheme:fi,smoothAnimations:yi,statusSaving:xi,uiOverlayContainer:vi},pt=({children:e,className:t,"data-testid":n="node-editor-base"})=>(_n(),a.jsx("div",{className:Y.classNames(S.nodeEditorBase,t),"data-testid":n,tabIndex:0,children:e}));pt.displayName="NodeEditorBase";const bi=(e,t)=>{switch(t.type){case"SET_VIEWPORT":return{...e,viewport:t.payload.viewport};case"PAN_VIEWPORT":{const{delta:n}=t.payload;return{...e,viewport:{...e.viewport,offset:{x:e.viewport.offset.x+n.x,y:e.viewport.offset.y+n.y}}}}case"ZOOM_VIEWPORT":{const{scale:n,center:o}=t.payload,i=Math.max(.01,Math.min(64,n));if(o){const s=i/e.viewport.scale,r={x:o.x-(o.x-e.viewport.offset.x)*s,y:o.y-(o.y-e.viewport.offset.y)*s};return{...e,viewport:{offset:r,scale:i}}}return{...e,viewport:{...e.viewport,scale:i}}}case"RESET_VIEWPORT":return{...e,viewport:{offset:{x:0,y:0},scale:1}};case"UPDATE_GRID_SETTINGS":return{...e,gridSettings:{...e.gridSettings,...t.payload.settings}};case"SET_SPACE_PANNING":return{...e,isSpacePanning:t.payload.isSpacePanning};case"START_PAN":return{...e,panState:{isPanning:!0,startPosition:t.payload.position}};case"UPDATE_PAN":{if(!e.panState.isPanning||!e.panState.startPosition)return e;const n=t.payload.position.x-e.panState.startPosition.x,o=t.payload.position.y-e.panState.startPosition.y;return{...e,viewport:{...e.viewport,offset:{x:e.viewport.offset.x+n,y:e.viewport.offset.y+o}},panState:{...e.panState,startPosition:t.payload.position}}}case"END_PAN":return{...e,panState:{isPanning:!1,startPosition:null}};default:return e}},Ni={viewport:{offset:{x:0,y:0},scale:1},gridSettings:{enabled:!1,size:20,showGrid:!0,snapToGrid:!1,snapThreshold:8},isSpacePanning:!1,panState:{isPanning:!1,startPosition:null}},Ci={setViewport:e=>({type:"SET_VIEWPORT",payload:{viewport:e}}),panViewport:e=>({type:"PAN_VIEWPORT",payload:{delta:e}}),zoomViewport:(e,t)=>({type:"ZOOM_VIEWPORT",payload:{scale:e,center:t}}),resetViewport:()=>({type:"RESET_VIEWPORT"}),updateGridSettings:e=>({type:"UPDATE_GRID_SETTINGS",payload:{settings:e}}),setSpacePanning:e=>({type:"SET_SPACE_PANNING",payload:{isSpacePanning:e}}),startPan:e=>({type:"START_PAN",payload:{position:e}}),updatePan:e=>({type:"UPDATE_PAN",payload:{position:e}}),endPan:()=>({type:"END_PAN"})},Si=(e,t)=>({screenToCanvas:(n,o)=>{if(!e.current)return console.warn("Canvas ref is not available for coordinate conversion"),{x:n,y:o};const i=e.current.getBoundingClientRect();return{x:(n-i.left-t.offset.x)/t.scale,y:(o-i.top-t.offset.y)/t.scale}},canvasToScreen:(n,o)=>{if(!e.current)return console.warn("Canvas ref is not available for coordinate conversion"),{x:n,y:o};const i=e.current.getBoundingClientRect();return{x:n*t.scale+t.offset.x+i.left,y:o*t.scale+t.offset.y+i.top}}}),ht=l.createContext(null),gt=({children:e,initialState:t})=>{const[n,o]=l.useReducer(bi,{...Ni,...t}),i=l.useRef(null),s=l.useMemo(()=>Si(i,n.viewport),[n.viewport]),r={state:n,dispatch:o,actions:Ci,canvasRef:i,utils:s};return a.jsx(ht.Provider,{value:r,children:e})},ee=()=>{const e=l.useContext(ht);if(!e)throw new Error("useNodeCanvas must be used within a NodeCanvasProvider");return e},wi="enenodtrelis",Ei="enehdr",Ii="enetitle",Di="enenodcouU5z",ji="enetreecnt",ki="eneempState",Pi="enetreeitm",Ti="eneseligQ",Mi="enenodeNamegua",Oi="enenodeicovQJ",zi="eneexpbtn",Ai="enevis",Ri="enedrgvgz",Vi="enedraoveins",Li="enedropind",_i="enedropul",q={nodeTreeList:wi,header:Ei,title:Ii,nodeCount:Di,treeContainer:ji,emptyState:ki,treeItem:Pi,selected:Ti,nodeName:Mi,nodeIcon:Oi,expandButton:zi,visibilityButton:Ai,dragging:Ri,dragOverInside:Vi,dropIndicator:Li,dropIndicatorPulse:_i},Hi=({node:e,level:t,isSelected:n,onSelect:o,onToggleVisibility:i,onToggleExpand:s,childNodes:r,dragState:c,onNodeDrop:d,onDragStateChange:h})=>{var k;const u=e.type==="group"&&r.length>0,p=e.type==="group"&&e.expanded!==!1,m=e.type==="group",y=c.draggingNodeId===e.id,N=c.dragOverNodeId===e.id,f=N?c.dragOverPosition:null,v=D=>{D.stopPropagation(),o(e.id,D.ctrlKey||D.metaKey)},x=D=>{D.stopPropagation(),s&&u&&s(e.id)},I=D=>{D.stopPropagation(),i&&i(e.id)},j=()=>{switch(e.type){case"group":return"📁";case"input":return"📥";case"output":return"📤";case"process":return"⚙️";default:return"📦"}},b=D=>{D.dataTransfer.effectAllowed="move",D.dataTransfer.setData("nodeId",e.id),h({draggingNodeId:e.id})},C=()=>{h({draggingNodeId:null,dragOverNodeId:null,dragOverPosition:null})},g=D=>{if(D.preventDefault(),D.stopPropagation(),c.draggingNodeId===e.id)return;const M=D.currentTarget.getBoundingClientRect(),P=D.clientY-M.top,T=M.height;let z;m&&P>T*.25&&P<T*.75?z="inside":P<T/2?z="before":z="after",(c.dragOverNodeId!==e.id||c.dragOverPosition!==z)&&h({dragOverNodeId:e.id,dragOverPosition:z})},w=D=>{D.currentTarget===D.target&&h({dragOverNodeId:null,dragOverPosition:null})},E=D=>{D.preventDefault(),D.stopPropagation();const M=D.dataTransfer.getData("nodeId");M&&c.dragOverPosition&&d(M,e.id,c.dragOverPosition),h({draggingNodeId:null,dragOverNodeId:null,dragOverPosition:null})};return a.jsxs(a.Fragment,{children:[N&&f==="before"&&a.jsx("div",{className:q.dropIndicator,style:{marginLeft:`${t*16+8}px`}}),a.jsxs("div",{className:`${q.treeItem} ${n?q.selected:""} ${y?q.dragging:""} ${N&&f==="inside"?q.dragOverInside:""}`,style:{paddingLeft:`${t*16+8}px`},onClick:v,draggable:!0,onDragStart:b,onDragEnd:C,onDragOver:g,onDragLeave:w,onDrop:E,children:[u&&a.jsx("button",{className:q.expandButton,onClick:x,"aria-label":p?"Collapse":"Expand",children:a.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"currentColor",style:{transform:p?"rotate(90deg)":"rotate(0deg)",transition:"transform 0.2s"},children:a.jsx("path",{d:"M2 1l4 3-4 3V1z"})})}),a.jsx("span",{className:q.nodeIcon,children:j()}),a.jsx("span",{className:q.nodeName,children:((k=e.data)==null?void 0:k.title)||e.type}),a.jsx("button",{className:q.visibilityButton,onClick:I,"aria-label":e.visible!==!1?"Hide":"Show",children:a.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"currentColor",children:e.visible!==!1?a.jsx("path",{d:"M8 3C4.5 3 1.73 5.11 1 8c.73 2.89 3.5 5 7 5s6.27-2.11 7-5c-.73-2.89-3.5-5-7-5zm0 8.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7zm0-5.5a2 2 0 1 0 0 4 2 2 0 0 0 0-4z"}):a.jsxs(a.Fragment,{children:[a.jsx("path",{d:"M8 3C4.5 3 1.73 5.11 1 8c.73 2.89 3.5 5 7 5s6.27-2.11 7-5c-.73-2.89-3.5-5-7-5zm0 8.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7zm0-5.5a2 2 0 1 0 0 4 2 2 0 0 0 0-4z",opacity:"0.3"}),a.jsx("path",{d:"M2 2l12 12",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]})})})]}),u&&p&&r.map(D=>a.jsx(mt,{nodeId:D.id,level:t+1,dragState:c,onNodeDrop:d,onDragStateChange:h},D.id)),N&&f==="after"&&a.jsx("div",{className:q.dropIndicator,style:{marginLeft:`${t*16+8}px`}})]})},mt=({nodeId:e,level:t,dragState:n,onNodeDrop:o,onDragStateChange:i})=>{const{state:s,dispatch:r,actions:c}=K(),{state:d,dispatch:h,actions:u}=W(),p=s.nodes[e];if(!p)return null;const m=d.selectedNodeIds.includes(e),y=Object.values(s.nodes).filter(x=>x.parentId===e),N=l.useCallback((x,I)=>{h(u.selectNode(x,I))},[h,u]),f=l.useCallback(x=>{const I=s.nodes[x];I&&r(c.updateNode(x,{visible:I.visible===!1}))},[s.nodes,r,c]),v=l.useCallback(x=>{const I=s.nodes[x];I&&I.type==="group"&&r(c.updateNode(x,{expanded:!I.expanded}))},[s.nodes,r,c]);return a.jsx(Hi,{node:p,level:t,isSelected:m,onSelect:N,onToggleVisibility:f,onToggleExpand:v,childNodes:y,dragState:n,onNodeDrop:o,onDragStateChange:i})},Bi=({className:e})=>{const{state:t,dispatch:n,actions:o}=K(),{dispatch:i,actions:s}=W(),[r,c]=l.useState({draggingNodeId:null,dragOverNodeId:null,dragOverPosition:null}),d=l.useMemo(()=>Object.values(t.nodes).filter(y=>!y.parentId),[t.nodes]),h=l.useMemo(()=>[...d].sort((y,N)=>{var x,I;if(y.type==="group"&&N.type!=="group")return-1;if(y.type!=="group"&&N.type==="group")return 1;const f=((x=y.data)==null?void 0:x.title)||y.type,v=((I=N.data)==null?void 0:I.title)||N.type;return f.localeCompare(v)}),[d]),u=l.useCallback(()=>{i(s.clearSelection())},[i,s]),p=l.useCallback(y=>{c(N=>({...N,...y}))},[]),m=l.useCallback((y,N,f)=>{const v=t.nodes[y],x=t.nodes[N];if(!v||!x)return;const I=(j,b)=>{const C=t.nodes[j];return C?C.parentId===b?!0:C.parentId?I(C.parentId,b):!1:!1};if(!(y===N||I(N,y)))if(f==="inside"&&x.type==="group")n(o.updateNode(y,{parentId:N})),x.expanded||n(o.updateNode(N,{expanded:!0}));else{const j=x.parentId||void 0;n(o.updateNode(y,{parentId:j}))}},[t.nodes,n,o]);return a.jsxs("div",{className:`${q.nodeTreeList} ${e||""}`,children:[a.jsxs("div",{className:q.header,children:[a.jsx("h3",{className:q.title,children:"Layers"}),a.jsxs("div",{className:q.nodeCount,children:[Object.keys(t.nodes).length," nodes"]})]}),a.jsx("div",{className:q.treeContainer,onClick:u,children:h.length===0?a.jsx("div",{className:q.emptyState,children:"No nodes yet"}):h.map(y=>a.jsx(mt,{nodeId:y.id,level:0,dragState:r,onNodeDrop:m,onDragStateChange:p},y.id))})]})},ft=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M3 2v20h2V2H3zm4 5v2h14V7H7zm0 4v2h10v-2H7zm0 4v2h14v-2H7z"})});ft.displayName="AlignLeftIcon";const yt=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M5 7v2h14V7H5zm2 4v2h10v-2H7zm-2 4v2h14v-2H5z"})});yt.displayName="AlignCenterIcon";const xt=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M19 2v20h2V2h-2zM3 7v2h14V7H3zm4 4v2h10v-2H7zm-4 4v2h14v-2H3z"})});xt.displayName="AlignRightIcon";const vt=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M2 3v2h20V3H2zm5 4v14h2V7H7zm4 0v10h2V7h-2zm4 0v14h2V7h-2z"})});vt.displayName="AlignTopIcon";const bt=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M7 5v14h2V5H7zm4 2v10h2V7h-2zm4-2v14h2V5h-2zM2 11v2h20v-2H2z"})});bt.displayName="AlignMiddleIcon";const Nt=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M7 3v14h2V3H7zm4 4v10h2V7h-2zm4-4v14h2V3h-2zM2 19v2h20v-2H2z"})});Nt.displayName="AlignBottomIcon";const Ct=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M4 6v12h3V6H4zm6.5 2v8h3V8h-3zM17 6v12h3V6h-3zM2 3v18h2V3H2zm18 0v18h2V3h-2z"})});Ct.displayName="DistributeHorizontalIcon";const St=({size:e,className:t})=>a.jsx("svg",{className:t,fill:"currentColor",width:e,height:e,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:a.jsx("path",{d:"M6 4h12v3H6V4zm2 6.5h8v3H8v-3zM6 17h12v3H6v-3zM3 2h18v2H3V2zm0 18h18v2H3v-2z"})});St.displayName="DistributeVerticalIcon";const Gi="enealncon",$i="enealnlbl",Xi="enealnGrid",Ui="enealnbtn",Ee={alignmentControls:Gi,alignmentLabel:$i,alignmentGrid:Xi,alignmentButton:Ui},wt=l.memo(({value:e,onChange:t,style:n,type:o="text",placeholder:i,id:s,name:r,"aria-label":c})=>a.jsx("input",{type:o,value:e,onChange:d=>t(d.target.value),style:n,placeholder:i,id:s,name:r,"aria-label":c}));wt.displayName="InspectorInput";const Et=l.memo(({value:e,onChange:t,style:n,id:o,name:i,"aria-label":s})=>a.jsx("textarea",{value:e,onChange:r=>t(r.target.value),style:n,id:o,name:i,"aria-label":s}));Et.displayName="InspectorTextarea";const xe=l.memo(({value:e,onChange:t,label:n,id:o,name:i,"aria-label":s})=>{const r={display:"flex",alignItems:"center",gap:"6px",backgroundColor:"#f5f5f5",border:"1px solid #ddd",borderRadius:"4px",padding:"4px 8px",fontSize:"12px"},c={color:"#666",fontSize:"11px",fontWeight:500,minWidth:"12px",textAlign:"center"},d={border:"none",background:"transparent",fontSize:"12px",outline:"none",width:"100%",textAlign:"right"};return a.jsxs("div",{style:r,children:[a.jsx("span",{style:c,children:n}),a.jsx("input",{type:"number",value:e,onChange:h=>t(Number(h.target.value)),style:d,id:o,name:i,"aria-label":s})]})});xe.displayName="InspectorNumberInput";const Ae=l.memo(({checked:e,onChange:t,label:n,id:o,name:i})=>a.jsxs("label",{htmlFor:o,style:{display:"flex",alignItems:"center",gap:"6px",cursor:"pointer"},children:[a.jsx("input",{type:"checkbox",checked:e,onChange:s=>t(s.target.checked),id:o,name:i}),a.jsx("span",{style:{fontSize:"13px"},children:n})]}));Ae.displayName="InspectorCheckbox";const It=l.memo(({selectedNodes:e,onAlign:t})=>{const n=e.length<2,o=[{type:"align-left",icon:ft,title:"Align Left"},{type:"align-center-horizontal",icon:yt,title:"Align Center Horizontal"},{type:"align-right",icon:xt,title:"Align Right"},{type:"align-top",icon:vt,title:"Align Top"},{type:"align-center-vertical",icon:bt,title:"Align Center Vertical"},{type:"align-bottom",icon:Nt,title:"Align Bottom"},{type:"distribute-horizontal",icon:Ct,title:"Distribute Horizontally"},{type:"distribute-vertical",icon:St,title:"Distribute Vertically"}];return a.jsxs("div",{className:Ee.alignmentControls,children:[a.jsxs("label",{className:Ee.alignmentLabel,children:["Alignment ",e.length>1?`(${e.length} nodes)`:"(select 2+ nodes)",":"]}),a.jsx("div",{className:Ee.alignmentGrid,children:o.map(i=>{const s=i.icon;return a.jsx("button",{onClick:()=>!n&&t(i.type),className:Ee.alignmentButton,title:n?"Select 2 or more nodes to enable alignment":i.title,disabled:n,children:a.jsx(s,{size:14})},i.type)})})]})});It.displayName="AlignmentControls";const Dt=l.memo(({node:e,onUpdateNode:t,onDeleteNode:n,selectedNodes:o=[],onAlignNodes:i})=>{var x,I;const s=l.useMemo(()=>({width:"100%",padding:"4px 8px",border:"1px solid #ddd",borderRadius:"4px",fontSize:"13px"}),[]),r=l.useMemo(()=>({display:"block",marginBottom:"4px",fontSize:"12px",fontWeight:500,color:"#666"}),[]),c=l.useCallback(j=>{t({data:{...e.data,title:j}})},[e.data,t]),d=l.useCallback(j=>{t({data:{...e.data,content:j}})},[e.data,t]),h=l.useCallback(j=>{t({position:{...e.position,x:j}})},[e.position,t]),u=l.useCallback(j=>{t({position:{...e.position,y:j}})},[e.position,t]),p=l.useCallback(j=>{var b;t({size:{...e.size,width:j,height:((b=e.size)==null?void 0:b.height)??0}})},[e.size,t]),m=l.useCallback(j=>{var b;t({size:{...e.size,height:j,width:((b=e.size)==null?void 0:b.width)??0}})},[e.size,t]),y=l.useCallback(j=>{t({locked:j})},[t]),N=l.useCallback(j=>{t({visible:j})},[t]),f=l.useCallback(j=>{!i||o.length<2||i(j,o)},[i,o]),v=l.useMemo(()=>({...s,minHeight:"60px",resize:"vertical"}),[s]);return l.useMemo(()=>({...s,width:"50%"}),[s]),a.jsxs("div",{children:[a.jsx("h4",{style:{margin:"0 0 16px",fontSize:"14px"},children:"Node Properties"}),a.jsxs("div",{style:{marginBottom:"12px"},children:[a.jsx("label",{htmlFor:`node-${e.id}-title`,style:r,children:"Title:"}),a.jsx(wt,{id:`node-${e.id}-title`,name:"nodeTitle",value:e.data.title||"",onChange:c,style:s})]}),e.data.content!==void 0&&a.jsxs("div",{style:{marginBottom:"12px"},children:[a.jsx("label",{htmlFor:`node-${e.id}-content`,style:r,children:"Content:"}),a.jsx(Et,{id:`node-${e.id}-content`,name:"nodeContent",value:String(e.data.content)||"",onChange:d,style:v})]}),a.jsx(It,{selectedNodes:o,onAlign:f}),a.jsxs("div",{style:{marginBottom:"12px"},children:[a.jsx("label",{style:r,children:"Position & Size:"}),a.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"4px"},children:[a.jsx(xe,{label:"X",value:e.position.x,onChange:h,id:`node-${e.id}-pos-x`,name:"nodePosX","aria-label":"X position"}),a.jsx(xe,{label:"Y",value:e.position.y,onChange:u,id:`node-${e.id}-pos-y`,name:"nodePosY","aria-label":"Y position"}),a.jsx(xe,{label:"W",value:((x=e.size)==null?void 0:x.width)||100,onChange:p,id:`node-${e.id}-width`,name:"nodeWidth","aria-label":"Width"}),a.jsx(xe,{label:"H",value:((I=e.size)==null?void 0:I.height)||100,onChange:m,id:`node-${e.id}-height`,name:"nodeHeight","aria-label":"Height"})]})]}),a.jsxs("div",{style:{marginBottom:"12px"},children:[a.jsx("label",{style:r,children:"Type:"}),a.jsx("div",{style:{padding:"4px 8px",backgroundColor:"#f5f5f5",borderRadius:"4px",fontSize:"13px"},children:e.type})]}),e.type==="group"&&a.jsxs(a.Fragment,{children:[a.jsx("div",{style:{marginBottom:"12px"},children:a.jsx(Ae,{checked:e.locked||!1,onChange:y,label:"Lock Layer"})}),a.jsx("div",{style:{marginBottom:"12px"},children:a.jsx(Ae,{checked:e.visible!==!1,onChange:N,label:"Visible"})})]}),a.jsx("div",{style:{marginTop:"16px",paddingTop:"16px",borderTop:"1px solid #eee"},children:a.jsx("button",{onClick:n,style:{padding:"8px 16px",backgroundColor:"#dc3545",color:"white",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"13px",width:"100%"},children:"Delete Node"})})]})});Dt.displayName="DefaultInspectorRenderer";function jt(e){var o,i;const t=((o=e.size)==null?void 0:o.width)||100,n=((i=e.size)==null?void 0:i.height)||100;return{left:e.position.x,top:e.position.y,right:e.position.x+t,bottom:e.position.y+n,width:t,height:n,centerX:e.position.x+t/2,centerY:e.position.y+n/2}}function Yi(e){if(e.length===0)return null;const t=e.map(jt),n=Math.min(...t.map(r=>r.left)),o=Math.min(...t.map(r=>r.top)),i=Math.max(...t.map(r=>r.right)),s=Math.max(...t.map(r=>r.bottom));return{left:n,top:o,right:i,bottom:s,width:i-n,height:s-o,centerX:n+(i-n)/2,centerY:o+(s-o)/2}}function Fi(e,t){if(e.length<2)return{};const n={},o=e.map(s=>({node:s,bounds:jt(s)})),i=Yi(e);if(!i)return{};switch(t){case"align-left":{const s=Math.min(...o.map(r=>r.bounds.left));o.forEach(({node:r})=>{n[r.id]={x:s,y:r.position.y}});break}case"align-center-horizontal":{o.forEach(({node:s,bounds:r})=>{const c=i.centerX-r.width/2;n[s.id]={x:c,y:s.position.y}});break}case"align-right":{const s=Math.max(...o.map(r=>r.bounds.right));o.forEach(({node:r,bounds:c})=>{const d=s-c.width;n[r.id]={x:d,y:r.position.y}});break}case"align-top":{const s=Math.min(...o.map(r=>r.bounds.top));o.forEach(({node:r})=>{n[r.id]={x:r.position.x,y:s}});break}case"align-center-vertical":{o.forEach(({node:s,bounds:r})=>{const c=i.centerY-r.height/2;n[s.id]={x:s.position.x,y:c}});break}case"align-bottom":{const s=Math.max(...o.map(r=>r.bounds.bottom));o.forEach(({node:r,bounds:c})=>{const d=s-c.height;n[r.id]={x:r.position.x,y:d}});break}case"distribute-horizontal":{if(e.length<3)break;const s=o.sort((u,p)=>u.bounds.left-p.bounds.left),r=s[0],h=(s[s.length-1].bounds.left-r.bounds.left)/(s.length-1);s.forEach(({node:u},p)=>{if(p===0||p===s.length-1)n[u.id]={x:u.position.x,y:u.position.y};else{const m=r.bounds.left+h*p;n[u.id]={x:m,y:u.position.y}}});break}case"distribute-vertical":{if(e.length<3)break;const s=o.sort((u,p)=>u.bounds.top-p.bounds.top),r=s[0],h=(s[s.length-1].bounds.top-r.bounds.top)/(s.length-1);s.forEach(({node:u},p)=>{if(p===0||p===s.length-1)n[u.id]={x:u.position.x,y:u.position.y};else{const m=r.bounds.top+h*p;n[u.id]={x:u.position.x,y:m}}});break}}return n}const He=({className:e})=>{var N,f;const{state:t,actions:n,dispatch:o}=K(),{state:i}=W(),{state:s,dispatch:r,actions:c}=ee(),[d,h]=l.useState("layers"),u=i.selectedNodeIds.length>0?t.nodes[i.selectedNodeIds[0]]:null,p=i.selectedNodeIds.map(v=>t.nodes[v]).filter(Boolean),m=i.selectedConnectionIds.length>0?t.connections[i.selectedConnectionIds[0]]:null,y=l.useCallback((v,x)=>{const I=Fi(x,v);Object.keys(I).length>0&&o(n.moveNodes(I))},[o,n]);return a.jsxs("div",{className:Y.classNames(S.inspectorPanel,e),"data-testid":"inspector-panel",children:[a.jsx("div",{className:S.inspectorHeader,children:a.jsxs("div",{className:S.inspectorTabs,children:[a.jsx("button",{className:Y.classNames(S.inspectorTab,d==="layers"&&S.active),onClick:()=>h("layers"),children:"Layers"}),a.jsx("button",{className:Y.classNames(S.inspectorTab,d==="properties"&&S.active),onClick:()=>h("properties"),children:"Properties"})]})}),a.jsx("div",{className:S.inspectorContent,children:d==="layers"?a.jsx(Bi,{}):a.jsxs(a.Fragment,{children:[u&&a.jsx("div",{className:S.inspectorSection,children:a.jsx(Dt,{node:u,selectedNodes:p,onAlignNodes:y,externalData:null,isLoadingExternalData:!1,externalDataError:null,onUpdateNode:v=>{o(n.updateNode(u.id,v))},onUpdateExternalData:async()=>{},onDeleteNode:()=>{o(n.deleteNode(u.id))}})}),m&&a.jsxs("div",{className:S.inspectorSection,children:[a.jsx("h4",{children:"Connection Properties"}),a.jsxs("div",{className:S.inspectorField,children:[a.jsx("label",{children:"From:"}),a.jsxs("span",{className:S.inspectorReadOnlyField,children:[((N=t.nodes[m.fromNodeId])==null?void 0:N.data.title)||m.fromNodeId,".",m.fromPortId]})]}),a.jsxs("div",{className:S.inspectorField,children:[a.jsx("label",{children:"To:"}),a.jsxs("span",{className:S.inspectorReadOnlyField,children:[((f=t.nodes[m.toNodeId])==null?void 0:f.data.title)||m.toNodeId,".",m.toPortId]})]})]}),!u&&!m&&a.jsx("div",{className:S.inspectorEmptyState,children:a.jsx("p",{children:"Select a node or connection to view its properties"})}),i.selectedNodeIds.length>1&&a.jsxs("div",{className:S.inspectorSection,children:[a.jsx("h4",{children:"Multiple Selection"}),a.jsxs("p",{children:[i.selectedNodeIds.length," nodes selected"]})]}),a.jsxs("div",{className:S.inspectorSection,children:[a.jsx("h4",{children:"Grid Settings"}),a.jsx("div",{className:S.inspectorField,children:a.jsxs("label",{children:[a.jsx("input",{id:"grid-show",name:"showGrid",type:"checkbox",checked:s.gridSettings.showGrid,onChange:v=>{r(c.updateGridSettings({showGrid:v.target.checked}))}}),"Show Grid"]})}),a.jsx("div",{className:S.inspectorField,children:a.jsxs("label",{children:[a.jsx("input",{id:"grid-snap",name:"snapToGrid",type:"checkbox",checked:s.gridSettings.snapToGrid,onChange:v=>{r(c.updateGridSettings({snapToGrid:v.target.checked}))}}),"Snap to Grid"]})}),a.jsxs("div",{className:S.inspectorField,children:[a.jsx("label",{htmlFor:"grid-size",children:"Grid Size:"}),a.jsx("input",{id:"grid-size",name:"gridSize",type:"number",className:S.inspectorInput,value:s.gridSettings.size,min:10,max:100,step:5,onChange:v=>{const x=parseInt(v.target.value,10);!isNaN(x)&&x>0&&r(c.updateGridSettings({size:x}))},"aria-label":"Grid size in pixels"})]}),a.jsxs("div",{className:S.inspectorField,children:[a.jsx("label",{htmlFor:"snap-threshold",children:"Snap Threshold:"}),a.jsx("input",{id:"snap-threshold",name:"snapThreshold",type:"number",className:S.inspectorInput,value:s.gridSettings.snapThreshold,min:1,max:20,step:1,onChange:v=>{const x=parseInt(v.target.value,10);!isNaN(x)&&x>0&&r(c.updateGridSettings({snapThreshold:x}))},"aria-label":"Snap threshold in pixels"})]})]