@unblocks/xyflow-react
Version:
Utilities for working with @xyflow/react
279 lines (269 loc) • 11 kB
JavaScript
'use client'
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
DagreFlow: () => DagreFlow,
Graph: () => Graph,
MultiHandle: () => MultiHandle_default,
WithMultiHandle: () => WithMultiHandle_default,
createEdge: () => createEdge,
createNode: () => createNode
});
module.exports = __toCommonJS(index_exports);
// src/components/DagreFlow.tsx
var import_react = __toESM(require("react"));
var import_react2 = require("@xyflow/react");
// src/models/dagreLayout.ts
var import_dagre = __toESM(require("@dagrejs/dagre"));
var DEFAULT_DAGRE_OPTIONS = { direction: "LR", nodesep: 8, ranksep: 48 };
function dagreLayout(nodes, edges, options = DEFAULT_DAGRE_OPTIONS) {
const g = new import_dagre.default.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
const { nodesep = 8, ranksep = 48 } = options;
g.setGraph({ rankdir: options.direction, nodesep, ranksep });
edges.forEach((edge) => g.setEdge(edge.source, edge.target));
nodes.forEach(
(node) => {
var _a, _b, _c, _d;
return g.setNode(node.id, __spreadProps(__spreadValues({}, node), {
width: (_b = (_a = node.measured) == null ? void 0 : _a.width) != null ? _b : 0,
height: (_d = (_c = node.measured) == null ? void 0 : _c.height) != null ? _d : 0
}));
}
);
import_dagre.default.layout(g);
return {
nodes: nodes.map((node) => {
var _a, _b, _c, _d;
const position = g.node(node.id);
const x = position.x - ((_b = (_a = node.measured) == null ? void 0 : _a.width) != null ? _b : 0) / 2;
const y = position.y - ((_d = (_c = node.measured) == null ? void 0 : _c.height) != null ? _d : 0) / 2;
return __spreadProps(__spreadValues({}, node), { position: { x, y } });
}),
edges
};
}
// src/components/DagreFlow.tsx
var OPTIONS = {
includeHiddenNodes: false
};
var DEFAULT_CHILDREN = /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(import_react2.Background, null), /* @__PURE__ */ import_react.default.createElement(import_react2.Controls, null));
function DagreFlow(_a) {
var _b = _a, { graph, dagreOptions, children } = _b, restProps = __objRest(_b, ["graph", "dagreOptions", "children"]);
const nodesInitialized = (0, import_react2.useNodesInitialized)(OPTIONS);
const { fitView } = (0, import_react2.useReactFlow)();
const [nodes, setNodes, onNodesChange] = (0, import_react2.useNodesState)(graph.nodes);
const [layoutedNodes, setLayoutedNodes] = (0, import_react.useState)(graph.nodes);
const isInitialized = (0, import_react.useRef)(false);
(0, import_react.useEffect)(() => {
setLayoutedNodes(graph.nodes);
setNodes(graph.nodes);
}, [graph, setNodes]);
(0, import_react.useEffect)(() => {
if (nodesInitialized) {
if (!isInitialized.current) {
const newNodes = dagreLayout(nodes, graph.edges, dagreOptions).nodes;
setLayoutedNodes(newNodes.concat());
isInitialized.current = true;
}
} else {
setLayoutedNodes(nodes.concat());
isInitialized.current = false;
}
setTimeout(() => {
requestAnimationFrame(() => {
fitView();
});
}, 10);
}, [nodes, fitView, graph, nodesInitialized, dagreOptions]);
const allEdges = (0, import_react.useMemo)(() => graph.getAllEdges(), [graph]);
return /* @__PURE__ */ import_react.default.createElement(import_react2.ReactFlow, __spreadValues({ nodes: layoutedNodes, edges: allEdges, onNodesChange, fitView: true }, restProps), typeof children === "undefined" ? DEFAULT_CHILDREN : children);
}
// src/components/MultiHandle.tsx
var import_react3 = __toESM(require("react"));
var import_react4 = require("@xyflow/react");
function MultiHandle({
topSourceHandle = false,
topTargetHandle = true,
leftSourceHandle = false,
leftTargetHandle = false,
rightSourceHandle = false,
rightTargetHandle = false,
bottomSourceHandle = true,
bottomTargetHandle = false
}) {
return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, topSourceHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "source", id: "top-source", position: import_react4.Position.Top }), topTargetHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "target", id: "top-target", position: import_react4.Position.Top }), bottomSourceHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "source", id: "bottom-source", position: import_react4.Position.Bottom }), bottomTargetHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "target", id: "bottom-target", position: import_react4.Position.Bottom }), leftSourceHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "source", id: "left-source", position: import_react4.Position.Left }), leftTargetHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "target", id: "left-target", position: import_react4.Position.Left }), rightSourceHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "source", id: "right-source", position: import_react4.Position.Right }), rightTargetHandle && /* @__PURE__ */ import_react3.default.createElement(import_react4.Handle, { type: "target", id: "right-target", position: import_react4.Position.Right }));
}
var MultiHandle_default = (0, import_react3.memo)(MultiHandle);
// src/components/WithMultiHandle.tsx
var import_react5 = __toESM(require("react"));
function WithMultiHandle(_a) {
var _b = _a, { children } = _b, restProps = __objRest(_b, ["children"]);
return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, children, /* @__PURE__ */ import_react5.default.createElement(MultiHandle_default, __spreadValues({}, restProps)));
}
var WithMultiHandle_default = (0, import_react5.memo)(WithMultiHandle);
// src/models/Graph.ts
var Graph = class {
constructor() {
this.nodes = [];
this.edges = [];
this.extraEdges = [];
this.nodeLookup = {};
this.edgeLookup = {};
this.extraEdgeLookup = {};
}
addNode(node) {
if (this.nodeLookup[node.id]) {
return this;
}
this.nodes.push(node);
this.nodeLookup[node.id] = node;
return this;
}
addNodes(nodes) {
nodes.forEach((node) => this.addNode(node));
return this;
}
findNode(id) {
return this.nodeLookup[id];
}
/**
* Add an edge to the graph (affects the layout)
* @param edge
*/
addEdge(edge) {
if (this.edgeLookup[edge.id]) {
return;
}
this.edges.push(edge);
this.edgeLookup[edge.id] = edge;
return this;
}
addEdges(edges) {
edges.forEach((edge) => this.addEdge(edge));
return this;
}
/**
* Add an extra edge that does not affect the layout
* @param edge edge
*/
addExtraEdge(edge) {
if (this.extraEdgeLookup[edge.id]) {
return this;
}
this.extraEdges.push(edge);
this.extraEdgeLookup[edge.id] = edge;
return this;
}
addExtraEdges(edges) {
edges.forEach((edge) => this.addExtraEdge(edge));
return this;
}
findEdge(id) {
return this.edgeLookup[id];
}
getAllEdges() {
return this.edges.concat(this.extraEdges);
}
};
// src/models/createNode.ts
var import_react6 = require("@xyflow/react");
function createNode(_a) {
var _b = _a, {
id,
data,
draggable = false,
position,
sourcePosition = import_react6.Position.Bottom,
targetPosition = import_react6.Position.Top
} = _b, rest = __objRest(_b, [
"id",
"data",
"draggable",
"position",
"sourcePosition",
"targetPosition"
]);
return __spreadValues({
id,
data,
draggable,
position: typeof position === "undefined" ? { x: 0, y: 0 } : position,
sourcePosition,
targetPosition
}, rest);
}
// src/models/createEdge.ts
function createEdge(_a) {
var _b = _a, { id, source, target } = _b, rest = __objRest(_b, ["id", "source", "target"]);
return __spreadValues({
id: id != null ? id : `${source}-${target}`,
source,
target
}, rest);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
DagreFlow,
Graph,
MultiHandle,
WithMultiHandle,
createEdge,
createNode
});