@statelyai/flow-react 0.9.2 → 0.9.4
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/esm/index.js +44 -18
- package/package.json +7 -4
package/dist/esm/index.js
CHANGED
|
@@ -551,7 +551,7 @@ function stringArraysEqual(a, b) {
|
|
|
551
551
|
}
|
|
552
552
|
function nodePaintEntriesEqual(a, b) {
|
|
553
553
|
if (a.length !== b.length) return false;
|
|
554
|
-
for (let index = 0; index < a.length; index++) if (a[index]?.id !== b[index]?.id || a[index]?.
|
|
554
|
+
for (let index = 0; index < a.length; index++) if (a[index]?.id !== b[index]?.id || a[index]?.zIndex !== b[index]?.zIndex) return false;
|
|
555
555
|
return true;
|
|
556
556
|
}
|
|
557
557
|
function classNames$1(...values) {
|
|
@@ -561,8 +561,31 @@ function assignRef(ref, value) {
|
|
|
561
561
|
if (typeof ref === "function") ref(value);
|
|
562
562
|
else if (ref) ref.current = value;
|
|
563
563
|
}
|
|
564
|
+
/**
|
|
565
|
+
* `dragRevision` changes only for transient drag geometry. Topology, paint
|
|
566
|
+
* order, and viewport membership stay stable during that transition, so
|
|
567
|
+
* list-level selectors can retain their prior value while per-entity DOM
|
|
568
|
+
* observers update only the moved cohort.
|
|
569
|
+
*/
|
|
570
|
+
function useDragStableFlowSelector(selector, isEqual) {
|
|
571
|
+
const cached = useRef(null);
|
|
572
|
+
return useFlowSelector((context) => {
|
|
573
|
+
if (cached.current && context.canvasState === "dragging" && cached.current.canvasState === "dragging" && context.dragRevision !== cached.current.dragRevision) {
|
|
574
|
+
cached.current.canvasState = context.canvasState;
|
|
575
|
+
cached.current.dragRevision = context.dragRevision;
|
|
576
|
+
return cached.current.value;
|
|
577
|
+
}
|
|
578
|
+
const value = selector(context);
|
|
579
|
+
cached.current = {
|
|
580
|
+
canvasState: context.canvasState,
|
|
581
|
+
dragRevision: context.dragRevision,
|
|
582
|
+
value
|
|
583
|
+
};
|
|
584
|
+
return value;
|
|
585
|
+
}, { isEqual });
|
|
586
|
+
}
|
|
564
587
|
function useRenderableIds(instance, enabled) {
|
|
565
|
-
return
|
|
588
|
+
return useDragStableFlowSelector((context) => computeRenderableIds(instance.internals.engine, context, enabled), renderableIdsEqual);
|
|
566
589
|
}
|
|
567
590
|
function useViewportTransform(ref, instance) {
|
|
568
591
|
useLayoutEffect(() => {
|
|
@@ -934,7 +957,7 @@ function EdgeLayer(props) {
|
|
|
934
957
|
const instance = useFlowInstance();
|
|
935
958
|
const markerPrefix = `stately-flow-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
936
959
|
const renderableIds = useRenderableIds(instance, props.onlyRenderVisible);
|
|
937
|
-
const edgeIds =
|
|
960
|
+
const edgeIds = useDragStableFlowSelector((_context) => getOrderedEntities(instance).edges.map((edge) => edge.id), stringArraysEqual);
|
|
938
961
|
const renderEdge = props.renderEdge;
|
|
939
962
|
return /* @__PURE__ */ jsxs("svg", {
|
|
940
963
|
"aria-label": "edges",
|
|
@@ -979,7 +1002,8 @@ const EdgeView = memo(function EdgeView(props) {
|
|
|
979
1002
|
hovered: context.hoveredEntityIds.has(props.id),
|
|
980
1003
|
highlights: props.flow.internals.engine.getHighlights(props.id)
|
|
981
1004
|
}), { isEqual: (a, b) => {
|
|
982
|
-
if (!(a.selected === b.selected && a.focused === b.focused && a.hovered === b.hovered && a.highlights === b.highlights)
|
|
1005
|
+
if (!(a.selected === b.selected && a.focused === b.focused && a.hovered === b.hovered && a.highlights === b.highlights)) return false;
|
|
1006
|
+
if (a.geometryActive !== b.geometryActive) return b.geometryActive ? edgeRenderContentEqual(a.edge, b.edge) : false;
|
|
983
1007
|
if (a.geometryActive) return edgeRenderContentEqual(a.edge, b.edge);
|
|
984
1008
|
return a.graph === b.graph && a.edge === b.edge && a.pathData === b.pathData;
|
|
985
1009
|
} });
|
|
@@ -1258,7 +1282,8 @@ const EdgeLabelItem = memo(function EdgeLabelItem(props) {
|
|
|
1258
1282
|
hovered: context.hoveredEntityIds.has(props.id),
|
|
1259
1283
|
highlights: props.flow.internals.engine.getHighlights(props.id)
|
|
1260
1284
|
}), { isEqual: (a, b) => {
|
|
1261
|
-
if (!(a.selected === b.selected && a.dragging === b.dragging && a.hovered === b.hovered && a.highlights === b.highlights)
|
|
1285
|
+
if (!(a.selected === b.selected && a.dragging === b.dragging && a.hovered === b.hovered && a.highlights === b.highlights)) return false;
|
|
1286
|
+
if (a.geometryActive !== b.geometryActive) return b.geometryActive ? edgeRenderContentEqual(a.edge, b.edge) : false;
|
|
1262
1287
|
if (a.geometryActive) return edgeRenderContentEqual(a.edge, b.edge);
|
|
1263
1288
|
return a.graph === b.graph && a.edge === b.edge && a.pathData === b.pathData;
|
|
1264
1289
|
} });
|
|
@@ -1383,16 +1408,16 @@ function projectedEdgeLabelBounds(pathData, label) {
|
|
|
1383
1408
|
function NodeLayer(props) {
|
|
1384
1409
|
const instance = useFlowInstance();
|
|
1385
1410
|
const renderableIds = useRenderableIds(instance, props.onlyRenderVisible);
|
|
1386
|
-
const nodePaintEntries =
|
|
1387
|
-
const
|
|
1411
|
+
const nodePaintEntries = useDragStableFlowSelector((context) => {
|
|
1412
|
+
const paintZIndices = instance.internals.engine.getPaintZIndices().nodes;
|
|
1388
1413
|
return context.graph.nodes.flatMap((node) => {
|
|
1389
|
-
const
|
|
1390
|
-
return
|
|
1414
|
+
const zIndex = paintZIndices.get(node.id);
|
|
1415
|
+
return zIndex === void 0 ? [] : [{
|
|
1391
1416
|
id: node.id,
|
|
1392
|
-
|
|
1417
|
+
zIndex
|
|
1393
1418
|
}];
|
|
1394
1419
|
});
|
|
1395
|
-
},
|
|
1420
|
+
}, nodePaintEntriesEqual);
|
|
1396
1421
|
const observer = useMeasurementObserver();
|
|
1397
1422
|
return /* @__PURE__ */ jsx("div", {
|
|
1398
1423
|
"aria-label": "nodes",
|
|
@@ -1405,13 +1430,13 @@ function NodeLayer(props) {
|
|
|
1405
1430
|
transformOrigin: "0 0",
|
|
1406
1431
|
pointerEvents: "none"
|
|
1407
1432
|
},
|
|
1408
|
-
children: nodePaintEntries.map(({ id,
|
|
1433
|
+
children: nodePaintEntries.map(({ id, zIndex }) => {
|
|
1409
1434
|
if (renderableIds && !renderableIds.nodeIds.has(id)) return null;
|
|
1410
1435
|
return /* @__PURE__ */ jsx(NodeView, {
|
|
1411
1436
|
flow: instance,
|
|
1412
1437
|
geometryObserver: props.geometryObserver,
|
|
1413
1438
|
id,
|
|
1414
|
-
|
|
1439
|
+
zIndex,
|
|
1415
1440
|
observer,
|
|
1416
1441
|
projections: props.projections,
|
|
1417
1442
|
renderNode: props.renderNode
|
|
@@ -1419,8 +1444,8 @@ function NodeLayer(props) {
|
|
|
1419
1444
|
})
|
|
1420
1445
|
});
|
|
1421
1446
|
}
|
|
1422
|
-
function getOrderedEntities(flow) {
|
|
1423
|
-
return flow.internals.engine.getVisibleEntities();
|
|
1447
|
+
function getOrderedEntities(flow, options = {}) {
|
|
1448
|
+
return flow.internals.engine.getVisibleEntities(options);
|
|
1424
1449
|
}
|
|
1425
1450
|
function rectsShallowEqual(a, b) {
|
|
1426
1451
|
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
@@ -1469,7 +1494,8 @@ const NodeView = memo(function NodeView(props) {
|
|
|
1469
1494
|
bounds: context.resizingEntityId === props.id && context.resizeCorners ? props.flow.internals.engine.getResizeBounds() ?? props.flow.internals.engine.visualBounds(props.id) : props.flow.internals.engine.visualBounds(props.id)
|
|
1470
1495
|
};
|
|
1471
1496
|
}, { isEqual: (a, b) => {
|
|
1472
|
-
if (!(a.hidden === b.hidden && a.selected === b.selected && a.dragging === b.dragging && a.focused === b.focused && a.hovered === b.hovered && a.highlights === b.highlights)
|
|
1497
|
+
if (!(a.hidden === b.hidden && a.selected === b.selected && a.dragging === b.dragging && a.focused === b.focused && a.hovered === b.hovered && a.highlights === b.highlights)) return false;
|
|
1498
|
+
if (a.geometryActive !== b.geometryActive) return b.geometryActive ? nodeRenderContentEqual(a.node, b.node) : false;
|
|
1473
1499
|
if (a.geometryActive) return nodeRenderContentEqual(a.node, b.node);
|
|
1474
1500
|
return a.graph === b.graph && a.node === b.node && rectsShallowEqual(a.bounds, b.bounds);
|
|
1475
1501
|
} });
|
|
@@ -1540,9 +1566,9 @@ const NodeView = memo(function NodeView(props) {
|
|
|
1540
1566
|
dragging
|
|
1541
1567
|
}),
|
|
1542
1568
|
cursor: dragging ? "grabbing" : "grab",
|
|
1543
|
-
pointerEvents: node.group && groupHasInteractiveContent ? "none" : "auto",
|
|
1569
|
+
pointerEvents: node.group?.type === "derived" || node.group && groupHasInteractiveContent ? "none" : "auto",
|
|
1544
1570
|
userSelect: "none",
|
|
1545
|
-
zIndex: props.
|
|
1571
|
+
zIndex: props.zIndex,
|
|
1546
1572
|
opacity: attrs.opacity
|
|
1547
1573
|
},
|
|
1548
1574
|
children: props.renderNode ? /* @__PURE__ */ jsx("div", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/flow-react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "Thin React adapter for @statelyai/flow with core and DOM re-exports.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"use-sync-external-store": "^1.6.0",
|
|
37
|
-
"@statelyai/flow": "0.
|
|
38
|
-
"@statelyai/flow-dom": "3.4.
|
|
37
|
+
"@statelyai/flow": "0.9.1",
|
|
38
|
+
"@statelyai/flow-dom": "3.4.4"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": "^18.2.0 || ^19.0.0",
|
|
@@ -83,7 +83,10 @@
|
|
|
83
83
|
"typecheck": "tsc --noEmit",
|
|
84
84
|
"test:browser": "vitest run --config vitest.browser.config.mjs",
|
|
85
85
|
"test:e2e": "playwright test",
|
|
86
|
-
"bench:browser": "playwright test --config playwright.performance.config.ts",
|
|
86
|
+
"bench:browser": "playwright test --config playwright.performance.config.ts && node ../../scripts/report-browser-benchmarks.mjs",
|
|
87
|
+
"bench:react": "playwright test --config playwright.performance.config.ts --grep StatelyFlow && node ../../scripts/report-browser-benchmarks.mjs",
|
|
88
|
+
"bench:interaction": "playwright test --config playwright.performance.config.ts --grep 'viewport pan' && node ../../scripts/report-browser-benchmarks.mjs",
|
|
89
|
+
"bench:comparison": "playwright test --config playwright.performance.config.ts --grep 'StatelyFlow|React Flow' && node ../../scripts/report-browser-benchmarks.mjs",
|
|
87
90
|
"storybook": "storybook dev -p 6008",
|
|
88
91
|
"storybook:build": "storybook build"
|
|
89
92
|
}
|