@kolosal-ai/rivet 0.1.0 → 0.1.1
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/dist/index.d.ts +20 -1
- package/dist/index.js +40 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -201,6 +201,25 @@ declare const DEFAULT_ALIGNMENT_HYSTERESIS = 1.2;
|
|
|
201
201
|
* absorbs).
|
|
202
202
|
*/
|
|
203
203
|
declare function resolveFacingSide(node: Rect, peer: Rect, previous?: HandlePosition, hysteresis?: number): HandlePosition;
|
|
204
|
+
/**
|
|
205
|
+
* {@link resolveFacingSide} restricted to the sides an end can actually reach.
|
|
206
|
+
*
|
|
207
|
+
* A node only offers connection points where its handles are. Letting an auto
|
|
208
|
+
* or live-aligned end resolve freely puts the edge on a bare side — a
|
|
209
|
+
* left/right node gets its edge stuck to the top midpoint, where the consumer
|
|
210
|
+
* put nothing. Passing the sides that carry a compatible handle keeps the edge
|
|
211
|
+
* on a real connection point.
|
|
212
|
+
*
|
|
213
|
+
* An empty `allowed` means "unconstrained" — a node with no registered handles
|
|
214
|
+
* attaches at side midpoints, so every side is equally valid, and anchors place
|
|
215
|
+
* themselves along whichever side faces the peer.
|
|
216
|
+
*
|
|
217
|
+
* When the freely-resolved side isn't reachable, a still-reachable `previous`
|
|
218
|
+
* wins over re-picking: with the peer straight above a left/right node the raw
|
|
219
|
+
* choice hangs on the sign of a near-zero `dx`, which would flicker frame to
|
|
220
|
+
* frame.
|
|
221
|
+
*/
|
|
222
|
+
declare function resolveFacingSideAmong(node: Rect, peer: Rect, allowed: readonly HandlePosition[], previous?: HandlePosition, hysteresis?: number): HandlePosition;
|
|
204
223
|
|
|
205
224
|
/** Resolved graph context for a pane right-click, passed to `onPaneContextMenu`. */
|
|
206
225
|
type PaneContextMenuContext = {
|
|
@@ -1009,4 +1028,4 @@ declare function rectsIntersect(a: Rect, b: Rect): boolean;
|
|
|
1009
1028
|
|
|
1010
1029
|
declare const VERSION = "0.0.0";
|
|
1011
1030
|
|
|
1012
|
-
export { AlignmentGuide, BUILTIN_EDGE_TYPES, BUILTIN_NODE_TYPES, Canvas2DEdgeRenderer, type CloneOptions, type ClonedElements, Connection, Controls, type ControlsProps, DEFAULT_ALIGNMENT_HYSTERESIS, DefaultEdgeOptions, DefaultNode, type EdgeAlignment, EdgeChange, EdgeDrawExtras, EdgeEnd, type EdgeEndpoint, EdgeId, EdgePathFn, EdgeRenderer, EdgeRendererFactory, EdgeRendererOptions, EdgeTypes, GroupNode, Handle, HandlePosition, type HandleProps, HandleRecord, HandleType, MiniMap, type MiniMapProps, NodeChange, NodeId, NodeProps, NodeResizer, type NodeResizerProps, NodeTypes, type PaneContextMenuContext, PendingConnection, ReconnectDelegate, Rect, Rivet, RivetControls, RivetEdge, type RivetInstance, RivetNode, type RivetProps, RivetSelection, RivetSnapshot, type RivetStore, Size, VERSION, Vec2, Viewport, alignRect, applyEdgeChanges, applyNodeChanges, boundingRect, canvas2DEdgeRenderer, clampChildToParent, cloneElements, createRivetStore, edgeEndpointHandle, facingSide, getBezierPath, getSmoothStepPath, getStepPath, getStraightPath, handleKey, parseEdgeEndpoint, parseSideHandleId, rectsIntersect, resolveFacingSide, screenToWorld, serializeGraph, snapToGrid, useRivet, useRivetContext, useRivetControls, useRivetFocusedNode, useRivetHistory, useRivetViewport, viewportToCss, visibleWorldRect, worldToScreen, zoomAt };
|
|
1031
|
+
export { AlignmentGuide, BUILTIN_EDGE_TYPES, BUILTIN_NODE_TYPES, Canvas2DEdgeRenderer, type CloneOptions, type ClonedElements, Connection, Controls, type ControlsProps, DEFAULT_ALIGNMENT_HYSTERESIS, DefaultEdgeOptions, DefaultNode, type EdgeAlignment, EdgeChange, EdgeDrawExtras, EdgeEnd, type EdgeEndpoint, EdgeId, EdgePathFn, EdgeRenderer, EdgeRendererFactory, EdgeRendererOptions, EdgeTypes, GroupNode, Handle, HandlePosition, type HandleProps, HandleRecord, HandleType, MiniMap, type MiniMapProps, NodeChange, NodeId, NodeProps, NodeResizer, type NodeResizerProps, NodeTypes, type PaneContextMenuContext, PendingConnection, ReconnectDelegate, Rect, Rivet, RivetControls, RivetEdge, type RivetInstance, RivetNode, type RivetProps, RivetSelection, RivetSnapshot, type RivetStore, Size, VERSION, Vec2, Viewport, alignRect, applyEdgeChanges, applyNodeChanges, boundingRect, canvas2DEdgeRenderer, clampChildToParent, cloneElements, createRivetStore, edgeEndpointHandle, facingSide, getBezierPath, getSmoothStepPath, getStepPath, getStraightPath, handleKey, parseEdgeEndpoint, parseSideHandleId, rectsIntersect, resolveFacingSide, resolveFacingSideAmong, screenToWorld, serializeGraph, snapToGrid, useRivet, useRivetContext, useRivetControls, useRivetFocusedNode, useRivetHistory, useRivetViewport, viewportToCss, visibleWorldRect, worldToScreen, zoomAt };
|
package/dist/index.js
CHANGED
|
@@ -313,6 +313,22 @@ function resolveFacingSide(node, peer, previous, hysteresis = DEFAULT_ALIGNMENT_
|
|
|
313
313
|
if (Math.abs(dx) > Math.abs(dy) * hysteresis) return dx > 0 ? "right" : "left";
|
|
314
314
|
return dy > 0 ? "bottom" : "top";
|
|
315
315
|
}
|
|
316
|
+
function bestAllowedSide(node, peer, allowed) {
|
|
317
|
+
const dx = peer.x + peer.width / 2 - (node.x + node.width / 2);
|
|
318
|
+
const dy = peer.y + peer.height / 2 - (node.y + node.height / 2);
|
|
319
|
+
const score = { left: -dx, right: dx, top: -dy, bottom: dy };
|
|
320
|
+
let best = null;
|
|
321
|
+
for (const side of allowed) {
|
|
322
|
+
if (best === null || score[side] > score[best]) best = side;
|
|
323
|
+
}
|
|
324
|
+
return best;
|
|
325
|
+
}
|
|
326
|
+
function resolveFacingSideAmong(node, peer, allowed, previous, hysteresis = DEFAULT_ALIGNMENT_HYSTERESIS) {
|
|
327
|
+
const resolved = resolveFacingSide(node, peer, previous, hysteresis);
|
|
328
|
+
if (allowed.length === 0 || allowed.includes(resolved)) return resolved;
|
|
329
|
+
if (previous && allowed.includes(previous)) return previous;
|
|
330
|
+
return bestAllowedSide(node, peer, allowed) ?? resolved;
|
|
331
|
+
}
|
|
316
332
|
|
|
317
333
|
// src/edge-ends.ts
|
|
318
334
|
function displayedSideKey(edgeId, end) {
|
|
@@ -2187,7 +2203,7 @@ var ARROW_DIRS = {
|
|
|
2187
2203
|
ArrowLeft: { x: -1, y: 0 },
|
|
2188
2204
|
ArrowRight: { x: 1, y: 0 }
|
|
2189
2205
|
};
|
|
2190
|
-
function createKeyboardHandler(store) {
|
|
2206
|
+
function createKeyboardHandler(store, getSnapGrid) {
|
|
2191
2207
|
return (event) => {
|
|
2192
2208
|
if (event.defaultPrevented) return;
|
|
2193
2209
|
const active = document.activeElement;
|
|
@@ -2208,15 +2224,16 @@ function createKeyboardHandler(store) {
|
|
|
2208
2224
|
const movers = store.getMovers(store.getSelectedNodes());
|
|
2209
2225
|
if (movers.length === 0) return;
|
|
2210
2226
|
event.preventDefault();
|
|
2211
|
-
const
|
|
2227
|
+
const snapGrid = getSnapGrid?.() ?? null;
|
|
2228
|
+
const factor = event.shiftKey ? ARROW_STEP_SHIFT : 1;
|
|
2229
|
+
const stepX = (snapGrid?.[0] || ARROW_STEP) * factor;
|
|
2230
|
+
const stepY = (snapGrid?.[1] || ARROW_STEP) * factor;
|
|
2212
2231
|
for (const id of movers) {
|
|
2213
2232
|
const node = store.nodes.get(id);
|
|
2214
2233
|
if (!node) continue;
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
true
|
|
2219
|
-
);
|
|
2234
|
+
let next = { x: node.position.x + dir.x * stepX, y: node.position.y + dir.y * stepY };
|
|
2235
|
+
if (snapGrid) next = snapToGrid(next, snapGrid);
|
|
2236
|
+
store.moveNode(id, next, true);
|
|
2220
2237
|
}
|
|
2221
2238
|
};
|
|
2222
2239
|
}
|
|
@@ -2722,6 +2739,16 @@ function handleOnSide(nodeId, side, role, handles) {
|
|
|
2722
2739
|
}
|
|
2723
2740
|
return null;
|
|
2724
2741
|
}
|
|
2742
|
+
function reachableSides(nodeId, role, handles) {
|
|
2743
|
+
if (!handles) return [];
|
|
2744
|
+
const sides = [];
|
|
2745
|
+
for (const record of handles.values()) {
|
|
2746
|
+
if (record.nodeId !== nodeId) continue;
|
|
2747
|
+
if (!WANTED_TYPES[role].includes(record.type)) continue;
|
|
2748
|
+
if (!sides.includes(record.position)) sides.push(record.position);
|
|
2749
|
+
}
|
|
2750
|
+
return sides;
|
|
2751
|
+
}
|
|
2725
2752
|
function resolveEnd(edge, role, node, peer, frame) {
|
|
2726
2753
|
const { handles, viewport, worldPositions, extras } = frame;
|
|
2727
2754
|
const handleId = role === "source" ? edge.sourceHandle : edge.targetHandle;
|
|
@@ -2759,9 +2786,10 @@ function resolveEnd(edge, role, node, peer, frame) {
|
|
|
2759
2786
|
return endAt(pinnedSide);
|
|
2760
2787
|
}
|
|
2761
2788
|
const key = displayedSideKey(edge.id, role);
|
|
2762
|
-
const side =
|
|
2789
|
+
const side = resolveFacingSideAmong(
|
|
2763
2790
|
rect,
|
|
2764
2791
|
nodeRect(peer, worldPositions),
|
|
2792
|
+
anchorId ? [] : reachableSides(node.id, role, handles),
|
|
2765
2793
|
extras?.displayedSides?.get(key)
|
|
2766
2794
|
);
|
|
2767
2795
|
extras?.displayedSides?.set(key, side);
|
|
@@ -3164,7 +3192,7 @@ function useRivetRuntime(params) {
|
|
|
3164
3192
|
}
|
|
3165
3193
|
pan.end(event);
|
|
3166
3194
|
};
|
|
3167
|
-
const onKeyDown = createKeyboardHandler(store);
|
|
3195
|
+
const onKeyDown = createKeyboardHandler(store, () => reconnectRef.current.snapGrid);
|
|
3168
3196
|
let focusRetryFrame = 0;
|
|
3169
3197
|
const unsubscribeFocus = store.subscribeFocus((id) => {
|
|
3170
3198
|
if (focusRetryFrame) {
|
|
@@ -4641,7 +4669,8 @@ function Rivet({
|
|
|
4641
4669
|
zoomSpeed,
|
|
4642
4670
|
minZoom,
|
|
4643
4671
|
maxZoom,
|
|
4644
|
-
gridGap
|
|
4672
|
+
gridGap,
|
|
4673
|
+
snapGrid: cfg.snapGrid
|
|
4645
4674
|
});
|
|
4646
4675
|
const contextValue = useMemo(
|
|
4647
4676
|
() => ({
|
|
@@ -4844,6 +4873,6 @@ function useRivet() {
|
|
|
4844
4873
|
// src/index.ts
|
|
4845
4874
|
var VERSION = "0.0.0";
|
|
4846
4875
|
|
|
4847
|
-
export { BUILTIN_EDGE_TYPES, BUILTIN_NODE_TYPES, Canvas2DEdgeRenderer, Controls, DEFAULT_ALIGNMENT_HYSTERESIS, DefaultNode, GroupNode, Handle, MiniMap, NodeResizer, Rivet, VERSION, alignRect, applyEdgeChanges, applyNodeChanges, boundingRect, canvas2DEdgeRenderer, clampChildToParent, cloneElements, createRivetStore, edgeEndpointHandle, facingSide, getBezierPath, getSmoothStepPath, getStepPath, getStraightPath, handleKey, parseEdgeEndpoint, parseSideHandleId, rectsIntersect, resolveFacingSide, screenToWorld, serializeGraph, snapToGrid, useRivet, viewportToCss, visibleWorldRect, worldToScreen, zoomAt };
|
|
4876
|
+
export { BUILTIN_EDGE_TYPES, BUILTIN_NODE_TYPES, Canvas2DEdgeRenderer, Controls, DEFAULT_ALIGNMENT_HYSTERESIS, DefaultNode, GroupNode, Handle, MiniMap, NodeResizer, Rivet, VERSION, alignRect, applyEdgeChanges, applyNodeChanges, boundingRect, canvas2DEdgeRenderer, clampChildToParent, cloneElements, createRivetStore, edgeEndpointHandle, facingSide, getBezierPath, getSmoothStepPath, getStepPath, getStraightPath, handleKey, parseEdgeEndpoint, parseSideHandleId, rectsIntersect, resolveFacingSide, resolveFacingSideAmong, screenToWorld, serializeGraph, snapToGrid, useRivet, viewportToCss, visibleWorldRect, worldToScreen, zoomAt };
|
|
4848
4877
|
//# sourceMappingURL=index.js.map
|
|
4849
4878
|
//# sourceMappingURL=index.js.map
|