@pyreon/flow 0.5.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types.ts","../../src/components/background.tsx","../../src/components/controls.tsx","../../src/components/flow-component.tsx","../../src/components/handle.tsx","../../src/components/minimap.tsx","../../src/components/node-resizer.tsx","../../src/components/node-toolbar.tsx","../../src/components/panel.tsx","../../src/edges.ts","../../src/flow.ts","../../src/layout.ts","../../src/styles.ts"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@pyreon/flow",
3
+ "version": "0.5.0",
4
+ "description": "Reactive flow diagrams for Pyreon — signal-native nodes, edges, pan/zoom, auto-layout",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/pyreon/fundamentals.git",
9
+ "directory": "packages/flow"
10
+ },
11
+ "homepage": "https://github.com/pyreon/fundamentals/tree/main/packages/flow#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/pyreon/fundamentals/issues"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "files": [
19
+ "lib",
20
+ "src",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "type": "module",
25
+ "main": "./lib/index.js",
26
+ "module": "./lib/index.js",
27
+ "types": "./lib/types/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "bun": "./src/index.ts",
31
+ "import": "./lib/index.js",
32
+ "types": "./lib/types/index.d.ts"
33
+ }
34
+ },
35
+ "sideEffects": false,
36
+ "scripts": {
37
+ "build": "vl_rolldown_build",
38
+ "dev": "vl_rolldown_build-watch",
39
+ "test": "vitest run",
40
+ "typecheck": "tsc --noEmit"
41
+ },
42
+ "dependencies": {
43
+ "elkjs": "^0.9.3"
44
+ },
45
+ "peerDependencies": {
46
+ "@pyreon/core": ">=0.5.0 <1.0.0",
47
+ "@pyreon/reactivity": ">=0.5.0 <1.0.0"
48
+ },
49
+ "devDependencies": {
50
+ "@happy-dom/global-registrator": "^20.8.3",
51
+ "@pyreon/core": ">=0.5.0 <1.0.0",
52
+ "@pyreon/reactivity": ">=0.5.0 <1.0.0",
53
+ "@vitus-labs/tools-lint": "^1.11.0"
54
+ }
55
+ }
@@ -0,0 +1,128 @@
1
+ import type { VNodeChild } from '@pyreon/core'
2
+ import type { BackgroundProps } from '../types'
3
+
4
+ /**
5
+ * Background pattern for the flow canvas.
6
+ * Renders dots, lines, or cross patterns that move with the viewport.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * <Flow instance={flow}>
11
+ * <Background variant="dots" gap={20} />
12
+ * </Flow>
13
+ * ```
14
+ */
15
+ export function Background(props: BackgroundProps): VNodeChild {
16
+ const { variant = 'dots', gap = 20, size = 1, color = '#ddd' } = props
17
+
18
+ const patternId = `flow-bg-${variant}`
19
+
20
+ if (variant === 'dots') {
21
+ return (
22
+ <svg
23
+ role="img"
24
+ aria-label="background pattern"
25
+ class="pyreon-flow-background"
26
+ style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;"
27
+ >
28
+ <defs>
29
+ <pattern
30
+ id={patternId}
31
+ x="0"
32
+ y="0"
33
+ width={String(gap)}
34
+ height={String(gap)}
35
+ patternUnits="userSpaceOnUse"
36
+ >
37
+ <circle
38
+ cx={String(size)}
39
+ cy={String(size)}
40
+ r={String(size)}
41
+ fill={color}
42
+ />
43
+ </pattern>
44
+ </defs>
45
+ <rect width="100%" height="100%" fill={`url(#${patternId})`} />
46
+ </svg>
47
+ )
48
+ }
49
+
50
+ if (variant === 'lines') {
51
+ return (
52
+ <svg
53
+ role="img"
54
+ aria-label="background pattern"
55
+ class="pyreon-flow-background"
56
+ style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;"
57
+ >
58
+ <defs>
59
+ <pattern
60
+ id={patternId}
61
+ x="0"
62
+ y="0"
63
+ width={String(gap)}
64
+ height={String(gap)}
65
+ patternUnits="userSpaceOnUse"
66
+ >
67
+ <line
68
+ x1="0"
69
+ y1={String(gap)}
70
+ x2={String(gap)}
71
+ y2={String(gap)}
72
+ stroke={color}
73
+ stroke-width={String(size)}
74
+ />
75
+ <line
76
+ x1={String(gap)}
77
+ y1="0"
78
+ x2={String(gap)}
79
+ y2={String(gap)}
80
+ stroke={color}
81
+ stroke-width={String(size)}
82
+ />
83
+ </pattern>
84
+ </defs>
85
+ <rect width="100%" height="100%" fill={`url(#${patternId})`} />
86
+ </svg>
87
+ )
88
+ }
89
+
90
+ // cross
91
+ return (
92
+ <svg
93
+ role="img"
94
+ aria-label="background pattern"
95
+ class="pyreon-flow-background"
96
+ style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;"
97
+ >
98
+ <defs>
99
+ <pattern
100
+ id={patternId}
101
+ x="0"
102
+ y="0"
103
+ width={String(gap)}
104
+ height={String(gap)}
105
+ patternUnits="userSpaceOnUse"
106
+ >
107
+ <line
108
+ x1={String(gap / 2 - size * 2)}
109
+ y1={String(gap / 2)}
110
+ x2={String(gap / 2 + size * 2)}
111
+ y2={String(gap / 2)}
112
+ stroke={color}
113
+ stroke-width={String(size)}
114
+ />
115
+ <line
116
+ x1={String(gap / 2)}
117
+ y1={String(gap / 2 - size * 2)}
118
+ x2={String(gap / 2)}
119
+ y2={String(gap / 2 + size * 2)}
120
+ stroke={color}
121
+ stroke-width={String(size)}
122
+ />
123
+ </pattern>
124
+ </defs>
125
+ <rect width="100%" height="100%" fill={`url(#${patternId})`} />
126
+ </svg>
127
+ )
128
+ }
@@ -0,0 +1,158 @@
1
+ import type { VNodeChild } from '@pyreon/core'
2
+ import type { ControlsProps, FlowInstance } from '../types'
3
+
4
+ const positionStyles: Record<string, string> = {
5
+ 'top-left': 'top: 10px; left: 10px;',
6
+ 'top-right': 'top: 10px; right: 10px;',
7
+ 'bottom-left': 'bottom: 10px; left: 10px;',
8
+ 'bottom-right': 'bottom: 10px; right: 10px;',
9
+ }
10
+
11
+ // Simple SVG icons
12
+ const ZoomInIcon = () => (
13
+ <svg
14
+ width="16"
15
+ height="16"
16
+ viewBox="0 0 16 16"
17
+ fill="none"
18
+ stroke="currentColor"
19
+ stroke-width="1.5"
20
+ >
21
+ <circle cx="7" cy="7" r="5" />
22
+ <line x1="7" y1="5" x2="7" y2="9" />
23
+ <line x1="5" y1="7" x2="9" y2="7" />
24
+ <line x1="11" y1="11" x2="14" y2="14" />
25
+ </svg>
26
+ )
27
+
28
+ const ZoomOutIcon = () => (
29
+ <svg
30
+ width="16"
31
+ height="16"
32
+ viewBox="0 0 16 16"
33
+ fill="none"
34
+ stroke="currentColor"
35
+ stroke-width="1.5"
36
+ >
37
+ <circle cx="7" cy="7" r="5" />
38
+ <line x1="5" y1="7" x2="9" y2="7" />
39
+ <line x1="11" y1="11" x2="14" y2="14" />
40
+ </svg>
41
+ )
42
+
43
+ const FitViewIcon = () => (
44
+ <svg
45
+ width="16"
46
+ height="16"
47
+ viewBox="0 0 16 16"
48
+ fill="none"
49
+ stroke="currentColor"
50
+ stroke-width="1.5"
51
+ >
52
+ <rect x="2" y="2" width="12" height="12" rx="2" />
53
+ <line x1="2" y1="6" x2="14" y2="6" />
54
+ <line x1="6" y1="2" x2="6" y2="14" />
55
+ </svg>
56
+ )
57
+
58
+ const LockIcon = () => (
59
+ <svg
60
+ width="16"
61
+ height="16"
62
+ viewBox="0 0 16 16"
63
+ fill="none"
64
+ stroke="currentColor"
65
+ stroke-width="1.5"
66
+ >
67
+ <rect x="3" y="7" width="10" height="7" rx="1" />
68
+ <path d="M5 7V5a3 3 0 0 1 6 0v2" />
69
+ </svg>
70
+ )
71
+
72
+ /**
73
+ * Zoom and viewport controls for the flow canvas.
74
+ * Shows zoom in, zoom out, fit view, and optional lock button.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * <Flow instance={flow}>
79
+ * <Controls />
80
+ * </Flow>
81
+ * ```
82
+ */
83
+ export function Controls(
84
+ props: ControlsProps & { instance?: FlowInstance },
85
+ ): VNodeChild {
86
+ const {
87
+ showZoomIn = true,
88
+ showZoomOut = true,
89
+ showFitView = true,
90
+ showLock = false,
91
+ position = 'bottom-left',
92
+ instance,
93
+ } = props
94
+
95
+ if (!instance) return null
96
+
97
+ const baseStyle = `position: absolute; ${positionStyles[position] ?? positionStyles['bottom-left']} display: flex; flex-direction: column; gap: 2px; z-index: 5; background: white; border: 1px solid #ddd; border-radius: 6px; padding: 2px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);`
98
+ const btnStyle =
99
+ 'width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: 4px; cursor: pointer; color: #555; padding: 0;'
100
+
101
+ return () => {
102
+ const zoomPercent = Math.round(instance.zoom() * 100)
103
+
104
+ return (
105
+ <div class="pyreon-flow-controls" style={baseStyle}>
106
+ {showZoomIn && (
107
+ <button
108
+ type="button"
109
+ style={btnStyle}
110
+ title="Zoom in"
111
+ onClick={() => instance.zoomIn()}
112
+ >
113
+ <ZoomInIcon />
114
+ </button>
115
+ )}
116
+ {showZoomOut && (
117
+ <button
118
+ type="button"
119
+ style={btnStyle}
120
+ title="Zoom out"
121
+ onClick={() => instance.zoomOut()}
122
+ >
123
+ <ZoomOutIcon />
124
+ </button>
125
+ )}
126
+ {showFitView && (
127
+ <button
128
+ type="button"
129
+ style={btnStyle}
130
+ title="Fit view"
131
+ onClick={() => instance.fitView()}
132
+ >
133
+ <FitViewIcon />
134
+ </button>
135
+ )}
136
+ {showLock && (
137
+ <button
138
+ type="button"
139
+ style={btnStyle}
140
+ title="Lock/unlock"
141
+ onClick={() => {
142
+ // Toggle pan/zoom by updating config
143
+ // This is a simple toggle — could be improved with state
144
+ }}
145
+ >
146
+ <LockIcon />
147
+ </button>
148
+ )}
149
+ <div
150
+ style="font-size: 10px; text-align: center; color: #999; padding: 2px 0; user-select: none;"
151
+ title="Current zoom level"
152
+ >
153
+ {zoomPercent}%
154
+ </div>
155
+ </div>
156
+ )
157
+ }
158
+ }