UNPKG

@selenite/graph-editor

Version:

A graph editor for visual programming, based on rete and svelte.

128 lines (127 loc) 5.68 kB
import { ClassicPreset, Scope } from 'rete'; import { classicConnectionPath, getDOMSocketPosition, loopConnectionPath } from 'rete-render-utils'; import Connection from './components/Connection.svelte'; import ConnectionWrapper from './components/ConnectionWrapper.svelte'; import Control from './components/Control.svelte'; import Node from './components/Node.svelte'; import Socket from './components/Socket.svelte'; export { default as Connection } from './components/Connection.svelte'; export { default as Control } from './components/Control.svelte'; export { default as Socket } from './components/Socket.svelte'; export { default as Button } from './components/Button.svelte'; // export {default as InputControl} from './components/InputControl.svelte' export { default as InputControl } from './components/InputControl.svelte'; export { default as ExecSocket } from './components/ExecSocket.svelte'; export { default as AddXmlAttributeControl } from '../../AddXmlAttributeControl.svelte'; /** * Classic preset for rendering nodes, connections, controls and sockets. */ export function setup(props) { const positionWatcher = typeof props?.socketPositionWatcher === 'undefined' ? getDOMSocketPosition() : props?.socketPositionWatcher; const { node, connection, socket, control } = props?.customize || {}; return { attach(plugin) { positionWatcher.attach(plugin); }, update(context, plugin) { const { payload } = context.data; const parent = plugin.parentScope(); if (!parent) throw new Error('parent'); const emit = parent.emit.bind(parent); if (context.data.type === 'node') { return { data: payload, emit }; } else if (context.data.type === 'connection') { const { start, end } = context.data; // console.log("Connection") return { data: payload, ...(start ? { start } : {}), ...(end ? { end } : {}) }; } return { data: payload }; }, // eslint-disable-next-line max-statements, complexity render(context, plugin) { const parent = plugin.parentScope(); const emit = parent.emit.bind(parent); if (context.data.type === 'node') { const component = node ? node(context.data) : Node; return (component && { component, props: { data: context.data.payload, emit } }); } else if (context.data.type === 'connection') { const component = connection ? connection(context.data) : Connection; const { payload } = context.data; const { source, target, sourceOutput, targetInput } = payload; return (component && { component: ConnectionWrapper, props: { data: context.data.payload, component, start: context.data.start || ((change) => positionWatcher.listen(source, 'output', sourceOutput, change)), end: context.data.end || ((change) => positionWatcher.listen(target, 'input', targetInput, change)), path: async (start, end) => { const response = await plugin.emit({ type: 'connectionpath', data: { payload, points: [start, end] } }); if (!response) return ''; const { path, points } = response.data; const curvature = 0.3; if (!path && points.length !== 2) throw new Error('cannot render connection with a custom number of points'); if (!path) return payload.isLoop ? loopConnectionPath(points, curvature, 120) : classicConnectionPath(points, curvature); return path; } } }); } else if (context.data.type === 'socket') { const { payload } = context.data; const component = socket ? socket(context.data) : Socket; return (component && { component, props: { data: payload } }); } else if (context.data.type === 'control') { const { payload } = context.data; if (control) { const component = control(context.data); return (component && { component, props: { data: payload } }); } return context.data.payload instanceof ClassicPreset.InputControl ? { component: Control, props: { data: payload } } : null; } } }; }