@sandeepsj0000/react-graph-visualizer 1.0.0 → 1.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/dist/graphEngine.d.ts +2 -0
- package/dist/index.cjs.js +78 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +78 -1
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -4483,6 +4483,17 @@ class GraphEngine {
|
|
|
4483
4483
|
getEdges() {
|
|
4484
4484
|
return [...this.edges];
|
|
4485
4485
|
}
|
|
4486
|
+
/** Search nodes by label or id (case-insensitive substring match) */
|
|
4487
|
+
searchNodes(query) {
|
|
4488
|
+
if (!query.trim())
|
|
4489
|
+
return [];
|
|
4490
|
+
const q = query.toLowerCase();
|
|
4491
|
+
return this.nodes.filter((n) => {
|
|
4492
|
+
var _a;
|
|
4493
|
+
return ((_a = n.label) !== null && _a !== void 0 ? _a : n.id).toLowerCase().includes(q) ||
|
|
4494
|
+
n.id.toLowerCase().includes(q);
|
|
4495
|
+
});
|
|
4496
|
+
}
|
|
4486
4497
|
/** Check if a node exists */
|
|
4487
4498
|
hasNode(id) {
|
|
4488
4499
|
return this.adjacency.has(id);
|
|
@@ -4894,6 +4905,9 @@ const GraphVisualizer = ({ data, width = 900, height = 600, onSelectionChange, n
|
|
|
4894
4905
|
const [invertedNodes, setInvertedNodes] = useState([]);
|
|
4895
4906
|
const [paths, setPaths] = useState([]);
|
|
4896
4907
|
const [hoveredNode, setHoveredNode] = useState(null);
|
|
4908
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
4909
|
+
const [searchFocused, setSearchFocused] = useState(false);
|
|
4910
|
+
const searchRef = useRef(null);
|
|
4897
4911
|
const engine = useMemo(() => new GraphEngine(data), [data]);
|
|
4898
4912
|
const directed = (_a = data.directed) !== null && _a !== void 0 ? _a : false;
|
|
4899
4913
|
// Build simulation data
|
|
@@ -5263,6 +5277,34 @@ const GraphVisualizer = ({ data, width = 900, height = 600, onSelectionChange, n
|
|
|
5263
5277
|
}
|
|
5264
5278
|
return [];
|
|
5265
5279
|
}, [selectedArray, mode, connectedNodes, invertedNodes, engine]);
|
|
5280
|
+
const searchResults = useMemo(() => {
|
|
5281
|
+
if (!searchQuery.trim())
|
|
5282
|
+
return [];
|
|
5283
|
+
const q = searchQuery.toLowerCase();
|
|
5284
|
+
return data.nodes.filter((n) => {
|
|
5285
|
+
var _a;
|
|
5286
|
+
return ((_a = n.label) !== null && _a !== void 0 ? _a : n.id).toLowerCase().includes(q) ||
|
|
5287
|
+
n.id.toLowerCase().includes(q);
|
|
5288
|
+
});
|
|
5289
|
+
}, [searchQuery, data.nodes]);
|
|
5290
|
+
const handleSearchSelect = useCallback((nodeId, event) => {
|
|
5291
|
+
var _a;
|
|
5292
|
+
if (event.ctrlKey || event.metaKey) {
|
|
5293
|
+
setSelectedNodes((prev) => {
|
|
5294
|
+
const next = new Set(prev);
|
|
5295
|
+
if (next.has(nodeId))
|
|
5296
|
+
next.delete(nodeId);
|
|
5297
|
+
else
|
|
5298
|
+
next.add(nodeId);
|
|
5299
|
+
return next;
|
|
5300
|
+
});
|
|
5301
|
+
}
|
|
5302
|
+
else {
|
|
5303
|
+
setSelectedNodes(new Set([nodeId]));
|
|
5304
|
+
}
|
|
5305
|
+
setSearchQuery("");
|
|
5306
|
+
(_a = searchRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
5307
|
+
}, []);
|
|
5266
5308
|
const handleExportCSV = () => {
|
|
5267
5309
|
if (mode === "paths" && paths.length > 0) {
|
|
5268
5310
|
exportPathsAsCSV(paths);
|
|
@@ -5304,7 +5346,42 @@ const GraphVisualizer = ({ data, width = 900, height = 600, onSelectionChange, n
|
|
|
5304
5346
|
flexDirection: "column",
|
|
5305
5347
|
gap: 12,
|
|
5306
5348
|
fontSize: 13,
|
|
5307
|
-
}, children: [jsxs("div", { style: {
|
|
5349
|
+
}, children: [jsxs("div", { style: { position: "relative" }, children: [jsx("label", { style: { fontWeight: 600, fontSize: 12, color: "#475569", display: "block", marginBottom: 4 }, children: "Search Nodes" }), jsx("input", { ref: searchRef, type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onFocus: () => setSearchFocused(true), onBlur: () => setTimeout(() => setSearchFocused(false), 150), placeholder: "Type to search...", style: {
|
|
5350
|
+
width: "100%",
|
|
5351
|
+
padding: "7px 10px",
|
|
5352
|
+
border: "1px solid #d1d5db",
|
|
5353
|
+
borderRadius: 6,
|
|
5354
|
+
fontSize: 12,
|
|
5355
|
+
outline: "none",
|
|
5356
|
+
boxSizing: "border-box",
|
|
5357
|
+
transition: "border-color 0.15s",
|
|
5358
|
+
borderColor: searchFocused ? "#4f46e5" : "#d1d5db",
|
|
5359
|
+
} }), searchFocused && searchQuery.trim() && (jsx("div", { style: {
|
|
5360
|
+
position: "absolute",
|
|
5361
|
+
top: "100%",
|
|
5362
|
+
left: 0,
|
|
5363
|
+
right: 0,
|
|
5364
|
+
marginTop: 4,
|
|
5365
|
+
background: "#fff",
|
|
5366
|
+
border: "1px solid #e2e8f0",
|
|
5367
|
+
borderRadius: 6,
|
|
5368
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
|
|
5369
|
+
maxHeight: 200,
|
|
5370
|
+
overflow: "auto",
|
|
5371
|
+
zIndex: 10,
|
|
5372
|
+
}, children: searchResults.length === 0 ? (jsx("div", { style: { padding: "8px 10px", color: "#94a3b8", fontSize: 12 }, children: "No nodes found" })) : (searchResults.map((n, i) => {
|
|
5373
|
+
var _a;
|
|
5374
|
+
return (jsxs("div", { onMouseDown: (e) => handleSearchSelect(n.id, e), style: {
|
|
5375
|
+
padding: "6px 10px",
|
|
5376
|
+
cursor: "pointer",
|
|
5377
|
+
display: "flex",
|
|
5378
|
+
justifyContent: "space-between",
|
|
5379
|
+
alignItems: "center",
|
|
5380
|
+
borderBottom: i < searchResults.length - 1 ? "1px solid #f1f5f9" : "none",
|
|
5381
|
+
background: selectedNodes.has(n.id) ? "#f0f0ff" : "#fff",
|
|
5382
|
+
fontSize: 12,
|
|
5383
|
+
}, onMouseEnter: (e) => (e.currentTarget.style.background = selectedNodes.has(n.id) ? "#e8e8ff" : "#f8fafc"), onMouseLeave: (e) => (e.currentTarget.style.background = selectedNodes.has(n.id) ? "#f0f0ff" : "#fff"), children: [jsx("span", { style: { fontWeight: 500 }, children: (_a = n.label) !== null && _a !== void 0 ? _a : n.id }), jsx("span", { style: { color: "#94a3b8", fontSize: 11 }, children: n.id })] }, n.id));
|
|
5384
|
+
})) }))] }), jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [jsx("label", { style: { fontWeight: 600, fontSize: 12, color: "#475569" }, children: "Selection Mode" }), jsx("div", { style: { display: "flex", gap: 4 }, children: [
|
|
5308
5385
|
["connected", "Connected"],
|
|
5309
5386
|
["inverted", "Inverted"],
|
|
5310
5387
|
["paths", "Paths"],
|