@barefootjs/xyflow 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.
- package/README.md +117 -0
- package/dist/classes.d.ts +31 -0
- package/dist/classes.d.ts.map +1 -0
- package/dist/compat.d.ts +67 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/connection.d.ts +20 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/edge-path.d.ts +14 -0
- package/dist/edge-path.d.ts.map +1 -0
- package/dist/flow-subsystems.d.ts +28 -0
- package/dist/flow-subsystems.d.ts.map +1 -0
- package/dist/hooks.d.ts +34 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6572 -0
- package/dist/node-resizer.d.ts +52 -0
- package/dist/node-resizer.d.ts.map +1 -0
- package/dist/node-type-dispatch.d.ts +34 -0
- package/dist/node-type-dispatch.d.ts.map +1 -0
- package/dist/selection.d.ts +32 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/store.d.ts +8 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/types.d.ts +214 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/xyflow.browser.min.js +95 -0
- package/dist/xyflow.browser.min.js.map +129 -0
- package/package.json +58 -0
- package/src/__tests__/clamp-drag-position.test.ts +111 -0
- package/src/__tests__/compat.test.ts +157 -0
- package/src/__tests__/host-element-store.test.ts +33 -0
- package/src/__tests__/jsx-smoke.test.ts +33 -0
- package/src/__tests__/jsx-smoke.tsx +23 -0
- package/src/__tests__/node-type-dispatch.test.ts +104 -0
- package/src/__tests__/store.test.ts +399 -0
- package/src/__tests__/tsconfig.json +23 -0
- package/src/classes.ts +41 -0
- package/src/compat.ts +237 -0
- package/src/connection.ts +459 -0
- package/src/constants.ts +8 -0
- package/src/context.ts +8 -0
- package/src/edge-path.ts +89 -0
- package/src/flow-subsystems.ts +506 -0
- package/src/hooks.ts +72 -0
- package/src/index.ts +134 -0
- package/src/node-resizer.ts +276 -0
- package/src/node-type-dispatch.ts +46 -0
- package/src/selection.ts +407 -0
- package/src/store.ts +526 -0
- package/src/types.ts +329 -0
- package/src/utils.ts +13 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NodeBase,
|
|
3
|
+
EdgeBase,
|
|
4
|
+
InternalNodeBase,
|
|
5
|
+
Viewport,
|
|
6
|
+
NodeLookup,
|
|
7
|
+
ParentLookup,
|
|
8
|
+
EdgeLookup,
|
|
9
|
+
ConnectionLookup,
|
|
10
|
+
CoordinateExtent,
|
|
11
|
+
SnapGrid,
|
|
12
|
+
NodeOrigin,
|
|
13
|
+
Transform,
|
|
14
|
+
PanZoomInstance,
|
|
15
|
+
XYPosition,
|
|
16
|
+
FitViewOptionsBase,
|
|
17
|
+
OnConnect,
|
|
18
|
+
OnConnectStart,
|
|
19
|
+
OnConnectEnd,
|
|
20
|
+
IsValidConnection,
|
|
21
|
+
NodeDragItem,
|
|
22
|
+
ConnectionMode,
|
|
23
|
+
Connection,
|
|
24
|
+
} from '@xyflow/system'
|
|
25
|
+
import type { Signal, Memo } from '@barefootjs/client'
|
|
26
|
+
import type { ComponentDef } from '@barefootjs/client/runtime'
|
|
27
|
+
|
|
28
|
+
export type FitViewOptions = FitViewOptionsBase
|
|
29
|
+
|
|
30
|
+
export type {
|
|
31
|
+
NodeBase,
|
|
32
|
+
EdgeBase,
|
|
33
|
+
InternalNodeBase,
|
|
34
|
+
Viewport,
|
|
35
|
+
NodeLookup,
|
|
36
|
+
ParentLookup,
|
|
37
|
+
EdgeLookup,
|
|
38
|
+
ConnectionLookup,
|
|
39
|
+
CoordinateExtent,
|
|
40
|
+
SnapGrid,
|
|
41
|
+
NodeOrigin,
|
|
42
|
+
Transform,
|
|
43
|
+
PanZoomInstance,
|
|
44
|
+
XYPosition,
|
|
45
|
+
OnConnect,
|
|
46
|
+
OnConnectStart,
|
|
47
|
+
OnConnectEnd,
|
|
48
|
+
IsValidConnection,
|
|
49
|
+
NodeDragItem,
|
|
50
|
+
ConnectionMode,
|
|
51
|
+
Connection,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Callback fired when an edge is reconnected to a new handle.
|
|
56
|
+
*/
|
|
57
|
+
export type OnReconnect<EdgeType extends EdgeBase = EdgeBase> = (
|
|
58
|
+
oldEdge: EdgeType,
|
|
59
|
+
newConnection: Connection,
|
|
60
|
+
) => void
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Options for creating a flow store.
|
|
64
|
+
*/
|
|
65
|
+
export type FlowStoreOptions<
|
|
66
|
+
NodeType extends NodeBase = NodeBase,
|
|
67
|
+
EdgeType extends EdgeBase = EdgeBase,
|
|
68
|
+
> = {
|
|
69
|
+
nodes?: NodeType[]
|
|
70
|
+
edges?: EdgeType[]
|
|
71
|
+
defaultViewport?: Viewport
|
|
72
|
+
minZoom?: number
|
|
73
|
+
maxZoom?: number
|
|
74
|
+
nodeOrigin?: NodeOrigin
|
|
75
|
+
nodeExtent?: CoordinateExtent
|
|
76
|
+
snapToGrid?: boolean
|
|
77
|
+
snapGrid?: SnapGrid
|
|
78
|
+
fitView?: boolean
|
|
79
|
+
fitViewOptions?: FitViewOptions
|
|
80
|
+
|
|
81
|
+
// Custom component types
|
|
82
|
+
nodeTypes?: Record<string, ComponentDef | ((props: NodeComponentProps<NodeType>) => void)>
|
|
83
|
+
edgeTypes?: Record<string, ComponentDef | ((props: EdgeComponentProps<EdgeType>) => void)>
|
|
84
|
+
|
|
85
|
+
// Edge reconnection
|
|
86
|
+
edgesReconnectable?: boolean
|
|
87
|
+
onReconnect?: OnReconnect<EdgeType>
|
|
88
|
+
|
|
89
|
+
// Connection callbacks
|
|
90
|
+
onConnect?: OnConnect
|
|
91
|
+
onConnectStart?: OnConnectStart
|
|
92
|
+
onConnectEnd?: OnConnectEnd
|
|
93
|
+
isValidConnection?: IsValidConnection
|
|
94
|
+
|
|
95
|
+
// Lifecycle callbacks
|
|
96
|
+
onInit?: (store: FlowStore<NodeType, EdgeType>) => void
|
|
97
|
+
onNodeDragStart?: (event: MouseEvent, node: NodeType, nodes: NodeType[]) => void
|
|
98
|
+
onNodeDragStop?: (event: MouseEvent, node: NodeType, nodes: NodeType[]) => void
|
|
99
|
+
onMoveEnd?: (event: MouseEvent | TouchEvent | null, viewport: Viewport) => void
|
|
100
|
+
onPaneClick?: (event: MouseEvent) => void
|
|
101
|
+
onPaneMouseMove?: (event: MouseEvent) => void
|
|
102
|
+
onNodesDelete?: (nodes: NodeType[]) => void
|
|
103
|
+
onEdgesDelete?: (edges: EdgeType[]) => void
|
|
104
|
+
|
|
105
|
+
// Interactivity config
|
|
106
|
+
panOnDrag?: boolean
|
|
107
|
+
panOnScroll?: boolean
|
|
108
|
+
zoomOnScroll?: boolean
|
|
109
|
+
zoomOnDoubleClick?: boolean
|
|
110
|
+
zoomActivationKeyCode?: string | null
|
|
111
|
+
nodesDraggable?: boolean
|
|
112
|
+
nodesConnectable?: boolean
|
|
113
|
+
elementsSelectable?: boolean
|
|
114
|
+
deleteKeyCode?: string[] | null
|
|
115
|
+
selectionKeyCode?: string | null
|
|
116
|
+
connectionLineStyle?: Record<string, string>
|
|
117
|
+
defaultEdgeOptions?: Partial<EdgeBase>
|
|
118
|
+
elevateNodesOnSelect?: boolean
|
|
119
|
+
reconnectRadius?: number
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The reactive flow store — all state exposed as signal getters.
|
|
124
|
+
*/
|
|
125
|
+
export type FlowStore<
|
|
126
|
+
NodeType extends NodeBase = NodeBase,
|
|
127
|
+
EdgeType extends EdgeBase = EdgeBase,
|
|
128
|
+
> = {
|
|
129
|
+
// Reactive state (signal getters)
|
|
130
|
+
nodes: Signal<NodeType[]>[0]
|
|
131
|
+
edges: Signal<EdgeType[]>[0]
|
|
132
|
+
viewport: Signal<Viewport>[0]
|
|
133
|
+
width: Signal<number>[0]
|
|
134
|
+
height: Signal<number>[0]
|
|
135
|
+
dragging: Signal<boolean>[0]
|
|
136
|
+
nodesInitialized: Memo<boolean>
|
|
137
|
+
|
|
138
|
+
// Lookups (signal getters)
|
|
139
|
+
nodeLookup: Signal<NodeLookup<InternalNodeBase<NodeType>>>[0]
|
|
140
|
+
parentLookup: Signal<ParentLookup<InternalNodeBase<NodeType>>>[0]
|
|
141
|
+
edgeLookup: Signal<EdgeLookup<EdgeType>>[0]
|
|
142
|
+
connectionLookup: Signal<ConnectionLookup>[0]
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Fine-grained per-node subscription. Returns the current internal
|
|
146
|
+
* entry for the given id, and tracks it for reactivity — the
|
|
147
|
+
* surrounding effect / memo will re-run only when **this** node's
|
|
148
|
+
* entry changes (data, selected, position via setNodes, or in-place
|
|
149
|
+
* drag updates), not on changes to sibling nodes.
|
|
150
|
+
*
|
|
151
|
+
* Use this in per-node consumers (data / selected / position
|
|
152
|
+
* observers). For iteration-style consumers that walk all nodes,
|
|
153
|
+
* keep using `nodeLookup()`.
|
|
154
|
+
*/
|
|
155
|
+
nodeSignal: (id: string) => InternalNodeBase<NodeType> | undefined
|
|
156
|
+
|
|
157
|
+
// Lightweight position change counter — subscribers re-run without
|
|
158
|
+
// triggering the full adoptUserNodes pipeline.
|
|
159
|
+
positionEpoch: Signal<number>[0]
|
|
160
|
+
triggerPositionUpdate: () => void
|
|
161
|
+
|
|
162
|
+
// Internal refs
|
|
163
|
+
panZoom: Signal<PanZoomInstance | null>[0]
|
|
164
|
+
domNode: Signal<HTMLElement | null>[0]
|
|
165
|
+
|
|
166
|
+
// Setters
|
|
167
|
+
setNodes: Signal<NodeType[]>[1]
|
|
168
|
+
setEdges: Signal<EdgeType[]>[1]
|
|
169
|
+
setViewport: Signal<Viewport>[1]
|
|
170
|
+
setWidth: Signal<number>[1]
|
|
171
|
+
setHeight: Signal<number>[1]
|
|
172
|
+
|
|
173
|
+
// Selection state
|
|
174
|
+
multiSelectionActive: Signal<boolean>[0]
|
|
175
|
+
|
|
176
|
+
// Interactivity — when false, nodes cannot be dragged/connected/deleted
|
|
177
|
+
nodesDraggable: Signal<boolean>[0]
|
|
178
|
+
setNodesDraggable: Signal<boolean>[1]
|
|
179
|
+
|
|
180
|
+
// Actions
|
|
181
|
+
fitView: (options?: FitViewOptions) => void
|
|
182
|
+
updateNodePositions: (
|
|
183
|
+
dragItems: Map<string, NodeDragItem | InternalNodeBase<NodeType>>,
|
|
184
|
+
dragging?: boolean,
|
|
185
|
+
) => void
|
|
186
|
+
unselectNodesAndEdges: (params?: {
|
|
187
|
+
nodes?: NodeType[]
|
|
188
|
+
edges?: EdgeType[]
|
|
189
|
+
}) => void
|
|
190
|
+
panByDelta: (delta: XYPosition) => Promise<boolean>
|
|
191
|
+
addEdge: (edge: EdgeType) => void
|
|
192
|
+
deleteElements: (params: {
|
|
193
|
+
nodes?: NodeType[]
|
|
194
|
+
edges?: EdgeType[]
|
|
195
|
+
}) => void
|
|
196
|
+
|
|
197
|
+
// Configuration
|
|
198
|
+
minZoom: number
|
|
199
|
+
maxZoom: number
|
|
200
|
+
nodeOrigin: NodeOrigin
|
|
201
|
+
nodeExtent: CoordinateExtent
|
|
202
|
+
snapToGrid: boolean
|
|
203
|
+
snapGrid: SnapGrid
|
|
204
|
+
|
|
205
|
+
// Viewport transform as [tx, ty, scale]
|
|
206
|
+
getTransform: () => Transform
|
|
207
|
+
|
|
208
|
+
// Custom component types
|
|
209
|
+
nodeTypes?: Record<string, ComponentDef | ((props: NodeComponentProps<NodeType>) => void)>
|
|
210
|
+
edgeTypes?: Record<string, ComponentDef | ((props: EdgeComponentProps<EdgeType>) => void)>
|
|
211
|
+
|
|
212
|
+
// Edge reconnection
|
|
213
|
+
edgesReconnectable: boolean
|
|
214
|
+
onReconnect?: OnReconnect<EdgeType>
|
|
215
|
+
|
|
216
|
+
// Connection callbacks
|
|
217
|
+
onConnect?: OnConnect
|
|
218
|
+
onConnectStart?: OnConnectStart
|
|
219
|
+
onConnectEnd?: OnConnectEnd
|
|
220
|
+
isValidConnection?: IsValidConnection
|
|
221
|
+
|
|
222
|
+
// Lifecycle callbacks
|
|
223
|
+
onInit?: (store: FlowStore<NodeType, EdgeType>) => void
|
|
224
|
+
onNodeDragStart?: (event: MouseEvent, node: NodeType, nodes: NodeType[]) => void
|
|
225
|
+
onNodeDragStop?: (event: MouseEvent, node: NodeType, nodes: NodeType[]) => void
|
|
226
|
+
onMoveEnd?: (event: MouseEvent | TouchEvent | null, viewport: Viewport) => void
|
|
227
|
+
onPaneClick?: (event: MouseEvent) => void
|
|
228
|
+
onPaneMouseMove?: (event: MouseEvent) => void
|
|
229
|
+
onNodesDelete?: (nodes: NodeType[]) => void
|
|
230
|
+
onEdgesDelete?: (edges: EdgeType[]) => void
|
|
231
|
+
|
|
232
|
+
// Interactivity (reactive signals)
|
|
233
|
+
nodesConnectable: Signal<boolean>[0]
|
|
234
|
+
setNodesConnectable: Signal<boolean>[1]
|
|
235
|
+
elementsSelectable: Signal<boolean>[0]
|
|
236
|
+
setElementsSelectable: Signal<boolean>[1]
|
|
237
|
+
panOnDrag: Signal<boolean>[0]
|
|
238
|
+
setPanOnDrag: Signal<boolean>[1]
|
|
239
|
+
panOnScroll: Signal<boolean>[0]
|
|
240
|
+
setPanOnScroll: Signal<boolean>[1]
|
|
241
|
+
zoomOnScroll: Signal<boolean>[0]
|
|
242
|
+
setZoomOnScroll: Signal<boolean>[1]
|
|
243
|
+
|
|
244
|
+
// Static config
|
|
245
|
+
deleteKeyCode: string[] | null
|
|
246
|
+
selectionKeyCode: string | null
|
|
247
|
+
connectionLineStyle?: Record<string, string>
|
|
248
|
+
defaultEdgeOptions?: Partial<EdgeBase>
|
|
249
|
+
elevateNodesOnSelect: boolean
|
|
250
|
+
reconnectRadius: number
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Internal setters exposed by createFlowStore but not part of the public API.
|
|
255
|
+
* Used only by initFlow during initialization.
|
|
256
|
+
*/
|
|
257
|
+
export type InternalFlowStore<
|
|
258
|
+
NodeType extends NodeBase = NodeBase,
|
|
259
|
+
EdgeType extends EdgeBase = EdgeBase,
|
|
260
|
+
> = FlowStore<NodeType, EdgeType> & {
|
|
261
|
+
setDragging: Signal<boolean>[1]
|
|
262
|
+
setPanZoom: Signal<PanZoomInstance | null>[1]
|
|
263
|
+
setDomNode: Signal<HTMLElement | null>[1]
|
|
264
|
+
setMultiSelectionActive: Signal<boolean>[1]
|
|
265
|
+
updatePanZoomConfig: () => void
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Props passed to custom node components.
|
|
270
|
+
*/
|
|
271
|
+
export type NodeComponentProps<NodeType extends NodeBase = NodeBase> = {
|
|
272
|
+
id: string
|
|
273
|
+
data: NodeType['data']
|
|
274
|
+
type: string
|
|
275
|
+
/**
|
|
276
|
+
* Reactive getter for this node's selected state. Call inside a
|
|
277
|
+
* createEffect to observe selection changes at runtime — reading it once
|
|
278
|
+
* at mount time only yields the initial value.
|
|
279
|
+
*/
|
|
280
|
+
selected: () => boolean
|
|
281
|
+
dragging: boolean
|
|
282
|
+
positionAbsoluteX: number
|
|
283
|
+
positionAbsoluteY: number
|
|
284
|
+
width?: number
|
|
285
|
+
height?: number
|
|
286
|
+
isConnectable: boolean
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Props passed to custom edge components.
|
|
291
|
+
*/
|
|
292
|
+
export type EdgeComponentProps<EdgeType extends EdgeBase = EdgeBase> = {
|
|
293
|
+
id: string
|
|
294
|
+
source: string
|
|
295
|
+
target: string
|
|
296
|
+
sourceX: number
|
|
297
|
+
sourceY: number
|
|
298
|
+
targetX: number
|
|
299
|
+
targetY: number
|
|
300
|
+
sourcePosition: string
|
|
301
|
+
targetPosition: string
|
|
302
|
+
data: EdgeType['data']
|
|
303
|
+
selected: boolean
|
|
304
|
+
animated: boolean
|
|
305
|
+
label?: string
|
|
306
|
+
/** SVG group element to render custom edge content into */
|
|
307
|
+
svgGroup: SVGGElement
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Selection mode for rectangle selection.
|
|
312
|
+
* - 'partial': selects nodes that partially overlap the rectangle (default)
|
|
313
|
+
* - 'full': only selects nodes fully contained in the rectangle
|
|
314
|
+
*/
|
|
315
|
+
export type SelectionMode = 'partial' | 'full'
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Props for the Flow init function.
|
|
319
|
+
*/
|
|
320
|
+
export type FlowProps<
|
|
321
|
+
NodeType extends NodeBase = NodeBase,
|
|
322
|
+
EdgeType extends EdgeBase = EdgeBase,
|
|
323
|
+
> = FlowStoreOptions<NodeType, EdgeType> & {
|
|
324
|
+
class?: string
|
|
325
|
+
/** When true, dragging on empty pane starts selection without Shift key */
|
|
326
|
+
selectionOnDrag?: boolean
|
|
327
|
+
/** Selection mode: 'partial' (default) or 'full' */
|
|
328
|
+
selectionMode?: SelectionMode
|
|
329
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply position styling to an absolutely-positioned container element.
|
|
3
|
+
* Parses a position string like 'top-left' or 'bottom-right'.
|
|
4
|
+
*/
|
|
5
|
+
export function applyPositionStyle(
|
|
6
|
+
el: HTMLElement,
|
|
7
|
+
position: string,
|
|
8
|
+
offset = '10px',
|
|
9
|
+
): void {
|
|
10
|
+
const [vertical, horizontal] = position.split('-')
|
|
11
|
+
el.style[vertical as 'top' | 'bottom'] = offset
|
|
12
|
+
el.style[horizontal as 'left' | 'right'] = offset
|
|
13
|
+
}
|