@luciole-sh/flow-graph 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +671 -2
  3. package/dist/Flow.d.ts +41 -0
  4. package/dist/Flow.d.ts.map +1 -0
  5. package/dist/Flow.js +489 -0
  6. package/dist/Flow.js.map +1 -0
  7. package/dist/components.d.ts +28 -0
  8. package/dist/components.d.ts.map +1 -0
  9. package/dist/components.js +100 -0
  10. package/dist/components.js.map +1 -0
  11. package/dist/frame.d.ts +68 -0
  12. package/dist/frame.d.ts.map +1 -0
  13. package/dist/frame.js +136 -0
  14. package/dist/frame.js.map +1 -0
  15. package/dist/geometry.d.ts +60 -0
  16. package/dist/geometry.d.ts.map +1 -0
  17. package/dist/geometry.js +205 -0
  18. package/dist/geometry.js.map +1 -0
  19. package/dist/hooks.d.ts +56 -0
  20. package/dist/hooks.d.ts.map +1 -0
  21. package/dist/hooks.js +65 -0
  22. package/dist/hooks.js.map +1 -0
  23. package/dist/index.d.ts +15 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +14 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/keymap.d.ts +11 -0
  28. package/dist/keymap.d.ts.map +1 -0
  29. package/dist/keymap.js +42 -0
  30. package/dist/keymap.js.map +1 -0
  31. package/dist/navigation.d.ts +32 -0
  32. package/dist/navigation.d.ts.map +1 -0
  33. package/dist/navigation.js +68 -0
  34. package/dist/navigation.js.map +1 -0
  35. package/dist/nodes.d.ts +18 -0
  36. package/dist/nodes.d.ts.map +1 -0
  37. package/dist/nodes.js +46 -0
  38. package/dist/nodes.js.map +1 -0
  39. package/dist/raster.d.ts +112 -0
  40. package/dist/raster.d.ts.map +1 -0
  41. package/dist/raster.js +370 -0
  42. package/dist/raster.js.map +1 -0
  43. package/dist/store.d.ts +104 -0
  44. package/dist/store.d.ts.map +1 -0
  45. package/dist/store.js +186 -0
  46. package/dist/store.js.map +1 -0
  47. package/dist/theme.d.ts +25 -0
  48. package/dist/theme.d.ts.map +1 -0
  49. package/dist/theme.js +39 -0
  50. package/dist/theme.js.map +1 -0
  51. package/dist/types.d.ts +140 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/vendor/xyflow/LICENSE +21 -0
  56. package/dist/vendor/xyflow/bezier.d.ts +26 -0
  57. package/dist/vendor/xyflow/bezier.d.ts.map +1 -0
  58. package/dist/vendor/xyflow/bezier.js +47 -0
  59. package/dist/vendor/xyflow/bezier.js.map +1 -0
  60. package/dist/vendor/xyflow/changes.d.ts +9 -0
  61. package/dist/vendor/xyflow/changes.d.ts.map +1 -0
  62. package/dist/vendor/xyflow/changes.js +133 -0
  63. package/dist/vendor/xyflow/changes.js.map +1 -0
  64. package/dist/vendor/xyflow/smoothstep.d.ts +17 -0
  65. package/dist/vendor/xyflow/smoothstep.d.ts.map +1 -0
  66. package/dist/vendor/xyflow/smoothstep.js +166 -0
  67. package/dist/vendor/xyflow/smoothstep.js.map +1 -0
  68. package/package.json +61 -4
  69. package/src/Flow.tsx +684 -0
  70. package/src/components.tsx +180 -0
  71. package/src/frame.ts +203 -0
  72. package/src/geometry.ts +274 -0
  73. package/src/hooks.tsx +121 -0
  74. package/src/index.ts +21 -0
  75. package/src/keymap.tsx +45 -0
  76. package/src/navigation.ts +86 -0
  77. package/src/nodes.tsx +86 -0
  78. package/src/raster.ts +453 -0
  79. package/src/store.ts +240 -0
  80. package/src/theme.ts +61 -0
  81. package/src/types.ts +130 -0
  82. package/src/vendor/xyflow/LICENSE +21 -0
  83. package/src/vendor/xyflow/README.md +20 -0
  84. package/src/vendor/xyflow/bezier.ts +102 -0
  85. package/src/vendor/xyflow/changes.ts +177 -0
  86. package/src/vendor/xyflow/smoothstep.ts +219 -0
  87. package/tsconfig.json +22 -0
@@ -0,0 +1,133 @@
1
+ /*
2
+ * This function applies changes to nodes or edges that are triggered by the canvas.
3
+ * When you drag a node for example, the canvas sends a position change update.
4
+ * This function then applies the changes and returns the updated elements.
5
+ */
6
+ function applyChanges(changes, elements) {
7
+ const updatedElements = [];
8
+ /*
9
+ * By storing a map of changes for each element, we can a quick lookup as we
10
+ * iterate over the elements array!
11
+ */
12
+ const changesMap = new Map();
13
+ const addItemChanges = [];
14
+ for (const change of changes) {
15
+ if (change.type === "add") {
16
+ addItemChanges.push(change);
17
+ continue;
18
+ }
19
+ else if (change.type === "remove" || change.type === "replace") {
20
+ /*
21
+ * For a 'remove' change we can safely ignore any other changes queued for
22
+ * the same element, it's going to be removed anyway!
23
+ */
24
+ changesMap.set(change.id, [change]);
25
+ }
26
+ else {
27
+ const elementChanges = changesMap.get(change.id);
28
+ if (elementChanges) {
29
+ /*
30
+ * If we have some changes queued already, we can do a mutable update of
31
+ * that array and save ourselves some copying.
32
+ */
33
+ elementChanges.push(change);
34
+ }
35
+ else {
36
+ changesMap.set(change.id, [change]);
37
+ }
38
+ }
39
+ }
40
+ for (const element of elements) {
41
+ const queued = changesMap.get(element.id);
42
+ /*
43
+ * When there are no changes for an element we can just push it unmodified,
44
+ * no need to copy it.
45
+ */
46
+ if (!queued) {
47
+ updatedElements.push(element);
48
+ continue;
49
+ }
50
+ const [first] = queued;
51
+ // If we have a 'remove' change queued, it'll be the only change in the array
52
+ if (first?.type === "remove") {
53
+ continue;
54
+ }
55
+ if (first?.type === "replace") {
56
+ updatedElements.push({ ...first.item });
57
+ continue;
58
+ }
59
+ /**
60
+ * For other types of changes, we want to start with a shallow copy of the
61
+ * object so React knows this element has changed. Sequential changes will
62
+ * each _mutate_ this object, so there's only ever one copy.
63
+ */
64
+ const updatedElement = { ...element };
65
+ for (const change of queued) {
66
+ applyChange(change, updatedElement);
67
+ }
68
+ updatedElements.push(updatedElement);
69
+ }
70
+ /*
71
+ * we need to wait for all changes to be applied before adding new items
72
+ * to be able to add them at the correct index
73
+ */
74
+ for (const change of addItemChanges) {
75
+ if (change.index !== undefined) {
76
+ updatedElements.splice(change.index, 0, { ...change.item });
77
+ }
78
+ else {
79
+ updatedElements.push({ ...change.item });
80
+ }
81
+ }
82
+ return updatedElements;
83
+ }
84
+ // A connection spread into an edge is one once it has an id: this narrows it to `E`.
85
+ function isElement(item) {
86
+ return typeof item === "object" && item !== null && "id" in item;
87
+ }
88
+ // Applies a single change to an element. This is a *mutable* update.
89
+ function applyChange(change, element) {
90
+ switch (change.type) {
91
+ case "select": {
92
+ element.selected = change.selected;
93
+ break;
94
+ }
95
+ case "position": {
96
+ if (typeof change.position !== "undefined") {
97
+ element.position = change.position;
98
+ }
99
+ if (typeof change.dragging !== "undefined") {
100
+ element.dragging = change.dragging;
101
+ }
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ /** Applies what the canvas proposes (drag, selection, removal…) to the application's nodes. */
107
+ export function applyNodeChanges(changes, nodes) {
108
+ return applyChanges(changes, nodes);
109
+ }
110
+ /** Applies what the canvas proposes to the application's edges. */
111
+ export function applyEdgeChanges(changes, edges) {
112
+ return applyChanges(changes, edges);
113
+ }
114
+ export const getEdgeId = ({ source, sourceHandle, target, targetHandle }) => `xy-edge__${source}${sourceHandle || ""}-${target}${targetHandle || ""}`;
115
+ const connectionExists = (edge, edges) => edges.some((el) => el.source === edge.source &&
116
+ el.target === edge.target &&
117
+ (el.sourceHandle === edge.sourceHandle || (!el.sourceHandle && !edge.sourceHandle)) &&
118
+ (el.targetHandle === edge.targetHandle || (!el.targetHandle && !edge.targetHandle)));
119
+ /** `edges` with a new edge for `connection`, unless the same connection exists already. */
120
+ export function addEdge(connection, edges, getId = getEdgeId) {
121
+ if (!connection.source || !connection.target)
122
+ return [...edges];
123
+ const known = "id" in connection ? connection.id : undefined;
124
+ const edge = { ...connection, id: typeof known === "string" ? known : getId(connection) };
125
+ if (connectionExists(edge, edges))
126
+ return [...edges];
127
+ if (edge.sourceHandle === null)
128
+ delete edge.sourceHandle;
129
+ if (edge.targetHandle === null)
130
+ delete edge.targetHandle;
131
+ return isElement(edge) ? [...edges, edge] : [...edges];
132
+ }
133
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../../src/vendor/xyflow/changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Position, XY } from "../../types.ts";
2
+ export type StepPoints = {
3
+ /** From the source to the target, both included; consecutive points share an axis. */
4
+ points: XY[];
5
+ labelX: number;
6
+ labelY: number;
7
+ };
8
+ export declare function getStepPoints({ source, sourcePosition, target, targetPosition, center, offset, stepPosition, }: {
9
+ source: XY;
10
+ sourcePosition?: Position;
11
+ target: XY;
12
+ targetPosition?: Position;
13
+ center?: Partial<XY>;
14
+ offset: number;
15
+ stepPosition?: number;
16
+ }): StepPoints;
17
+ //# sourceMappingURL=smoothstep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoothstep.d.ts","sourceRoot":"","sources":["../../../src/vendor/xyflow/smoothstep.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AA2BnD,MAAM,MAAM,UAAU,GAAG;IACvB,sFAAsF;IACtF,MAAM,EAAE,EAAE,EAAE,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAMF,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,cAAyB,EACzB,MAAM,EACN,cAAsB,EACtB,MAAW,EACX,MAAM,EACN,YAAmB,GACpB,EAAE;IACD,MAAM,EAAE,EAAE,CAAC;IACX,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,MAAM,EAAE,EAAE,CAAC;IACX,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,UAAU,CAiKb"}
@@ -0,0 +1,166 @@
1
+ import { getEdgeCenter } from "./bezier.js";
2
+ const HALF = 0.5;
3
+ const handleDirections = {
4
+ left: { x: -1, y: 0 },
5
+ right: { x: 1, y: 0 },
6
+ top: { x: 0, y: -1 },
7
+ bottom: { x: 0, y: 1 },
8
+ };
9
+ const getDirection = ({ source, sourcePosition, target, }) => {
10
+ if (sourcePosition === "left" || sourcePosition === "right") {
11
+ return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };
12
+ }
13
+ return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };
14
+ };
15
+ /*
16
+ * With this function we try to mimic an orthogonal edge routing behaviour
17
+ * It's not as good as a real orthogonal edge routing, but it's faster and good enough as a default for step and smooth step edges
18
+ */
19
+ export function getStepPoints({ source, sourcePosition = "bottom", target, targetPosition = "top", center = {}, offset, stepPosition = HALF, }) {
20
+ const sourceDir = handleDirections[sourcePosition];
21
+ const targetDir = handleDirections[targetPosition];
22
+ const sourceGapped = {
23
+ x: source.x + sourceDir.x * offset,
24
+ y: source.y + sourceDir.y * offset,
25
+ };
26
+ const targetGapped = {
27
+ x: target.x + targetDir.x * offset,
28
+ y: target.y + targetDir.y * offset,
29
+ };
30
+ const dir = getDirection({ source: sourceGapped, sourcePosition, target: targetGapped });
31
+ const dirAccessor = dir.x !== 0 ? "x" : "y";
32
+ const currDir = dir[dirAccessor];
33
+ let points;
34
+ let centerX;
35
+ let centerY;
36
+ const sourceGapOffset = { x: 0, y: 0 };
37
+ const targetGapOffset = { x: 0, y: 0 };
38
+ // opposite handle positions, default case
39
+ if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
40
+ if (dirAccessor === "x") {
41
+ // Primary direction is horizontal, so stepPosition affects X coordinate
42
+ centerX = center.x ?? sourceGapped.x + (targetGapped.x - sourceGapped.x) * stepPosition;
43
+ centerY = center.y ?? (sourceGapped.y + targetGapped.y) / 2;
44
+ }
45
+ else {
46
+ // Primary direction is vertical, so stepPosition affects Y coordinate
47
+ centerX = center.x ?? (sourceGapped.x + targetGapped.x) / 2;
48
+ centerY = center.y ?? sourceGapped.y + (targetGapped.y - sourceGapped.y) * stepPosition;
49
+ }
50
+ /*
51
+ * --->
52
+ * |
53
+ * >---
54
+ */
55
+ const verticalSplit = [
56
+ { x: centerX, y: sourceGapped.y },
57
+ { x: centerX, y: targetGapped.y },
58
+ ];
59
+ /*
60
+ * |
61
+ * ---
62
+ * |
63
+ */
64
+ const horizontalSplit = [
65
+ { x: sourceGapped.x, y: centerY },
66
+ { x: targetGapped.x, y: centerY },
67
+ ];
68
+ if (sourceDir[dirAccessor] === currDir) {
69
+ points = dirAccessor === "x" ? verticalSplit : horizontalSplit;
70
+ }
71
+ else {
72
+ points = dirAccessor === "x" ? horizontalSplit : verticalSplit;
73
+ }
74
+ }
75
+ else {
76
+ // sourceTarget means we take x from source and y from target, targetSource is the opposite
77
+ const sourceTarget = [{ x: sourceGapped.x, y: targetGapped.y }];
78
+ const targetSource = [{ x: targetGapped.x, y: sourceGapped.y }];
79
+ // this handles edges with same handle positions
80
+ if (dirAccessor === "x") {
81
+ points = sourceDir.x === currDir ? targetSource : sourceTarget;
82
+ }
83
+ else {
84
+ points = sourceDir.y === currDir ? sourceTarget : targetSource;
85
+ }
86
+ if (sourcePosition === targetPosition) {
87
+ const diff = Math.abs(source[dirAccessor] - target[dirAccessor]);
88
+ // if an edge goes from right to right for example (sourcePosition === targetPosition) and the distance between source.x and target.x is less than the offset, the added point and the gapped source/target will overlap. This leads to a weird edge path. To avoid this we add a gapOffset to the source/target
89
+ if (diff <= offset) {
90
+ const gapOffset = Math.min(offset - 1, offset - diff);
91
+ if (sourceDir[dirAccessor] === currDir) {
92
+ sourceGapOffset[dirAccessor] =
93
+ (sourceGapped[dirAccessor] > source[dirAccessor] ? -1 : 1) * gapOffset;
94
+ }
95
+ else {
96
+ targetGapOffset[dirAccessor] =
97
+ (targetGapped[dirAccessor] > target[dirAccessor] ? -1 : 1) * gapOffset;
98
+ }
99
+ }
100
+ }
101
+ // these are conditions for handling mixed handle positions like Right -> Bottom for example
102
+ if (sourcePosition !== targetPosition) {
103
+ const dirAccessorOpposite = dirAccessor === "x" ? "y" : "x";
104
+ const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];
105
+ const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];
106
+ const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];
107
+ const flipSourceTarget = (sourceDir[dirAccessor] === 1 &&
108
+ ((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) ||
109
+ (sourceDir[dirAccessor] !== 1 &&
110
+ ((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo)));
111
+ if (flipSourceTarget) {
112
+ points = dirAccessor === "x" ? sourceTarget : targetSource;
113
+ }
114
+ }
115
+ const sourceGapPoint = {
116
+ x: sourceGapped.x + sourceGapOffset.x,
117
+ y: sourceGapped.y + sourceGapOffset.y,
118
+ };
119
+ const targetGapPoint = {
120
+ x: targetGapped.x + targetGapOffset.x,
121
+ y: targetGapped.y + targetGapOffset.y,
122
+ };
123
+ const corner = points[0] ?? sourceGapPoint;
124
+ const maxXDistance = Math.max(Math.abs(sourceGapPoint.x - corner.x), Math.abs(targetGapPoint.x - corner.x));
125
+ const maxYDistance = Math.max(Math.abs(sourceGapPoint.y - corner.y), Math.abs(targetGapPoint.y - corner.y));
126
+ // we want to place the label on the longest segment of the edge
127
+ if (maxXDistance >= maxYDistance) {
128
+ centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;
129
+ centerY = corner.y;
130
+ }
131
+ else {
132
+ centerX = corner.x;
133
+ centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;
134
+ }
135
+ }
136
+ const gappedSource = {
137
+ x: sourceGapped.x + sourceGapOffset.x,
138
+ y: sourceGapped.y + sourceGapOffset.y,
139
+ };
140
+ const gappedTarget = {
141
+ x: targetGapped.x + targetGapOffset.x,
142
+ y: targetGapped.y + targetGapOffset.y,
143
+ };
144
+ const first = points[0] ?? gappedSource;
145
+ const last = points.at(-1) ?? gappedTarget;
146
+ // Unlike the original, the default label center (getEdgeCenter) is only a fallback.
147
+ const [defaultX, defaultY] = getEdgeCenter({
148
+ sourceX: source.x,
149
+ sourceY: source.y,
150
+ targetX: target.x,
151
+ targetY: target.y,
152
+ });
153
+ return {
154
+ points: [
155
+ source,
156
+ // we only want to add the gapped source/target if they are different from the first/last point to avoid duplicates which can cause issues with the bends
157
+ ...(gappedSource.x !== first.x || gappedSource.y !== first.y ? [gappedSource] : []),
158
+ ...points,
159
+ ...(gappedTarget.x !== last.x || gappedTarget.y !== last.y ? [gappedTarget] : []),
160
+ target,
161
+ ],
162
+ labelX: Number.isFinite(centerX) ? centerX : defaultX,
163
+ labelY: Number.isFinite(centerY) ? centerY : defaultY,
164
+ };
165
+ }
166
+ //# sourceMappingURL=smoothstep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoothstep.js","sourceRoot":"","sources":["../../../src/vendor/xyflow/smoothstep.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,63 @@
1
1
  {
2
2
  "name": "@luciole-sh/flow-graph",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "Node graphs in the terminal, after React Flow: nodes, edges drawn in box characters, minimap, keyboard first.",
6
+ "keywords": [
7
+ "tui",
8
+ "terminal",
9
+ "react-flow",
10
+ "graph",
11
+ "node-graph",
12
+ "opentui",
13
+ "react"
14
+ ],
15
+ "license": "MIT",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/sykar-f/luciole.git",
22
+ "directory": "packages/flow-graph"
23
+ },
24
+ "homepage": "https://luciole.sh",
25
+ "type": "module",
26
+ "sideEffects": false,
27
+ "exports": {
28
+ ".": {
29
+ "bun": "./src/index.ts",
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "src",
38
+ "tsconfig.json",
39
+ "README.md",
40
+ "LICENSE"
41
+ ],
42
+ "engines": {
43
+ "node": ">=20",
44
+ "bun": ">=1.3"
45
+ },
46
+ "scripts": {
47
+ "build": "bun scripts/build.ts",
48
+ "prepack": "bun scripts/build.ts"
49
+ },
50
+ "peerDependencies": {
51
+ "@opentui/core": "^0.5.12",
52
+ "@opentui/keymap": "^0.5.12",
53
+ "@opentui/react": "^0.5.12",
54
+ "react": "^19.2.0"
55
+ },
56
+ "devDependencies": {
57
+ "@opentui/core": "0.5.12",
58
+ "@opentui/keymap": "0.5.12",
59
+ "@opentui/react": "0.5.12",
60
+ "react": "19.3.0",
61
+ "@types/react": "19.3.0"
62
+ }
63
+ }