UNPKG

@matthewgapp/solidjs-flow

Version:

React Flow - A highly customizable React library for building node-based editors and interactive flow charts.

177 lines (153 loc) 5.15 kB
import { infiniteExtent, ConnectionMode, adoptUserNodes, getViewportForBounds, Transform, updateConnectionLookup, devWarn, getInternalNodesBounds, PanZoomInstance, SelectionRect, ConnectionStatus, ConnectingHandle, OnError, } from '@xyflow/system'; import { FitViewOptions, type Edge, type InternalNode, type Node, type SolidFlowStore, OnSelectionChangeFunc } from '../types'; import { Signal, createSignal } from 'solid-js'; import { ReactiveMap } from '@solid-primitives/map'; const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, }: { nodes?: Node[]; edges?: Edge[]; defaultNodes?: Node[]; defaultEdges?: Edge[]; width?: number; height?: number; fitView?: boolean; } = {}): SolidFlowStore => { const nodeLookup = new Map<string, InternalNode>(); const parentLookup = new Map(); const connectionLookup = new Map(); const edgeLookup = new Map(); const storeEdges = defaultEdges ?? edges ?? []; const storeNodes = defaultNodes ?? nodes ?? []; updateConnectionLookup(connectionLookup, edgeLookup, storeEdges); adoptUserNodes(storeNodes, nodeLookup, parentLookup, { nodeOrigin: [0, 0], elevateNodesOnSelect: false, }); let transform: Transform = [0, 0, 1]; if (fitView && width && height) { // @todo users nodeOrigin should be used here const bounds = getInternalNodesBounds(nodeLookup, { nodeOrigin: [0, 0], filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)), }); const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1); transform = [x, y, zoom]; } return { rfId: new Writable('1'), width: new Writable(0), height: new Writable(0), transform: new Writable(transform), nodes: new Writable(storeNodes), nodeLookup: new ReactiveMap(), parentLookup: new ReactiveMap(), edges: new Writable(storeEdges), edgeLookup: new ReactiveMap(), connectionLookup: new ReactiveMap(), onNodesChange: wNullable(), onEdgesChange: wNullable(), hasDefaultNodes: new Writable(defaultNodes !== undefined), hasDefaultEdges: new Writable(defaultEdges !== undefined), panZoom: new Writable<PanZoomInstance | null>(null), minZoom: new Writable(0.5), maxZoom: new Writable(2), translateExtent: new Writable(infiniteExtent), nodeExtent: new Writable(infiniteExtent), nodesSelectionActive: new Writable(false), userSelectionActive: new Writable(false), userSelectionRect: new Writable<SelectionRect | null>(null), connectionPosition: new Writable({ x: 0, y: 0 }), connectionStatus: new Writable<ConnectionStatus | null>(null), connectionMode: new Writable<ConnectionMode>(ConnectionMode.Strict), domNode: new Writable<HTMLDivElement | null>(null), paneDragging: new Writable(false, "paneDragging"), noPanClassName: new Writable('nopan'), nodeOrigin: new Writable([0, 0]), nodeDragThreshold: new Writable(1), snapGrid: new Writable([15, 15]), snapToGrid: new Writable(false), nodesDraggable: new Writable(true), nodesConnectable: new Writable(true), nodesFocusable: new Writable(true), edgesFocusable: new Writable(true), edgesUpdatable: new Writable(true), elementsSelectable: new Writable(true), elevateNodesOnSelect: new Writable(true), elevateEdgesOnSelect: new Writable(false), fitViewOnInit: new Writable(false), fitViewDone: new Writable(false), fitViewOnInitOptions: new Writable<FitViewOptions | undefined>(undefined), selectNodesOnDrag: new Writable(true), multiSelectionActive: new Writable(false), connectionStartHandle: new Writable<ConnectingHandle | null>(null), connectionEndHandle: new Writable<ConnectingHandle | null>(null), connectionClickStartHandle: wNullable(), connectOnClick: w(true), ariaLiveMessage: w(''), autoPanOnConnect: w(true), autoPanOnNodeDrag: w(true), connectionRadius: w(20), onError: w<OnError | undefined>(devWarn), isValidConnection: undefined, onSelectionChangeHandlers: w<OnSelectionChangeFunc[]>([]), onConnect: wEmpty(), onDelete: wEmpty(), onEdgesDelete: wEmpty(), onNodesDelete: wEmpty(), onBeforeDelete: wEmpty(), onViewportChange: wEmpty(), onViewportChangeEnd: wEmpty(), onViewportChangeStart: wEmpty(), lib: new Writable('solid'), debug: new Writable(false), }; }; export default getInitialState; const w = <T,>(x: T) => new Writable<T>(x) const wEmpty = <T>() => new Writable<T | undefined>(undefined) const wNullable = <T>() => new Writable<T | null>(null) export class Writable<T> { private s: Signal<T> constructor(initial: T, private debugName?: string) { this.s = createSignal(initial, { name: debugName }); } get() { return this.s[0](); } set(v: T) { if (this.debugName) { console.log("setting", this.debugName, v) } this.s[1](() => { return v; }); } setFromPrev(fn: (prev: T) => T) { this.s[1]((prev) => { return fn(prev); }); } }